getCollectionClass() public method

Return a collection class given the collection id.
public getCollectionClass ( string $id ) : string | boolean
$id string The collection id.
return string | boolean The collection class or false if not found.
Example #1
0
 /**
  * Handle incoming SYNC nodes
  *
  * @param array $collection  The current collection array.
  *
  * @return boolean
  */
 protected function _parseSyncCommands(&$collection)
 {
     // Some broken clients send SYNC_COMMANDS with a synckey of 0.
     // This is a violation of the spec, and could lead to all kinds
     // of data integrity issues.
     if (empty($collection['synckey'])) {
         $this->_logger->warn(sprintf('[%s] Attempting a SYNC_COMMANDS, but device failed to send synckey. Ignoring.', $this->_procid));
     }
     if (empty($collection['class'])) {
         $collection['class'] = $this->_collections->getCollectionClass($collection['id']);
     }
     if (empty($collection['serverid'])) {
         try {
             $collection['serverid'] = $this->_collections->getBackendIdForFolderUid($collection['id']);
         } catch (Horde_ActiveSync_Exception $e) {
             $this->_statusCode = self::STATUS_FOLDERSYNC_REQUIRED;
             $this->_handleError($colleciton);
             return false;
         }
     }
     try {
         $this->_collections->initCollectionState($collection);
     } catch (Horde_ActiveSync_Exception_StateGone $e) {
         $this->_logger->warn(sprintf('[%s] State not found sending STATUS_KEYMISM', $this->_procid));
         $this->_statusCode = self::STATUS_KEYMISM;
         $this->_handleError($collection);
         return false;
     } catch (Horde_ActiveSync_Exception_StaleState $e) {
         $this->_logger->notice($e->getMessage());
         $this->_statusCode = self::STATUS_SERVERERROR;
         $this->_handleGlobalSyncError();
         return false;
     } catch (Horde_ActiveSync_Exception $e) {
         $this->_logger->err($e->getMessage());
         $this->_statusCode = self::STATUS_SERVERERROR;
         $this->_handleGlobalSyncError();
         return false;
     }
     // Configure importer with last state
     if (!empty($collection['synckey'])) {
         $importer = $this->_activeSync->getImporter();
         $importer->init($this->_state, $collection['id'], $collection['conflict']);
     }
     $nchanges = 0;
     while (1) {
         // SYNC_MODIFY, SYNC_REMOVE, SYNC_ADD or SYNC_FETCH
         $element = $this->_decoder->getElement();
         if ($element[Horde_ActiveSync_Wbxml::EN_TYPE] != Horde_ActiveSync_Wbxml::EN_TYPE_STARTTAG) {
             $this->_decoder->_ungetElement($element);
             break;
         }
         $nchanges++;
         // Only sent during SYNC_MODIFY/SYNC_REMOVE/SYNC_FETCH
         if (($element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_MODIFY || $element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_REMOVE || $element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_FETCH) && $this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_SERVERENTRYID)) {
             $serverid = $this->_decoder->getElementContent();
             // Work around broken clients (Blackberry) that can send empty
             // $serverid values as a single empty <SYNC_SERVERENTRYID /> tag.
             if ($serverid !== false && !$this->_decoder->getElementEndTag()) {
                 $this->_statusCode = self::STATUS_PROTERROR;
                 $this->_handleGlobalSyncError();
                 $this->_logger->err('Parsing Error - expecting </SYNC_SERVERENTRYID>');
                 return false;
             }
         } else {
             $serverid = false;
         }
         // This tag is only sent here during > 12.1 and SYNC_ADD requests...
         // and it's not even sent by all clients. Parse it if it's there,
         // ignore it if not.
         if ($this->_activeSync->device->version > Horde_ActiveSync::VERSION_TWELVEONE && $element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_ADD && $this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_FOLDERTYPE)) {
             $collection['class'] = $this->_decoder->getElementContent();
             if (!$this->_decoder->getElementEndTag()) {
                 $this->_statusCode = self::STATUS_PROTERROR;
                 $this->_handleGlobalSyncError();
                 $this->_logger->err('Parsing Error - expecting </SYNC_FOLDERTYPE>');
                 return false;
             }
         }
         // Only sent during SYNC_ADD
         if ($element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_ADD && $this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_CLIENTENTRYID)) {
             $clientid = $this->_decoder->getElementContent();
             if (!$this->_decoder->getElementEndTag()) {
                 $this->_statusCode = self::STATUS_PROTERROR;
                 $this->_handleGlobalSyncError();
                 $this->_logger->err('Parsing Error - expecting </SYNC_CLIENTENTRYID>');
                 return false;
             }
         } else {
             $clientid = false;
         }
         // Create Message object from messages passed from client.
         // Only passed during SYNC_ADD or SYNC_MODIFY
         if (($element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_ADD || $element[Horde_ActiveSync_Wbxml::EN_TAG] == Horde_ActiveSync::SYNC_MODIFY) && $this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_DATA)) {
             switch ($collection['class']) {
                 case Horde_ActiveSync::CLASS_EMAIL:
                     $appdata = Horde_ActiveSync::messageFactory('Mail');
                     $appdata->decodeStream($this->_decoder);
                     break;
                 case Horde_ActiveSync::CLASS_CONTACTS:
                     $appdata = Horde_ActiveSync::messageFactory('Contact');
                     $appdata->decodeStream($this->_decoder);
                     break;
                 case Horde_ActiveSync::CLASS_CALENDAR:
                     $appdata = Horde_ActiveSync::messageFactory('Appointment');
                     $appdata->decodeStream($this->_decoder);
                     break;
                 case Horde_ActiveSync::CLASS_TASKS:
                     $appdata = Horde_ActiveSync::messageFactory('Task');
                     $appdata->decodeStream($this->_decoder);
                     break;
                 case Horde_ActiveSync::CLASS_NOTES:
                     $appdata = Horde_ActiveSync::messageFactory('Note');
                     $appdata->decodeStream($this->_decoder);
                     break;
                 case Horde_ActiveSync::CLASS_SMS:
                     $appdata = Horde_ActiveSync::messageFactory('Mail');
                     $appdata->decodeStream($this->_decoder);
                     break;
             }
             if (!$this->_decoder->getElementEndTag()) {
                 // End application data
                 $this->_statusCode = self::STATUS_PROTERROR;
                 $this->_handleGlobalSyncError();
                 return false;
             }
         }
         if (!empty($collection['synckey'])) {
             switch ($element[Horde_ActiveSync_Wbxml::EN_TAG]) {
                 case Horde_ActiveSync::SYNC_MODIFY:
                     if (isset($appdata)) {
                         $id = $importer->importMessageChange($serverid, $appdata, $this->_device, false);
                         if ($id && !is_array($id)) {
                             $collection['importedchanges'] = true;
                         } elseif (is_array($id)) {
                             $collection['importfailures'][$id[0]] = $id[1];
                         }
                     }
                     break;
                 case Horde_ActiveSync::SYNC_ADD:
                     if (isset($appdata)) {
                         $id = $importer->importMessageChange(false, $appdata, $this->_device, $clientid, $collection['class']);
                         if ($clientid && $id && !is_array($id)) {
                             $collection['clientids'][$clientid] = $id;
                             $collection['importedchanges'] = true;
                         } elseif (!$id || is_array($id)) {
                             $collection['clientids'][$clientid] = false;
                         }
                     }
                     break;
                 case Horde_ActiveSync::SYNC_REMOVE:
                     // Work around broken clients that send empty $serverid.
                     if ($serverid) {
                         $collection['removes'][] = $serverid;
                     }
                     break;
                 case Horde_ActiveSync::SYNC_FETCH:
                     $collection['fetchids'][] = $serverid;
                     break;
             }
         }
         if (!$this->_decoder->getElementEndTag()) {
             $this->_statusCode = self::STATUS_PROTERROR;
             $this->_handleGlobalSyncError();
             $this->_logger->err('Parsing error');
             return false;
         }
     }
     // Do all the SYNC_REMOVE requests at once
     if (!empty($collection['removes']) && !empty($collection['synckey'])) {
         if (!empty($collection['deletesasmoves']) && ($folderid = $this->_driver->getWasteBasket($collection['class']))) {
             $results = $importer->importMessageMove($collection['removes'], $folderid);
         } else {
             $results = $importer->importMessageDeletion($collection['removes'], $collection['class']);
             if (is_array($results)) {
                 $results['results'] = $results;
                 $results['missing'] = array_diff($collection['removes'], $results['results']);
             }
         }
         if (!empty($results['missing'])) {
             $collection['missing'] = $results['missing'];
         }
         unset($collection['removes']);
         $collection['importedchanges'] = true;
     }
     $this->_logger->info(sprintf('[%s] Processed %d incoming changes', $this->_procid, $nchanges));
     if (!$this->_decoder->getElementEndTag()) {
         // end commands
         $this->_statusCode = self::STATUS_PROTERROR;
         $this->_handleGlobalSyncError();
         $this->_logger->err('PARSING ERROR');
         return false;
     }
     return true;
 }
Example #2
0
File: Sync.php Project: horde/horde
 /**
  * Helper method for parsing incoming SYNC_FOLDERS nodes.
  *
  */
 protected function _parseSyncFolders()
 {
     while ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_FOLDER)) {
         $collection = $this->_collections->getNewCollection();
         while (($folder_tag = $this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_FOLDERTYPE) ? Horde_ActiveSync::SYNC_FOLDERTYPE : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_SYNCKEY) ? Horde_ActiveSync::SYNC_SYNCKEY : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_FOLDERID) ? Horde_ActiveSync::SYNC_FOLDERID : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_SUPPORTED) ? Horde_ActiveSync::SYNC_SUPPORTED : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_DELETESASMOVES) ? Horde_ActiveSync::SYNC_DELETESASMOVES : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_GETCHANGES) ? Horde_ActiveSync::SYNC_GETCHANGES : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_WINDOWSIZE) ? Horde_ActiveSync::SYNC_WINDOWSIZE : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_CONVERSATIONMODE) ? Horde_ActiveSync::SYNC_CONVERSATIONMODE : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_OPTIONS) ? Horde_ActiveSync::SYNC_OPTIONS : ($this->_decoder->getElementStartTag(Horde_ActiveSync::SYNC_COMMANDS) ? Horde_ActiveSync::SYNC_COMMANDS : -1)))))))))) != -1) {
             switch ($folder_tag) {
                 case Horde_ActiveSync::SYNC_FOLDERTYPE:
                     // According to docs, in 12.1 this is sent here, in > 12.1
                     // it is NOT sent here, it is sent in the ADD command ONLY.
                     // BUT, I haven't seen any 12.1 client actually send this.
                     // Only < 12.1 - leave version sniffing out in this case.
                     $collection['class'] = $this->_decoder->getElementContent();
                     if (!$this->_decoder->getElementEndTag()) {
                         throw new Horde_ActiveSync_Exception('Protocol error');
                     }
                     break;
                 case Horde_ActiveSync::SYNC_SYNCKEY:
                     $collection['synckey'] = $this->_decoder->getElementContent();
                     if (!$this->_decoder->getElementEndTag()) {
                         throw new Horde_ActiveSync_Exception('Protocol error');
                     }
                     break;
                 case Horde_ActiveSync::SYNC_FOLDERID:
                     $collection['id'] = $this->_decoder->getElementContent();
                     if ($collection['id'] === false) {
                         // Log this case explicitly since we can't send back
                         // a protocol error status (the response requires a
                         // collection id and we obviously don't have one).
                         $this->_logger->err(sprintf('[%s] PROTOCOL ERROR. Client sent an empty SYNC_FOLDERID value.', $this->_procid));
                         throw new Horde_ActiveSync_Exception('Protocol error');
                     }
                     if (!$this->_decoder->getElementEndTag()) {
                         throw new Horde_ActiveSync_Exception('Protocol error');
                     }
                     break;
                 case Horde_ActiveSync::SYNC_WINDOWSIZE:
                     $collection['windowsize'] = $this->_decoder->getElementContent();
                     if (!$this->_decoder->getElementEndTag()) {
                         $this->_statusCode = self::STATUS_PROTERROR;
                         $this->_handleError($collection);
                         return false;
                     }
                     if ($collection['windowsize'] < 1 || $collection['windowsize'] > self::MAX_WINDOW_SIZE) {
                         $this->_logger->err(sprintf('[%s] Bad windowsize sent, defaulting to 512', $this->_procid));
                         $collection['windowsize'] = self::MAX_WINDOW_SIZE;
                     }
                     break;
                 case Horde_ActiveSync::SYNC_CONVERSATIONMODE:
                     // Optional element, but if it's present with an empty value
                     // it defaults to true.
                     $collection['conversationmode'] = $this->_decoder->getElementContent();
                     if ($collection['conversationmode'] !== false && !$this->_decoder->getElementEndTag()) {
                         throw new Horde_ActiveSync_Exception('Protocol Error');
                     } elseif ($collection['conversationmode'] === false) {
                         $collection['conversationmode'] = true;
                     }
                     break;
                 case Horde_ActiveSync::SYNC_SUPPORTED:
                     // Only allowed on initial sync request
                     if ($collection['synckey'] != '0') {
                         $this->_statusCode = self::STATUS_PROTERROR;
                         $this->_handleError($collection);
                         return false;
                     }
                     while (1) {
                         $el = $this->_decoder->getElement();
                         if ($this->_decoder->isEmptyElement($this->_decoder->getLastStartElement())) {
                             // MS-ASCMD 2.2.3.168 An empty SUPPORTED tag
                             // indicates that ALL elements able to be ghosted
                             // ARE ghosted.
                             $collection['supported'] = array(Horde_ActiveSync::ALL_GHOSTED);
                             break;
                         }
                         if ($el[Horde_ActiveSync_Wbxml::EN_TYPE] == Horde_ActiveSync_Wbxml::EN_TYPE_ENDTAG) {
                             break;
                         }
                         $collection['supported'][] = $el[2];
                     }
                     if (!empty($collection['supported'])) {
                         // Initial sync and we have SUPPORTED data - save it
                         if (empty($this->_device->supported)) {
                             $this->_device->supported = array();
                         }
                         // Not all clients send the $collection['class'] in more
                         // recent EAS versions. Grab it from the collection
                         // handler if needed.
                         if (empty($collection['class'])) {
                             $collection['class'] = $this->_collections->getCollectionClass($collection['id']);
                         }
                         $this->_device->supported[$collection['class']] = $collection['supported'];
                         $this->_device->save();
                     }
                     break;
                 case Horde_ActiveSync::SYNC_DELETESASMOVES:
                     // Optional element, but if it's present with an empty value
                     // it defaults to true.
                     $collection['deletesasmoves'] = $this->_decoder->getElementContent();
                     if ($collection['deletesasmoves'] !== false && !$this->_decoder->getElementEndTag()) {
                         throw new Horde_ActiveSync_Exception('Protocol Error');
                     } elseif ($collection['deletesasmoves'] === false) {
                         $collection['deletesasmoves'] = true;
                     }
                     break;
                 case Horde_ActiveSync::SYNC_GETCHANGES:
                     // Optional element, but if it's present with an empty value
                     // it defaults to true.
                     $collection['getchanges'] = $this->_decoder->getElementContent();
                     if ($collection['getchanges'] !== false && !$this->_decoder->getElementEndTag()) {
                         // Present, has a value, but no closing tag.
                         throw new Horde_ActiveSync_Exception('Protocol Error');
                     } elseif ($collection['getchanges'] === false) {
                         // Present, but is an empty tag, so defaults to true.
                         $collection['getchanges'] = true;
                     }
                     break;
                 case Horde_ActiveSync::SYNC_OPTIONS:
                     if (!$this->_decoder->isEmptyElement($this->_decoder->getLastStartElement())) {
                         $this->_parseSyncOptions($collection);
                     }
                     break;
                 case Horde_ActiveSync::SYNC_COMMANDS:
                     if (!$this->_parseSyncCommands($collection)) {
                         return false;
                     }
             }
         }
         if (!$this->_decoder->getElementEndTag()) {
             $this->_statusCode = self::STATUS_PROTERROR;
             $this->_handleError($collection);
             return false;
         }
         if (isset($collection['filtertype']) && !$this->_collections->checkFilterType($collection['id'], $collection['filtertype'])) {
             $this->_logger->info(sprintf('[%s] Found updated filtertype, will force a SOFTDELETE.', $this->_procid));
             $collection['forcerefresh'] = true;
         }
         // Default value, if missing is TRUE if we have a non-empty synckey,
         // otherwise FALSE.
         if (!isset($collection['getchanges'])) {
             $collection['getchanges'] = !empty($collection['synckey']);
         }
         try {
             $this->_collections->addCollection($collection);
         } catch (Horde_ActiveSync_Exception_StateGone $e) {
             $this->_statusCode = self::STATUS_NOTFOUND;
             $this->_handleError($collection);
             return false;
         } catch (Horde_ActiveSync_Exception $e) {
             $this->_statusCode = self::STATUS_SERVERERROR;
             $this->_handleError($collection);
             return false;
         }
         if (!empty($collection['importedchanges'])) {
             $this->_collections->importedChanges = true;
         }
         if ($this->_collections->collectionExists($collection['id']) && !empty($collection['windowsize'])) {
             $this->_collections->updateWindowSize($collection['id'], $collection['windowsize']);
         }
     }
     if (!$this->_decoder->getElementEndTag()) {
         $this->_logger->err('Parsing Error');
         return false;
     }
     return true;
 }