/** * Decodes the WBXML from a WBXMLdecoder until we reach the same depth level of WBXML. * This means that if there are multiple objects at this level, then only the first is * decoded SubOjects are auto-instantiated and decoded using the same functionality * * @param WBXMLDecoder $decoder * * @access public */ public function Decode(&$decoder) { while (1) { $entity = $decoder->getElement(); if ($entity[EN_TYPE] == EN_TYPE_STARTTAG) { if (!($entity[EN_FLAGS] & EN_FLAGS_CONTENT)) { $map = $this->mapping[$entity[EN_TAG]]; if (isset($map[self::STREAMER_ARRAY])) { $this->{$map}[self::STREAMER_VAR] = array(); } else { if (!isset($map[self::STREAMER_TYPE])) { $this->{$map}[self::STREAMER_VAR] = ""; } else { if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE_DASHES) { $this->{$map}[self::STREAMER_VAR] = ""; } else { if (isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_SEND_EMPTY) { $this->{$map}[self::STREAMER_VAR] = ""; } } } } continue; } // Found a start tag if (!isset($this->mapping[$entity[EN_TAG]])) { // This tag shouldn't be here, abort ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("Tag '%s' unexpected in type XML type '%s'", $entity[EN_TAG], get_class($this))); return false; } else { $map = $this->mapping[$entity[EN_TAG]]; // Handle an array if (isset($map[self::STREAMER_ARRAY])) { while (1) { //do not get start tag for an array without a container if (!(isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER)) { if (!$decoder->getElementStartTag($map[self::STREAMER_ARRAY])) { break; } } if (isset($map[self::STREAMER_TYPE])) { $decoded = new $map[self::STREAMER_TYPE](); $decoded->Decode($decoder); } else { $decoded = $decoder->getElementContent(); } if (!isset($this->{$map}[self::STREAMER_VAR])) { $this->{$map}[self::STREAMER_VAR] = array($decoded); } else { array_push($this->{$map}[self::STREAMER_VAR], $decoded); } if (!$decoder->getElementEndTag()) { //end tag of a container element return false; } if (isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER) { $e = $decoder->peek(); //go back to the initial while if another block of no container elements is found if ($e[EN_TYPE] == EN_TYPE_STARTTAG) { continue 2; } //break on end tag because no container elements block end is reached if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { break; } if (empty($e)) { break; } } } //do not get end tag for an array without a container if (!(isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER)) { if (!$decoder->getElementEndTag()) { //end tag of container return false; } } } else { // Handle single value if (isset($map[self::STREAMER_TYPE])) { // Complex type, decode recursively if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE_DASHES) { $decoded = $this->parseDate($decoder->getElementContent()); if (!$decoder->getElementEndTag()) { return false; } } else { if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_HEX) { $decoded = hex2bin($decoder->getElementContent()); if (!$decoder->getElementEndTag()) { return false; } } else { if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_COMMA_SEPARATED || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEMICOLON_SEPARATED) { $glue = $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_COMMA_SEPARATED ? ", " : "; "; $decoded = explode($glue, $decoder->getElementContent()); if (!$decoder->getElementEndTag()) { return false; } } else { $subdecoder = new $map[self::STREAMER_TYPE](); if ($subdecoder->Decode($decoder) === false) { return false; } $decoded = $subdecoder; if (!$decoder->getElementEndTag()) { ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("No end tag for '%s'", $entity[EN_TAG])); return false; } } } } } else { // Simple type, just get content $decoded = $decoder->getElementContent(); if ($decoded === false) { // the tag is declared to have content, but no content is available. // set an empty content $decoded = ""; } if (!$decoder->getElementEndTag()) { ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("Unable to get end tag for '%s'", $entity[EN_TAG])); return false; } } // $decoded now contains data object (or string) $this->{$map}[self::STREAMER_VAR] = $decoded; } } } else { if ($entity[EN_TYPE] == EN_TYPE_ENDTAG) { $decoder->ungetElement($entity); break; } else { ZLog::Write(LOGLEVEL_WBXMLSTACK, "Unexpected content in type"); break; } } } }
/** * Handles the Search command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { $searchrange = '0'; $cpo = new ContentParameters(); if (!self::$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { return false; } // TODO check: possible to search in other stores? if (!self::$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { return false; } if (!self::$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { return false; } $searchname = strtoupper(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } if (!self::$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { return false; } // check if it is a content of an element (= GAL search) // or a starttag (= mailbox or documentlibrary search) $searchquery = self::$decoder->getElementContent(); if ($searchquery && !self::$decoder->getElementEndTag()) { return false; } if ($searchquery === false) { $cpo->SetSearchName($searchname); if (self::$decoder->getElementStartTag(SYNC_SEARCH_AND)) { if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { $searchfolderid = self::$decoder->getElementContent(); $cpo->SetSearchFolderid($searchfolderid); if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE return false; } } if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { $searchclass = self::$decoder->getElementContent(); $cpo->SetSearchClass($searchclass); if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE return false; } } if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { $searchfolderid = self::$decoder->getElementContent(); $cpo->SetSearchFolderid($searchfolderid); if (!self::$decoder->getElementEndTag()) { // SYNC_FOLDERTYPE return false; } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { $searchfreetext = self::$decoder->getElementContent(); $cpo->SetSearchFreeText($searchfreetext); if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT return false; } } //TODO - review if (self::$decoder->getElementStartTag(SYNC_SEARCH_GREATERTHAN)) { if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { $datereceivedgreater = true; if (($dam = self::$decoder->getElementContent()) !== false) { $datereceivedgreater = true; if (!self::$decoder->getElementEndTag()) { return false; } } $cpo->SetSearchDateReceivedGreater($datereceivedgreater); } if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { $searchvalue = self::$decoder->getElementContent(); $cpo->SetSearchValueGreater($searchvalue); if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE return false; } } if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_GREATERTHAN return false; } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_LESSTHAN)) { if (self::$decoder->getElementStartTag(SYNC_POOMMAIL_DATERECEIVED)) { $datereceivedless = true; if (($dam = self::$decoder->getElementContent()) !== false) { $datereceivedless = true; if (!self::$decoder->getElementEndTag()) { return false; } } $cpo->SetSearchDateReceivedLess($datereceivedless); } if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { $searchvalue = self::$decoder->getElementContent(); $cpo->SetSearchValueLess($searchvalue); if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE return false; } } if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_LESSTHAN return false; } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_FREETEXT)) { $searchfreetext = self::$decoder->getElementContent(); $cpo->SetSearchFreeText($searchfreetext); if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_FREETEXT return false; } } if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_AND return false; } } elseif (self::$decoder->getElementStartTag(SYNC_SEARCH_EQUALTO)) { // linkid can be an empty tag as well as have value if (self::$decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID)) { if (($linkId = self::$decoder->getElementContent()) !== false) { $cpo->SetLinkId($linkId); if (!self::$decoder->getElementEndTag()) { // SYNC_DOCUMENTLIBRARY_LINKID return false; } } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_VALUE)) { $searchvalue = self::$decoder->getElementContent(); $cpo->SetSearchValueEqualTo($searchvalue); if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_VALUE return false; } } if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_EQUALTO return false; } } if (!self::$decoder->getElementEndTag()) { // SYNC_SEARCH_QUERY return false; } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { WBXMLDecoder::ResetInWhile("searchOptions"); while (WBXMLDecoder::InWhile("searchOptions")) { if (self::$decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { $searchrange = self::$decoder->getElementContent(); $cpo->SetSearchRange($searchrange); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_SEARCH_REBUILDRESULTS)) { $rebuildresults = true; if (($dam = self::$decoder->getElementContent()) !== false) { $rebuildresults = true; if (!self::$decoder->getElementEndTag()) { return false; } } $cpo->SetSearchRebuildResults($rebuildresults); } if (self::$decoder->getElementStartTag(SYNC_SEARCH_DEEPTRAVERSAL)) { $deeptraversal = true; if (($dam = self::$decoder->getElementContent()) !== false) { $deeptraversal = true; if (!self::$decoder->getElementEndTag()) { return false; } } $cpo->SetSearchDeepTraversal($deeptraversal); } if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { $cpo->SetMimeSupport(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } //TODO body preferences while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { $bptype = self::$decoder->getElementContent(); $cpo->BodyPreference($bptype); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { $cpo->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { $cpo->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { $cpo->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (!self::$decoder->getElementEndTag()) { return false; } } $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } } if (!self::$decoder->getElementEndTag()) { //store return false; } if (!self::$decoder->getElementEndTag()) { //search return false; } // get SearchProvider $searchprovider = ZPush::GetSearchProvider(); $status = SYNC_SEARCHSTATUS_SUCCESS; $rows = array(); // TODO support other searches if ($searchprovider->SupportsType($searchname)) { $storestatus = SYNC_SEARCHSTATUS_STORE_SUCCESS; try { if ($searchname == ISearchProvider::SEARCH_GAL) { //get search results from the searchprovider $rows = $searchprovider->GetGALSearchResults($searchquery, $searchrange); } elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($cpo->GetSearchFolderid()); $cpo->SetSearchFolderid($backendFolderId); $rows = $searchprovider->GetMailboxSearchResults($cpo); } } catch (StatusException $stex) { $storestatus = $stex->getCode(); } } else { $rows = array('searchtotal' => 0); $status = SYNC_SEARCHSTATUS_SERVERERROR; ZLog::Write(LOGLEVEL_WARN, sprintf("Searchtype '%s' is not supported.", $searchname)); self::$topCollector->AnnounceInformation(sprintf("Unsupported type '%s''", $searchname), true); } $searchprovider->Disconnect(); self::$topCollector->AnnounceInformation(sprintf("'%s' search found %d results", $searchname, $rows['searchtotal']), true); self::$encoder->startWBXML(); self::$encoder->startTag(SYNC_SEARCH_SEARCH); self::$encoder->startTag(SYNC_SEARCH_STATUS); self::$encoder->content($status); self::$encoder->endTag(); if ($status == SYNC_SEARCHSTATUS_SUCCESS) { self::$encoder->startTag(SYNC_SEARCH_RESPONSE); self::$encoder->startTag(SYNC_SEARCH_STORE); self::$encoder->startTag(SYNC_SEARCH_STATUS); self::$encoder->content($storestatus); self::$encoder->endTag(); if (isset($rows['range'])) { $searchrange = $rows['range']; unset($rows['range']); } if (isset($rows['searchtotal'])) { $searchtotal = $rows['searchtotal']; unset($rows['searchtotal']); } if ($searchname == ISearchProvider::SEARCH_GAL) { if (is_array($rows) && !empty($rows)) { foreach ($rows as $u) { self::$encoder->startTag(SYNC_SEARCH_RESULT); self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); self::$encoder->startTag(SYNC_GAL_DISPLAYNAME); self::$encoder->content(isset($u[SYNC_GAL_DISPLAYNAME]) ? $u[SYNC_GAL_DISPLAYNAME] : "No name"); self::$encoder->endTag(); if (isset($u[SYNC_GAL_PHONE])) { self::$encoder->startTag(SYNC_GAL_PHONE); self::$encoder->content($u[SYNC_GAL_PHONE]); self::$encoder->endTag(); } if (isset($u[SYNC_GAL_OFFICE])) { self::$encoder->startTag(SYNC_GAL_OFFICE); self::$encoder->content($u[SYNC_GAL_OFFICE]); self::$encoder->endTag(); } if (isset($u[SYNC_GAL_TITLE])) { self::$encoder->startTag(SYNC_GAL_TITLE); self::$encoder->content($u[SYNC_GAL_TITLE]); self::$encoder->endTag(); } if (isset($u[SYNC_GAL_COMPANY])) { self::$encoder->startTag(SYNC_GAL_COMPANY); self::$encoder->content($u[SYNC_GAL_COMPANY]); self::$encoder->endTag(); } if (isset($u[SYNC_GAL_ALIAS])) { self::$encoder->startTag(SYNC_GAL_ALIAS); self::$encoder->content($u[SYNC_GAL_ALIAS]); self::$encoder->endTag(); } // Always send the firstname, even empty. Nokia needs this to display the entry self::$encoder->startTag(SYNC_GAL_FIRSTNAME); self::$encoder->content(isset($u[SYNC_GAL_FIRSTNAME]) ? $u[SYNC_GAL_FIRSTNAME] : ""); self::$encoder->endTag(); self::$encoder->startTag(SYNC_GAL_LASTNAME); self::$encoder->content(isset($u[SYNC_GAL_LASTNAME]) ? $u[SYNC_GAL_LASTNAME] : "No name"); self::$encoder->endTag(); if (isset($u[SYNC_GAL_HOMEPHONE])) { self::$encoder->startTag(SYNC_GAL_HOMEPHONE); self::$encoder->content($u[SYNC_GAL_HOMEPHONE]); self::$encoder->endTag(); } if (isset($u[SYNC_GAL_MOBILEPHONE])) { self::$encoder->startTag(SYNC_GAL_MOBILEPHONE); self::$encoder->content($u[SYNC_GAL_MOBILEPHONE]); self::$encoder->endTag(); } self::$encoder->startTag(SYNC_GAL_EMAILADDRESS); self::$encoder->content(isset($u[SYNC_GAL_EMAILADDRESS]) ? $u[SYNC_GAL_EMAILADDRESS] : ""); self::$encoder->endTag(); self::$encoder->endTag(); //result self::$encoder->endTag(); //properties } } } elseif ($searchname == ISearchProvider::SEARCH_MAILBOX) { foreach ($rows as $u) { $folderid = self::$deviceManager->GetFolderIdForBackendId($u['folderid']); self::$encoder->startTag(SYNC_SEARCH_RESULT); self::$encoder->startTag(SYNC_FOLDERTYPE); self::$encoder->content($u['class']); self::$encoder->endTag(); self::$encoder->startTag(SYNC_SEARCH_LONGID); self::$encoder->content($u['longid']); self::$encoder->endTag(); self::$encoder->startTag(SYNC_FOLDERID); self::$encoder->content($folderid); self::$encoder->endTag(); self::$encoder->startTag(SYNC_SEARCH_PROPERTIES); $tmp = explode(":", $u['longid']); $message = self::$backend->Fetch($u['folderid'], $tmp[1], $cpo); $message->Encode(self::$encoder); self::$encoder->endTag(); //result self::$encoder->endTag(); //properties } } // it seems that android 4 requires range and searchtotal // or it won't display the search results if (isset($searchrange)) { self::$encoder->startTag(SYNC_SEARCH_RANGE); self::$encoder->content($searchrange); self::$encoder->endTag(); } if (isset($searchtotal) && $searchtotal > 0) { self::$encoder->startTag(SYNC_SEARCH_TOTAL); self::$encoder->content($searchtotal); self::$encoder->endTag(); } self::$encoder->endTag(); //store self::$encoder->endTag(); //response } self::$encoder->endTag(); //search return true; }
/** * Synchronizes a folder to the output stream. Changes for this folders are expected. * * @param SyncCollections $sc * @param SyncParameters $spa * @param IExportChanges $exporter Fully configured exporter for this folder * @param int $changecount Amount of changes expected * @param ImportChangesStream $streamimporter Output stream * @param int $status current status of the folder processing * @param string $newFolderStat the new folder stat to be set if everything was exported * * @throws StatusException * @return int sync status code */ private function syncFolder($sc, $spa, $exporter, $changecount, $streamimporter, $status, $newFolderStat) { $actiondata = $sc->GetParameter($spa, "actiondata"); // send the WBXML start tags (if not happened already) $this->sendFolderStartTag(); self::$encoder->startTag(SYNC_FOLDER); if ($spa->HasContentClass()) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("Folder type: %s", $spa->GetContentClass())); // AS 12.0 devices require content class if (Request::GetProtocolVersion() < 12.1) { self::$encoder->startTag(SYNC_FOLDERTYPE); self::$encoder->content($spa->GetContentClass()); self::$encoder->endTag(); } } self::$encoder->startTag(SYNC_SYNCKEY); if ($status == SYNC_STATUS_SUCCESS && $spa->HasNewSyncKey()) { self::$encoder->content($spa->GetNewSyncKey()); } else { self::$encoder->content($spa->GetSyncKey()); } self::$encoder->endTag(); self::$encoder->startTag(SYNC_FOLDERID); self::$encoder->content($spa->GetFolderId()); self::$encoder->endTag(); self::$encoder->startTag(SYNC_STATUS); self::$encoder->content($status); self::$encoder->endTag(); // announce failing status to the process loop detection if ($status !== SYNC_STATUS_SUCCESS) { self::$deviceManager->AnnounceProcessStatus($spa->GetFolderId(), $status); } // Output IDs and status for incoming items & requests if ($status == SYNC_STATUS_SUCCESS && (!empty($actiondata["clientids"]) || !empty($actiondata["modifyids"]) || !empty($actiondata["removeids"]) || !empty($actiondata["fetchids"]))) { self::$encoder->startTag(SYNC_REPLIES); // output result of all new incoming items foreach ($actiondata["clientids"] as $clientid => $serverid) { self::$encoder->startTag(SYNC_ADD); self::$encoder->startTag(SYNC_CLIENTENTRYID); self::$encoder->content($clientid); self::$encoder->endTag(); if ($serverid) { self::$encoder->startTag(SYNC_SERVERENTRYID); self::$encoder->content($serverid); self::$encoder->endTag(); } self::$encoder->startTag(SYNC_STATUS); self::$encoder->content(isset($actiondata["statusids"][$clientid]) ? $actiondata["statusids"][$clientid] : SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR); self::$encoder->endTag(); self::$encoder->endTag(); } // loop through modify operations which were not a success, send status foreach ($actiondata["modifyids"] as $serverid) { if (isset($actiondata["statusids"][$serverid]) && $actiondata["statusids"][$serverid] !== SYNC_STATUS_SUCCESS) { self::$encoder->startTag(SYNC_MODIFY); self::$encoder->startTag(SYNC_SERVERENTRYID); self::$encoder->content($serverid); self::$encoder->endTag(); self::$encoder->startTag(SYNC_STATUS); self::$encoder->content($actiondata["statusids"][$serverid]); self::$encoder->endTag(); self::$encoder->endTag(); } } // loop through remove operations which were not a success, send status foreach ($actiondata["removeids"] as $serverid) { if (isset($actiondata["statusids"][$serverid]) && $actiondata["statusids"][$serverid] !== SYNC_STATUS_SUCCESS) { self::$encoder->startTag(SYNC_REMOVE); self::$encoder->startTag(SYNC_SERVERENTRYID); self::$encoder->content($serverid); self::$encoder->endTag(); self::$encoder->startTag(SYNC_STATUS); self::$encoder->content($actiondata["statusids"][$serverid]); self::$encoder->endTag(); self::$encoder->endTag(); } } if (!empty($actiondata["fetchids"])) { self::$topCollector->AnnounceInformation(sprintf("Fetching %d objects ", count($actiondata["fetchids"])), $this->singleFolder); $this->saveMultiFolderInfo("fetching", count($actiondata["fetchids"])); } foreach ($actiondata["fetchids"] as $id) { $data = false; try { $fetchstatus = SYNC_STATUS_SUCCESS; // if this is an additional folder the backend has to be setup correctly if (!self::$backend->Setup(ZPush::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()))) { throw new StatusException(sprintf("HandleSync(): could not Setup() the backend to fetch in folder id %s/%s", $spa->GetFolderId(), $spa->GetBackendFolderId()), SYNC_STATUS_OBJECTNOTFOUND); } $data = self::$backend->Fetch($spa->GetBackendFolderId(), $id, $spa->GetCPO()); // check if the message is broken if (ZPush::GetDeviceManager(false) && ZPush::GetDeviceManager()->DoNotStreamMessage($id, $data)) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): message not to be streamed as requested by DeviceManager, id = %s", $id)); $fetchstatus = SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR; } } catch (StatusException $stex) { $fetchstatus = $stex->getCode(); } self::$encoder->startTag(SYNC_FETCH); self::$encoder->startTag(SYNC_SERVERENTRYID); self::$encoder->content($id); self::$encoder->endTag(); self::$encoder->startTag(SYNC_STATUS); self::$encoder->content($fetchstatus); self::$encoder->endTag(); if ($data !== false && $status == SYNC_STATUS_SUCCESS) { self::$encoder->startTag(SYNC_DATA); $data->Encode(self::$encoder); self::$encoder->endTag(); } else { ZLog::Write(LOGLEVEL_WARN, sprintf("Unable to Fetch '%s'", $id)); } self::$encoder->endTag(); } self::$encoder->endTag(); } if ($sc->GetParameter($spa, "getchanges") && $spa->HasFolderId() && $spa->HasContentClass() && $spa->HasSyncKey()) { $moreAvailableSent = false; $windowSize = self::$deviceManager->GetWindowSize($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter(), $changecount); // limit windowSize to the max available limit of the global window size left $globallyAvailable = $sc->GetGlobalWindowSize() - $this->globallyExportedItems; if ($changecount > $globallyAvailable && $windowSize > $globallyAvailable) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Limit window size to %d as the global window size limit will be reached", $globallyAvailable)); $windowSize = $globallyAvailable; } // send <MoreAvailable/> if there are more changes than fit in the folder windowsize // or there is a move state (another sync should be done afterwards) if ($changecount > $windowSize || $spa->GetMoveState() !== false) { self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true); $moreAvailableSent = true; $spa->DelFolderStat(); } } // Stream outgoing changes if ($status == SYNC_STATUS_SUCCESS && $sc->GetParameter($spa, "getchanges") == true && $windowSize > 0 && !!$exporter) { self::$topCollector->AnnounceInformation(sprintf("Streaming data of %d objects", $changecount > $windowSize ? $windowSize : $changecount)); // Output message changes per folder self::$encoder->startTag(SYNC_PERFORM); $n = 0; WBXMLDecoder::ResetInWhile("syncSynchronize"); while (WBXMLDecoder::InWhile("syncSynchronize")) { try { $progress = $exporter->Synchronize(); if (!is_array($progress)) { break; } $n++; if ($n % 10 == 0) { self::$topCollector->AnnounceInformation(sprintf("Streamed data of %d objects out of %d", $n, $changecount > $windowSize ? $windowSize : $changecount)); } } catch (SyncObjectBrokenException $mbe) { $brokenSO = $mbe->GetSyncObject(); if (!$brokenSO) { ZLog::Write(LOGLEVEL_ERROR, sprintf("HandleSync(): Catched SyncObjectBrokenException but broken SyncObject not available. This should be fixed in the backend.")); } else { if (!isset($brokenSO->id)) { $brokenSO->id = "Unknown ID"; ZLog::Write(LOGLEVEL_ERROR, sprintf("HandleSync(): Catched SyncObjectBrokenException but no ID of object set. This should be fixed in the backend.")); } self::$deviceManager->AnnounceIgnoredMessage($spa->GetFolderId(), $brokenSO->id, $brokenSO); } } catch (StatusException $stex) { $status = $stex->getCode(); // during export we found out that the states should be thrown away (ZP-623) if ($status == SYNC_STATUS_INVALIDSYNCKEY) { self::$deviceManager->ForceFolderResync($spa->GetFolderId()); break; } } if ($n >= $windowSize || Request::IsRequestTimeoutReached()) { ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Exported maxItems of messages: %d / %d", $n, $changecount)); break; } } // $progress is not an array when exporting the last message // so we get the number to display from the streamimporter if it's available if (!!$streamimporter) { $n = $streamimporter->GetImportedMessages(); } self::$encoder->endTag(); // log the request timeout if (Request::IsRequestTimeoutReached()) { ZLog::Write(LOGLEVEL_DEBUG, "HandleSync(): Stopping export as maximum request timeout is almost reached!"); // Send a <MoreAvailable/> tag if we reached the request timeout, there are more changes and a moreavailable was not already send if (!$moreAvailableSent && $n > $windowSize) { self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true); $spa->DelFolderStat(); $moreAvailableSent = true; } } self::$topCollector->AnnounceInformation(sprintf("Outgoing %d objects%s", $n, $n >= $windowSize ? " of " . $changecount : ""), $this->singleFolder); $this->saveMultiFolderInfo("outgoing", $n); $this->saveMultiFolderInfo("queued", $changecount); $this->globallyExportedItems += $n; // update folder status, if there is something set if ($spa->GetFolderSyncRemaining() && $changecount > 0) { $spa->SetFolderSyncRemaining($changecount); } // changecount is initialized with 'false', so 0 means no changes! if ($changecount === 0 || $changecount !== false && $changecount <= $windowSize) { self::$deviceManager->SetFolderSyncStatus($spa->GetFolderId(), DeviceManager::FLD_SYNC_COMPLETED); // we should update the folderstat, but we recheck to see if it changed. If so, it's not updated to force another sync $newFolderStatAfterExport = self::$backend->GetFolderStat(ZPush::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()), $spa->GetBackendFolderId()); if ($newFolderStat === $newFolderStatAfterExport) { $this->setFolderStat($spa, $newFolderStat); } else { ZLog::Write(LOGLEVEL_DEBUG, "Sync() Folderstat differs after export, force another exporter run."); } } else { self::$deviceManager->SetFolderSyncStatus($spa->GetFolderId(), DeviceManager::FLD_SYNC_INPROGRESS); } } self::$encoder->endTag(); // Save the sync state for the next time if ($spa->HasNewSyncKey()) { self::$topCollector->AnnounceInformation("Saving state"); try { if (isset($exporter) && $exporter) { $state = $exporter->GetState(); // update the move state (it should be gone now) list($moveState, ) = $exporter->GetMoveStates(); $spa->SetMoveState($moveState); } else { if ($sc->GetParameter($spa, "state") !== null) { $state = $sc->GetParameter($spa, "state"); } else { if (!$spa->HasSyncKey()) { $state = ""; } } } } catch (StatusException $stex) { $status = $stex->getCode(); } if (isset($state) && $status == SYNC_STATUS_SUCCESS) { self::$deviceManager->GetStateManager()->SetSyncState($spa->GetNewSyncKey(), $state, $spa->GetFolderId()); } else { ZLog::Write(LOGLEVEL_ERROR, sprintf("HandleSync(): error saving '%s' - no state information available", $spa->GetNewSyncKey())); } } // save SyncParameters if ($status == SYNC_STATUS_SUCCESS && empty($actiondata["fetchids"])) { $sc->SaveCollection($spa); } return $status; }
/** * Handles the ItemOperations command * Provides batched online handling for Fetch, EmptyFolderContents and Move * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { // Parse input if (!self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS)) { return false; } $itemoperations = array(); //ItemOperations can either be Fetch, EmptyFolderContents or Move WBXMLDecoder::ResetInWhile("itemOperationsActions"); while (WBXMLDecoder::InWhile("itemOperationsActions")) { //TODO check if multiple item operations are possible in one request $el = self::$decoder->getElement(); if ($el[EN_TYPE] != EN_TYPE_STARTTAG) { return false; } $fetch = $efc = $move = false; $operation = array(); if ($el[EN_TAG] == SYNC_ITEMOPERATIONS_FETCH) { $fetch = true; $operation['operation'] = SYNC_ITEMOPERATIONS_FETCH; self::$topCollector->AnnounceInformation("Fetch", true); } else { if ($el[EN_TAG] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { $efc = true; $operation['operation'] = SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS; self::$topCollector->AnnounceInformation("Empty Folder", true); } else { if ($el[EN_TAG] == SYNC_ITEMOPERATIONS_MOVE) { $move = true; $operation['operation'] = SYNC_ITEMOPERATIONS_MOVE; self::$topCollector->AnnounceInformation("Move", true); } } } if (!$fetch && !$efc && !$move) { ZLog::Write(LOGLEVEL_DEBUG, "Unknown item operation:" . print_r($el, 1)); self::$topCollector->AnnounceInformation("Unknown operation", true); return false; } // process operation WBXMLDecoder::ResetInWhile("itemOperationsOperation"); while (WBXMLDecoder::InWhile("itemOperationsOperation")) { if ($fetch) { if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_STORE)) { $operation['store'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_ITEMOPERATIONS_STORE } if (self::$decoder->getElementStartTag(SYNC_SEARCH_LONGID)) { $operation['longid'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_SEARCH_LONGID } if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { $operation['folderid'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_FOLDERID } if (self::$decoder->getElementStartTag(SYNC_SERVERENTRYID)) { $operation['serverid'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_SERVERENTRYID } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_FILEREFERENCE)) { $operation['filereference'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_AIRSYNCBASE_FILEREFERENCE } if (($el = self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) { //TODO other options //schema //range //username //password //bodypartpreference //rm:RightsManagementSupport // Save all OPTIONS into a ContentParameters object $operation["cpo"] = new ContentParameters(); WBXMLDecoder::ResetInWhile("itemOperationsOptions"); while (WBXMLDecoder::InWhile("itemOperationsOptions")) { while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { $bptype = self::$decoder->getElementContent(); $operation["cpo"]->BodyPreference($bptype); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { $operation["cpo"]->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { $operation["cpo"]->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) { $operation["cpo"]->BodyPreference($bptype)->SetPreview(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_AIRSYNCBASE_BODYPREFERENCE } if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) { $operation["cpo"]->SetMimeSupport(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_RANGE)) { $operation["range"] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_SCHEMA)) { // read schema tags WBXMLDecoder::ResetInWhile("itemOperationsSchema"); while (WBXMLDecoder::InWhile("itemOperationsSchema")) { // TODO save elements $el = self::$decoder->getElement(); $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } } //break if it reached the endtag $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } } } // end if fetch if ($efc) { if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) { $operation['folderid'] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_FOLDERID } if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS)) { if (self::$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_DELETESUBFOLDERS)) { $operation['deletesubfolders'] = true; if (($dsf = self::$decoder->getElementContent()) !== false) { $operation['deletesubfolders'] = (bool) $dsf; if (!self::$decoder->getElementEndTag()) { return false; } } } self::$decoder->getElementEndTag(); } } //TODO move //break if it reached the endtag SYNC_ITEMOPERATIONS_FETCH or SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS or SYNC_ITEMOPERATIONS_MOVE $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } // end while operation // rewrite folderid into backendfolderid to be used on backend operations below if (isset($operation['folderid'])) { $operation['backendfolderid'] = self::$deviceManager->GetBackendIdForFolderId($operation['folderid']); } $itemoperations[] = $operation; //break if it reached the endtag $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); //SYNC_ITEMOPERATIONS_ITEMOPERATIONS break; } } // end operations loop $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; self::$encoder->startWBXML(); self::$encoder->startTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS); self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); self::$encoder->content($status); self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_STATUS // Stop here if something went wrong if ($status != SYNC_ITEMOPERATIONSSTATUS_SUCCESS) { self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_ITEMOPERATIONS return true; } self::$encoder->startTag(SYNC_ITEMOPERATIONS_RESPONSE); foreach ($itemoperations as $operation) { // fetch response if ($operation['operation'] == SYNC_ITEMOPERATIONS_FETCH) { $status = SYNC_ITEMOPERATIONSSTATUS_SUCCESS; // retrieve the data // Fetch throws Sync status codes, - GetAttachmentData ItemOperations codes if (isset($operation['filereference'])) { try { self::$topCollector->AnnounceInformation("Get attachment data from backend with file reference"); $data = self::$backend->GetAttachmentData($operation['filereference']); } catch (StatusException $stex) { $status = $stex->getCode(); } } else { try { if (isset($operation['folderid']) && isset($operation['serverid'])) { self::$topCollector->AnnounceInformation("Fetching data from backend with item and folder id"); $data = self::$backend->Fetch($operation['backendfolderid'], $operation['serverid'], $operation["cpo"]); } else { if (isset($operation['longid'])) { self::$topCollector->AnnounceInformation("Fetching data from backend with long id"); $tmp = explode(":", $operation['longid']); $data = self::$backend->Fetch(self::$deviceManager->GetBackendIdForFolderId($tmp[0]), $tmp[1], $operation["cpo"]); } } } catch (StatusException $stex) { // the only option to return is that we could not retrieve it $status = SYNC_ITEMOPERATIONSSTATUS_CONVERSIONFAILED; } } self::$encoder->startTag(SYNC_ITEMOPERATIONS_FETCH); self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); self::$encoder->content($status); self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_STATUS if (isset($operation['folderid']) && isset($operation['serverid'])) { self::$encoder->startTag(SYNC_FOLDERID); self::$encoder->content($operation['folderid']); self::$encoder->endTag(); // end SYNC_FOLDERID self::$encoder->startTag(SYNC_SERVERENTRYID); self::$encoder->content($operation['serverid']); self::$encoder->endTag(); // end SYNC_SERVERENTRYID self::$encoder->startTag(SYNC_FOLDERTYPE); self::$encoder->content("Email"); self::$encoder->endTag(); } if (isset($operation['longid'])) { self::$encoder->startTag(SYNC_SEARCH_LONGID); self::$encoder->content($operation['longid']); self::$encoder->endTag(); // end SYNC_FOLDERID self::$encoder->startTag(SYNC_FOLDERTYPE); self::$encoder->content("Email"); self::$encoder->endTag(); } if (isset($operation['filereference'])) { self::$encoder->startTag(SYNC_AIRSYNCBASE_FILEREFERENCE); self::$encoder->content($operation['filereference']); self::$encoder->endTag(); // end SYNC_AIRSYNCBASE_FILEREFERENCE } if (isset($data)) { self::$topCollector->AnnounceInformation("Streaming data"); self::$encoder->startTag(SYNC_ITEMOPERATIONS_PROPERTIES); $data->Encode(self::$encoder); self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_PROPERTIES } self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_FETCH } else { if ($operation['operation'] == SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS) { try { self::$topCollector->AnnounceInformation("Emptying folder"); // send request to backend self::$backend->EmptyFolder($operation['backendfolderid'], $operation['deletesubfolders']); } catch (StatusException $stex) { $status = $stex->getCode(); } self::$encoder->startTag(SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS); self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); self::$encoder->content($status); self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_STATUS if (isset($operation['folderid'])) { self::$encoder->startTag(SYNC_FOLDERID); self::$encoder->content($operation['folderid']); self::$encoder->endTag(); // end SYNC_FOLDERID } self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS } else { self::$topCollector->AnnounceInformation("not implemented", true); // reply with "can't do" self::$encoder->startTag(SYNC_ITEMOPERATIONS_MOVE); self::$encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); self::$encoder->content(SYNC_ITEMOPERATIONSSTATUS_SERVERERROR); self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_STATUS self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_MOVE } } } self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_RESPONSE self::$encoder->endTag(); //SYNC_ITEMOPERATIONS_ITEMOPERATIONS return true; }
/** * Handles the Settings command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { if (!self::$decoder->getElementStartTag(SYNC_SETTINGS_SETTINGS)) { return false; } // add capability header for KOE if (self::$deviceManager->IsKoe()) { // define the supported capabilites $cap = array(); if (defined('KOE_CAPABILITY_GAB') && KOE_CAPABILITY_GAB) { $cap[] = "gab"; } if (defined('KOE_CAPABILITY_RECEIVEFLAGS') && KOE_CAPABILITY_RECEIVEFLAGS) { $cap[] = "receiveflags"; } if (defined('KOE_CAPABILITY_SENDFLAGS') && KOE_CAPABILITY_SENDFLAGS) { $cap[] = "sendflags"; } if (defined('KOE_CAPABILITY_OOFTIMES') && KOE_CAPABILITY_OOFTIMES) { $cap[] = "ooftime"; } elseif (defined('KOE_CAPABILITY_OOF') && KOE_CAPABILITY_OOF) { $cap[] = "oof"; } // 'ooftime' superseeds 'oof'. If 'ooftime' is set, 'oof' should not be defined. if (defined('KOE_CAPABILITY_NOTES') && KOE_CAPABILITY_NOTES) { $cap[] = "notes"; } if (defined('KOE_CAPABILITY_SHAREDFOLDER') && KOE_CAPABILITY_SHAREDFOLDER) { $cap[] = "sharedfolder"; } if (defined('KOE_CAPABILITY_SENDAS') && KOE_CAPABILITY_SENDAS) { $cap[] = "sendas"; } self::$specialHeaders = array(); self::$specialHeaders[] = "X-Push-Capabilities: " . implode(",", $cap); self::$specialHeaders[] = "X-Push-GAB-Name: " . bin2hex(KOE_GAB_NAME); } //save the request parameters $request = array(); // Loop through properties. Possible are: // - Out of office // - DevicePassword // - DeviceInformation // - UserInformation // Each of them should only be once per request. Each property must be processed in order. WBXMLDecoder::ResetInWhile("settingsMain"); while (WBXMLDecoder::InWhile("settingsMain")) { $propertyName = ""; if (self::$decoder->getElementStartTag(SYNC_SETTINGS_OOF)) { $propertyName = SYNC_SETTINGS_OOF; } if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEPW)) { $propertyName = SYNC_SETTINGS_DEVICEPW; } if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEINFORMATION)) { $propertyName = SYNC_SETTINGS_DEVICEINFORMATION; } if (self::$decoder->getElementStartTag(SYNC_SETTINGS_USERINFORMATION)) { $propertyName = SYNC_SETTINGS_USERINFORMATION; } //TODO - check if it is necessary //no property name available - break if (!$propertyName) { break; } //the property name is followed by either get or set if (self::$decoder->getElementStartTag(SYNC_SETTINGS_GET)) { //get is only available for OOF and user information switch ($propertyName) { case SYNC_SETTINGS_OOF: $oofGet = new SyncOOF(); $oofGet->Decode(self::$decoder); if (!self::$decoder->getElementEndTag()) { return false; } // SYNC_SETTINGS_GET break; case SYNC_SETTINGS_USERINFORMATION: $userInformation = new SyncUserInformation(); break; default: //TODO: a special status code needed? ZLog::Write(LOGLEVEL_WARN, sprintf("This property ('%s') is not allowed to use get in request", $propertyName)); } } elseif (self::$decoder->getElementStartTag(SYNC_SETTINGS_SET)) { //set is available for OOF, device password and device information switch ($propertyName) { case SYNC_SETTINGS_OOF: $oofSet = new SyncOOF(); $oofSet->Decode(self::$decoder); //TODO check - do it after while(1) finished? break; case SYNC_SETTINGS_DEVICEPW: //TODO device password $devicepassword = new SyncDevicePassword(); $devicepassword->Decode(self::$decoder); break; case SYNC_SETTINGS_DEVICEINFORMATION: $deviceinformation = new SyncDeviceInformation(); $deviceinformation->Decode(self::$decoder); $deviceinformation->Status = SYNC_SETTINGSSTATUS_SUCCESS; self::$deviceManager->SaveDeviceInformation($deviceinformation); break; default: //TODO: a special status code needed? ZLog::Write(LOGLEVEL_WARN, sprintf("This property ('%s') is not allowed to use set in request", $propertyName)); } if (!self::$decoder->getElementEndTag()) { return false; } // SYNC_SETTINGS_SET } else { ZLog::Write(LOGLEVEL_WARN, sprintf("Neither get nor set found for property '%s'", $propertyName)); return false; } if (!self::$decoder->getElementEndTag()) { return false; } // SYNC_SETTINGS_OOF or SYNC_SETTINGS_DEVICEPW or SYNC_SETTINGS_DEVICEINFORMATION or SYNC_SETTINGS_USERINFORMATION //break if it reached the endtag $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); //SYNC_SETTINGS_SETTINGS break; } } $status = SYNC_SETTINGSSTATUS_SUCCESS; //TODO put it in try catch block //TODO implement Settings in the backend //TODO save device information in device manager //TODO status handling // $data = self::$backend->Settings($request); self::$encoder->startWBXML(); self::$encoder->startTag(SYNC_SETTINGS_SETTINGS); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS //get oof settings if (isset($oofGet)) { $oofGet = self::$backend->Settings($oofGet); self::$encoder->startTag(SYNC_SETTINGS_OOF); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($oofGet->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->startTag(SYNC_SETTINGS_GET); $oofGet->Encode(self::$encoder); self::$encoder->endTag(); //SYNC_SETTINGS_GET self::$encoder->endTag(); //SYNC_SETTINGS_OOF } //get user information //TODO none email address found if (isset($userInformation)) { self::$backend->Settings($userInformation); self::$encoder->startTag(SYNC_SETTINGS_USERINFORMATION); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($userInformation->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->startTag(SYNC_SETTINGS_GET); $userInformation->Encode(self::$encoder); self::$encoder->endTag(); //SYNC_SETTINGS_GET self::$encoder->endTag(); //SYNC_SETTINGS_USERINFORMATION } //set out of office if (isset($oofSet)) { $oofSet = self::$backend->Settings($oofSet); self::$encoder->startTag(SYNC_SETTINGS_OOF); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($oofSet->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->endTag(); //SYNC_SETTINGS_OOF } //set device passwort if (isset($devicepassword)) { self::$encoder->startTag(SYNC_SETTINGS_DEVICEPW); self::$encoder->startTag(SYNC_SETTINGS_SET); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($devicepassword->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->endTag(); //SYNC_SETTINGS_SET self::$encoder->endTag(); //SYNC_SETTINGS_DEVICEPW } //set device information if (isset($deviceinformation)) { self::$encoder->startTag(SYNC_SETTINGS_DEVICEINFORMATION); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($deviceinformation->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->endTag(); //SYNC_SETTINGS_DEVICEINFORMATION } self::$encoder->endTag(); //SYNC_SETTINGS_SETTINGS return true; }
/** * Handles the Ping command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { $interval = defined('PING_INTERVAL') && PING_INTERVAL > 0 ? PING_INTERVAL : 30; $pingstatus = false; $fakechanges = array(); $foundchanges = false; // Contains all requested folders (containers) $sc = new SyncCollections(); // read from stream to see if the symc params are being sent $params_present = self::$decoder->getElementStartTag(SYNC_PING_PING); // Load all collections - do load states, check permissions and allow unconfirmed states try { $sc->LoadAllCollections(true, true, true, true, false); } catch (StateInvalidException $siex) { // if no params are present, indicate to send params, else do hierarchy sync if (!$params_present) { $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; self::$topCollector->AnnounceInformation("StateInvalidException: require PingParameters", true); } else { // we do not have a ping status for this, but SyncCollections should have generated fake changes for the folders which are broken $fakechanges = $sc->GetChangedFolderIds(); $foundchanges = true; self::$topCollector->AnnounceInformation("StateInvalidException: force sync", true); } } catch (StatusException $stex) { $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; self::$topCollector->AnnounceInformation("StatusException: require HierarchySync", true); } ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): reference PolicyKey for PING: %s", $sc->GetReferencePolicyKey())); // receive PING initialization data if ($params_present) { self::$topCollector->AnnounceInformation("Processing PING data"); ZLog::Write(LOGLEVEL_DEBUG, "HandlePing(): initialization data received"); if (self::$decoder->getElementStartTag(SYNC_PING_LIFETIME)) { $sc->SetLifetime(self::$decoder->getElementContent()); self::$decoder->getElementEndTag(); } if (($el = self::$decoder->getElementStartTag(SYNC_PING_FOLDERS)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) { // cache requested (pingable) folderids $pingable = array(); while (self::$decoder->getElementStartTag(SYNC_PING_FOLDER)) { WBXMLDecoder::ResetInWhile("pingFolder"); while (WBXMLDecoder::InWhile("pingFolder")) { if (self::$decoder->getElementStartTag(SYNC_PING_SERVERENTRYID)) { $folderid = self::$decoder->getElementContent(); self::$decoder->getElementEndTag(); } if (self::$decoder->getElementStartTag(SYNC_PING_FOLDERTYPE)) { $class = self::$decoder->getElementContent(); self::$decoder->getElementEndTag(); } $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } $spa = $sc->GetCollection($folderid); if (!$spa) { // The requested collection is not synchronized. // check if the HierarchyCache is available, if not, trigger a HierarchySync try { self::$deviceManager->GetFolderClassFromCacheByID($folderid); } catch (NoHierarchyCacheAvailableException $nhca) { ZLog::Write(LOGLEVEL_INFO, sprintf("HandlePing(): unknown collection '%s', triggering HierarchySync", $folderid)); $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; } // Trigger a Sync request because then the device will be forced to resync this folder. $fakechanges[$folderid] = 1; $foundchanges = true; } else { if ($this->isClassValid($class, $spa)) { $pingable[] = $folderid; ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): using saved sync state for '%s' id '%s'", $spa->GetContentClass(), $folderid)); } } } if (!self::$decoder->getElementEndTag()) { return false; } // update pingable flags foreach ($sc as $folderid => $spa) { // if the folderid is in $pingable, we should ping it, else remove the flag if (in_array($folderid, $pingable)) { $spa->SetPingableFlag(true); } else { $spa->DelPingableFlag(); } } } if (!self::$decoder->getElementEndTag()) { return false; } if (!$this->lifetimeBetweenBound($sc->GetLifetime())) { $pingstatus = SYNC_PINGSTATUS_HBOUTOFRANGE; ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_HBOUTOFRANGE.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); } // save changed data foreach ($sc as $folderid => $spa) { $sc->SaveCollection($spa); } } else { // if no ping initialization data was sent, we check if we have pingable folders // if not, we indicate that there is nothing to do. if (!$sc->PingableFolders()) { $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; ZLog::Write(LOGLEVEL_DEBUG, "HandlePing(): no pingable folders found and no initialization data sent. Returning SYNC_PINGSTATUS_FAILINGPARAMS."); } elseif (!$this->lifetimeBetweenBound($sc->GetLifetime())) { $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandlePing(): ping lifetime not between bound (higher bound:'%d' lower bound:'%d' current lifetime:'%d'. Returning SYNC_PINGSTATUS_FAILINGPARAMS.", PING_HIGHER_BOUND_LIFETIME, PING_LOWER_BOUND_LIFETIME, $sc->GetLifetime())); } } // Check for changes on the default LifeTime, set interval and ONLY on pingable collections try { if (!$pingstatus && empty($fakechanges)) { self::$deviceManager->DoAutomaticASDeviceSaving(false); $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval, true); } } catch (StatusException $ste) { switch ($ste->getCode()) { case SyncCollections::ERROR_NO_COLLECTIONS: $pingstatus = SYNC_PINGSTATUS_FAILINGPARAMS; break; case SyncCollections::ERROR_WRONG_HIERARCHY: $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; self::$deviceManager->AnnounceProcessStatus(false, $pingstatus); break; case SyncCollections::OBSOLETE_CONNECTION: $foundchanges = false; break; case SyncCollections::HIERARCHY_CHANGED: $pingstatus = SYNC_PINGSTATUS_FOLDERHIERSYNCREQUIRED; break; } } self::$encoder->StartWBXML(); self::$encoder->startTag(SYNC_PING_PING); self::$encoder->startTag(SYNC_PING_STATUS); if (isset($pingstatus) && $pingstatus) { self::$encoder->content($pingstatus); } else { self::$encoder->content($foundchanges ? SYNC_PINGSTATUS_CHANGES : SYNC_PINGSTATUS_HBEXPIRED); } self::$encoder->endTag(); if (!$pingstatus) { self::$encoder->startTag(SYNC_PING_FOLDERS); if (empty($fakechanges)) { $changes = $sc->GetChangedFolderIds(); } else { $changes = $fakechanges; } foreach ($changes as $folderid => $changecount) { if ($changecount > 0) { self::$encoder->startTag(SYNC_PING_FOLDER); self::$encoder->content($folderid); self::$encoder->endTag(); if (empty($fakechanges)) { self::$topCollector->AnnounceInformation(sprintf("Found change in %s", $sc->GetCollection($folderid)->GetContentClass()), true); } } } self::$encoder->endTag(); } elseif ($pingstatus == SYNC_PINGSTATUS_HBOUTOFRANGE) { self::$encoder->startTag(SYNC_PING_LIFETIME); if ($sc->GetLifetime() > PING_HIGHER_BOUND_LIFETIME) { self::$encoder->content(PING_HIGHER_BOUND_LIFETIME); } else { self::$encoder->content(PING_LOWER_BOUND_LIFETIME); } self::$encoder->endTag(); } self::$encoder->endTag(); return true; }
function HandleResolveRecipients($backend, $devid, $protocolversion) { global $zpushdtd; global $input, $output; // define ('OVERRIDE_GZIP',true); $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS)) { return false; } $status = 1; while ($status == 1 && ($field = $decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_TO) ? SYNC_RESOLVERECIPIENTS_TO : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_OPTIONS) ? SYNC_RESOLVERECIPIENTS_OPTIONS : -1)) != -1) { if ($field == SYNC_RESOLVERECIPIENTS_OPTIONS) { while ($status == 1 && ($option = $decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL) ? SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_MAXCERTIFICATES) ? SYNC_RESOLVERECIPIENTS_MAXCERTIFICATES : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_MAXAMBIGUOUSRECIPIENTS) ? SYNC_RESOLVERECIPIENTS_MAXAMBIGUOUSRECIPIENTS : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_AVAILABILITY) ? SYNC_RESOLVERECIPIENTS_AVAILABILITY : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_PICTURE) ? SYNC_RESOLVERECIPIENTS_PICTURE : -1))))) != -1) { switch ($option) { case SYNC_RESOLVERECIPIENTS_AVAILABILITY: while (($suboption = $decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_STARTTIME) ? SYNC_RESOLVERECIPIENTS_STARTTIME : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_ENDTIME) ? SYNC_RESOLVERECIPIENTS_ENDTIME : -1)) != -1) { $ts = $decoder->getElementContent(); if (preg_match("/(\\d{4})[^0-9]*(\\d{2})[^0-9]*(\\d{2})T(\\d{2})[^0-9]*(\\d{2})[^0-9]*(\\d{2})(.\\d+)?Z/", $ts, $matches)) { if ($matches[1] >= 2038) { $matches[1] = 2038; $matches[2] = 1; $matches[3] = 18; $matches[4] = $matches[5] = $matches[6] = 0; } $ts = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); } else { $ts = 0; } $options[$option][$suboption] = $ts; if (!$decoder->getElementEndTag()) { $status = 5; } } if (!$decoder->getElementEndTag()) { $status = 5; } break; case SYNC_RESOLVERECIPIENTS_PICTURE: while (($suboption = $decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_MAXSIZE) ? SYNC_RESOLVERECIPIENTS_MAXSIZE : ($decoder->getElementStartTag(SYNC_RESOLVERECIPIENTS_MAXPICTURES) ? SYNC_RESOLVERECIPIENTS_MAXPICTURES : -1)) != -1) { $options[$option][$suboption] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { $status = 5; } } if (!$decoder->getElementEndTag()) { $status = 5; } break; default: $options[$option] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { $status = 5; } } } if (!$decoder->getElementEndTag()) { $status = 5; } } else { if ($field == SYNC_RESOLVERECIPIENTS_TO) { $to[] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { $status = 5; } } } } $results = ''; foreach ($to as $item) { if (isset($options[SYNC_RESOLVERECIPIENTS_AVAILABILITY])) { $result = $backend->resolveRecipient('availability', $item, array('starttime' => $options[SYNC_RESOLVERECIPIENTS_AVAILABILITY][SYNC_RESOLVERECIPIENTS_STARTTIME], 'endtime' => $options[SYNC_RESOLVERECIPIENTS_AVAILABILITY][SYNC_RESOLVERECIPIENTS_ENDTIME])); $results[$item] = $result[$item]; } if (isset($options[SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL])) { $result = $backend->resolveRecipient('certificate', $item, array('maxcerts' => $options[SYNC_RESOLVERECIPIENTS_MAXCERTIFICATES], 'maxambigious' => $options[SYNC_RESOLVERECIPIENTS_MAXAMBIGUOUSRECIPIENTS])); $results[$item] = $result[$item]; } } debugLog("Results returned" . print_r($results, true)); $encoder->startWBXML(); $encoder->startTag(SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS); $encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); $encoder->content($status); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_STATUS foreach ($to as $item) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_RESPONSE); $encoder->startTag(SYNC_RESOLVERECIPIENTS_TO); $encoder->content($item); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_TO $encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); $encoder->content(sizeof($results[$item]) > 1 ? 2 : (sizeof($results[$item]) == 0 ? 4 : (sizeof($results[$item]) == 1 ? 1 : 3))); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_STATUS $encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT); $encoder->content(sizeof($results[$item])); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT foreach ($results[$item] as $value) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENT); $encoder->startTag(SYNC_RESOLVERECIPIENTS_TYPE); $encoder->content($value['type']); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_TYPE $encoder->startTag(SYNC_RESOLVERECIPIENTS_DISPLAYNAME); $encoder->content($value['displayname']); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_DISPLAYNAME $encoder->startTag(SYNC_RESOLVERECIPIENTS_EMAILADDRESS); $encoder->content($value['emailaddress']); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_EMAILADDRESS if (isset($options[SYNC_RESOLVERECIPIENTS_AVAILABILITY])) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_AVAILABILITY); $encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); $encoder->content(1); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_STATUS $encoder->startTag(SYNC_RESOLVERECIPIENTS_MERGEDFREEBUSY); $encoder->content($value['mergedfb']); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_MERGEDFREEBUSY $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_AVAILABILITY } if (isset($options[SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL]) && $options[SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL] > 1) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_CERTIFICATES); $encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); $encoder->content(sizeof($value['entries']) == 0 ? 7 : 1); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_STATUS $encoder->startTag(SYNC_RESOLVERECIPIENTS_CERTIFICATECOUNT); $encoder->content(sizeof($value['entries'])); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_CERTIFICATECOUNT $encoder->startTag(SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT); $encoder->content(sizeof($results[$item])); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_RECIPIENTCOUNT switch ($options[SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL]) { case '2': foreach ($value['entries'] as $cert) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_CERTIFICATE); $encoder->content($cert); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_CERTIFICATE } break; case '3': foreach ($value['entries'] as $cert) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_MINICERTIFICATE); $encoder->content($cert); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_MINICERTIFICATE } break; } $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_CERTIFICATERETRIEVAL } /* if (isset($item['options'][SYNC_RESOLVERECIPIENTS_PICTURE])) { $encoder->startTag(SYNC_RESOLVERECIPIENTS_PICTURE); $encoder->startTag(SYNC_RESOLVERECIPIENTS_STATUS); $encoder->content(); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_STATUS $encoder->startTag(SYNC_RESOLVERECIPIENTS_DATA); $encoder->content(); $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_DATA $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_PICTURE } */ $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_RECIPIENT } $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_RESPONSE } $encoder->endTag(); // end SYNC_RESOLVERECIPIENTS_RESOLVERECIPIENTS return true; }
/** * Handles the Provisioning command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { $status = SYNC_PROVISION_STATUS_SUCCESS; $policystatus = SYNC_PROVISION_POLICYSTATUS_SUCCESS; $rwstatus = self::$deviceManager->GetProvisioningWipeStatus(); $rwstatusWiped = false; $deviceInfoSet = false; // if this is a regular provisioning require that an authenticated remote user if ($rwstatus < SYNC_PROVISION_RWSTATUS_PENDING) { ZLog::Write(LOGLEVEL_DEBUG, "RequestProcessor::HandleProvision(): Forcing delayed Authentication"); self::Authenticate(); } $phase2 = true; if (!self::$decoder->getElementStartTag(SYNC_PROVISION_PROVISION)) { return false; } // Loop through Provision request tags. Possible are: // - Remote Wipe // - DeviceInformation // - Policies // Each of them should only be once per request. WBXMLDecoder::ResetInWhile("provisioningMain"); while (WBXMLDecoder::InWhile("provisioningMain")) { $requestName = ""; if (self::$decoder->getElementStartTag(SYNC_PROVISION_REMOTEWIPE)) { $requestName = SYNC_PROVISION_REMOTEWIPE; } if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICIES)) { $requestName = SYNC_PROVISION_POLICIES; } if (self::$decoder->getElementStartTag(SYNC_SETTINGS_DEVICEINFORMATION)) { $requestName = SYNC_SETTINGS_DEVICEINFORMATION; } if (!$requestName) { break; } //set is available for OOF, device password and device information switch ($requestName) { case SYNC_PROVISION_REMOTEWIPE: if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { return false; } $instatus = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } if (!self::$decoder->getElementEndTag()) { return false; } $phase2 = false; $rwstatusWiped = true; //TODO check - do it after while(1) finished? break; case SYNC_PROVISION_POLICIES: if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICY)) { return false; } if (!self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYTYPE)) { return false; } $policytype = self::$decoder->getElementContent(); if ($policytype != 'MS-WAP-Provisioning-XML' && $policytype != 'MS-EAS-Provisioning-WBXML') { $status = SYNC_PROVISION_STATUS_SERVERERROR; } if (!self::$decoder->getElementEndTag()) { //policytype return false; } if (self::$decoder->getElementStartTag(SYNC_PROVISION_POLICYKEY)) { $devpolicykey = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } if (!self::$decoder->getElementStartTag(SYNC_PROVISION_STATUS)) { return false; } $instatus = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } $phase2 = false; } if (!self::$decoder->getElementEndTag()) { //policy return false; } if (!self::$decoder->getElementEndTag()) { //policies return false; } break; case SYNC_SETTINGS_DEVICEINFORMATION: // AS14.1 and later clients pass Device Information on the initial Provision request if (!self::$decoder->getElementStartTag(SYNC_SETTINGS_SET)) { return false; } $deviceInfoSet = true; $deviceinformation = new SyncDeviceInformation(); $deviceinformation->Decode(self::$decoder); $deviceinformation->Status = SYNC_SETTINGSSTATUS_SUCCESS; self::$deviceManager->SaveDeviceInformation($deviceinformation); if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_SET return false; } if (!self::$decoder->getElementEndTag()) { // SYNC_SETTINGS_DEVICEINFORMATION return false; } break; default: //TODO: a special status code needed? ZLog::Write(LOGLEVEL_WARN, sprintf("This property ('%s') is not allowed to be used in a provision request", $requestName)); } } if (!self::$decoder->getElementEndTag()) { //provision return false; } if (PROVISIONING !== true) { ZLog::Write(LOGLEVEL_INFO, "No policies deployed to device"); $policystatus = SYNC_PROVISION_POLICYSTATUS_NOPOLICY; } self::$encoder->StartWBXML(); //set the new final policy key in the device manager // START ADDED dw2412 Android provisioning fix if (!$phase2) { $policykey = self::$deviceManager->GenerateProvisioningPolicyKey(); self::$deviceManager->SetProvisioningPolicyKey($policykey); self::$topCollector->AnnounceInformation("Policies deployed", true); } else { // just create a temporary key (i.e. iPhone OS4 Beta does not like policykey 0 in response) $policykey = self::$deviceManager->GenerateProvisioningPolicyKey(); } // END ADDED dw2412 Android provisioning fix self::$encoder->startTag(SYNC_PROVISION_PROVISION); self::$encoder->startTag(SYNC_PROVISION_STATUS); self::$encoder->content($status); self::$encoder->endTag(); if ($deviceInfoSet) { self::$encoder->startTag(SYNC_SETTINGS_DEVICEINFORMATION); self::$encoder->startTag(SYNC_SETTINGS_STATUS); self::$encoder->content($deviceinformation->Status); self::$encoder->endTag(); //SYNC_SETTINGS_STATUS self::$encoder->endTag(); //SYNC_SETTINGS_DEVICEINFORMATION } self::$encoder->startTag(SYNC_PROVISION_POLICIES); self::$encoder->startTag(SYNC_PROVISION_POLICY); if (isset($policytype)) { self::$encoder->startTag(SYNC_PROVISION_POLICYTYPE); self::$encoder->content($policytype); self::$encoder->endTag(); } self::$encoder->startTag(SYNC_PROVISION_STATUS); self::$encoder->content($policystatus); self::$encoder->endTag(); self::$encoder->startTag(SYNC_PROVISION_POLICYKEY); self::$encoder->content($policykey); self::$encoder->endTag(); if ($phase2 && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { self::$encoder->startTag(SYNC_PROVISION_DATA); if ($policytype == 'MS-WAP-Provisioning-XML') { self::$encoder->content('<wap-provisioningdoc><characteristic type="SecurityPolicy"><parm name="4131" value="1"/><parm name="4133" value="1"/></characteristic></wap-provisioningdoc>'); } elseif ($policytype == 'MS-EAS-Provisioning-WBXML') { self::$encoder->startTag(SYNC_PROVISION_EASPROVISIONDOC); // get the provisioning object and log the loaded policy values $prov = self::$deviceManager->GetProvisioningObject(true); if (!$prov->Check()) { throw new FatalException("Invalid policies!"); } self::$deviceManager->SavePolicyHashAndName($prov); $prov->Encode(self::$encoder); self::$encoder->endTag(); } else { ZLog::Write(LOGLEVEL_WARN, "Wrong policy type"); self::$topCollector->AnnounceInformation("Policytype not supported", true); return false; } self::$topCollector->AnnounceInformation("Updated provisiong", true); self::$encoder->endTag(); //data } self::$encoder->endTag(); //policy self::$encoder->endTag(); //policies //wipe data if a higher RWSTATUS is requested if ($rwstatus > SYNC_PROVISION_RWSTATUS_OK && $policystatus === SYNC_PROVISION_POLICYSTATUS_SUCCESS) { self::$encoder->startTag(SYNC_PROVISION_REMOTEWIPE, false, true); self::$deviceManager->SetProvisioningWipeStatus($rwstatusWiped ? SYNC_PROVISION_RWSTATUS_WIPED : SYNC_PROVISION_RWSTATUS_REQUESTED); self::$topCollector->AnnounceInformation(sprintf("Remote wipe %s", $rwstatusWiped ? "executed" : "requested"), true); } self::$encoder->endTag(); //provision return true; }
include_once '../../src/lib/wbxml/wbxmldecoder.php'; include_once '../../src/lib/wbxml/wbxmlencoder.php'; // minimal definitions & log to stdout overwrite define('WBXML_DEBUG', true); define("LOGLEVEL_WBXML", "wbxml"); define("LOGLEVEL_DEBUG", "debug"); class ZLog { public static function Write($level, $msg, $truncate = false) { // we only care about the wbxml if ($level == "wbxml") { if (substr($msg, 0, 1) == "I") { echo substr($msg, 1) . "\n"; } else { echo $msg . "\n"; } } } } // setup $wxbml = StringStreamWrapper::Open($wbxml64); $base64filter = stream_filter_append($wxbml, 'convert.base64-decode'); $decoder = new WBXMLDecoder($wxbml); if (!$decoder->IsWBXML()) { die("input is not WBXML as base64\n\n"); } echo "\n"; // read everything and log it $decoder->readRemainingData(); echo "\n";
/** * Handles the GetItemEstimate command * Returns an estimation of how many items will be synchronized at the next sync * This is mostly used to show something in the progress bar * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { $sc = new SyncCollections(); if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE)) { return false; } if (!self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERS)) { return false; } while (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDER)) { $spa = new SyncParameters(); $spastatus = false; // read the folder properties WBXMLDecoder::ResetInWhile("getItemEstimateFolders"); while (WBXMLDecoder::InWhile("getItemEstimateFolders")) { if (self::$decoder->getElementStartTag(SYNC_SYNCKEY)) { try { $spa->SetSyncKey(self::$decoder->getElementContent()); } catch (StateInvalidException $siex) { $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED; } if (!self::$decoder->getElementEndTag()) { return false; } } elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) { $fid = self::$decoder->getElementContent(); $spa->SetFolderId($fid); $spa->SetBackendFolderId(self::$deviceManager->GetBackendIdForFolderId($fid)); if (!self::$decoder->getElementEndTag()) { return false; } } elseif (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) { $spa->SetConversationMode(true); if (($conversationmode = self::$decoder->getElementContent()) !== false) { $spa->SetConversationMode((bool) $conversationmode); if (!self::$decoder->getElementEndTag()) { return false; } } } elseif (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERTYPE)) { $spa->SetContentClass(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } elseif (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { $spa->SetFilterType(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } while (self::$decoder->getElementStartTag(SYNC_OPTIONS)) { WBXMLDecoder::ResetInWhile("getItemEstimateOptions"); while (WBXMLDecoder::InWhile("getItemEstimateOptions")) { $firstOption = true; // foldertype definition if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) { $foldertype = self::$decoder->getElementContent(); ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleGetItemEstimate(): specified options block with foldertype '%s'", $foldertype)); // switch the foldertype for the next options $spa->UseCPO($foldertype); // set to synchronize all changes. The mobile could overwrite this value $spa->SetFilterType(SYNC_FILTERTYPE_ALL); if (!self::$decoder->getElementEndTag()) { return false; } } else { if ($firstOption) { $spa->UseCPO(); // set to synchronize all changes. The mobile could overwrite this value $spa->SetFilterType(SYNC_FILTERTYPE_ALL); } } $firstOption = false; if (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) { $spa->SetFilterType(self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_MAXITEMS)) { $spa->SetWindowSize($maxitems = self::$decoder->getElementContent()); if (!self::$decoder->getElementEndTag()) { return false; } } $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } } $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); //SYNC_GETITEMESTIMATE_FOLDER break; } } // Process folder data //In AS 14 request only collectionid is sent, without class if (!$spa->HasContentClass() && $spa->HasFolderId()) { try { $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId())); } catch (NoHierarchyCacheAvailableException $nhca) { $spastatus = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; } } // compatibility mode AS 1.0 - get folderid which was sent during GetHierarchy() if (!$spa->HasFolderId() && $spa->HasContentClass()) { $spa->SetFolderId(self::$deviceManager->GetFolderIdFromCacheByClass($spa->GetContentClass())); } // Add collection to SC and load state $sc->AddCollection($spa); if ($spastatus) { // the CPO has a folder id now, so we can set the status $sc->AddParameter($spa, "status", $spastatus); } else { try { $sc->AddParameter($spa, "state", self::$deviceManager->GetStateManager()->GetSyncState($spa->GetSyncKey())); // if this is an additional folder the backend has to be setup correctly if (!self::$backend->Setup(ZPush::GetAdditionalSyncFolderStore($spa->GetBackendFolderId()))) { throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id %s/%s", $spa->GetFolderId(), $spa->GetBackendFolderId()), SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); } } catch (StateNotFoundException $snfex) { // ok, the key is invalid. Question is, if the hierarchycache is still ok //if not, we have to issue SYNC_GETITEMESTSTATUS_COLLECTIONINVALID which triggers a FolderSync try { self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()); // we got here, so the HierarchyCache is ok $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCKKEYINVALID); } catch (NoHierarchyCacheAvailableException $nhca) { $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); } self::$topCollector->AnnounceInformation("StateNotFoundException " . $sc->GetParameter($spa, "status"), true); } catch (StatusException $stex) { if ($stex->getCode() == SYNC_GETITEMESTSTATUS_COLLECTIONINVALID) { $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_COLLECTIONINVALID); } else { $sc->AddParameter($spa, "status", SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED); } self::$topCollector->AnnounceInformation("StatusException " . $sc->GetParameter($spa, "status"), true); } } } if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_GETITEMESTIMATE_FOLDERS if (!self::$decoder->getElementEndTag()) { return false; } //SYNC_GETITEMESTIMATE_GETITEMESTIMATE self::$encoder->startWBXML(); self::$encoder->startTag(SYNC_GETITEMESTIMATE_GETITEMESTIMATE); $status = SYNC_GETITEMESTSTATUS_SUCCESS; // look for changes in all collections try { $sc->CountChanges(); } catch (StatusException $ste) { $status = SYNC_GETITEMESTSTATUS_COLLECTIONINVALID; } $changes = $sc->GetChangedFolderIds(); foreach ($sc as $folderid => $spa) { self::$encoder->startTag(SYNC_GETITEMESTIMATE_RESPONSE); if ($sc->GetParameter($spa, "status")) { $status = $sc->GetParameter($spa, "status"); } self::$encoder->startTag(SYNC_GETITEMESTIMATE_STATUS); self::$encoder->content($status); self::$encoder->endTag(); self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDER); self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERTYPE); self::$encoder->content($spa->GetContentClass()); self::$encoder->endTag(); self::$encoder->startTag(SYNC_GETITEMESTIMATE_FOLDERID); self::$encoder->content($spa->GetFolderId()); self::$encoder->endTag(); if (isset($changes[$folderid]) && $changes[$folderid] !== false) { self::$encoder->startTag(SYNC_GETITEMESTIMATE_ESTIMATE); self::$encoder->content($changes[$folderid]); self::$encoder->endTag(); if ($changes[$folderid] > 0) { self::$topCollector->AnnounceInformation(sprintf("%s %d changes", $spa->GetContentClass(), $changes[$folderid]), true); } // update the device data to mark folders as complete when synching with WM if ($changes[$folderid] == 0) { self::$deviceManager->SetFolderSyncStatus($folderid, DeviceManager::FLD_SYNC_COMPLETED); } } self::$encoder->endTag(); self::$encoder->endTag(); } if (array_sum($changes) == 0) { self::$topCollector->AnnounceInformation("No changes found", true); } self::$encoder->endTag(); return true; }
function HandleSearch($backend, $devid, $protocolversion) { global $zpushdtd; global $input, $output; $searchrange = '0'; $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { return false; } $searchname = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { return false; } $searchquery = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } if ($decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { while (1) { if ($decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { $searchrange = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } $e = $decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { $decoder->getElementEndTag(); break; } } //if(!$decoder->getElementEndTag()) //return false; } if (!$decoder->getElementEndTag()) { //store return false; } if (!$decoder->getElementEndTag()) { //search return false; } if (strtoupper($searchname) != "GAL") { debugLog("Searchtype {$searchname} is not supported"); return false; } //get search results from backend if (defined('SEARCH_PROVIDER') && @constant('SEARCH_PROVIDER') != "" && class_exists(SEARCH_PROVIDER)) { $searchClass = constant('SEARCH_PROVIDER'); $searchbackend = new $searchClass(); $searchbackend->initialize($backend); $rows = $searchbackend->getSearchResults($searchquery, $searchrange); $searchbackend->disconnect(); } else { $rows = $backend->getSearchResults($searchquery, $searchrange); } $encoder->startWBXML(); $encoder->startTag(SYNC_SEARCH_SEARCH); $encoder->startTag(SYNC_SEARCH_STATUS); $encoder->content(1); $encoder->endTag(); $encoder->startTag(SYNC_SEARCH_RESPONSE); $encoder->startTag(SYNC_SEARCH_STORE); $encoder->startTag(SYNC_SEARCH_STATUS); $encoder->content(1); $encoder->endTag(); if (is_array($rows) && !empty($rows)) { $searchrange = $rows['range']; unset($rows['range']); $searchtotal = $rows['searchtotal']; unset($rows['searchtotal']); foreach ($rows as $u) { $encoder->startTag(SYNC_SEARCH_RESULT); $encoder->startTag(SYNC_SEARCH_PROPERTIES); $encoder->startTag(SYNC_GAL_DISPLAYNAME); $encoder->content(isset($u[SYNC_GAL_DISPLAYNAME]) ? $u[SYNC_GAL_DISPLAYNAME] : "No name"); $encoder->endTag(); if (isset($u[SYNC_GAL_PHONE])) { $encoder->startTag(SYNC_GAL_PHONE); $encoder->content($u[SYNC_GAL_PHONE]); $encoder->endTag(); } if (isset($u[SYNC_GAL_OFFICE])) { $encoder->startTag(SYNC_GAL_OFFICE); $encoder->content($u[SYNC_GAL_OFFICE]); $encoder->endTag(); } if (isset($u[SYNC_GAL_TITLE])) { $encoder->startTag(SYNC_GAL_TITLE); $encoder->content($u[SYNC_GAL_TITLE]); $encoder->endTag(); } if (isset($u[SYNC_GAL_COMPANY])) { $encoder->startTag(SYNC_GAL_COMPANY); $encoder->content($u[SYNC_GAL_COMPANY]); $encoder->endTag(); } if (isset($u[SYNC_GAL_ALIAS])) { $encoder->startTag(SYNC_GAL_ALIAS); $encoder->content($u[SYNC_GAL_ALIAS]); $encoder->endTag(); } // Always send the firstname, even empty. Nokia needs this to display the entry $encoder->startTag(SYNC_GAL_FIRSTNAME); $encoder->content(isset($u[SYNC_GAL_FIRSTNAME]) ? $u[SYNC_GAL_FIRSTNAME] : ""); $encoder->endTag(); $encoder->startTag(SYNC_GAL_LASTNAME); $encoder->content(isset($u[SYNC_GAL_LASTNAME]) ? $u[SYNC_GAL_LASTNAME] : "No name"); $encoder->endTag(); if (isset($u[SYNC_GAL_HOMEPHONE])) { $encoder->startTag(SYNC_GAL_HOMEPHONE); $encoder->content($u[SYNC_GAL_HOMEPHONE]); $encoder->endTag(); } if (isset($u[SYNC_GAL_MOBILEPHONE])) { $encoder->startTag(SYNC_GAL_MOBILEPHONE); $encoder->content($u[SYNC_GAL_MOBILEPHONE]); $encoder->endTag(); } $encoder->startTag(SYNC_GAL_EMAILADDRESS); $encoder->content(isset($u[SYNC_GAL_EMAILADDRESS]) ? $u[SYNC_GAL_EMAILADDRESS] : ""); $encoder->endTag(); $encoder->endTag(); //result $encoder->endTag(); //properties } if ($searchtotal > 0) { $encoder->startTag(SYNC_SEARCH_RANGE); $encoder->content($searchrange); $encoder->endTag(); $encoder->startTag(SYNC_SEARCH_TOTAL); $encoder->content($searchtotal); $encoder->endTag(); } } $encoder->endTag(); //store $encoder->endTag(); //response $encoder->endTag(); //search return true; }
function HandleItemOperations($backend, $devid, $protocolversion, $multipart) { global $zpushdtd; global $input, $output; global $auth_user, $auth_domain, $auth_pw; $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS)) { return false; } $request = array(); while (($reqtype = $decoder->getElementStartTag(SYNC_ITEMOPERATIONS_FETCH) ? SYNC_ITEMOPERATIONS_FETCH : ($decoder->getElementStartTag(SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENT) ? SYNC_ITEMOPERATIONS_EMPTYFOLDERCONTENTS : -1)) != -1) { if ($reqtype == SYNC_ITEMOPERATIONS_FETCH) { $thisio["type"] = "fetch"; while (($reqtag = $decoder->getElementStartTag(SYNC_ITEMOPERATIONS_STORE) ? SYNC_ITEMOPERATIONS_STORE : ($decoder->getElementStartTag(SYNC_ITEMOPERATIONS_OPTIONS) ? SYNC_ITEMOPERATIONS_OPTIONS : ($decoder->getElementStartTag(SYNC_SERVERENTRYID) ? SYNC_SERVERENTRYID : ($decoder->getElementStartTag(SYNC_FOLDERID) ? SYNC_FOLDERID : ($decoder->getElementStartTag(SYNC_DOCUMENTLIBRARY_LINKID) ? SYNC_DOCUMENTLIBRARY_LINKID : ($decoder->getElementStartTag(SYNC_AIRSYNCBASE_FILEREFERENCE) ? SYNC_AIRSYNCBASE_FILEREFERENCE : ($decoder->getElementStartTag(SYNC_ITEMOPERATIONS_USERNAME) ? SYNC_ITEMOPERATIONS_USERNAME : ($decoder->getElementStartTag(SYNC_ITEMOPERATIONS_PASSWORD) ? SYNC_ITEMOPERATIONS_PASSWORD : ($decoder->getElementStartTag(SYNC_SEARCH_LONGID) ? SYNC_SEARCH_LONGID : -1))))))))) != -1) { if ($reqtag == SYNC_ITEMOPERATIONS_OPTIONS) { if ($decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) { $bodypreference = array(); while (1) { if ($decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) { $bodypreference["Type"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) { $bodypreference["TruncationSize"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) { $bodypreference["AllOrNone"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } $e = $decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { $decoder->getElementEndTag(); if (!isset($thisio["bodypreference"]["wanted"])) { $thisio["bodypreference"]["wanted"] = $bodypreference["Type"]; } if (isset($bodypreference["Type"])) { $thisio["bodypreference"][$bodypreference["Type"]] = $bodypreference; } break; } } } } elseif ($reqtag == SYNC_ITEMOPERATIONS_STORE) { $thisio["store"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_ITEMOPERATIONS_USERNAME) { $thisio["username"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_ITEMOPERATIONS_PASSWORD) { $thisio["password"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_SEARCH_LONGID) { $thisio["searchlongid"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_AIRSYNCBASE_FILEREFERENCE) { $thisio["airsyncbasefilereference"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_SERVERENTRYID) { $thisio["serverentryid"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_FOLDERID) { $thisio["folderid"] = $decoder->getElementContent(); } elseif ($reqtag == SYNC_DOCUMENTLIBRARY_LINKID) { $thisio["documentlibrarylinkid"] = $decoder->getElementContent(); } $e = $decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { $decoder->getElementEndTag(); } } $itemoperations[] = $thisio; $decoder->getElementEndTag(); // end SYNC_ITEMOPERATIONS_FETCH } } $decoder->getElementEndTag(); // end SYNC_ITEMOPERATIONS_ITEMOPERATIONS if ($multipart == true) { $encoder->startWBXML(true); } else { $encoder->startWBXML(false); } $encoder->startTag(SYNC_ITEMOPERATIONS_ITEMOPERATIONS); $encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); $encoder->content(1); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_STATUS $encoder->startTag(SYNC_ITEMOPERATIONS_RESPONSE); foreach ($itemoperations as $value) { switch ($value["type"]) { case "fetch": switch (strtolower($value["store"])) { case "mailbox": $encoder->startTag(SYNC_ITEMOPERATIONS_FETCH); $encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); $encoder->content(1); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_STATUS if (isset($value["airsyncbasefilereference"])) { $encoder->startTag(SYNC_AIRSYNCBASE_FILEREFERENCE); $encoder->content($value["airsyncbasefilereference"]); $encoder->endTag(); // end SYNC_SERVERENTRYID } else { if (isset($value["folderid"])) { $encoder->startTag(SYNC_FOLDERID); $encoder->content($value["folderid"]); $encoder->endTag(); // end SYNC_FOLDERID } if (isset($value["serverentryid"])) { $encoder->startTag(SYNC_SERVERENTRYID); $encoder->content($value["serverentryid"]); $encoder->endTag(); // end SYNC_SERVERENTRYID } if (isset($value["searchlongid"])) { $ids = $backend->ItemOperationsGetIDs($value['searchlongid']); $encoder->startTag(SYNC_FOLDERID); $encoder->content($ids["folderid"]); $encoder->endTag(); // end SYNC_FOLDERID $encoder->startTag(SYNC_SERVERENTRYID); $encoder->content($ids["serverentryid"]); $encoder->endTag(); // end SYNC_SERVERENTRYID } $encoder->startTag(SYNC_FOLDERTYPE); $encoder->content("Email"); $encoder->endTag(); } $encoder->startTag(SYNC_ITEMOPERATIONS_PROPERTIES); if (isset($value['bodypreference'])) { $encoder->_bodypreference = $value['bodypreference']; } if (isset($value["searchlongid"])) { $msg = $backend->ItemOperationsFetchMailbox($value['searchlongid'], $value['bodypreference']); } else { if (isset($value["airsyncbasefilereference"])) { $msg = $backend->ItemOperationsGetAttachmentData($value["airsyncbasefilereference"]); } else { $msg = $backend->Fetch($value['folderid'], $value['serverentryid'], $value['bodypreference']); } } $msg->encode($encoder); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_PROPERTIES $encoder->endTag(); // end SYNC_ITEMOPERATIONS_FETCH break; case "documentlibrary": if (isset($value['username'])) { if (strpos($value['username'], "\\")) { list($cred['username']['domain'], $cred['username']['username']) = explode("\\", $value['username']); } else { $cred['username'] = array('domain' => "", 'username' => $value['username']); } } else { $cred['username']['domain'] = $auth_domain; $cred['username']['username'] = $auth_user; } $cred['password'] = isset($value['password']) ? $value['password'] : $auth_pw; $result = $backend->ItemOperationsGetDocumentLibraryLink($value["documentlibrarylinkid"], $cred); $encoder->startTag(SYNC_ITEMOPERATIONS_FETCH); $encoder->startTag(SYNC_ITEMOPERATIONS_STATUS); $encoder->content($result['status']); // $encoder->content(1); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_STATUS $encoder->startTag(SYNC_DOCUMENTLIBRARY_LINKID); $encoder->content($value["documentlibrarylinkid"]); $encoder->endTag(); // end SYNC_DOCUMENTLIBRARY_LINKID if ($result['status'] == 1) { $encoder->startTag(SYNC_ITEMOPERATIONS_PROPERTIES); if ($multipart == true) { $encoder->_bodyparts[] = $result['data']; $encoder->startTag(SYNC_ITEMOPERATIONS_PART); $encoder->content("" . sizeof($encoder->_bodyparts) . ""); $encoder->endTag(); } else { $encoder->startTag(SYNC_ITEMOPERATIONS_DATA); $encoder->content($result['data']); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_DATA } $encoder->startTag(SYNC_ITEMOPERATIONS_VERSION); $encoder->content(gmstrftime("%Y-%m-%dT%H:%M:%S.000Z", $result['version'])); $encoder->endTag(); // end SYNC_ITEMOPERATIONS_VERSION $encoder->endTag(); // end SYNC_ITEMOPERATIONS_PROPERTIES } else { $encoder->_bodyparts = array(); } $encoder->endTag(); // end SYNC_ITEMOPERATIONS_FETCH break; default: debugLog("Store " . $value["type"] . " not supported by HandleItemOperations"); break; } break; default: debugLog("Operations " . $value["type"] . " not supported by HandleItemOperations"); break; } } $encoder->endTag(); //end SYNC_ITEMOPERATIONS_RESPONSE $encoder->endTag(); //end SYNC_ITEMOPERATIONS_ITEMOPERATIONS return true; }
/** * Handles the FolderSync command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { // Parse input if (!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC)) { return false; } if (!self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_SYNCKEY)) { return false; } $synckey = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } // every FolderSync with SyncKey 0 should return the supported AS version & command headers if ($synckey == "0") { self::$specialHeaders = array(); self::$specialHeaders[] = ZPush::GetSupportedProtocolVersions(); self::$specialHeaders[] = ZPush::GetSupportedCommands(); } $status = SYNC_FSSTATUS_SUCCESS; $newsynckey = $synckey; try { $syncstate = self::$deviceManager->GetStateManager()->GetSyncState($synckey); // We will be saving the sync state under 'newsynckey' $newsynckey = self::$deviceManager->GetStateManager()->GetNewSyncKey($synckey); // there are no SyncParameters for the hierarchy, but we use it to save the latest synckeys $spa = self::$deviceManager->GetStateManager()->GetSynchedFolderState(false); } catch (StateNotFoundException $snfex) { $status = SYNC_FSSTATUS_SYNCKEYERROR; } catch (StateInvalidException $sive) { $status = SYNC_FSSTATUS_SYNCKEYERROR; } // The ChangesWrapper caches all imports in-memory, so we can send a change count // before sending the actual data. // the HierarchyCache is notified and the changes from the PIM are transmitted to the actual backend $changesMem = self::$deviceManager->GetHierarchyChangesWrapper(); // the hierarchyCache should now fully be initialized - check for changes in the additional folders $changesMem->Config(ZPush::GetAdditionalSyncFolders(false)); // reset to default store in backend self::$backend->Setup(false); // process incoming changes if (self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_CHANGES)) { // Ignore <Count> if present if (self::$decoder->getElementStartTag(SYNC_FOLDERHIERARCHY_COUNT)) { self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } } // Process the changes (either <Add>, <Modify>, or <Remove>) $element = self::$decoder->getElement(); if ($element[EN_TYPE] != EN_TYPE_STARTTAG) { return false; } $importer = false; WBXMLDecoder::ResetInWhile("folderSyncIncomingChange"); while (WBXMLDecoder::InWhile("folderSyncIncomingChange")) { $folder = new SyncFolder(); if (!$folder->Decode(self::$decoder)) { break; } // add the backendId to the SyncFolder object $folder->BackendId = self::$deviceManager->GetBackendIdForFolderId($folder->serverid); try { if ($status == SYNC_FSSTATUS_SUCCESS && !$importer) { // Configure the backends importer with last state $importer = self::$backend->GetImporter(); $importer->Config($syncstate); // the messages from the PIM will be forwarded to the backend $changesMem->forwardImporter($importer); } if ($status == SYNC_FSSTATUS_SUCCESS) { switch ($element[EN_TAG]) { case SYNC_ADD: case SYNC_MODIFY: $serverid = $changesMem->ImportFolderChange($folder); break; case SYNC_REMOVE: $serverid = $changesMem->ImportFolderDeletion($folder); break; } } else { ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): ignoring incoming folderchange for folder '%s' as status indicates problem.", $folder->displayname)); self::$topCollector->AnnounceInformation("Incoming change ignored", true); } } catch (StatusException $stex) { $status = $stex->getCode(); } } if (!self::$decoder->getElementEndTag()) { return false; } } else { // check for a potential process loop like described in Issue ZP-5 if ($synckey != "0" && self::$deviceManager->IsHierarchyFullResyncRequired()) { $status = SYNC_FSSTATUS_SYNCKEYERROR; } self::$deviceManager->AnnounceProcessStatus(false, $status); } if (!self::$decoder->getElementEndTag()) { return false; } // We have processed incoming foldersync requests, now send the PIM // our changes // Output our WBXML reply now self::$encoder->StartWBXML(); self::$encoder->startTag(SYNC_FOLDERHIERARCHY_FOLDERSYNC); if ($status == SYNC_FSSTATUS_SUCCESS) { try { // do nothing if this is an invalid device id (like the 'validate' Androids internal client sends) if (!Request::IsValidDeviceID()) { throw new StatusException(sprintf("Request::IsValidDeviceID() indicated that '%s' is not a valid device id", Request::GetDeviceID()), SYNC_FSSTATUS_SERVERERROR); } // Changes from backend are sent to the MemImporter and processed for the HierarchyCache. // The state which is saved is from the backend, as the MemImporter is only a proxy. $exporter = self::$backend->GetExporter(); $exporter->Config($syncstate); $exporter->InitializeExporter($changesMem); // Stream all changes to the ImportExportChangesMem $totalChanges = $exporter->GetChangeCount(); $exported = 0; $partial = false; while (is_array($exporter->Synchronize())) { $exported++; if (time() % 4) { self::$topCollector->AnnounceInformation(sprintf("Exported %d from %d folders", $exported, $totalChanges)); } // if partial sync is allowed, stop if this takes too long if (USE_PARTIAL_FOLDERSYNC && Request::IsRequestTimeoutReached()) { ZLog::Write(LOGLEVEL_WARN, sprintf("Request->HandleFolderSync(): Exporting folders is too slow. In %d seconds only %d from %d changes were processed.", time() - $_SERVER["REQUEST_TIME"], $exported, $totalChanges)); self::$topCollector->AnnounceInformation(sprintf("Partial export of %d out of %d folders", $exported, $totalChanges), true); self::$deviceManager->SetFolderSyncComplete(false); $partial = true; break; } } // update the foldersync complete flag if (USE_PARTIAL_FOLDERSYNC && $partial == false && self::$deviceManager->GetFolderSyncComplete() === false) { // say that we are done with partial synching self::$deviceManager->SetFolderSyncComplete(true); // reset the loop data to prevent any loop detection to kick in now self::$deviceManager->ClearLoopDetectionData(Request::GetAuthUser(), Request::GetDeviceID()); ZLog::Write(LOGLEVEL_INFO, "Request->HandleFolderSync(): Chunked exporting of folders completed successfully"); } // get the new state from the backend $newsyncstate = isset($exporter) ? $exporter->GetState() : ""; } catch (StatusException $stex) { if ($stex->getCode() == SYNC_FSSTATUS_CODEUNKNOWN) { $status = SYNC_FSSTATUS_SYNCKEYERROR; } else { $status = $stex->getCode(); } } } self::$encoder->startTag(SYNC_FOLDERHIERARCHY_STATUS); self::$encoder->content($status); self::$encoder->endTag(); if ($status == SYNC_FSSTATUS_SUCCESS) { self::$encoder->startTag(SYNC_FOLDERHIERARCHY_SYNCKEY); $synckey = $changesMem->IsStateChanged() ? $newsynckey : $synckey; self::$encoder->content($synckey); self::$encoder->endTag(); // Stream folders directly to the PDA $streamimporter = new ImportChangesStream(self::$encoder, false); $changesMem->InitializeExporter($streamimporter); $changeCount = $changesMem->GetChangeCount(); self::$encoder->startTag(SYNC_FOLDERHIERARCHY_CHANGES); self::$encoder->startTag(SYNC_FOLDERHIERARCHY_COUNT); self::$encoder->content($changeCount); self::$encoder->endTag(); while ($changesMem->Synchronize()) { } self::$encoder->endTag(); self::$topCollector->AnnounceInformation(sprintf("Outgoing %d folders", $changeCount), true); // everything fine, save the sync state for the next time if ($synckey == $newsynckey) { self::$deviceManager->GetStateManager()->SetSyncState($newsynckey, $newsyncstate); // update SPA & save it $spa->SetSyncKey($newsynckey); $spa->SetFolderId(false); self::$deviceManager->GetStateManager()->SetSynchedFolderState($spa); // invalidate all pingable flags SyncCollections::InvalidatePingableFlags(); } } self::$encoder->endTag(); return true; }
/** * Handles the MeetingResponse command * * @param int $commandCode * * @access public * @return boolean */ public function Handle($commandCode) { $requests = array(); if (!self::$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE)) { return false; } while (self::$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUEST)) { $req = array(); WBXMLDecoder::ResetInWhile("meetingResponseRequest"); while (WBXMLDecoder::InWhile("meetingResponseRequest")) { if (self::$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_USERRESPONSE)) { $req["response"] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_FOLDERID)) { $req["folderid"] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } } if (self::$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUESTID)) { $req["requestid"] = self::$decoder->getElementContent(); if (!self::$decoder->getElementEndTag()) { return false; } } $e = self::$decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { self::$decoder->getElementEndTag(); break; } } array_push($requests, $req); } if (!self::$decoder->getElementEndTag()) { return false; } // output the error code, plus the ID of the calendar item that was generated by the // accept of the meeting response self::$encoder->StartWBXML(); self::$encoder->startTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE); foreach ($requests as $req) { $status = SYNC_MEETRESPSTATUS_SUCCESS; try { $backendFolderId = self::$deviceManager->GetBackendIdForFolderId($req["folderid"]); // if the source folder is an additional folder the backend has to be setup correctly if (!self::$backend->Setup(ZPush::GetAdditionalSyncFolderStore($backendFolderId))) { throw new StatusException(sprintf("HandleMoveItems() could not Setup() the backend for folder id %s/%s", $req["folderid"], $backendFolderId), SYNC_MEETRESPSTATUS_SERVERERROR); } $calendarid = self::$backend->MeetingResponse($req["requestid"], $backendFolderId, $req["response"]); if ($calendarid === false) { throw new StatusException("HandleMeetingResponse() not possible", SYNC_MEETRESPSTATUS_SERVERERROR); } } catch (StatusException $stex) { $status = $stex->getCode(); } self::$encoder->startTag(SYNC_MEETINGRESPONSE_RESULT); self::$encoder->startTag(SYNC_MEETINGRESPONSE_REQUESTID); self::$encoder->content($req["requestid"]); self::$encoder->endTag(); self::$encoder->startTag(SYNC_MEETINGRESPONSE_STATUS); self::$encoder->content($status); self::$encoder->endTag(); if ($status == SYNC_MEETRESPSTATUS_SUCCESS && !empty($calendarid)) { self::$encoder->startTag(SYNC_MEETINGRESPONSE_CALENDARID); self::$encoder->content($calendarid); self::$encoder->endTag(); } self::$encoder->endTag(); self::$topCollector->AnnounceInformation(sprintf("Operation status %d", $status), true); } self::$encoder->endTag(); return true; }
function HandleMeetingResponse($backend, $protocolversion) { global $zpushdtd; global $output, $input; $response = false; $folderid = false; $requestid = false; $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE)) { return false; } if (!$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUEST)) { return false; } if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_USERRESPONSE)) { $response = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_FOLDERID)) { $folderid = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUESTID)) { $requestid = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if (!$decoder->getElementEndTag()) { return false; } if (!$decoder->getElementEndTag()) { return false; } $calendarid = ""; $ok = $backend->MeetingResponse($requestid, $folderid, $response, $calendarid); // Start output, simply the error code $encoder->StartWBXML(); $encoder->startTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE); $encoder->startTag(SYNC_MEETINGRESPONSE_RESULT); $encoder->startTag(SYNC_MEETINGRESPONSE_REQUESTID); $encoder->content($requestid); $encoder->endTag(); $encoder->startTag(SYNC_MEETINGRESPONSE_ERROR); $encoder->content($ok ? 1 : 2); $encoder->endTag(); if ($ok) { $encoder->startTag(SYNC_MEETINGRESPONSE_CALENDARID); $encoder->content($calendarid); $encoder->endTag(); } $encoder->endTag(); $encoder->endTag(); return true; }
function HandleMeetingResponse($backend, $protocolversion) { global $zpushdtd; global $output, $input; $requests = array(); $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE)) { return false; } while ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUEST)) { $req = array(); if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_USERRESPONSE)) { $req["response"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_FOLDERID)) { $req["folderid"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if ($decoder->getElementStartTag(SYNC_MEETINGRESPONSE_REQUESTID)) { $req["requestid"] = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } if (!$decoder->getElementEndTag()) { return false; } array_push($requests, $req); } if (!$decoder->getElementEndTag()) { return false; } // Start output, simply the error code, plus the ID of the calendar item that was generated by the // accept of the meeting response $encoder->StartWBXML(); $encoder->startTag(SYNC_MEETINGRESPONSE_MEETINGRESPONSE); foreach ($requests as $req) { $calendarid = ""; $ok = $backend->MeetingResponse($req["requestid"], $req["folderid"], $req["response"], $calendarid); $encoder->startTag(SYNC_MEETINGRESPONSE_RESULT); $encoder->startTag(SYNC_MEETINGRESPONSE_REQUESTID); $encoder->content($req["requestid"]); $encoder->endTag(); $encoder->startTag(SYNC_MEETINGRESPONSE_ERROR); $encoder->content($ok ? 1 : 2); $encoder->endTag(); if ($ok) { $encoder->startTag(SYNC_MEETINGRESPONSE_CALENDARID); $encoder->content($calendarid); $encoder->endTag(); } $encoder->endTag(); } $encoder->endTag(); return true; }
function HandleSearch($backend, $devid, $protocolversion) { global $zpushdtd; global $input, $output; $searchrange = '0'; $decoder = new WBXMLDecoder($input, $zpushdtd); $encoder = new WBXMLEncoder($output, $zpushdtd); if (!$decoder->getElementStartTag(SYNC_SEARCH_SEARCH)) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_STORE)) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_NAME)) { return false; } $searchname = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } if (!$decoder->getElementStartTag(SYNC_SEARCH_QUERY)) { return false; } $searchquery = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } if ($decoder->getElementStartTag(SYNC_SEARCH_OPTIONS)) { while (1) { if ($decoder->getElementStartTag(SYNC_SEARCH_RANGE)) { $searchrange = $decoder->getElementContent(); if (!$decoder->getElementEndTag()) { return false; } } $e = $decoder->peek(); if ($e[EN_TYPE] == EN_TYPE_ENDTAG) { $decoder->getElementEndTag(); break; } } //if(!$decoder->getElementEndTag()) //return false; } if (!$decoder->getElementEndTag()) { //store return false; } if (!$decoder->getElementEndTag()) { //search return false; } if (strtoupper($searchname) != "GAL") { debugLog("Searchtype {$searchname} is not supported"); return false; } //get search results from backend $rows = $backend->getSearchResults($searchquery, $searchrange); $encoder->startWBXML(); $encoder->startTag(SYNC_SEARCH_SEARCH); $encoder->startTag(SYNC_SEARCH_STATUS); $encoder->content(1); $encoder->endTag(); $encoder->startTag(SYNC_SEARCH_RESPONSE); $encoder->startTag(SYNC_SEARCH_STORE); $encoder->startTag(SYNC_SEARCH_STATUS); $encoder->content(1); $encoder->endTag(); if (is_array($rows) && !empty($rows)) { $searchrange = $rows['range']; unset($rows['range']); foreach ($rows as $u) { $encoder->startTag(SYNC_SEARCH_RESULT); $encoder->startTag(SYNC_SEARCH_PROPERTIES); $encoder->startTag(SYNC_GAL_DISPLAYNAME); $encoder->content($u["fullname"]); $encoder->endTag(); $encoder->startTag(SYNC_GAL_PHONE); $encoder->content($u["businessphone"]); $encoder->endTag(); $encoder->startTag(SYNC_GAL_ALIAS); $encoder->content($u["username"]); $encoder->endTag(); //it's not possible not get first and last name of an user //from the gab and user functions, so we just set fullname //to lastname and leave firstname empty because nokia needs //first and lastname in order to display the search result $encoder->startTag(SYNC_GAL_FIRSTNAME); $encoder->content(""); $encoder->endTag(); $encoder->startTag(SYNC_GAL_LASTNAME); $encoder->content($u["fullname"]); $encoder->endTag(); $encoder->startTag(SYNC_GAL_EMAILADDRESS); $encoder->content($u["emailaddress"]); $encoder->endTag(); $encoder->endTag(); //result $encoder->endTag(); //properties } $encoder->startTag(SYNC_SEARCH_RANGE); $encoder->content($searchrange); $encoder->endTag(); $encoder->startTag(SYNC_SEARCH_TOTAL); $encoder->content(count($rows)); $encoder->endTag(); } $encoder->endTag(); //store $encoder->endTag(); //response $encoder->endTag(); //search return true; }
/** * Returns either a start tag, content or end tag * * @access private * @return */ private function _getToken() { // Get the data from the input stream $element = array(); WBXMLDecoder::ResetInWhile("decoderGetToken"); while (WBXMLDecoder::InWhile("decoderGetToken")) { $byte = fread($this->in, 1); if ($byte === "" || $byte === false) { break; } $byte = ord($byte); switch ($byte) { case self::WBXML_SWITCH_PAGE: $this->tagcp = $this->getByte(); break; case self::WBXML_END: $element[EN_TYPE] = EN_TYPE_ENDTAG; return $element; case self::WBXML_STR_I: $element[EN_TYPE] = EN_TYPE_CONTENT; $element[EN_CONTENT] = $this->getTermStr(); return $element; case self::WBXML_OPAQUE: $length = $this->getMBUInt(); $element[EN_TYPE] = EN_TYPE_CONTENT; $element[EN_CONTENT] = $this->getOpaque($length); return $element; case self::WBXML_ENTITY: case self::WBXML_LITERAL: case self::WBXML_EXT_I_0: case self::WBXML_EXT_I_1: case self::WBXML_EXT_I_2: case self::WBXML_PI: case self::WBXML_LITERAL_C: case self::WBXML_EXT_T_0: case self::WBXML_EXT_T_1: case self::WBXML_EXT_T_2: case self::WBXML_STR_T: case self::WBXML_LITERAL_A: case self::WBXML_EXT_0: case self::WBXML_EXT_1: case self::WBXML_EXT_2: case self::WBXML_LITERAL_AC: throw new WBXMLException("Invalid token :" . $byte); default: if ($byte & self::WBXML_WITH_ATTRIBUTES) { throw new WBXMLException("Attributes are not allowed :" . $byte); } $element[EN_TYPE] = EN_TYPE_STARTTAG; $element[EN_TAG] = $this->getMapping($this->tagcp, $byte & 0x3f); $element[EN_FLAGS] = $byte & self::WBXML_WITH_CONTENT ? EN_FLAGS_CONTENT : 0; return $element; } } }