The backend provides the following groups of functions:
1) Access to the datastore
Reading, adding, replacing and deleting of entries. Also retrieve
information about changes in data store. This is done via the
retrieveEntry(), addEntry(), replaceEntry(), deleteEntry() and
getServerChanges() methods.
2) User management functions
This is the checkAuthentication() method to verify that a given user
password combination is allowed to access the backend data store, and
the setUser() method which does a "login" to the backend data store if
required by the type of backend data store. Please note that the
password is only transferred once in a sync session, so when handling
the subsequent packets messages, the user may need to be "logged in"
without a password. (Or the session management keeps the user "logged
in").
3) Maintainig the client ID <-> server ID map
The SyncML protocol does not require clients and servers to use the same
primary keys for the data entries. So a map has to be in place to
convert between client primary keys (called cuid's here) and server
primary keys (called suid's). It's up to the server to maintain this
map. Method for this is createUidMap().
4) Sync anchor handling
After a successful initial sync, the client and server sync timestamps
are stored. This allows to perform subsequent syncs as delta syncs,
where only new changes are replicated. Servers as well as clients need
to be able to store two sync anchors (the client's and the server's) for
a sync. Methods for this are readSyncAnchors() and writeSyncAnchors().
5) Test supporting functions
The SyncML module comes with its own testing framework. All you need to
do is implement the two methods testSetup() and testTearDown() and you
are able to test your backend with all the test cases that are part of
the module.
6) Miscellaneous functions
This involves session handling (sessionStart() and sessionClose()),
logging (logMessage() and logFile()), timestamp creation
(getCurrentTimeStamp()), charset handling (getCharset(), setCharset())
and database identification (isValidDatabaseURI()). For all of these
functions, a default implementation is provided in Horde_SyncMl_Backend.
If you want to create a backend for your own appliction, you can either
derive from Horde_SyncMl_Backend and implement everything in groups 1 to 5
or you derive from Horde_SyncMl_Backend_Sql which implements an example
backend based on direct database access using the PEAR MDB2 package. In this
case you only need to implement groups 1 to 3 and can use the implementation
from Horde_SyncMl_Backend_Sql as a guideline for these functions.
Key Concepts
------------
In order to successfully create a backend, some understanding of a few key
concepts in SyncML and the Horde_SyncMl package are certainly helpful. So
here's some stuff that should make some issues clear (or at lest less
obfuscated):
1) DatabaseURIs and Databases
The SyncML protocol itself is completly independant from the data that
is replicated. Normally the data are calendar or address book entries
but it may really be anything from browser bookmarks to comeplete
database tables. An ID (string name) of the database you want to
actually replicate has to be configured in the client. Typically that's
something like 'calendar' or 'tasks'. Client and server must agree on
these names. In addition this string may be used to provide additional
arguments. These are provided in a HTTP GET query style: like
tasks?ignorecompletedtasks to replicate only pending tasks. Such a "sync
identifier" is called a DatabaseURI and is really a database name plus
some additional options.
The Horde_SyncMl package completly ignores these options and simply passes
them on to the backend. It's up to the backend to decide what to do with
them. However when dealing with the internal maps (cuid<->suid and sync
anchors), it's most likely to use the database name only rather than the
full databaseURI. The map information saying that server entry
20070101203040xxa@mypc.org has id 768 in the client device is valid for
the database "tasks", not for "tasks?somesillyoptions". So what you
normally do is calling some kind of
$database =
$this->normalize($databaseURI) in every backend method that deals
with databaseURIs and use $database afterwards. However actual usage of
options is up to the backend implementation. SyncML works fine without.
2) Suid and Guid mapping
This is the mapping of client IDs to server IDs and vice versa. Please
note that this map is per user and per client device: the server entry
20070101203040xxa@mypc.org may have ID 720 in your PDA and AA10FC3A in
your mobile phone.
3) Sync Anchors
Datei:
Syncml.php
Projekt:
horde/horde
Datei:
Syncml.php
Projekt:
horde/horde
Datei:
testpacket.php
Projekt:
raz0rsdge/horde
Datei:
Horde.php
Projekt:
raz0rsdge/horde
Datei:
testsync.php
Projekt:
horde/horde
Datei:
Sql.php
Projekt:
jubinpatel/horde