libsyncml  0.5.4
data_sync_devinf.c
1 /*
2  * libsyncml - A syncml protocol implementation
3  * Copyright (C) 2008-2009 Michael Bell <michael.bell@opensync.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 #include "data_sync_devinf.h"
22 #include "libsyncml/syncml_internals.h"
23 #include "libsyncml/sml_error_internals.h"
24 
25 static SmlDevInfProperty *_add_ctcap_property_by_name(
26  SmlDevInfCTCap *ctcap,
27  const char *name,
28  SmlError **error)
29 {
30  smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name));
31  CHECK_ERROR_REF
32  smlAssert(ctcap);
33  smlAssert(name);
34 
35  SmlDevInfProperty *prop = smlDevInfNewProperty(error);
36  if (!prop)
37  goto error;
38  smlDevInfPropertySetPropName(prop, name);
39  smlDevInfCTCapAddProperty(ctcap, prop);
40 
41  smlTrace(TRACE_EXIT, "%s", __func__);
42  return prop;
43 error:
44  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
45  return NULL;
46 }
47 
48 static SmlDevInfProperty *_add_ctcap_property_by_name_value(
49  SmlDevInfCTCap *ctcap,
50  const char*name,
51  const char *value,
52  SmlError **error)
53 {
54  smlTrace(TRACE_ENTRY, "%s (%s ::= %s)", __func__, VA_STRING(name), VA_STRING(value));
55  CHECK_ERROR_REF
56  smlAssert(ctcap);
57  smlAssert(name);
58  smlAssert(value);
59 
60  SmlDevInfProperty *prop = _add_ctcap_property_by_name(ctcap, name, error);
61  if (!prop)
62  goto error;
63  smlDevInfPropertyAddValEnum(prop, value);
64 
65  smlTrace(TRACE_EXIT, "%s", __func__);
66  return prop;
67 error:
68  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
69  return NULL;
70 }
71 
72 static SmlDevInfPropParam *_add_property_param(
73  SmlDevInfProperty *prop,
74  const char *name,
75  SmlError **error)
76 {
77  smlTrace(TRACE_ENTRY, "%s (%s)", __func__, VA_STRING(name));
78  CHECK_ERROR_REF
79  smlAssert(prop);
80  smlAssert(name);
81 
82  SmlDevInfPropParam *param = smlDevInfNewPropParam(error);
83  if (!param)
84  goto error;
85 
86  smlDevInfPropParamSetParamName(param, name);
87  smlDevInfPropertyAddPropParam(prop, param);
88 
89  smlTrace(TRACE_EXIT, "%s", __func__);
90  return param;
91 error:
92  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
93  return NULL;
94 }
95 
96 #define _ADD_PROPERTY_PARAM(text) \
97  param = _add_property_param(prop, text, error); \
98  if (!param) \
99  goto error;
100 #define _ADD_CTCAP_PROPERTY_BY_NAME(text) \
101  prop = _add_ctcap_property_by_name(ctcap, text, error); \
102  if (!prop) \
103  goto error;
104 #define _ADD_CTCAP_PROPERTY_BY_NAME_VALUE(name,value) \
105  if (!_add_ctcap_property_by_name_value(ctcap, name, value, error)) \
106  goto error;
107 
108 static SmlBool add_devinf_ctcap(
109  SmlDevInf *devinf,
110  const char* cttype,
111  const char *verct,
112  SmlError **error)
113 {
114  smlTrace(TRACE_ENTRY, "%s (%s %s)", __func__, VA_STRING(cttype), VA_STRING(verct));
115  CHECK_ERROR_REF
116  smlAssert(devinf);
117  smlAssert(cttype);
118  smlAssert(verct);
119 
120  // first we check for an already configure CTCap
121  SmlDevInfContentType *ct = smlDevInfNewContentType(cttype, verct, error);
122  if (!ct)
123  goto error;
124 
125  if (smlDevInfGetCTCap(devinf, ct) != NULL)
126  {
127  smlDevInfFreeContentType(ct);
128  smlTrace(TRACE_EXIT, "%s - content type already present in devinf", __func__);
129  return TRUE;
130  } else {
131  smlDevInfFreeContentType(ct);
132  smlTrace(TRACE_INTERNAL, "%s: new content type detected", __func__);
133  }
134 
135  SmlDevInfCTCap *ctcap;
136  SmlDevInfProperty *prop;
137  SmlDevInfPropParam *param;
138  if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD) &&
139  !strcmp(verct, "2.1"))
140  {
141  smlTrace(TRACE_INTERNAL, "%s: vCard 2.1 detected", __func__);
142  ctcap = smlDevInfNewCTCap(error);
143  if (!ctcap)
144  goto error;
145 
146  smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD);
147  smlDevInfCTCapSetVerCT(ctcap, "2.1");
148  _ADD_CTCAP_PROPERTY_BY_NAME("ADR")
149  _ADD_PROPERTY_PARAM("TYPE")
150  smlDevInfPropParamAddValEnum(param, "HOME");
151  smlDevInfPropParamAddValEnum(param, "WORK");
152  smlDevInfPropParamAddValEnum(param, "PARCEL");
153  smlDevInfPropParamAddValEnum(param, "POSTAL");
154  smlDevInfPropParamAddValEnum(param, "INTL");
155  smlDevInfPropParamAddValEnum(param, "DOM");
156  _ADD_PROPERTY_PARAM("HOME");
157  _ADD_PROPERTY_PARAM("WORK");
158  _ADD_PROPERTY_PARAM("PARCEL");
159  _ADD_PROPERTY_PARAM("POSTAL");
160  _ADD_PROPERTY_PARAM("INTL");
161  _ADD_PROPERTY_PARAM("DOM");
162  _ADD_CTCAP_PROPERTY_BY_NAME("AGENT")
163  _ADD_CTCAP_PROPERTY_BY_NAME("BDAY")
164  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN","VCARD")
165  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END","VCARD")
166  _ADD_CTCAP_PROPERTY_BY_NAME("EMAIL")
167  _ADD_PROPERTY_PARAM("TYPE")
168  smlDevInfPropParamAddValEnum(param, "INTERNET");
169  _ADD_PROPERTY_PARAM("INTERNET");
170  _ADD_CTCAP_PROPERTY_BY_NAME("FN")
171  _ADD_CTCAP_PROPERTY_BY_NAME("GEO")
172  _ADD_CTCAP_PROPERTY_BY_NAME("KEY")
173  _ADD_PROPERTY_PARAM("TYPE")
174  smlDevInfPropParamAddValEnum(param, "X509");
175  smlDevInfPropParamAddValEnum(param, "PGP");
176  _ADD_PROPERTY_PARAM("X509");
177  _ADD_PROPERTY_PARAM("PGP");
178  _ADD_CTCAP_PROPERTY_BY_NAME("LABEL")
179  _ADD_PROPERTY_PARAM("TYPE")
180  smlDevInfPropParamAddValEnum(param, "HOME");
181  smlDevInfPropParamAddValEnum(param, "WORK");
182  smlDevInfPropParamAddValEnum(param, "PARCEL");
183  smlDevInfPropParamAddValEnum(param, "POSTAL");
184  smlDevInfPropParamAddValEnum(param, "INTL");
185  smlDevInfPropParamAddValEnum(param, "DOM");
186  _ADD_PROPERTY_PARAM("HOME");
187  _ADD_PROPERTY_PARAM("WORK");
188  _ADD_PROPERTY_PARAM("PARCEL");
189  _ADD_PROPERTY_PARAM("POSTAL");
190  _ADD_PROPERTY_PARAM("INTL");
191  _ADD_PROPERTY_PARAM("DOM");
192  _ADD_CTCAP_PROPERTY_BY_NAME("LOGO")
193  _ADD_PROPERTY_PARAM("TYPE")
194  smlDevInfPropParamAddValEnum(param, "JPEG");
195  _ADD_PROPERTY_PARAM("JPEG");
196  _ADD_CTCAP_PROPERTY_BY_NAME("MAILER")
197  _ADD_CTCAP_PROPERTY_BY_NAME("N")
198  _ADD_CTCAP_PROPERTY_BY_NAME("NOTE")
199  _ADD_CTCAP_PROPERTY_BY_NAME("ORG")
200  _ADD_CTCAP_PROPERTY_BY_NAME("PHOTO")
201  _ADD_PROPERTY_PARAM("TYPE")
202  smlDevInfPropParamAddValEnum(param, "JPEG");
203  _ADD_PROPERTY_PARAM("JPEG");
204  _ADD_CTCAP_PROPERTY_BY_NAME("REV")
205  _ADD_CTCAP_PROPERTY_BY_NAME("ROLE")
206  _ADD_CTCAP_PROPERTY_BY_NAME("SOUND")
207  _ADD_PROPERTY_PARAM("TYPE")
208  smlDevInfPropParamAddValEnum(param, "AIFF");
209  smlDevInfPropParamAddValEnum(param, "PCM");
210  smlDevInfPropParamAddValEnum(param, "WAVE");
211  _ADD_PROPERTY_PARAM("AIFF");
212  _ADD_PROPERTY_PARAM("PCM");
213  _ADD_PROPERTY_PARAM("WAVE");
214  _ADD_CTCAP_PROPERTY_BY_NAME("TEL")
215  _ADD_PROPERTY_PARAM("TYPE")
216  smlDevInfPropParamAddValEnum(param, "WORK");
217  smlDevInfPropParamAddValEnum(param, "VOICE");
218  smlDevInfPropParamAddValEnum(param, "PREF");
219  smlDevInfPropParamAddValEnum(param, "PAGER");
220  smlDevInfPropParamAddValEnum(param, "MSG");
221  smlDevInfPropParamAddValEnum(param, "MODEM");
222  smlDevInfPropParamAddValEnum(param, "ISDN");
223  smlDevInfPropParamAddValEnum(param, "HOME");
224  smlDevInfPropParamAddValEnum(param, "FAX");
225  smlDevInfPropParamAddValEnum(param, "CELL");
226  smlDevInfPropParamAddValEnum(param, "CAR");
227  smlDevInfPropParamAddValEnum(param, "BBS");
228  _ADD_PROPERTY_PARAM("WORK");
229  _ADD_PROPERTY_PARAM("VOICE");
230  _ADD_PROPERTY_PARAM("PREF");
231  _ADD_PROPERTY_PARAM("PAGER");
232  _ADD_PROPERTY_PARAM("MSG");
233  _ADD_PROPERTY_PARAM("MODEM");
234  _ADD_PROPERTY_PARAM("ISDN");
235  _ADD_PROPERTY_PARAM("HOME");
236  _ADD_PROPERTY_PARAM("FAX");
237  _ADD_PROPERTY_PARAM("CELL");
238  _ADD_PROPERTY_PARAM("CAR");
239  _ADD_PROPERTY_PARAM("BBS");
240  _ADD_CTCAP_PROPERTY_BY_NAME("TITLE")
241  _ADD_CTCAP_PROPERTY_BY_NAME("TZ")
242  _ADD_CTCAP_PROPERTY_BY_NAME("UID")
243  _ADD_CTCAP_PROPERTY_BY_NAME("URL")
244  _ADD_PROPERTY_PARAM("TYPE")
245  smlDevInfPropParamAddValEnum(param, "WORK");
246  smlDevInfPropParamAddValEnum(param, "HOME");
247  _ADD_PROPERTY_PARAM("WORK");
248  _ADD_PROPERTY_PARAM("HOME");
249  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.1")
250  smlDevInfAppendCTCap(devinf, ctcap);
251  }
252  else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCARD_30) &&
253  !strcmp(verct, "3.0"))
254  {
255  // FIXME: this is no vCard 3.0 spec
256  // FIXME: this is in terms of vCard 3.0 a bug
257  smlTrace(TRACE_INTERNAL, "%s: vCard 3.0 detected", __func__);
258  ctcap = smlDevInfNewCTCap(error);
259  if (!ctcap)
260  goto error;
261 
262  smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCARD_30);
263  smlDevInfCTCapSetVerCT(ctcap, "3.0");
264  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("BEGIN", "VCARD")
265  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("END", "VCARD")
266  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "3.0")
267  _ADD_CTCAP_PROPERTY_BY_NAME("REV")
268  _ADD_CTCAP_PROPERTY_BY_NAME("N")
269  _ADD_CTCAP_PROPERTY_BY_NAME("TITLE")
270  _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
271  _ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
272  _ADD_CTCAP_PROPERTY_BY_NAME("ORG")
273  _ADD_CTCAP_PROPERTY_BY_NAME("EMAIL")
274  _ADD_CTCAP_PROPERTY_BY_NAME("URL")
275  _ADD_CTCAP_PROPERTY_BY_NAME("TEL")
276  _ADD_PROPERTY_PARAM("TYPE")
277  smlDevInfPropParamAddValEnum(param, "CELL");
278  smlDevInfPropParamAddValEnum(param, "HOME");
279  smlDevInfPropParamAddValEnum(param, "WORK");
280  smlDevInfPropParamAddValEnum(param, "FAX");
281  smlDevInfPropParamAddValEnum(param, "MODEM");
282  smlDevInfPropParamAddValEnum(param, "VOICE");
283  _ADD_CTCAP_PROPERTY_BY_NAME("ADR")
284  _ADD_PROPERTY_PARAM("TYPE")
285  smlDevInfPropParamAddValEnum(param, "HOME");
286  smlDevInfPropParamAddValEnum(param, "WORK");
287  _ADD_CTCAP_PROPERTY_BY_NAME("BDAY")
288  _ADD_CTCAP_PROPERTY_BY_NAME("NOTE")
289  _ADD_CTCAP_PROPERTY_BY_NAME("PHOTO")
290  _ADD_PROPERTY_PARAM("TYPE")
291  smlDevInfAppendCTCap(devinf, ctcap);
292  }
293  /* Oracle collaboration Suite uses the content type to distinguish */
294  /* the versions of vCalendar (and iCalendar) */
295  /* text/x-vcalendar --> VERSION 1.0 (vCalendar) */
296  /* text/calendar --> VERSION 2.0 (iCalendar) */
297  /* So be VERY VERY CAREFUL if you change something here. */
298  else if (!strcmp(cttype, SML_ELEMENT_TEXT_VCAL) &&
299  !strcmp(verct, "1.0"))
300  {
301  smlTrace(TRACE_INTERNAL, "%s: vCalendar 1.0 detected", __func__);
302  ctcap = smlDevInfNewCTCap(error);
303  if (!ctcap)
304  goto error;
305 
306  smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_VCAL);
307  smlDevInfCTCapSetVerCT(ctcap, "1.0");
308  _ADD_CTCAP_PROPERTY_BY_NAME("AALARM")
309  _ADD_CTCAP_PROPERTY_BY_NAME("ATTACH")
310  _ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE")
311  _ADD_PROPERTY_PARAM("EXCEPT")
312  _ADD_PROPERTY_PARAM("RSVP")
313  _ADD_PROPERTY_PARAM("STATUS")
314  _ADD_PROPERTY_PARAM("ROLE")
315  _ADD_CTCAP_PROPERTY_BY_NAME("BEGIN")
316  smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
317  smlDevInfPropertyAddValEnum(prop, "VEVENT");
318  smlDevInfPropertyAddValEnum(prop, "VTODO");
319  _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
320  _ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED")
321  _ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
322  smlDevInfPropertyAddValEnum(prop, "PUBLIC");
323  smlDevInfPropertyAddValEnum(prop, "PRIVATE");
324  smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL");
325  _ADD_CTCAP_PROPERTY_BY_NAME("DALARM")
326  _ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT")
327  _ADD_CTCAP_PROPERTY_BY_NAME("DCREATED")
328  _ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION")
329  _ADD_CTCAP_PROPERTY_BY_NAME("DTSTART")
330  _ADD_CTCAP_PROPERTY_BY_NAME("DTEND")
331  _ADD_CTCAP_PROPERTY_BY_NAME("DUE")
332  _ADD_CTCAP_PROPERTY_BY_NAME("END")
333  smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
334  smlDevInfPropertyAddValEnum(prop, "VEVENT");
335  smlDevInfPropertyAddValEnum(prop, "VTODO");
336  _ADD_CTCAP_PROPERTY_BY_NAME("EXDATE")
337  _ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED")
338  _ADD_CTCAP_PROPERTY_BY_NAME("LOCATION")
339  _ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY")
340  _ADD_CTCAP_PROPERTY_BY_NAME("RRULE")
341  _ADD_CTCAP_PROPERTY_BY_NAME("STATUS")
342  _ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY")
343  _ADD_CTCAP_PROPERTY_BY_NAME("UID")
344  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "1.0")
345  smlDevInfAppendCTCap(devinf, ctcap);
346  }
347  else if (!strcmp(cttype, SML_ELEMENT_TEXT_ICAL) &&
348  !strcmp(verct, "2.0"))
349  {
350  // FIXME: this is no iCal spec !!!
351  // FIXME: this is nearly a direct copy&paste from vCal
352  // FIXME: this is a bug in terms of iCal
353  smlTrace(TRACE_INTERNAL, "%s: iCalendar (vCalendar 2.0) detected", __func__);
354  ctcap = smlDevInfNewCTCap(error);
355  if (!ctcap)
356  goto error;
357 
358  smlDevInfCTCapSetCTType(ctcap, SML_ELEMENT_TEXT_ICAL);
359  smlDevInfCTCapSetVerCT(ctcap, "2.0");
360  _ADD_CTCAP_PROPERTY_BY_NAME("AALARM")
361  _ADD_CTCAP_PROPERTY_BY_NAME("ATTACH")
362  _ADD_CTCAP_PROPERTY_BY_NAME("ATTENDEE")
363  _ADD_PROPERTY_PARAM("RSVP")
364  _ADD_PROPERTY_PARAM("PARTSTAT")
365  _ADD_PROPERTY_PARAM("ROLE")
366  _ADD_CTCAP_PROPERTY_BY_NAME("BEGIN")
367  smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
368  smlDevInfPropertyAddValEnum(prop, "VEVENT");
369  smlDevInfPropertyAddValEnum(prop, "VTODO");
370  _ADD_CTCAP_PROPERTY_BY_NAME("CATEGORIES")
371  _ADD_CTCAP_PROPERTY_BY_NAME("COMPLETED")
372  _ADD_CTCAP_PROPERTY_BY_NAME("CLASS")
373  smlDevInfPropertyAddValEnum(prop, "PUBLIC");
374  smlDevInfPropertyAddValEnum(prop, "PRIVATE");
375  smlDevInfPropertyAddValEnum(prop, "CONFIDENTIAL");
376  _ADD_CTCAP_PROPERTY_BY_NAME("DALARM")
377  _ADD_CTCAP_PROPERTY_BY_NAME("DAYLIGHT")
378  _ADD_CTCAP_PROPERTY_BY_NAME("DCREATED")
379  _ADD_CTCAP_PROPERTY_BY_NAME("DESCRIPTION")
380  _ADD_CTCAP_PROPERTY_BY_NAME("DTSTART")
381  _ADD_CTCAP_PROPERTY_BY_NAME("DTEND")
382  _ADD_CTCAP_PROPERTY_BY_NAME("DUE")
383  _ADD_CTCAP_PROPERTY_BY_NAME("END")
384  smlDevInfPropertyAddValEnum(prop, "VCALENDAR");
385  smlDevInfPropertyAddValEnum(prop, "VEVENT");
386  smlDevInfPropertyAddValEnum(prop, "VTODO");
387  _ADD_CTCAP_PROPERTY_BY_NAME("EXDATE")
388  _ADD_CTCAP_PROPERTY_BY_NAME("LAST-MODIFIED")
389  _ADD_CTCAP_PROPERTY_BY_NAME("LOCATION")
390  _ADD_CTCAP_PROPERTY_BY_NAME("PRIORITY")
391  _ADD_CTCAP_PROPERTY_BY_NAME("RRULE")
392  _ADD_CTCAP_PROPERTY_BY_NAME("STATUS")
393  _ADD_CTCAP_PROPERTY_BY_NAME("SUMMARY")
394  _ADD_CTCAP_PROPERTY_BY_NAME("UID")
395  _ADD_CTCAP_PROPERTY_BY_NAME_VALUE("VERSION", "2.0")
396  smlDevInfAppendCTCap(devinf, ctcap);
397  }
398  else
399  {
400  /* trace the missing stuff and create a minimal CTCap */
401  smlTrace(TRACE_INTERNAL, "%s: unknown content type - %s %s", __func__, VA_STRING(cttype), VA_STRING(verct));
402  ctcap = smlDevInfNewCTCap(error);
403  if (!ctcap)
404  goto error;
405  smlDevInfCTCapSetCTType(ctcap, cttype);
406  smlDevInfCTCapSetVerCT(ctcap, verct);
407  smlDevInfAppendCTCap(devinf, ctcap);
408  }
409 
410  smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__);
411  return TRUE;
412 error:
413  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
414  return FALSE;
415 }
416 
417 static void _update_session_config_from_devinf(SmlDataSyncObject *dsObject)
418 {
419  smlTrace(TRACE_ENTRY, "%s called", __func__);
420  SmlDevInf *devinf = dsObject->remoteDevInf;
421  SmlSession *session = dsObject->session;
422 
423  // direct session config
424 
425  smlSessionUseNumberOfChanges(session, smlDevInfSupportsNumberOfChanges(devinf));
426  smlSessionUseLargeObjects(session, smlDevInfSupportsLargeObjs(devinf));
427 
428  // local device information
429 
430  if (smlDevInfSupportsUTC(devinf))
431  dsObject->onlyLocaltime = FALSE;
432  else
433  dsObject->onlyLocaltime = TRUE;
434 
435  smlTrace(TRACE_EXIT, "%s succeeded", __func__);
436 }
437 
438 /* here start the internal API functions */
439 
440 SmlBool smlDataSyncDevInfAddDatastore(
441  SmlDevInf *devinf,
442  SmlDataSyncDatastore *datastore,
443  SmlError **error)
444 {
445  smlTrace(TRACE_ENTRY, "%s (%p, %p)", __func__, devinf, datastore);
446  CHECK_ERROR_REF
447  smlAssert(datastore);
448  smlAssert(datastore->contentType);
449  smlAssert(datastore->sourceUri);
450 
451  SmlDevInfDataStore *ds = smlDevInfDataStoreNew(datastore->sourceUri, error);
452  if (!ds)
453  goto error;
454 
455  const char *ct = datastore->contentType;
456  SmlDevInfContentType *ctype;
457 
458  if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD))
459  {
460  // we prefer actually vCard 2.1
461  // because the most cellphones support it
462  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error);
463  if (!ctype)
464  goto error;
465  smlDevInfDataStoreAddRx(ds, ctype);
466  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "3.0", error);
467  if (!ctype)
468  goto error;
469  smlDevInfDataStoreAddTx(ds, ctype);
470  smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1");
471  smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD, "2.1");
472  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error))
473  goto error;
474  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error))
475  goto error;
476  }
477  else if (!strcmp(ct, SML_ELEMENT_TEXT_VCARD_30))
478  {
479  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error);
480  if (!ctype)
481  goto error;
482  smlDevInfDataStoreAddRx(ds, ctype);
483  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCARD_30, "2.1", error);
484  if (!ctype)
485  goto error;
486  smlDevInfDataStoreAddTx(ds, ctype);
487  smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0");
488  smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCARD_30, "3.0");
489  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD, "2.1", error))
490  goto error;
491  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCARD_30, "3.0", error))
492  goto error;
493  }
494  else if (!strcmp(ct, SML_ELEMENT_TEXT_VCAL))
495  {
496  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error);
497  if (!ctype)
498  goto error;
499  smlDevInfDataStoreAddRx(ds, ctype);
500  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_ICAL, "2.0", error);
501  if (!ctype)
502  goto error;
503  smlDevInfDataStoreAddTx(ds, ctype);
504  smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0");
505  smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_VCAL, "1.0");
506  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error))
507  goto error;
508  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error))
509  goto error;
510  }
511  else if (!strcmp(ct, SML_ELEMENT_TEXT_ICAL))
512  {
513  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error);
514  if (!ctype)
515  goto error;
516  smlDevInfDataStoreAddRx(ds, ctype);
517  ctype = smlDevInfNewContentType(SML_ELEMENT_TEXT_VCAL, "1.0", error);
518  if (!ctype)
519  goto error;
520  smlDevInfDataStoreAddTx(ds, ctype);
521  smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0");
522  smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_ICAL, "2.0");
523  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_VCAL, "1.0", error))
524  goto error;
525  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_ICAL, "2.0", error))
526  goto error;
527  }
528  else if (!strcmp(ct, SML_ELEMENT_TEXT_PLAIN))
529  {
530  smlDevInfDataStoreSetRxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0");
531  smlDevInfDataStoreSetTxPref(ds, SML_ELEMENT_TEXT_PLAIN, "1.0");
532  if (!add_devinf_ctcap(devinf, SML_ELEMENT_TEXT_PLAIN, "1.0", error))
533  goto error;
534  }
535  else
536  {
537  smlTrace(TRACE_INTERNAL, "%s - unknown content type detected (%s)",
538  __func__, VA_STRING(ct));
539  smlDevInfDataStoreSetRxPref(ds, ct, "1.0");
540  smlDevInfDataStoreSetTxPref(ds, ct, "1.0");
541  if (!add_devinf_ctcap(devinf, ct, "1.0", error))
542  goto error;
543  }
544 
545  // configure supported sync modes
546  smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_TWO_WAY, TRUE);
547  smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SLOW_SYNC, TRUE);
548  // server alerted sync means that the client has to interpret alerts !!!
549  // FIXME: we receive alerts but we do nothing with it
550  if (smlDsServerGetServerType(datastore->server) == SML_DS_CLIENT)
551  // smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT, TRUE);
552  smlTrace(TRACE_INTERNAL, "%s: SyncML clients only support SLOW and TWO WAY SYNC", __func__);
553  else
554  smlDevInfDataStoreSetSyncCap(ds, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC, TRUE);
555 
556  smlDevInfAddDataStore(devinf, ds);
557  smlTrace(TRACE_EXIT, "%s - content type newly added to devinf", __func__);
558  return TRUE;
559 error:
560  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
561  return FALSE;
562 }
563 
564 SmlBool smlDataSyncDevInfLoadRemote(
565  SmlDataSyncObject *dsObject,
566  SmlBool sendGet,
567  SmlError **error)
568 {
569  smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error);
570  CHECK_ERROR_REF
571  smlAssert(dsObject);
572  smlAssertMsg(dsObject->session, "an active session is needed to have a remote device");
573 
574  /* if there is already a remote device information
575  * then cleanup the reference.
576  */
577  if (dsObject->remoteDevInf)
578  smlDevInfUnref(dsObject->remoteDevInf);
579 
580  dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf(dsObject->agent, dsObject->session);
581  if (dsObject->remoteDevInf)
582  {
583  smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was received.", __func__);
584  smlDevInfRef(dsObject->remoteDevInf);
585  _update_session_config_from_devinf(dsObject);
586  /* DevInf caching is optional */
587  if (dsObject->writeDevInfCallback) {
588  smlTrace(TRACE_EXIT, "%s - calling writeDevInfCallback", __func__);
589  return dsObject->writeDevInfCallback(
590  dsObject, dsObject->remoteDevInf,
591  dsObject->writeDevInfUserdata,
592  error);
593  } else {
594  smlTrace(TRACE_EXIT, "%s - remote DevInf available", __func__);
595  return TRUE;
596  }
597  } else {
598  smlTrace(TRACE_INTERNAL, "%s: The remote DevInf was not received.", __func__);
599  /* DevInf caching is optional */
600  if (dsObject->readDevInfCallback)
601  {
602  smlTrace(TRACE_INTERNAL, "%s: calling read DevInf callback", __func__);
603  SmlDevInf *devinf = dsObject->readDevInfCallback(
604  dsObject,
605  smlLocationGetURI(smlSessionGetTarget(dsObject->session)),
606  dsObject->readDevInfUserdata, error);
607  if (!devinf && *error)
608  goto error;
609  if (devinf) {
610  if (!smlDevInfAgentSetSessionDevInf(
611  dsObject->agent,
612  dsObject->session,
613  devinf,
614  error))
615  {
616  goto error;
617  }
618  dsObject->remoteDevInf = smlDevInfAgentGetSessionDevInf(
619  dsObject->agent,
620  dsObject->session);
621  /* smlDevInfAgentSetDevInf consumes the DevInf object.
622  * So the reference counter must be incremented for
623  * remoteDevInf.
624  */
625  smlDevInfRef(dsObject->remoteDevInf);
626  _update_session_config_from_devinf(dsObject);
627  smlTrace(TRACE_EXIT, "%s - cached DevInf", __func__);
628  return TRUE;
629  }
630  }
631  if (sendGet)
632  {
633  /* the local device information is only send for fairness ;) */
635  dsObject->agent,
636  dsObject->session,
637  error);
639  dsObject->agent,
640  dsObject->session,
641  error);
642  }
643  smlTrace(TRACE_EXIT, "%s - no remote DevInf available at all", __func__);
644  return FALSE;
645  }
646 error:
647  smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
648  return FALSE;
649 }
650 
651 char *smlDataSyncDevInfGetIdentifier()
652 {
653  smlTrace(TRACE_ENTRY, "%s", __func__);
654  const char *user = g_get_user_name();
655  const char *host = g_get_host_name();
656  char *id = g_strjoin("@", user, host, NULL);
657  smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(id));
658  return id;
659  // smlTrace(TRACE_INTERNAL, "%s - %s", __func__, VA_STRING(id));
660  // char *b64 = g_base64_encode(id, strlen(id));
661  // smlSafeCFree(&id);
662  // smlTrace(TRACE_EXIT, "%s - %s", __func__, VA_STRING(b64));
663  // return b64;
664 }
665 
666 SmlBool smlDataSyncDevInfInit(
667  SmlDataSyncObject *dsObject,
668  SmlDevInfDevTyp type,
669  SmlError **error)
670 {
671  CHECK_ERROR_REF
672  SmlDevInf *devinf = NULL;
673 
674  /* fix missing identifier */
675  if (!dsObject->identifier)
676  dsObject->identifier = smlDataSyncDevInfGetIdentifier();
677 
678  if (dsObject->fakeDevice)
679  {
680  smlTrace(TRACE_INTERNAL, "%s: faking devinf", __func__);
681  devinf = smlDevInfNew(dsObject->identifier, SML_DEVINF_DEVTYPE_SMARTPHONE, error);
682  if (!devinf)
683  goto error;
684 
685  smlDevInfSetManufacturer(devinf, dsObject->fakeManufacturer);
686  smlDevInfSetModel(devinf, dsObject->fakeModel);
687  smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion);
688  } else {
689  smlTrace(TRACE_INTERNAL, "%s: not faking devinf", __func__);
690  devinf = smlDevInfNew(dsObject->identifier, type, error);
691  if (!devinf)
692  goto error;
693 
694  smlDevInfSetSoftwareVersion(devinf, dsObject->fakeSoftwareVersion);
695  }
696 
697  smlDevInfSetSupportsNumberOfChanges(devinf, TRUE);
698  smlDevInfSetSupportsLargeObjs(devinf, TRUE);
699  if (!dsObject->onlyLocaltime)
700  smlDevInfSetSupportsUTC(devinf, TRUE);
701  smlAssert(dsObject->maxMsgSize);
702  smlAssert(dsObject->maxObjSize);
703 
704  dsObject->localDevInf = devinf;
705 
706  dsObject->agent = smlDevInfAgentNew(dsObject->localDevInf, error);
707  if (!dsObject->agent)
708  goto error;
709  smlDevInfRef(dsObject->localDevInf); /* the agent consumes the object */
710 
711  if (!smlDevInfAgentRegister(dsObject->agent, dsObject->manager, error))
712  goto error;
713 
714  return TRUE;
715 error:
716  if (devinf)
717  smlDevInfUnref(devinf);
718  if (dsObject->agent)
719  smlDevInfAgentFree(dsObject->agent);
720  dsObject->localDevInf = NULL;
721  dsObject->agent = NULL;
722  return FALSE;
723 }
724 
725 SmlBool smlDataSyncManageDevInf(
726  SmlDataSyncObject *dsObject,
727  SmlBool sendGet,
728  SmlError **error)
729 {
730  smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, dsObject, sendGet, error);
731  CHECK_ERROR_REF
732  smlAssertMsg(dsObject->session, "an active session is needed to manage device informations");
733 
734  /* If the callback is available
735  * then we dump the local device information first.
736  */
737  if (dsObject->writeDevInfCallback)
738  {
739  /* store device info */
740  smlTrace(TRACE_INTERNAL, "%s: calling write DevInf callback", __func__);
741  if (!dsObject->writeDevInfCallback(
742  dsObject, dsObject->localDevInf,
743  dsObject->writeDevInfUserdata, error))
744  goto error;
745  }
746 
747  /* handle remote device information */
748  if (smlDataSyncDevInfLoadRemote(dsObject, sendGet, error) &&
749  dsObject->remoteDevInf &&
750  dsObject->handleRemoteDevInfCallback &&
751  !dsObject->handleRemoteDevInfCallback(
752  dsObject,
753  dsObject->remoteDevInf,
754  dsObject->handleRemoteDevInfUserdata,
755  error))
756  {
757  /* the remote device information
758  * and the callback are available
759  * but the callback failed.
760  */
761  goto error;
762  } else {
763  /* check if there was an error during DevInfLoadRemote
764  * or dsObject->handleRemoteDevInfCallback
765  */
766  if (*error != NULL)
767  goto error;
768  /* if the remote peer does not support UTC
769  * then dsObject must be configured properly
770  */
771  if (dsObject->remoteDevInf &&
772  !smlDevInfSupportsUTC(dsObject->remoteDevInf))
773  {
774  smlTrace(TRACE_INTERNAL,
775  "%s: enforcing localtime because of remote DevInf",
776  __func__);
777  dsObject->onlyLocaltime = TRUE;
778  }
779  }
780 
781  smlTrace(TRACE_EXIT, "%s - TRUE", __func__);
782  return TRUE;
783 error:
784  smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
785  return FALSE;
786 }
787 
SmlBool smlDevInfAgentSendDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
This object represents an OMA DS datastore.
Definition: data_sync.h:93
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
This is the central synchronization object.
Definition: data_sync.h:110
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
SmlBool smlDevInfAgentRequestDevInf(SmlDevInfAgent *agent, SmlSession *session, SmlError **error)
Represent an error.