egroupware/phpgwapi/inc/horde/Horde/SyncML/Command/Put.php
Patrick Bihan-Faou 95eeded398 Make the detection of the device types a little smarter and able to use
out-of-band data such as the HTTP user agent.

Use that to determine weither message fragmentation should be used or not.

Indicate that Funambol 6+ supports fragmentation (this solves cases where
big addressbooks cannot be syncrhonized because there are too many entries).
2007-12-19 07:45:36 +00:00

266 lines
7.1 KiB
PHP

<?php
include_once 'Horde/SyncML/State.php';
include_once 'Horde/SyncML/Command.php';
/**
* $Horde: framework/SyncML/SyncML/Command/Put.php,v 1.12 2004/07/02 19:24:44 chuck Exp $
*
* Copyright 2003-2004 Anthony Mills <amills@pyramid6.com>
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author Anthony Mills <amills@pyramid6.com>
* @version $Revision$
* @since Horde 3.0
* @package Horde_SyncML
*/
class Horde_SyncML_Command_Put extends Horde_SyncML_Command {
/**
* @var string $_manufacturer
*/
var $_manufacturer;
/**
* @var string $_model
*/
var $_model;
/**
* @var string $_oem
*/
var $_oem;
/**
* @var string $_softwareVersion
*/
var $_softwareVersion;
function endElement($uri, $element) {
switch ($this->_xmlStack) {
case 5:
switch($element) {
case 'DataStore':
$this->_deviceInfo['dataStore'][$this->_sourceReference] = array(
'maxGUIDSize' => $this->_maxGUIDSize,
'rxPreference' => $this->_rxPreference,
'txPreference' => $this->_txPreference,
'syncCapabilities' => $this->_syncCapabilities,
);
break;
case 'DevID':
$this->_deviceInfo['deviceID'] = trim($this->_chars);
break;
case 'DevTyp':
$this->_deviceInfo['deviceType'] = trim($this->_chars);
break;
case 'FwV':
$this->_deviceInfo['firmwareVersion'] = trim($this->_chars);
break;
case 'HwV':
$this->_deviceInfo['hardwareVersion'] = trim($this->_chars);
break;
case 'Man':
$this->_deviceInfo['manufacturer'] = trim($this->_chars);
break;
case 'Mod':
$this->_deviceInfo['model'] = trim($this->_chars);
break;
case 'OEM':
$this->_deviceInfo['oem'] = trim($this->_chars);
break;
case 'SwV':
$this->_deviceInfo['softwareVersion'] = trim($this->_chars);
break;
case 'SupportLargeObjs':
$this->_deviceInfo['supportLargeObjs'] = true;
break;
case 'SupportNumberOfChanges':
$this->_deviceInfo['supportNumberOfChanges'] = true;
break;
case 'UTC':
$this->_deviceInfo['UTC'] = true;
break;
case 'VerDTD':
$this->_deviceInfo['DTDVersion'] = trim($this->_chars);
break;
}
break;
case 6:
switch($element) {
case 'MaxGUIDSize':
$this->_maxGUIDSize = trim($this->_chars);
break;
case 'Rx-Pref':
$this->_rxPreference = array(
'contentType' => $this->_contentType,
'contentVersion' => $this->_contentVersion,
);
break;
case 'SourceRef':
$this->_sourceReference = trim($this->_chars);
break;
case 'Tx-Pref':
$this->_txPreference = array(
'contentType' => $this->_contentType,
'contentVersion' => $this->_contentVersion,
);
break;
}
break;
case 7:
switch($element) {
case 'CTType':
$this->_contentType = trim($this->_chars);
if (substr($this->_contentType, 0, 14) == "text/x-s4j-sif")
{
// workaround a little bug in sync4j for mobile v3.1.3 (and possibly others)
// where the content-type is set to just one value regardless of
// the source... this further leads to a failure to send updates
// by the server since it does not know how to convert say tasks to text/x-s4j-sifc
// (it should be text/x-s4j-sift).
switch ($this->_sourceReference)
{
case 'contact':
if ($this->_contentType != "text/x-s4j-sifc")
{
error_log("forcing 'contact' content type to 'text/x-s4j-sifc' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sifc";
}
break;
case 'calendar':
case 'appointment':
if ($this->_contentType != "text/x-s4j-sife")
{
error_log("forcing 'calendar' content type to 'text/x-s4j-sife' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sife";
}
break;
case 'task':
if ($this->_contentType != "text/x-s4j-sift")
{
error_log("forcing 'task' content type to 'text/x-s4j-sift' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sift";
}
break;
case 'note':
if ($this->_contentType != "text/x-s4j-sifn")
{
error_log("forcing 'note' content type to 'text/x-s4j-sifn' instead of '".$this->_contentType."'");
$this->_contentType = "text/x-s4j-sifn";
}
break;
default:
#error_log("Leaving ContentType='".$this->_contentType."' as is for source '".$this->_sourceReference."'");
break;
}
}
break;
case 'SyncType':
$this->_syncCapabilities[] = trim($this->_chars);
break;
case 'VerCT':
$this->_contentVersion = trim($this->_chars);
break;
}
break;
}
parent::endElement($uri, $element);
}
function finalizeDeviceInfo()
{
// get some more information about the device from out of band data
$ua = $_SERVER['HTTP_USER_AGENT'];
if (preg_match("/^\s*Funambol (.*) (\d+\.\d+\.\d+)\s*$/i", $ua, $matches))
{
if (!isset($this->_deviceInfo['manufacturer']))
$this->_deviceInfo['manufacturer'] = 'Funambol';
if (!isset($this->_deviceInfo['model']))
$this->_deviceInfo['model'] = 'Funambol ' . trim($matches[1]);
if (!isset($this->_deviceInfo['softwareVersion']))
$this->_deviceInfo['softwareVersion'] = $matches[2];
if (!isset($this->_deviceInfo['deviceType']))
{
switch (strtolower(trim($matches[1])))
{
case 'outlook plug-in'
default:
$this->_deviceInfo['deviceType'] = 'workstation';
break;
case 'pocket pc plug-in'
$this->_deviceInfo['deviceType'] = 'windowsmobile';
break;
}
}
}
$devid = $this->_deviceInfo['deviceID'];
switch (strtolower($devid))
{
case 'fmz-thunderbird-plugin':
if (empty($this->_devinceInfo['manufacturer']))
$this->_deviceInfo['manufacturer'] = 'Funambol';
if (empty($this->_devinceInfo['model']))
$this->_deviceInfo['model'] = 'ThunderBird';
if (empty($this->_devinceInfo['softwareVersion']))
$this->_deviceInfo['softwareVersion'] = '0.3';
break;
}
}
function output($currentCmdID, &$output ) {
$state = &$_SESSION['SyncML.state'];
$status = &new Horde_SyncML_Command_Status((($state->isAuthorized()) ? RESPONSE_OK : RESPONSE_INVALID_CREDENTIALS), 'Put');
$status->setCmdRef($this->_cmdID);
$ref = ($state->getVersion() == 0) ? './devinf10' : './devinf11';
$status->setSourceRef($ref);
if($state->isAuthorized()) {
$this->finalizeDeviceInfo();
if(count((array)$this->_deviceInfo) > 0) {
$state->setClientDeviceInfo($this->_deviceInfo);
$state->writeClientDeviceInfo();
}
}
return $status->output($currentCmdID, $output);
}
function startElement($uri, $element, $attrs) {
parent::startElement($uri, $element, $attrs);
}
}