summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING37
-rw-r--r--configure-pre.in2
-rw-r--r--src/Makefile-gen.am2
-rw-r--r--src/core/EvolutionSyncClient.cpp293
-rw-r--r--src/core/EvolutionSyncSource.h2
-rw-r--r--src/core/Makefile.am4
-rwxr-xr-xsrc/sunbird_client.xml821
-rw-r--r--src/syncevolution.xml883
-rw-r--r--src/syncserv_odbc.xml2558
9 files changed, 4589 insertions, 13 deletions
diff --git a/HACKING b/HACKING
index 9b03f799..bc72b112 100644
--- a/HACKING
+++ b/HACKING
@@ -1,3 +1,40 @@
+Synthesis Branch
+----------------
+
+Compile and install Synthesis SDK in directory "foo".
+
+Configure SyncEvolution with
+ SYNTHESIS_CFLAGS=-Ifoo/include SYNTHESIS_LIBS=-Lfoo/lib -lsynthesissdk
+
+Create a syncevolution.xml config file in the current
+directory, see src/syncevolution.xml.
+
+Run syncevolution with LD_LIBRARY_PATH=foo/lib:SDK_PATH/SDK/bin/Linux
+where SDK_PATH is the installation directory of the official Synthesis
+SDK (only necessary if .xml config refers to some of those modules).
+
+Currently none of the SyncEvolution backends are connected to Synthesis,
+so one has to configure a dummy file backend and use the SDK_textdb.so
+to handle the data.
+
+Example config: $ ./syncevolution --print-config --quiet funambol_1
+
+syncURL = http://my.funambol.com/sync
+username = xxxx
+password = yyyy
+logdir = /tmp
+useProxy = 1
+proxyHost = http://proxy.isw.intel.com:911
+deviceId = sc-pim-3e43622c-2e38-477a-9a9d-29ce45aba78c
+
+[addressbook]
+sync = two-way
+type = file:text/x-calendar:1.0
+evolutionsource = file:///home/pohly/funambol/addressbook
+uri = card
+
+
+
Checking out the Source
-----------------------
diff --git a/configure-pre.in b/configure-pre.in
index dfeb699f..b7109727 100644
--- a/configure-pre.in
+++ b/configure-pre.in
@@ -104,6 +104,8 @@ AC_ARG_ENABLE(maemo,
MODIFY_SYNCCOMPARE='-e "s/use encoding/#use encoding/;" -e "s/:utf8//;"'])
AC_SUBST(MODIFY_SYNCCOMPARE)
+PKG_CHECK_MODULES(SYNTHESIS, "synthesis")
+
AC_CHECK_HEADERS(signal.h dlfcn.h)
# cppunit needed?
diff --git a/src/Makefile-gen.am b/src/Makefile-gen.am
index 542566c3..c1583851 100644
--- a/src/Makefile-gen.am
+++ b/src/Makefile-gen.am
@@ -1,7 +1,7 @@
BACKENDS = @BACKENDS@
SUBDIRS = core $(BACKENDS)
-AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) @BACKEND_CPPFLAGS@ @FUNAMBOL_CFLAGS@
+AM_CPPFLAGS = $(SUBDIRS:%=-I$(srcdir)/%) @BACKEND_CPPFLAGS@ @FUNAMBOL_CFLAGS@ $(GLIB_CFLAGS)
# applies to sources in SyncEvolution repository, but not
# the Funambol C++ client library
diff --git a/src/core/EvolutionSyncClient.cpp b/src/core/EvolutionSyncClient.cpp
index 8c94e628..d77776c7 100644
--- a/src/core/EvolutionSyncClient.cpp
+++ b/src/core/EvolutionSyncClient.cpp
@@ -7,6 +7,7 @@
#include "SyncEvolutionUtil.h"
#include <posix/base/posixlog.h>
+#include <posix/http/CurlTransportAgent.h>
#include <list>
#include <memory>
@@ -28,6 +29,8 @@ using namespace std;
#include <dirent.h>
#include <errno.h>
+#include "synthesis/enginemodulebridge.h"
+
SourceList *EvolutionSyncClient::m_sourceListPtr;
EvolutionSyncClient::EvolutionSyncClient(const string &server,
@@ -342,6 +345,11 @@ public:
}
}
+ /** return log directory, empty if not enabled */
+ const string &getLogdir() {
+ return m_logdir.getLogdir();
+ }
+
/** return previous log dir found in setLogdir() */
const string &getPrevLogdir() const { return m_previousLogdir; }
@@ -813,23 +821,288 @@ int EvolutionSyncClient::sync()
// give derived class also a chance to update the configs
prepare(sourceList.getSourceArray());
- // ready to go: dump initial databases and prepare for final report
- sourceList.syncPrepare();
+ // ready to go: dump initial databases and prepare for final report
+ sourceList.syncPrepare();
- // do it
- res = SyncClient::sync(*this, sourceList.getSourceArray());
+ if (false) {
+ // do it
+ res = SyncClient::sync(*this, sourceList.getSourceArray());
- // store modified properties: must be done even after failed
- // sync because the source's anchor might have been reset
- flush();
+ // store modified properties: must be done even after failed
+ // sync because the source's anchor might have been reset
+ flush();
- if (res) {
+ if (res) {
if (getLastErrorCode() && getLastErrorMsg() && getLastErrorMsg()[0]) {
- throwError(getLastErrorMsg());
+ throwError(getLastErrorMsg());
}
// no error code/description?!
throwError("sync failed without an error description, check log");
- }
+ }
+ } else {
+ // Synthesis SDK
+ sysync::TEngineModuleBridge engine;
+ sysync::TSyError err;
+
+ // Use libsynthesis that we were linked against. The name
+ // of a .so could be given here, too, to use that instead.
+ err = engine.Connect("[]", 0, 0);
+ if (err) {
+ throwError("Connect");
+ }
+
+ sysync::appPointer keyH;
+ sysync::appPointer subkeyH;
+ string s;
+
+ err = engine.OpenKeyByPath(keyH, NULL, "/configvars", 0);
+ if (err) {
+ throwError("open config vars");
+ }
+ engine.SetStrValue(keyH, "defout_path", sourceList.getLogdir());
+ engine.SetStrValue(keyH, "device_uri", getDevID());
+ engine.SetStrValue(keyH, "device_name", getDevType());
+ // TODO: redirect to log file?
+ engine.SetStrValue(keyH, "conferrpath", "console");
+ engine.CloseKey(keyH);
+
+ string xmlConfig("syncevolution.xml");
+ err = engine.InitEngineFile(xmlConfig.c_str());
+ if (err) {
+ throwError(xmlConfig);
+ }
+
+ err = engine.OpenKeyByPath(keyH, NULL, "/profiles", 0);
+ if (err) {
+ throwError("open profiles");
+ }
+
+ // check the settings status (MUST BE DONE TO MAKE SETTINGS READY)
+ err = engine.GetStrValue(keyH, "settingsstatus", s);
+ // allow creating new settings when existing settings are not up/downgradeable
+ err = engine.SetStrValue(keyH, "overwrite", "1" );
+ // check status again
+ err = engine.GetStrValue(keyH, "settingsstatus", s);
+
+ // open first profile
+ err = engine.OpenSubkey(subkeyH, keyH, KEYVAL_ID_FIRST, 0);
+ if (err == 204) { // DB_NoContent
+ // no profile already exists, create default profile
+ err = engine.OpenSubkey(subkeyH, keyH, KEYVAL_ID_NEW_DEFAULT, 0);
+ }
+ if (err) {
+ throwError("open first profile");
+ }
+
+ engine.SetStrValue(subkeyH, "serverURI", getSyncURL());
+ engine.SetStrValue(subkeyH, "serverUser", getUsername());
+ engine.SetStrValue(subkeyH, "serverPassword", getPassword());
+
+ // TODO: remove hard-coded XML encoding as soon as out transport
+ // can post WBXML and XML (currently limited to XML)
+ engine.SetInt32Value(subkeyH, "encoding", 2);
+
+ // Iterate over all data stores in the XML config
+ // and match them with sync sources.
+ // TODO: let sync sources provide their own
+ // XML snippets (inside <client> and inside <datatypes>).
+ sysync::appPointer targetsH, targetH;
+ err = engine.OpenKeyByPath(targetsH, subkeyH, "targets", 0);
+ if (err) {
+ throwError("targets");
+ }
+ err = engine.OpenSubkey(targetH, targetsH, KEYVAL_ID_FIRST, 0);
+ while (err != 204) {
+ if (err) {
+ throwError("reading target");
+ }
+ err = engine.GetStrValue(targetH, "dbname", s);
+ if (err) {
+ throwError("reading target name");
+ }
+ EvolutionSyncSource *source = sourceList[s];
+ if (source) {
+ engine.SetInt32Value(targetH, "enabled", 1);
+ int slow = 0;
+ int direction = 0;
+ string mode = source->getSync();
+ if (!strcasecmp(mode.c_str(), "slow")) {
+ slow = 1;
+ direction = 0;
+ } else if (!strcasecmp(mode.c_str(), "two-way")) {
+ slow = 0;
+ direction = 0;
+ } else if (!strcasecmp(mode.c_str(), "refresh-from-server")) {
+ slow = 1;
+ direction = 1;
+ } else if (!strcasecmp(mode.c_str(), "refresh-from-client")) {
+ slow = 1;
+ direction = 2;
+ } else if (!strcasecmp(mode.c_str(), "one-way-from-server")) {
+ slow = 0;
+ direction = 1;
+ } else if (!strcasecmp(mode.c_str(), "one-way-from-client")) {
+ slow = 0;
+ direction = 2;
+ } else {
+ source->throwError(string("invalid sync mode: ") + mode);
+ }
+ engine.SetInt32Value(targetH, "forceslow", slow);
+ engine.SetInt32Value(targetH, "syncmode", direction);
+
+ engine.SetStrValue(targetH, "remotepath", source->getURI());
+ } else {
+ engine.SetInt32Value(targetH, "enabled", 0);
+ }
+ engine.CloseKey(targetH);
+ err = engine.OpenSubkey(targetH, targetsH, KEYVAL_ID_NEXT, 0);
+ }
+ engine.CloseKey(targetsH);
+ engine.CloseKey(subkeyH);
+ engine.CloseKey(keyH);
+
+ // run an HTTP client sync session
+ Proxy proxy;
+ if (getUseProxy()) {
+ proxy.setProxy(getProxyHost(),
+ getProxyPort(),
+ getProxyUsername(),
+ getProxyPassword());
+ }
+ URL url;
+ CurlTransportAgent agent(url, proxy,
+ getResponseTimeout());
+ agent.setUserAgent(getUserAgent());
+ // TODO: SSL settings
+
+ sysync::appPointer sessionH;
+ sysync::TEngineProgressInfo progressInfo;
+ sysync::uInt16 stepCmd = STEPCMD_CLIENTSTART; // first step
+ err = engine.OpenSession(sessionH, 0, "syncevolution_session");
+ if (err) {
+ throwError("OpenSession");
+ }
+
+ // sync main loop
+ char *received = NULL;
+ do {
+ // take next step
+ err = engine.SessionStep(sessionH, stepCmd, &progressInfo);
+ if (err != LOCERR_OK) {
+ // error, terminate with error
+ stepCmd = STEPCMD_ERROR;
+ } else {
+ // step ran ok, evaluate step command
+ switch (stepCmd) {
+ case STEPCMD_OK:
+ // no progress info, call step again
+ stepCmd = STEPCMD_STEP;
+ break;
+ case STEPCMD_PROGRESS:
+ // new progress info to show
+ // Check special case of interactive display alert
+ if (progressInfo.eventtype==PEV_DISPLAY100) {
+ // alert 100 received from remote, message text is in
+ // SessionKey's "displayalert" field
+ sysync::appPointer sessionKeyH;
+ err = engine.OpenSessionKey(sessionH, sessionKeyH, 0);
+ if (err != LOCERR_OK) {
+ throwError("session key");
+ }
+ // get message from server to display
+ engine.GetStrValue(sessionKeyH,
+ "displayalert",
+ s);
+ LOG.info("message from server: %s",
+ s.c_str());
+ engine.CloseKey(sessionKeyH);
+ } else {
+ // normal progress info
+ // tbd: show progress in the UI
+ }
+ stepCmd = STEPCMD_STEP;
+ break;
+ case STEPCMD_ERROR:
+ // error, terminate (should not happen, as status is
+ // already checked above)
+ break;
+ case STEPCMD_RESTART:
+ // make sure connection is closed and will be re-opened for next request
+ // tbd: close communication channel if still open to make sure it is
+ // re-opened for the next request
+ stepCmd = STEPCMD_STEP;
+ break;
+ case STEPCMD_SENDDATA: {
+ // send data to remote
+
+ // use OpenSessionKey() and GetValue() to retrieve "connectURI"
+ // and "contenttype" to be used to send data to the server
+ sysync::appPointer sessionKeyH;
+ err = engine.OpenSessionKey(sessionH, sessionKeyH, 0);
+ if (err != LOCERR_OK) {
+ throwError("session key");
+ }
+ engine.GetStrValue(sessionKeyH,
+ "connectURI",
+ s);
+ URL newurl(s.c_str());
+ agent.setURL(newurl);
+ string contenttype;
+ engine.GetStrValue(sessionKeyH,
+ "contenttype",
+ contenttype);
+ engine.CloseKey(sessionKeyH);
+
+ // use GetSyncMLBuffer()/RetSyncMLBuffer() to access the data to be
+ // sent or have it copied into caller's buffer using
+ // ReadSyncMLBuffer(), then send it to the server
+ sysync::appPointer buffer;
+ sysync::memSize length;
+ err = engine.GetSyncMLBuffer(sessionH, true, buffer, length);
+ if (err) {
+ throwError("buffer");
+ }
+ // need temporary null-terminated string for agent
+ string tmp;
+ tmp.append((const char *)buffer, 0, length);
+ received = agent.sendMessage(tmp.c_str());
+ engine.RetSyncMLBuffer(sessionH, true, length);
+
+ // status for next step
+ if (received) {
+ stepCmd = STEPCMD_SENTDATA; // we have sent the data and received response
+ } else {
+ stepCmd = STEPCMD_TRANSPFAIL; // communication with server failed
+ }
+ break;
+ }
+ case STEPCMD_NEEDDATA:
+ // put answer received earlier into SyncML engine's buffer
+ if (received) {
+ err = engine.WriteSyncMLBuffer(sessionH, received, strlen(received));
+ if (err) {
+ throwError("write buffer");
+ }
+ delete [] received;
+ received = NULL;
+ stepCmd = STEPCMD_GOTDATA; // we have received response data
+ } else {
+ stepCmd = STEPCMD_TRANSPFAIL; // communication with server failed
+ }
+ break;
+ } // switch stepcmd
+ }
+ // check for suspend or abort, if so, modify step command for next step
+ if (false /* tdb: check if user requests suspending the session */) {
+ stepCmd = STEPCMD_SUSPEND;
+ }
+ if (false /* tdb: check if user requests aborting the session */) {
+ stepCmd = STEPCMD_ABORT;
+ }
+ // loop until session done or aborted with error
+ } while (stepCmd!=STEPCMD_DONE && stepCmd!=STEPCMD_ERROR);
+ engine.CloseSession(sessionH);
+ }
// all went well: print final report before cleaning up
sourceList.syncDone(true);
diff --git a/src/core/EvolutionSyncSource.h b/src/core/EvolutionSyncSource.h
index 8852e99a..bf7615e4 100644
--- a/src/core/EvolutionSyncSource.h
+++ b/src/core/EvolutionSyncSource.h
@@ -574,6 +574,7 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig
ESource *findSource( ESourceList *list, const string &id );
#endif
+ public:
#ifdef HAVE_EDS
/**
* throw an exception after an operation failed and
@@ -610,6 +611,7 @@ class EvolutionSyncSource : public SyncSource, public EvolutionSyncSourceConfig
*/
void throwError(const string &failure);
+ protected:
const string m_changeId;
class Items : public set<string> {
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 7688489c..2c37b38f 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -68,8 +68,8 @@ CORE_SOURCES = \
$(VOCL_SOURCES)
libsyncevolution_la_SOURCES = $(CORE_SOURCES)
-libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ @FUNAMBOL_LIBS@ @TRANSPORT_LDFLAGS@ @LIBS@
-libsyncevolution_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS)
+libsyncevolution_la_LIBADD = @EPACKAGE_LIBS@ @GLIB_LIBS@ @FUNAMBOL_LIBS@ @TRANSPORT_LDFLAGS@ @LIBS@ $(SYNTHESIS_LIBS)
+libsyncevolution_la_CXXFLAGS = $(SYNCEVOLUTION_CXXFLAGS) $(SYNTHESIS_CFLAGS)
# include boost in distribution
dist-hook:
diff --git a/src/sunbird_client.xml b/src/sunbird_client.xml
new file mode 100755
index 00000000..94468660
--- /dev/null
+++ b/src/sunbird_client.xml
@@ -0,0 +1,821 @@
+<?xml version="1.0"?>
+<!-- SYNTHESIS SYNC CLIENT Version 3.1 Configuration file -->
+<!-- (works for V3.1.1.0 and later) -->
+
+<sysync_config version="1.0">
+
+ <configvar platform="win32" name="logpath" value="$(exedir_path)\sysynclogs"/>
+ <configvar platform="macosx" name="logpath" value="$(userdir_path)/sysynclogs"/>
+
+ <configvar platform="macosx" name="targetdb" value="sunbird"/> <!-- %%% mac does not have that yet -->
+
+ <!-- enter your license details here. Not all versions need a
+ license (for example the demo runs without one).
+ You should have received license code information
+ along with the purchase or evaluation package.
+ If not, please contact sales@synthesis.ch
+ <licensename>your license text here</licensename>
+ <licensecode>YOUR-LICE-NSES-CODE</licensecode>
+ -->
+
+ <!-- this string is output to every session debug logfile to identify the config in use -->
+ <configidstring>Sunbird/Lightning 0.5 client demo using SQLite direct access</configidstring>
+
+ <debug>
+ <!-- path where logfiles are stored -->
+ <logpath>$(logpath)</logpath>
+ <logflushmode>flush</logflushmode> <!-- buffered is fastest mode, but may loose data on process abort. Other options: "flush" (after every line) or "openclose" (safest, slowest, like in 2.x server) -->
+ <!-- per session log -->
+ <sessionlogs>yes</sessionlogs> <!-- by default, create a session log file for every sync session (might be disabled for special users/devices in scripts) -->
+ <!-- debug format options -->
+ <logformat>html</logformat> <!-- html is nicely colored and easily viewable with a web browser. Other options: "xml", "text" -->
+ <timestamp>yes</timestamp> <!-- show timestamps for structure elements in log -->
+ <timestampall>no</timestampall> <!-- don't show timestamp for every log line -->
+ <timedsessionlognames>yes</timedsessionlognames> <!-- session logs also have the session start timestamp in the filename - makes them more easily sortable -->
+ <!-- thread logging mode -->
+ <subthreadmode>separate</subthreadmode> <!-- write log info from subthreads into separate log files. Other options: "suppress" -->
+ <!-- basic debug level selection -->
+ <enable option="extended"/> <!-- "extended" is a good choice for start testing. For production, use "normal" or "minimal" -->
+ <!-- <enable option="normal"/> --> <!-- "normal" provides rich debug info, but still in reasonable size -->
+ <!-- <enable option="minimal"/> --> <!-- "minimal" just shows basic flow and error. Not suitable for debugging -->
+ <!-- <enable option="maximal"/> --> <!-- "maximal" can create VERY LARGE logs and cause HEAVY SLOWDOWN. Only for detail debugging -->
+ <!-- <enable option="all"/> --> <!-- "all" shows EVERYTHING possible, and way too much for any normal situation. For hardcore debugging ONLY! -->
+ <!-- additional debug info switches -->
+ <enable option="userdata"/> <!-- Make this <disable ...> if you don't want user data in the logs -->
+ <enable option="scripts"/> <!-- Make this <enable ...> to show script execution in logs -->
+ <disable option="exotic"/> <!-- Make this <enable ...> to include very in-detail info. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care! -->
+ <!-- see manual for more debug info switches -->
+ <!-- global log options -->
+ <globallogs>yes</globallogs> <!-- by default, do not log global session dispatching, creation etc. (not useful in multi-user operation) -->
+ <singlegloballog>no</singlegloballog> <!-- a new global log will be started for every start of the server/application -->
+ <!-- SyncML message dumping options -->
+ <msgdump>no</msgdump> <!-- do not dump syncml traffic 1:1 to files -->
+ <xmltranslate>no</xmltranslate> <!-- do not try to translate syncml traffic into XML (DO NOT SET THIS OPTION IN PRODUCTIVE SERVERS!) -->
+ </debug>
+
+ <!-- Note: since 2.1.1.5, clients have a <transport> section to specify <keepconnection> behaviour -->
+ <transport type="xpt">
+ <!-- allow HTTP 1.1 kepp-alive (multiple request-answer-exchanges in single TCP connection) -->
+ <keepconnection>true</keepconnection>
+ </transport>
+
+ <scripting>
+ <looptimeout>5</looptimeout>
+ </scripting>
+
+
+ <datatypes>
+
+
+ <!-- list of internal fields representing vCalendar data
+ (for both events (vEVENT) and tasks (vTODO)) -->
+ <fieldlist name="calendar">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+
+ <!-- this field defines if the data item is an EVENT or a TODO (task) -->
+ <field name="KIND" type="string" compare="always"/>
+
+ <field name="DMODIFIED" type="timestamp" compare="never" age="yes"/>
+ <field name="DCREATED" type="timestamp" compare="never"/>
+
+ <field name="CATEGORIES" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <field name="SUMMARY" type="multiline" compare="always"/>
+ <field name="DESCRIPTION" type="multiline" compare="slowsync" merge="lines"/>
+
+ <field name="ATTENDEES" array="yes" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <field name="LOCATION" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <!-- alarm -->
+ <field name="ALARM_TIME" type="timestamp" compare="conflict"/>
+ <field name="ALARM_SNOOZE" type="string" compare="conflict"/>
+ <field name="ALARM_REPEAT" type="string" compare="conflict"/>
+ <field name="ALARM_MSG" type="string" compare="conflict"/>
+
+ <!-- recurrence rule block, fields must be in that order, including
+ DTSTART as last field !! -->
+ <field name="RR_FREQ" type="string" compare="conflict"/>
+ <field name="RR_INTERVAL" type="integer" compare="conflict"/>
+ <field name="RR_FMASK" type="integer" compare="conflict"/>
+ <field name="RR_LMASK" type="integer" compare="conflict"/>
+ <field name="RR_END" type="timestamp" compare="conflict"/>
+
+ <!-- Note: DTSTART/DTEND are compared in the <comparescript>,
+ therefore compare is set no "never" here -->
+ <field name="DTSTART" type="timestamp" compare="never"/> <!-- also used as DUE in vTODO -->
+
+ <field name="DTEND" type="timestamp" compare="never"/>
+
+ <field name="ALLDAY" type="integer" compare="never"/>
+
+ <!-- exception dates to the recurrence rule -->
+ <field name="EXDATES" array="yes" type="timestamp" compare="conflict"/>
+
+ <!-- for tasks only -->
+ <field name="PRIORITY" type="integer" compare="conflict"/>
+ <field name="STATUS" type="string" compare="conflict" merge="fillempty"/>
+
+ </fieldlist>
+
+ <!-- vCalendar profile, including subprofiles for
+ both events (vEVENT) and tasks (vTODO) -->
+ <mimeprofile name="vcalendar" fieldlist="calendar">
+
+ <profile name="VCALENDAR" nummandatory="1">
+
+ <property name="VERSION" mandatory="yes">
+ <value conversion="version"/>
+ </property>
+
+ <property name="TZ" show="true" suppressempty="yes">
+ <value field="DTSTART" conversion="tz"/>
+ </property>
+
+ <property name="DAYLIGHT" mode="daylight" show="true" suppressempty="yes">
+ <value field="DTSTART" conversion="daylight"/>
+ </property>
+
+ <!-- sub-profile for events -->
+ <subprofile name="VEVENT" nummandatory="1" field="KIND" value="EVENT" showprops="true">
+
+ <property name="LAST-MODIFIED" delayedparsing="1">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes">
+ <value field="DCREATED"/>
+ </property>
+
+ <property name="CATEGORIES" suppressempty="yes">
+ <value field="CATEGORIES"/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes">
+ <value field="LOCATION"/>
+ </property>
+
+ <property name="DTSTART" suppressempty="yes">
+ <value field="DTSTART"/>
+ <!--
+ <parameter name="TZID" default="no" show="yes">
+ <value field="DTSTART" conversion="TZID"/>
+ </parameter>
+ -->
+ </property>
+
+ <property name="DTEND" suppressempty="yes">
+ <value field="DTEND"/>
+ <!--
+ <parameter name="TZID" default="no" show="yes">
+ <value field="DTEND" conversion="TZID"/>
+ </parameter>
+ -->
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes">
+ <value field="ATTENDEES"/>
+ <position field="ATTENDEES" repeat="ARRAY" increment="1" minshow="0"/>
+ </property>
+
+ <!-- recurrence rule (with delayed parsing, as it is dependent on DTSTART) -->
+ <property name="RRULE" suppressempty="yes" delayedparsing="1">
+ <!-- Note: RR_FREQ is the beginning of a block of fields
+ suitable for the "rrule" conversion mode -->
+ <value field="RR_FREQ" conversion="rrule"/>
+ </property>
+
+ <!-- up to five exceptions for recurrence rule -->
+ <property name="EXDATE" values="list" suppressempty="yes">
+ <value field="EXDATES"/>
+ <position field="EXDATES" repeat="ARRAY" increment="1" minshow="0"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ <!-- sub-profile for tasks (todo's) -->
+ <subprofile name="VTODO" nummandatory="1" field="KIND" value="TODO" showprops="true">
+
+ <property name="LAST-MODIFIED" show="false">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes" show="false">
+ <value field="DCREATED"/>
+ </property>
+
+ <property name="CATEGORIES" suppressempty="yes" show="false">
+ <value field="CATEGORIES"/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes" show="false">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes" show="false">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes" show="false">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes" show="false">
+ <value field="LOCATION"/>
+ </property>
+
+
+ <property name="DUE" suppressempty="yes" show="true">
+ <value field="DTSTART"/> <!-- we use DTSTART field for DUE property in tasks -->
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes" show="false">
+ <value field="ATTENDEES"/>
+ <position field="ATTENDEES" repeat="ARRAY" increment="1" minshow="0"/>
+ </property>
+
+ <property name="PRIORITY" suppressempty="yes" show="true">
+
+ <value field="PRIORITY"/>
+ </property>
+
+ <property name="STATUS" suppressempty="yes" show="true">
+ <value field="STATUS" conversion="emptyonly"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes" show="false">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes" show="false">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ <subprofile name="VTIMEZONE" mode="vtimezones" showprops="true"/>
+
+ </profile>
+ </mimeprofile>
+
+
+ <!-- vCalendar 1.0 datatype, using vCalendar profile defined
+ above -->
+ <datatype name="vcalendar10" basetype="vcalendar">
+ <version>1.0</version>
+ <use mimeprofile="vcalendar"/>
+
+ <!-- Scripting allows sophisticated data adjustment:
+ make sure we have always have a SUMMARY, but avoid
+ SUMMARY and DESCRIPTION being identical,
+ as well as always having a DTSTART
+ and an alarm message -->
+ <incomingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have at least a summary
+ if (SUMMARY==EMPTY) SUMMARY=DESCRIPTION; // use description if we don't have a summary
+ if (SUMMARY==EMPTY) SUMMARY="unnamed"; // set dummy summary if we still don't have one
+ if (DESCRIPTION==SUMMARY) DESCRIPTION=EMPTY; // do not save twice
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></incomingscript>
+
+ <outgoingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have both description AND summary
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ if (SUMMARY==EMPTY) SUMMARY="unnamed";
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ // make sure we have an alarm message
+ if (ALARM_TIME!=EMPTY && ALARM_MSG==EMPTY) ALARM_MSG="alarm";
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></outgoingscript>
+
+ </datatype>
+
+
+ </datatypes>
+
+
+ <client type="sql">
+
+ <binfilespath platform="win32">$(prefs_path)\synthesis.ch\syncml_client_$(targetdb)</binfilespath>
+
+ <sessioninitscript><![CDATA[
+ string s,res;
+ string matches[];
+ integer n;
+ integer h,m;
+
+ // %%% testing NUMFORMAT
+ h=2;
+ m=30;
+ DEBUGMESSAGE (NUMFORMAT(h,3,"0","+") + ":" + NUMFORMAT(m,2,"0"));
+ h=-2;
+ m=30;
+ DEBUGMESSAGE (NUMFORMAT(h,3,"0","+") + ":" + NUMFORMAT(m,2,"0"));
+ h=11;
+ m=30;
+ DEBUGMESSAGE (NUMFORMAT(h,3,"0","+") + ":" + NUMFORMAT(m,2,"$"));
+ h=11;
+ m=3;
+ DEBUGMESSAGE (NUMFORMAT(h,3,"0","+") + ":" + NUMFORMAT(m,-2,"x"));
+
+ // %%% testing regexps
+ s = "the quick brown fox faxes fudi fast";
+ /*
+ n = REGEX_FIND(s,"/QUICK/i",0);
+ n = REGEX_FIND(s,"/QUICK (.*) fox/i",0);
+ n = REGEX_FIND(s,"/(BroWN) (.*)/i",0);
+
+ n = REGEX_MATCH(s,"/(QUICK) (.*) fox/i",0,matches);
+ DEBUGMESSAGE(matches[0]);
+ DEBUGMESSAGE(matches[1]);
+ DEBUGMESSAGE(matches[2]);
+
+ res = REGEX_REPLACE(s,"/f(.)/","[F]\\1(\\2)",0,2); // 2 recurrences
+ DEBUGMESSAGE(res);
+ */
+
+ res = REGEX_REPLACE(s,"/f(.)/","[F]\\1(\\2)",0,0); // all
+ DEBUGMESSAGE(res);
+
+ ]]></sessioninitscript>
+
+
+ <!-- IMPORTANT: Note that the following charset, lineend and quoting settings are relevant for session-level data access only.
+ Most data access takes place in individual <datastores>, which each has the same three settings
+ again locally (see below in the <datastore> sections). -->
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- text db plugin is designed for Unix linefeeds (\n, 0x0A), make data is passed with unix linefeeds (and not the DOS CRLF = 0x0D,0x0A default) -->
+ <datalineends>unix</datalineends>
+
+ <!-- If you want a text logfile, specify its full path here: -->
+ <logfile platform="win32">$(logpath)\$(targetdb)_synclog.txt</logfile>
+
+ <!-- %%% mac does not have $(targetdb) yet -->
+ <logfile platform="macosx">$(logpath)/sunbirdsynclog.txt</logfile>
+
+ <logenabled>yes</logenabled> <!-- log enabled by default (session login scripts might disable it for special users/devices) -->
+
+ <!-- the logfile format can be customized with <loglabels> and <logformat>
+ but if these are not specified, a default format will be used
+ -->
+ <!-- This sample produces a simplified logfile:
+ <loglabels>SyncEndTime\tUser\tStatus\tSynctype\tRemoteName\tDatabase\tLocAdded\tLocUpdated\tLocDeleted\n\n</loglabels>
+ <logformat>%seT\t%U\t%sS\t%tS\t%nR\t%lD\t%laI\t%luI\t%ldI\n</logformat>
+ -->
+
+
+ <!-- timeout for unfinished sessions in seconds -->
+ <sessiontimeout>20</sessiontimeout>
+
+
+ <datastore name="events" type="sql">
+
+ <alertprepscript><![CDATA[
+ if (targetsetting("extras") & 1 == 1) {
+ setdaysrange(
+ targetsetting("limit1"),
+ targetsetting("limit2")
+ );
+ }
+ ]]></alertprepscript>
+
+ <dbtypeid>1001</dbtypeid> <!-- %%% DBID_MAPI_CONTACTS for now -->
+
+ <sqlitefile platform="win32">$(mozillaprofile)\storage.sdb</sqlitefile>
+
+ <!-- %%% mac does not have lightning support yet -->
+ <sqlitefile platform="macosx">$(prefs_path)/Sunbird/Profiles/$(sunbirdprofile)/storage.sdb</sqlitefile>
+
+ <lastmodfieldtype>unixtime_us</lastmodfieldtype>
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- text db plugin is designed for Unix linefeeds (\n, 0x0A), make data is passed with unix linefeeds (and not the DOS CRLF = 0x0D,0x0A default) -->
+ <datalineends>unix</datalineends>
+
+ <!-- specifies the time zone for timestamps stored in the database (UTC, SYSTEM, ...) -->
+ <datatimezone>UTC</datatimezone>
+
+ <!-- if set to yet, all timestamps read from the DB are converted to user time zone (from DB time zone) before sending to remote -->
+ <userzoneoutput>yes</userzoneoutput>
+
+ <!-- enable this one if the database needs all fields re-written for every UPDATE
+ operation (exotic Triggers etc.). Normally, this is not needed
+ (SyncML server will update only changed fields)
+ -->
+ <updateallfields>no</updateallfields>
+
+ <!-- If this is set to yes, the server will try to convert
+ the filter expressions to a WHERE clause which then can be used with %AF or %WF
+ in the <selectidandmodifiedsql> statement. In this sample it is set to "yes"
+ as it allows for efficient visibility control. It can be turned off if filters
+ are not suitable for being included in SQL -->
+ <dbcanfilter>yes</dbcanfilter>
+
+ <!-- statement that retrieves KEY and MODIFIED timestamp for all records to be synced.
+ Note that %AF or %WF must be included to make filtering work
+ -->
+ <selectidandmodifiedsql>SELECT id || coalesce(recurrence_id,'') as fullid,last_modified FROM cal_events %WF</selectidandmodifiedsql>
+
+ <!-- We use our own IDs as ROWIDs are not persistent in SunBird -->
+ <obtainidafterinsert>no</obtainidafterinsert>
+
+ <localidscript><![CDATA[
+ // create new ID from random plus time
+ return "SySync:" + NUMFORMAT(RANDOM(10000),4,"0") + "_" + (STRING)MILLISECONDS(NOW());
+ ]]></localidscript>
+
+ <!-- statements to read, insert, update and delete single records in the database
+ %N represents the name list of all mapped fields
+ %v represents the value list of all mapped fields
+ %V represents the name=value list of all mapped fields
+ %k represents the record key (CONTACTS_KEY, EVENTS_KEY...)
+ %f represents the folder key (see <folderkeysql> above)
+ -->
+ <selectdatasql>SELECT %N FROM cal_events WHERE id || coalesce(recurrence_id,'')='%k'</selectdatasql>
+ <insertdatasql>INSERT INTO cal_events (id,last_modified,time_created,%N,cal_id,priority,event_start_tz,event_end_tz) VALUES ('%k',%M,%M,%v,0,0,'/mozilla.org/20070129_1/Africa/Ceuta','/mozilla.org/20070129_1/Africa/Ceuta')</insertdatasql>
+ <updatedatasql>UPDATE cal_events SET last_modified=%M,%V WHERE id || coalesce(recurrence_id,'')='%k'</updatedatasql>
+ <deletedatasql>DELETE FROM cal_events WHERE id || coalesce(recurrence_id,'')='%k'</deletedatasql>
+
+ <!-- Database has combined Date/time field for saving time of last modification. -->
+ <modtimestamp>yes</modtimestamp>
+
+ <!-- filter to let only suitable vCalendar items pass -->
+ <acceptfilter>F.KIND:=EVENT</acceptfilter>
+
+ <!-- if set, SyncML DS 1.2 filtering is possible and will be indicated in server devInf -->
+ <ds12filters>yes</ds12filters>
+
+ <!-- if set, datastore supports filtering by a date range specification (SINCE,BEFORE or /dr())
+ Note: if this is set to yes, actual range filtering must be implemented in the datatype
+ and/or the datastore, usually with scripting. See <filterscript> for vCalendar above -->
+ <daterangesupport>yes</daterangesupport>
+
+
+ <!-- Mapping of the fields in SYNC_EVENTS to the common fieldlist "calendar"
+ which is shared between events and tasks -->
+ <fieldmap fieldlist="calendar">
+
+ <initscript><![CDATA[
+ // general vars
+ integer ok, version, daylist[], numelems, i, wd, rc, rcidx;
+ string s, dateslist[];
+ // flags
+ integer flags; // 0x08 = allday, 0x04 = must always be present
+ // recurrence params
+ string recur_type;
+ integer interval,count;
+ timestamp end_date,ts;
+ string day; // comma separated list of weekday as 1=Su, 2=Mo ... 7=Sa
+ // plus for monthly: 8*occurrence in month
+ // (e.g: 37 = 0x25 = 4th thursday, -13 = 0x0D = last thursday)
+ string monthday; // comma separated list of days in month
+ string dates; // for exception dates
+
+ // init random seed
+ RANDOM(1,NOW());
+
+ // init flags
+ flags = 4;
+
+ // check for correct schema version
+ SQLEXECUTE("select version from cal_calendar_schema_version");
+ ok = SQLFETCHROW();
+ if (ok) {
+ SQLGETCOLUMN(1,version,"numeric");
+ ok = version == 7; // this configuration is for SunBird 0.5 with schema version 7
+ }
+ SQLCOMMIT();
+ if (!ok) {
+ DEBUGMESSAGE("SunBird SQLite database has none or wrong schema version");
+ ABORTSESSION(510);
+ RETURN false; // fail the script
+ }
+ ]]></initscript>
+
+
+ <beforewritescript><![CDATA[
+ // create flags
+ flags = 0x04; // we need Bit2 always
+ // check for allay (non-floating timestamps checked in user time zone)
+ i = ALLDAYCOUNT(DTSTART,DTEND,true);
+ if (i>0) {
+ // all day - make dates span full day (required by SunBird)
+ flags = flags | 0x08; // set allday bit
+ DTSTART = CONVERTTOUSERZONE(DTSTART); // convert non-floating to user zone
+ SETFLOATING(DTSTART); // make floating
+ DTSTART = DATEONLY(DTSTART); // set to beginning of day
+ DTEND = DTSTART + DAYUNITS(i); // make end exact number of days after start
+ }
+ // check for recurrence
+ if (NORMALIZED(RR_FREQ)!=EMPTY)
+ flags = flags | 0x10; // set recurrence bit
+ ]]></beforewritescript>
+
+
+ <afterwritescript><![CDATA[
+ // update separately stored properties
+ // - delete all associated properties
+ SQLEXECUTE("DELETE FROM cal_properties WHERE (key='LOCATION' OR key='DESCRIPTION') AND item_id='%k'");
+ if (!DELETING()) {
+ // (re-)add properties
+ // - location
+ if (LOCATION!=EMPTY) {
+ SQLEXECUTE(
+ "INSERT INTO cal_properties (key,item_id,value) VALUES ('LOCATION','%k'," +
+ DBLITERAL(LOCATION,"string") + ")"
+ );
+ }
+ // - description
+ if (DESCRIPTION!=EMPTY) {
+ SQLEXECUTE(
+ "INSERT INTO cal_properties (key,item_id,value) VALUES ('DESCRIPTION','%k'," +
+ DBLITERAL(DESCRIPTION,"string") + ")"
+ );
+ }
+ }
+ SQLCOMMIT();
+ // update recurrence
+ // - delete all associated recurrence info
+ SQLEXECUTE("DELETE FROM cal_recurrence WHERE item_id='%k'");
+ if (!DELETING()) {
+ // (re-)add recurrence info
+ // - recurrence itself
+ interval = RR_INTERVAL;
+ end_date = RR_END;
+ day = "";
+ monthday = "";
+ daylist = EMPTY;
+ recur_type = EMPTY;
+ // - check type of recurrence
+ if (SUBSTR(RR_FREQ,0,1)=="D") {
+ recur_type = "DAILY";
+ }
+ else if (RR_FREQ=="WW") {
+ recur_type = "WEEKLY";
+ // create list of days 1..7 = SU..SA
+ i=0;
+ while (i<7) {
+ if (RR_FMASK & (1<<i))
+ daylist[SIZE(daylist)]=i+1;
+ i=i+1;
+ }
+ day = EXPLODE(",",daylist);
+ }
+ else if (RR_FREQ=="MD") {
+ recur_type = "MONTHLY";
+ // create list of monthdays 1..31
+ i=0;
+ while (i<31) {
+ if (RR_FMASK & (1<<i))
+ daylist[SIZE(daylist)] = i+1;
+ if (RR_LMASK & (1<<i))
+ daylist[SIZE(daylist)] = -(i+1);
+ i=i+1;
+ }
+ monthday = EXPLODE(",",daylist);
+ }
+ else if (RR_FREQ=="MW") {
+ recur_type = "MONTHLY";
+ // create list of nth weekday in month as (weekday 1..7) + (nTh * 8)
+ i=0;
+ while (i<35) {
+ if (RR_FMASK & (1<<i))
+ daylist[SIZE(daylist)] = (i%7)+1 + 8*(i/7+1);
+ if (RR_LMASK & (1<<i))
+ daylist[SIZE(daylist)] = -((i%7)+1 + 8*(i/7+1));
+ i=i+1;
+ }
+ day = EXPLODE(",",daylist);
+ }
+ else if (SUBSTR(RR_FREQ,0,1)=="Y") {
+ recur_type="YEARLY";
+ }
+ // - now write recurrence, if any
+ if (NORMALIZED(RR_FREQ) != EMPTY) {
+ // - write
+ rcidx = 0;
+ SQLEXECUTE(
+ "INSERT INTO cal_recurrence (item_id, recur_index, recur_type, interval, end_date, day, monthday) VALUES ('%k', " +
+ DBLITERAL(rcidx,"numeric") + "," +
+ DBLITERAL(recur_type,"string") + "," +
+ DBLITERAL(interval,"numeric") + "," +
+ DBLITERAL(end_date,"unixtime_us") + "," +
+ DBLITERAL(day,"string") + "," +
+ DBLITERAL(monthday,"string") + ")"
+ );
+ rcidx=rcidx+1;
+ // - exceptions
+ i=0;
+ WHILE(i<SIZE(EXDATES)) {
+ dates = "ZT" + (string)(TIMESTAMPTODBINT(CONVERTTODATAZONE(EXDATES[i]),"unixtime_us")) + ":/mozilla.org/20070129_1/Africa/Ceuta";
+ // create x-date exception record
+ SQLEXECUTE(
+ "INSERT INTO cal_recurrence (item_id, recur_index, recur_type, is_negative, dates) VALUES ('%k', " +
+ DBLITERAL(rcidx,"numeric") + "," +
+ "'x-date',1," +
+ DBLITERAL(dates,"string") + ")"
+ );
+ rcidx=rcidx+1;
+ i=i+1;
+ }
+ // done
+ SQLCOMMIT();
+ }
+ } // not DELETING()
+ ]]></afterwritescript>
+
+
+ <afterreadscript><![CDATA[
+ // apply flags
+ if (flags & 8) {
+ // all day, adjust time and make timestamps floating
+ MAKEALLDAY(DTSTART,DTEND);
+ SETFLOATING(RR_END);
+ }
+ // get separately stored properties
+ // - location
+ SQLEXECUTE("SELECT value FROM cal_properties WHERE key='LOCATION' AND item_id='%k'");
+ IF (SQLFETCHROW()) {
+ SQLGETCOLUMN(1,LOCATION,"string");
+ }
+ // - description
+ SQLEXECUTE("SELECT value FROM cal_properties WHERE key='DESCRIPTION' AND item_id='%k'");
+ IF (SQLFETCHROW()) {
+ SQLGETCOLUMN(1,DESCRIPTION,"string");
+ }
+ SQLCOMMIT();
+ // - recurrence
+ SQLEXECUTE("SELECT recur_type, count, interval, end_date, day, monthday, dates FROM cal_recurrence WHERE item_id='%k'");
+ WHILE (SQLFETCHROW()) {
+ // get fields
+ SQLGETCOLUMN(1,recur_type,"string");
+ SQLGETCOLUMN(2,count,"numeric");
+ SQLGETCOLUMN(3,interval,"numeric");
+ SQLGETCOLUMN(4,end_date,"unixtime_us");
+ SQLGETCOLUMN(5,day,"string");
+ SQLGETCOLUMN(6,monthday,"string");
+ SQLGETCOLUMN(7,dates,"string");
+ DEBUGSHOWVARS();
+ // calculate internal fields
+ if (recur_type=="x-date") {
+ // evaluate date(s) and make exceptions out of it
+ numelems = REGEX_SPLIT(dates,"/[\s,]+/",dateslist);
+ i=0;
+ WHILE(i<numelems) {
+ REGEX_MATCH(dateslist[i],"/(?<=ZT)\\d+/",0,rc);
+ ts = DBINTTOTIMESTAMP(rc,"unixtime_us");
+ EXDATES[SIZE(EXDATES)] = CONVERTTODATAZONE(ts,true); // unfloat!
+ i = i+1;
+ }
+ }
+ else {
+ // normal recurrence
+ RR_FMASK = 0;
+ RR_LMASK = 0;
+ RR_INTERVAL = interval;
+ RR_END = end_date;
+ RR_FREQ = EMPTY;
+ if (recur_type=="DAILY") {
+ // daily
+ RR_FREQ = "D ";
+ }
+ else if (recur_type=="WEEKLY") {
+ // weekly by weekday list
+ RR_FREQ = "WW";
+ numelems = REGEX_SPLIT(day,"/[\s,]+/",daylist);
+ i=0;
+ while (i<numelems) {
+ RR_FMASK = RR_FMASK | (1<<(daylist[i]-1));
+ i = i+1;
+ }
+ }
+ else if (recur_type=="MONTHLY") {
+ if (monthday!=EMPTY) {
+ // monthly by monthday
+ RR_FREQ = "MD";
+ numelems = REGEX_SPLIT(monthday,"/[\s,]+/",daylist);
+ i=0;
+ while (i<numelems) {
+ rc = abs(daylist[i])-1;
+ if (daylist[i]>0)
+ RR_FMASK = RR_FMASK | (1<<rc);
+ else
+ RR_LMASK = RR_LMASK | (1<<rc);
+ i = i+1;
+ }
+ }
+ else {
+ // monthly by weekday
+ RR_FREQ = "MW";
+ numelems = REGEX_SPLIT(day,"/[\s,]+/",daylist);
+ i=0;
+ while (i<numelems) {
+ // format: Bit0..2 = weekday with offset 1, Bit 3,4 = occurrence in month with offset 1
+ rc = abs(daylist[i]);
+ wd = (rc & 0x07)-1;
+ rc = (rc/8-1)*7 + wd; // bit number for internal masks
+ if (daylist[i]>0) {
+ // counting from beginning
+ RR_FMASK = RR_FMASK | (1<<rc);
+ }
+ else {
+ // counting from end
+ RR_LMASK = RR_LMASK | (1<<rc);
+ }
+ i = i+1;
+ }
+ }
+ }
+ else if (recur_type=="YEARLY") {
+ RR_FREQ = "Y ";
+ }
+ // make sure start date is first recurrence
+ DTSTART = RECURRENCE_DATE(
+ DTSTART,RR_FREQ,RR_INTERVAL,RR_FMASK,RR_LMASK,
+ true,1
+ );
+ // calculate end date if not specified
+ if (RR_END==EMPTY) {
+ // get date of count-th. recurrence = end date
+ RR_END = RECURRENCE_DATE(
+ DTSTART,RR_FREQ,RR_INTERVAL,RR_FMASK,RR_LMASK,
+ true,count
+ );
+ }
+ }
+ }
+ SQLCOMMIT();
+ DEBUGSHOWITEM();
+ ]]></afterreadscript>
+
+
+ <map name="last_modified" references="DMODIFIED" type="unixtime_us" mode="r"/>
+ <map name="time_created" references="DCREATED" type="unixtime_us" mode="r"/>
+
+ <map name="privacy" references="CLASS" type="string" mode="rw" size="63"/>
+
+ <map name="title" references="SUMMARY" type="string" mode="rw" size="254"/>
+
+ <map name="flags" references="flags" type="string" mode="rw"/>
+
+ <map name="event_start" references="DTSTART" type="unixtime_us" mode="rw"/>
+ <map name="event_end" references="DTEND" type="unixtime_us" mode="rw"/>
+
+ <map name="alarm_time" references="ALARM_TIME" type="unixtime_us" mode="rw"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcalendar10" mode="rw" preferred="yes" variant="VEVENT"/>
+ </typesupport>
+
+ </datastore>
+
+
+ </client>
+
+</sysync_config>
diff --git a/src/syncevolution.xml b/src/syncevolution.xml
new file mode 100644
index 00000000..9b6850ce
--- /dev/null
+++ b/src/syncevolution.xml
@@ -0,0 +1,883 @@
+<?xml version="1.0"?>
+<!-- SYNTHESIS SYNC CLIENT Version 3.1 Configuration file -->
+<!-- (works for V3.1.1.0 and later) -->
+
+<sysync_config version="1.0">
+
+ <configvar name="logpath" value="$(defout_path)"/>
+
+ <!-- this string is output to every session debug logfile to identify the config in use -->
+ <configidstring>SyncEvolution client config</configidstring>
+
+ <debug>
+ <!-- path where logfiles are stored -->
+ <logpath>$(logpath)</logpath>
+ <logflushmode>flush</logflushmode> <!-- buffered is fastest mode, but may loose data on process abort. Other options: "flush" (after every line) or "openclose" (safest, slowest, like in 2.x server) -->
+ <!-- per session log -->
+ <sessionlogs>yes</sessionlogs> <!-- by default, create a session log file for every sync session (might be disabled for special users/devices in scripts) -->
+ <!-- debug format options -->
+ <logformat>html</logformat> <!-- html is nicely colored and easily viewable with a web browser. Other options: "xml", "text" -->
+ <timestamp>yes</timestamp> <!-- show timestamps for structure elements in log -->
+ <timestampall>no</timestampall> <!-- don't show timestamp for every log line -->
+ <timedsessionlognames>yes</timedsessionlognames> <!-- session logs also have the session start timestamp in the filename - makes them more easily sortable -->
+ <!-- thread logging mode -->
+ <subthreadmode>separate</subthreadmode> <!-- write log info from subthreads into separate log files. Other options: "suppress" -->
+ <!-- basic debug level selection -->
+ <!-- enable option="extended"/ --> <!-- "extended" is a good choice for start testing. For production, use "normal" or "minimal" -->
+ <!-- <enable option="normal"/> --> <!-- "normal" provides rich debug info, but still in reasonable size -->
+ <!-- <enable option="minimal"/> --> <!-- "minimal" just shows basic flow and error. Not suitable for debugging -->
+ <!-- <enable option="maximal"/> --> <!-- "maximal" can create VERY LARGE logs and cause HEAVY SLOWDOWN. Only for detail debugging -->
+ <enable option="all"/> <!-- "all" shows EVERYTHING possible, and way too much for any normal situation. For hardcore debugging ONLY! -->
+ <!-- additional debug info switches -->
+ <enable option="userdata"/> <!-- Make this <disable ...> if you don't want user data in the logs -->
+ <enable option="scripts"/> <!-- Make this <enable ...> to show script execution in logs -->
+ <enable option="exotic"/> <!-- Make this <enable ...> to include very in-detail info. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care! -->
+ <!-- see manual for more debug info switches -->
+ <!-- global log options -->
+ <globallogs>yes</globallogs> <!-- by default, do not log global session dispatching, creation etc. (not useful in multi-user operation) -->
+ <singlegloballog>no</singlegloballog> <!-- a new global log will be started for every start of the server/application -->
+ <!-- SyncML message dumping options -->
+ <msgdump>yes</msgdump> <!-- do not dump syncml traffic 1:1 to files -->
+ <xmltranslate>yes</xmltranslate> <!-- do not try to translate syncml traffic into XML (DO NOT SET THIS OPTION IN PRODUCTIVE SERVERS!) -->
+ </debug>
+
+ <!-- Note: since 2.1.1.5, clients have a <transport> section to specify <keepconnection> behaviour -->
+ <transport type="xpt">
+ <!-- allow HTTP 1.1 kepp-alive (multiple request-answer-exchanges in single TCP connection) -->
+ <keepconnection>true</keepconnection>
+ </transport>
+
+ <scripting>
+ <looptimeout>5</looptimeout>
+ </scripting>
+
+
+ <datatypes>
+
+
+
+ <!-- list of internal fields representing vCard data -->
+ <fieldlist name="contacts">
+ <field name="REV" type="timestamp" compare="never" age="yes"/>
+ <field name="SYNCLVL" type="integer" compare="never"/>
+ <!-- Name elements -->
+ <field name="N_LAST" type="string" compare="always"/>
+ <field name="N_FIRST" type="string" compare="always"/>
+ <field name="N_PREFIX" type="string" compare="conflict"/>
+ <field name="TITLE" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- categories and classification -->
+ <field name="CATEGORIES" type="string" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- organisation -->
+ <field name="ORG_NAME" type="string" compare="slowsync" merge="fillempty"/>
+ <field name="ORG_DIVISION" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- birthday -->
+ <field name="BDAY" type="date" compare="conflict" merge="fillempty"/>
+
+ <!-- telephone numbers -->
+ <field name="TEL_HOME" type="telephone" compare="conflict"/>
+ <field name="TEL_WORK" type="telephone" compare="conflict"/>
+ <field name="TEL_MOBILE" type="telephone" compare="conflict"/>
+ <field name="TEL_FAX" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_1" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_2" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_3" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_4" type="telephone" compare="conflict"/>
+
+ <!-- home address -->
+ <field name="ADR_H_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_H_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_H_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_H_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_H_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_H_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_H_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- work address -->
+ <field name="ADR_W_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_W_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_W_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_W_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_W_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_W_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_W_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- other address -->
+ <field name="ADR_O_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_O_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_O_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_O_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_O_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_O_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_O_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- emails -->
+ <field name="EMAIL_1" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="EMAIL_2" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <!-- web addresses -->
+ <field name="WEB_1" type="url" compare="conflict" merge="fillempty"/>
+ <field name="WEB_2" type="url" compare="conflict" merge="fillempty"/>
+
+ <!-- Note -->
+ <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+ <!-- Photo -->
+ <field name="PHOTO" type="blob" compare="never" merge="fillempty"/>
+ <field name="PHOTO_TYPE" type="string" compare="never" merge="fillempty"/>
+
+ </fieldlist>
+
+ <!-- vCard profile -->
+ <mimeprofile name="vcard" fieldlist="contacts">
+
+ <profile name="VCARD" nummandatory="0"> <!-- we relax vCard here and allow vCards w/o name, like from K750i. Strict handling would be nummandatory="1" -->
+ <property name="VERSION">
+ <value conversion="version"/>
+ </property>
+
+ <property name="REV">
+ <value field="REV"/>
+ </property>
+
+ <property name="N" values="5" mandatory="no"> <!-- we relax vCard here and allow vCards w/o name, like from K750i. Strict handling would be mandatory="yes" -->
+ <value index="0" field="N_LAST"/>
+ <value index="1" field="N_FIRST"/>
+ <value index="3" field="N_PREFIX"/>
+ </property>
+
+ <property name="TITLE">
+ <value field="TITLE"/>
+ </property>
+
+ <!-- vCard 2.1 does not really have a CATEGORIES property, but we let it inherit that of vCard 3.0 (NOT that of vCalendar 1.0 with ; separators!!) -->
+ <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="ORG" values="2">
+ <value index="0" field="ORG_NAME"/>
+ <value index="1" field="ORG_DIVISION"/>
+ </property>
+
+ <property name="EMAIL">
+ <value field="EMAIL_1"/>
+ <position field="EMAIL_1" repeat="2" increment="1" minshow="1"/>
+ </property>
+
+ <property name="URL">
+ <value field="WEB_1"/>
+ <position field="WEB_1" repeat="2" increment="1" minshow="1"/>
+ </property>
+
+ <property name="TEL">
+ <value field="TEL_HOME"/>
+ <parameter name="TYPE" default="yes" positional="yes" show="yes">
+ <value>
+ <enum name="CELL"/>
+ <enum name="HOME"/>
+ <enum name="WORK"/>
+ <enum name="FAX"/>
+ <enum name="MODEM"/>
+ <enum name="VOICE"/>
+ </value>
+ <position has="HOME" hasnot="FAX,CELL" shows="VOICE" field="TEL_HOME" overwriteempty="yes"/>
+ <position has="WORK" hasnot="FAX,CELL" shows="VOICE" field="TEL_WORK" overwriteempty="yes"/>
+ <position has="CELL" shows="VOICE" field="TEL_MOBILE" overwriteempty="yes"/>
+ <position has="FAX" field="TEL_FAX" overwriteempty="yes"/>
+ <position field="TEL_OTHER_1" repeat="4" increment="1" minshow="0" overwriteempty="yes"/>
+ </parameter>
+ </property>
+
+ <property name="ADR" values="7">
+ <value index="0" field="ADR_H_POBOX"/>
+ <value index="1" field="ADR_H_ADDTL"/>
+ <value index="2" field="ADR_H_STREET"/>
+ <value index="3" field="ADR_H_CITY"/>
+ <value index="4" field="ADR_H_REG"/>
+ <value index="5" field="ADR_H_ZIP"/>
+ <value index="6" field="ADR_H_COUNTRY"/>
+ <parameter name="TYPE" default="yes" positional="yes" show="yes">
+ <value>
+ <enum name="HOME"/>
+ <enum name="WORK"/>
+ </value>
+ <position has="WORK" field="ADR_W_POBOX"/>
+ <position has="HOME" field="ADR_H_POBOX"/>
+ <position field="ADR_O_POBOX"/>
+ </parameter>
+ </property>
+
+ <property name="BDAY">
+ <value field="BDAY"/>
+ </property>
+
+ <property name="NOTE" filter="no">
+ <value field="NOTE"/>
+ </property>
+
+ <property name="PHOTO" filter="no">
+ <value field="PHOTO" conversion="BLOB_B64"/>
+ <parameter name="TYPE" default="no" show="no"> <!-- note: do not show the param, because e.g. Nokia E-Series would not send PHOTO then -->
+ <value field="PHOTO_TYPE"/>
+ </parameter>
+ </property>
+
+ </profile>
+ </mimeprofile>
+
+ <!-- vCard 2.1 datatype, using vCard profile defined above -->
+ <datatype name="vcard21" basetype="vcard">
+ <version>2.1</version>
+ <use mimeprofile="vcard"/>
+ </datatype>
+
+ <!-- vCard 3.0 datatype, using vCard profile defined above -->
+ <datatype name="vcard30" basetype="vcard">
+ <version>3.0</version>
+ <use mimeprofile="vcard"/>
+ </datatype>
+
+
+ <!-- list of internal fields representing vCalendar data
+ (for both events (vEVENT) and tasks (vTODO)) -->
+ <fieldlist name="calendar">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+
+ <!-- this field defines if the data item is an EVENT or a TODO (task) -->
+ <field name="KIND" type="string" compare="always"/>
+
+ <field name="TIMEZONE" type="integer" compare="never"/>
+
+ <field name="DMODIFIED" type="timestamp" compare="never" age="yes"/>
+ <field name="DCREATED" type="timestamp" compare="never"/>
+
+ <field name="CATEGORIES" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <field name="SUMMARY" type="multiline" compare="always"/>
+ <field name="DESCRIPTION" type="multiline" compare="slowsync" merge="lines"/>
+
+ <field name="ATTENDEE_1" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_2" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_3" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_4" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_5" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <field name="LOCATION" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <!-- alarm -->
+ <field name="ALARM_TIME" type="timestamp" compare="conflict"/>
+ <field name="ALARM_SNOOZE" type="string" compare="conflict"/>
+ <field name="ALARM_REPEAT" type="string" compare="conflict"/>
+ <field name="ALARM_MSG" type="string" compare="conflict"/>
+
+ <!-- recurrence rule block, fields must be in that order, including
+ DTSTART as last field !! -->
+ <field name="RR_FREQ" type="string" compare="conflict"/>
+ <field name="RR_INTERVAL" type="integer" compare="conflict"/>
+ <field name="RR_FMASK" type="integer" compare="conflict"/>
+ <field name="RR_LMASK" type="integer" compare="conflict"/>
+ <field name="RR_END" type="timestamp" compare="conflict"/>
+
+ <!-- Note: DTSTART/DTEND are compared in the <comparescript>,
+ therefore compare is set no "never" here -->
+ <field name="DTSTART" type="timestamp" compare="never"/> <!-- also used as DUE in vTODO -->
+
+ <field name="DTEND" type="timestamp" compare="never"/>
+
+ <!-- exception dates to the recurrence rule -->
+ <field name="EXDATE_1" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_2" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_3" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_4" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_5" type="timestamp" compare="conflict"/>
+
+ <!-- for tasks only -->
+ <field name="PRIORITY" type="integer" compare="conflict"/>
+ <field name="STATUS" type="string" compare="conflict" merge="fillempty"/>
+
+ </fieldlist>
+
+ <!-- vCalendar profile, including subprofiles for
+ both events (vEVENT) and tasks (vTODO) -->
+ <mimeprofile name="vcalendar" fieldlist="calendar">
+
+ <profile name="VCALENDAR" nummandatory="1">
+
+ <property name="VERSION" mandatory="yes">
+ <value conversion="version"/>
+ </property>
+
+ <property name="TZ">
+ <value field="TIMEZONE" conversion="TZ"/>
+ </property>
+
+ <!-- sub-profile for events -->
+ <subprofile name="VEVENT" nummandatory="1" field="KIND" value="EVENT" showifselectedonly="true">
+
+ <property name="LAST-MODIFIED">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes">
+ <value field="DCREATED"/>
+ </property>
+
+ <!-- vCalendar 1.0 needs ";" as separator between categories -->
+ <property name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes">
+ <value field="LOCATION"/>
+ </property>
+
+ <property name="DTSTART" suppressempty="yes">
+ <value field="DTSTART"/>
+ </property>
+
+ <property name="DTEND" suppressempty="yes">
+ <value field="DTEND"/>
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes">
+ <value field="ATTENDEE_1"/>
+ <position field="ATTENDEE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <!-- recurrence rule (with delayed parsing, as it is dependent on DTSTART) -->
+ <property name="RRULE" suppressempty="yes" delayedparsing="1">
+ <!-- Note: RR_FREQ is the beginning of a block of fields
+ suitable for the "rrule" conversion mode -->
+ <value field="RR_FREQ" conversion="rrule"/>
+ </property>
+
+ <!-- up to five exceptions for recurrence rule -->
+ <property name="EXDATE" values="list" suppressempty="yes">
+ <value field="EXDATE_1"/>
+ <position field="EXDATE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ <!-- sub-profile for tasks (todo's) -->
+ <subprofile name="VTODO" nummandatory="1" field="KIND" value="TODO" showifselectedonly="true">
+
+ <property name="LAST-MODIFIED">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes">
+ <value field="DCREATED"/>
+ </property>
+
+ <!-- vCalendar 1.0 needs ";" as separator between categories -->
+ <property name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes">
+ <value field="LOCATION"/>
+ </property>
+
+
+ <property name="DUE" suppressempty="yes">
+ <value field="DTSTART"/> <!-- we use DTSTART field for DUE property in tasks -->
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes">
+ <value field="ATTENDEE_1"/>
+ <position field="ATTENDEE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <property name="PRIORITY" suppressempty="yes">
+ <value field="PRIORITY"/>
+ </property>
+
+ <property name="STATUS" suppressempty="yes">
+ <value field="STATUS" conversion="emptyonly"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ </profile>
+ </mimeprofile>
+
+
+ <!-- vCalendar 1.0 datatype, using vCalendar profile defined
+ above -->
+ <datatype name="vcalendar10" basetype="vcalendar">
+ <version>1.0</version>
+ <use mimeprofile="vcalendar"/>
+
+ <!-- Scripting allows sophisticated data adjustment:
+ make sure we have always have a SUMMARY, but avoid
+ SUMMARY and DESCRIPTION being identical,
+ as well as always having a DTSTART
+ and an alarm message -->
+ <incomingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have at least a summary
+ if (SUMMARY==EMPTY) SUMMARY=DESCRIPTION; // use description if we don't have a summary
+ if (SUMMARY==EMPTY) SUMMARY="unnamed"; // set dummy summary if we still don't have one
+ if (DESCRIPTION==SUMMARY) DESCRIPTION=EMPTY; // do not save twice
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></incomingscript>
+
+ <outgoingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have both description AND summary
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ if (SUMMARY==EMPTY) SUMMARY="unnamed";
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ // make sure we have an alarm message
+ if (ALARM_TIME!=EMPTY && ALARM_MSG==EMPTY) ALARM_MSG="alarm";
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></outgoingscript>
+
+ <!-- filterinitscript TODO DBHANDLESOPTS not supported><![CDATA[
+ // check if we need to filter
+ INTEGER NEEDFILTER;
+
+ // we need to filter if STARTDATE() and/or ENDDATE() are set...
+ NEEDFILTER =
+ !DBHANDLESOPTS() && // ...but only if DB itself does not handle it directly
+ (STARTDATE()!=EMPTY || ENDDATE()!=EMPTY); // start or end date set
+ SETFILTERALL(NEEDFILTER); // as the filter conditions change dynamically with time, we need to filter ALL records
+ RETURN NEEDFILTER; // we need to filter
+ ]]></filterinitscript -->
+
+ <!-- filterscript TODO ENDDATE not supported><![CDATA[
+ INTEGER PASSES;
+
+ // check if item passes filter
+ PASSES=FALSE;
+ // as vCalendar handles events and tasks, we need to differentiate here
+ IF (KIND=="EVENT") {
+ // Events pass if they start within the range or
+ // have a recurrence that has started, but not yet ended
+ PASSES =
+ (DTSTART<=ENDDATE()) &&
+ (
+ (DTSTART>=STARTDATE()) ||
+ ((RR_FREQ!=EMPTY) && ((RR_END==EMPTY) || (RR_END>STARTDATE())))
+ );
+ }
+ ELSE {
+ // Todo pass if they have no DUE or one within the range
+ PASSES =
+ (DTSTART==EMPTY) ||
+ (DTSTART>=STARTDATE() && DTSTART<=ENDDATE());
+ }
+ RETURN PASSES;
+ ]]></filterscript -->
+
+ <!-- TODO comparescript><![CDATA[
+ INTEGER RES;
+
+ // do standard compare (WHICH MUST NOT INCLUDE DTSTART/DTEND!)
+ RES = COMPAREFIELDS();
+ // do specially relaxed date checking
+ if (RES==0) {
+ // only check for same local date (not time) of DTSTART(=DUE for vTODO)
+ // to increase probability that time zone problems get masked out
+ RES = COMPARE(DATEONLY(TARGET.DTSTART),DATEONLY(REFERENCE.DTSTART));
+ }
+ RETURN RES;
+ ]]></comparescript -->
+ </datatype>
+
+
+
+ <!-- list of internal fields representing plain text note data -->
+ <fieldlist name="Note">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+ <field name="SUBJECT" type="multiline" compare="always"/>
+ <field name="TEXT" type="multiline" compare="conflict" merge="lines"/>
+ </fieldlist>
+
+ <textprofile name="Note" fieldlist="Note">
+ <linemap field="SUBJECT">
+ <numlines>1</numlines>
+ <inheader>false</inheader>
+ <allowempty>true</allowempty>
+ <filterkeyword>SUBJECT</filterkeyword>
+ </linemap>
+ <linemap field="TEXT">
+ <numlines>0</numlines>
+ <inheader>false</inheader>
+ <allowempty>true</allowempty>
+ </linemap>
+ </textprofile>
+
+ <datatype name="note" basetype="text">
+ <use profile="Note"/>
+ <typestring>text/plain</typestring>
+ <versionstring>1.0</versionstring>
+ </datatype>
+
+ <datatype name="note11" basetype="text">
+ <use profile="Note"/>
+ <typestring>text/plain</typestring>
+ <versionstring>1.1</versionstring>
+ </datatype>
+
+
+ <!-- list of internal fields representing vBookmark data -->
+ <fieldlist name="bookmarks">
+ <field name="REV" type="timestamp" compare="never" age="yes"/>
+ <field name="SYNCLVL" type="integer" compare="never"/>
+
+ <!-- Name -->
+ <field name="TITLE" type="string" compare="always"/>
+
+ <!-- categories and classification -->
+ <field name="CATEGORIES" type="string" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- web addresses -->
+ <field name="URL" type="url" compare="slowsync" merge="fillempty"/>
+
+ <!-- Note -->
+ <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+ </fieldlist>
+
+ <!-- vBookmark profile -->
+ <mimeprofile name="vbookmark" fieldlist="bookmarks">
+
+ <profile name="VBKM" nummandatory="0">
+ <property name="VERSION">
+ <value conversion="version"/>
+ </property>
+
+ <property name="X-LAST-MODIFIED">
+ <value field="REV"/>
+ </property>
+
+ <property name="TITLE">
+ <value field="TITLE"/>
+ </property>
+
+ <property name="URL">
+ <value field="URL"/>
+ </property>
+
+ <!-- non-standard properties -->
+
+ <!-- inherit CATEGORIES from vCard 3.0, i.e. comma separated -->
+ <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="NOTE" filter="no">
+ <value field="NOTE"/>
+ </property>
+
+ </profile>
+ </mimeprofile>
+
+ <!-- vBookmark datatype, using vBookmark profile defined above -->
+ <datatype name="vbookmark" basetype="mimedir">
+ <typestring>text/x-vbookmark</typestring>
+ <versionstring>1.0</versionstring>
+ <use profile="vbookmark"/>
+ </datatype>
+
+ </datatypes>
+
+
+ <client type="plugin">
+ <plugin_module>SDK_textdb</plugin_module>
+
+ <!-- TODO: configure this in SyncEvolution -->
+ <binfilespath>/home/pohly/.syncevolution</binfilespath>
+ <defaultauth>none</defaultauth>
+
+ <datastore name="addressbook" type="plugin">
+
+
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ <datafilepath>/home/pohly/funambol/addressbook</datafilepath>
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- Mapping of the fields to the fieldlist "contacts" -->
+ <fieldmap fieldlist="contacts">
+ <initscript><![CDATA[
+ DEBUGSHOWVARS();
+ string foo;
+ DEBUGSHOWVARS();
+ DEBUGMESSAGE("hello world");
+ DEBUGSHOWVARS();
+ ]]></initscript>
+ <beforewritescript><![CDATA[
+ DEBUGSHOWVARS();
+ foo = MAKETEXTWITHPROFILE("vcard", 2);
+ DEBUGSHOWVARS();
+ ]]></beforewritescript>
+ <afterreadscript><![CDATA[
+ DEBUGSHOWVARS();
+ PARSETEXTWITHPROFILE(foo, "vcard", 2);
+ DEBUGSHOWVARS();
+ ]]></afterreadscript>
+ <map name="0" references="N_LAST" type="string"/>
+ <map name="1" references="foo" type="string"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcard21" mode="rw" preferred="yes"/>
+ <use datatype="vcard30" mode="rw"/>
+ </typesupport>
+
+ </datastore>
+
+ <datastore name="notes" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- Mapping of the fields to the fieldlist "notes" -->
+ <fieldmap fieldlist="Note">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <typesupport>
+ <use datatype="note" mode="rw" preferred="yes"/>
+ <use datatype="note11" mode="rw"/>
+ </typesupport>
+
+ </datastore>
+
+ <datastore name="bookmarks" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- Mapping of the fields to the fieldlist "bookmarks" -->
+ <fieldmap fieldlist="bookmarks">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vbookmark" mode="rw" preferred="yes"/>
+ </typesupport>
+
+ </datastore>
+
+ </client>
+
+</sysync_config>
diff --git a/src/syncserv_odbc.xml b/src/syncserv_odbc.xml
new file mode 100644
index 00000000..538e2742
--- /dev/null
+++ b/src/syncserv_odbc.xml
@@ -0,0 +1,2558 @@
+<?xml version="1.0"?>
+<!-- SYNTHESIS SYNC SERVER Version 3.0 Configuration file -->
+<!-- (works for V2.9.9.0 and later) -->
+<!-- RELEASE: SDK sample config for a PRO Server using plugins: xpt, Standard types, textdb-plugin -->
+
+<sysync_config version="1.0">
+
+ <!-- enter your license details here. Not all versions need a
+ license (for example the demo runs without one).
+ You should have received license code information
+ along with the purchase or evaluation package.
+ If not, please contact sales@synthesis.ch -->
+ <licensename>licensee name</licensename>
+ <licensecode>XXXX-XXXX-XXXX-XXXX</licensecode>
+
+ <!-- this string is output to every session debug logfile to identify the config in use -->
+ <configidstring>RELEASE: SDK sample config for a PRO Server using plugins: xpt, Standard types, textdb-plugin, generated 2008-Nov-20 20:39:17</configidstring>
+
+ <debug>
+ <!-- path where logfiles are stored -->
+ <!-- <logpath platform="win32">D:\your\log\directory</logpath> -->
+ <!-- <logpath platform="linux">/your/log/directory</logpath> -->
+ <!-- <logpath platform="macosx">/your/log/directory</logpath> -->
+ <logflushmode>buffered</logflushmode> <!-- buffered is fastest mode, but may loose data on process abort. Other options: "flush" (after every line) or "openclose" (safest, slowest, like in 2.x server) -->
+ <!-- per session log -->
+ <sessionlogs>yes</sessionlogs> <!-- by default, create a session log file for every sync session (might be disabled for special users/devices in scripts) -->
+ <!-- debug format options -->
+ <logformat>html</logformat> <!-- html is nicely colored and easily viewable with a web browser. Other options: "xml", "text" -->
+ <folding>auto</folding> <!-- dynamic folding of blocks enabled, automatically expanded or collapsed default. Other options: "none", "expanded", "collapsed" -->
+ <timestamp>yes</timestamp> <!-- show timestamps for structure elements in log -->
+ <timestampall>no</timestampall> <!-- don't show timestamp for every log line -->
+ <timedsessionlognames>yes</timedsessionlognames> <!-- session logs also have the session start timestamp in the filename - makes them more easily sortable -->
+ <!-- thread logging mode -->
+ <subthreadmode>separate</subthreadmode> <!-- write log info from subthreads into separate log files. Other options: "suppress" -->
+ <!-- basic debug level selection -->
+ <enable option="extended"/> <!-- "extended" is a good choice for start testing. For production, use "normal" or "minimal" -->
+ <!-- <enable option="normal"/> --> <!-- "normal" provides rich debug info, but still in reasonable size -->
+ <!-- <enable option="minimal"/> --> <!-- "minimal" just shows basic flow and error. Not suitable for debugging -->
+ <!-- <enable option="maximal"/> --> <!-- "maximal" can create VERY LARGE logs and cause HEAVY SLOWDOWN. Only for detail debugging -->
+ <!-- <enable option="all"/> --> <!-- "all" shows EVERYTHING possible, and way too much for any normal situation. For hardcore debugging ONLY! -->
+ <!-- additional debug info switches -->
+ <enable option="userdata"/> <!-- Make this <disable ...> if you don't want user data in the logs -->
+ <disable option="scripts"/> <!-- Make this <enable ...> to show script execution in logs -->
+ <disable option="match"/> <!-- Make this <enable ...> to show slow sync matching. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care! -->
+ <disable option="exotic"/> <!-- Make this <enable ...> to include very in-detail info. CAN PRODUCE ENORMOUS LOGS and HEAVILY IMPACT PERFORMANCE for large slow syncs - use with care! -->
+ <!-- see manual for more debug info switches -->
+ <!-- global log options -->
+ <globallogs>no</globallogs> <!-- by default, do not log global session dispatching, creation etc. (not useful in multi-user operation) -->
+ <singlegloballog>no</singlegloballog> <!-- a new global log will be started for every start of the server/application -->
+ <!-- SyncML message dumping options -->
+ <msgdump>no</msgdump> <!-- do not dump syncml traffic 1:1 to files -->
+ <xmltranslate>no</xmltranslate> <!-- do not try to translate syncml traffic into XML (DO NOT SET THIS OPTION IN PRODUCTIVE SERVERS!) -->
+ </debug>
+
+ <!-- Note: since Server 1.0.8.50, we can have multiple <transport> sections
+ to allow using the same config file for both ISAPI and standalone
+ server versions -->
+ <transport type="xpt">
+ <!-- settings for standalone operation -->
+ <!-- Note: protocol can be "HTTP", "OBEX/TCP" or "OBEX/IR" -->
+ <protocol>HTTP</protocol>
+ <!-- Note: If protocol is OBEX/TCP, <httpport> specifies the OBEX server port -->
+ <httpport>80</httpport>
+ <!-- allow HTTP 1.1 kepp-alive (multiple request-answer-exchanges in single TCP connection) -->
+ <keepconnection>true</keepconnection>
+ <!-- you can set the server IP address, 0.0.0.0=all
+ <ipaddress>0.0.0.0</ipaddress>
+ -->
+ <!-- For OBEX/IR, you can specify another service (analogous to TCP port number)
+ than the default of "SYNCML-SYNC"
+ <obexservice>SYNCML-SYNC</obexservice>
+ -->
+ </transport>
+
+ <transport type="isapi">
+ <!-- settings for ISAPI (IIS) operation -->
+ <!-- controls HTTP 1.1 connection behaviour -->
+ <keepconnection>true</keepconnection>
+ <!-- if set, clients can repeat a failed message and server is
+ able to repeat the most recent answer. Switch this off
+ if you are extremely tight on memory on the server -->
+ <bufferretryanswer>true</bufferretryanswer>
+ </transport>
+
+ <transport type="pipe">
+ <!-- settings for Apache based server (using pipes for communication with server process) -->
+ <!-- if set, clients can repeat a failed message and server is
+ able to repeat the most recent answer. Switch this off
+ if you are extremely tight on memory on the server -->
+ <bufferretryanswer>true</bufferretryanswer>
+ <!-- The following controls how many sessions are run per server process:
+ 0 : single-threaded server, one process per sync session (default, and only
+ mode available in servers before 3.0.0.19).
+ 1 : only one session at a time per process, but after session finishes,
+ server process keeps running and can process another session.
+ >1 : multi-threaded server, can run the specified number of sessions
+ in parallel threads. This is the recommended mode when starting a new
+ server process is expensive in terms of memory or cpu, such as with
+ Java based plugins (with a multithreaded server, the Java VM will
+ be loaded only once for all sessions, in a single-threaded server,
+ each session will instantiate a new Java VM). -->
+ <maxthreads>0</maxthreads>
+ <!-- if set to >0, this is the max number of sessions a server process should
+ run before exiting. This can be useful to make sure the server environment
+ is restarted once in a while to avoid eventual memory leaks in plugins etc.
+ to accumulate too much -->
+ <maxsessionruns>0</maxsessionruns>
+ </transport>
+
+
+ <scripting>
+ <!-- Global script function definitions -->
+
+ <!-- as an example, we define a function to clear email addresses
+ that do not conform to minimal standards. It is used
+ in the contacts datastores's <beforewritescript> below. -->
+ <function><![CDATA[
+ // clear invalid email addresses
+ checkEmail(multiline &EMAIL)
+ {
+ INTEGER A,D,S;
+
+ // check Email address
+ A=FIND(EMAIL,"@",0);
+ D=RFIND(EMAIL,".",LENGTH(EMAIL));
+ S=FIND(EMAIL," ",0);
+ // clear email if not in xxx@yyy.zz form or has spaces in it
+ IF (S!=EMPTY || A==EMPTY || D==EMPTY || A==0 || D<A+2) EMAIL=EMPTY;
+ }
+ ]]></function>
+
+ <!-- The following email handling scripts are defined as script MACROS because they
+ are used in multiple <datatype> definitions below. This avoids duplicating these
+ script's source code in the config file -->
+
+ <macro name="EMAIL_INIT_SCRIPT"><![CDATA[
+ INTEGER ITEMLIMIT;
+ // default limit is limit of session
+ ITEMLIMIT = SIZELIMIT();
+ ]]></macro>
+
+
+ <macro name="EMAIL_PROCESSITEM_SCRIPT"><![CDATA[
+ // pre-process item
+ if (UPPERCASE(FOLDER)=="INBOX") {
+ // In any case, prevent adding to inbox (delete remote items instead)
+ PREVENTADD();
+ // server always wins for inbox
+ CONFLICTSTRATEGY("server-wins");
+ if (SLOWSYNC()) {
+ // also prevent modifications in server
+ IGNOREUPDATE();
+ }
+ else {
+ // normal sync items going to inbox from client need special treatment
+ if (SYNCOP()=="add" || SYNCOP()=="replace") {
+ // make sure that existing server item will conflict with this item
+ if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+ // force conflict only if this is a reload
+ FORCECONFLICT();
+ }
+ // make sure we never overwrite a body in the inbox
+ BODY = UNASSIGNED;
+ // delete always wins over replace in inbox (to avoid adds to inbox)
+ DELETEWINS();
+ }
+ }
+ }
+ else if (UPPERCASE(FOLDER)=="OUTBOX") {
+ // never try to change something in outbox
+ IGNOREUPDATE();
+ if (SYNCOP()!="delete") {
+ // - date of mail is NOW, set it such that a correct date is written to the DB
+ MAILDATE = DBNOW();
+ // MAILDATE = (INTEGER)DBNOW() - TIMEUNITS(120); // %%% backdate it 2 mins to make sure it does not get retransmitted
+ // - echo item as replace (to force-move it to the sent folder)
+ ECHOITEM("replace");
+ }
+ CONFLICTSTRATEGY("client-wins");
+ }
+ else if (UPPERCASE(FOLDER)=="SENT") {
+ // never try to change something in sent folder
+ IGNOREUPDATE();
+ // Server has precedence in case of conflicts
+ CONFLICTSTRATEGY("server-wins");
+ // Implement reload capability for sent items as well
+ if (SLOWSYNC()) {
+ // do not add new sent items to the server in slowsync
+ PREVENTADD(); // causes extra sent items on the client to be deleted
+ }
+ else {
+ // make sure that existing server item will conflict with this item
+ if (SYNCOP()=="replace") {
+ if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+ // force conflict only if this is a reload
+ FORCECONFLICT();
+ REJECTITEM(200); // but do not process the item further
+ }
+ else {
+ // silently ignore other types of changes
+ REJECTITEM(200);
+ }
+ // make sure we never overwrite a body in the sent folder
+ BODY = UNASSIGNED;
+ }
+ }
+ }
+ else {
+ // Other folder
+ // - silently discard incoming item for other folder than the above
+ // except if it is a delete
+ if (SYNCOP()!="delete")
+ REJECTITEM(0);
+ }
+ ]]></macro>
+
+
+ <macro name="EMAIL_MERGE_SCRIPT"><![CDATA[
+ // pre-process item
+ if (UPPERCASE(LOOSING.FOLDER)!="OUTBOX") {
+ // non-outbox (especially inbox) needs special merge to accomplish reload feature
+ // - loosing item is client's, winning is server's
+ if (LOOSING.LIMIT!=EMPTY) {
+ // loosing (remote) item specifies a new limit, override winning's default
+ WINNING.LIMIT=LOOSING.LIMIT;
+ SETWINNINGCHANGED(TRUE);
+ }
+ // make sure winning has right folder
+ WINNING.FOLDER=LOOSING.FOLDER;
+ // make sure a set read-flag gets propagated to server
+ if (LOOSING.ISREAD=="true") WINNING.ISREAD="true";
+ // merge other fields normally
+ MERGEFIELDS();
+ // make sure body does not get re-written to local DB even if merge would cause local update
+ LOOSING.BODY=UNASSIGNED;
+ }
+ else {
+ // normal merging in other folders
+ MERGEFIELDS();
+ }
+ ]]></macro>
+
+ <macro name="EMAIL_OUTGOING_SCRIPT"><![CDATA[
+ // pre-process item
+ if (UPPERCASE(FOLDER)=="OUTBOX") {
+ // writing to outbox is always the ECHOITEM
+ // - cause item to move into "sent" folder
+ FOLDER = "sent";
+ if (!SESSIONVAR("retransfer_body")) {
+ // - prevent body retransfer, but not for dumb P800/P900/M600/P990 clients
+ BODY = UNASSIGNED; // prevent body transfer
+ ATT_COUNT = 0; // prevent attachment transfer
+ ATT_CONTENTS = UNASSIGNED;
+ // basically, this item is not limited (already complete on the client)
+ // even if contents are not sent
+ LIMIT = -1;
+ SETSIZELIMIT(-1);
+ }
+ }
+ else {
+ // outgoing item to any folder of of remote (inbox, sent...)
+ // - limit body to what is set in the LIMIT field
+ // %%% probably obsolete, as textitem will handle limit field automatically for >=V1.0.8.21
+ IF (LIMIT==EMPTY)
+ LIMIT = SIZELIMIT(); // if none set already, use default for this item (=default of datastore, if not SETSIZELIMIT() called before for this item generation)
+ }
+ // set limit for item generator
+ if (LIMIT!=EMPTY)
+ SETSIZELIMIT(LIMIT);
+ ]]></macro>
+
+
+ <macro name="EMAIL_FILTERINIT_SCRIPT"><![CDATA[
+ // check if we need to filter
+ INTEGER NEEDFILTER;
+
+ NEEDFILTER =
+ !DBHANDLESOPTS() && // only if DB cannot handle it
+ (STARTDATE()!=EMPTY); // and only if a start date is set (end date not needed as there are never future emails today)
+ SETFILTERALL(NEEDFILTER);
+ RETURN NEEDFILTER;
+ ]]></macro>
+
+
+ <macro name="EMAIL_FILTER_SCRIPT"><![CDATA[
+ INTEGER PASSES;
+
+ // check if item passes filter
+ PASSES=FALSE;
+ // Emails pass if they have a MAILDATE on or later than start date
+ PASSES = MAILDATE>=STARTDATE();
+ RETURN PASSES;
+ ]]></macro>
+
+ </scripting>
+
+
+ <datatypes>
+
+
+
+ <!-- list of internal fields representing vCard data -->
+ <fieldlist name="contacts">
+ <field name="REV" type="timestamp" compare="never" age="yes"/>
+ <field name="SYNCLVL" type="integer" compare="never"/>
+ <!-- Name elements -->
+ <field name="N_LAST" type="string" compare="always"/>
+ <field name="N_FIRST" type="string" compare="always"/>
+ <field name="N_PREFIX" type="string" compare="conflict"/>
+ <field name="TITLE" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- categories and classification -->
+ <field name="CATEGORIES" type="string" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- organisation -->
+ <field name="ORG_NAME" type="string" compare="slowsync" merge="fillempty"/>
+ <field name="ORG_DIVISION" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- birthday -->
+ <field name="BDAY" type="date" compare="conflict" merge="fillempty"/>
+
+ <!-- telephone numbers -->
+ <field name="TEL_HOME" type="telephone" compare="conflict"/>
+ <field name="TEL_WORK" type="telephone" compare="conflict"/>
+ <field name="TEL_MOBILE" type="telephone" compare="conflict"/>
+ <field name="TEL_FAX" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_1" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_2" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_3" type="telephone" compare="conflict"/>
+ <field name="TEL_OTHER_4" type="telephone" compare="conflict"/>
+
+ <!-- home address -->
+ <field name="ADR_H_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_H_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_H_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_H_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_H_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_H_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_H_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- work address -->
+ <field name="ADR_W_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_W_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_W_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_W_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_W_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_W_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_W_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- other address -->
+ <field name="ADR_O_POBOX" type="multiline" compare="conflict"/>
+ <field name="ADR_O_ADDTL" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_O_STREET" type="multiline" compare="conflict"/>
+ <field name="ADR_O_CITY" type="multiline" compare="conflict"/>
+ <field name="ADR_O_REG" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ADR_O_ZIP" type="multiline" compare="conflict"/>
+ <field name="ADR_O_COUNTRY" type="multiline" compare="conflict"/>
+
+ <!-- emails -->
+ <field name="EMAIL_1" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="EMAIL_2" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <!-- web addresses -->
+ <field name="WEB_1" type="url" compare="conflict" merge="fillempty"/>
+ <field name="WEB_2" type="url" compare="conflict" merge="fillempty"/>
+
+ <!-- Note -->
+ <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+ <!-- Photo -->
+ <field name="PHOTO" type="blob" compare="never" merge="fillempty"/>
+ <field name="PHOTO_TYPE" type="string" compare="never" merge="fillempty"/>
+
+ </fieldlist>
+
+ <!-- vCard profile -->
+ <mimeprofile name="vcard" fieldlist="contacts">
+
+ <profile name="VCARD" nummandatory="0"> <!-- we relax vCard here and allow vCards w/o name, like from K750i. Strict handling would be nummandatory="1" -->
+ <property name="VERSION">
+ <value conversion="version"/>
+ </property>
+
+ <property name="REV">
+ <value field="REV"/>
+ </property>
+
+ <property name="N" values="5" mandatory="no"> <!-- we relax vCard here and allow vCards w/o name, like from K750i. Strict handling would be mandatory="yes" -->
+ <value index="0" field="N_LAST"/>
+ <value index="1" field="N_FIRST"/>
+ <value index="3" field="N_PREFIX"/>
+ </property>
+
+ <property name="TITLE">
+ <value field="TITLE"/>
+ </property>
+
+ <!-- vCard 2.1 does not really have a CATEGORIES property, but we let it inherit that of vCard 3.0 (NOT that of vCalendar 1.0 with ; separators!!) -->
+ <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="ORG" values="2">
+ <value index="0" field="ORG_NAME"/>
+ <value index="1" field="ORG_DIVISION"/>
+ </property>
+
+ <property name="EMAIL">
+ <value field="EMAIL_1"/>
+ <position field="EMAIL_1" repeat="2" increment="1" minshow="1"/>
+ </property>
+
+ <property name="URL">
+ <value field="WEB_1"/>
+ <position field="WEB_1" repeat="2" increment="1" minshow="1"/>
+ </property>
+
+ <property name="TEL">
+ <value field="TEL_HOME"/>
+ <parameter name="TYPE" default="yes" positional="yes" show="yes">
+ <value>
+ <enum name="CELL"/>
+ <enum name="HOME"/>
+ <enum name="WORK"/>
+ <enum name="FAX"/>
+ <enum name="MODEM"/>
+ <enum name="VOICE"/>
+ </value>
+ <position has="HOME" hasnot="FAX,CELL" shows="VOICE" field="TEL_HOME" overwriteempty="yes"/>
+ <position has="WORK" hasnot="FAX,CELL" shows="VOICE" field="TEL_WORK" overwriteempty="yes"/>
+ <position has="CELL" shows="VOICE" field="TEL_MOBILE" overwriteempty="yes"/>
+ <position has="FAX" field="TEL_FAX" overwriteempty="yes"/>
+ <position field="TEL_OTHER_1" repeat="4" increment="1" minshow="0" overwriteempty="yes"/>
+ </parameter>
+ </property>
+
+ <property name="ADR" values="7">
+ <value index="0" field="ADR_H_POBOX"/>
+ <value index="1" field="ADR_H_ADDTL"/>
+ <value index="2" field="ADR_H_STREET"/>
+ <value index="3" field="ADR_H_CITY"/>
+ <value index="4" field="ADR_H_REG"/>
+ <value index="5" field="ADR_H_ZIP"/>
+ <value index="6" field="ADR_H_COUNTRY"/>
+ <parameter name="TYPE" default="yes" positional="yes" show="yes">
+ <value>
+ <enum name="HOME"/>
+ <enum name="WORK"/>
+ </value>
+ <position has="WORK" field="ADR_W_POBOX"/>
+ <position has="HOME" field="ADR_H_POBOX"/>
+ <position field="ADR_O_POBOX"/>
+ </parameter>
+ </property>
+
+ <property name="BDAY">
+ <value field="BDAY"/>
+ </property>
+
+ <property name="NOTE" filter="no">
+ <value field="NOTE"/>
+ </property>
+
+ <property name="PHOTO" filter="no">
+ <value field="PHOTO" conversion="BLOB_B64"/>
+ <parameter name="TYPE" default="no" show="no"> <!-- note: do not show the param, because e.g. Nokia E-Series would not send PHOTO then -->
+ <value field="PHOTO_TYPE"/>
+ </parameter>
+ </property>
+
+ </profile>
+ </mimeprofile>
+
+ <!-- vCard 2.1 datatype, using vCard profile defined above -->
+ <datatype name="vcard21" basetype="vcard">
+ <version>2.1</version>
+ <use mimeprofile="vcard"/>
+ </datatype>
+
+ <!-- vCard 3.0 datatype, using vCard profile defined above -->
+ <datatype name="vcard30" basetype="vcard">
+ <version>3.0</version>
+ <use mimeprofile="vcard"/>
+ </datatype>
+
+
+ <!-- list of internal fields representing vCalendar data
+ (for both events (vEVENT) and tasks (vTODO)) -->
+ <fieldlist name="calendar">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+
+ <!-- this field defines if the data item is an EVENT or a TODO (task) -->
+ <field name="KIND" type="string" compare="always"/>
+
+ <field name="TIMEZONE" type="integer" compare="never"/>
+
+ <field name="DMODIFIED" type="timestamp" compare="never" age="yes"/>
+ <field name="DCREATED" type="timestamp" compare="never"/>
+
+ <field name="CATEGORIES" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <field name="SUMMARY" type="multiline" compare="always"/>
+ <field name="DESCRIPTION" type="multiline" compare="slowsync" merge="lines"/>
+
+ <field name="ATTENDEE_1" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_2" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_3" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_4" type="multiline" compare="conflict" merge="fillempty"/>
+ <field name="ATTENDEE_5" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <field name="LOCATION" type="multiline" compare="conflict" merge="fillempty"/>
+
+ <!-- alarm -->
+ <field name="ALARM_TIME" type="timestamp" compare="conflict"/>
+ <field name="ALARM_SNOOZE" type="string" compare="conflict"/>
+ <field name="ALARM_REPEAT" type="string" compare="conflict"/>
+ <field name="ALARM_MSG" type="string" compare="conflict"/>
+
+ <!-- recurrence rule block, fields must be in that order, including
+ DTSTART as last field !! -->
+ <field name="RR_FREQ" type="string" compare="conflict"/>
+ <field name="RR_INTERVAL" type="integer" compare="conflict"/>
+ <field name="RR_FMASK" type="integer" compare="conflict"/>
+ <field name="RR_LMASK" type="integer" compare="conflict"/>
+ <field name="RR_END" type="timestamp" compare="conflict"/>
+
+ <!-- Note: DTSTART/DTEND are compared in the <comparescript>,
+ therefore compare is set no "never" here -->
+ <field name="DTSTART" type="timestamp" compare="never"/> <!-- also used as DUE in vTODO -->
+
+ <field name="DTEND" type="timestamp" compare="never"/>
+
+ <!-- exception dates to the recurrence rule -->
+ <field name="EXDATE_1" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_2" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_3" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_4" type="timestamp" compare="conflict"/>
+ <field name="EXDATE_5" type="timestamp" compare="conflict"/>
+
+ <!-- for tasks only -->
+ <field name="PRIORITY" type="integer" compare="conflict"/>
+ <field name="STATUS" type="string" compare="conflict" merge="fillempty"/>
+
+ </fieldlist>
+
+ <!-- vCalendar profile, including subprofiles for
+ both events (vEVENT) and tasks (vTODO) -->
+ <mimeprofile name="vcalendar" fieldlist="calendar">
+
+ <profile name="VCALENDAR" nummandatory="1">
+
+ <property name="VERSION" mandatory="yes">
+ <value conversion="version"/>
+ </property>
+
+ <property name="TZ">
+ <value field="TIMEZONE" conversion="TZ"/>
+ </property>
+
+ <!-- sub-profile for events -->
+ <subprofile name="VEVENT" nummandatory="1" field="KIND" value="EVENT" showifselectedonly="true">
+
+ <property name="LAST-MODIFIED">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes">
+ <value field="DCREATED"/>
+ </property>
+
+ <!-- vCalendar 1.0 needs ";" as separator between categories -->
+ <property name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes">
+ <value field="LOCATION"/>
+ </property>
+
+ <property name="DTSTART" suppressempty="yes">
+ <value field="DTSTART"/>
+ </property>
+
+ <property name="DTEND" suppressempty="yes">
+ <value field="DTEND"/>
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes">
+ <value field="ATTENDEE_1"/>
+ <position field="ATTENDEE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <!-- recurrence rule (with delayed parsing, as it is dependent on DTSTART) -->
+ <property name="RRULE" suppressempty="yes" delayedparsing="1">
+ <!-- Note: RR_FREQ is the beginning of a block of fields
+ suitable for the "rrule" conversion mode -->
+ <value field="RR_FREQ" conversion="rrule"/>
+ </property>
+
+ <!-- up to five exceptions for recurrence rule -->
+ <property name="EXDATE" values="list" suppressempty="yes">
+ <value field="EXDATE_1"/>
+ <position field="EXDATE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ <!-- sub-profile for tasks (todo's) -->
+ <subprofile name="VTODO" nummandatory="1" field="KIND" value="TODO" showifselectedonly="true">
+
+ <property name="LAST-MODIFIED">
+ <value field="DMODIFIED"/>
+ </property>
+
+ <property name="DCREATED" suppressempty="yes">
+ <value field="DCREATED"/>
+ </property>
+
+ <!-- vCalendar 1.0 needs ";" as separator between categories -->
+ <property name="CATEGORIES" values="list" valueseparator=";" altvalueseparator="," suppressempty="yes">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="SUMMARY" mandatory="yes">
+ <value field="SUMMARY"/>
+ </property>
+
+ <property name="DESCRIPTION" mandatory="yes">
+ <value field="DESCRIPTION"/>
+ </property>
+
+ <property name="LOCATION" suppressempty="yes">
+ <value field="LOCATION"/>
+ </property>
+
+
+ <property name="DUE" suppressempty="yes">
+ <value field="DTSTART"/> <!-- we use DTSTART field for DUE property in tasks -->
+ </property>
+
+ <property name="ATTENDEE" suppressempty="yes">
+ <value field="ATTENDEE_1"/>
+ <position field="ATTENDEE_1" repeat="5" increment="1" minshow="0"/>
+ </property>
+
+ <property name="PRIORITY" suppressempty="yes">
+ <value field="PRIORITY"/>
+ </property>
+
+ <property name="STATUS" suppressempty="yes">
+ <value field="STATUS" conversion="emptyonly"/>
+ </property>
+
+ <!-- AALARM and DALARM both use the same fields -->
+ <property name="AALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+ <property name="DALARM" values="4" suppressempty="yes">
+ <value index="0" field="ALARM_TIME" conversion="emptyonly"/>
+ <value index="1" field="ALARM_SNOOZE" conversion="emptyonly"/>
+ <value index="2" field="ALARM_REPEAT" conversion="emptyonly"/>
+ <value index="3" field="ALARM_MSG" conversion="emptyonly"/>
+ </property>
+
+ </subprofile>
+
+ </profile>
+ </mimeprofile>
+
+
+ <!-- vCalendar 1.0 datatype, using vCalendar profile defined
+ above -->
+ <datatype name="vcalendar10" basetype="vcalendar">
+ <version>1.0</version>
+ <use mimeprofile="vcalendar"/>
+
+ <!-- Scripting allows sophisticated data adjustment:
+ make sure we have always have a SUMMARY, but avoid
+ SUMMARY and DESCRIPTION being identical,
+ as well as always having a DTSTART
+ and an alarm message -->
+ <incomingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have at least a summary
+ if (SUMMARY==EMPTY) SUMMARY=DESCRIPTION; // use description if we don't have a summary
+ if (SUMMARY==EMPTY) SUMMARY="unnamed"; // set dummy summary if we still don't have one
+ if (DESCRIPTION==SUMMARY) DESCRIPTION=EMPTY; // do not save twice
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></incomingscript>
+
+ <outgoingscript><![CDATA[
+ // make sure we have all trailing and leading spaces eliminated
+ DESCRIPTION=NORMALIZED(DESCRIPTION);
+ SUMMARY=NORMALIZED(SUMMARY);
+ // make sure we have both description AND summary
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ if (SUMMARY==EMPTY) SUMMARY="unnamed";
+ if (DESCRIPTION==EMPTY) DESCRIPTION=SUMMARY; // use summary text to send
+ // make sure we have an alarm message
+ if (ALARM_TIME!=EMPTY && ALARM_MSG==EMPTY) ALARM_MSG="alarm";
+ // make sure we have DTSTART
+ if (DTSTART==EMPTY) DTSTART=DTEND;
+ ]]></outgoingscript>
+
+ <filterinitscript><![CDATA[
+ // check if we need to filter
+ INTEGER NEEDFILTER;
+
+ // we need to filter if STARTDATE() and/or ENDDATE() are set...
+ NEEDFILTER =
+ !DBHANDLESOPTS() && // ...but only if DB itself does not handle it directly
+ (STARTDATE()!=EMPTY || ENDDATE()!=EMPTY); // start or end date set
+ SETFILTERALL(NEEDFILTER); // as the filter conditions change dynamically with time, we need to filter ALL records
+ RETURN NEEDFILTER; // we need to filter
+ ]]></filterinitscript>
+
+ <filterscript><![CDATA[
+ INTEGER PASSES;
+
+ // check if item passes filter
+ PASSES=FALSE;
+ // as vCalendar handles events and tasks, we need to differentiate here
+ IF (KIND=="EVENT") {
+ // Events pass if they start within the range or
+ // have a recurrence that has started, but not yet ended
+ PASSES =
+ (DTSTART<=ENDDATE()) &&
+ (
+ (DTSTART>=STARTDATE()) ||
+ ((RR_FREQ!=EMPTY) && ((RR_END==EMPTY) || (RR_END>STARTDATE())))
+ );
+ }
+ ELSE {
+ // Todo pass if they have no DUE or one within the range
+ PASSES =
+ (DTSTART==EMPTY) ||
+ (DTSTART>=STARTDATE() && DTSTART<=ENDDATE());
+ }
+ RETURN PASSES;
+ ]]></filterscript>
+
+ <comparescript><![CDATA[
+ INTEGER RES;
+
+ // do standard compare (WHICH MUST NOT INCLUDE DTSTART/DTEND!)
+ RES = COMPAREFIELDS();
+ // do specially relaxed date checking
+ if (RES==0) {
+ // only check for same local date (not time) of DTSTART(=DUE for vTODO)
+ // to increase probability that time zone problems get masked out
+ RES = COMPARE(DATEONLY(TARGET.DTSTART),DATEONLY(REFERENCE.DTSTART));
+ }
+ RETURN RES;
+ ]]></comparescript>
+ </datatype>
+
+
+
+ <!-- list of internal fields representing plain text note data -->
+ <fieldlist name="Note">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+ <field name="SUBJECT" type="multiline" compare="always"/>
+ <field name="TEXT" type="multiline" compare="conflict" merge="lines"/>
+ </fieldlist>
+
+ <textprofile name="Note" fieldlist="Note">
+ <linemap field="SUBJECT">
+ <numlines>1</numlines>
+ <inheader>false</inheader>
+ <allowempty>true</allowempty>
+ <filterkeyword>SUBJECT</filterkeyword>
+ </linemap>
+ <linemap field="TEXT">
+ <numlines>0</numlines>
+ <inheader>false</inheader>
+ <allowempty>true</allowempty>
+ </linemap>
+ </textprofile>
+
+ <datatype name="note" basetype="text">
+ <use profile="Note"/>
+ <typestring>text/plain</typestring>
+ <versionstring>1.0</versionstring>
+ </datatype>
+
+ <datatype name="note11" basetype="text">
+ <use profile="Note"/>
+ <typestring>text/plain</typestring>
+ <versionstring>1.1</versionstring>
+ </datatype>
+
+
+ <!-- list of internal fields representing vBookmark data -->
+ <fieldlist name="bookmarks">
+ <field name="REV" type="timestamp" compare="never" age="yes"/>
+ <field name="SYNCLVL" type="integer" compare="never"/>
+
+ <!-- Name -->
+ <field name="TITLE" type="string" compare="always"/>
+
+ <!-- categories and classification -->
+ <field name="CATEGORIES" type="string" compare="conflict" merge="fillempty"/>
+ <field name="CLASS" type="string" compare="conflict" merge="fillempty"/>
+
+ <!-- web addresses -->
+ <field name="URL" type="url" compare="slowsync" merge="fillempty"/>
+
+ <!-- Note -->
+ <field name="NOTE" type="multiline" compare="conflict" merge="lines"/>
+
+ </fieldlist>
+
+ <!-- vBookmark profile -->
+ <mimeprofile name="vbookmark" fieldlist="bookmarks">
+
+ <profile name="VBKM" nummandatory="0">
+ <property name="VERSION">
+ <value conversion="version"/>
+ </property>
+
+ <property name="X-LAST-MODIFIED">
+ <value field="REV"/>
+ </property>
+
+ <property name="TITLE">
+ <value field="TITLE"/>
+ </property>
+
+ <property name="URL">
+ <value field="URL"/>
+ </property>
+
+ <!-- non-standard properties -->
+
+ <!-- inherit CATEGORIES from vCard 3.0, i.e. comma separated -->
+ <property name="CATEGORIES" values="list" valueseparator="," altvalueseparator=";">
+ <value field="CATEGORIES" combine=","/>
+ </property>
+
+ <property name="CLASS" suppressempty="yes">
+ <value field="CLASS"/>
+ </property>
+
+ <property name="NOTE" filter="no">
+ <value field="NOTE"/>
+ </property>
+
+ </profile>
+ </mimeprofile>
+
+ <!-- vBookmark datatype, using vBookmark profile defined above -->
+ <datatype name="vbookmark" basetype="mimedir">
+ <typestring>text/x-vbookmark</typestring>
+ <versionstring>1.0</versionstring>
+ <use profile="vbookmark"/>
+ </datatype>
+
+
+
+ <!-- list of internal fields representing email data -->
+ <fieldlist name="email">
+ <field name="SYNCLVL" type="integer" compare="never"/>
+ <field name="MODIFIED" type="timestamp" compare="never" age="yes"/>
+ <field name="SENDER" type="multiline" compare="always"/>
+ <field name="RECEIVER" type="multiline" compare="always"/>
+ <field name="CARBONCOPY" type="multiline" compare="always"/>
+ <field name="BLINDCARBONCOPY" type="multiline" compare="always"/>
+ <field name="REPLY_TO" type="multiline" compare="never"/>
+ <field name="SUBJECT" type="multiline" compare="always"/>
+ <field name="PRIORITY" type="integer" compare="never"/>
+ <field name="MAILDATE" type="timestamp" compare="never"/>
+ <field name="STATUS" type="string" compare="never"/>
+ <field name="FOLDER" type="string" compare="conflict"/>
+ <field name="ISREAD" type="string" compare="never"/>
+ <field name="LIMIT" type="integer" compare="never"/>
+ <field name="BODY" type="multiline" compare="never"/>
+ <field name="ATT_COUNT" type="integer" compare="never"/>
+ <field name="ATT_NAMES" array="yes" type="string" compare="never"/>
+ <field name="ATT_MIMETYPES" array="yes" type="string" compare="never"/>
+ <field name="ATT_SIZES" array="yes" type="integer" compare="never"/>
+ <field name="ATT_CONTENTS" array="yes" type="blob" compare="never"/>
+ </fieldlist>
+
+
+ <!-- this is the text profile used to generate and decode RFC2822/MIME-Multipart
+ email messages. -->
+ <textprofile name="rfc2822_email" fieldlist="email">
+
+ <mimemail>true</mimemail>
+ <!-- attachment configuration -->
+ <maxattachments>100</maxattachments>
+ <attachmentcountfield>ATT_COUNT</attachmentcountfield>
+ <attachmentmimetypesfield>ATT_MIMETYPES</attachmentmimetypesfield>
+ <attachmentsfield>ATT_CONTENTS</attachmentsfield>
+ <attachmentsizesfield>ATT_SIZES</attachmentsizesfield>
+ <attachmentnamesfield>ATT_NAMES</attachmentnamesfield>
+ <sizelimitfield>LIMIT</sizelimitfield>
+
+
+ <linemap field="SENDER">
+ <headertag>From:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ <filterkeyword>FROM</filterkeyword>
+ </linemap>
+
+ <linemap field="RECEIVER">
+ <headertag>To:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ <filterkeyword>TO</filterkeyword>
+ </linemap>
+
+ <linemap field="CARBONCOPY">
+ <headertag>Cc:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ <filterkeyword>CC</filterkeyword>
+ </linemap>
+
+ <linemap field="BLINDCARBONCOPY">
+ <headertag>Bcc:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ <filterkeyword>BCC</filterkeyword>
+ </linemap>
+
+ <linemap field="REPLY_TO">
+ <headertag>Reply-To:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="SUBJECT">
+ <headertag>Subject:</headertag>
+ <valuetype>rfc2047</valuetype>
+ <inheader>true</inheader>
+ <filterkeyword>SUBJECT</filterkeyword>
+ </linemap>
+
+ <linemap field="PRIORITY">
+ <headertag>X-Priority:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="MAILDATE">
+ <valuetype>date</valuetype>
+ <headertag>Date:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="STATUS">
+ <headertag>Status:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="FOLDER">
+ <headertag>X-Sync-Parent-Folder:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="ISREAD">
+ <headertag>X-Sync-Message-Read:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="MODIFIED">
+ <!-- note that this is a ISO8601 date -->
+ <headertag>X-Sync-Lastmodified:</headertag>
+ <inheader>true</inheader>
+ </linemap>
+
+ <linemap field="BODY">
+ <valuetype>body</valuetype>
+ <numlines>0</numlines>
+ <inheader>false</inheader>
+ <allowempty>true</allowempty>
+ </linemap>
+ </textprofile>
+
+
+ <datatype name="email" basetype="text">
+ <use profile="rfc2822_email"/>
+ <typestring>text/message</typestring> <!-- this is P800-like -->
+ <versionstring>1.0</versionstring>
+
+ <initscript><![CDATA[
+ $EMAIL_INIT_SCRIPT
+ ]]></initscript>
+
+ <processitemscript><![CDATA[
+ $EMAIL_PROCESSITEM_SCRIPT
+ ]]></processitemscript>
+
+
+ <mergescript><![CDATA[
+ $EMAIL_MERGE_SCRIPT
+ ]]></mergescript>
+
+
+ <outgoingscript><![CDATA[
+ $EMAIL_OUTGOING_SCRIPT
+ ]]></outgoingscript>
+
+ <filterinitscript><![CDATA[
+ $EMAIL_FILTERINIT_SCRIPT
+ ]]></filterinitscript>
+
+
+ <filterscript><![CDATA[
+ $EMAIL_FILTER_SCRIPT
+ ]]></filterscript>
+
+ </datatype>
+
+
+ <!-- Note: This is a proprietary extension datatype for Synthesis AG Windows Mobile SyncML clients.
+ This format is a compressed form of the standard RFC2822 format. For one, the entire data
+ is compressed using the zip algorithm (<zippedbindata>), and secondly attachments are included
+ in binary form in the RFC2822 data stream rather than bandwidth wasting B64, adding a
+ "Content-Length:" header for each MIME part (<binaryparts>). -->
+
+ <datatype name="email_zipbin" basetype="text">
+ <use profile="rfc2822_email"/>
+ <typestring>application/x-zip-message</typestring> <!-- our own private zipped binary optimized format -->
+ <versionstring>1.1</versionstring>
+ <binaryparts>yes</binaryparts>
+ <zippedbindata>yes</zippedbindata>
+ <zipcompressionlevel>9</zipcompressionlevel> <!-- -1=default, 0=no compression, 1=fast & least effective ... 9=slow and most effective -->
+
+ <initscript><![CDATA[
+ $EMAIL_INIT_SCRIPT
+ ]]></initscript>
+
+ <processitemscript><![CDATA[
+ $EMAIL_PROCESSITEM_SCRIPT
+ ]]></processitemscript>
+
+
+ <mergescript><![CDATA[
+ $EMAIL_MERGE_SCRIPT
+ ]]></mergescript>
+
+
+ <outgoingscript><![CDATA[
+ $EMAIL_OUTGOING_SCRIPT
+ ]]></outgoingscript>
+
+ <filterinitscript><![CDATA[
+ $EMAIL_FILTERINIT_SCRIPT
+ ]]></filterinitscript>
+
+
+ <filterscript><![CDATA[
+ $EMAIL_FILTER_SCRIPT
+ ]]></filterscript>
+
+ </datatype>
+
+
+
+ <datatype name="email_sonyericsson" basetype="text">
+ <use profile="rfc2822_email"/>
+ <typestring>message/rfc822</typestring> <!-- this is M600i/P990-like -->
+ <versionstring>1.0</versionstring>
+
+ <initscript><![CDATA[
+ $EMAIL_INIT_SCRIPT
+ ]]></initscript>
+
+ <processitemscript><![CDATA[
+ $EMAIL_PROCESSITEM_SCRIPT
+ ]]></processitemscript>
+
+
+ <mergescript><![CDATA[
+ $EMAIL_MERGE_SCRIPT
+ ]]></mergescript>
+
+
+ <outgoingscript><![CDATA[
+ $EMAIL_OUTGOING_SCRIPT
+ ]]></outgoingscript>
+
+ <filterinitscript><![CDATA[
+ $EMAIL_FILTERINIT_SCRIPT
+ ]]></filterinitscript>
+
+
+ <filterscript><![CDATA[
+ $EMAIL_FILTER_SCRIPT
+ ]]></filterscript>
+
+ </datatype>
+
+
+ <datatype name="email_nokia9500" basetype="text">
+ <use profile="rfc2822_email"/>
+ <typestring>message/x-rfc822</typestring> <!-- this is Nokia 9500/9300-like -->
+ <versionstring>1.0</versionstring>
+
+ <initscript><![CDATA[
+ INTEGER ITEMLIMIT;
+ // default limit is limit of session
+ ITEMLIMIT = SIZELIMIT();
+ ]]></initscript>
+
+ <processitemscript><![CDATA[
+ INTEGER n;
+
+ // For Nokia Email, we must derive folder ID from source LocURI
+ // which has form "./somestrangenumber/folder/itemid"
+ // where folder can be "Inbox" or "Outbox"
+ if (FIND(REMOTEID(),"Inbox",0)!=UNASSIGNED) {
+ FOLDER="INBOX";
+ }
+ else if (FIND(REMOTEID(),"Outbox",0)!=UNASSIGNED) {
+ FOLDER="OUTBOX";
+ }
+ // pre-process item
+ if (UPPERCASE(FOLDER)=="INBOX") {
+ // In any case, prevent adding to inbox (delete remote items instead)
+ PREVENTADD();
+ // server always wins for inbox
+ CONFLICTSTRATEGY("server-wins");
+ if (SLOWSYNC()) {
+ // also prevent modifications in server
+ IGNOREUPDATE();
+ }
+ else {
+ // normal sync items going to inbox from client need special treatment
+ if (SYNCOP()=="add" || SYNCOP()=="replace") {
+ // make sure that existing server item will conflict with this item
+ if (LIMIT!=EMPTY && (LIMIT<0 || LIMIT>SIZELIMIT())) {
+ // force conflict only if this is a reload
+ FORCECONFLICT();
+ }
+ // make sure we never overwrite a body in the inbox
+ BODY = UNASSIGNED;
+ // delete always wins over replace in inbox (to avoid adds to inbox)
+ DELETEWINS();
+ }
+ }
+ }
+ else if (UPPERCASE(FOLDER)=="OUTBOX") {
+ // never try to change something in outbox
+ IGNOREUPDATE();
+ if (SYNCOP()!="delete") {
+ // - date of mail is NOW, set it such that a correct date is written to the DB
+ MAILDATE = DBNOW();
+ // MAILDATE = (INTEGER)DBNOW() - TIMEUNITS(120); // %%% backdate it 2 mins to make sure it does not get retransmitted
+ // - echo item as delete (this causes that it is moved to the "sent" folder in the 9500)
+ ECHOITEM("delete");
+ }
+ CONFLICTSTRATEGY("client-wins");
+ }
+ else {
+ // Other folder
+ // - silently discard incoming item for other folder than the above
+ // except if it is a delete
+ if (SYNCOP()!="delete")
+ REJECTITEM(0);
+ }
+ ]]></processitemscript>
+
+
+ <mergescript><![CDATA[
+ // pre-process item
+ if (UPPERCASE(LOOSING.FOLDER)!="OUTBOX") {
+ // non-outbox (especially inbox) needs special merge to accomplish reload feature
+ // - loosing item is client's, winning is server's
+ if (LOOSING.LIMIT!=EMPTY) {
+ // loosing (remote) item specifies a new limit, override winning's default
+ WINNING.LIMIT=LOOSING.LIMIT;
+ SETWINNINGCHANGED(TRUE);
+ }
+ // make sure winning has right folder
+ WINNING.FOLDER=LOOSING.FOLDER;
+ // make sure a set read-flag gets propagated to server
+ if (LOOSING.ISREAD=="true") WINNING.ISREAD="true";
+ // merge other fields normally
+ MERGEFIELDS();
+ // make sure body does not get re-written to local DB even if merge would cause local update
+ LOOSING.BODY=UNASSIGNED;
+ }
+ else {
+ // normal merging in other folders
+ MERGEFIELDS();
+ }
+ ]]></mergescript>
+
+
+ <outgoingscript><![CDATA[
+ // we can only send to inbox or outbox
+ // - If we have no remote ID (=add command) prepare special Target item ID
+ // containing target folder.
+ if (REMOTEID()==EMPTY) {
+ if (UPPERCASE(FOLDER)=="INBOX") {
+ SETREMOTEID(REMOTEDBNAME()+"/Inbox/");
+ }
+ else if (UPPERCASE(FOLDER)=="OUTBOX") {
+ SETREMOTEID(REMOTEDBNAME()+"/Outbox/");
+ }
+ }
+ ]]></outgoingscript>
+
+ <filterinitscript><![CDATA[
+ // check if we need to filter
+ INTEGER NEEDFILTER;
+
+ NEEDFILTER =
+ !DBHANDLESOPTS() && // only if DB cannot handle it
+ (STARTDATE()!=EMPTY); // and only if a start date is set (end date not needed as there are never future emails today)
+ SETFILTERALL(NEEDFILTER);
+ RETURN NEEDFILTER;
+ ]]></filterinitscript>
+
+
+ <filterscript><![CDATA[
+ INTEGER PASSES;
+
+ // check if item passes filter
+ PASSES=FALSE;
+ // Filter out anything not for Inbox or Outbox
+ if (UPPERCASE(FOLDER)!="INBOX" && UPPERCASE(FOLDER)!="OUTBOX") RETURN FALSE;
+ // Emails pass if they have a MAILDATE on or later than start date
+ PASSES = MAILDATE>=STARTDATE();
+ RETURN PASSES;
+ ]]></filterscript>
+
+ </datatype>
+
+ </datatypes>
+
+
+ <server type="plugin">
+
+ <!-- Uncomment the following for Linux if you are sure properly working pthread implementation is available
+ For Windows and Mac OS X, multithreading is enabled by default -->
+ <!--<multithread>yes</multithread>-->
+
+
+ <!-- plugin module which handles the session level, i.e. login and device tracking -->
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_sessionauth>yes</plugin_sessionauth>
+ <plugin_deviceadmin>yes</plugin_deviceadmin>
+
+ <plugin_params>
+ <!-- plugin params can contain any number of plugin-specific parameters
+ that will be passed to the plugin implementation for processing -->
+
+ <!-- For TextDB: text file locations: -->
+ <!-- Uncomment the following tags if you want
+ to specifiy locations for the text files generated by the
+ server. If you leave it commented, all text files will be in the
+ application directory -->
+ <!--
+ <mapfilepath>C:\sync\auxfiles</mapfilepath>
+ <datafilepath>C:\sync\datafiles</datafilepath>
+ -->
+
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+ <!-- un-comment or change the following directive if you want the server only accept
+ SyncML 1.1 or 1.0 connections - not recommended normally, but
+ eventually useful for testing. By default, the server accepts
+ all 1.2, 1.1 and 1.0 connections -->
+ <!-- <maxsyncmlversion>1.1</maxsyncmlversion> -->
+
+ <!-- IMPORTANT: Note that the following charset, lineend and quoting settings are relevant for session-level data access only.
+ Most data access takes place in individual <datastores>, which each has the same three settings
+ again locally (see below in the <datastore> sections). -->
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+
+ <!-- If you want a text logfile, specify its full path here: -->
+ <!-- <logfile platform="win32">D:\your\log\directory\yourlogfile.txt</logfile> -->
+ <!-- <logfile platform="linux">/your/log/directory/yourlogfile.txt</logfile> -->
+ <!-- <logfile platform="macosx">/your/log/directory/yourlogfile.txt</logfile> -->
+
+ <logenabled>yes</logenabled> <!-- log enabled by default (session login scripts might disable it for special users/devices) -->
+
+ <!-- the logfile format can be customized with <loglabels> and <logformat>
+ but if these are not specified, a default format will be used
+ -->
+ <!-- This sample produces a simplified logfile:
+ <loglabels>SyncEndTime\tUser\tStatus\tSynctype\tRemoteName\tDatabase\tLocAdded\tLocUpdated\tLocDeleted\n\n</loglabels>
+ <logformat>%seT\t%U\t%sS\t%tS\t%nR\t%lD\t%laI\t%luI\t%ldI\n</logformat>
+ -->
+
+
+ <sessioninitscript><![CDATA[
+ // these variables are possibly modified by rule scripts
+ TIMESTAMP mindate; // earliest date remote party can handle
+ INTEGER retransfer_body; // if set to true, body is re-sent to client when message is moved from outbox to sent
+ mindate=EMPTY; // no limit by default
+ retransfer_body=FALSE; // normally, do not retransfer email body (and attachments) when moving items to sent box
+ ]]></sessioninitscript>
+
+ <!-- timeout for unfinished sessions in seconds -->
+ <sessiontimeout>300</sessiontimeout>
+
+ <!-- defines how clients must authenticate with the server
+ To allow simple authentication (unencrypted passwords will
+ be transferred over the net, so be careful)
+ set <requiredauth> to "basic" instead of "md5"
+ -->
+ <requestedauth>md5</requestedauth>
+ <requiredauth>md5</requiredauth>
+ <autononce>yes</autononce>
+
+ <!-- you can comment out <simpleauthuser> and <simpleauthpw>
+ to have the server use the userauth.txt file for user
+ authentification check -->
+ <simpleauthuser>test</simpleauthuser>
+ <simpleauthpw>test</simpleauthpw>
+
+ <!-- text file locations. -->
+ <!-- Uncomment the following tags if you want
+ to specifiy locations for the text files generated by the
+ server. If you leave it commented, all text files will be in the
+ application directory -->
+ <!--
+ <mapfilepath>C:\sync\auxfiles</mapfilepath>
+ <datafilepath>C:\sync\datafiles</datafilepath>
+ -->
+
+
+ <datastore name="contacts" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "contacts" -->
+ <fieldmap fieldlist="contacts">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcard21" mode="rw" preferred="yes"/>
+ <use datatype="vcard30" mode="rw"/>
+ </typesupport>
+
+ </datastore>
+
+
+ <datastore name="events" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "calendar" -->
+ <fieldmap fieldlist="calendar">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcalendar10" mode="rw" preferred="yes" variant="VEVENT"/>
+ </typesupport>
+
+ </datastore>
+
+
+ <datastore name="tasks" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "calendar" -->
+ <fieldmap fieldlist="calendar">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcalendar10" mode="rw" preferred="yes" variant="VTODO"/>
+ </typesupport>
+
+ </datastore>
+
+ <!-- this "superdatastore" makes the two individual
+ "events" and "tasks" datastores accessible as one
+ datastore. This is required for example for
+ SyncML clients like Nokia 9210 RemoteSync -->
+ <superdatastore name="calendar">
+
+ <!-- sub-datastores contained in this superdatastore -->
+
+ <!-- if set, SyncML DS 1.2 filtering is possible and will be indicated in server devInf -->
+ <ds12filters>yes</ds12filters>
+
+ <!-- if set, datastore supports filtering by a date range specification (SINCE,BEFORE or /dr())
+ Note: if this is set to yes, actual range filtering must be implemented in the datatype
+ and/or the subdatastores contained in this superdatastore -->
+ <daterangesupport>yes</daterangesupport>
+
+ <contains datastore="events">
+ <dispatchfilter>F.KIND:=EVENT</dispatchfilter>
+ <guidprefix>e</guidprefix>
+ </contains>
+
+ <contains datastore="tasks">
+ <dispatchfilter>F.KIND:=TODO</dispatchfilter>
+ <guidprefix>t</guidprefix>
+ </contains>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vcalendar10" mode="rw" preferred="yes"/>
+ </typesupport>
+
+ </superdatastore>
+
+
+ <datastore name="notes" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "notes" -->
+ <fieldmap fieldlist="Note">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <typesupport>
+ <use datatype="note" mode="rw" preferred="yes"/>
+ <use datatype="note11" mode="rw"/>
+ </typesupport>
+
+ </datastore>
+
+
+ <datastore name="bookmarks" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "bookmarks" -->
+ <fieldmap fieldlist="bookmarks">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <!-- datatypes supported by this datastore -->
+ <typesupport>
+ <use datatype="vbookmark" mode="rw" preferred="yes"/>
+ </typesupport>
+
+ </datastore>
+
+
+ <datastore name="emails" type="plugin">
+
+ <plugin_module>SDK_textdb</plugin_module>
+ <plugin_datastoreadmin>yes</plugin_datastoreadmin>
+ <plugin_params>
+ <!-- specify plugin-specific parameters here, they will be
+ passed to the plugin implementation for processing -->
+ <ultimate_answer>42</ultimate_answer> <!-- just as an example -->
+ </plugin_params>
+
+
+ <!-- General datastore settings for all DB types -->
+
+ <!-- if this is set to "yes", SyncML clients can only read
+ from the server database, but make no modifications -->
+ <readonly>no</readonly>
+
+ <!-- conflict strategy: Newer item wins
+ You can set "server-wins" or "client-wins" as well
+ if you want to give one side precedence
+ -->
+ <conflictstrategy>newer-wins</conflictstrategy>
+
+ <!-- on slowsync: duplicate items that are not fully equal
+ You can set this to "newer-wins" as well to avoid
+ duplicates as much as possible
+ -->
+ <slowsyncstrategy>duplicate</slowsyncstrategy>
+
+ <!-- Visibility control: Server items that have the SYNCLVL
+ field set to 0 will be invisible to SyncML clients.
+ Using CGI-filtering in database names (such as
+ ./contacts?SYNCLVL:>=5) smaller clients can
+ sync a reduced set of server items -->
+ <makepassfilter>F.SYNCLVL:=10</makepassfilter>
+ <invisiblefilter>F.SYNCLVL:=0|F.SYNCLVL*=E</invisiblefilter>
+ <makevisiblefilter>F.SYNCLVL:=10</makevisiblefilter>
+
+
+ <!-- text db plugin is designed for UTF-8, make sure data is passed as UTF-8 (and not the ISO-8859-1 default) -->
+ <datacharset>UTF-8</datacharset>
+ <!-- use C-language (unix style) linefeeds (\n, 0x0A) -->
+ <datalineends>unix</datalineends>
+
+ <!-- set this to "UTC" if time values should be stored in UTC into the database
+ rather than local time. "SYSTEM" denotes local server time zone. -->
+ <datatimezone>SYSTEM</datatimezone>
+
+ <!-- plugin DB may have its own identifiers to determine the point in time of changes, so
+ we must make sure this identifier is stored (and not only the sync time) -->
+ <storesyncidentifiers>yes</storesyncidentifiers>
+
+ <!-- TextDB plugin supports resume and resuming partial items, so enable these here -->
+ <resumesupport>yes</resumesupport>
+ <resumeitemsupport>yes</resumeitemsupport>
+
+
+
+ <!-- Mapping of the fields to the fieldlist "notes" -->
+ <fieldmap fieldlist="email">
+ <automap indexasname="true"/>
+ </fieldmap>
+
+ <typesupport>
+ <!-- Note: the compressed Synthesis specific "email_zipbin" format is made the preferred format
+ here to make sure clients supporting that format will actually use it. -->
+ <use datatype="email_zipbin" mode="rw" preferred="yes"/>
+ <use datatype="email" mode="rw" preferred="no"/>
+ <use datatype="email_nokia9500" mode="rw" preferred="no"/>
+ <use datatype="email_sonyericsson" mode="rw" preferred="no"/>
+ </typesupport>
+
+ </datastore>
+
+
+ <!-- Remote Rules list
+ =================
+ Note: the <remoterule> tags specify options and exceptions needed for correct handling of
+ certain devices. Synthesis AG provides this list including all currently know
+ exceptions in this config file and also publishes regular updates for the list
+ of remote rules on its web site at http://www.synthesis.ch
+ -->
+
+
+ <remoterule name="t39m">
+ <!-- Rule for Ericsson T39m client -->
+ <manufacturer>Ericsson</manufacturer>
+ <software>R1A</software>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Ericsson T39m</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="t68">
+ <!-- Rule for Ericsson T68 client -->
+ <manufacturer>Ericsson</manufacturer>
+ <software>R1B</software>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Ericsson T68</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="V3">
+ <!-- Rule for Motorola V3 -->
+ <manufacturer>Motorola*</manufacturer>
+ <model>V3</model>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <quote8bitcontent>yes</quote8bitcontent>
+ <nocontentfolding>yes</nocontentfolding>
+ <outputcharset>ANSI</outputcharset>
+ <descriptivename>Motorola V3</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="V3i">
+ <!-- Rule for Motorola V3i -->
+ <manufacturer>Motorola*</manufacturer>
+ <model>V3i</model>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <quote8bitcontent>yes</quote8bitcontent>
+ <nocontentfolding>yes</nocontentfolding>
+ <outputcharset>ANSI</outputcharset>
+ <descriptivename>Motorola V3i</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6230">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6230</model>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6230</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="9210">
+ <manufacturer>NOKIA</manufacturer>
+ <model>9210</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 9210</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="9210i">
+ <manufacturer>NOKIA</manufacturer>
+ <model>9210i</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 9210</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3220">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3220</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3220</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3230">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3230</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3230</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3600">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3600</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3600</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3620">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3620</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3620</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3650">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3650</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3650</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="3660">
+ <manufacturer>NOKIA</manufacturer>
+ <model>3660</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 3660</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6260">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6260</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6260</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6600">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6600</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6600</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6620">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6620</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6620</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6630">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6630</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6630</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="6670">
+ <manufacturer>NOKIA</manufacturer>
+ <model>6670</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 6670</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="7250">
+ <manufacturer>NOKIA</manufacturer>
+ <model>7250</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 7250</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="7250i">
+ <manufacturer>NOKIA</manufacturer>
+ <model>7250i</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 7250i</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="7260">
+ <manufacturer>NOKIA</manufacturer>
+ <model>7260</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 7260</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="7610">
+ <manufacturer>NOKIA</manufacturer>
+ <model>7610</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 7610</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="7650">
+ <manufacturer>NOKIA</manufacturer>
+ <model>7650</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia 7650</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="N-Gage">
+ <manufacturer>NOKIA</manufacturer>
+ <model>N-Gage</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia N-Gage</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="N-Gage QD">
+ <manufacturer>NOKIA</manufacturer>
+ <model>N-Gage QD</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Nokia N-Gage QD</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="9300">
+ <manufacturer>NOKIA</manufacturer>
+ <model>9300</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <treatasutc>yes</treatasutc> <!-- needs 2.1.1 or later server -->
+ <descriptivename>Nokia 9300</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="9500">
+ <manufacturer>NOKIA</manufacturer>
+ <model>9500</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <treatasutc>yes</treatasutc> <!-- needs 2.1.1 or later server -->
+ <descriptivename>Nokia 9500</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="E90">
+ <manufacturer>NOKIA</manufacturer>
+ <model>E90</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <ignoredevinfmaxsize>yes</ignoredevinfmaxsize>
+ <descriptivename>Nokia E90</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="X">
+ <manufacturer>Sendo</manufacturer>
+ <model>X</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>Sendo X</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="SX1">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>SX1</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ ]]></rulescript>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <forcelocaltime>yes</forcelocaltime>
+ <!-- Note: SX1 crashes on contacts with empty properties -->
+ <noemptyproperties>yes</noemptyproperties>
+ <descriptivename>Siemens SX1</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="M55">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>M55</model>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Siemens M55</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="SL55">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>SL55</model>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Siemens SL55</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="S55">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>S55</model>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Siemens S55</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="S65">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>S65</model>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Siemens S65</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="SL65">
+ <manufacturer>SIEMENS</manufacturer>
+ <model>SL65</model>
+
+ <forcelocaltime>yes</forcelocaltime>
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>Siemens SL65</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="K700">
+ <!-- Rule for SonyEricsson K700 (aka SEMC Phone) client -->
+ <manufacturer>SonyEricsson</manufacturer>
+ <model>SEMC Phone</model>
+ <software>R3B</software>
+
+ <!-- is a 1.1 client and claims UTC support, but it seems not to work ok
+ <forcelocaltime>yes</forcelocaltime>
+ -->
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>SonyEricsson K700</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="T610/T630">
+ <!-- Rule for SonyEricsson T610/T630 client -->
+ <manufacturer>SonyEricsson</manufacturer>
+ <software>R2B</software>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>SonyEricsson T610/T630</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in M600i vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your M600i is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your M600i has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ M600i devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the M600i is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="M600i">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>M600i</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson M600i</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in P800 vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your P800 is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your P800 has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ P800 devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the P800 is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="P800">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>P800</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson P800</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in P900 vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your P900 is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your P900 has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ P900 devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the P900 is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="P900">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>P900</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson P900</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in P910 vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your P910 is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your P910 has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ P910 devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the P910 is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="P910">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>P910</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson P910</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in P910i vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your P910i is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your P910i has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ P910i devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the P910i is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="P910i">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>P910i</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson P910i</descriptivename>
+ </remoterule>
+
+
+ <!-- Due to a problem in P990i vCalendar implementation,
+ the device does not calculate time zones correctly
+ in all cases.
+ If your P990i is brand new, you need to specify
+ "calendar?/o(Z)" as database path instead of just
+ "calendar". If your P990i has already been synced
+ at least once via the cradle and the software
+ delivered with the device, you must omit the
+ "?/o(Z)" appendix and specify just "calendar" instead.
+ Please also note that the o(Z) option for never-synced
+ P990i devices only works if your server's config is
+ derived from a recent version of our sample config.
+ Otherwise, just make sure the P990i is synced once
+ in the cradle before using SyncML.
+ -->
+ <remoterule name="P990i">
+ <manufacturer>Sony Ericsson</manufacturer>
+ <model>P990i</model>
+
+ <rulescript><![CDATA[
+ // no dates before 1980
+ mindate=(TIMESTAMP)"19800101T000000Z";
+ // retransfer body when items are moved to sent box
+ retransfer_body=TRUE;
+ ]]></rulescript>
+
+ <treataslocaltime>no</treataslocaltime> <!-- can be set to yes to have /o(Z) mode (see comment above) as default, otherwise /o(z) is default -->
+ <forcelocaltime>yes</forcelocaltime>
+ <descriptivename>SonyEricsson P990i</descriptivename>
+ </remoterule>
+
+
+ <remoterule name="t68i">
+ <!-- Rule for SonyEricsson T68i client -->
+ <manufacturer>SonyEricsson</manufacturer>
+ <software>R2A</software>
+
+ <limitedfieldlengths>yes</limitedfieldlengths>
+ <descriptivename>SonyEricsson T68i</descriptivename>
+ </remoterule>
+
+ <!-- End of remote rule list. -->
+
+ </server>
+
+</sysync_config>