mirror of
https://github.com/YunoHost-Apps/z-push_ynh.git
synced 2024-09-03 18:05:58 +02:00
419 lines
No EOL
14 KiB
PHP
419 lines
No EOL
14 KiB
PHP
<?php
|
|
/***********************************************
|
|
* File : syncparameters.php
|
|
* Project : Z-Push
|
|
* Descr : Transportation container for
|
|
* requested content parameters and information
|
|
* about the container and states
|
|
*
|
|
* Created : 11.04.2011
|
|
*
|
|
* Copyright 2007 - 2013 Zarafa Deutschland GmbH
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation with the following additional
|
|
* term according to sec. 7:
|
|
*
|
|
* According to sec. 7 of the GNU Affero General Public License, version 3,
|
|
* the terms of the AGPL are supplemented with the following terms:
|
|
*
|
|
* "Zarafa" is a registered trademark of Zarafa B.V.
|
|
* "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
|
|
* The licensing of the Program under the AGPL does not imply a trademark license.
|
|
* Therefore any rights, title and interest in our trademarks remain entirely with us.
|
|
*
|
|
* However, if you propagate an unmodified version of the Program you are
|
|
* allowed to use the term "Z-Push" to indicate that you distribute the Program.
|
|
* Furthermore you may use our trademarks where it is necessary to indicate
|
|
* the intended purpose of a product or service provided you use it in accordance
|
|
* with honest practices in industrial or commercial matters.
|
|
* If you want to propagate modified versions of the Program under the name "Z-Push",
|
|
* you may only do so if you have a written permission by Zarafa Deutschland GmbH
|
|
* (to acquire a permission please contact Zarafa at trademark@zarafa.com).
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Consult LICENSE file for details
|
|
************************************************/
|
|
|
|
class SyncParameters extends StateObject {
|
|
const DEFAULTOPTIONS = "DEFAULT";
|
|
const EMAILOPTIONS = "EMAIL";
|
|
const CALENDAROPTIONS = "CALENDAR";
|
|
const CONTACTOPTIONS = "CONTACTS";
|
|
const NOTEOPTIONS = "NOTES";
|
|
const TASKOPTIONS = "TASKS";
|
|
const SMSOPTIONS = "SMS";
|
|
|
|
private $synckeyChanged = false;
|
|
private $currentCPO = self::DEFAULTOPTIONS;
|
|
|
|
protected $unsetdata = array(
|
|
'uuid' => false,
|
|
'uuidcounter' => false,
|
|
'uuidnewcounter' => false,
|
|
'folderid' => false,
|
|
'referencelifetime' => 10,
|
|
'lastsynctime' => false,
|
|
'referencepolicykey' => true,
|
|
'pingableflag' => false,
|
|
'contentclass' => false,
|
|
'deletesasmoves' => false,
|
|
'conversationmode' => false,
|
|
'windowsize' => 5,
|
|
'contentparameters' => array(),
|
|
'foldersynctotal' => false,
|
|
'foldersyncremaining' => false,
|
|
);
|
|
|
|
/**
|
|
* SyncParameters constructor
|
|
*/
|
|
public function SyncParameters() {
|
|
// initialize ContentParameters for the current option
|
|
$this->checkCPO();
|
|
}
|
|
|
|
|
|
/**
|
|
* SyncKey methods
|
|
*
|
|
* The current and next synckey is saved as uuid and counter
|
|
* so partial and ping can access the latest states.
|
|
*/
|
|
|
|
/**
|
|
* Returns the latest SyncKey of this folder
|
|
*
|
|
* @access public
|
|
* @return string/boolean false if no uuid/counter available
|
|
*/
|
|
public function GetSyncKey() {
|
|
if (isset($this->uuid) && isset($this->uuidCounter))
|
|
return StateManager::BuildStateKey($this->uuid, $this->uuidCounter);
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets the the current synckey.
|
|
* This is done by parsing it and saving uuid and counter.
|
|
* By setting the current key, the "next" key is obsolete
|
|
*
|
|
* @param string $synckey
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function SetSyncKey($synckey) {
|
|
list($this->uuid, $this->uuidCounter) = StateManager::ParseStateKey($synckey);
|
|
|
|
// remove newSyncKey
|
|
unset($this->uuidNewCounter);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Indicates if this folder has a synckey
|
|
*
|
|
* @access public
|
|
* @return booleans
|
|
*/
|
|
public function HasSyncKey() {
|
|
return (isset($this->uuid) && isset($this->uuidCounter));
|
|
}
|
|
|
|
/**
|
|
* Sets the the next synckey.
|
|
* This is done by parsing it and saving uuid and next counter.
|
|
* if the folder has no synckey until now (new sync), the next counter becomes current asl well.
|
|
*
|
|
* @param string $synckey
|
|
*
|
|
* @access public
|
|
* @throws FatalException if the uuids of current and next do not match
|
|
* @return boolean
|
|
*/
|
|
public function SetNewSyncKey($synckey) {
|
|
list($uuid, $uuidNewCounter) = StateManager::ParseStateKey($synckey);
|
|
if (!$this->HasSyncKey()) {
|
|
$this->uuid = $uuid;
|
|
$this->uuidCounter = $uuidNewCounter;
|
|
}
|
|
else if ($uuid !== $this->uuid)
|
|
throw new FatalException("SyncParameters->SetNewSyncKey(): new SyncKey must have the same UUID as current SyncKey");
|
|
|
|
$this->uuidNewCounter = $uuidNewCounter;
|
|
$this->synckeyChanged = true;
|
|
}
|
|
|
|
/**
|
|
* Returns the next synckey
|
|
*
|
|
* @access public
|
|
* @return string/boolean returns false if uuid or counter are not available
|
|
*/
|
|
public function GetNewSyncKey() {
|
|
if (isset($this->uuid) && isset($this->uuidNewCounter))
|
|
return StateManager::BuildStateKey($this->uuid, $this->uuidNewCounter);
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Indicates if the folder has a next synckey
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function HasNewSyncKey() {
|
|
return (isset($this->uuid) && isset($this->uuidNewCounter));
|
|
}
|
|
|
|
/**
|
|
* Return the latest synckey.
|
|
* When this is called the new key becomes the current key (if a new key is available).
|
|
* The current key is then returned.
|
|
*
|
|
* @access public
|
|
* @return string
|
|
*/
|
|
public function GetLatestSyncKey() {
|
|
// New becomes old
|
|
if ($this->HasUuidNewCounter()) {
|
|
$this->uuidCounter = $this->uuidNewCounter;
|
|
unset($this->uuidNewCounter);
|
|
}
|
|
|
|
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->GetLatestSyncKey(): '%s'", $this->GetSyncKey()));
|
|
return $this->GetSyncKey();
|
|
}
|
|
|
|
/**
|
|
* Removes the saved SyncKey of this folder
|
|
*
|
|
* @access public
|
|
* @return boolean
|
|
*/
|
|
public function RemoveSyncKey() {
|
|
if (isset($this->uuid))
|
|
unset($this->uuid);
|
|
|
|
if (isset($this->uuidCounter))
|
|
unset($this->uuidCounter);
|
|
|
|
if (isset($this->uuidNewCounter))
|
|
unset($this->uuidNewCounter);
|
|
|
|
ZLog::Write(LOGLEVEL_DEBUG, "SyncParameters->RemoveSyncKey(): saved sync key removed");
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* CPO methods
|
|
*
|
|
* A sync request can have several options blocks. Each block is saved into an own CPO object
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* Returns the a specified CPO
|
|
*
|
|
* @param string $options (opt) If not specified, the default Options (CPO) will be used
|
|
* Valid option SyncParameters::SMSOPTIONS (string "SMS")
|
|
*
|
|
* @access public
|
|
* @return ContentParameters object
|
|
*/
|
|
public function GetCPO($options = self::DEFAULTOPTIONS) {
|
|
$options = strtoupper($options);
|
|
$this->isValidType($options);
|
|
$options = $this->normalizeType($options);
|
|
|
|
$this->checkCPO($options);
|
|
|
|
// copy contentclass and conversationmode to the CPO
|
|
$this->contentParameters[$options]->SetContentClass($this->contentclass);
|
|
$this->contentParameters[$options]->SetConversationMode($this->conversationmode);
|
|
|
|
return $this->contentParameters[$options];
|
|
}
|
|
|
|
/**
|
|
* Use the submitted CPO type for next setters/getters
|
|
*
|
|
* @param string $options (opt) If not specified, the default Options (CPO) will be used
|
|
* Valid option SyncParameters::SMSOPTIONS (string "SMS")
|
|
*
|
|
* @access public
|
|
* @return
|
|
*/
|
|
public function UseCPO($options = self::DEFAULTOPTIONS) {
|
|
$options = strtoupper($options);
|
|
$this->isValidType($options);
|
|
|
|
// remove potential old default CPO if available
|
|
if (isset($this->contentParameters[self::DEFAULTOPTIONS]) && $options != self::DEFAULTOPTIONS && $options !== self::SMSOPTIONS) {
|
|
$a = $this->contentParameters;
|
|
unset($a[self::DEFAULTOPTIONS]);
|
|
$this->contentParameters = $a;
|
|
ZLog::Write(LOGLEVEL_DEBUG, "SyncParameters->UseCPO(): removed existing DEFAULT CPO as it is obsolete");
|
|
}
|
|
|
|
ZLOG::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->UseCPO('%s')", $options));
|
|
$this->currentCPO = $options;
|
|
$this->checkCPO($this->currentCPO);
|
|
}
|
|
|
|
/**
|
|
* Checks if a CPO is correctly inicialized and inicializes it if necessary
|
|
*
|
|
* @param string $options (opt) If not specified, the default Options (CPO) will be used
|
|
* Valid option SyncParameters::SMSOPTIONS (string "SMS")
|
|
*
|
|
* @access private
|
|
* @return boolean
|
|
*/
|
|
private function checkCPO($options = self::DEFAULTOPTIONS) {
|
|
$this->isValidType($options);
|
|
|
|
if (!isset($this->contentParameters[$options])) {
|
|
$a = $this->contentParameters;
|
|
$a[$options] = new ContentParameters();
|
|
$this->contentParameters = $a;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks if the requested option type is available
|
|
*
|
|
* @param string $options CPO type
|
|
*
|
|
* @access private
|
|
* @return boolean
|
|
* @throws FatalNotImplementedException
|
|
*/
|
|
private function isValidType($options) {
|
|
if ($options !== self::DEFAULTOPTIONS &&
|
|
$options !== self::EMAILOPTIONS &&
|
|
$options !== self::CALENDAROPTIONS &&
|
|
$options !== self::CONTACTOPTIONS &&
|
|
$options !== self::NOTEOPTIONS &&
|
|
$options !== self::TASKOPTIONS &&
|
|
$options !== self::SMSOPTIONS)
|
|
throw new FatalNotImplementedException(sprintf("SyncParameters->isAllowedType('%s') ContentParameters is invalid. Such type is not available.", $options));
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Normalizes the requested option type and returns it as
|
|
* default option if no default is available
|
|
*
|
|
* @param string $options CPO type
|
|
*
|
|
* @access private
|
|
* @return string
|
|
* @throws FatalNotImplementedException
|
|
*/
|
|
private function normalizeType($options) {
|
|
// return the requested CPO as it is defined
|
|
if (isset($this->contentParameters[$options]))
|
|
return $options;
|
|
|
|
$returnCPO = $options;
|
|
// return email, calendar, contact or note CPO as default CPO if there no explicit default CPO defined
|
|
if ($options == self::DEFAULTOPTIONS && !isset($this->contentParameters[self::DEFAULTOPTIONS])) {
|
|
|
|
if (isset($this->contentParameters[self::EMAILOPTIONS]))
|
|
$returnCPO = self::EMAILOPTIONS;
|
|
elseif (isset($this->contentParameters[self::CALENDAROPTIONS]))
|
|
$returnCPO = self::CALENDAROPTIONS;
|
|
elseif (isset($this->contentParameters[self::CONTACTOPTIONS]))
|
|
$returnCPO = self::CONTACTOPTIONS;
|
|
elseif (isset($this->contentParameters[self::NOTEOPTIONS]))
|
|
$returnCPO = self::NOTEOPTIONS;
|
|
elseif (isset($this->contentParameters[self::TASKOPTIONS]))
|
|
$returnCPO = self::TASKOPTIONS;
|
|
|
|
if ($returnCPO != $options)
|
|
ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncParameters->normalizeType(): using %s for requested %s", $returnCPO, $options));
|
|
return $returnCPO;
|
|
}
|
|
// something unexpected happened, just return default, empty in the worst case
|
|
else {
|
|
ZLog::Write(LOGLEVEL_WARN, "SyncParameters->normalizeType(): no DEFAULT CPO available, creating empty CPO");
|
|
$this->checkCPO(self::DEFAULTOPTIONS);
|
|
return self::DEFAULTOPTIONS;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* PHP magic to implement any getter, setter, has and delete operations
|
|
* on an instance variable.
|
|
*
|
|
* NOTICE: All magic getters and setters of this object which are not defined in the unsetdata array are passed to the current CPO.
|
|
*
|
|
* Methods like e.g. "SetVariableName($x)" and "GetVariableName()" are supported
|
|
*
|
|
* @access public
|
|
* @return mixed
|
|
*/
|
|
public function __call($name, $arguments) {
|
|
$lowname = strtolower($name);
|
|
$operator = substr($lowname, 0,3);
|
|
$var = substr($lowname,3);
|
|
|
|
if (array_key_exists($var, $this->unsetdata)) {
|
|
return parent::__call($name, $arguments);
|
|
}
|
|
|
|
return $this->contentParameters[$this->currentCPO]->__call($name, $arguments);
|
|
}
|
|
|
|
|
|
/**
|
|
* un/serialization methods
|
|
*/
|
|
|
|
/**
|
|
* Called before the StateObject is serialized
|
|
*
|
|
* @access protected
|
|
* @return boolean
|
|
*/
|
|
protected function preSerialize() {
|
|
parent::preSerialize();
|
|
|
|
if ($this->changed === true && ($this->synckeyChanged || $this->lastsynctime === false))
|
|
$this->lastsynctime = time();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Called after the StateObject was unserialized
|
|
*
|
|
* @access protected
|
|
* @return boolean
|
|
*/
|
|
protected function postUnserialize() {
|
|
// init with default options
|
|
$this->UseCPO();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
?>
|