rpc.php in horde's main directory is the starting point for our (and any)
RPC call.

It determines the $serverType ("syncml" for us) and then does something
like this:

$server = Horde_RPC::factory($serverType); // [will include RPC/syncml.php and create the class therein]
$server->authorize();
$input = $server->getInput(); // [basically the HTTP POST data]
$out = $server->getResponse($input, $params);
echo $out

So the main part takes place in getResponse of
framework/RPC/RPC/syncml.php's Horde_RPC_syncml class and there in
getResponse:


First, XML_WBXML_ContentHandler is installed as an output content handler:

$this->output = new XML_WBXML_ContentHandler();

Despite the name, this class has (almost) nothing to do with WBXML.
It's a helper to produce xml. To do this, it has 4 main methods:

1) startElement($uri, $element, $attrs) produces an <$element xlmns=$uri
   attr1=v1 ...> opening tag
2) characters($str) addes $str to the content
3) endElement($uri, $element) produces a closing tag </$element>
4) getOutput() returns the output produced so far

All subsequent code produces output by calling functions 1)-3)

After installing the output content handler, Horde_RPC_syncml::getResponse
continues with

$this->_parse($request);

do do the actual parsing and output creation and then finally

$xmlinput = $this->output->getOutput();

to retrieve the created output from the content handler.
The name $xmlinput is misleading, it should be called xmloutput instead.

So our quest for the code continues withing the Horde_RPC_syncml's _parse
function:

It creates an XML Parser and registers the class (well, the object) itself
as element handlers:
_startElement,_endElement, and _characters, which only format the data a
bit and call startElement,endElement, and characters respectively.

Please note, that start/endElment sounding functions are used for processing
the input as well as for creation of the output.
This can be somewhat confusing. As a rule of thumb, code that produces xml
output contains reference to an output var and looks like this:

$this->output->startElement(...);

After the XML parser is istalled, it is fired and the execution takes place
in the element handler functions.

A syncml message (input as well as output) has this structure::

  <SyncML>
    <SyncHdr>
      ...stuff...
    </SyncHdr>
    <SyncBody>
      ...stuff...
    </SyncBody>
  <SyncML>

the content handler in Horde_RPC_syncml delegate the work for header and
body to the two sub-content handlers SyncML_SyncMLHdr and
SyncML_SyncMLBody which reside in framework/SyncML/SyncML.php.
So at least we made it to the to the SyncML package by now...

The job of SyncML_SyncMLHdr is to read all the values in the header
and store them in a php session (custom session, not normal horde session
system) of type SyncML_State. After all header data is collected,
outputSyncHdr write a SyncHdr as output.

SyncML_SyncMLBody is another delegator. First it creates a
SyncML_Command_Status to output the status-code of the session
(authorized or not).
The content of the <syncBody> element are command(-tags): for each element
in there, an appropriate handler is created with
SyncML_Command::factory($element);
and assigned the tasks of handling this command.
So execution continues with classes in SyncML/Command/ which are
all children of SyncML_Command.

>From here, you're on your own. Just two more facts:

1)
processing of changes received from the client are handled in
SyncML/Sync.php (not to be confused with SyncML/Command/Sync.php) and
there in runSyncCommand($command) command is one of
SyncML_Command_Sync_(Add|Delete|Replace)

2)
The other way around:
creating changes on the server for the client is done after the changes
from the client have been processed. This is done in TwoWaySync.php.
Some care has to be taken to avoid that the changes that are received
from the client are considered "new changes" and echoed back to the
client. That would result in severe data duplication meltdown.