* Generate well-formed XML for Funambol and SyncEvolution clients (community bug#2975)

This commit is contained in:
Jörg Lehrke 2011-07-08 19:45:40 +00:00
parent 3e405cc1b7
commit d9581a6ff3
2 changed files with 129 additions and 130 deletions

View File

@ -20,135 +20,129 @@ include_once 'Horde/SyncML/Command/Sync/SyncElementItem.php';
class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_Sync_SyncElementItem { class Horde_SyncML_Command_Sync_ContentSyncElement extends Horde_SyncML_Command_Sync_SyncElementItem {
function outputCommand($currentCmdID, &$output, $command) function outputCommand($currentCmdID, &$output, $command)
{ {
$state = $_SESSION['SyncML.state']; $state = $_SESSION['SyncML.state'];
$maxMsgSize = $state->getMaxMsgSizeClient(); $maxMsgSize = $state->getMaxMsgSizeClient();
$maxGUIDSize = $state->getMaxGUIDSizeClient(); $maxGUIDSize = $state->getMaxGUIDSizeClient();
if ($this->_moreData) { if ($this->_moreData) {
$command = $this->_command; $command = $this->_command;
} else { } else {
$this->_command = $command; $this->_command = $command;
} }
$attrs = array(); $attrs = array();
$output->startElement($state->getURI(), $command, $attrs); $strict_xml = strtolower($this->_contentFormat) == 'strictxml';
$output->startElement($state->getURI(), $command, $attrs);
$output->startElement($state->getURI(), 'CmdID', $attrs);
$output->characters($currentCmdID); $output->startElement($state->getURI(), 'CmdID', $attrs);
$output->endElement($state->getURI(), 'CmdID'); $output->characters($currentCmdID);
$output->endElement($state->getURI(), 'CmdID');
/*
if (isset($this->_contentType)) { if (isset($this->_content) && !$this->_moreData) {
$output->startElement($state->getURI(), 'Meta', $attrs); //$this->_content = trim($this->_content);
$output->startElement($state->getURIMeta(), 'Type', $attrs); $this->_contentSize = strlen($this->_content);
$output->characters($this->_contentType); if (strtolower($this->_contentFormat) == 'b64') {
$output->endElement($state->getURIMeta(), 'Type'); $this->_content = base64_encode($this->_content);
$output->endElement($state->getURI(), 'Meta'); }
} } else {
*/ $this->_contentSize = 0;
if (isset($this->_content) && !$this->_moreData) { }
//$this->_content = trim($this->_content);
$this->_contentSize = strlen($this->_content); // <command><Meta>
if (strtolower($this->_contentFormat) == 'b64') { if ($this->_contentSize || isset($this->_contentType) ||
$this->_content = base64_encode($this->_content); (!$strict_xml && isset($this->_contentFormat))) {
} $output->startElement($state->getURI(), 'Meta', $attrs);
} else { if (isset($this->_contentType)) {
$this->_contentSize = 0; $output->startElement($state->getURIMeta(), 'Type', $attrs);
} $output->characters($this->_contentType);
$output->endElement($state->getURIMeta(), 'Type');
// <command><Meta> }
if ($this->_contentSize || isset($this->_contentType) || isset($this->_contentFormat)) { if (!$strict_xml && isset($this->_contentFormat)) {
$output->startElement($state->getURI(), 'Meta', $attrs); $output->startElement($state->getURIMeta(), 'Format', $attrs);
if (isset($this->_contentType)) { $output->characters($this->_contentFormat);
$output->startElement($state->getURIMeta(), 'Type', $attrs); $output->endElement($state->getURIMeta(), 'Format');
$output->characters($this->_contentType); }
$output->endElement($state->getURIMeta(), 'Type'); if ($this->_contentSize) {
} $output->startElement($state->getURIMeta(), 'Size', $attrs);
if (isset($this->_contentFormat)) { $output->characters(($this->_contentSize));
$output->startElement($state->getURIMeta(), 'Format', $attrs); $output->endElement($state->getURIMeta(), 'Size');
$output->characters($this->_contentFormat); }
$output->endElement($state->getURIMeta(), 'Format'); $output->endElement($state->getURI(), 'Meta');
} }
if ($this->_contentSize) {
$output->startElement($state->getURIMeta(), 'Size', $attrs); if (isset($this->_content) || isset($this->_luid) || isset($this->_guid)) {
$output->characters(($this->_contentSize)); $output->startElement($state->getURI(), 'Item', $attrs);
$output->endElement($state->getURIMeta(), 'Size');
} // <command><Item><Source><LocURI>
$output->endElement($state->getURI(), 'Meta'); if (isset($this->_guid)) {
} $output->startElement($state->getURI(), 'Source', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs);
if (isset($this->_content) || isset($this->_luid) || isset($this->_guid)) { $chars = substr($this->_guid, 0, $maxGUIDSize);
$output->startElement($state->getURI(), 'Item', $attrs); $state->setUIDMapping($this->_guid, $chars);
$output->characters($chars);
// <command><Item><Source><LocURI> $output->endElement($state->getURI(), 'LocURI');
if (isset($this->_guid)) { $output->endElement($state->getURI(), 'Source');
$output->startElement($state->getURI(), 'Source', $attrs); }
$output->startElement($state->getURI(), 'LocURI', $attrs);
$chars = substr($this->_guid, 0, $maxGUIDSize); // <command><Item><Target><LocURI>
$state->setUIDMapping($this->_guid, $chars); if (isset($this->_luid)) {
$output->characters($chars); $output->startElement($state->getURI(), 'Target', $attrs);
$output->endElement($state->getURI(), 'LocURI'); $output->startElement($state->getURI(), 'LocURI', $attrs);
$output->endElement($state->getURI(), 'Source'); $output->characters($this->_luid);
} $output->endElement($state->getURI(), 'LocURI');
$output->endElement($state->getURI(), 'Target');
// <command><Item><Target><LocURI> }
if (isset($this->_luid)) {
$output->startElement($state->getURI(), 'Target', $attrs);
$output->startElement($state->getURI(), 'LocURI', $attrs); // <command><Item><Data>
$output->characters($this->_luid); if (isset($this->_content)) {
$output->endElement($state->getURI(), 'LocURI'); $output->startElement($state->getURI(), 'Data', $attrs);
$output->endElement($state->getURI(), 'Target'); $currentSize = $output->getOutputSize();
} Horde::logMessage("SyncML: $command: current = $currentSize, max = $maxMsgSize", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if (!$maxMsgSize ||
(($currentSize + MIN_MSG_LEFT + $this->_contentSize + 12) <= $maxMsgSize)) {
// <command><Item><Data> $chars = $this->_content;
if (isset($this->_content)) { unset($this->_content);
$output->startElement($state->getURI(), 'Data', $attrs); $this->_moreData = false;
#$chars = '<![CDATA['.$this->_content.']]>'; } else {
$currentSize = $output->getOutputSize(); $sizeLeft = $maxMsgSize - $currentSize - MIN_MSG_LEFT - 12;
Horde::logMessage("SyncML: $command: current = $currentSize, max = $maxMsgSize", __FILE__, __LINE__, PEAR_LOG_DEBUG); if ($sizeLeft < 0) {
if (!$maxMsgSize || Horde::logMessage("SyncML: $command: split with $currentSize for $maxMsgSize, increase MIN_MSG_LEFT!", __FILE__, __LINE__, PEAR_LOG_WARNING);
(($currentSize + MIN_MSG_LEFT + $this->_contentSize) <= $maxMsgSize)) { $sizeLeft = 0;
$chars = $this->_content; }
unset($this->_content); // don't let us loose characters by trimming
$this->_moreData = false; while (($this->_contentSize > $sizeLeft) &&
} else { (strlen(trim(substr($this->_content, $sizeLeft - 1, 2))) < 2)) {
$sizeLeft = $maxMsgSize - $currentSize - MIN_MSG_LEFT; Horde::logMessage("SyncML: $command: split at $sizeLeft hit WS!", __FILE__, __LINE__, PEAR_LOG_DEBUG);
if ($sizeLeft < 0) { $sizeLeft++;
Horde::logMessage("SyncML: $command: split with $currentSize for $maxMsgSize, increase MIN_MSG_LEFT!", __FILE__, __LINE__, PEAR_LOG_WARNING); }
$sizeLeft = 0; $chars = substr($this->_content, 0, $sizeLeft);
} $this->_content = substr($this->_content, $sizeLeft, $this->_contentSize - $sizeLeft);
// don't let us loose characters by trimming Horde::logMessage("SyncML: $command: "
while (($this->_contentSize > $sizeLeft) && . $this->_contentSize . " split at $sizeLeft:\n"
(strlen(trim(substr($this->_content, $sizeLeft - 1, 2))) < 2)) {
Horde::logMessage("SyncML: $command: split at $sizeLeft hit WS!", __FILE__, __LINE__, PEAR_LOG_DEBUG);
$sizeLeft++;
}
$chars = substr($this->_content, 0, $sizeLeft);
$this->_content = substr($this->_content, $sizeLeft, $this->_contentSize - $sizeLeft);
Horde::logMessage("SyncML: $command: "
. $this->_contentSize . " split at $sizeLeft:\n"
. $chars, __FILE__, __LINE__, PEAR_LOG_DEBUG); . $chars, __FILE__, __LINE__, PEAR_LOG_DEBUG);
$this->_moreData = true; $this->_moreData = true;
} }
$output->characters($chars); if ($strict_xml) {
$output->endElement($state->getURI(), 'Data'); $chars = '<![CDATA['. $chars. ']]>';
}
// <command><Item><MoreData/> $output->characters($chars);
if ($this->_moreData) { $output->endElement($state->getURI(), 'Data');
$output->startElement($state->getURI(), 'MoreData', $attrs);
$output->endElement($state->getURI(), 'MoreData'); // <command><Item><MoreData/>
} if ($this->_moreData) {
} $output->startElement($state->getURI(), 'MoreData', $attrs);
$output->endElement($state->getURI(), 'Item'); $output->endElement($state->getURI(), 'MoreData');
} }
}
$output->endElement($state->getURI(), $command); $output->endElement($state->getURI(), 'Item');
}
$currentCmdID++;
$output->endElement($state->getURI(), $command);
return $currentCmdID;
} $currentCmdID++;
return $currentCmdID;
}
} }

View File

@ -838,6 +838,8 @@ class Horde_SyncML_State {
$manufacturer = isset($deviceInfo['manufacturer']) ? strtolower($deviceInfo['manufacturer']) : 'unknown'; $manufacturer = isset($deviceInfo['manufacturer']) ? strtolower($deviceInfo['manufacturer']) : 'unknown';
switch ($manufacturer) { switch ($manufacturer) {
case 'funambol': case 'funambol':
// Funambol requires well-formed XML
$res['ContentFormat'] = 'strictxml';
switch (strtolower($deviceInfo['model'])) { switch (strtolower($deviceInfo['model'])) {
case 'thunderbird': case 'thunderbird':
case 'mozilla plugin': case 'mozilla plugin':
@ -853,6 +855,9 @@ class Horde_SyncML_State {
break; break;
} }
break; break;
case 'patrick ohly':
// SyncEvolution requires well-formed XML, too
$res['ContentFormat'] = 'strictxml';
default: default:
$res['mayFragment'] = 1; $res['mayFragment'] = 1;
break; break;