Example #1
0
 function __construct()
 {
     $mapping = array(SYNC_POOMMAIL_ALLDAYEVENT => array(self::STREAMER_VAR => "alldayevent", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ZEROORONE => self::STREAMER_CHECK_SETZERO)), SYNC_POOMMAIL_STARTTIME => array(self::STREAMER_VAR => "starttime", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_CMPLOWER => SYNC_POOMMAIL_ENDTIME)), SYNC_POOMMAIL_DTSTAMP => array(self::STREAMER_VAR => "dtstamp", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO)), SYNC_POOMMAIL_ENDTIME => array(self::STREAMER_VAR => "endtime", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETONE, self::STREAMER_CHECK_CMPHIGHER => SYNC_POOMMAIL_STARTTIME)), SYNC_POOMMAIL_INSTANCETYPE => array(self::STREAMER_VAR => "instancetype", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3))), SYNC_POOMMAIL_LOCATION => array(self::STREAMER_VAR => "location"), SYNC_POOMMAIL_ORGANIZER => array(self::STREAMER_VAR => "organizer", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY)), SYNC_POOMMAIL_RECURRENCEID => array(self::STREAMER_VAR => "recurrenceid", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMMAIL_REMINDER => array(self::STREAMER_VAR => "reminder", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1)), SYNC_POOMMAIL_RESPONSEREQUESTED => array(self::STREAMER_VAR => "responserequested"), SYNC_POOMMAIL_RECURRENCES => array(self::STREAMER_VAR => "recurrences", self::STREAMER_TYPE => "SyncMeetingRequestRecurrence", self::STREAMER_ARRAY => SYNC_POOMMAIL_RECURRENCE), SYNC_POOMMAIL_SENSITIVITY => array(self::STREAMER_VAR => "sensitivity", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3))), SYNC_POOMMAIL_BUSYSTATUS => array(self::STREAMER_VAR => "busystatus", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETTWO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3, 4))), SYNC_POOMMAIL_TIMEZONE => array(self::STREAMER_VAR => "timezone", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => base64_encode(pack("la64vvvvvvvv" . "la64vvvvvvvv" . "l", 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0)))), SYNC_POOMMAIL_GLOBALOBJID => array(self::STREAMER_VAR => "globalobjid"));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_POOMMAIL_DISALLOWNEWTIMEPROPOSAL] = array(self::STREAMER_VAR => "disallownewtimeproposal", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1)));
     }
     parent::__construct($mapping);
 }
Example #2
0
 function __construct()
 {
     $mapping = array(SYNC_AIRSYNCBASE_TYPE => array(self::STREAMER_VAR => "type"), SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array(self::STREAMER_VAR => "estimatedDataSize"), SYNC_AIRSYNCBASE_TRUNCATED => array(self::STREAMER_VAR => "truncated"), SYNC_AIRSYNCBASE_DATA => array(self::STREAMER_VAR => "data", self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM_ASPLAIN, self::STREAMER_RONOTIFY => true));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_AIRSYNCBASE_PREVIEW] = array(self::STREAMER_VAR => "preview");
     }
     parent::__construct($mapping);
 }
Example #3
0
 function __construct()
 {
     $mapping = array(SYNC_POOMTASKS_START => array(self::STREAMER_VAR => "start", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_TYPE => array(self::STREAMER_VAR => "type", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3, 5, 6)), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_UNTIL => array(self::STREAMER_VAR => "until", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_OCCURRENCES => array(self::STREAMER_VAR => "occurrences", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 1000), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_INTERVAL => array(self::STREAMER_VAR => "interval", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 1000), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_DEADOCCUR => array(self::STREAMER_VAR => "deadoccur", self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_REGENERATE => array(self::STREAMER_VAR => "regenerate", self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_DAYOFWEEK => array(self::STREAMER_VAR => "dayofweek", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 128), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_DAYOFMONTH => array(self::STREAMER_VAR => "dayofmonth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 32), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_WEEKOFMONTH => array(self::STREAMER_VAR => "weekofmonth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(1, 2, 3, 4, 5)), self::STREAMER_RONOTIFY => true), SYNC_POOMTASKS_MONTHOFYEAR => array(self::STREAMER_VAR => "monthofyear", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)), self::STREAMER_RONOTIFY => true));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_POOMTASKS_CALENDARTYPE] = array(self::STREAMER_VAR => "calendartype", self::STREAMER_RONOTIFY => true);
     }
     parent::__construct($mapping);
 }
 function __construct()
 {
     $mapping = array(SYNC_POOMMAIL_TYPE => array(self::STREAMER_VAR => "type", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3, 5, 6))), SYNC_POOMMAIL_UNTIL => array(self::STREAMER_VAR => "until", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE), SYNC_POOMMAIL_OCCURRENCES => array(self::STREAMER_VAR => "occurrences", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 1000)), SYNC_POOMMAIL_INTERVAL => array(self::STREAMER_VAR => "interval", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 1000)), SYNC_POOMMAIL_DAYOFWEEK => array(self::STREAMER_VAR => "dayofweek", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 128)), SYNC_POOMMAIL_DAYOFMONTH => array(self::STREAMER_VAR => "dayofmonth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 32)), SYNC_POOMMAIL_WEEKOFMONTH => array(self::STREAMER_VAR => "weekofmonth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(1, 2, 3, 4, 5))), SYNC_POOMMAIL_MONTHOFYEAR => array(self::STREAMER_VAR => "monthofyear", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_POOMMAIL2_CALENDARTYPE] = array(self::STREAMER_VAR => "calendartype");
     }
     parent::__construct($mapping);
 }
 function SyncBaseBody()
 {
     $mapping = array(SYNC_AIRSYNCBASE_TYPE => array(self::STREAMER_VAR => "type"), SYNC_AIRSYNCBASE_ESTIMATEDDATASIZE => array(self::STREAMER_VAR => "estimatedDataSize"), SYNC_AIRSYNCBASE_TRUNCATED => array(self::STREAMER_VAR => "truncated"), SYNC_AIRSYNCBASE_DATA => array(self::STREAMER_VAR => "data"));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_AIRSYNCBASE_PREVIEW] = array(self::STREAMER_VAR => "preview");
     }
     parent::SyncObject($mapping);
 }
 function SyncAttendee()
 {
     $mapping = array(SYNC_POOMCAL_EMAIL => array(self::STREAMER_VAR => "email", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY)), SYNC_POOMCAL_NAME => array(self::STREAMER_VAR => "name", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY)));
     if (Request::GetProtocolVersion() >= 12.0) {
         $mapping[SYNC_POOMCAL_ATTENDEESTATUS] = array(self::STREAMER_VAR => "attendeestatus");
         $mapping[SYNC_POOMCAL_ATTENDEETYPE] = array(self::STREAMER_VAR => "attendeetype");
     }
     parent::SyncObject($mapping);
 }
Example #7
0
 function __construct()
 {
     $mapping = array(SYNC_POOMCAL_EMAIL => array(self::STREAMER_VAR => "email", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY), self::STREAMER_RONOTIFY => true), SYNC_POOMCAL_NAME => array(self::STREAMER_VAR => "name", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY), self::STREAMER_RONOTIFY => true));
     if (Request::GetProtocolVersion() >= 12.0) {
         $mapping[SYNC_POOMCAL_ATTENDEESTATUS] = array(self::STREAMER_VAR => "attendeestatus", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCAL_ATTENDEETYPE] = array(self::STREAMER_VAR => "attendeetype", self::STREAMER_RONOTIFY => true);
     }
     parent::__construct($mapping);
 }
 function SyncTask()
 {
     $mapping = array(SYNC_POOMTASKS_BODY => array(self::STREAMER_VAR => "body"), SYNC_POOMTASKS_COMPLETE => array(self::STREAMER_VAR => "complete", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ZEROORONE => self::STREAMER_CHECK_SETZERO)), SYNC_POOMTASKS_DATECOMPLETED => array(self::STREAMER_VAR => "datecompleted", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_DUEDATE => array(self::STREAMER_VAR => "duedate", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_UTCDUEDATE => array(self::STREAMER_VAR => "utcduedate", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_IMPORTANCE => array(self::STREAMER_VAR => "importance", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETONE, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2))), SYNC_POOMTASKS_RECURRENCE => array(self::STREAMER_VAR => "recurrence", self::STREAMER_TYPE => "SyncTaskRecurrence"), SYNC_POOMTASKS_REGENERATE => array(self::STREAMER_VAR => "regenerate"), SYNC_POOMTASKS_DEADOCCUR => array(self::STREAMER_VAR => "deadoccur"), SYNC_POOMTASKS_REMINDERSET => array(self::STREAMER_VAR => "reminderset", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_ZEROORONE => self::STREAMER_CHECK_SETZERO)), SYNC_POOMTASKS_REMINDERTIME => array(self::STREAMER_VAR => "remindertime", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_SENSITIVITY => array(self::STREAMER_VAR => "sensitivity", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3))), SYNC_POOMTASKS_STARTDATE => array(self::STREAMER_VAR => "startdate", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_UTCSTARTDATE => array(self::STREAMER_VAR => "utcstartdate", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES), SYNC_POOMTASKS_SUBJECT => array(self::STREAMER_VAR => "subject"), SYNC_POOMTASKS_RTF => array(self::STREAMER_VAR => "rtf"), SYNC_POOMTASKS_CATEGORIES => array(self::STREAMER_VAR => "categories", self::STREAMER_ARRAY => SYNC_POOMTASKS_CATEGORY));
     if (Request::GetProtocolVersion() >= 12.0) {
         $mapping[SYNC_AIRSYNCBASE_BODY] = array(self::STREAMER_VAR => "asbody", self::STREAMER_TYPE => "SyncBaseBody");
         //unset these properties because airsyncbase body and attachments will be used instead
         unset($mapping[SYNC_POOMTASKS_BODY]);
     }
     parent::SyncObject($mapping);
 }
 public function SyncUserInformation()
 {
     $mapping = array(SYNC_SETTINGS_ACCOUNTID => array(self::STREAMER_VAR => "accountid"), SYNC_SETTINGS_ACCOUNTNAME => array(self::STREAMER_VAR => "accountname"), SYNC_SETTINGS_EMAILADDRESSES => array(self::STREAMER_VAR => "emailaddresses", self::STREAMER_ARRAY => SYNC_SETTINGS_SMPTADDRESS), SYNC_SETTINGS_PROP_STATUS => array(self::STREAMER_VAR => "Status", self::STREAMER_TYPE => self::STREAMER_TYPE_IGNORE));
     if (Request::GetProtocolVersion() >= 12.1) {
         $mapping[SYNC_SETTINGS_USERDISPLAYNAME] = array(self::STREAMER_VAR => "userdisplayname");
     }
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_SETTINGS_SENDDISABLED] = array(self::STREAMER_VAR => "senddisabled");
     }
     parent::SyncObject($mapping);
 }
 public function __construct()
 {
     $mapping = array();
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_RESOLVERECIPIENTS_STARTTIME] = array(self::STREAMER_VAR => "starttime");
         $mapping[SYNC_RESOLVERECIPIENTS_ENDTIME] = array(self::STREAMER_VAR => "endtime");
         $mapping[SYNC_RESOLVERECIPIENTS_STATUS] = array(self::STREAMER_VAR => "status");
         $mapping[SYNC_RESOLVERECIPIENTS_MERGEDFREEBUSY] = array(self::STREAMER_VAR => "mergedfreebusy");
     }
     parent::__construct($mapping);
 }
 public function __construct()
 {
     $mapping = array();
     if (Request::GetProtocolVersion() >= 14.1) {
         $mapping[SYNC_RESOLVERECIPIENTS_MAXSIZE] = array(self::STREAMER_VAR => "maxsize");
         $mapping[SYNC_RESOLVERECIPIENTS_MAXPICTURES] = array(self::STREAMER_VAR => "maxpictures");
         $mapping[SYNC_RESOLVERECIPIENTS_STATUS] = array(self::STREAMER_VAR => "status");
         $mapping[SYNC_RESOLVERECIPIENTS_DATA] = array(self::STREAMER_VAR => "data", self::STREAMER_TYPE => self::STREAMER_TYPE_STREAM_ASBASE64);
     }
     parent::__construct($mapping);
 }
 public function __construct()
 {
     $mapping = array(SYNC_RESOLVERECIPIENTS_TYPE => array(self::STREAMER_VAR => "type"), SYNC_RESOLVERECIPIENTS_DISPLAYNAME => array(self::STREAMER_VAR => "displayname"), SYNC_RESOLVERECIPIENTS_EMAILADDRESS => array(self::STREAMER_VAR => "emailaddress"), SYNC_RESOLVERECIPIENTS_CERTIFICATES => array(self::STREAMER_VAR => "certificates", self::STREAMER_TYPE => "SyncResolveRecipientsCertificates"));
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_RESOLVERECIPIENTS_AVAILABILITY] = array(self::STREAMER_VAR => "availability", self::STREAMER_TYPE => "SyncResolveRecipientsAvailability");
     }
     if (Request::GetProtocolVersion() >= 14.1) {
         $mapping[SYNC_RESOLVERECIPIENTS_PICTURE] = array(self::STREAMER_VAR => "picture", self::STREAMER_TYPE => "SyncResolveRecipientsPicture");
     }
     parent::__construct($mapping);
 }
 public function SyncDeviceInformation()
 {
     $mapping = array(SYNC_SETTINGS_MODEL => array(self::STREAMER_VAR => "model"), SYNC_SETTINGS_IMEI => array(self::STREAMER_VAR => "imei"), SYNC_SETTINGS_FRIENDLYNAME => array(self::STREAMER_VAR => "friendlyname"), SYNC_SETTINGS_OS => array(self::STREAMER_VAR => "os"), SYNC_SETTINGS_OSLANGUAGE => array(self::STREAMER_VAR => "oslanguage"), SYNC_SETTINGS_PHONENUMBER => array(self::STREAMER_VAR => "phonenumber"), SYNC_SETTINGS_PROP_STATUS => array(self::STREAMER_VAR => "Status", self::STREAMER_TYPE => self::STREAMER_TYPE_IGNORE));
     if (Request::GetProtocolVersion() >= 12.1) {
         $mapping[SYNC_SETTINGS_USERAGENT] = array(self::STREAMER_VAR => "useragent");
     }
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_SETTINGS_MOBILEOPERATOR] = array(self::STREAMER_VAR => "mobileoperator");
         $mapping[SYNC_SETTINGS_ENABLEOUTBOUNDSMS] = array(self::STREAMER_VAR => "enableoutboundsms");
     }
     parent::SyncObject($mapping);
 }
Example #14
0
 /**
  * Handles the Sync command
  * Performs the synchronization of messages
  *
  * @param int       $commandCode
  *
  * @access public
  * @return boolean
  */
 public function Handle($commandCode)
 {
     // Contains all requested folders (containers)
     $sc = new SyncCollections();
     $status = SYNC_STATUS_SUCCESS;
     $wbxmlproblem = false;
     $emptysync = false;
     // check if the hierarchySync was fully completed
     if (USE_PARTIAL_FOLDERSYNC) {
         if (self::$deviceManager->GetFolderSyncComplete() === false) {
             ZLog::Write(LOGLEVEL_INFO, "Request->HandleSync(): Sync request aborted, as exporting of folders has not yet completed");
             self::$topCollector->AnnounceInformation("Aborted due incomplete folder sync", true);
             $status = SYNC_STATUS_FOLDERHIERARCHYCHANGED;
         } else {
             ZLog::Write(LOGLEVEL_INFO, "Request->HandleSync(): FolderSync marked as complete");
         }
     }
     // Start Synchronize
     if (self::$decoder->getElementStartTag(SYNC_SYNCHRONIZE)) {
         // AS 1.0 sends version information in WBXML
         if (self::$decoder->getElementStartTag(SYNC_VERSION)) {
             $sync_version = self::$decoder->getElementContent();
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("WBXML sync version: '%s'", $sync_version));
             if (!self::$decoder->getElementEndTag()) {
                 return false;
             }
         }
         // Synching specified folders
         // Android still sends heartbeat sync even if all syncfolders are disabled.
         // Check if Folders tag is empty (<Folders/>) and only sync if there are
         // some folders in the request. See ZP-172
         $startTag = self::$decoder->getElementStartTag(SYNC_FOLDERS);
         if (isset($startTag[EN_FLAGS]) && $startTag[EN_FLAGS]) {
             while (self::$decoder->getElementStartTag(SYNC_FOLDER)) {
                 $actiondata = array();
                 $actiondata["requested"] = true;
                 $actiondata["clientids"] = array();
                 $actiondata["modifyids"] = array();
                 $actiondata["removeids"] = array();
                 $actiondata["fetchids"] = array();
                 $actiondata["statusids"] = array();
                 // read class, synckey and folderid without SyncParameters Object for now
                 $class = $synckey = $folderid = false;
                 //for AS versions < 2.5
                 if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) {
                     $class = self::$decoder->getElementContent();
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("Sync folder: '%s'", $class));
                     if (!self::$decoder->getElementEndTag()) {
                         return false;
                     }
                 }
                 // SyncKey
                 if (self::$decoder->getElementStartTag(SYNC_SYNCKEY)) {
                     $synckey = "0";
                     if (($synckey = self::$decoder->getElementContent()) !== false) {
                         if (!self::$decoder->getElementEndTag()) {
                             return false;
                         }
                     }
                 } else {
                     return false;
                 }
                 // FolderId
                 if (self::$decoder->getElementStartTag(SYNC_FOLDERID)) {
                     $folderid = self::$decoder->getElementContent();
                     if (!self::$decoder->getElementEndTag()) {
                         return false;
                     }
                 }
                 // compatibility mode AS 1.0 - get folderid which was sent during GetHierarchy()
                 if (!$folderid && $class) {
                     $folderid = self::$deviceManager->GetFolderIdFromCacheByClass($class);
                 }
                 // folderid HAS TO BE known by now, so we retrieve the correct SyncParameters object for an update
                 try {
                     $spa = self::$deviceManager->GetStateManager()->GetSynchedFolderState($folderid);
                     // TODO remove resync of folders for < Z-Push 2 beta4 users
                     // this forces a resync of all states previous to Z-Push 2 beta4
                     if (!$spa instanceof SyncParameters) {
                         throw new StateInvalidException("Saved state are not of type SyncParameters");
                     }
                     // new/resync requested
                     if ($synckey == "0") {
                         $spa->RemoveSyncKey();
                     } else {
                         if ($synckey !== false) {
                             $spa->SetSyncKey($synckey);
                         }
                     }
                 } catch (StateInvalidException $stie) {
                     $spa = new SyncParameters();
                     $status = SYNC_STATUS_INVALIDSYNCKEY;
                     self::$topCollector->AnnounceInformation("State invalid - Resync folder", true);
                     self::$deviceManager->ForceFolderResync($folderid);
                 }
                 // update folderid.. this might be a new object
                 $spa->SetFolderId($folderid);
                 if ($class !== false) {
                     $spa->SetContentClass($class);
                 }
                 // Get class for as versions >= 12.0
                 if (!$spa->HasContentClass()) {
                     try {
                         $spa->SetContentClass(self::$deviceManager->GetFolderClassFromCacheByID($spa->GetFolderId()));
                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("GetFolderClassFromCacheByID from Device Manager: '%s' for id:'%s'", $spa->GetContentClass(), $spa->GetFolderId()));
                     } catch (NoHierarchyCacheAvailableException $nhca) {
                         $status = SYNC_STATUS_FOLDERHIERARCHYCHANGED;
                         self::$deviceManager->ForceFullResync();
                     }
                 }
                 // done basic SPA initialization/loading -> add to SyncCollection
                 $sc->AddCollection($spa);
                 $sc->AddParameter($spa, "requested", true);
                 if ($spa->HasContentClass()) {
                     self::$topCollector->AnnounceInformation(sprintf("%s request", $spa->GetContentClass()), true);
                 } else {
                     ZLog::Write(LOGLEVEL_WARN, "Not possible to determine class of request. Request did not contain class and apparently there is an issue with the HierarchyCache.");
                 }
                 // SUPPORTED properties
                 if (($se = self::$decoder->getElementStartTag(SYNC_SUPPORTED)) !== false) {
                     // ZP-481: LG phones send an empty supported tag, so only read the contents if available here
                     // if <Supported/> is received, it's as no supported fields would have been sent at all.
                     // unsure if this is the correct approach, or if in this case some default list should be used
                     if ($se[EN_FLAGS] & EN_FLAGS_CONTENT) {
                         $supfields = array();
                         while (1) {
                             $el = self::$decoder->getElement();
                             if ($el[EN_TYPE] == EN_TYPE_ENDTAG) {
                                 break;
                             } else {
                                 $supfields[] = $el[EN_TAG];
                             }
                         }
                         self::$deviceManager->SetSupportedFields($spa->GetFolderId(), $supfields);
                     }
                 }
                 // Deletes as moves can be an empty tag as well as have value
                 if (self::$decoder->getElementStartTag(SYNC_DELETESASMOVES)) {
                     $spa->SetDeletesAsMoves(true);
                     if (($dam = self::$decoder->getElementContent()) !== false) {
                         $spa->SetDeletesAsMoves((bool) $dam);
                         if (!self::$decoder->getElementEndTag()) {
                             return false;
                         }
                     }
                 }
                 // Get changes can be an empty tag as well as have value
                 // code block partly contributed by dw2412
                 if (self::$decoder->getElementStartTag(SYNC_GETCHANGES)) {
                     $sc->AddParameter($spa, "getchanges", true);
                     if (($gc = self::$decoder->getElementContent()) !== false) {
                         $sc->AddParameter($spa, "getchanges", $gc);
                         if (!self::$decoder->getElementEndTag()) {
                             return false;
                         }
                     }
                 }
                 if (self::$decoder->getElementStartTag(SYNC_WINDOWSIZE)) {
                     $ws = self::$decoder->getElementContent();
                     // normalize windowsize - see ZP-477
                     if ($ws == 0 || $ws > 512) {
                         $ws = 512;
                     }
                     $spa->SetWindowSize($ws);
                     // also announce the currently requested window size to the DeviceManager
                     self::$deviceManager->SetWindowSize($spa->GetFolderId(), $spa->GetWindowSize());
                     if (!self::$decoder->getElementEndTag()) {
                         return false;
                     }
                 }
                 // conversation mode requested
                 if (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) {
                     $spa->SetConversationMode(true);
                     if (($conversationmode = self::$decoder->getElementContent()) !== false) {
                         $spa->SetConversationMode((bool) $conversationmode);
                         if (!self::$decoder->getElementEndTag()) {
                             return false;
                         }
                     }
                 }
                 // Do not truncate by default
                 $spa->SetTruncation(SYNC_TRUNCATION_ALL);
                 // use default conflict handling if not specified by the mobile
                 $spa->SetConflict(SYNC_CONFLICT_DEFAULT);
                 while (self::$decoder->getElementStartTag(SYNC_OPTIONS)) {
                     $firstOption = true;
                     while (1) {
                         // foldertype definition
                         if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) {
                             $foldertype = self::$decoder->getElementContent();
                             ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): 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_TRUNCATION)) {
                             $spa->SetTruncation(self::$decoder->getElementContent());
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         }
                         if (self::$decoder->getElementStartTag(SYNC_RTFTRUNCATION)) {
                             $spa->SetRTFTruncation(self::$decoder->getElementContent());
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         }
                         if (self::$decoder->getElementStartTag(SYNC_MIMESUPPORT)) {
                             $spa->SetMimeSupport(self::$decoder->getElementContent());
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         }
                         if (self::$decoder->getElementStartTag(SYNC_MIMETRUNCATION)) {
                             $spa->SetMimeTruncation(self::$decoder->getElementContent());
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         }
                         if (self::$decoder->getElementStartTag(SYNC_CONFLICT)) {
                             $spa->SetConflict(self::$decoder->getElementContent());
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         }
                         while (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_BODYPREFERENCE)) {
                             if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TYPE)) {
                                 $bptype = self::$decoder->getElementContent();
                                 $spa->BodyPreference($bptype);
                                 if (!self::$decoder->getElementEndTag()) {
                                     return false;
                                 }
                             }
                             if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_TRUNCATIONSIZE)) {
                                 $spa->BodyPreference($bptype)->SetTruncationSize(self::$decoder->getElementContent());
                                 if (!self::$decoder->getElementEndTag()) {
                                     return false;
                                 }
                             }
                             if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_ALLORNONE)) {
                                 $spa->BodyPreference($bptype)->SetAllOrNone(self::$decoder->getElementContent());
                                 if (!self::$decoder->getElementEndTag()) {
                                     return false;
                                 }
                             }
                             if (self::$decoder->getElementStartTag(SYNC_AIRSYNCBASE_PREVIEW)) {
                                 $spa->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;
                         }
                     }
                 }
                 // limit items to be synchronized to the mobiles if configured
                 if (defined('SYNC_FILTERTIME_MAX') && SYNC_FILTERTIME_MAX > SYNC_FILTERTYPE_ALL && (!$spa->HasFilterType() || $spa->GetFilterType() == SYNC_FILTERTYPE_ALL || $spa->GetFilterType() > SYNC_FILTERTIME_MAX)) {
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("SYNC_FILTERTIME_MAX defined. Filter set to value: %s", SYNC_FILTERTIME_MAX));
                     $spa->SetFilterType(SYNC_FILTERTIME_MAX);
                 }
                 // Check if the hierarchycache is available. If not, trigger a HierarchySync
                 if (self::$deviceManager->IsHierarchySyncRequired()) {
                     $status = SYNC_STATUS_FOLDERHIERARCHYCHANGED;
                     ZLog::Write(LOGLEVEL_DEBUG, "HierarchyCache is also not available. Triggering HierarchySync to device");
                 }
                 if (($el = self::$decoder->getElementStartTag(SYNC_PERFORM)) && $el[EN_FLAGS] & EN_FLAGS_CONTENT) {
                     // We can not proceed here as the content class is unknown
                     if ($status != SYNC_STATUS_SUCCESS) {
                         ZLog::Write(LOGLEVEL_WARN, "Ignoring all incoming actions as global status indicates problem.");
                         $wbxmlproblem = true;
                         break;
                     }
                     $performaction = true;
                     // unset the importer
                     $this->importer = false;
                     $nchanges = 0;
                     while (1) {
                         // ADD, MODIFY, REMOVE or FETCH
                         $element = self::$decoder->getElement();
                         if ($element[EN_TYPE] != EN_TYPE_STARTTAG) {
                             self::$decoder->ungetElement($element);
                             break;
                         }
                         if ($status == SYNC_STATUS_SUCCESS) {
                             $nchanges++;
                         }
                         // Foldertype sent when synching SMS
                         if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) {
                             $foldertype = self::$decoder->getElementContent();
                             ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): incoming data with foldertype '%s'", $foldertype));
                             if (!self::$decoder->getElementEndTag()) {
                                 return false;
                             }
                         } else {
                             $foldertype = false;
                         }
                         $serverid = false;
                         if (self::$decoder->getElementStartTag(SYNC_SERVERENTRYID)) {
                             if (($serverid = self::$decoder->getElementContent()) !== false) {
                                 if (!self::$decoder->getElementEndTag()) {
                                     // end serverid
                                     return false;
                                 }
                             }
                         }
                         if (self::$decoder->getElementStartTag(SYNC_CLIENTENTRYID)) {
                             $clientid = self::$decoder->getElementContent();
                             if (!self::$decoder->getElementEndTag()) {
                                 // end clientid
                                 return false;
                             }
                         } else {
                             $clientid = false;
                         }
                         // Get the SyncMessage if sent
                         if (self::$decoder->getElementStartTag(SYNC_DATA)) {
                             $message = ZPush::getSyncObjectFromFolderClass($spa->GetContentClass());
                             $message->Decode(self::$decoder);
                             // set Ghosted fields
                             $message->emptySupported(self::$deviceManager->GetSupportedFields($spa->GetFolderId()));
                             if (!self::$decoder->getElementEndTag()) {
                                 // end applicationdata
                                 return false;
                             }
                         } else {
                             $message = false;
                         }
                         switch ($element[EN_TAG]) {
                             case SYNC_FETCH:
                                 array_push($actiondata["fetchids"], $serverid);
                                 break;
                             default:
                                 // get the importer
                                 if ($this->importer == false) {
                                     $status = $this->getImporter($sc, $spa, $actiondata);
                                 }
                                 if ($status == SYNC_STATUS_SUCCESS) {
                                     $this->importMessage($spa, $actiondata, $element[EN_TAG], $message, $clientid, $serverid, $foldertype, $nchanges);
                                 } else {
                                     ZLog::Write(LOGLEVEL_WARN, "Ignored incoming change, global status indicates problem.");
                                 }
                                 break;
                         }
                         if ($actiondata["fetchids"]) {
                             self::$topCollector->AnnounceInformation(sprintf("Fetching %d", $nchanges));
                         } else {
                             self::$topCollector->AnnounceInformation(sprintf("Incoming %d", $nchanges));
                         }
                         if (!self::$decoder->getElementEndTag()) {
                             // end add/change/delete/move
                             return false;
                         }
                     }
                     if ($status == SYNC_STATUS_SUCCESS && $this->importer !== false) {
                         ZLog::Write(LOGLEVEL_INFO, sprintf("Sync->Handle(): Processed %d incoming changes", $nchanges));
                         if (!$actiondata["fetchids"]) {
                             self::$topCollector->AnnounceInformation(sprintf("%d incoming", $nchanges), true);
                         }
                         try {
                             // Save the updated state, which is used for the exporter later
                             $sc->AddParameter($spa, "state", $this->importer->GetState());
                         } catch (StatusException $stex) {
                             $status = $stex->getCode();
                         }
                     }
                     if (!self::$decoder->getElementEndTag()) {
                         // end PERFORM
                         return false;
                     }
                 }
                 // save the failsave state
                 if (!empty($actiondata["statusids"])) {
                     unset($actiondata["failstate"]);
                     $actiondata["failedsyncstate"] = $sc->GetParameter($spa, "state");
                     self::$deviceManager->GetStateManager()->SetSyncFailState($actiondata);
                 }
                 // save actiondata
                 $sc->AddParameter($spa, "actiondata", $actiondata);
                 if (!self::$decoder->getElementEndTag()) {
                     // end collection
                     return false;
                 }
                 // AS14 does not send GetChanges anymore. We should do it if there were no incoming changes
                 if (!isset($performaction) && !$sc->GetParameter($spa, "getchanges") && $spa->HasSyncKey()) {
                     $sc->AddParameter($spa, "getchanges", true);
                 }
             }
             // END FOLDER
             if (!$wbxmlproblem && !self::$decoder->getElementEndTag()) {
                 // end collections
                 return false;
             }
         }
         // end FOLDERS
         if (self::$decoder->getElementStartTag(SYNC_HEARTBEATINTERVAL)) {
             $hbinterval = self::$decoder->getElementContent();
             if (!self::$decoder->getElementEndTag()) {
                 // SYNC_HEARTBEATINTERVAL
                 return false;
             }
         }
         if (self::$decoder->getElementStartTag(SYNC_WAIT)) {
             $wait = self::$decoder->getElementContent();
             if (!self::$decoder->getElementEndTag()) {
                 // SYNC_WAIT
                 return false;
             }
             // internally the heartbeat interval and the wait time are the same
             // heartbeat is in seconds, wait in minutes
             $hbinterval = $wait * 60;
         }
         if (self::$decoder->getElementStartTag(SYNC_WINDOWSIZE)) {
             $sc->SetGlobalWindowSize(self::$decoder->getElementContent());
             if (!self::$decoder->getElementEndTag()) {
                 // SYNC_WINDOWSIZE
                 return false;
             }
         }
         if (self::$decoder->getElementStartTag(SYNC_PARTIAL)) {
             $partial = true;
         } else {
             $partial = false;
         }
         if (!$wbxmlproblem && !self::$decoder->getElementEndTag()) {
             // end sync
             return false;
         }
     } else {
         $emptysync = true;
     }
     // END SYNCHRONIZE
     // check heartbeat/wait time
     if (isset($hbinterval)) {
         if ($hbinterval < 60 || $hbinterval > 3540) {
             $status = SYNC_STATUS_INVALIDWAITORHBVALUE;
             ZLog::Write(LOGLEVEL_WARN, sprintf("HandleSync(): Invalid heartbeat or wait value '%s'", $hbinterval));
         }
     }
     // Partial & Empty Syncs need saved data to proceed with synchronization
     if ($status == SYNC_STATUS_SUCCESS && ($emptysync === true || $partial === true)) {
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Partial or Empty sync requested. Retrieving data of synchronized folders."));
         // Load all collections - do not overwrite existing (received!), load states and check permissions
         try {
             $sc->LoadAllCollections(false, true, true);
         } catch (StateNotFoundException $snfex) {
             $status = SYNC_STATUS_INVALIDSYNCKEY;
             self::$topCollector->AnnounceInformation("StateNotFoundException", true);
         } catch (StatusException $stex) {
             $status = SYNC_STATUS_FOLDERHIERARCHYCHANGED;
             self::$topCollector->AnnounceInformation(sprintf("StatusException code: %d", $status), true);
         }
         // update a few values
         foreach ($sc as $folderid => $spa) {
             // manually set getchanges parameter for this collection
             $sc->AddParameter($spa, "getchanges", true);
             // set new global windowsize without marking the SPA as changed
             if ($sc->GetGlobalWindowSize()) {
                 $spa->SetWindowSize($sc->GetGlobalWindowSize(), false);
             }
             // announce WindowSize to DeviceManager
             self::$deviceManager->SetWindowSize($folderid, $spa->GetWindowSize());
         }
         if (!$sc->HasCollections()) {
             $status = SYNC_STATUS_SYNCREQUESTINCOMPLETE;
         }
     }
     // HEARTBEAT & Empty sync
     if ($status == SYNC_STATUS_SUCCESS && (isset($hbinterval) || $emptysync == true)) {
         $interval = defined('PING_INTERVAL') && PING_INTERVAL > 0 ? PING_INTERVAL : 30;
         if (isset($hbinterval)) {
             $sc->SetLifetime($hbinterval);
         }
         // states are lazy loaded - we have to make sure that they are there!
         $loadstatus = SYNC_STATUS_SUCCESS;
         foreach ($sc as $folderid => $spa) {
             // some androids do heartbeat on the OUTBOX folder, with weird results - ZP-362
             // we do not load the state so we will never get relevant changes on the OUTBOX folder
             if (self::$deviceManager->GetFolderTypeFromCacheById($folderid) == SYNC_FOLDER_TYPE_OUTBOX) {
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Heartbeat on Outbox folder not allowed"));
                 continue;
             }
             $fad = array();
             // if loading the states fails, we do not enter heartbeat, but we keep $status on SYNC_STATUS_SUCCESS
             // so when the changes are exported the correct folder gets an SYNC_STATUS_INVALIDSYNCKEY
             if ($loadstatus == SYNC_STATUS_SUCCESS) {
                 $loadstatus = $this->loadStates($sc, $spa, $fad);
             }
         }
         if ($loadstatus == SYNC_STATUS_SUCCESS) {
             $foundchanges = false;
             try {
                 // always check for changes
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Entering Heartbeat mode"));
                 $foundchanges = $sc->CheckForChanges($sc->GetLifetime(), $interval);
             } catch (StatusException $stex) {
                 if ($stex->getCode() == SyncCollections::OBSOLETE_CONNECTION) {
                     $status = SYNC_COMMONSTATUS_SYNCSTATEVERSIONINVALID;
                 } else {
                     $status = SYNC_STATUS_FOLDERHIERARCHYCHANGED;
                     self::$topCollector->AnnounceInformation(sprintf("StatusException code: %d", $status), true);
                 }
             }
             // in case there are no changes and no other request has synchronized while we waited, we can reply with an empty response
             if (!$foundchanges && $status == SYNC_STATUS_SUCCESS) {
                 // if there were changes to the SPA or CPOs we need to save this before we terminate
                 // only save if the state was not modified by some other request, if so, return state invalid status
                 foreach ($sc as $folderid => $spa) {
                     if (self::$deviceManager->CheckHearbeatStateIntegrity($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter())) {
                         $status = SYNC_COMMONSTATUS_SYNCSTATEVERSIONINVALID;
                     } else {
                         $sc->SaveCollection($spa);
                     }
                 }
                 if ($status == SYNC_STATUS_SUCCESS) {
                     ZLog::Write(LOGLEVEL_DEBUG, "No changes found and no other process changed states. Replying with empty response and closing connection.");
                     self::$specialHeaders = array();
                     self::$specialHeaders[] = "Connection: close";
                     return true;
                 }
             }
             if ($foundchanges) {
                 foreach ($sc->GetChangedFolderIds() as $folderid => $changecount) {
                     // check if there were other sync requests for a folder during the heartbeat
                     $spa = $sc->GetCollection($folderid);
                     if ($changecount > 0 && $sc->WaitedForChanges() && self::$deviceManager->CheckHearbeatStateIntegrity($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter())) {
                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): heartbeat: found %d changes in '%s' which was already synchronized. Heartbeat aborted!", $changecount, $folderid));
                         $status = SYNC_COMMONSTATUS_SYNCSTATEVERSIONINVALID;
                     } else {
                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): heartbeat: found %d changes in '%s'", $changecount, $folderid));
                     }
                 }
             }
         }
     }
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): Start Output"));
     // Start the output
     self::$encoder->startWBXML();
     self::$encoder->startTag(SYNC_SYNCHRONIZE);
     // global status
     // SYNC_COMMONSTATUS_* start with values from 101
     if ($status != SYNC_COMMONSTATUS_SUCCESS && $status > 100) {
         self::$encoder->startTag(SYNC_STATUS);
         self::$encoder->content($status);
         self::$encoder->endTag();
     } else {
         self::$encoder->startTag(SYNC_FOLDERS);
         foreach ($sc as $folderid => $spa) {
             // get actiondata
             $actiondata = $sc->GetParameter($spa, "actiondata");
             if ($status == SYNC_STATUS_SUCCESS && (!$spa->GetContentClass() || !$spa->GetFolderId())) {
                 ZLog::Write(LOGLEVEL_ERROR, sprintf("HandleSync(): no content class or folderid found for collection."));
                 continue;
             }
             if (!$sc->GetParameter($spa, "requested")) {
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("HandleSync(): partial sync for folder class '%s' with id '%s'", $spa->GetContentClass(), $spa->GetFolderId()));
             }
             // initialize exporter to get changecount
             $changecount = false;
             if (isset($exporter)) {
                 unset($exporter);
             }
             // TODO we could check against $sc->GetChangedFolderIds() on heartbeat so we do not need to configure all exporter again
             if ($status == SYNC_STATUS_SUCCESS && ($sc->GetParameter($spa, "getchanges") || !$spa->HasSyncKey())) {
                 //make sure the states are loaded
                 $status = $this->loadStates($sc, $spa, $actiondata);
                 if ($status == SYNC_STATUS_SUCCESS) {
                     try {
                         // if this is an additional folder the backend has to be setup correctly
                         if (!self::$backend->Setup(ZPush::GetAdditionalSyncFolderStore($spa->GetFolderId()))) {
                             throw new StatusException(sprintf("HandleSync() could not Setup() the backend for folder id '%s'", $spa->GetFolderId()), SYNC_STATUS_FOLDERHIERARCHYCHANGED);
                         }
                         // Use the state from the importer, as changes may have already happened
                         $exporter = self::$backend->GetExporter($spa->GetFolderId());
                         if ($exporter === false) {
                             throw new StatusException(sprintf("HandleSync() could not get an exporter for folder id '%s'", $spa->GetFolderId()), SYNC_STATUS_FOLDERHIERARCHYCHANGED);
                         }
                     } catch (StatusException $stex) {
                         $status = $stex->getCode();
                     }
                     try {
                         // Stream the messages directly to the PDA
                         $streamimporter = new ImportChangesStream(self::$encoder, ZPush::getSyncObjectFromFolderClass($spa->GetContentClass()));
                         if ($exporter !== false) {
                             $exporter->Config($sc->GetParameter($spa, "state"));
                             $exporter->ConfigContentParameters($spa->GetCPO());
                             $exporter->InitializeExporter($streamimporter);
                             $changecount = $exporter->GetChangeCount();
                         }
                     } catch (StatusException $stex) {
                         if ($stex->getCode() === SYNC_FSSTATUS_CODEUNKNOWN && $spa->HasSyncKey()) {
                             $status = SYNC_STATUS_INVALIDSYNCKEY;
                         } else {
                             $status = $stex->getCode();
                         }
                     }
                     if (!$spa->HasSyncKey()) {
                         self::$topCollector->AnnounceInformation(sprintf("Exporter registered. %d objects queued.", $changecount), true);
                         // update folder status as initialized
                         $spa->SetFolderSyncTotal($changecount);
                         $spa->SetFolderSyncRemaining($changecount);
                         if ($changecount > 0) {
                             self::$deviceManager->SetFolderSyncStatus($folderid, DeviceManager::FLD_SYNC_INITIALIZED);
                         }
                     } else {
                         if ($status != SYNC_STATUS_SUCCESS) {
                             self::$topCollector->AnnounceInformation(sprintf("StatusException code: %d", $status), true);
                         }
                     }
                 }
             }
             if (isset($hbinterval) && $changecount == 0 && $status == SYNC_STATUS_SUCCESS) {
                 ZLog::Write(LOGLEVEL_DEBUG, "No changes found for heartbeat folder. Omitting empty output.");
                 continue;
             }
             // Get a new sync key to output to the client if any changes have been send or will are available
             if (!empty($actiondata["modifyids"]) || !empty($actiondata["clientids"]) || !empty($actiondata["removeids"]) || $changecount > 0 || !$spa->HasSyncKey() && $status == SYNC_STATUS_SUCCESS) {
                 $spa->SetNewSyncKey(self::$deviceManager->GetStateManager()->GetNewSyncKey($spa->GetSyncKey()));
             }
             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"])), true);
                 }
                 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->GetFolderId()))) {
                             throw new StatusException(sprintf("HandleSync(): could not Setup() the backend to fetch in folder id '%s'", $spa->GetFolderId()), SYNC_STATUS_OBJECTNOTFOUND);
                         }
                         $data = self::$backend->Fetch($spa->GetFolderId(), $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()) {
                 $windowSize = self::$deviceManager->GetWindowSize($spa->GetFolderId(), $spa->GetContentClass(), $spa->GetUuid(), $spa->GetUuidCounter(), $changecount);
                 if ($changecount > $windowSize) {
                     self::$encoder->startTag(SYNC_MOREAVAILABLE, false, true);
                 }
             }
             // Stream outgoing changes
             if ($status == SYNC_STATUS_SUCCESS && $sc->GetParameter($spa, "getchanges") == true && $windowSize > 0) {
                 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;
                 while (1) {
                     try {
                         $progress = $exporter->Synchronize();
                         if (!is_array($progress)) {
                             break;
                         }
                         $n++;
                     } 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) {
                         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 (isset($streamimporter)) {
                     $n = $streamimporter->GetImportedMessages();
                 }
                 self::$encoder->endTag();
                 self::$topCollector->AnnounceInformation(sprintf("Outgoing %d objects%s", $n, $n >= $windowSize ? " of " . $changecount : ""), true);
                 // 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($folderid, DeviceManager::FLD_SYNC_COMPLETED);
                 } else {
                     self::$deviceManager->SetFolderSyncStatus($folderid, 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();
                     } 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);
             }
             // reset status for the next folder
             $status = SYNC_STATUS_SUCCESS;
         }
         // END foreach collection
         self::$encoder->endTag();
         //SYNC_FOLDERS
     }
     self::$encoder->endTag();
     //SYNC_SYNCHRONIZE
     return true;
 }
 /**
  * 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;
         if (Request::GetProtocolVersion() >= 14.0) {
             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;
                 }
             }
             if (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) {
                 $spa->SetFolderId(self::$decoder->getElementContent());
                 if (!self::$decoder->getElementEndTag()) {
                     return false;
                 }
             }
             // conversation mode requested
             if (self::$decoder->getElementStartTag(SYNC_CONVERSATIONMODE)) {
                 $spa->SetConversationMode(true);
                 if (($conversationmode = self::$decoder->getElementContent()) !== false) {
                     $spa->SetConversationMode((bool) $conversationmode);
                     if (!self::$decoder->getElementEndTag()) {
                         return false;
                     }
                 }
             }
             if (self::$decoder->getElementStartTag(SYNC_OPTIONS)) {
                 while (1) {
                     if (self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) {
                         $spa->SetFilterType(self::$decoder->getElementContent());
                         if (!self::$decoder->getElementEndTag()) {
                             return false;
                         }
                     }
                     if (self::$decoder->getElementStartTag(SYNC_FOLDERTYPE)) {
                         $spa->SetContentClass(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;
                     }
                 }
             }
         } else {
             //get items estimate does not necessarily send the folder type
             if (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERTYPE)) {
                 $spa->SetContentClass(self::$decoder->getElementContent());
                 if (!self::$decoder->getElementEndTag()) {
                     return false;
                 }
             }
             if (self::$decoder->getElementStartTag(SYNC_GETITEMESTIMATE_FOLDERID)) {
                 $spa->SetFolderId(self::$decoder->getElementContent());
                 if (!self::$decoder->getElementEndTag()) {
                     return false;
                 }
             }
             if (!self::$decoder->getElementStartTag(SYNC_FILTERTYPE)) {
                 return false;
             }
             $spa->SetFilterType(self::$decoder->getElementContent());
             if (!self::$decoder->getElementEndTag()) {
                 return false;
             }
             if (!self::$decoder->getElementStartTag(SYNC_SYNCKEY)) {
                 return false;
             }
             try {
                 $spa->SetSyncKey(self::$decoder->getElementContent());
             } catch (StateInvalidException $siex) {
                 $spastatus = SYNC_GETITEMESTSTATUS_SYNCSTATENOTPRIMED;
             }
             if (!self::$decoder->getElementEndTag()) {
                 return false;
             }
         }
         if (!self::$decoder->getElementEndTag()) {
             return false;
         }
         //SYNC_GETITEMESTIMATE_FOLDER
         // 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->GetFolderId()))) {
                     throw new StatusException(sprintf("HandleGetItemEstimate() could not Setup() the backend for folder id '%s'", $spa->GetFolderId()), 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);
             }
         }
         self::$encoder->endTag();
         self::$encoder->endTag();
     }
     if (array_sum($changes) == 0) {
         self::$topCollector->AnnounceInformation("No changes found", true);
     }
     self::$encoder->endTag();
     return true;
 }
 function SyncAppointment()
 {
     $mapping = array(SYNC_POOMCAL_TIMEZONE => array(self::STREAMER_VAR => "timezone"), SYNC_POOMCAL_DTSTAMP => array(self::STREAMER_VAR => "dtstamp", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO)), SYNC_POOMCAL_STARTTIME => array(self::STREAMER_VAR => "starttime", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETZERO, self::STREAMER_CHECK_CMPLOWER => SYNC_POOMCAL_ENDTIME)), SYNC_POOMCAL_SUBJECT => array(self::STREAMER_VAR => "subject", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETEMPTY)), SYNC_POOMCAL_UID => array(self::STREAMER_VAR => "uid"), SYNC_POOMCAL_ORGANIZERNAME => array(self::STREAMER_VAR => "organizername"), SYNC_POOMCAL_ORGANIZEREMAIL => array(self::STREAMER_VAR => "organizeremail"), SYNC_POOMCAL_LOCATION => array(self::STREAMER_VAR => "location"), SYNC_POOMCAL_ENDTIME => array(self::STREAMER_VAR => "endtime", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETONE, self::STREAMER_CHECK_CMPHIGHER => SYNC_POOMCAL_STARTTIME)), SYNC_POOMCAL_RECURRENCE => array(self::STREAMER_VAR => "recurrence", self::STREAMER_TYPE => "SyncRecurrence"), SYNC_POOMCAL_SENSITIVITY => array(self::STREAMER_VAR => "sensitivity", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3))), SYNC_POOMCAL_BUSYSTATUS => array(self::STREAMER_VAR => "busystatus", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_REQUIRED => self::STREAMER_CHECK_SETTWO, self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3))), SYNC_POOMCAL_ALLDAYEVENT => array(self::STREAMER_VAR => "alldayevent", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ZEROORONE => self::STREAMER_CHECK_SETZERO)), SYNC_POOMCAL_REMINDER => array(self::STREAMER_VAR => "reminder", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1)), SYNC_POOMCAL_RTF => array(self::STREAMER_VAR => "rtf"), SYNC_POOMCAL_MEETINGSTATUS => array(self::STREAMER_VAR => "meetingstatus", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 3, 5, 7, 9, 11, 13, 15))), SYNC_POOMCAL_ATTENDEES => array(self::STREAMER_VAR => "attendees", self::STREAMER_TYPE => "SyncAttendee", self::STREAMER_ARRAY => SYNC_POOMCAL_ATTENDEE), SYNC_POOMCAL_BODY => array(self::STREAMER_VAR => "body"), SYNC_POOMCAL_BODYTRUNCATED => array(self::STREAMER_VAR => "bodytruncated"), SYNC_POOMCAL_EXCEPTIONS => array(self::STREAMER_VAR => "exceptions", self::STREAMER_TYPE => "SyncAppointmentException", self::STREAMER_ARRAY => SYNC_POOMCAL_EXCEPTION), SYNC_POOMCAL_CATEGORIES => array(self::STREAMER_VAR => "categories", self::STREAMER_ARRAY => SYNC_POOMCAL_CATEGORY));
     if (Request::GetProtocolVersion() >= 12.0) {
         $mapping[SYNC_AIRSYNCBASE_BODY] = array(self::STREAMER_VAR => "asbody", self::STREAMER_TYPE => "SyncBaseBody");
         $mapping[SYNC_AIRSYNCBASE_NATIVEBODYTYPE] = array(self::STREAMER_VAR => "nativebodytype");
         //unset these properties because airsyncbase body and attachments will be used instead
         unset($mapping[SYNC_POOMCAL_BODY], $mapping[SYNC_POOMCAL_BODYTRUNCATED]);
     }
     if (Request::GetProtocolVersion() >= 14.0) {
         $mapping[SYNC_POOMCAL_DISALLOWNEWTIMEPROPOSAL] = array(self::STREAMER_VAR => "disallownewtimeprop");
         $mapping[SYNC_POOMCAL_RESPONSEREQUESTED] = array(self::STREAMER_VAR => "responserequested");
         $mapping[SYNC_POOMCAL_RESPONSETYPE] = array(self::STREAMER_VAR => "responsetype");
     }
     parent::SyncObject($mapping);
 }
Example #17
0
 private function _ParseLDAPMessage($result_id, $entry_id, $truncsize = -1)
 {
     $contact = new SyncContact();
     $values = ldap_get_attributes($this->ldap_link, $entry_id);
     for ($i = 0; $i < $values["count"]; $i++) {
         $name = $values[$i];
         $value = $values[$name][0];
         switch ($name) {
             //person
             case "cn":
             case "fileAs":
                 $contact->fileas = $value;
                 break;
             case "sn":
                 $contact->lastname = $value;
                 break;
                 //inetOrgPerson
             //inetOrgPerson
             case "departmentNumber":
                 $contact->department = $value;
                 break;
             case "givenName":
                 $contact->firstname = $value;
                 break;
             case "homePhone":
                 $contact->homephonenumber = $value;
                 if ($values[$name]["count"] >= 2) {
                     $contact->home2phonenumber = $values[$name][1];
                 }
                 break;
             case "jpegPhoto":
                 $contact->picture = base64_encode($value);
                 break;
             case "labeledURI":
                 $contact->webpage = $value;
                 break;
             case "mail":
                 $contact->email1address = $value;
                 if ($values[$name]["count"] >= 2) {
                     $contact->email2address = $values[$name][1];
                 }
                 if ($values[$name]["count"] >= 3) {
                     $contact->email3address = $values[$name][2];
                 }
                 break;
             case "mobile":
                 $contact->mobilephonenumber = $value;
                 break;
             case "o":
                 $contact->companyname = $value;
                 break;
             case "pager":
                 $contact->pagernumber = $value;
                 break;
             case "secretary":
             case "assistantName":
                 $contact->assistantname = $value;
                 break;
                 //organizationalPerson
             //organizationalPerson
             case "l":
                 $contact->businesscity = $value;
                 break;
             case "ou":
                 $contact->department = $value;
                 break;
             case "physicalDeliveryOfficeName":
                 $contact->officelocation = $value;
                 break;
             case "postalCode":
                 $contact->businesspostalcode = $value;
                 break;
             case "st":
                 $contact->businessstate = $value;
                 break;
             case "street":
                 $contact->businessstreet = $value;
                 break;
             case "telephoneNumber":
                 $contact->businessphonenumber = $value;
                 if ($values[$name]["count"] >= 2) {
                     $contact->business2phonenumber = $values[$name][1];
                 }
                 break;
             case "title":
                 $contact->title = $value;
                 break;
             case "description":
             case "note":
                 if (Request::GetProtocolVersion() >= 12.0) {
                     $contact->asbody = new SyncBaseBody();
                     $contact->asbody->type = SYNC_BODYPREFERENCE_PLAIN;
                     $contact->asbody->data = $value;
                     if ($truncsize > 0 && $truncsize < strlen($contact->asbody->data)) {
                         $contact->asbody->truncated = 1;
                         $contact->asbody->data = Utils::Utf8_truncate($contact->asbody->data, $truncsize);
                     } else {
                         $contact->asbody->truncated = 0;
                     }
                     $contact->asbody->estimatedDataSize = strlen($contact->asbody->data);
                 } else {
                     $contact->body = $value;
                     if ($truncsize > 0 && $truncsize < strlen($contact->body)) {
                         $contact->bodytruncated = 1;
                         $contact->body = Utils::Utf8_truncate($contact->body, $truncsize);
                     } else {
                         $contact->bodytruncated = 0;
                     }
                     $contact->bodysize = strlen($contact->body);
                 }
                 break;
             case "assistantPhone":
                 $contact->assistnamephonenumber = $value;
                 break;
             case "birthDate":
                 $contact->birthday = $value;
                 break;
             case "anniversary":
                 $contact->anniversary = $value;
                 break;
             case "businessRole":
                 $contact->jobtitle = $value;
                 break;
             case "carPhone":
                 $contact->carphonenumber = $value;
                 break;
             case "facsimileTelephoneNumber":
                 $contact->businessfaxnumber = $value;
                 break;
             case "homeFacsimileTelephoneNumber":
                 $contact->homefaxnumber = $value;
                 break;
             case "spouseName":
                 $contact->spouse = $value;
                 break;
             case "managerName":
                 $contact->managername = $value;
                 break;
             case "radio":
                 $contact->radiophonenumber = $value;
                 break;
         }
     }
     return $contact;
 }
 /**
  * Called at the end of the request
  * Statistics about received/sent data is saved here
  *
  * @access public
  * @return boolean
  */
 public function Save()
 {
     // TODO save other stuff
     // check if previousily ignored messages were synchronized for the current folder
     // on multifolder operations of AS14 this is done by setLatestFolder()
     if ($this->latestFolder !== false) {
         $this->checkBrokenMessages($this->latestFolder);
     }
     // update the user agent and AS version on the device
     $this->device->SetUserAgent(Request::GetUserAgent());
     $this->device->SetASVersion(Request::GetProtocolVersion());
     // data to be saved
     $data = $this->device->GetData();
     if ($data && Request::IsValidDeviceID()) {
         ZLog::Write(LOGLEVEL_DEBUG, "DeviceManager->Save(): Device data changed");
         try {
             // check if this is the first time the device data is saved and it is authenticated. If so, link the user to the device id
             if ($this->device->IsNewDevice() && RequestProcessor::isUserAuthenticated()) {
                 ZLog::Write(LOGLEVEL_INFO, sprintf("Linking device ID '%s' to user '%s'", $this->devid, $this->device->GetDeviceUser()));
                 $this->statemachine->LinkUserDevice($this->device->GetDeviceUser(), $this->devid);
             }
             if (RequestProcessor::isUserAuthenticated() || $this->device->GetForceSave()) {
                 $this->statemachine->SetState($data, $this->devid, IStateMachine::DEVICEDATA);
                 ZLog::Write(LOGLEVEL_DEBUG, "DeviceManager->Save(): Device data saved");
             }
         } catch (StateNotFoundException $snfex) {
             ZLog::Write(LOGLEVEL_ERROR, "DeviceManager->Save(): Exception: " . $snfex->getMessage());
         }
     }
     // remove old search data
     $oldpid = $this->loopdetection->ProcessLoopDetectionGetOutdatedSearchPID();
     if ($oldpid) {
         ZPush::GetBackend()->GetSearchProvider()->TerminateSearch($oldpid);
     }
     // we terminated this process
     if ($this->loopdetection) {
         $this->loopdetection->ProcessLoopDetectionTerminate();
     }
     return true;
 }
Example #19
0
 /**
  * Returns the actual SyncXXX object type.
  *
  * @param string            $folderid           id of the parent folder
  * @param string            $id                 id of the message
  * @param ContentParameters $contentparameters  parameters of the requested message (truncation, mimesupport etc)
  *
  * @access public
  * @return object/false     false if the message could not be retrieved
  */
 public function GetMessage($folder, $id, $contentparameters)
 {
     $folderid = $folder->serverid;
     ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . ', ..)');
     /*
     public $to;
          public $cc;
          public $from;
          public $subject;
          public $threadtopic;
          public $datereceived;
          public $displayto;
          public $importance;
          public $read;
          public $attachments;
          public $mimetruncated;
          public $mimedata;
          public $mimesize;
          public $bodytruncated;
          public $bodysize;
          public $body;
          public $messageclass;
          public $meetingrequest;
          public $reply_to;
     // AS 2.5 prop
          public $internetcpid;
     // AS 12.0 props
          public $asbody;
          public $asattachments;
          public $flag;
          public $contentclass;
          public $nativebodytype;
     // AS 14.0 props
          public $umcallerid;
          public $umusernotes;
          public $conversationid;
          public $conversationindex;
          public $lastverbexecuted; //possible values unknown, reply to sender, reply to all, forward
          public $lastverbexectime;
          public $receivedasbcc;
          public $sender;
     */
     $bodypreference = $contentparameters->GetBodyPreference();
     if ($bodypreference !== false) {
         $bpReturnType = Utils::GetBodyPreferenceBestMatch($bodypreference);
     }
     ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): bpReturnType: ' . $bpReturnType);
     $output = new SyncMail();
     $response = $this->OXConnector->OXreqGET('/ajax/mail', array('action' => 'get', 'session' => $this->OXConnector->getSession(), 'folder' => $folderid, 'id' => $id, 'unseen' => 'true', 'timezone' => 'UTC'));
     foreach ($response["data"]["to"] as &$to) {
         $output->to[] = $to[1];
     }
     foreach ($response["data"]["from"] as &$from) {
         $output->from = $from[1];
     }
     $output->reply_to = array();
     //OX 0 - no prio, 2 - high, 1 - most important, 3 - normal, 5 - lowest
     //AS 0 - low, 1 - normal, 2 - important
     $normalPrio = array(0, 3);
     $highPrio = array(1, 2);
     $lowPrio = array(4, 5);
     if (in_array($response["data"]["priority"], $normalPrio)) {
         $output->importance = 1;
         ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): Priority is "Normal"');
     } else {
         if (in_array($response["data"]["priority"], $highPrio)) {
             $output->importance = 2;
             ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): Priority is "High"');
         } else {
             if (in_array($response["data"]["priority"], $lowPrio)) {
                 $output->importance = 0;
                 ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): Priority is "Low"');
             }
         }
     }
     $output->subject = $response["data"]["subject"];
     // Though the unseen key is not in data we can assume the messages returned are in fact unseen
     // because of the "unseen" => true parameter to OX API (?)
     $output->read = array_key_exists("unseen", $response["data"]) && $response["data"]["unseen"] == "true" ? false : false;
     $output->datereceived = $this->OXUtils->timestampOXtoPHP($response["data"]["received_date"]);
     foreach ($response["data"]["attachments"] as $attachment) {
         ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): Attachment "' . $attachment['id'] . '" has Contenttype "' . $attachment['content_type'] . '"');
         // Extract text/html and text/plain parts:
         $textPlain = "";
         $textHtml = "";
         if ($attachment['content_type'] == "text/plain") {
             $textPlain = html_entity_decode(str_replace("<br>", "\n", $attachment['content']), ENT_NOQUOTES, 'UTF-8');
             // OX sends the Umlauts as HTML-Tags. So we mus convert them :(.
         } else {
             if ($attachment['content_type'] == "text/html") {
                 $textHtml = $attachment['content'];
             }
         }
     }
     // Does our client understand AS-Version >= 12.0 ?
     if (Request::GetProtocolVersion() >= 12.0 && $bpReturnType == SYNC_BODYPREFERENCE_MIME) {
         $output->asbody = new SyncBaseBody();
         // For MIME-Message we need to get the Mail in "raw":
         $MIMEresponse = $this->OXConnector->OXreqGET('/ajax/mail', array('action' => 'get', 'session' => $this->OXConnector->getSession(), 'folder' => $folderid, 'id' => $id, 'unseen' => 'true', 'src' => 'true', 'timezone' => 'UTC'));
         ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . '): MIME-Response: "' . print_r($MIMEresponse, true));
         $output->asbody->data = $MIMEresponse["data"];
         $output->asbody->type = SYNC_BODYPREFERENCE_MIME;
         $output->nativebodytype = SYNC_BODYPREFERENCE_MIME;
         $output->asbody->estimatedDataSize = strlen($output->asbody->data);
         $output->messageclass = "IPM.Note";
         $output->internetcpid = INTERNET_CPID_UTF8;
         $output->contentclass = "urn:content-classes:message";
         $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
         if (strlen($output->asbody->data) > $truncsize) {
             $output->asbody->data = Utils::Utf8_truncate($output->asbody->data, $truncsize);
             $output->asbody->truncated = 1;
         }
     } else {
         if (Request::GetProtocolVersion() >= 12.0 && !empty($textHtml) && $bpReturnType == SYNC_BODYPREFERENCE_HTML) {
             // HTML-Mails:
             $output->asbody = new SyncBaseBody();
             $output->asbody->data = $textHtml;
             $output->asbody->type = SYNC_BODYPREFERENCE_HTML;
             $output->nativebodytype = SYNC_BODYPREFERENCE_HTML;
             $output->asbody->estimatedDataSize = strlen($output->asbody->data);
             $output->messageclass = "IPM.Note";
             $output->internetcpid = INTERNET_CPID_UTF8;
             $output->contentclass = "urn:content-classes:message";
             $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
             if (strlen($output->asbody->data) > $truncsize) {
                 $output->asbody->data = Utils::Utf8_truncate($output->asbody->data, $truncsize);
                 $output->asbody->truncated = 1;
             }
         } else {
             if (Request::GetProtocolVersion() >= 12.0 && !empty($textPlain)) {
                 // Text-Mails:
                 $output->asbody = new SyncBaseBody();
                 $output->asbody->data = $textPlain;
                 // $textHtml;
                 $output->asbody->type = SYNC_BODYPREFERENCE_PLAIN;
                 $output->nativebodytype = SYNC_BODYPREFERENCE_PLAIN;
                 $output->asbody->estimatedDataSize = strlen($output->asbody->data);
                 $bpo = $contentparameters->BodyPreference($output->asbody->type);
                 if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) {
                     $output->asbody->preview = Utils::Utf8_truncate(Utils::ConvertHtmlToText($plainBody), $bpo->GetPreview());
                 }
             } else {
                 // Default action is to only send the textPlain-Part via AS2.5
                 $output->body = $textPlain;
                 $output->nativebodytype = SYNC_BODYPREFERENCE_PLAIN;
             }
         }
     }
     // ZLog::Write(LOGLEVEL_DEBUG, 'OXEmailSync::GetMessage(' . $folderid . ', ' . $id . ') Output: ' . print_r($output, true));
     return $output;
 }
Example #20
0
 protected function GetEvent($id, $contentparameters)
 {
     $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
     $events = $this->models->execute_kw(ODOO_DB, $this->uid, $this->password, 'calendar.event', 'search_read', [['|', ['user_id', '=', $this->uid], ['partner_ids', 'in', [$this->partnerID]], ['id', '=', intval(substr($id, 6))]]], ['fields' => []]);
     ZLog::Write(LOGLEVEL_DEBUG, 'Odoo::GetEvent: $events = (' . print_r($events, true) . ')');
     if (!count($events)) {
         $message = new SyncAppointment();
         $message->deleted = 1;
         return $message;
     }
     $event = $events[0];
     $users = $this->models->execute_kw(ODOO_DB, $this->uid, $this->password, 'res.users', 'search_read', [[['id', '=', $event['user_id'][0]]]], ['fields' => ['email']]);
     ZLog::Write(LOGLEVEL_DEBUG, 'Odoo::GetMessage: $users = (' . print_r($users, true)) . ')';
     if (!count($users)) {
         return false;
     }
     $user = $users[0];
     $attendees = $this->models->execute_kw(ODOO_DB, $this->uid, $this->password, 'calendar.attendee', 'read', [$event['attendee_ids']], ['fields' => ['cn', 'email', 'state']]);
     ZLog::Write(LOGLEVEL_DEBUG, 'Odoo::GetMessage: $attendees = (' . print_r($attendees, true)) . ')';
     $categories = $this->models->execute_kw(ODOO_DB, $this->uid, $this->password, 'calendar.event.type', 'read', [$event['categ_ids']], ['fields' => []]);
     ZLog::Write(LOGLEVEL_DEBUG, 'Odoo::GetMessage: $categories = (' . print_r($categories, true)) . ')';
     $message = new SyncAppointment();
     $message->uid = $event['id'];
     $message->dtstamp = strtotime($event['write_date']);
     $message->starttime = strtotime($event['start']) + $this->_getTimezoneOffset($this->utz);
     $message->endtime = strtotime($event['stop']) + $this->_getTimezoneOffset($this->utz);
     $message->timezone = $this->_GetTimezoneString($this->utz);
     $message->subject = $event['name'];
     if (count($attendees) != 0) {
         $message->organizername = $event['user_id'][1];
         $message->organizeremail = $user['email'];
     }
     $message->location = $event['location'];
     if ($event['recurrency']) {
         $recurrence = new SyncRecurrence();
         switch ($event['rrule_type']) {
             case 'daily':
                 $recurrence->type = 0;
                 break;
             case 'weekly':
                 $recurrence->type = 1;
                 break;
             case 'monthly':
                 $recurrence->type = 2;
                 if ($event['month_by'] == 'day') {
                     $recurrence->type = 3;
                 }
                 break;
             case 'yearly':
                 $recurrence->type = 5;
                 break;
         }
         $recurrence->until = strtotime($event['final_date']);
         $recurrence->occurrences = intval($event['count']);
         $recurrence->interval = intval($event['interval']);
         //weekly
         if ($recurrence->type == 1) {
             $recurrence->dayofweek = 0;
             if ($event['su']) {
                 $recurrence->dayofweek += 1;
             }
             if ($event['mo']) {
                 $recurrence->dayofweek += 2;
             }
             if ($event['tu']) {
                 $recurrence->dayofweek += 4;
             }
             if ($event['we']) {
                 $recurrence->dayofweek += 8;
             }
             if ($event['th']) {
                 $recurrence->dayofweek += 16;
             }
             if ($event['fr']) {
                 $recurrence->dayofweek += 32;
             }
             if ($event['sa']) {
                 $recurrence->dayofweek += 64;
             }
         }
         //monthly
         if ($recurrence->type == 2) {
             $recurrence->dayofmonth = intval($event['day']);
         }
         //monthly on nth day
         if ($recurrence->type == 3) {
             $recurrence->dayofweek = 0;
             switch ($event['byday']) {
                 case '1':
                 case '2':
                 case '3':
                 case '4':
                 case '5':
                     $recurrence->weekofmonth = intval($event['byday']);
                     break;
                 case '-1':
                     $recurrence->weekofmonth = 5;
                     break;
             }
             switch ($event['week_list']) {
                 case 'SU':
                     $recurrence->dayofweek += 1;
                     break;
                 case 'MO':
                     $recurrence->dayofweek += 2;
                     break;
                 case 'TU':
                     $recurrence->dayofweek += 4;
                     break;
                 case 'WE':
                     $recurrence->dayofweek += 8;
                     break;
                 case 'TH':
                     $recurrence->dayofweek += 16;
                     break;
                 case 'FR':
                     $recurrence->dayofweek += 32;
                     break;
                 case 'SA':
                     $recurrence->dayofweek += 64;
                     break;
             }
         }
         if ($recurrence->type == 5) {
             $start_date = strtotime($event['start_date']);
             $recurrence->monthofyear = intval(date('n', $start_date));
         }
         $message->recurrence = $recurrence;
     }
     switch ($event['class']) {
         case 'public':
             $message->sensitivity = 0;
             break;
         case 'private':
             $message->sensitivity = 2;
             break;
         case 'confidential':
             $message->sensitivity = 3;
             break;
     }
     switch ($event['show_as']) {
         case 'free':
             $message->busystatus = 0;
             break;
         case 'busy':
             $message->busystatus = 2;
             break;
     }
     $message->alldayevent = $event['allday'];
     $message->reminder = 30;
     //TODO
     $message->meetingstatus = count($attendees) == 0 ? 0 : 1;
     $message->attendees = array_map(function ($attendee) use($message) {
         $syncattendee = new SyncAttendee();
         $syncattendee->email = $attendee['email'];
         $syncattendee->name = $attendee['cn'];
         $syncattendee->attendeetype = 1;
         switch ($attendee['state']) {
             case 'needsAction':
                 $syncattendee->attendeestatus = 5;
                 break;
             case 'tentative':
                 $syncattendee->attendeestatus = 2;
                 break;
             case 'declined':
                 $syncattendee->attendeestatus = 4;
                 break;
             case 'accepted':
                 $syncattendee->attendeestatus = 3;
                 break;
             default:
                 $syncattendee->attendeestatus = 0;
         }
         return $syncattendee;
     }, $attendees);
     if (Request::GetProtocolVersion() >= 12.0) {
         $message->asbody = new SyncBaseBody();
         $message->asbody->type = SYNC_BODYPREFERENCE_PLAIN;
         $message->asbody->data = $event['description'];
         $message->asbody->estimatedDataSize = mb_strlen($event['description'], 'UTF-8');
         if ($message->asbody->estimatedDataSize > $truncsize) {
             $message->asbody->data = Utils::Utf8_truncate($message->asbody->data, $truncsize);
             $message->asbody->truncated = 1;
         }
     } else {
         $message->body = $event['description'];
         $message->body = str_replace("\n", "\r\n", str_replace("\r", "", $message->body));
         $message->bodysize = mb_strlen($event['description'], 'UTF-8');
         if (strlen($message->body) > $truncsize) {
             $message->body = Utils::Utf8_truncate($message->body, $truncsize);
             $message->bodytruncated = 1;
         }
     }
     $message->categories = array_map(function ($category) {
         return $category['name'];
     }, $categories);
     ZLog::Write(LOGLEVEL_DEBUG, 'Odoo::GetMessage: $message = (' . print_r($message, true) . ')');
     return $message;
 }
Example #21
0
 /**
  * Returns the actual SyncXXX object type.
  *
  * @param string            $folderid           id of the parent folder
  * @param string            $id                 id of the message
  * @param ContentParameters $contentparameters  parameters of the requested message (truncation, mimesupport etc)
  *
  * @access public
  * @return object/false     false if the message could not be retrieved
  */
 public function GetMessage($folderid, $id, $contentparameters)
 {
     $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
     $mimesupport = $contentparameters->GetMimeSupport();
     $bodypreference = $contentparameters->GetBodyPreference();
     /* fmbiete's contribution r1528, ZP-320 */
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage('%s', '%s', '%s')", $folderid, $id, implode(",", $bodypreference)));
     $folderImapid = $this->getImapIdFromFolderId($folderid);
     // Get flags, etc
     $stat = $this->StatMessage($folderid, $id);
     if ($stat) {
         $this->imap_reopen_folder($folderImapid);
         $mail = @imap_fetchheader($this->mbox, $id, FT_UID) . @imap_body($this->mbox, $id, FT_PEEK | FT_UID);
         if (empty($mail)) {
             throw new StatusException(sprintf("BackendIMAP->GetMessage(): Error, message not found, maybe was moved"), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);
         }
         $mobj = new Mail_mimeDecode($mail);
         $message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8'));
         $is_multipart = is_multipart($message);
         $is_smime = is_smime($message);
         $is_encrypted = $is_smime ? is_encrypted($message) : false;
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): Message is multipart: %d, smime: %d, smime encrypted: %d", $is_multipart, $is_smime, $is_encrypted));
         //Select body type preference
         $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
         if ($bodypreference !== false) {
             $bpReturnType = Utils::GetBodyPreferenceBestMatch($bodypreference);
             // changed by mku ZP-330
         }
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): getBodyPreferenceBestMatch: %d", $bpReturnType));
         // Prefered format is MIME -OR- message is SMIME -OR- the device supports MIME (iPhone) and doesn't really understand HTML
         if ($bpReturnType == SYNC_BODYPREFERENCE_MIME || $is_smime || in_array(SYNC_BODYPREFERENCE_MIME, $bodypreference)) {
             $bpReturnType = SYNC_BODYPREFERENCE_MIME;
         }
         // We need the text body even though MIME is used, for the preview
         $textBody = "";
         Mail_mimeDecode::getBodyRecursive($message, "html", $textBody, true);
         if (strlen($textBody) > 0) {
             if ($bpReturnType != SYNC_BODYPREFERENCE_MIME) {
                 $bpReturnType = SYNC_BODYPREFERENCE_HTML;
             }
         } else {
             Mail_mimeDecode::getBodyRecursive($message, "plain", $textBody, true);
             if ($bpReturnType != SYNC_BODYPREFERENCE_MIME) {
                 $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
             }
         }
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): after thinking a bit we will use: %d", $bpReturnType));
         $output = new SyncMail();
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->asbody = new SyncBaseBody();
             switch ($bpReturnType) {
                 case SYNC_BODYPREFERENCE_PLAIN:
                     $output->asbody->data = $textBody;
                     break;
                 case SYNC_BODYPREFERENCE_HTML:
                     $output->asbody->data = $textBody;
                     break;
                 case SYNC_BODYPREFERENCE_MIME:
                     if ($is_smime) {
                         $output->asbody->data = $mail;
                         if ($is_encrypted) {
                             // #190, KD 2015-06-04 - If message body is encrypted we'd drop it as data should only be in the attachment but... there's no good way to let only headers through...
                             $truncsize = 500;
                         }
                     } else {
                         $output->asbody->data = build_mime_message($message);
                     }
                     break;
                 case SYNC_BODYPREFERENCE_RTF:
                     ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->GetMessage(): RTF Format NOT CHECKED");
                     $output->asbody->data = base64_encode($textBody);
                     break;
             }
             // truncate body, if requested.
             // MIME should not be truncated, but encrypted messages are truncated always to a minimal fixed size
             if (($bpReturnType !== SYNC_BODYPREFERENCE_MIME || $is_encrypted) && strlen($output->asbody->data) > $truncsize) {
                 $output->asbody->data = Utils::Utf8_truncate($output->asbody->data, $truncsize);
                 $output->asbody->truncated = 1;
             } else {
                 $output->asbody->truncated = 0;
             }
             $output->asbody->type = $bpReturnType;
             if ($bpReturnType == SYNC_BODYPREFERENCE_MIME) {
                 // NativeBodyType can be only (1 => PLAIN, 2 => HTML, 3 => RTF). MIME uses 1
                 $output->nativebodytype = SYNC_BODYPREFERENCE_PLAIN;
             } else {
                 $output->nativebodytype = $bpReturnType;
             }
             $output->asbody->estimatedDataSize = strlen($output->asbody->data);
             $bpo = $contentparameters->BodyPreference($output->asbody->type);
             if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) {
                 $output->asbody->preview = Utils::Utf8_truncate(Utils::ConvertHtmlToText($textBody), $bpo->GetPreview());
             }
         } else {
             // ASV_2.5
             //DEPRECATED : very old devices, and incomplete code
             $output->bodytruncated = 0;
             /* BEGIN fmbiete's contribution r1528, ZP-320 */
             if ($bpReturnType == SYNC_BODYPREFERENCE_MIME) {
                 // truncate body, if requested, but never truncate MIME messages
                 $output->mimetruncated = 0;
                 $output->mimedata = $mail;
                 $output->mimesize = strlen($output->mimedata);
             } else {
                 // truncate body, if requested
                 if (strlen($textBody) > $truncsize) {
                     $output->body = Utils::Utf8_truncate($textBody, $truncsize);
                     $output->bodytruncated = 1;
                 } else {
                     $output->body = $textBody;
                     $output->bodytruncated = 0;
                 }
                 $output->bodysize = strlen($output->body);
             }
             /* END fmbiete's contribution r1528, ZP-320 */
         }
         unset($textBody);
         $output->datereceived = isset($message->headers["date"]) ? $this->cleanupDate($message->headers["date"]) : null;
         if ($is_smime) {
             // #190, KD 2015-06-04 - Add Encrypted (and possibly signed) to the classifications emitted
             if ($is_encrypted) {
                 $output->messageclass = "IPM.Note.SMIME";
             } else {
                 $output->messageclass = "IPM.Note.SMIME.MultipartSigned";
             }
         } else {
             $output->messageclass = "IPM.Note";
         }
         $output->subject = isset($message->headers["subject"]) ? $message->headers["subject"] : "";
         $output->read = $stat["flags"];
         $output->from = isset($message->headers["from"]) ? $message->headers["from"] : null;
         /* BEGIN fmbiete's contribution r1528, ZP-320 */
         if (isset($message->headers["thread-topic"])) {
             $output->threadtopic = $message->headers["thread-topic"];
             /*
             //FIXME: Conversation support, get conversationid and conversationindex good values
             if (Request::GetProtocolVersion() >= 14.0) {
                 // since the conversationid must be unique for a thread we could use the threadtopic in base64 minus the ==
                 $output->conversationid = strtoupper(str_replace("=", "", base64_encode($output->threadtopic)));
                 if (isset($message->headers["thread-index"]))
                     $output->conversationindex = strtoupper($message->headers["thread-index"]);
             }
             */
         } else {
             $output->threadtopic = $output->subject;
         }
         // Language Code Page ID: http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx
         $output->internetcpid = INTERNET_CPID_UTF8;
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->contentclass = "urn:content-classes:message";
             $output->flag = new SyncMailFlags();
             if (isset($stat["star"]) && $stat["star"]) {
                 //flagstatus 0: clear, 1: complete, 2: active
                 $output->flag->flagstatus = SYNC_FLAGSTATUS_ACTIVE;
                 //flagtype: for follow up
                 $output->flag->flagtype = "FollowUp";
             } else {
                 $output->flag->flagstatus = SYNC_FLAGSTATUS_CLEAR;
             }
         }
         /* END fmbiete's contribution r1528, ZP-320 */
         $Mail_RFC822 = new Mail_RFC822();
         $toaddr = $ccaddr = $replytoaddr = array();
         if (isset($message->headers["to"])) {
             $toaddr = $Mail_RFC822->parseAddressList($message->headers["to"]);
         }
         if (isset($message->headers["cc"])) {
             $ccaddr = $Mail_RFC822->parseAddressList($message->headers["cc"]);
         }
         if (isset($message->headers["reply-to"])) {
             $replytoaddr = $Mail_RFC822->parseAddressList($message->headers["reply-to"]);
         }
         $output->to = array();
         $output->cc = array();
         $output->reply_to = array();
         foreach (array("to" => $toaddr, "cc" => $ccaddr, "reply_to" => $replytoaddr) as $type => $addrlist) {
             if ($addrlist === false) {
                 //If we couldn't parse the addresslist we put the raw header (decoded)
                 if ($type == "reply_to") {
                     array_push($output->{$type}, $message->headers["reply-to"]);
                 } else {
                     array_push($output->{$type}, $message->headers[$type]);
                 }
             } else {
                 foreach ($addrlist as $addr) {
                     // If the address was a group we have "groupname" and "addresses" atributes
                     if (isset($addr->addresses)) {
                         if (count($addr->addresses) == 0) {
                             // readd the empty group delimiter
                             array_push($output->{$type}, sprintf("%s:;", $addr->groupname));
                             if (!isset($output->displayto) && strlen($addr->groupname) > 0) {
                                 $output->displayto = $addr->groupname;
                             }
                         } else {
                             foreach ($addr->addresses as $addr_group) {
                                 $name = $this->add_address_to_list($output->{$type}, $addr_group);
                                 if (!isset($output->displayto) && strlen($name) > 0) {
                                     $output->displayto = $name;
                                 }
                             }
                         }
                     } else {
                         // Not a group
                         $name = $this->add_address_to_list($output->{$type}, $addr);
                         if (!isset($output->displayto) && strlen($name) > 0) {
                             $output->displayto = $name;
                         }
                     }
                 }
             }
         }
         // convert mime-importance to AS-importance
         if (isset($message->headers["x-priority"])) {
             $mimeImportance = preg_replace("/\\D+/", "", $message->headers["x-priority"]);
             //MAIL 1 - most important, 3 - normal, 5 - lowest
             //AS 0 - low, 1 - normal, 2 - important
             if ($mimeImportance > 3) {
                 $output->importance = 0;
             } elseif ($mimeImportance == 3) {
                 $output->importance = 1;
             } elseif ($mimeImportance < 3) {
                 $output->importance = 2;
             }
         } else {
             /* fmbiete's contribution r1528, ZP-320 */
             $output->importance = 1;
         }
         // Attachments are also needed for MIME messages
         if (isset($message->parts)) {
             $mparts = $message->parts;
             for ($i = 0; $i < count($mparts); $i++) {
                 $part = $mparts[$i];
                 //recursively add parts
                 if (isset($part->ctype_primary) && $part->ctype_primary == "multipart" && (isset($part->ctype_secondary) && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related"))) {
                     foreach ($part->parts as $spart) {
                         $mparts[] = $spart;
                     }
                     continue;
                 }
                 if (is_calendar($part)) {
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): text/calendar part found, trying to convert"));
                     $output->meetingrequest = new SyncMeetingRequest();
                     $this->parseMeetingCalendar($part, $output);
                 } else {
                     //add part as attachment if it's disposition indicates so or if it is not a text part
                     if (isset($part->disposition) && ($part->disposition == "attachment" || $part->disposition == "inline") || isset($part->ctype_primary) && $part->ctype_primary != "text") {
                         if (isset($part->d_parameters['filename'])) {
                             $attname = $part->d_parameters['filename'];
                         } else {
                             if (isset($part->ctype_parameters['name'])) {
                                 $attname = $part->ctype_parameters['name'];
                             } else {
                                 if (isset($part->headers['content-description'])) {
                                     $attname = $part->headers['content-description'];
                                 } else {
                                     $attname = "unknown attachment";
                                 }
                             }
                         }
                         /* BEGIN fmbiete's contribution r1528, ZP-320 */
                         if (Request::GetProtocolVersion() >= 12.0) {
                             if (!isset($output->asattachments) || !is_array($output->asattachments)) {
                                 $output->asattachments = array();
                             }
                             $attachment = new SyncBaseAttachment();
                             $attachment->estimatedDataSize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                             $attachment->displayname = $attname;
                             $attachment->filereference = $folderid . ":" . $id . ":" . $i;
                             $attachment->method = 1;
                             //Normal attachment
                             $attachment->contentid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                             if (isset($part->disposition) && $part->disposition == "inline") {
                                 $attachment->isinline = 1;
                                 // #209 - KD 2015-06-16 If we got a filename use it, otherwise guess
                                 if (!isset($part->filename)) {
                                     // We try to fix the name for the inline file.
                                     // FIXME: This is a dirty hack as the used in the Zarafa backend, if you have a better method let me know!
                                     if (isset($part->ctype_primary) && isset($part->ctype_secondary)) {
                                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): Guessing extension for inline attachment [primary_type %s secondary_type %s]", $part->ctype_primary, $part->ctype_secondary));
                                         if (isset(BackendIMAP::$mimeTypes[$part->ctype_primary . '/' . $part->ctype_secondary])) {
                                             ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): primary_type %s secondary_type %s", $part->ctype_primary, $part->ctype_secondary));
                                             $attachment->displayname = "inline_" . $i . "." . BackendIMAP::$mimeTypes[$part->ctype_primary . '/' . $part->ctype_secondary];
                                         } else {
                                             ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): no extension found in '%s'!!", SYSTEM_MIME_TYPES_MAPPING));
                                         }
                                     } else {
                                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage(): no primary_type or secondary_type"));
                                     }
                                 }
                             } else {
                                 $attachment->isinline = 0;
                             }
                             array_push($output->asattachments, $attachment);
                         } else {
                             //ASV_2.5
                             if (!isset($output->attachments) || !is_array($output->attachments)) {
                                 $output->attachments = array();
                             }
                             $attachment = new SyncAttachment();
                             $attachment->attsize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                             $attachment->displayname = $attname;
                             $attachment->attname = $folderid . ":" . $id . ":" . $i;
                             $attachment->attmethod = 1;
                             $attachment->attoid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                             array_push($output->attachments, $attachment);
                         }
                         /* END fmbiete's contribution r1528, ZP-320 */
                     }
                 }
             }
         }
         unset($message);
         unset($mobj);
         unset($mail);
         return $output;
     }
     return false;
 }
Example #22
0
 /**
  * Converts the vCard into SyncContact
  *
  * @param string        $data           string with the vcard
  * @param int           $truncsize      truncate size requested
  * @return SyncContact
  */
 private function ParseFromVCard($data, $truncsize = -1)
 {
     ZLog::Write(LOGLEVEL_WBXML, sprintf("BackendCardDAV->ParseFromVCard : vCard\n%s\n", $data));
     $types = array('dom' => 'type', 'intl' => 'type', 'postal' => 'type', 'parcel' => 'type', 'home' => 'type', 'work' => 'type', 'pref' => 'type', 'voice' => 'type', 'fax' => 'type', 'msg' => 'type', 'cell' => 'type', 'pager' => 'type', 'bbs' => 'type', 'modem' => 'type', 'car' => 'type', 'isdn' => 'type', 'video' => 'type', 'aol' => 'type', 'applelink' => 'type', 'attmail' => 'type', 'cis' => 'type', 'eworld' => 'type', 'internet' => 'type', 'ibmmail' => 'type', 'mcimail' => 'type', 'powershare' => 'type', 'prodigy' => 'type', 'tlx' => 'type', 'x400' => 'type', 'gif' => 'type', 'cgm' => 'type', 'wmf' => 'type', 'bmp' => 'type', 'met' => 'type', 'pmb' => 'type', 'dib' => 'type', 'pict' => 'type', 'tiff' => 'type', 'pdf' => 'type', 'ps' => 'type', 'jpeg' => 'type', 'qtime' => 'type', 'mpeg' => 'type', 'mpeg2' => 'type', 'avi' => 'type', 'wave' => 'type', 'aiff' => 'type', 'pcm' => 'type', 'x509' => 'type', 'pgp' => 'type', 'text' => 'value', 'inline' => 'value', 'url' => 'value', 'cid' => 'value', 'content-id' => 'value', '7bit' => 'encoding', '8bit' => 'encoding', 'quoted-printable' => 'encoding', 'base64' => 'encoding');
     // Parse the vcard
     $message = new SyncContact();
     $data = str_replace("", '', $data);
     $data = str_replace("\r\n", "\n", $data);
     $data = str_replace("\r", "\n", $data);
     $data = preg_replace('/(\\n)([ \\t])/i', '', $data);
     $lines = explode("\n", $data);
     $vcard = array();
     foreach ($lines as $line) {
         if (trim($line) == '') {
             continue;
         }
         $pos = strpos($line, ':');
         if ($pos === false) {
             continue;
         }
         $field = trim(substr($line, 0, $pos));
         $value = trim(substr($line, $pos + 1));
         $fieldparts = preg_split('/(?<!\\\\)(\\;)/i', $field, -1, PREG_SPLIT_NO_EMPTY);
         $type = strtolower(array_shift($fieldparts));
         $fieldvalue = array();
         foreach ($fieldparts as $fieldpart) {
             if (preg_match('/([^=]+)=(.+)/', $fieldpart, $matches)) {
                 if (!in_array(strtolower($matches[1]), array('value', 'type', 'encoding', 'language'))) {
                     continue;
                 }
                 if (isset($fieldvalue[strtolower($matches[1])]) && is_array($fieldvalue[strtolower($matches[1])])) {
                     if (strtolower($matches[1]) == 'type') {
                         $fieldvalue[strtolower($matches[1])] = array_merge($fieldvalue[strtolower($matches[1])], array_map('strtolower', preg_split('/(?<!\\\\)(\\,)/i', $matches[2], -1, PREG_SPLIT_NO_EMPTY)));
                     } else {
                         $fieldvalue[strtolower($matches[1])] = array_merge($fieldvalue[strtolower($matches[1])], preg_split('/(?<!\\\\)(\\,)/i', $matches[2], -1, PREG_SPLIT_NO_EMPTY));
                     }
                 } else {
                     if (strtolower($matches[1]) == 'type') {
                         $fieldvalue[strtolower($matches[1])] = array_map('strtolower', preg_split('/(?<!\\\\)(\\,)/i', $matches[2], -1, PREG_SPLIT_NO_EMPTY));
                     } else {
                         $fieldvalue[strtolower($matches[1])] = preg_split('/(?<!\\\\)(\\,)/i', $matches[2], -1, PREG_SPLIT_NO_EMPTY);
                     }
                 }
             } else {
                 if (!isset($types[strtolower($fieldpart)])) {
                     continue;
                 }
                 $fieldvalue[$types[strtolower($fieldpart)]][] = $fieldpart;
             }
         }
         //
         switch ($type) {
             case 'categories':
                 //case 'nickname':
                 $val = preg_split('/(\\s)*(\\\\)?\\,(\\s)*/i', $value);
                 break;
             default:
                 $val = preg_split('/(?<!\\\\)(\\;)/i', $value);
                 break;
         }
         if (isset($fieldvalue['encoding'][0])) {
             switch (strtolower($fieldvalue['encoding'][0])) {
                 case 'q':
                 case 'quoted-printable':
                     foreach ($val as $i => $v) {
                         $val[$i] = quoted_printable_decode($v);
                     }
                     break;
                 case 'b':
                 case 'base64':
                     foreach ($val as $i => $v) {
                         $val[$i] = base64_decode($v);
                     }
                     break;
             }
         } else {
             foreach ($val as $i => $v) {
                 $val[$i] = $this->unescape($v);
             }
         }
         $fieldvalue['val'] = $val;
         $vcard[$type][] = $fieldvalue;
     }
     if (isset($vcard['email'][0]['val'][0])) {
         $message->email1address = $vcard['email'][0]['val'][0];
     }
     if (isset($vcard['email'][1]['val'][0])) {
         $message->email2address = $vcard['email'][1]['val'][0];
     }
     if (isset($vcard['email'][2]['val'][0])) {
         $message->email3address = $vcard['email'][2]['val'][0];
     }
     if (isset($vcard['tel'])) {
         foreach ($vcard['tel'] as $tel) {
             if (!isset($tel['type'])) {
                 $tel['type'] = array();
             }
             if (in_array('car', $tel['type'])) {
                 $message->carphonenumber = $tel['val'][0];
             } elseif (in_array('pager', $tel['type'])) {
                 $message->pagernumber = $tel['val'][0];
             } elseif (in_array('cell', $tel['type'])) {
                 $message->mobilephonenumber = $tel['val'][0];
             } elseif (in_array('home', $tel['type'])) {
                 if (in_array('fax', $tel['type'])) {
                     $message->homefaxnumber = $tel['val'][0];
                 } elseif (empty($message->homephonenumber)) {
                     $message->homephonenumber = $tel['val'][0];
                 } else {
                     $message->home2phonenumber = $tel['val'][0];
                 }
             } elseif (in_array('work', $tel['type'])) {
                 if (in_array('fax', $tel['type'])) {
                     $message->businessfaxnumber = $tel['val'][0];
                 } elseif (empty($message->businessphonenumber)) {
                     $message->businessphonenumber = $tel['val'][0];
                 } else {
                     $message->business2phonenumber = $tel['val'][0];
                 }
             } elseif (empty($message->homephonenumber)) {
                 $message->homephonenumber = $tel['val'][0];
             } elseif (empty($message->home2phonenumber)) {
                 $message->home2phonenumber = $tel['val'][0];
             } else {
                 $message->radiophonenumber = $tel['val'][0];
             }
         }
     }
     //;;street;city;state;postalcode;country
     if (isset($vcard['adr'])) {
         foreach ($vcard['adr'] as $adr) {
             if (empty($adr['type'])) {
                 $a = 'other';
             } elseif (in_array('home', $adr['type'])) {
                 $a = 'home';
             } elseif (in_array('work', $adr['type'])) {
                 $a = 'business';
             } else {
                 $a = 'other';
             }
             if (!empty($adr['val'][2])) {
                 $b = $a . 'street';
                 $message->{$b} = $adr['val'][2];
             }
             if (!empty($adr['val'][3])) {
                 $b = $a . 'city';
                 $message->{$b} = $adr['val'][3];
             }
             if (!empty($adr['val'][4])) {
                 $b = $a . 'state';
                 $message->{$b} = $adr['val'][4];
             }
             if (!empty($adr['val'][5])) {
                 $b = $a . 'postalcode';
                 $message->{$b} = $adr['val'][5];
             }
             if (!empty($adr['val'][6])) {
                 $b = $a . 'country';
                 $message->{$b} = $adr['val'][6];
             }
         }
     }
     if (!empty($vcard['fn'][0]['val'][0])) {
         $message->fileas = $vcard['fn'][0]['val'][0];
     }
     if (!empty($vcard['n'][0]['val'][0])) {
         $message->lastname = $vcard['n'][0]['val'][0];
     }
     if (!empty($vcard['n'][0]['val'][1])) {
         $message->firstname = $vcard['n'][0]['val'][1];
     }
     if (!empty($vcard['n'][0]['val'][2])) {
         $message->middlename = $vcard['n'][0]['val'][2];
     }
     if (!empty($vcard['n'][0]['val'][3])) {
         $message->title = $vcard['n'][0]['val'][3];
     }
     if (!empty($vcard['n'][0]['val'][4])) {
         $message->suffix = $vcard['n'][0]['val'][4];
     }
     if (!empty($vcard['nickname'][0]['val'][0])) {
         $message->nickname = $vcard['nickname'][0]['val'][0];
     }
     if (!empty($vcard['bday'][0]['val'][0])) {
         $tz = date_default_timezone_get();
         date_default_timezone_set('UTC');
         $message->birthday = strtotime($vcard['bday'][0]['val'][0]);
         date_default_timezone_set($tz);
     }
     if (!empty($vcard['org'][0]['val'][0])) {
         $message->companyname = $vcard['org'][0]['val'][0];
     }
     if (!empty($vcard['note'][0]['val'][0])) {
         if (Request::GetProtocolVersion() >= 12.0) {
             $message->asbody = new SyncBaseBody();
             $message->asbody->type = SYNC_BODYPREFERENCE_PLAIN;
             $message->asbody->data = $vcard['note'][0]['val'][0];
             if ($truncsize > 0 && $truncsize < strlen($message->asbody->data)) {
                 $message->asbody->truncated = 1;
                 $message->asbody->data = Utils::Utf8_truncate($message->asbody->data, $truncsize);
             } else {
                 $message->asbody->truncated = 0;
             }
             $message->asbody->estimatedDataSize = strlen($message->asbody->data);
         } else {
             $message->body = $vcard['note'][0]['val'][0];
             if ($truncsize > 0 && $truncsize < strlen($message->body)) {
                 $message->bodytruncated = 1;
                 $message->body = Utils::Utf8_truncate($message->body, $truncsize);
             } else {
                 $message->bodytruncated = 0;
             }
             $message->bodysize = strlen($message->body);
         }
     }
     if (!empty($vcard['role'][0]['val'][0])) {
         $message->jobtitle = $vcard['role'][0]['val'][0];
     }
     //$vcard['title'][0]['val'][0]
     if (!empty($vcard['url'][0]['val'][0])) {
         $message->webpage = $vcard['url'][0]['val'][0];
     }
     if (!empty($vcard['categories'][0]['val'])) {
         $message->categories = $vcard['categories'][0]['val'];
     }
     if (!empty($vcard['photo'][0]['val'][0])) {
         $message->picture = base64_encode($vcard['photo'][0]['val'][0]);
     }
     return $message;
 }
Example #23
0
 /**
  * Returns the actual SyncXXX object type.
  *
  * @param string            $folderid           id of the parent folder
  * @param string            $id                 id of the message
  * @param ContentParameters $contentparameters  parameters of the requested message (truncation, mimesupport etc)
  *
  * @access public
  * @return object/false     false if the message could not be retrieved
  */
 public function GetMessage($folderid, $id, $contentparameters)
 {
     $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
     $mimesupport = $contentparameters->GetMimeSupport();
     $bodypreference = $contentparameters->GetBodyPreference();
     /* fmbiete's contribution r1528, ZP-320 */
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage('%s','%s')", $folderid, $id));
     $folderImapid = $this->getImapIdFromFolderId($folderid);
     // Get flags, etc
     $stat = $this->StatMessage($folderid, $id);
     if ($stat) {
         $this->imap_reopen_folder($folderImapid);
         $mail = @imap_fetchheader($this->mbox, $id, FT_UID) . @imap_body($this->mbox, $id, FT_PEEK | FT_UID);
         if (empty($mail)) {
             throw new StatusException(sprintf("BackendIMAP->GetMessage(): Error, message not found, maybe was moved"), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);
         }
         $mobj = new Mail_mimeDecode($mail);
         $message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'charset' => 'utf-8'));
         /* BEGIN fmbiete's contribution r1528, ZP-320 */
         $output = new SyncMail();
         //Select body type preference
         $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
         if ($bodypreference !== false) {
             $bpReturnType = Utils::GetBodyPreferenceBestMatch($bodypreference);
             // changed by mku ZP-330
         }
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - getBodyPreferenceBestMatch: %d", $bpReturnType));
         if (is_smime($message)) {
             ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - Message is SMIME, forcing to work with MIME"));
             $bpReturnType = SYNC_BODYPREFERENCE_MIME;
         }
         //Get body data
         Mail_mimeDecode::getBodyRecursive($message, "plain", $plainBody);
         Mail_mimeDecode::getBodyRecursive($message, "html", $htmlBody);
         if ($plainBody == "") {
             $plainBody = Utils::ConvertHtmlToText($htmlBody);
         }
         $htmlBody = str_replace("\n", "\r\n", str_replace("\r", "", $htmlBody));
         $plainBody = str_replace("\n", "\r\n", str_replace("\r", "", $plainBody));
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->asbody = new SyncBaseBody();
             switch ($bpReturnType) {
                 case SYNC_BODYPREFERENCE_PLAIN:
                     $output->asbody->data = $plainBody;
                     break;
                 case SYNC_BODYPREFERENCE_HTML:
                     if ($htmlBody == "") {
                         $output->asbody->data = $plainBody;
                         $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
                     } else {
                         $output->asbody->data = $htmlBody;
                     }
                     break;
                 case SYNC_BODYPREFERENCE_MIME:
                     if (is_smime($message)) {
                         $output->asbody->data = $mail;
                     } else {
                         $output->asbody->data = build_mime_message($message);
                     }
                     break;
                 case SYNC_BODYPREFERENCE_RTF:
                     ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->GetMessage RTF Format NOT CHECKED");
                     $output->asbody->data = base64_encode($plainBody);
                     break;
             }
             // truncate body, if requested, but never truncate MIME messages
             if ($bpReturnType !== SYNC_BODYPREFERENCE_MIME && strlen($output->asbody->data) > $truncsize) {
                 $output->asbody->data = Utils::Utf8_truncate($output->asbody->data, $truncsize);
                 $output->asbody->truncated = 1;
             } else {
                 $output->asbody->truncated = 0;
             }
             $output->asbody->type = $bpReturnType;
             if ($bpReturnType == SYNC_BODYPREFERENCE_MIME) {
                 $output->nativebodytype = SYNC_BODYPREFERENCE_PLAIN;
                 // http://msdn.microsoft.com/en-us/library/ee220018%28v=exchg.80%29.aspx
             } else {
                 $output->nativebodytype = $bpReturnType;
             }
             $output->asbody->estimatedDataSize = strlen($output->asbody->data);
             $bpo = $contentparameters->BodyPreference($output->asbody->type);
             if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) {
                 $output->asbody->preview = Utils::Utf8_truncate(Utils::ConvertHtmlToText($plainBody), $bpo->GetPreview());
             }
         } else {
             // ASV_2.5
             $output->bodytruncated = 0;
             /* BEGIN fmbiete's contribution r1528, ZP-320 */
             if ($bpReturnType == SYNC_BODYPREFERENCE_MIME) {
                 // truncate body, if requested, but never truncate MIME messages
                 $output->mimetruncated = 0;
                 $output->mimedata = $mail;
                 $output->mimesize = strlen($output->mimedata);
             } else {
                 // truncate body, if requested
                 if (strlen($plainBody) > $truncsize) {
                     $output->body = Utils::Utf8_truncate($plainBody, $truncsize);
                     $output->bodytruncated = 1;
                 } else {
                     $output->body = $plainBody;
                     $output->bodytruncated = 0;
                 }
                 $output->bodysize = strlen($output->body);
             }
             /* END fmbiete's contribution r1528, ZP-320 */
         }
         $output->datereceived = isset($message->headers["date"]) ? $this->cleanupDate($message->headers["date"]) : null;
         if (is_smime($message)) {
             $output->messageclass = "IPM.Note.SMIME.MultipartSigned";
         } else {
             $output->messageclass = "IPM.Note";
         }
         $output->subject = isset($message->headers["subject"]) ? $message->headers["subject"] : "";
         $output->read = $stat["flags"];
         $output->from = isset($message->headers["from"]) ? $message->headers["from"] : null;
         /* BEGIN fmbiete's contribution r1528, ZP-320 */
         if (isset($message->headers["thread-topic"])) {
             $output->threadtopic = $message->headers["thread-topic"];
             /*
             //FIXME: Conversation support, get conversationid and conversationindex good values
             if (Request::GetProtocolVersion() >= 14.0) {
                 // since the conversationid must be unique for a thread we could use the threadtopic in base64 minus the ==
                 $output->conversationid = strtoupper(str_replace("=", "", base64_encode($output->threadtopic)));
                 if (isset($message->headers["thread-index"]))
                     $output->conversationindex = strtoupper($message->headers["thread-index"]);
             }
             */
         } else {
             $output->threadtopic = $output->subject;
         }
         // Language Code Page ID: http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx
         $output->internetcpid = INTERNET_CPID_UTF8;
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->contentclass = "urn:content-classes:message";
             $output->flag = new SyncMailFlags();
             if (isset($stat["star"]) && $stat["star"]) {
                 //flagstatus 0: clear, 1: complete, 2: active
                 $output->flag->flagstatus = SYNC_FLAGSTATUS_ACTIVE;
                 //flagtype: for follow up
                 $output->flag->flagtype = "FollowUp";
             } else {
                 $output->flag->flagstatus = SYNC_FLAGSTATUS_CLEAR;
             }
         }
         /* END fmbiete's contribution r1528, ZP-320 */
         $Mail_RFC822 = new Mail_RFC822();
         $toaddr = $ccaddr = $replytoaddr = array();
         if (isset($message->headers["to"])) {
             $toaddr = $Mail_RFC822->parseAddressList($message->headers["to"]);
         }
         if (isset($message->headers["cc"])) {
             $ccaddr = $Mail_RFC822->parseAddressList($message->headers["cc"]);
         }
         if (isset($message->headers["reply-to"])) {
             $replytoaddr = $Mail_RFC822->parseAddressList($message->headers["reply-to"]);
         }
         $output->to = array();
         $output->cc = array();
         $output->reply_to = array();
         foreach (array("to" => $toaddr, "cc" => $ccaddr, "reply_to" => $replytoaddr) as $type => $addrlist) {
             if ($addrlist === false) {
                 //If we couldn't parse the addresslist we put the raw header (decoded)
                 if ($type == "reply_to") {
                     array_push($output->{$type}, $message->headers["reply-to"]);
                 } else {
                     array_push($output->{$type}, $message->headers[$type]);
                 }
             } else {
                 foreach ($addrlist as $addr) {
                     if (isset($addr->mailbox) && isset($addr->host) && isset($addr->personal)) {
                         $address = $addr->mailbox . "@" . $addr->host;
                         $name = $addr->personal;
                         if (!isset($output->displayto) && $name != "") {
                             $output->displayto = $name;
                         }
                         if ($name == "" || $name == $address) {
                             $fulladdr = $address;
                         } else {
                             if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') {
                                 $fulladdr = "\"" . $name . "\" <" . $address . ">";
                             } else {
                                 $fulladdr = $name . " <" . $address . ">";
                             }
                         }
                         array_push($output->{$type}, $fulladdr);
                     }
                 }
             }
         }
         // convert mime-importance to AS-importance
         if (isset($message->headers["x-priority"])) {
             $mimeImportance = preg_replace("/\\D+/", "", $message->headers["x-priority"]);
             //MAIL 1 - most important, 3 - normal, 5 - lowest
             //AS 0 - low, 1 - normal, 2 - important
             if ($mimeImportance > 3) {
                 $output->importance = 0;
             } elseif ($mimeImportance == 3) {
                 $output->importance = 1;
             } elseif ($mimeImportance < 3) {
                 $output->importance = 2;
             }
         } else {
             /* fmbiete's contribution r1528, ZP-320 */
             $output->importance = 1;
         }
         // Attachments are also needed for MIME messages
         if (isset($message->parts)) {
             $mparts = $message->parts;
             for ($i = 0; $i < count($mparts); $i++) {
                 $part = $mparts[$i];
                 //recursively add parts
                 if (isset($part->ctype_primary) && $part->ctype_primary == "multipart" && (isset($part->ctype_secondary) && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related"))) {
                     foreach ($part->parts as $spart) {
                         $mparts[] = $spart;
                     }
                     continue;
                 }
                 if (is_calendar($part)) {
                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - text/calendar part found, trying to convert"));
                     $output->meetingrequest = new SyncMeetingRequest();
                     $this->parseMeetingCalendar($part, $output);
                 } else {
                     //add part as attachment if it's disposition indicates so or if it is not a text part
                     if (isset($part->disposition) && ($part->disposition == "attachment" || $part->disposition == "inline") || isset($part->ctype_primary) && $part->ctype_primary != "text") {
                         if (isset($part->d_parameters['filename'])) {
                             $attname = $part->d_parameters['filename'];
                         } else {
                             if (isset($part->ctype_parameters['name'])) {
                                 $attname = $part->ctype_parameters['name'];
                             } else {
                                 if (isset($part->headers['content-description'])) {
                                     $attname = $part->headers['content-description'];
                                 } else {
                                     $attname = "unknown attachment";
                                 }
                             }
                         }
                         /* BEGIN fmbiete's contribution r1528, ZP-320 */
                         if (Request::GetProtocolVersion() >= 12.0) {
                             if (!isset($output->asattachments) || !is_array($output->asattachments)) {
                                 $output->asattachments = array();
                             }
                             $attachment = new SyncBaseAttachment();
                             $attachment->estimatedDataSize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                             $attachment->displayname = $attname;
                             $attachment->filereference = $folderid . ":" . $id . ":" . $i;
                             $attachment->method = 1;
                             //Normal attachment
                             $attachment->contentid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                             if (isset($part->disposition) && $part->disposition == "inline") {
                                 $attachment->isinline = 1;
                                 // We try to fix the name for the inline file.
                                 // FIXME: This is a dirty hack as the used in the Zarafa backend, if you have a better method let me know!
                                 if (isset($part->ctype_primary) && isset($part->ctype_secondary)) {
                                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - Guessing extension for inline attachment [primary_type %s secondary_type %s]", $part->ctype_primary, $part->ctype_secondary));
                                     if (isset(BackendIMAP::$mimeTypes[$part->ctype_primary . '/' . $part->ctype_secondary])) {
                                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - primary_type %s secondary_type %s", $part->ctype_primary, $part->ctype_secondary));
                                         $attachment->displayname = "inline_" . $i . "." . BackendIMAP::$mimeTypes[$part->ctype_primary . '/' . $part->ctype_secondary];
                                     } else {
                                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - no extension found in /etc/mime.types'!!"));
                                     }
                                 } else {
                                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - no primary_type or secondary_type"));
                                 }
                             } else {
                                 $attachment->isinline = 0;
                             }
                             array_push($output->asattachments, $attachment);
                         } else {
                             //ASV_2.5
                             if (!isset($output->attachments) || !is_array($output->attachments)) {
                                 $output->attachments = array();
                             }
                             $attachment = new SyncAttachment();
                             $attachment->attsize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                             $attachment->displayname = $attname;
                             $attachment->attname = $folderid . ":" . $id . ":" . $i;
                             $attachment->attmethod = 1;
                             $attachment->attoid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                             array_push($output->attachments, $attachment);
                         }
                         /* END fmbiete's contribution r1528, ZP-320 */
                     }
                 }
             }
         }
         // unset mimedecoder & mail
         unset($mobj);
         unset($mail);
         return $output;
     }
     return false;
 }
Example #24
0
 /**
  * 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;
 }
Example #25
0
 /**
  * Returns a SyncObject class name for a folder class
  *
  * @param string $folderclass
  *
  * @access public
  * @return string
  * @throws FatalNotImplementedException
  */
 public static function getSyncObjectFromFolderClass($folderclass)
 {
     if (!isset(self::$classes[$folderclass])) {
         throw new FatalNotImplementedException("Class '{$folderclass}' is not supported");
     }
     $class = self::$classes[$folderclass][self::CLASS_NAME];
     if (self::$classes[$folderclass][self::CLASS_REQUIRESPROTOCOLVERSION]) {
         return new $class(Request::GetProtocolVersion());
     } else {
         return new $class();
     }
 }
Example #26
0
 function __construct()
 {
     $mapping = array(SYNC_POOMCONTACTS_ANNIVERSARY => array(self::STREAMER_VAR => "anniversary", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES, self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_ASSISTANTNAME => array(self::STREAMER_VAR => "assistantname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_ASSISTNAMEPHONENUMBER => array(self::STREAMER_VAR => "assistnamephonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BIRTHDAY => array(self::STREAMER_VAR => "birthday", self::STREAMER_TYPE => self::STREAMER_TYPE_DATE_DASHES, self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BODY => array(self::STREAMER_VAR => "body", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BODYSIZE => array(self::STREAMER_VAR => "bodysize"), SYNC_POOMCONTACTS_BODYTRUNCATED => array(self::STREAMER_VAR => "bodytruncated"), SYNC_POOMCONTACTS_BUSINESS2PHONENUMBER => array(self::STREAMER_VAR => "business2phonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSCITY => array(self::STREAMER_VAR => "businesscity", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSCOUNTRY => array(self::STREAMER_VAR => "businesscountry", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSPOSTALCODE => array(self::STREAMER_VAR => "businesspostalcode", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSSTATE => array(self::STREAMER_VAR => "businessstate", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSSTREET => array(self::STREAMER_VAR => "businessstreet", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSFAXNUMBER => array(self::STREAMER_VAR => "businessfaxnumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_BUSINESSPHONENUMBER => array(self::STREAMER_VAR => "businessphonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_CARPHONENUMBER => array(self::STREAMER_VAR => "carphonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_CHILDREN => array(self::STREAMER_VAR => "children", self::STREAMER_ARRAY => SYNC_POOMCONTACTS_CHILD, self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_COMPANYNAME => array(self::STREAMER_VAR => "companyname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_DEPARTMENT => array(self::STREAMER_VAR => "department", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_EMAIL1ADDRESS => array(self::STREAMER_VAR => "email1address", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_EMAIL2ADDRESS => array(self::STREAMER_VAR => "email2address", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_EMAIL3ADDRESS => array(self::STREAMER_VAR => "email3address", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_FILEAS => array(self::STREAMER_VAR => "fileas", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_FIRSTNAME => array(self::STREAMER_VAR => "firstname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOME2PHONENUMBER => array(self::STREAMER_VAR => "home2phonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMECITY => array(self::STREAMER_VAR => "homecity", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMECOUNTRY => array(self::STREAMER_VAR => "homecountry", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMEPOSTALCODE => array(self::STREAMER_VAR => "homepostalcode", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMESTATE => array(self::STREAMER_VAR => "homestate", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMESTREET => array(self::STREAMER_VAR => "homestreet", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMEFAXNUMBER => array(self::STREAMER_VAR => "homefaxnumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_HOMEPHONENUMBER => array(self::STREAMER_VAR => "homephonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_JOBTITLE => array(self::STREAMER_VAR => "jobtitle", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_LASTNAME => array(self::STREAMER_VAR => "lastname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_MIDDLENAME => array(self::STREAMER_VAR => "middlename", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_MOBILEPHONENUMBER => array(self::STREAMER_VAR => "mobilephonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OFFICELOCATION => array(self::STREAMER_VAR => "officelocation", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OTHERCITY => array(self::STREAMER_VAR => "othercity", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OTHERCOUNTRY => array(self::STREAMER_VAR => "othercountry", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OTHERPOSTALCODE => array(self::STREAMER_VAR => "otherpostalcode", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OTHERSTATE => array(self::STREAMER_VAR => "otherstate", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_OTHERSTREET => array(self::STREAMER_VAR => "otherstreet", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_PAGERNUMBER => array(self::STREAMER_VAR => "pagernumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_RADIOPHONENUMBER => array(self::STREAMER_VAR => "radiophonenumber", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_SPOUSE => array(self::STREAMER_VAR => "spouse", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_SUFFIX => array(self::STREAMER_VAR => "suffix", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_TITLE => array(self::STREAMER_VAR => "title", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_WEBPAGE => array(self::STREAMER_VAR => "webpage", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_YOMICOMPANYNAME => array(self::STREAMER_VAR => "yomicompanyname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_YOMIFIRSTNAME => array(self::STREAMER_VAR => "yomifirstname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_YOMILASTNAME => array(self::STREAMER_VAR => "yomilastname", self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_RTF => array(self::STREAMER_VAR => "rtf"), SYNC_POOMCONTACTS_PICTURE => array(self::STREAMER_VAR => "picture", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_LENGTHMAX => SYNC_CONTACTS_MAXPICTURESIZE), self::STREAMER_RONOTIFY => true), SYNC_POOMCONTACTS_CATEGORIES => array(self::STREAMER_VAR => "categories", self::STREAMER_ARRAY => SYNC_POOMCONTACTS_CATEGORY, self::STREAMER_RONOTIFY => true));
     if (Request::GetProtocolVersion() >= 2.5) {
         $mapping[SYNC_POOMCONTACTS2_CUSTOMERID] = array(self::STREAMER_VAR => "customerid", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_GOVERNMENTID] = array(self::STREAMER_VAR => "governmentid", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_IMADDRESS] = array(self::STREAMER_VAR => "imaddress", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_IMADDRESS2] = array(self::STREAMER_VAR => "imaddress2", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_IMADDRESS3] = array(self::STREAMER_VAR => "imaddress3", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_MANAGERNAME] = array(self::STREAMER_VAR => "managername", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_COMPANYMAINPHONE] = array(self::STREAMER_VAR => "companymainphone", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_ACCOUNTNAME] = array(self::STREAMER_VAR => "accountname", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_NICKNAME] = array(self::STREAMER_VAR => "nickname", self::STREAMER_RONOTIFY => true);
         $mapping[SYNC_POOMCONTACTS2_MMS] = array(self::STREAMER_VAR => "mms", self::STREAMER_RONOTIFY => true);
     }
     if (Request::GetProtocolVersion() >= 12.0) {
         $mapping[SYNC_AIRSYNCBASE_BODY] = array(self::STREAMER_VAR => "asbody", self::STREAMER_TYPE => "SyncBaseBody", self::STREAMER_RONOTIFY => true);
         //unset these properties because airsyncbase body and attachments will be used instead
         unset($mapping[SYNC_POOMCONTACTS_BODY], $mapping[SYNC_POOMCONTACTS_BODYTRUNCATED]);
     }
     parent::__construct($mapping);
 }
Example #27
0
 /**
  * Parse 1 VEvent
  * @param ical_vevent $event
  * @param SyncAppointment(Exception) $message
  * @param int $truncsize
  */
 private function _ParseVEventToSyncObject($event, $message, $truncsize)
 {
     //Defaults
     $message->busystatus = "2";
     $properties = $event->GetProperties();
     foreach ($properties as $property) {
         switch ($property->Name()) {
             case "LAST-MODIFIED":
                 $message->dtstamp = Utils::MakeUTCDate($property->Value());
                 break;
             case "DTSTART":
                 $message->starttime = Utils::MakeUTCDate($property->Value(), Utils::ParseTimezone($property->GetParameterValue("TZID")));
                 if (strlen($property->Value()) == 8) {
                     $message->alldayevent = "1";
                 }
                 break;
             case "SUMMARY":
                 $message->subject = $property->Value();
                 break;
             case "UID":
                 $message->uid = $property->Value();
                 break;
             case "ORGANIZER":
                 $org_mail = str_ireplace("MAILTO:", "", $property->Value());
                 $message->organizeremail = $org_mail;
                 $org_cn = $property->GetParameterValue("CN");
                 if ($org_cn) {
                     $message->organizername = $org_cn;
                 }
                 break;
             case "LOCATION":
                 $message->location = $property->Value();
                 break;
             case "DTEND":
                 $message->endtime = Utils::MakeUTCDate($property->Value(), Utils::ParseTimezone($property->GetParameterValue("TZID")));
                 if (strlen($property->Value()) == 8) {
                     $message->alldayevent = "1";
                 }
                 break;
             case "DURATION":
                 if (!isset($message->endtime)) {
                     $start = date_create("@" . $message->starttime);
                     $val = str_replace("+", "", $property->Value());
                     $interval = new DateInterval($val);
                     $message->endtime = date_timestamp_get(date_add($start, $interval));
                 }
                 break;
             case "RRULE":
                 $message->recurrence = $this->_ParseRecurrence($property->Value(), "vevent");
                 break;
             case "CLASS":
                 switch ($property->Value()) {
                     case "PUBLIC":
                         $message->sensitivity = "0";
                         break;
                     case "PRIVATE":
                         $message->sensitivity = "2";
                         break;
                     case "CONFIDENTIAL":
                         $message->sensitivity = "3";
                         break;
                 }
                 break;
             case "TRANSP":
                 switch ($property->Value()) {
                     case "TRANSPARENT":
                         $message->busystatus = "0";
                         break;
                     case "OPAQUE":
                         $message->busystatus = "2";
                         break;
                 }
                 break;
                 // SYNC_POOMCAL_MEETINGSTATUS
                 // Meetingstatus values
                 //  0 = is not a meeting
                 //  1 = is a meeting
                 //  3 = Meeting received
                 //  5 = Meeting is canceled
                 //  7 = Meeting is canceled and received
                 //  9 = as 1
                 // 11 = as 3
                 // 13 = as 5
                 // 15 = as 7
             // SYNC_POOMCAL_MEETINGSTATUS
             // Meetingstatus values
             //  0 = is not a meeting
             //  1 = is a meeting
             //  3 = Meeting received
             //  5 = Meeting is canceled
             //  7 = Meeting is canceled and received
             //  9 = as 1
             // 11 = as 3
             // 13 = as 5
             // 15 = as 7
             case "STATUS":
                 switch ($property->Value()) {
                     case "TENTATIVE":
                         $message->meetingstatus = "3";
                         // was 1
                         break;
                     case "CONFIRMED":
                         $message->meetingstatus = "1";
                         // was 3
                         break;
                     case "CANCELLED":
                         $message->meetingstatus = "5";
                         // could also be 7
                         break;
                 }
                 break;
             case "ATTENDEE":
                 $attendee = new SyncAttendee();
                 $att_email = str_ireplace("MAILTO:", "", $property->Value());
                 $attendee->email = $att_email;
                 $att_cn = $property->GetParameterValue("CN");
                 if ($att_cn) {
                     $attendee->name = $att_cn;
                 }
                 if (isset($message->attendees) && is_array($message->attendees)) {
                     $message->attendees[] = $attendee;
                 } else {
                     $message->attendees = array($attendee);
                 }
                 break;
             case "DESCRIPTION":
                 if (Request::GetProtocolVersion() >= 12.0) {
                     $message->asbody = new SyncBaseBody();
                     $message->asbody->data = str_replace("\n", "\r\n", str_replace("\r", "", Utils::ConvertHtmlToText($property->Value())));
                     // truncate body, if requested
                     if (strlen($message->asbody->data) > $truncsize) {
                         $message->asbody->truncated = 1;
                         $message->asbody->data = Utils::Utf8_truncate($message->asbody->data, $truncsize);
                     } else {
                         $message->asbody->truncated = 0;
                     }
                     $message->nativebodytype = SYNC_BODYPREFERENCE_PLAIN;
                 } else {
                     $body = $property->Value();
                     // truncate body, if requested
                     if (strlen($body) > $truncsize) {
                         $body = Utils::Utf8_truncate($body, $truncsize);
                         $message->bodytruncated = 1;
                     } else {
                         $body = $body;
                         $message->bodytruncated = 0;
                     }
                     $body = str_replace("\n", "\r\n", str_replace("\r", "", $body));
                     $message->body = $body;
                 }
                 break;
             case "CATEGORIES":
                 $categories = explode(",", $property->Value());
                 $message->categories = $categories;
                 break;
             case "EXDATE":
                 $exception = new SyncAppointmentException();
                 $exception->deleted = "1";
                 $exception->exceptionstarttime = Utils::MakeUTCDate($property->Value());
                 if (!isset($message->exceptions)) {
                     $message->exceptions = array();
                 }
                 $message->exceptions[] = $exception;
                 break;
                 //We can ignore the following
             //We can ignore the following
             case "PRIORITY":
             case "SEQUENCE":
             case "CREATED":
             case "DTSTAMP":
             case "X-MOZ-GENERATION":
             case "X-MOZ-LASTACK":
             case "X-LIC-ERROR":
             case "RECURRENCE-ID":
                 break;
             default:
                 ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendCalDAV->_ParseVEventToSyncObject(): '%s' is not yet supported.", $property->Name()));
         }
     }
     $valarm = current($event->GetComponents("VALARM"));
     if ($valarm) {
         $properties = $valarm->GetProperties();
         foreach ($properties as $property) {
             if ($property->Name() == "TRIGGER") {
                 $parameters = $property->Parameters();
                 if (array_key_exists("VALUE", $parameters) && $parameters["VALUE"] == "DATE-TIME") {
                     $trigger = date_create("@" . Utils::MakeUTCDate($property->Value()));
                     $begin = date_create("@" . $message->starttime);
                     $interval = date_diff($begin, $trigger);
                     $message->reminder = $interval->format("%i") + $interval->format("%h") * 60 + $interval->format("%a") * 60 * 24;
                 } elseif (!array_key_exists("VALUE", $parameters) || $parameters["VALUE"] == "DURATION") {
                     $val = str_replace("-", "", $property->Value());
                     $interval = new DateInterval($val);
                     $message->reminder = $interval->format("%i") + $interval->format("%h") * 60 + $interval->format("%a") * 60 * 24;
                 }
             }
         }
     }
     return $message;
 }
Example #28
0
 /**
  * Returns the actual SyncXXX object type.
  *
  * @param string            $folderid           id of the parent folder
  * @param string            $id                 id of the message
  * @param ContentParameters $contentparameters  parameters of the requested message (truncation, mimesupport etc)
  *
  * @access public
  * @return object/false     false if the message could not be retrieved
  */
 public function GetMessage($folderid, $id, $contentparameters)
 {
     $truncsize = Utils::GetTruncSize($contentparameters->GetTruncation());
     $mimesupport = $contentparameters->GetMimeSupport();
     $bodypreference = $contentparameters->GetBodyPreference();
     /* fmbiete's contribution r1528, ZP-320 */
     ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage('%s','%s')", $folderid, $id));
     $folderImapid = $this->getImapIdFromFolderId($folderid);
     // Get flags, etc
     $stat = $this->StatMessage($folderid, $id);
     if ($stat) {
         $this->imap_reopenFolder($folderImapid);
         $mail = @imap_fetchheader($this->mbox, $id, FT_UID) . @imap_body($this->mbox, $id, FT_PEEK | FT_UID);
         $mobj = new Mail_mimeDecode($mail);
         $message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'charset' => 'utf-8'));
         /* BEGIN fmbiete's contribution r1528, ZP-320 */
         $output = new SyncMail();
         //Select body type preference
         $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
         if ($bodypreference !== false) {
             $bpReturnType = Utils::GetBodyPreferenceBestMatch($bodypreference);
             // changed by mku ZP-330
         }
         ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->GetMessage - getBodyPreferenceBestMatch: %d", $bpReturnType));
         //Get body data
         $this->getBodyRecursive($message, "plain", $plainBody);
         $this->getBodyRecursive($message, "html", $htmlBody);
         if ($plainBody == "") {
             $plainBody = Utils::ConvertHtmlToText($htmlBody);
         }
         $htmlBody = str_replace("\n", "\r\n", str_replace("\r", "", $htmlBody));
         $plainBody = str_replace("\n", "\r\n", str_replace("\r", "", $plainBody));
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->asbody = new SyncBaseBody();
             switch ($bpReturnType) {
                 case SYNC_BODYPREFERENCE_PLAIN:
                     $output->asbody->data = $plainBody;
                     break;
                 case SYNC_BODYPREFERENCE_HTML:
                     if ($htmlBody == "") {
                         $output->asbody->data = $plainBody;
                         $bpReturnType = SYNC_BODYPREFERENCE_PLAIN;
                     } else {
                         $output->asbody->data = $htmlBody;
                     }
                     break;
                 case SYNC_BODYPREFERENCE_MIME:
                     //We don't need to create a new MIME mail, we already have one!!
                     $output->asbody->data = $mail;
                     break;
                 case SYNC_BODYPREFERENCE_RTF:
                     ZLog::Write(LOGLEVEL_DEBUG, "BackendIMAP->GetMessage RTF Format NOT CHECKED");
                     $output->asbody->data = base64_encode($plainBody);
                     break;
             }
             // truncate body, if requested
             if (strlen($output->asbody->data) > $truncsize) {
                 $output->asbody->data = Utils::Utf8_truncate($output->asbody->data, $truncsize);
                 $output->asbody->truncated = 1;
             }
             $output->asbody->type = $bpReturnType;
             $output->nativebodytype = $bpReturnType;
             $output->asbody->estimatedDataSize = strlen($output->asbody->data);
             $bpo = $contentparameters->BodyPreference($output->asbody->type);
             if (Request::GetProtocolVersion() >= 14.0 && $bpo->GetPreview()) {
                 $output->asbody->preview = Utils::Utf8_truncate(Utils::ConvertHtmlToText($plainBody), $bpo->GetPreview());
             } else {
                 $output->asbody->truncated = 0;
             }
         } else {
             // ASV_2.5
             $output->bodytruncated = 0;
             /* BEGIN fmbiete's contribution r1528, ZP-320 */
             if ($bpReturnType == SYNC_BODYPREFERENCE_MIME) {
                 if (strlen($mail) > $truncsize) {
                     $output->mimedata = Utils::Utf8_truncate($mail, $truncsize);
                     $output->mimetruncated = 1;
                 } else {
                     $output->mimetruncated = 0;
                     $output->mimedata = $mail;
                 }
                 $output->mimesize = strlen($output->mimedata);
             } else {
                 // truncate body, if requested
                 if (strlen($plainBody) > $truncsize) {
                     $output->body = Utils::Utf8_truncate($plainBody, $truncsize);
                     $output->bodytruncated = 1;
                 } else {
                     $output->body = $plainBody;
                     $output->bodytruncated = 0;
                 }
                 $output->bodysize = strlen($output->body);
             }
             /* END fmbiete's contribution r1528, ZP-320 */
         }
         $output->datereceived = isset($message->headers["date"]) ? $this->cleanupDate($message->headers["date"]) : null;
         $output->messageclass = "IPM.Note";
         $output->subject = isset($message->headers["subject"]) ? $message->headers["subject"] : "";
         $output->read = $stat["flags"];
         $output->from = isset($message->headers["from"]) ? $message->headers["from"] : null;
         /* BEGIN fmbiete's contribution r1528, ZP-320 */
         if (isset($message->headers["thread-topic"])) {
             $output->threadtopic = $message->headers["thread-topic"];
         }
         // Language Code Page ID: http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756%28v=vs.85%29.aspx
         $output->internetcpid = INTERNET_CPID_UTF8;
         if (Request::GetProtocolVersion() >= 12.0) {
             $output->contentclass = "urn:content-classes:message";
         }
         /* END fmbiete's contribution r1528, ZP-320 */
         $Mail_RFC822 = new Mail_RFC822();
         $toaddr = $ccaddr = $replytoaddr = array();
         if (isset($message->headers["to"])) {
             $toaddr = $Mail_RFC822->parseAddressList($message->headers["to"]);
         }
         if (isset($message->headers["cc"])) {
             $ccaddr = $Mail_RFC822->parseAddressList($message->headers["cc"]);
         }
         if (isset($message->headers["reply_to"])) {
             $replytoaddr = $Mail_RFC822->parseAddressList($message->headers["reply_to"]);
         }
         $output->to = array();
         $output->cc = array();
         $output->reply_to = array();
         foreach (array("to" => $toaddr, "cc" => $ccaddr, "reply_to" => $replytoaddr) as $type => $addrlist) {
             foreach ($addrlist as $addr) {
                 $address = $addr->mailbox . "@" . $addr->host;
                 $name = $addr->personal;
                 if (!isset($output->displayto) && $name != "") {
                     $output->displayto = $name;
                 }
                 if ($name == "" || $name == $address) {
                     $fulladdr = w2u($address);
                 } else {
                     if (substr($name, 0, 1) != '"' && substr($name, -1) != '"') {
                         $fulladdr = "\"" . w2u($name) . "\" <" . w2u($address) . ">";
                     } else {
                         $fulladdr = w2u($name) . " <" . w2u($address) . ">";
                     }
                 }
                 array_push($output->{$type}, $fulladdr);
             }
         }
         // convert mime-importance to AS-importance
         if (isset($message->headers["x-priority"])) {
             $mimeImportance = preg_replace("/\\D+/", "", $message->headers["x-priority"]);
             //MAIL 1 - most important, 3 - normal, 5 - lowest
             //AS 0 - low, 1 - normal, 2 - important
             if ($mimeImportance > 3) {
                 $output->importance = 0;
             }
             if ($mimeImportance == 3) {
                 $output->importance = 1;
             }
             if ($mimeImportance < 3) {
                 $output->importance = 2;
             }
         } else {
             /* fmbiete's contribution r1528, ZP-320 */
             $output->importance = 1;
         }
         // Attachments are not needed for MIME messages
         if ($bpReturnType != SYNC_BODYPREFERENCE_MIME && isset($message->parts)) {
             $mparts = $message->parts;
             for ($i = 0; $i < count($mparts); $i++) {
                 $part = $mparts[$i];
                 //recursively add parts
                 if ($part->ctype_primary == "multipart" && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related")) {
                     foreach ($part->parts as $spart) {
                         $mparts[] = $spart;
                     }
                     continue;
                 }
                 //add part as attachment if it's disposition indicates so or if it is not a text part
                 if (isset($part->disposition) && ($part->disposition == "attachment" || $part->disposition == "inline") || isset($part->ctype_primary) && $part->ctype_primary != "text") {
                     if (isset($part->d_parameters['filename'])) {
                         $attname = $part->d_parameters['filename'];
                     } else {
                         if (isset($part->ctype_parameters['name'])) {
                             $attname = $part->ctype_parameters['name'];
                         } else {
                             if (isset($part->headers['content-description'])) {
                                 $attname = $part->headers['content-description'];
                             } else {
                                 $attname = "unknown attachment";
                             }
                         }
                     }
                     /* BEGIN fmbiete's contribution r1528, ZP-320 */
                     if (Request::GetProtocolVersion() >= 12.0) {
                         if (!isset($output->asattachments) || !is_array($output->asattachments)) {
                             $output->asattachments = array();
                         }
                         $attachment = new SyncBaseAttachment();
                         $attachment->estimatedDataSize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                         $attachment->displayname = $attname;
                         $attachment->filereference = $folderid . ":" . $id . ":" . $i;
                         $attachment->method = 1;
                         //Normal attachment
                         $attachment->contentid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                         if (isset($part->disposition) && $part->disposition == "inline") {
                             $attachment->isinline = 1;
                         } else {
                             $attachment->isinline = 0;
                         }
                         array_push($output->asattachments, $attachment);
                     } else {
                         //ASV_2.5
                         if (!isset($output->attachments) || !is_array($output->attachments)) {
                             $output->attachments = array();
                         }
                         $attachment = new SyncAttachment();
                         $attachment->attsize = isset($part->d_parameters['size']) ? $part->d_parameters['size'] : isset($part->body) ? strlen($part->body) : 0;
                         $attachment->displayname = $attname;
                         $attachment->attname = $folderid . ":" . $id . ":" . $i;
                         $attachment->attmethod = 1;
                         $attachment->attoid = isset($part->headers['content-id']) ? str_replace("<", "", str_replace(">", "", $part->headers['content-id'])) : "";
                         array_push($output->attachments, $attachment);
                     }
                     /* END fmbiete's contribution r1528, ZP-320 */
                 }
             }
         }
         // unset mimedecoder & mail
         unset($mobj);
         unset($mail);
         return $output;
     }
     return false;
 }
 /**
  * Sets properties for an email message
  *
  * @param mixed             $mapimessage
  * @param SyncMail          $message
  *
  * @access private
  * @return void
  */
 private function setFlag($mapimessage, &$message)
 {
     // do nothing if protocoll version is lower than 12.0 as flags haven't been defined before
     if (Request::GetProtocolVersion() < 12.0) {
         return;
     }
     $message->flag = new SyncMailFlags();
     $this->getPropsFromMAPI($message->flag, $mapimessage, MAPIMapping::GetMailFlagsMapping());
 }
 function SyncProvisioning()
 {
     $mapping = array(SYNC_PROVISION_DEVPWENABLED => array(self::STREAMER_VAR => "devpwenabled", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALPHANUMPWREQ => array(self::STREAMER_VAR => "alphanumpwreq", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_PWRECOVERYENABLED => array(self::STREAMER_VAR => "pwrecoveryenabled", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_DEVENCENABLED => array(self::STREAMER_VAR => "devencenabled", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_DOCBROWSEENABLED => array(self::STREAMER_VAR => "docbrowseenabled"), SYNC_PROVISION_ATTENABLED => array(self::STREAMER_VAR => "attenabled", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_MINDEVPWLENGTH => array(self::STREAMER_VAR => "mindevpwlenngth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 0, self::STREAMER_CHECK_CMPLOWER => 17)), SYNC_PROVISION_MAXINACTTIMEDEVLOCK => array(self::STREAMER_VAR => "maxinacttimedevlock"), SYNC_PROVISION_MAXDEVPWFAILEDATTEMPTS => array(self::STREAMER_VAR => "maxdevpwfailedattempts", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => 3, self::STREAMER_CHECK_CMPLOWER => 17)), SYNC_PROVISION_MAXATTSIZE => array(self::STREAMER_VAR => "maxattsize", self::STREAMER_PROP => self::STREAMER_TYPE_SEND_EMPTY, self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1)), SYNC_PROVISION_ALLOWSIMPLEDEVPW => array(self::STREAMER_VAR => "allowsimpledevpw", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_DEVPWEXPIRATION => array(self::STREAMER_VAR => "devpwexpiration", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1)), SYNC_PROVISION_DEVPWHISTORY => array(self::STREAMER_VAR => "devpwhistory", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1)));
     if (Request::GetProtocolVersion() >= 12.1) {
         $mapping += array(SYNC_PROVISION_ALLOWSTORAGECARD => array(self::STREAMER_VAR => "allostoragecard", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWCAM => array(self::STREAMER_VAR => "allowcam", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_REQDEVENC => array(self::STREAMER_VAR => "reqdevenc", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWUNSIGNEDAPPS => array(self::STREAMER_VAR => "allowunsignedapps", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWUNSIGNEDINSTALLATIONPACKAGES => array(self::STREAMER_VAR => "allowunsigninstallpacks", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_MINDEVPWCOMPLEXCHARS => array(self::STREAMER_VAR => "mindevcomplexchars", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(1, 2, 3, 4))), SYNC_PROVISION_ALLOWWIFI => array(self::STREAMER_VAR => "allowwifi", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWTEXTMESSAGING => array(self::STREAMER_VAR => "allowtextmessaging", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWPOPIMAPEMAIL => array(self::STREAMER_VAR => "allowpopimapemail", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWBLUETOOTH => array(self::STREAMER_VAR => "allowbluetooth", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2))), SYNC_PROVISION_ALLOWIRDA => array(self::STREAMER_VAR => "allowirda", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_REQMANUALSYNCWHENROAM => array(self::STREAMER_VAR => "reqmansyncroam", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWDESKTOPSYNC => array(self::STREAMER_VAR => "allowdesktopsync", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_MAXCALAGEFILTER => array(self::STREAMER_VAR => "maxcalagefilter", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 4, 5, 6, 7))), SYNC_PROVISION_ALLOWHTMLEMAIL => array(self::STREAMER_VAR => "allowhtmlemail", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_MAXEMAILAGEFILTER => array(self::STREAMER_VAR => "maxemailagefilter", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -1, self::STREAMER_CHECK_CMPLOWER => 6)), SYNC_PROVISION_MAXEMAILBODYTRUNCSIZE => array(self::STREAMER_VAR => "maxemailbodytruncsize", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -2)), SYNC_PROVISION_MAXEMAILHTMLBODYTRUNCSIZE => array(self::STREAMER_VAR => "maxemailhtmlbodytruncsize", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_CMPHIGHER => -2)), SYNC_PROVISION_REQSIGNEDSMIMEMESSAGES => array(self::STREAMER_VAR => "reqsignedsmimemessages", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_REQENCSMIMEMESSAGES => array(self::STREAMER_VAR => "reqencsmimemessages", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_REQSIGNEDSMIMEALGORITHM => array(self::STREAMER_VAR => "reqsignedsmimealgorithm", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_REQENCSMIMEALGORITHM => array(self::STREAMER_VAR => "reqencsmimealgorithm", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2, 3, 4))), SYNC_PROVISION_ALLOWSMIMEENCALGORITHNEG => array(self::STREAMER_VAR => "allowsmimeencalgneg", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1, 2))), SYNC_PROVISION_ALLOWSMIMESOFTCERTS => array(self::STREAMER_VAR => "allowsmimesoftcerts", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWBROWSER => array(self::STREAMER_VAR => "allowbrowser", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWCONSUMEREMAIL => array(self::STREAMER_VAR => "allowconsumeremail", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWREMOTEDESKTOP => array(self::STREAMER_VAR => "allowremotedesk", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_ALLOWINTERNETSHARING => array(self::STREAMER_VAR => "allowinternetsharing", self::STREAMER_CHECKS => array(self::STREAMER_CHECK_ONEVALUEOF => array(0, 1))), SYNC_PROVISION_UNAPPROVEDINROMAPPLIST => array(self::STREAMER_VAR => "unapprovedinromapplist", self::STREAMER_PROP => self::STREAMER_TYPE_SEND_EMPTY, self::STREAMER_ARRAY => SYNC_PROVISION_APPNAME), SYNC_PROVISION_APPROVEDAPPLIST => array(self::STREAMER_VAR => "approvedapplist", self::STREAMER_PROP => self::STREAMER_TYPE_SEND_EMPTY, self::STREAMER_ARRAY => SYNC_PROVISION_HASH));
     }
     parent::SyncObject($mapping);
 }