410 lines
10 KiB
PHP
410 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* The Horde_SyncMl_State class provides a SyncML state object.
|
|
*
|
|
* Copyright 2003-2016 Horde LLC (http://www.horde.org/)
|
|
*
|
|
* See the enclosed file COPYING for license information (LGPL). If you
|
|
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
|
|
*
|
|
* @author Anthony Mills <amills@pyramid6.com>
|
|
* @author Jan Schneider <jan@horde.org>
|
|
* @package SyncMl
|
|
*/
|
|
class Horde_SyncMl_State
|
|
{
|
|
/**
|
|
* Id of this SyncML session.
|
|
*
|
|
* This is not to confuse with the PHP session id, though it is part of
|
|
* the generated PHP session id.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $sessionID;
|
|
|
|
/**
|
|
* Id of the current message.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $messageID;
|
|
|
|
/**
|
|
* The target URI as sent by the client.
|
|
*
|
|
* This is normally the URL of the RPC server. However the client is
|
|
* free to send anything.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $targetURI;
|
|
|
|
/**
|
|
* The source URI as sent by the client.
|
|
*
|
|
* Can be used to identify the client and is part of the PHP session id.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $sourceURI;
|
|
|
|
/**
|
|
* SyncML protocol version.
|
|
*
|
|
* 0 for SyncML 1.0, 1 for SyncML 1.1, etc.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $version;
|
|
|
|
/**
|
|
* Username used to authenticate with the backend.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $user;
|
|
|
|
/**
|
|
* Whether this session has authenticated successfully.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $authenticated = false;
|
|
|
|
/**
|
|
* <SyncML> namespace uri.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_uri;
|
|
|
|
/**
|
|
* <Meta> namespace uri.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $uriMeta;
|
|
|
|
/**
|
|
* <DevInf> namespace uri.
|
|
*
|
|
* @var string
|
|
*/
|
|
public $uriDevInf;
|
|
|
|
/**
|
|
* Whether WBXML encoding is used.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $wbxml = false;
|
|
|
|
/**
|
|
* The maximum allowed message size in bytes.
|
|
*
|
|
* @todo Change to PHP_INT_MAX.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $maxMsgSize = 1000000000;
|
|
|
|
/**
|
|
* The maximum allowed object size in bytes.
|
|
*
|
|
* @todo Change to PHP_INT_MAX.
|
|
*
|
|
* @var integer
|
|
*/
|
|
public $maxObjSize = 1000000000;
|
|
|
|
/**
|
|
* Array of Horde_SyncMl_Sync objects.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_syncs = array();
|
|
|
|
/**
|
|
* The list of all server changes being sent to the client as a reference
|
|
* for Status responses from the client.
|
|
*
|
|
* @var array
|
|
*/
|
|
public $serverChanges = array();
|
|
|
|
/**
|
|
* Name of the appropriate device driver.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_deviceDriver;
|
|
|
|
/**
|
|
* Device info provided by the SyncML DevInf data.
|
|
*
|
|
* @var Horde_SyncMl_DeviceInfo
|
|
*/
|
|
public $deviceInfo;
|
|
|
|
/**
|
|
* Current sync element sent from client.
|
|
*
|
|
* Stored in state if one element is split into multiple message packets.
|
|
*
|
|
* @var Horde_SyncMl_SyncElement
|
|
*/
|
|
public $curSyncItem;
|
|
|
|
/**
|
|
* Flag that is set if the client sends a Final but we are not finished
|
|
* with the current package and thus can't final this package yet.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $delayedFinal = false;
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct($sourceURI, $user, $sessionID)
|
|
{
|
|
$this->sourceURI = $sourceURI;
|
|
$this->user = $user;
|
|
$this->sessionID = $sessionID;
|
|
|
|
/* Create empty dummy device info. Will be replaced with real DevInf
|
|
* information if provided by the client. */
|
|
$this->deviceInfo = new Horde_SyncMl_DeviceInfo();
|
|
}
|
|
|
|
/**
|
|
* Returns the <DevInf><VerDTD> content based on the protocol version.
|
|
*/
|
|
public function getVerDTD()
|
|
{
|
|
switch ($this->version) {
|
|
case 1:
|
|
return '1.1';
|
|
case 2:
|
|
return '1.2';
|
|
default:
|
|
return '1.0';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the DevInf URI based on the protocol version.
|
|
*/
|
|
public function getDevInfURI()
|
|
{
|
|
switch ($this->version) {
|
|
case 1:
|
|
return './devinf11';
|
|
case 2:
|
|
return './devinf12';
|
|
default:
|
|
return './devinf10';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the protocol name based on the protocol version.
|
|
*/
|
|
public function getProtocolName()
|
|
{
|
|
switch ($this->version) {
|
|
case 1:
|
|
return 'SyncML/1.1';
|
|
case 2:
|
|
return 'SyncML/1.2';
|
|
default:
|
|
return 'SyncML/1.0';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the protocol version
|
|
*
|
|
* @param integer $version The protocol version: 0 for SyncML 1.0, 1 for
|
|
* SyncML 1.1 etc.
|
|
*/
|
|
public function setVersion($version)
|
|
{
|
|
switch ($version) {
|
|
case 1:
|
|
$this->_uri = Horde_SyncMl::NAME_SPACE_URI_SYNCML_1_1;
|
|
$this->uriMeta = Horde_SyncMl::NAME_SPACE_URI_METINF_1_1;
|
|
$this->uriDevInf = Horde_SyncMl::NAME_SPACE_URI_DEVINF_1_1;
|
|
break;
|
|
case 2:
|
|
$this->_uri = Horde_SyncMl::NAME_SPACE_URI_SYNCML_1_2;
|
|
$this->uriMeta = Horde_SyncMl::NAME_SPACE_URI_METINF_1_2;
|
|
$this->uriDevInf = Horde_SyncMl::NAME_SPACE_URI_DEVINF_1_2;
|
|
break;
|
|
default:
|
|
$this->_uri = Horde_SyncMl::NAME_SPACE_URI_SYNCML;
|
|
$this->uriMeta = Horde_SyncMl::NAME_SPACE_URI_METINF;
|
|
$this->uriDevInf = Horde_SyncMl::NAME_SPACE_URI_DEVINF;
|
|
break;
|
|
}
|
|
|
|
$this->version = $version;
|
|
}
|
|
|
|
/**
|
|
* Returns the namespace URI for the <SyncML> element.
|
|
*
|
|
* @return string The namespace URI to use, if any.
|
|
*/
|
|
public function getURI()
|
|
{
|
|
/* The non WBXML devices (notably SonyEricsson and Funambol) seem to
|
|
* get confused by a <SyncML xmlns="syncml:SYNCML1.1"> element. They
|
|
* require just <SyncML>. So don't use a namespace for non-wbxml
|
|
* devices. */
|
|
if ($this->wbxml || $this->version > 0) {
|
|
return $this->_uri;
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a Horde_SyncMl_Device instance for the device used in this session.
|
|
*
|
|
* @return Horde_SyncMl_Device A Horde_SyncMl_Device instance.
|
|
*/
|
|
public function getDevice()
|
|
{
|
|
if (empty($this->_deviceDriver)) {
|
|
$si = $this->sourceURI;
|
|
$di = $this->deviceInfo;
|
|
|
|
if (stristr($si, 'sync4j') !== false ||
|
|
stristr($si, 'sc-pim') !== false ||
|
|
stristr($si, 'fol-') !== false ||
|
|
stristr($si, 'fwm-') !== false ||
|
|
stristr($si, 'fbb-') !== false) {
|
|
$this->_deviceDriver = 'Sync4j';
|
|
} elseif (!empty($di->Man) &&
|
|
(stristr($di->Man, 'Sony Ericsson') !== false ||
|
|
stristr($di->Mod, 'A1000') !== false)) {
|
|
/* The Morola A1000 has a similar (UIQ) firmware as the
|
|
* P800: */
|
|
$this->_deviceDriver = 'P800';
|
|
} elseif (!empty($di->Man) &&
|
|
stristr($di->Man, 'nokia') !== false) {
|
|
$this->_deviceDriver = 'Nokia';
|
|
} elseif (stristr($si, 'fmz-') !== false) {
|
|
$this->_deviceDriver = 'Sync4JMozilla';
|
|
} else {
|
|
$this->_deviceDriver = 'default';
|
|
}
|
|
}
|
|
|
|
return Horde_SyncMl_Device::factory($this->_deviceDriver);
|
|
}
|
|
|
|
/**
|
|
* @param string $target
|
|
* @param Horde_SyncMl_Sync $sync
|
|
*/
|
|
public function setSync($target, $sync)
|
|
{
|
|
$this->_syncs[$target] = $sync;
|
|
}
|
|
|
|
/**
|
|
* @param string $target
|
|
* @return Horde_SyncMl_Sync
|
|
*/
|
|
public function getSync($target)
|
|
{
|
|
if (isset($this->_syncs[$target])) {
|
|
return $this->_syncs[$target];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getSyncs()
|
|
{
|
|
return $this->_syncs;
|
|
}
|
|
|
|
/**
|
|
* Returns whether there are any pending elements that have not been sent
|
|
* to due to message size restrictions. These will be sent int the next
|
|
* message.
|
|
*
|
|
* @return boolean True if there are pending elements that have yet to be
|
|
* sent.
|
|
*/
|
|
public function hasPendingSyncs()
|
|
{
|
|
if (is_array($this->_syncs)) {
|
|
foreach ($this->_syncs as $sync) {
|
|
if ($sync->hasPendingElements()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns all syncs which have pending elements left.
|
|
*
|
|
* @return array Array of TargetLocURIs which can be used as a key in
|
|
* getSync() calls.
|
|
*/
|
|
public function getPendingSyncs()
|
|
{
|
|
$pending = array();
|
|
if (is_array($this->_syncs)) {
|
|
foreach ($this->_syncs as $target => $sync) {
|
|
if ($sync->hasPendingElements()) {
|
|
$pending[] = $target;
|
|
}
|
|
}
|
|
}
|
|
return $pending;
|
|
}
|
|
|
|
/**
|
|
* Returns whether all syncs are in completed state or no syncs are
|
|
* present.
|
|
*
|
|
* @return boolean True if all syncs are in completed state.
|
|
*/
|
|
public function isAllSyncsComplete()
|
|
{
|
|
if (is_array($this->_syncs)) {
|
|
foreach ($this->_syncs as $target => $sync) {
|
|
if (!$sync->isComplete()) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Propagates final tags here and then further to every sync.
|
|
*
|
|
* This allows the sync objects to determine if they are complete.
|
|
*/
|
|
public function handleFinal(&$output, $debug = false)
|
|
{
|
|
if (is_array($this->_syncs)) {
|
|
foreach (array_keys($this->_syncs) as $t) {
|
|
$this->_syncs[$t]->handleFinal($output, $debug);
|
|
}
|
|
}
|
|
}
|
|
}
|