/** * Method checks if the object has the minimum of required parameters * and fullfills semantic dependencies * * This overloads the general check() with special checks to be executed * * @param boolean $logAsDebug (opt) default is false, so messages are logged in WARN log level * * @access public * @return boolean */ public function Check($logAsDebug = false) { $ret = parent::Check($logAsDebug); if (!$ret) { return false; } if (isset($this->start) && isset($this->until) && $this->until < $this->start) { ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter 'start' is HIGHER than 'until'. Check failed!", get_class($this))); return false; } return true; }
/** * Method checks if the object has the minimum of required parameters * and fullfills semantic dependencies * * This overloads the general check() with special checks to be executed * * @param boolean $logAsDebug (opt) default is false, so messages are logged in WARN log level * * @access public * @return boolean */ public function Check($logAsDebug = false) { $ret = parent::Check($logAsDebug); // semantic checks general "turn off switch" if (defined("DO_SEMANTIC_CHECKS") && DO_SEMANTIC_CHECKS === false) { return $ret; } if (!$ret) { return false; } if (isset($this->start) && isset($this->until) && $this->until < $this->start) { ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter 'start' is HIGHER than 'until'. Check failed!", get_class($this))); return false; } return true; }
/** * Method checks if the object has the minimum of required parameters * and fullfills semantic dependencies * * This overloads the general check() with special checks to be executed * * @param boolean $logAsDebug (opt) default is false, so messages are logged in WARN log level * * @access public * @return boolean */ public function Check($logAsDebug = false) { $ret = parent::Check($logAsDebug); // semantic checks general "turn off switch" if (defined("DO_SEMANTIC_CHECKS") && DO_SEMANTIC_CHECKS === false) { return $ret; } if (!$ret) { return false; } if (isset($this->startdate) && isset($this->duedate) && $this->duedate < $this->startdate) { ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter 'startdate' is HIGHER than 'duedate'. Check failed!", get_class($this))); return false; } if (isset($this->utcstartdate) && isset($this->utcduedate) && $this->utcduedate < $this->utcstartdate) { ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter 'utcstartdate' is HIGHER than 'utcduedate'. Check failed!", get_class($this))); return false; } if (isset($this->duedate) && $this->duedate != Utils::getDayStartOfTimestamp($this->duedate)) { $this->duedate = Utils::getDayStartOfTimestamp($this->duedate); ZLog::Write(LOGLEVEL_DEBUG, "Set the due time to the start of the day"); if (isset($this->startdate) && $this->duedate < $this->startdate) { $this->startdate = Utils::getDayStartOfTimestamp($this->startdate); ZLog::Write(LOGLEVEL_DEBUG, "Set the start date to the start of the day"); } } return true; }
/** * Imports a message * * @param SyncParameters $spa SyncParameters object * @param array $actiondata Actiondata array * @param integer $todo WBXML flag indicating how message should be imported. * Valid values: SYNC_ADD, SYNC_MODIFY, SYNC_REMOVE * @param SyncObject $message SyncObject message to be imported * @param string $clientid Client message identifier * @param string $serverid Server message identifier * @param string $foldertype On sms sync, this says "SMS", else false * @param integer $messageCount Counter of already imported messages * * @access private * @throws StatusException in case the importer is not available * @return - Message related status are returned in the actiondata. */ private function importMessage($spa, &$actiondata, $todo, $message, $clientid, $serverid, $foldertype, $messageCount) { // the importer needs to be available! if ($this->importer == false) { throw StatusException("Sync->importMessage(): importer not available", SYNC_STATUS_SERVERERROR); } // mark this state as used, e.g. for HeartBeat self::$deviceManager->SetHeartbeatStateIntegrity($spa->GetFolderId(), $spa->GetUuid(), $spa->GetUuidCounter()); // Detect incoming loop // messages which were created/removed before will not have the same action executed again // if a message is edited we perform this action "again", as the message could have been changed on the mobile in the meantime $ignoreMessage = false; if ($actiondata["failstate"]) { // message was ADDED before, do NOT add it again if ($todo == SYNC_ADD && isset($actiondata["failstate"]["clientids"][$clientid])) { $ignoreMessage = true; // make sure no messages are sent back self::$deviceManager->SetWindowSize($spa->GetFolderId(), 0); $actiondata["clientids"][$clientid] = $actiondata["failstate"]["clientids"][$clientid]; $actiondata["statusids"][$clientid] = $actiondata["failstate"]["statusids"][$clientid]; ZLog::Write(LOGLEVEL_WARN, sprintf("Mobile loop detected! Incoming new message '%s' was created on the server before. Replying with known new server id: %s", $clientid, $actiondata["clientids"][$clientid])); } // message was REMOVED before, do NOT attemp to remove it again if ($todo == SYNC_REMOVE && isset($actiondata["failstate"]["removeids"][$serverid])) { $ignoreMessage = true; // make sure no messages are sent back self::$deviceManager->SetWindowSize($spa->GetFolderId(), 0); $actiondata["removeids"][$serverid] = $actiondata["failstate"]["removeids"][$serverid]; $actiondata["statusids"][$serverid] = $actiondata["failstate"]["statusids"][$serverid]; ZLog::Write(LOGLEVEL_WARN, sprintf("Mobile loop detected! Message '%s' was deleted by the mobile before. Replying with known status: %s", $clientid, $actiondata["statusids"][$serverid])); } } if (!$ignoreMessage) { switch ($todo) { case SYNC_MODIFY: self::$topCollector->AnnounceInformation(sprintf("Saving modified message %d", $messageCount)); try { $actiondata["modifyids"][] = $serverid; // ignore sms messages if ($foldertype == "SMS" || stripos($serverid, self::ZPUSHIGNORESMS) !== false) { ZLog::Write(LOGLEVEL_DEBUG, "SMS sync are not supported. Ignoring message."); // TODO we should update the SMS $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } else { if (!$message instanceof SyncObject || !$message->Check(true)) { $actiondata["statusids"][$serverid] = SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR; } else { if (isset($message->read)) { // Currently, 'read' is only sent by the PDA when it is ONLY setting the read flag. $this->importer->ImportMessageReadFlag($serverid, $message->read); } elseif (!isset($message->flag)) { $this->importer->ImportMessageChange($serverid, $message); } // email todoflags - some devices send todos flags together with read flags, // so they have to be handled separately if (isset($message->flag)) { $this->importer->ImportMessageChange($serverid, $message); } $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } } } catch (StatusException $stex) { $actiondata["statusids"][$serverid] = $stex->getCode(); } break; case SYNC_ADD: self::$topCollector->AnnounceInformation(sprintf("Creating new message from mobile %d", $messageCount)); try { // ignore sms messages if ($foldertype == "SMS") { ZLog::Write(LOGLEVEL_DEBUG, "SMS sync are not supported. Ignoring message."); // TODO we should create the SMS // return a fake serverid which we can identify later $actiondata["clientids"][$clientid] = self::ZPUSHIGNORESMS . $clientid; $actiondata["statusids"][$clientid] = SYNC_STATUS_SUCCESS; } else { if (!$message instanceof SyncObject || !$message->Check(true)) { $actiondata["clientids"][$clientid] = false; $actiondata["statusids"][$clientid] = SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR; } else { $actiondata["clientids"][$clientid] = false; $actiondata["clientids"][$clientid] = $this->importer->ImportMessageChange(false, $message); $actiondata["statusids"][$clientid] = SYNC_STATUS_SUCCESS; } } } catch (StatusException $stex) { $actiondata["statusids"][$clientid] = $stex->getCode(); } break; case SYNC_REMOVE: self::$topCollector->AnnounceInformation(sprintf("Deleting message removed on mobile %d", $messageCount)); try { $actiondata["removeids"][] = $serverid; // ignore sms messages if ($foldertype == "SMS" || stripos($serverid, self::ZPUSHIGNORESMS) !== false) { ZLog::Write(LOGLEVEL_DEBUG, "SMS sync are not supported. Ignoring message."); // TODO we should delete the SMS $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } else { // if message deletions are to be moved, move them if ($spa->GetDeletesAsMoves()) { $folderid = self::$backend->GetWasteBasket(); if ($folderid) { $this->importer->ImportMessageMove($serverid, $folderid); $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; break; } else { ZLog::Write(LOGLEVEL_WARN, "Message should be moved to WasteBasket, but the Backend did not return a destination ID. Message is hard deleted now!"); } } $this->importer->ImportMessageDeletion($serverid); $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } } catch (StatusException $stex) { $actiondata["statusids"][$serverid] = $stex->getCode(); } break; } ZLog::Write(LOGLEVEL_DEBUG, "Sync->importMessage(): message imported"); } }
/** * Method checks if the object has the minimum of required parameters * and fullfills semantic dependencies * * This overloads the general check() with special checks to be executed * Checks if SYNC_POOMCAL_ORGANIZERNAME and SYNC_POOMCAL_ORGANIZEREMAIL are correctly set * * @param boolean $logAsDebug (opt) default is false, so messages are logged in WARN log level * * @access public * @return boolean */ public function Check($logAsDebug = false) { $ret = parent::Check($logAsDebug); // semantic checks general "turn off switch" if (defined("DO_SEMANTIC_CHECKS") && DO_SEMANTIC_CHECKS === false) { return $ret; } if (!$ret) { return false; } if ($this->meetingstatus > 0) { if (!isset($this->organizername) || !isset($this->organizeremail)) { ZLog::Write(LOGLEVEL_WARN, "SyncAppointment->Check(): Parameter 'organizername' and 'organizeremail' should be set for a meeting request"); } } // do not sync a recurrent appointment without a timezone if (isset($this->recurrence) && !isset($this->timezone)) { ZLog::Write(LOGLEVEL_ERROR, "SyncAppointment->Check(): timezone for a recurring appointment is not set."); return false; } return true; }
/** * Imports a message * * @param SyncParameters $spa SyncParameters object * @param array $actiondata Actiondata array * @param integer $todo WBXML flag indicating how message should be imported. * Valid values: SYNC_ADD, SYNC_MODIFY, SYNC_REMOVE * @param SyncObject $message SyncObject message to be imported * @param string $clientid Client message identifier * @param string $serverid Server message identifier * * @access private * @throws StatusException in case the importer is not available * @return - Message related status are returned in the actiondata. */ private function importMessage($spa, &$actiondata, $todo, $message, $clientid, $serverid) { // the importer needs to be available! if ($this->importer == false) { throw StatusException(sprintf("Sync->importMessage(): importer not available", SYNC_STATUS_SERVERERROR)); } // Detect incoming loop // messages which were created/removed before will not have the same action executed again // if a message is edited we perform this action "again", as the message could have been changed on the mobile in the meantime $ignoreMessage = false; if ($actiondata["failstate"]) { // message was ADDED before, do NOT add it again if ($todo == SYNC_ADD && $actiondata["failstate"]["clientids"][$clientid]) { $ignoreMessage = true; // make sure no messages are sent back self::$deviceManager->SetWindowSize($spa->GetFolderId(), 0); $actiondata["clientids"][$clientid] = $actiondata["failstate"]["clientids"][$clientid]; $actiondata["statusids"][$clientid] = $actiondata["failstate"]["statusids"][$clientid]; ZLog::Write(LOGLEVEL_WARN, sprintf("Mobile loop detected! Incoming new message '%s' was created on the server before. Replying with known new server id: %s", $clientid, $actiondata["clientids"][$clientid])); } // message was REMOVED before, do NOT attemp to remove it again if ($todo == SYNC_REMOVE && $actiondata["failstate"]["removeids"][$serverid]) { $ignoreMessage = true; // make sure no messages are sent back self::$deviceManager->SetWindowSize($spa->GetFolderId(), 0); $actiondata["removeids"][$serverid] = $actiondata["failstate"]["removeids"][$serverid]; $actiondata["statusids"][$serverid] = $actiondata["failstate"]["statusids"][$serverid]; ZLog::Write(LOGLEVEL_WARN, sprintf("Mobile loop detected! Message '%s' was deleted by the mobile before. Replying with known status: %s", $clientid, $actiondata["statusids"][$serverid])); } } if (!$ignoreMessage) { switch ($todo) { case SYNC_MODIFY: try { $actiondata["modifyids"][] = $serverid; // check incoming message without logging WARN messages about errors if (!$message instanceof SyncObject || !$message->Check(true)) { $actiondata["statusids"][$serverid] = SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR; } else { if (isset($message->read)) { // Currently, 'read' is only sent by the PDA when it is ONLY setting the read flag. $this->importer->ImportMessageReadFlag($serverid, $message->read); } elseif (!isset($message->flag)) { $this->importer->ImportMessageChange($serverid, $message); } // email todoflags - some devices send todos flags together with read flags, // so they have to be handled separately if (isset($message->flag)) { $this->importer->ImportMessageChange($serverid, $message); } $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } } catch (StatusException $stex) { $actiondata["statusids"][$serverid] = $stex->getCode(); } break; case SYNC_ADD: try { // check incoming message without logging WARN messages about errors if (!$message instanceof SyncObject || !$message->Check(true)) { $actiondata["clientids"][$clientid] = false; $actiondata["statusids"][$clientid] = SYNC_STATUS_CLIENTSERVERCONVERSATIONERROR; } else { $actiondata["clientids"][$clientid] = false; $actiondata["clientids"][$clientid] = $this->importer->ImportMessageChange(false, $message); $actiondata["statusids"][$clientid] = SYNC_STATUS_SUCCESS; } } catch (StatusException $stex) { $actiondata["statusids"][$clientid] = $stex->getCode(); } break; case SYNC_REMOVE: try { $actiondata["removeids"][] = $serverid; // if message deletions are to be moved, move them if ($spa->GetDeletesAsMoves()) { $folderid = self::$backend->GetWasteBasket(); if ($folderid) { $this->importer->ImportMessageMove($serverid, $folderid); $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; break; } else { ZLog::Write(LOGLEVEL_WARN, "Message should be moved to WasteBasket, but the Backend did not return a destination ID. Message is hard deleted now!"); } } $this->importer->ImportMessageDeletion($serverid); $actiondata["statusids"][$serverid] = SYNC_STATUS_SUCCESS; } catch (StatusException $stex) { $actiondata["statusids"][$serverid] = $stex->getCode(); } break; } ZLog::Write(LOGLEVEL_DEBUG, "Sync->importMessage(): message imported"); } }