data_sync_devinf.c
/*
* libsyncml - A syncml protocol implementation
* Copyright (C) 2008-2009 Michael Bell <michael.bell@opensync.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "data_sync_devinf.h"
#include "libsyncml/syncml_internals.h"
#include "libsyncml/sml_error_internals.h"
static SmlDevInfProperty *_add_ctcap_property_by_name(
SmlDevInfCTCap *ctcap,
const char *name,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name));
CHECK_ERROR_REF
smlAssert(ctcap);
smlAssert(name);
SmlDevInfProperty *prop = smlDevInfNewProperty(error);
if (!prop)
goto error;
smlDevInfPropertySetPropName(prop, name);
smlDevInfCTCapAddProperty(ctcap, prop);
smlTrace(TRACE_EXIT, "%s", __func__);
return prop;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
static SmlDevInfProperty *_add_ctcap_property_by_name_value(
SmlDevInfCTCap *ctcap,
const char*name,
const char *value,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s (%s ::= %s)", __func__, VA_STRING(name), VA_STRING(value));
CHECK_ERROR_REF
smlAssert(ctcap);
smlAssert(name);
smlAssert(value);
SmlDevInfProperty *prop = _add_ctcap_property_by_name(ctcap, name, error);
if (!prop)
goto error;
smlDevInfPropertyAddValEnum(prop, value);
smlTrace(TRACE_EXIT, "%s", __func__);
return prop;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
static SmlDevInfPropParam *_add_property_param(
SmlDevInfProperty *prop,
const char *name,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name));
CHECK_ERROR_REF
smlAssert(prop);
smlAssert(name);
SmlDevInfPropParam *param = smlDevInfNewPropParam(error);
if (!param)
goto error;
smlDevInfPropParamSetParamName(param, name);
smlDevInfPropertyAddPropParam(prop, param);
smlTrace(TRACE_EXIT, "%s", __func__);
return param;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
#define _ADD_PROPERTY_PARAM(text) \
param = _add_property_param(prop, text, error); \
if (!param) \
goto error;
#define _ADD_CTCAP_PROPERTY_BY_NAME(text) \
prop = _add_ctcap_property_by_name(ctcap, text, error); \
if (!prop) \
goto error;
#define _ADD_CTCAP_PROPERTY_BY_NAME_VALUE(name,value) \
if (!_add_ctcap_property_by_name_value(ctcap, name, value, error)) \
goto error;
static SmlBool add_devinf_ctcap(
SmlDevInf *devinf,
const char* cttype,
const char *verct,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s (%s %s)", __func__, VA_STRING(cttype), VA_STRING(verct));
CHECK_ERROR_REF
smlAssert(devinf);
smlAssert(cttype);
smlAssert(verct);
// first we check for an already configure CTCap
SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error);
if (!ct)
goto error;
if (smlDevInfGetCTCap(devinf, ct) != NULL)
{
smlDevInfFreeContentType(ct);
smlTrace(TRACE_EXIT, "%s - content type already present in devinf", __func__);
return TRUE;
} else {
smlDevInfFreeContentType(ct);
smlTrace(TRACE_INTERNAL, "%s: new content type detected", __func__);
}
SmlDevInfCTCap *ctcap;
SmlDevInfProperty *prop;
SmlDevInfPropParam *param;
if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD) &&
!strcmp(verct, "2.1"))
{
smlTrace(TRACE_INTERNAL, "%s: vCard 2.1 detected", __func__);
ctcap = smlDevInfNewCTCap(error);
if (!ctcap)
goto error;
smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD);
smlDevInfCTCapSetVerCT(ctcap, "2.1");
_ADD_CTCAP_PROPERTY_BY_NAME("ADR")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "HOME");
smlDevInfPropParamAddValEnum(param, "WORK");
smlDevInfPropParamAddValEnum(param, "PARCEL");
smlDevInfPropParamAddValEnum(param, "POSTAL");
smlDevInfPropParamAddValEnum(param, "INTL");
smlDevInfPropParamAddValEnum(param, "DOM");
_ADD_PROPERTY_PARAM("HOME");
_ADD_PROPERTY_PARAM("WORK");
_ADD_PROPERTY_PARAM("PARCEL");
_ADD_PROPERTY_PARAM("POSTAL");
_ADD_PROPERTY_PARAM("INTL");
_ADD_PROPERTY_PARAM("DOM");
_ADD_CTCAP_PROPERTY_BY_NAME("AGENT")
_ADD_CTCAP_PROPERTY_BY_NAME("BDAY")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN","VCARD")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END","VCARD")
_ADD_CTCAP_PROPERTY_BY_NAME("EMAIL")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "INTERNET");
_ADD_PROPERTY_PARAM("INTERNET");
_ADD_CTCAP_PROPERTY_BY_NAME("FN")
_ADD_CTCAP_PROPERTY_BY_NAME("GEO")
_ADD_CTCAP_PROPERTY_BY_NAME("KEY")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "X509");
smlDevInfPropParamAddValEnum(param, "PGP");
_ADD_PROPERTY_PARAM("X509");
_ADD_PROPERTY_PARAM("PGP");
_ADD_CTCAP_PROPERTY_BY_NAME("LABEL")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "HOME");
smlDevInfPropParamAddValEnum(param, "WORK");
smlDevInfPropParamAddValEnum(param, "PARCEL");
smlDevInfPropParamAddValEnum(param, "POSTAL");
smlDevInfPropParamAddValEnum(param, "INTL");
smlDevInfPropParamAddValEnum(param, "DOM");
_ADD_PROPERTY_PARAM("HOME");
_ADD_PROPERTY_PARAM("WORK");
_ADD_PROPERTY_PARAM("PARCEL");
_ADD_PROPERTY_PARAM("POSTAL");
_ADD_PROPERTY_PARAM("INTL");
_ADD_PROPERTY_PARAM("DOM");
_ADD_CTCAP_PROPERTY_BY_NAME("LOGO")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "JPEG");
_ADD_PROPERTY_PARAM("JPEG");
_ADD_CTCAP_PROPERTY_BY_NAME("MAILER")
_ADD_CTCAP_PROPERTY_BY_NAME("N")
_ADD_CTCAP_PROPERTY_BY_NAME("NOTE")
_ADD_CTCAP_PROPERTY_BY_NAME("ORG")
_ADD_CTCAP_PROPERTY_BY_NAME("PHOTO")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "JPEG");
_ADD_PROPERTY_PARAM("JPEG");
_ADD_CTCAP_PROPERTY_BY_NAME("REV")
_ADD_CTCAP_PROPERTY_BY_NAME("ROLE")
_ADD_CTCAP_PROPERTY_BY_NAME("SOUND")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "AIFF");
smlDevInfPropParamAddValEnum(param, "PCM");
smlDevInfPropParamAddValEnum(param, "WAVE");
_ADD_PROPERTY_PARAM("AIFF");
_ADD_PROPERTY_PARAM("PCM");
_ADD_PROPERTY_PARAM("WAVE");
_ADD_CTCAP_PROPERTY_BY_NAME("TEL")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "WORK");
smlDevInfPropParamAddValEnum(param, "VOICE");
smlDevInfPropParamAddValEnum(param, "PREF");
smlDevInfPropParamAddValEnum(param, "PAGER");
smlDevInfPropParamAddValEnum(param, "MSG");
smlDevInfPropParamAddValEnum(param, "MODEM");
smlDevInfPropParamAddValEnum(param, "ISDN");
smlDevInfPropParamAddValEnum(param, "HOME");
smlDevInfPropParamAddValEnum(param, "FAX");
smlDevInfPropParamAddValEnum(param, "CELL");
smlDevInfPropParamAddValEnum(param, "CAR");
smlDevInfPropParamAddValEnum(param, "BBS");
_ADD_PROPERTY_PARAM("WORK");
_ADD_PROPERTY_PARAM("VOICE");
_ADD_PROPERTY_PARAM("PREF");
_ADD_PROPERTY_PARAM("PAGER");
_ADD_PROPERTY_PARAM("MSG");
_ADD_PROPERTY_PARAM("MODEM");
_ADD_PROPERTY_PARAM("ISDN");
_ADD_PROPERTY_PARAM("HOME");
_ADD_PROPERTY_PARAM("FAX");
_ADD_PROPERTY_PARAM("CELL");
_ADD_PROPERTY_PARAM("CAR");
_ADD_PROPERTY_PARAM("BBS");
_ADD_CTCAP_PROPERTY_BY_NAME("TITLE")
_ADD_CTCAP_PROPERTY_BY_NAME("TZ")
_ADD_CTCAP_PROPERTY_BY_NAME("UID")
_ADD_CTCAP_PROPERTY_BY_NAME("URL")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "WORK");
smlDevInfPropParamAddValEnum(param, "HOME");
_ADD_PROPERTY_PARAM("WORK");
_ADD_PROPERTY_PARAM("HOME");
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.1")
smlDevInfAppendCTCap(devinf, ctcap);
}
else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD_30) &&
!strcmp(verct, "3.0"))
{
// FIXME: this is no vCard 3.0 spec
// FIXME: this is in terms of vCard 3.0 a bug
smlTrace(TRACE_INTERNAL, "%s: vCard 3.0 detected", __func__);
ctcap = smlDevInfNewCTCap(error);
if (!ctcap)
goto error;
smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD_30);
smlDevInfCTCapSetVerCT(ctcap, "3.0");
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN", "VCARD")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END", "VCARD")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "3.0")
_ADD_CTCAP_PROPERTY_BY_NAME("REV")
_ADD_CTCAP_PROPERTY_BY_NAME("N")
_ADD_CTCAP_PROPERTY_BY_NAME("TITLE")
_ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
_ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
_ADD_CTCAP_PROPERTY_BY_NAME("ORG")
_ADD_CTCAP_PROPERTY_BY_NAME("EMAIL")
_ADD_CTCAP_PROPERTY_BY_NAME("URL")
_ADD_CTCAP_PROPERTY_BY_NAME("TEL")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "CELL");
smlDevInfPropParamAddValEnum(param, "HOME");
smlDevInfPropParamAddValEnum(param, "WORK");
smlDevInfPropParamAddValEnum(param, "FAX");
smlDevInfPropParamAddValEnum(param, "MODEM");
smlDevInfPropParamAddValEnum(param, "VOICE");
_ADD_CTCAP_PROPERTY_BY_NAME("ADR")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfPropParamAddValEnum(param, "HOME");
smlDevInfPropParamAddValEnum(param, "WORK");
_ADD_CTCAP_PROPERTY_BY_NAME("BDAY")
_ADD_CTCAP_PROPERTY_BY_NAME("NOTE")
_ADD_CTCAP_PROPERTY_BY_NAME("PHOTO")
_ADD_PROPERTY_PARAM("TYPE")
smlDevInfAppendCTCap(devinf, ctcap);
}
/* Oracle collaboration Suite uses the content type to distinguish */
/* the versions of vCalendar (and iCalendar) */
/* text/x-vcalendar --> VERSION 1.0 (vCalendar) */
/* text/calendar --> VERSION 2.0 (iCalendar) */
/* So be VERY VERY CAREFUL if you change something here. */
else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCAL) &&
!strcmp(verct, "1.0"))
{
smlTrace(TRACE_INTERNAL, "%s: vCalendar 1.0 detected", __func__);
ctcap = smlDevInfNewCTCap(error);
if (!ctcap)
goto error;
smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCAL);
smlDevInfCTCapSetVerCT(ctcap, "1.0");
_ADD_CTCAP_PROPERTY_BY_NAME("AALARM")
_ADD_CTCAP_PROPERTY_BY_NAME("ATTACH")
_ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE")
_ADD_PROPERTY_PARAM("EXCEPT")
_ADD_PROPERTY_PARAM("RSVP")
_ADD_PROPERTY_PARAM("STATUS")
_ADD_PROPERTY_PARAM("ROLE")
_ADD_CTCAP_PROPERTY_BY_NAME("BEGIN")
smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
smlDevInfPropertyAddValEnum(prop, "VEVENT");
smlDevInfPropertyAddValEnum(prop, "VTODO");
_ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
_ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED")
_ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
smlDevInfPropertyAddValEnum(prop, "PUBLIC");
smlDevInfPropertyAddValEnum(prop, "PRIVATE");
smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL");
_ADD_CTCAP_PROPERTY_BY_NAME("DALARM")
_ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT")
_ADD_CTCAP_PROPERTY_BY_NAME("DCREATED")
_ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION")
_ADD_CTCAP_PROPERTY_BY_NAME("DTSTART")
_ADD_CTCAP_PROPERTY_BY_NAME("DTEND")
_ADD_CTCAP_PROPERTY_BY_NAME("DUE")
_ADD_CTCAP_PROPERTY_BY_NAME("END")
smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
smlDevInfPropertyAddValEnum(prop, "VEVENT");
smlDevInfPropertyAddValEnum(prop, "VTODO");
_ADD_CTCAP_PROPERTY_BY_NAME("EXDATE")
_ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED")
_ADD_CTCAP_PROPERTY_BY_NAME("LOCATION")
_ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY")
_ADD_CTCAP_PROPERTY_BY_NAME("RRULE")
_ADD_CTCAP_PROPERTY_BY_NAME("STATUS")
_ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY")
_ADD_CTCAP_PROPERTY_BY_NAME("UID")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "1.0")
smlDevInfAppendCTCap(devinf, ctcap);
}
else if (!strcmp(cttype, SML_ELEMENT_TEXT_ICAL) &&
!strcmp(verct, "2.0"))
{
// FIXME: this is no iCal spec !!!
// FIXME: this is nearly a direct copy&paste from vCal
// FIXME: this is a bug in terms of iCal
smlTrace(TRACE_INTERNAL, "%s: iCalendar (vCalendar 2.0) detected", __func__);
ctcap = smlDevInfNewCTCap(error);
if (!ctcap)
goto error;
smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_ICAL);
smlDevInfCTCapSetVerCT(ctcap, "2.0");
_ADD_CTCAP_PROPERTY_BY_NAME("AALARM")
_ADD_CTCAP_PROPERTY_BY_NAME("ATTACH")
_ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE")
_ADD_PROPERTY_PARAM("RSVP")
_ADD_PROPERTY_PARAM("PARTSTAT")
_ADD_PROPERTY_PARAM("ROLE")
_ADD_CTCAP_PROPERTY_BY_NAME("BEGIN")
smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
smlDevInfPropertyAddValEnum(prop, "VEVENT");
smlDevInfPropertyAddValEnum(prop, "VTODO");
_ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
_ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED")
_ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
smlDevInfPropertyAddValEnum(prop, "PUBLIC");
smlDevInfPropertyAddValEnum(prop, "PRIVATE");
smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL");
_ADD_CTCAP_PROPERTY_BY_NAME("DALARM")
_ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT")
_ADD_CTCAP_PROPERTY_BY_NAME("DCREATED")
_ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION")
_ADD_CTCAP_PROPERTY_BY_NAME("DTSTART")
_ADD_CTCAP_PROPERTY_BY_NAME("DTEND")
_ADD_CTCAP_PROPERTY_BY_NAME("DUE")
_ADD_CTCAP_PROPERTY_BY_NAME("END")
smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
smlDevInfPropertyAddValEnum(prop, "VEVENT");
smlDevInfPropertyAddValEnum(prop, "VTODO");
_ADD_CTCAP_PROPERTY_BY_NAME("EXDATE")
_ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED")
_ADD_CTCAP_PROPERTY_BY_NAME("LOCATION")
_ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY")
_ADD_CTCAP_PROPERTY_BY_NAME("RRULE")
_ADD_CTCAP_PROPERTY_BY_NAME("STATUS")
_ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY")
_ADD_CTCAP_PROPERTY_BY_NAME("UID")
_ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.0")
smlDevInfAppendCTCap(devinf, ctcap);
}
else
{
/* trace the missing stuff and create a minimal CTCap */
smlTrace(TRACE_INTERNAL, "%s: unknown content type - %s %s", __func__, VA_STRING(cttype), VA_STRING(verct));
ctcap = smlDevInfNewCTCap(error);
if (!ctcap)
goto error;
smlDevInfCTCapSetCTType(ctcap, cttype);
smlDevInfCTCapSetVerCT(ctcap, verct);
smlDevInfAppendCTCap(devinf, ctcap);
}
smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
static void _update_session_config_from_devinf(SmlDataSyncObject *dsObject)
{
smlTrace(TRACE_ENTRY, "%s called", __func__);
SmlDevInf *devinf = dsObject->remoteDevInf;
SmlSession *session = dsObject->session;
// direct session config
smlSessionUseNumberOfChanges(session, smlDevInfSupportsNumberOfChanges(devinf));
smlSessionUseLargeObjects(session, smlDevInfSupportsLargeObjs(devinf));
// local device information
if (smlDevInfSupportsUTC(devinf))
dsObject->onlyLocaltime = FALSE;
else
dsObject->onlyLocaltime = TRUE;
smlTrace(TRACE_EXIT, "%s succeeded", __func__);
}
/* here start the internal API functions */
SmlBool smlDataSyncDevInfAddDatastore(
SmlDevInf *devinf,
SmlDataSyncDatastore *datastore,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s (%p, %p)", __func__, devinf, datastore);
CHECK_ERROR_REF
smlAssert(datastore);
smlAssert(datastore->contentType);
smlAssert(datastore->sourceUri);
SmlDevInfDataStore *ds = smlDevInfDataStoreNew(datastore->sourceUri, error);
if (!ds)
goto error;
const char *ct = datastore->contentType;
SmlDevInfContentType *ctype;
if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD))
{
// we prefer actually vCard 2.1
// because the most cellphones support it
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddRx(ds, ctype);
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddTx(ds, ctype);
smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1");
smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1");
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error))
goto error;
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error))
goto error;
}
else if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD_30))
{
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddRx(ds, ctype);
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddTx(ds, ctype);
smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0");
smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0");
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error))
goto error;
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error))
goto error;
}
else if (!strcmp(ct, SML_ELEMENT_TEXT_VCAL))
{
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddRx(ds, ctype);
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddTx(ds, ctype);
smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0");
smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0");
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error))
goto error;
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error))
goto error;
}
else if (!strcmp(ct, SML_ELEMENT_TEXT_ICAL))
{
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddRx(ds, ctype);
ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error);
if (!ctype)
goto error;
smlDevInfDataStoreAddTx(ds, ctype);
smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0");
smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0");
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error))
goto error;
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error))
goto error;
}
else if (!strcmp(ct, SML_ELEMENT_TEXT_PLAIN))
{
smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0");
smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0");
if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_PLAIN, "1.0", error))
goto error;
}
else
{
smlTrace(TRACE_INTERNAL, "%s - unknown content type detected (%s)",
__func__, VA_STRING(ct));
smlDevInfDataStoreSetRxPref(ds, ct, "1.0");
smlDevInfDataStoreSetTxPref(ds, ct, "1.0");
if (!add_devinf_ctcap(devinf, ct, "1.0", error))
goto error;
}
// configure supported sync modes
smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE);
smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE);
// server alerted sync means that the client has to interpret alerts !!!
// FIXME: we receive alerts but we do nothing with it
if (smlDsServerGetServerType(datastore->server) == SML_DS_CLIENT)
// smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT, TRUE);
smlTrace(TRACE_INTERNAL, "%s: SyncML clients only support SLOW and TWO WAY SYNC", __func__);
else
smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE);
smlDevInfAddDataStore(devinf, ds);
smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlDataSyncDevInfLoadRemote(
SmlDataSyncObject *dsObject,
SmlBool sendGet,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error);
CHECK_ERROR_REF
smlAssert(dsObject);
smlAssertMsg(dsObject->session, "an active session is needed to have a remote device");
/* if there is already a remote device information
* then cleanup the reference.
*/
if (dsObject->remoteDevInf)
smlDevInfUnref(dsObject->remoteDevInf);
dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf(dsObject->agent, dsObject->session);
if (dsObject->remoteDevInf)
{
smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was received.", __func__);
smlDevInfRef(dsObject->remoteDevInf);
_update_session_config_from_devinf(dsObject);
/* DevInf caching is optional */
if (dsObject->writeDevInfCallback) {
smlTrace(TRACE_EXIT, "%s - calling writeDevInfCallback", __func__);
return dsObject->writeDevInfCallback(
dsObject, dsObject->remoteDevInf,
dsObject->writeDevInfUserdata,
error);
} else {
smlTrace(TRACE_EXIT, "%s - remote DevInf available", __func__);
return TRUE;
}
} else {
smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was not received.", __func__);
/* DevInf caching is optional */
if (dsObject->readDevInfCallback)
{
smlTrace(TRACE_INTERNAL, "%s: calling read DevInf callback", __func__);
SmlDevInf *devinf = dsObject->readDevInfCallback(
dsObject,
smlLocationGetURI(smlSessionGetTarget(dsObject->session)),
dsObject->readDevInfUserdata, error);
if (!devinf && *error)
goto error;
if (devinf) {
if (!smlDevInfAgentSetSessionDevInf(
dsObject->agent,
dsObject->session,
devinf,
error))
{
goto error;
}
dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf(
dsObject->agent,
dsObject->session);
/* smlDevInfAgentSetDevInf consumes the DevInf object.
* So the reference counter must be incremented for
* remoteDevInf.
*/
smlDevInfRef(dsObject->remoteDevInf);
_update_session_config_from_devinf(dsObject);
smlTrace(TRACE_EXIT, "%s - cached DevInf", __func__);
return TRUE;
}
}
if (sendGet)
{
/* the local device information is only send for fairness ;) */
smlDevInfAgentSendDevInf(
dsObject->agent,
dsObject->session,
error);
smlDevInfAgentRequestDevInf(
dsObject->agent,
dsObject->session,
error);
}
smlTrace(TRACE_EXIT, "%s - no remote DevInf available at all", __func__);
return FALSE;
}
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return FALSE;
}
char *smlDataSyncDevInfGetIdentifier()
{
smlTrace(TRACE_ENTRY, "%s", __func__);
const char *user = g_get_user_name();
const char *host = g_get_host_name();
char *id = g_strjoin("@", user, host, NULL);
smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(id));
return id;
// smlTrace(TRACE_INTERNAL, "%s - %s", __func__, VA_STRING(id));
// char *b64 = g_base64_encode(id, strlen(id));
// smlSafeCFree(&id);
// smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(b64));
// return b64;
}
SmlBool smlDataSyncDevInfInit(
SmlDataSyncObject *dsObject,
SmlDevInfDevTyp type,
SmlError **error)
{
CHECK_ERROR_REF
SmlDevInf *devinf = NULL;
/* fix missing identifier */
if (!dsObject->identifier)
dsObject->identifier = smlDataSyncDevInfGetIdentifier();
if (dsObject->fakeDevice)
{
smlTrace(TRACE_INTERNAL, "%s: faking devinf", __func__);
devinf = smlDevInfNew(dsObject->identifier, SML_DEVINF_DEVTYPE_SMARTPHONE, error);
if (!devinf)
goto error;
smlDevInfSetManufacturer(devinf, dsObject->fakeManufacturer);
smlDevInfSetModel(devinf, dsObject->fakeModel);
smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion);
} else {
smlTrace(TRACE_INTERNAL, "%s: not faking devinf", __func__);
devinf = smlDevInfNew(dsObject->identifier, type, error);
if (!devinf)
goto error;
smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion);
}
smlDevInfSetSupportsNumberOfChanges(devinf, TRUE);
smlDevInfSetSupportsLargeObjs(devinf, TRUE);
if (!dsObject->onlyLocaltime)
smlDevInfSetSupportsUTC(devinf, TRUE);
smlAssert(dsObject->maxMsgSize);
smlAssert(dsObject->maxObjSize);
dsObject->localDevInf = devinf;
dsObject->agent = smlDevInfAgentNew(dsObject->localDevInf, error);
if (!dsObject->agent)
goto error;
smlDevInfRef(dsObject->localDevInf); /* the agent consumes the object */
if (!smlDevInfAgentRegister(dsObject->agent, dsObject->manager, error))
goto error;
return TRUE;
error:
if (devinf)
smlDevInfUnref(devinf);
if (dsObject->agent)
smlDevInfAgentFree(dsObject->agent);
dsObject->localDevInf = NULL;
dsObject->agent = NULL;
return FALSE;
}
SmlBool smlDataSyncManageDevInf(
SmlDataSyncObject *dsObject,
SmlBool sendGet,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error);
CHECK_ERROR_REF
smlAssertMsg(dsObject->session, "an active session is needed to manage device informations");
/* If the callback is available
* then we dump the local device information first.
*/
if (dsObject->writeDevInfCallback)
{
/* store device info */
smlTrace(TRACE_INTERNAL, "%s: calling write DevInf callback", __func__);
if (!dsObject->writeDevInfCallback(
dsObject, dsObject->localDevInf,
dsObject->writeDevInfUserdata, error))
goto error;
}
/* handle remote device information */
if (smlDataSyncDevInfLoadRemote(dsObject, sendGet, error) &&
dsObject->remoteDevInf &&
dsObject->handleRemoteDevInfCallback &&
!dsObject->handleRemoteDevInfCallback(
dsObject,
dsObject->remoteDevInf,
dsObject->handleRemoteDevInfUserdata,
error))
{
/* the remote device information
* and the callback are available
* but the callback failed.
*/
goto error;
} else {
/* check if there was an error during DevInfLoadRemote
* or dsObject->handleRemoteDevInfCallback
*/
if (*error != NULL)
goto error;
/* if the remote peer does not support UTC
* then dsObject must be configured properly
*/
if (dsObject->remoteDevInf &&
!smlDevInfSupportsUTC(dsObject->remoteDevInf))
{
smlTrace(TRACE_INTERNAL,
"%s: enforcing localtime because of remote DevInf",
__func__);
dsObject->onlyLocaltime = TRUE;
}
}
smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return FALSE;
}
smlDevInfAgentSendDevInf
SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
Definition: sml_devinf_obj.c:494
SmlDataSyncDatastore
This object represents an OMA DS datastore.
Definition: data_sync.h:93
smlErrorPrint
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlDataSyncObject
This is the central synchronization object.
Definition: data_sync.h:110
SmlDevInfCTCap
Definition: sml_devinf_internals.h:102
SmlSession
Definition: sml_session_internals.h:27
SmlDevInfContentType
Definition: sml_devinf_internals.h:107
smlTrace
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
smlDevInfAgentRequestDevInf
SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
Definition: sml_devinf_obj.c:512
SmlDevInf
Definition: sml_devinf_internals.h:33
SmlDevInfDataStore
Definition: sml_devinf_internals.h:55
SmlDevInfProperty
Definition: sml_devinf_internals.h:90
SmlError
Represent an error.
Definition: sml_error_internals.h:29
SmlDevInfPropParam
Definition: sml_devinf_internals.h:83