Horde_ActiveSync_Collections::initCollectionState PHP Method

initCollectionState() public method

Attempt to initialize the sync state.
public initCollectionState ( array &$collection, boolean $requireSyncKey = false )
$collection array The collection array.
$requireSyncKey boolean Require collection to have a synckey and throw exception if it's not present.
    public function initCollectionState(array &$collection, $requireSyncKey = false)
    {
        // Clear the changes cache.
        $this->_changes = null;
        // Ensure we have a collection class.
        if (empty($collection['class'])) {
            if (!($collection['class'] = $this->getCollectionClass($collection['id']))) {
                throw new Horde_ActiveSync_Exception_FolderGone('Could not load collection class for ' . $collection['id']);
            }
        }
        // Load the collection's type if we can.
        if (empty($collection['type'])) {
            $collection['type'] = $this->getCollectionType($collection['id']);
        }
        // Get the backend serverid.
        if (empty($collection['serverid'])) {
            $collection['serverid'] = $this->getBackendIdForFolderUid($collection['id']);
        }
        if ($requireSyncKey && empty($collection['synckey'])) {
            throw new Horde_ActiveSync_Exception_InvalidRequest(sprintf('[%s] Empty synckey for %s.', $this->_procid, $collection['id']));
        }
        // Initialize the state
        $this->_logger->info(sprintf('[%s] Initializing state for collection: %s, synckey: %s', $this->_procid, $collection['serverid'], $collection['synckey']));
        $this->_as->state->loadState($collection, $collection['synckey'], Horde_ActiveSync::REQUEST_TYPE_SYNC, $collection['id']);
    }

Usage Example

Beispiel #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;
 }