public function updateSpotXml($fullSpot, $updatesToApply)
 {
     $result = new Dto_FormResult();
     /*
      * before we merge we first want to clean the form from the stuff
      * we don't want to merge with the original spot
      */
     $spot = $this->cleanseUpdates($updatesToApply);
     /*
      * subcat must be an array so let's make it an array if it is not,
      * otherwise we get in trouble in the verifyCategories() method
      */
     if (!is_array($spot['subcatb'])) {
         $spot['subcatb'] = array();
     }
     if (!is_array($spot['subcatc'])) {
         $spot['subcatc'] = array();
     }
     if (!is_array($spot['subcatd'])) {
         $spot['subcatd'] = array();
     }
     # Verify several properties from the caller
     $result->addData('spot', $spot);
     $result = $this->_spotValidator->verifyTitle($result);
     $result = $this->_spotValidator->verifyBody($result);
     $result = $this->_spotValidator->verifyCategories($result);
     $result = $this->_spotValidator->verifyWebsite($result);
     $result = $this->_spotValidator->verifyTag($result);
     /*
      * Retrieve the spot information from the result,
      * and remove it again. We do not want to send the
      * whole spot back to the caller
      */
     $spot = $result->getData('spot');
     $result->removeData('spot');
     if ($result->isSuccess()) {
         # We now merge the cleaned edit form into the original spot
         $spot = array_merge($fullSpot, $spot);
         $imageInfo = array('height' => $spot['image']['height'], 'width' => $spot['image']['width'], 'segments' => $spot['image']['segment']);
         $nzbSegmentList = $spot['nzb'];
         # Parse the updated spot to an XML structure
         $spotCreator = new Services_Format_Creation();
         $spotXml = $spotCreator->convertSpotToXml($spot, $imageInfo, $nzbSegmentList);
         $result->addData('spotxml', $spotXml);
     }
     # if
     return $result;
 }
示例#2
0
 public function postSpot(Services_User_Record $svcUserRecord, array $user, array $spot, $imageFilename, $nzbFilename)
 {
     $result = new Dto_FormResult();
     $spotDao = $this->_daoFactory->getSpotDao();
     # Make sure the anonymous user and reserved usernames cannot post content
     if (!$svcUserRecord->allowedToPost($user)) {
         $result->addError(_("You need to login to be able to post spots"));
     }
     # if
     # Retrieve the users' private key
     $user['privatekey'] = $svcUserRecord->getUserPrivateRsaKey($user['userid']);
     $hdr_newsgroup = $this->_settings->get('hdr_group');
     $bin_newsgroup = $this->_settings->get('nzb_group');
     /*
      * We'll get the messageid's with <>'s but we always strip
      * them in Spotweb, so remove them
      */
     $spot['newmessageid'] = substr($spot['newmessageid'], 1, -1);
     /*
     		$hdr_newsgroup = 'alt.test';
     		$bin_newsgroup = 'alt.test';
     */
     # If the hashcash doesn't match, we will never post it
     if (substr(sha1('<' . $spot['newmessageid'] . '>'), 0, 4) != '0000') {
         $result->addError(_('Hash was not calculated properly'));
     }
     # if
     # Verify several properties from the caller
     $result->addData('spot', $spot);
     $result = $this->_spotValidator->verifyTitle($result);
     $result = $this->_spotValidator->verifyBody($result);
     $result = $this->_spotValidator->verifyCategories($result);
     $result = $this->_spotValidator->verifyWebsite($result);
     $result = $this->_spotValidator->verifyTag($result);
     /*
      * Retrieve the spot information from the result,
      * and remove it again. We do not want to send the
      * whole spot back to the caller
      */
     $spot = $result->getData('spot');
     $result->removeData('spot');
     # Read the contents of image so we can check it
     $imageContents = file_get_contents($imageFilename);
     # the image should be below 1MB
     if (strlen($imageContents) > 1024 * 1024) {
         $result->addError(_('Uploaded image is too large (maximum 1MB)'));
     }
     # if
     /*
      * Get some image information, if it fails, this is an
      * error as well
      */
     $tmpGdImageSize = getimagesize($imageFilename);
     if ($tmpGdImageSize === false) {
         $result->addError(_('Uploaded image was not recognized as an image'));
     } else {
         $imageInfo = array('width' => $tmpGdImageSize[0], 'height' => $tmpGdImageSize[1]);
     }
     # if
     /*
      * Load the NZB file as an XML file so we can make sure 
      * it's a valid XML and NZB file and we can determine the
      * filesize
      */
     $nzbFileContents = file_get_contents($nzbFilename);
     $nzbXml = simplexml_load_string($nzbFileContents);
     # Do some basic sanity checking for some required NZB elements
     if (empty($nzbXml->file)) {
         $result->addError(_('Incorrect NZB file'));
     }
     # if
     # and determine the total filesize
     $spot['filesize'] = 0;
     foreach ($nzbXml->file as $file) {
         foreach ($file->segments->segment as $seg) {
             $spot['filesize'] += (int) $seg['bytes'];
         }
         # foreach
     }
     # foreach
     /*
      * Make sure we didn't use this messageid recently or at all, this
      * prevents people from not recalculating the hashcash in order to spam
      * the system
      */
     if (!$spotDao->isNewSpotMessageIdUnique($spot['newmessageid'])) {
         $result->addError(_('Replay attack!?'));
     }
     # if
     # Make sure a newmessageid contains a certain length
     if (strlen($spot['newmessageid']) < 10) {
         $result->addError(_('MessageID too short!?'));
     }
     # if
     # We require the keyid 7 because it is selfsigned
     $spot['key'] = 7;
     # Poster's  username
     $spot['poster'] = $user['username'];
     # actually post the spot
     if ($result->isSuccess()) {
         /*
          * Retrieve the image information and post the image to 
          * the appropriate newsgroup so we have the messageid list of 
          * images
          */
         $imgSegmentList = $this->_nntp_post->postBinaryMessage($user, $bin_newsgroup, $imageContents, '');
         $imageInfo['segments'] = $imgSegmentList;
         # Post the NZB file to the appropriate newsgroups
         $nzbSegmentList = $this->_nntp_post->postBinaryMessage($user, $bin_newsgroup, gzdeflate($nzbFileContents), '');
         # Convert the current Spotnet info, to an XML structure
         $spotCreator = new Services_Format_Creation();
         $spotXml = $spotCreator->convertSpotToXml($spot, $imageInfo, $nzbSegmentList);
         $spot['spotxml'] = $spotXml;
         # And actually post to the newsgroups
         $this->_nntp_post->postFullSpot($user, $this->_settings->get('privatekey'), $hdr_newsgroup, $spot);
         $spotDao->addPostedSpot($user['userid'], $spot, $spotXml);
     }
     # if
     return $result;
 }
 function validateSettings($settings)
 {
     $result = new Dto_FormResult();
     # Define arrays with valid settings
     $validNntpEnc = array(false, 'ssl', 'tls');
     $validModerationAction = array('disable', 'act', 'markspot');
     $validRetentionTypes = array('fullonly', 'everything');
     # Get the given value for NNTP encryption
     $settings['nntp_nzb']['enc'] = isset($settings['nntp_nzb']['enc']['switch']) ? $settings['nntp_nzb']['enc']['select'] : false;
     $settings['nntp_hdr']['enc'] = isset($settings['nntp_hdr']['enc']['switch']) ? $settings['nntp_hdr']['enc']['select'] : false;
     $settings['nntp_post']['enc'] = isset($settings['nntp_post']['enc']['switch']) ? $settings['nntp_post']['enc']['select'] : false;
     # Trim human-entered text fields
     $settings['nntp_nzb']['host'] = trim($settings['nntp_nzb']['host']);
     $settings['nntp_hdr']['host'] = trim($settings['nntp_hdr']['host']);
     $settings['nntp_post']['host'] = trim($settings['nntp_post']['host']);
     # Verify settings with the previous declared arrays
     if (in_array($settings['nntp_nzb']['enc'], $validNntpEnc) === false || in_array($settings['nntp_hdr']['enc'], $validNntpEnc) === false || in_array($settings['nntp_post']['enc'], $validNntpEnc) === false) {
         $result->addError(_('Invalid encryption setting'));
     }
     # if
     if (in_array($settings['spot_moderation'], $validModerationAction) === false) {
         $result->addError(_('Invalid spot moderation setting'));
     }
     # if
     if (in_array($settings['retentiontype'], $validRetentionTypes) === false) {
         $result->addError(_('Invalid spot retentiontype setting'));
     }
     # if
     # Verify settings
     $settings['cookie_expires'] = (int) $settings['cookie_expires'];
     if ($settings['cookie_expires'] < 0) {
         $result->addError(_('Invalid cookie_expires setting'));
     }
     # if
     $settings['retention'] = (int) $settings['retention'];
     if ($settings['retention'] < 0) {
         $result->addError(_('Invalid retention setting'));
     }
     # if
     $settings['retrieve_newer_than'] = strtotime($settings['retrieve_newer_than']);
     if ($settings['retrieve_newer_than'] === false || $settings['retrieve_newer_than'] > time()) {
         $result->addError(_('Invalid retrieve_newer_than setting'));
     } elseif ($settings['retrieve_newer_than'] < 1230789600) {
         /* We don't allow settings earlier than january 1st 2009 */
         $settings['retrieve_newer_than'] = 1230789600;
     }
     # elseif
     $settings['retrieve_increment'] = (int) $settings['retrieve_increment'];
     if ($settings['retrieve_increment'] < 1) {
         $result->addError(_('Invalid retrieve_increment setting'));
     }
     # if
     # check the mailaddress
     if (!filter_var($settings['systemfrommail'], FILTER_VALIDATE_EMAIL)) {
         $result->addError(_('Not a valid email address'));
     }
     # if
     # We don't want to save megabyts of CSS, so put a limit to the size
     if (strlen($settings['customcss'] > 1024 * 10)) {
         $result->addError(_('Custom CSS is too large'));
     }
     # if
     # Convert other settings (usually checkboxes) to be simply boolean settings
     $settings['deny_robots'] = isset($settings['deny_robots']) ? true : false;
     $settings['sendwelcomemail'] = isset($settings['sendwelcomemail']) ? true : false;
     $settings['nntp_nzb']['buggy'] = isset($settings['nntp_nzb']['buggy']) ? true : false;
     $settings['nntp_hdr']['buggy'] = isset($settings['nntp_hdr']['buggy']) ? true : false;
     $settings['nntp_post']['buggy'] = isset($settings['nntp_post']['buggy']) ? true : false;
     $settings['retrieve_full'] = isset($settings['retrieve_full']) ? true : false;
     $settings['prefetch_image'] = isset($settings['prefetch_image']) ? true : false;
     $settings['prefetch_nzb'] = isset($settings['prefetch_nzb']) ? true : false;
     $settings['retrieve_comments'] = isset($settings['retrieve_comments']) ? true : false;
     $settings['retrieve_full_comments'] = isset($settings['retrieve_full_comments']) ? true : false;
     $settings['retrieve_reports'] = isset($settings['retrieve_reports']) ? true : false;
     $settings['enable_timing'] = isset($settings['enable_timing']) ? true : false;
     $settings['enable_stacktrace'] = isset($settings['enable_stacktrace']) ? true : false;
     $settings['prepare_statistics'] = isset($settings['prepare_statistics']) ? true : false;
     $settings['external_blacklist'] = isset($settings['external_blacklist']) ? true : false;
     $settings['external_whitelist'] = isset($settings['external_whitelist']) ? true : false;
     $settings['imageover_subcats'] = isset($settings['imageover_subcats']) ? true : false;
     # Default server settings if they won't be used
     if (!isset($settings['nntp_hdr']['use'])) {
         $settings['nntp_hdr'] = array('host' => '', 'user' => '', 'pass' => '', 'enc' => false, 'port' => 119, 'buggy' => false);
     }
     # if
     if (!isset($settings['nntp_post']['use'])) {
         $settings['nntp_post'] = array('host' => '', 'user' => '', 'pass' => '', 'enc' => false, 'port' => 119, 'buggy' => false);
     }
     # if
     /* 
      * Remove dummy preferences 
      */
     unset($settings['nntp_hdr']['use'], $settings['nntp_post']['use']);
     /*
      * We want to pass the updated settings back to the caller because
      * we fixed several stuff.
      */
     $result->addData('settings', $settings);
     return $result;
 }
 /**
  * Make sure the correct categories are chosen
  *
  * @param Dto_FormResult $result
  * @return Dto_FormResult
  */
 public function verifyCategories(Dto_FormResult $result)
 {
     $spot = $result->getData('spot');
     /* Make sure the category is valid
      * We use array_key_exists() to allow for gaps in the category numbering. This is an intentional
      * deviation from similar code used in Services_Posting_Spot.php
      */
     if (!array_key_exists($spot['category'], SpotCategories::$_head_categories)) {
         $result->addError(sprintf(_('Incorrect headcategory (%s)'), $spot['category']));
     }
     # if
     # Make sure the subcategories are in the proper format
     if (is_array($spot['subcata']) || is_array($spot['subcatz']) || !is_array($spot['subcatb']) || !is_array($spot['subcatc']) || !is_array($spot['subcatd'])) {
         $result->addError(_('Invalid subcategories given'));
     }
     # if
     # create a list of the chosen subcategories
     $spot['subcatlist'] = array_merge(array($spot['subcata']), $spot['subcatb'], $spot['subcatc'], $spot['subcatd']);
     /*
      * Loop through all subcategories and check if they are valid in
      * our list of subcategories
      */
     $subCatSplitted = array('a' => array(), 'b' => array(), 'c' => array(), 'd' => array(), 'z' => array());
     foreach ($spot['subcatlist'] as $subCat) {
         $subcats = explode('_', $subCat);
         # If not in our format
         if (count($subcats) != 3) {
             $result->addError(sprintf(_('Incorrect subcategories (%s)'), $subCat));
         } else {
             $subCatLetter = substr($subcats[2], 0, 1);
             $subCatSplitted[$subCatLetter][] = $subCat;
             if (!isset(SpotCategories::$_categories[$spot['category']][$subCatLetter][substr($subcats[2], 1)])) {
                 $result->addError(sprintf(_('Incorrect subcategories (%s)'), $subCat . ' !! ' . $subCatLetter . ' !! ' . substr($subcats[2], 1)));
             }
             # if
         }
         # else
     }
     # foreach
     /*
      * Make sure all subcategories are in the format we expect, for
      * example we strip the 'cat' part and strip the z-subcat
      */
     $subcatCount = count($spot['subcatlist']);
     for ($i = 0; $i < $subcatCount; $i++) {
         $subcats = explode('_', $spot['subcatlist'][$i]);
         # If not in our format
         if (count($subcats) != 3) {
             $result->addError(sprintf(_('Incorrect subcategories (%s)'), $spot['subcatlist'][$i]));
         } else {
             $spot['subcatlist'][$i] = substr($subcats[2], 0, 1) . str_pad(substr($subcats[2], 1), 2, '0', STR_PAD_LEFT);
             # Explicitly add the 'z'-category - we derive it from the full categorynames we already have
             $zcatStr = substr($subcats[1], 0, 1) . str_pad(substr($subcats[1], 1), 2, '0', STR_PAD_LEFT);
             if (is_numeric(substr($subcats[1], 1)) && array_search($zcatStr, $spot['subcatlist']) === false) {
                 $spot['subcatlist'][] = $zcatStr;
             }
             # if
         }
         # else
     }
     # for
     # Make sure the spot isn't being posted in many categories
     if (count($subCatSplitted['a']) > 1) {
         $result->addError(_('You can only specify one format for a spot'));
     }
     # if
     # Make sure the spot has at least a format
     if (count($subCatSplitted['a']) < 1) {
         $result->addError(_('You need to specify a format for a spot'));
     }
     # if
     # Make sure the spot isn't being posted for too many categories
     if (count($spot['subcatlist']) > 10) {
         $result->addError(_('Too many categories'));
     }
     # if
     # Make sure the spot isn't being posted for too many categories
     # The "A"-subcategory, and the "Z" subcategory are always selected by
     # the form, so we need to check for 3
     if (count($spot['subcatlist']) < 3) {
         $result->addError(_('At least one category need to be selected'));
     }
     # if
     $result->addData('spot', $spot);
     return $result;
 }
示例#5
0
 function validateUserPreferences($prefs, $currentPrefs)
 {
     $result = new Dto_FormResult();
     # Define several arrays with valid settings
     $validDateFormats = array('human', '%a, %d-%b-%Y (%H:%M)', '%d-%m-%Y (%H:%M)');
     $validTemplates = array_keys($this->_settings->get('valid_templates'));
     $validDefaultSorts = array('', 'stamp');
     $validLanguages = array_keys($this->_settings->get('system_languages'));
     # Check per page setting
     $prefs['perpage'] = (int) $prefs['perpage'];
     if ($prefs['perpage'] < 2 || $prefs['perpage'] > 250) {
         $result->addError(_('Invalid preference value (perpage)'));
     }
     # if
     # Controleer basis settings
     if (in_array($prefs['date_formatting'], $validDateFormats) === false) {
         $result->addError(_('Invalid user preference value (date_formatting)'));
     }
     # if
     if (in_array($prefs['normal_template'], $validTemplates) === false) {
         $result->addError(_('Invalid user preference value (template)'));
     }
     # if
     if (in_array($prefs['mobile_template'], $validTemplates) === false) {
         $result->addError(_('Invalid user preference value (template)'));
     }
     # if
     if (in_array($prefs['tablet_template'], $validTemplates) === false) {
         $result->addError(_('Invalid user preference value (template)'));
     }
     # if
     if (in_array($prefs['user_language'], $validLanguages) === false) {
         $result->addError(_('Invalid user preference value (language)'));
     }
     # if
     if (in_array($prefs['defaultsortfield'], $validDefaultSorts) === false) {
         $result->addError(_('Invalid user preference value (defaultsortfield)'));
     }
     # if
     # when an sabnzbd host is entered, it has to be a valid URL
     if ($prefs['nzbhandling']['action'] == 'client-sabnzbd' || $prefs['nzbhandling']['action'] == 'push-sabnzbd') {
         $tmpHost = parse_url($prefs['nzbhandling']['sabnzbd']['url']);
         if ($tmpHost === false | !isset($tmpHost['scheme']) || $tmpHost['scheme'] != 'http' && $tmpHost['scheme'] != 'https') {
             $result->addError(_('sabnzbd host is not a valid URL'));
         }
         # if
         # SABnzbd URL should always end with a s slash
         if (substr($prefs['nzbhandling']['sabnzbd']['url'], -1) !== '/') {
             $prefs['nzbhandling']['sabnzbd']['url'] .= '/';
         }
         # if
     }
     # if
     # when an nzbget host is entered, it has to be a valid URL
     if ($prefs['nzbhandling']['action'] == 'nzbget') {
         if (empty($prefs['nzbhandling']['nzbget']['host'])) {
             $result->addError(_("Host entered for nzbget is not valid"));
         }
         # if
         if (empty($prefs['nzbhandling']['nzbget']['port'])) {
             $result->addError(_("Port entered for nzbget is not valid"));
         }
         # if
     }
     # if
     # Twitter tokens are never posted by the form, but they shouldn't be tossed out
     $prefs['notifications']['twitter']['screen_name'] = $currentPrefs['notifications']['twitter']['screen_name'];
     $prefs['notifications']['twitter']['access_token'] = $currentPrefs['notifications']['twitter']['access_token'];
     $prefs['notifications']['twitter']['access_token_secret'] = $currentPrefs['notifications']['twitter']['access_token_secret'];
     $prefs['notifications']['twitter']['request_token'] = $currentPrefs['notifications']['twitter']['request_token'];
     $prefs['notifications']['twitter']['request_token_secret'] = $currentPrefs['notifications']['twitter']['request_token_secret'];
     # We don't want to save megabyts of CSS, so put a limit to the size
     if (strlen($prefs['customcss'] > 1024 * 10)) {
         $result->addError(_('Custom CSS is too large'));
     }
     # if
     # We don't want to save megabytes of default newspot body, so limit it
     if (strlen($prefs['newspotdefault_tag'] > 90)) {
         $result->addError(_('Default value for a spots\' tag is too long'));
     }
     # if
     if (strlen($prefs['newspotdefault_body'] > 9000)) {
         $result->addError(_('Default value for a spots\' body is too long'));
     }
     # if
     # When a 'runcommand' or 'save' action is chosen, 'local_dir' is a mandatry setting
     if ($prefs['nzbhandling']['action'] == 'save' || $prefs['nzbhandling']['action'] == 'runcommand') {
         if (empty($prefs['nzbhandling']['local_dir'])) {
             $result->addError(_('When NZB handling is either "save" or "runcommand" the directory must be entered'));
         }
         # if
     }
     # if
     # When a 'runcommand' action is chosen, 'command' is a mandatry setting
     if ($prefs['nzbhandling']['action'] == 'runcommand') {
         if (empty($prefs['nzbhandling']['command'])) {
             $result->addError(_('When NZB handling is "runcommand" a command must be entered'));
         }
         # if
     }
     # if
     # For the 'growl' notification provider, a host is mandatory
     if ($prefs['notifications']['growl']['enabled']) {
         if (empty($prefs['notifications']['growl']['host'])) {
             $result->addError(_('Growl notifications require a growl host to be entered'));
         }
         # if
     }
     # if
     # 'Notify My Android' requires an API key
     if ($prefs['notifications']['nma']['enabled']) {
         if (empty($prefs['notifications']['nma']['api'])) {
             $result->addError(_('"Notify My Android" notifications require an API key'));
         }
         # if
     }
     # if
     # 'Notifo' requires both a username and apikey
     if ($prefs['notifications']['notifo']['enabled']) {
         if (empty($prefs['notifications']['notifo']['username'])) {
             $result->addError(_('"Notifo" notifications require an username to be entered'));
         }
         # if
         if (empty($prefs['notifications']['notifo']['api'])) {
             $result->addError(_('"Notifo" notifications require an api key to be entered'));
         }
         # if
     }
     # if
     # 'Prowl' requires an API key
     if ($prefs['notifications']['prowl']['enabled']) {
         if (empty($prefs['notifications']['prowl']['apikey'])) {
             $result->addError(_('"Prowl" notifications require an API key to be entered'));
         }
         # if
     }
     # if
     # To use Twitter, an twitter account should be defined
     if ($prefs['notifications']['twitter']['enabled']) {
         if (empty($prefs['notifications']['twitter']['access_token']) || empty($prefs['notifications']['twitter']['access_token_secret'])) {
             $result->addError(_('To use twitter you need to enter and validate a twitter account'));
         }
         # if
     }
     # if
     /* Make sure a valid value for minimum_reportcount is entered */
     if (!is_numeric($prefs['minimum_reportcount']) || $prefs['minimum_reportcount'] > 10) {
         $result->addError(_('Invalid value for minimum_reportcount'));
     }
     # if
     /*
      * We want to return the fixed up preferences to the caller
      */
     $result->addData('prefs', $prefs);
     return $result;
 }
 public function xmlToFilters($xmlStr)
 {
     $filterList = array();
     /*
      * Parse the XML file
      */
     $xml = @new SimpleXMLElement($xmlStr);
     # We can only parse version 1.0 of the filters
     if ((string) $xml->version != '1.0') {
         return $filterList;
     }
     # if
     # and try to process all of the filters
     foreach ($xml->xpath('/spotwebfilter/filters/filter') as $filterItem) {
         $filter['id'] = (string) $filterItem->id;
         $filter['title'] = (string) $filterItem->title;
         $filter['icon'] = (string) $filterItem->icon;
         $filter['tparent'] = (string) $filterItem->parent;
         $filter['torder'] = (string) $filterItem->order;
         $filter['filtertype'] = 'filter';
         $filter['sorton'] = '';
         $filter['sortorder'] = '';
         $filter['tree'] = '';
         $filter['enablenotify'] = (string) $filterItem->enablenotify;
         $filter['children'] = array();
         /*
          * start with the tree items
          */
         $treeStr = "";
         foreach ($filterItem->xpath('tree/item') as $treeItem) {
             $treeType = (string) $treeItem->attributes()->type;
             if ($treeType == 'exclude') {
                 $treeStr .= ',!' . $treeItem[0];
             } elseif ($treeType == 'strongnot') {
                 $treeStr .= ',~' . $treeItem[0];
             } elseif ($treeType == 'include') {
                 $treeStr .= ',' . $treeItem[0];
             }
             # if
         }
         # foreach
         if (strlen($treeStr) > 1) {
             $treeStr = substr($treeStr, 1);
         }
         # if
         $filter['tree'] = $treeStr;
         /*
          * now parse the values (textsearches etc)
          */
         $filterValues = array();
         foreach ($filterItem->xpath('values/item') as $valueItem) {
             $filterValues[] = urlencode((string) $valueItem->fieldname . ':' . (string) $valueItem->operator . ':' . (string) $valueItem->booloper . ':' . (string) $valueItem->value);
         }
         # foreach
         $filter['valuelist'] = $filterValues;
         /* 
          * Sorting elements are optional
          */
         if ($filterItem->sort) {
             $filter['sorton'] = (string) $filterItem->sort->item->fieldname;
             $filter['sortorder'] = (string) $filterItem->sort->item->direction;
         }
         # if
         $filterList[$filter['id']] = $filter;
     }
     # foreach
     /*
      * Now create a tree out of it. We cannot do this the same way
      * as in SpotDb because we cannot create references to the XPATH
      * function
      */
     foreach ($filterList as $idx => &$filter) {
         if ($filter['tparent'] != 0 && isset($filterList[$filter['tparent']])) {
             $filterList[$filter['tparent']]['children'][] =& $filter;
         }
         # if
     }
     # foreach
     /*
      * we have to run it in two passes because unsetting it 
      * will result in an incorrect result on an nested-nested
      * list
      */
     foreach ($filterList as $idx => &$filter) {
         if ($filter['tparent'] != 0 && isset($filterList[$filter['tparent']])) {
             unset($filterList[$filter['id']]);
         }
         # if
     }
     # foreach
     /*
      * Create a new result object
      */
     $result = new Dto_FormResult('success');
     $result->addData('filters', $filterList);
     return $result;
 }