예제 #1
0
 /**
  * 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;
             }
         }
     }
 }
예제 #2
0
 /**
  * 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;
 }
예제 #3
0
파일: sync.php 프로젝트: EGroupware/z-push
 /**
  * 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;
 }
예제 #4
0
 /**
  * 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;
 }
예제 #5
0
 /**
  * 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;
 }
예제 #6
0
파일: ping.php 프로젝트: EGroupware/z-push
 /**
  * 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;
 }
예제 #7
0
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;
}
예제 #8
0
 /**
  * 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;
 }
예제 #9
0
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";
예제 #10
0
 /**
  * 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;
 }
예제 #11
0
파일: request.php 프로젝트: nnaannoo/paskot
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;
}
예제 #12
0
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;
}
예제 #13
0
 /**
  * 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;
 }
예제 #14
0
 /**
  * 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;
 }
예제 #15
0
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;
}
예제 #16
0
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;
}
예제 #17
0
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;
}
예제 #18
0
 /**
  * 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;
         }
     }
 }