libsyncml 0.5.4

- Main Page
- Modules
- Data Structures
- Files

- File List

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 ;) */
634 smlDevInfAgentSendDevInf(
635 dsObject->agent,
636 dsObject->session,
637 error);
638 smlDevInfAgentRequestDevInf(
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