libsyncml 0.5.4

- Main Page
- Modules
- Data Structures
- Files

- File List

sml_elements.c
1 /*
2 * libsyncml - A syncml protocol implementation
3 * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4 * Copyright (C) 2007-2009 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include "syncml.h"
23
24 #include "syncml_internals.h"
25 #include "sml_parse_internals.h"
26 #include "sml_elements_internals.h"
27 #include "sml_command_internals.h"
28 #include "sml_error_internals.h"
29
30 SmlLocation *smlLocationNew(const char *locURI, const char *locName, SmlError **error)
31 {
32 smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(locURI), VA_STRING(locName), error);
33 CHECK_ERROR_REF
34
35 if (!locURI) {
36 smlErrorSet(error, SML_ERROR_GENERIC, "No locURI was given");
37 goto error;
38 }
39
40 SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error);
41 if (!location)
42 goto error;
43
44 location->refCount = 1;
45 location->locURI = g_strdup(locURI);
46 location->locName = g_strdup(locName);
47
48 smlTrace(TRACE_EXIT, "%s: %p", __func__, location);
49 return location;
50
51 error:
52 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
53 return NULL;
54 }
55
56 SmlLocation *smlLocationRef(SmlLocation *loc)
57 {
58 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc);
59 smlAssert(loc);
60
61 g_atomic_int_inc(&(loc->refCount));
62
63 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, loc->refCount);
64 return loc;
65 }
66
67 void smlLocationUnref(SmlLocation *loc)
68 {
69 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc);
70 smlAssert(loc);
71
72 if (g_atomic_int_dec_and_test(&(loc->refCount))) {
73 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
74
75 if (loc->locURI)
76 smlSafeCFree(&(loc->locURI));
77
78 if (loc->locName)
79 smlSafeCFree(&(loc->locName));
80
81 smlSafeFree((gpointer *)&loc);
82 }
83
84 smlTrace(TRACE_EXIT, "%s", __func__);
85 }
86
87 const char *smlLocationGetURI(SmlLocation *loc)
88 {
89 smlAssert(loc);
90 return loc->locURI;
91 }
92
93 void smlLocationSetURI(SmlLocation *loc, const char *uri)
94 {
95 smlAssert(loc);
96 smlAssert(uri);
97 if (loc->locURI)
98 smlSafeCFree(&(loc->locURI));
99 loc->locURI = g_strdup(uri);
100 }
101
102 const char *smlLocationGetName(SmlLocation *loc)
103 {
104 smlAssert(loc);
105 return loc->locName;
106 }
107
108 void smlLocationSetName(SmlLocation *loc, const char *name)
109 {
110 smlAssert(loc);
111 smlAssert(name);
112 if (loc->locName)
113 smlSafeCFree(&(loc->locName));
114 loc->locName = g_strdup(name);
115 }
116
117 SmlLocation *smlLocationClone(SmlLocation *source, SmlError **error)
118 {
119 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, error);
120 CHECK_ERROR_REF
121 smlAssert(source);
122
123 SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error);
124 if (!location)
125 goto error;
126 location->refCount = 1;
127
128 smlLocationCopy(source, location);
129
130 smlTrace(TRACE_EXIT, "%s: %p", __func__, location);
131 return location;
132
133 error:
134 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
135 return NULL;
136 }
137
138 void smlLocationCopy(SmlLocation *source, SmlLocation *target)
139 {
140 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, target);
141 smlAssert(source);
142 smlAssert(target);
143
144 if (target->locURI)
145 smlSafeCFree(&(target->locURI));
146
147 if (target->locName)
148 smlSafeCFree(&(target->locName));
149
150 target->locURI = g_strdup(source->locURI);
151 target->locName = g_strdup(source->locName);
152
153 smlTrace(TRACE_EXIT, "%s", __func__);
154 }
155
156 #define URL_DELIMITER "/"
157
158 char *strreplace(const char *input, const char *needle, const char *replacement)
159 {
160 char *output = g_strdup(input);
161
162 while (g_strrstr(output, needle)) {
163 char *buffer = g_strndup(output, g_strrstr(output, needle) - output);
164 char *buffer2 = g_strconcat(buffer, replacement ? replacement : "", g_strrstr(output, needle) + strlen(needle), NULL);
165 smlSafeCFree(&output);
166 output = buffer2;
167 smlSafeCFree(&buffer);
168 }
169
170 return output;
171 }
172
173 char *normalizeUrl(const char *url)
174 {
175 smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(url));
176
177 if (!url)
178 return NULL;
179
180 char *buffer = strreplace(url, "./", "");
181 char *buffer2 = strreplace(buffer, "//", "/");
182 smlSafeCFree(&buffer);
183
184 if (strlen(buffer2) > 0 && buffer2[strlen(buffer2) - 1] == '/')
185 buffer2[strlen(buffer2) - 1] = 0;
186
187 smlTrace(TRACE_EXIT, "%s: %s", __func__, VA_STRING(buffer2));
188 return buffer2;
189 }
190
191 SmlBool smlLocationCompare(SmlLocation *objectroot, SmlLocation *object, SmlLocation *urlroot, SmlLocation *url)
192 {
193 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, objectroot, object, urlroot, url);
194 if (objectroot)
195 smlTrace(TRACE_INTERNAL, "%s: objectroot: %s", __func__, VA_STRING(objectroot->locURI));
196 if (object)
197 smlTrace(TRACE_INTERNAL, "%s: object: %s", __func__, VA_STRING(object->locURI));
198 if (urlroot)
199 smlTrace(TRACE_INTERNAL, "%s: urlroot: %s", __func__, VA_STRING(urlroot->locURI));
200 if (url)
201 smlTrace(TRACE_INTERNAL, "%s: url: %s", __func__, VA_STRING(url->locURI));
202 char *cmpobjurl = NULL;
203 char *cmpurl = NULL;
204 char *buffer = NULL;
205 char *buffer2 = NULL;
206 SmlBool ret = FALSE;
207
208 if (object && !url) {
209 smlTrace(TRACE_EXIT, "%s: url not given but object: FALSE", __func__);
210 return FALSE;
211 }
212
213 if (!object) {
214 smlTrace(TRACE_EXIT, "%s: No object given: TRUE", __func__);
215 return TRUE;
216 }
217
218 if (g_path_is_absolute(url->locURI) || !urlroot)
219 cmpurl = normalizeUrl(url->locURI);
220 else {
221 buffer2 = normalizeUrl(url->locURI);
222 buffer = g_strconcat(urlroot->locURI, "/", buffer2, NULL);
223 cmpurl = normalizeUrl(buffer);
224 smlSafeCFree(&buffer);
225 smlSafeCFree(&buffer2);
226 }
227
228 if (g_path_is_absolute(object->locURI) || !objectroot)
229 cmpobjurl = normalizeUrl(object->locURI);
230 else {
231 buffer2 = normalizeUrl(object->locURI);
232 buffer = g_strconcat(objectroot->locURI, "/", buffer2, NULL);
233 cmpobjurl = normalizeUrl(buffer);
234 smlSafeCFree(&buffer);
235 smlSafeCFree(&buffer2);
236 }
237
238
239 smlTrace(TRACE_INTERNAL, "%s: Comparing %s and %s", __func__, VA_STRING(cmpobjurl), VA_STRING(cmpurl));
240
241 if (strcmp(cmpobjurl, cmpurl))
242 ret = FALSE;
243 else
244 ret = TRUE;
245
246 smlSafeCFree(&cmpobjurl);
247 smlSafeCFree(&cmpurl);
248
249 smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
250 return ret;
251 }
252
253 SmlBool smlLocationIsRelative(SmlLocation *location)
254 {
255 smlAssert(location);
256
257 return g_path_is_absolute(location->locURI) ? FALSE : TRUE;
258 }
259
260 SmlAnchor *smlAnchorNew(const char *last, const char *next, SmlError **error)
261 {
262 smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(last), VA_STRING(next), error);
263 CHECK_ERROR_REF
264
265 SmlAnchor *anchor = smlTryMalloc0(sizeof(SmlAnchor), error);
266 if (!anchor)
267 goto error;
268
269 anchor->last = g_strdup(last);
270 anchor->next = g_strdup(next);
271
272 smlTrace(TRACE_EXIT, "%s: %p", __func__, anchor);
273 return anchor;
274
275 error:
276 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
277 return NULL;
278 }
279
280 void smlAnchorFree(SmlAnchor *anchor)
281 {
282 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, anchor);
283 smlAssert(anchor);
284 if (anchor->last)
285 smlSafeCFree(&(anchor->last));
286
287 if (anchor->next)
288 smlSafeCFree(&(anchor->next));
289
290 smlSafeFree((gpointer *)&anchor);
291
292 smlTrace(TRACE_EXIT, "%s", __func__);
293 }
294
295 void smlHeaderFree(SmlHeader *header)
296 {
297 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, header);
298
299 if (header->sessionID)
300 smlSafeCFree(&(header->sessionID));
301
302 if (header->emi)
303 smlSafeCFree(&(header->emi));
304
305 if (header->source)
306 smlLocationUnref(header->source);
307
308 if (header->target)
309 smlLocationUnref(header->target);
310
311 if (header->responseURI)
312 smlSafeCFree(&(header->responseURI));
313
314 smlSafeFree((gpointer *)&header);
315
316 smlTrace(TRACE_EXIT, "%s", __func__);
317 }
318
319 SmlItem *smlItemNew(unsigned int size, SmlError **error)
320 {
321 smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, size, error);
322 CHECK_ERROR_REF
323
324 SmlItem *item = smlTryMalloc0(sizeof(SmlItem), error);
325 if (!item)
326 goto error;
327
328 item->refCount = 1;
329 item->size = size;
330
331 smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
332 return item;
333
334 error:
335 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
336 return NULL;
337 }
338
339 /* If data is NULL, this call is the same if smlItemNew */
340 SmlItem *smlItemNewForData(const char *data, unsigned int size, SmlError **error)
341 {
342 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error);
343 CHECK_ERROR_REF
344
345 SmlItem *item = smlItemNew(size, error);
346 if (!item)
347 goto error;
348
349 if (data) {
350 if (!smlItemAddData(item, data, size, error))
351 goto error_free_item;
352 }
353
354 smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
355 return item;
356
357 error_free_item:
358 smlItemUnref(item);
359 error:
360 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
361 return NULL;
362 }
363
364 SmlItem *smlItemRef(SmlItem *item)
365 {
366 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
367 smlAssert(item);
368
369 g_atomic_int_inc(&(item->refCount));
370
371 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount);
372 return item;
373 }
374
375 void smlItemUnref(SmlItem *item)
376 {
377 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
378 smlAssert(item);
379
380 if (g_atomic_int_dec_and_test(&(item->refCount))) {
381 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
382
383 if (item->source)
384 smlLocationUnref(item->source);
385
386 if (item->target)
387 smlLocationUnref(item->target);
388
389 if (item->sourceParent)
390 smlLocationUnref(item->sourceParent);
391
392 if (item->targetParent)
393 smlLocationUnref(item->targetParent);
394
395 if (item->anchor)
396 smlAnchorFree(item->anchor);
397
398 if (item->buffer)
399 xmlBufferFree(item->buffer);
400
401 if (item->contenttype)
402 smlSafeCFree(&(item->contenttype));
403
404 smlSafeFree((gpointer *)&item);
405 }
406
407 smlTrace(TRACE_EXIT, "%s: %i", __func__, item ? item->refCount : 0);
408 }
409
410 SmlBool smlItemAddData(SmlItem *item, const char *data, unsigned int size, SmlError **error)
411 {
412 smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, item, data, size, error);
413 CHECK_ERROR_REF
414
415 if (item->size && xmlBufferLength(item->buffer) + size > item->size) {
416 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data. size limit reached");
417 goto error;
418 }
419
420 if (data) {
421 if (!item->buffer) {
422 if (item->size)
423 item->buffer = xmlBufferCreateSize(item->size);
424 else
425 item->buffer = xmlBufferCreateSize(size);
426 }
427
428 if (xmlBufferAdd(item->buffer, (xmlChar *)data, size) != 0) {
429 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data.");
430 goto error;
431 }
432 }
433
434 smlTrace(TRACE_EXIT, "%s", __func__);
435 return TRUE;
436
437 error:
438 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
439 return FALSE;
440
441 }
442
444 SmlBool smlItemCheck(SmlItem *item)
445 {
446 smlAssert(xmlBufferLength(item->buffer) >= 0);
447 smlAssert(item);
448 if (!item->size)
449 return TRUE;
450
451 if ((unsigned int)xmlBufferLength(item->buffer) != item->size)
452 {
453 smlTrace(TRACE_INTERNAL, "%s: failed because size (%d != %d) does not match (%s).",
454 __func__, item->size,
455 xmlBufferLength(item->buffer), VA_STRING((char *)xmlBufferContent(item->buffer)));
456 return FALSE;
457 }
458
459 return TRUE;
460 }
461
462 SmlBool smlItemHasData(SmlItem *item)
463 {
464 smlAssert(item);
465 return item->buffer ? TRUE : FALSE;
466 }
467
470 SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
471 {
472 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error);
473 CHECK_ERROR_REF
474 smlAssert(size);
475
476 if (!smlItemCheck(item)) {
477 smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed");
478 goto error;
479 }
480
481 *size = xmlBufferLength(item->buffer);
482 *data = g_strndup((const char *) xmlBufferContent(item->buffer), *size);
483 xmlBufferFree(item->buffer);
484 item->buffer = NULL;
485
486 smlTrace(TRACE_EXIT, "%s", __func__);
487 return TRUE;
488
489 error:
490 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
491 return FALSE;
492 }
493
495 SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
496 {
497 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error);
498 CHECK_ERROR_REF
499
500 if (!smlItemCheck(item)) {
501 smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed");
502 goto error;
503 }
504
505 *data = (char *)xmlBufferContent(item->buffer);
506 *size = xmlBufferLength(item->buffer);
507
508 smlTrace(TRACE_EXIT, "%s", __func__);
509 return TRUE;
510
511 error:
512 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
513 return FALSE;
514 }
515
516 void smlItemSetSource(SmlItem *item, SmlLocation *source)
517 {
518 smlAssert(item);
519 smlAssert(source);
520
521 item->source = source;
522 smlLocationRef(source);
523 }
524
525 SmlLocation *smlItemGetSource(SmlItem *item)
526 {
527 smlAssert(item);
528
529 return item->source;
530 }
531
532 void smlItemSetTarget(SmlItem *item, SmlLocation *target)
533 {
534 smlAssert(item);
535 smlAssert(target);
536
537 item->target = target;
538 smlLocationRef(target);
539 }
540
541 SmlLocation *smlItemGetTarget(SmlItem *item)
542 {
543 smlAssert(item);
544
545 return item->target;
546 }
547
548 void smlItemSetSourceParent(SmlItem *item, SmlLocation *sourceParent)
549 {
550 smlAssert(item);
551 smlAssert(sourceParent);
552
553 item->sourceParent = sourceParent;
554 smlLocationRef(sourceParent);
555 }
556
557 SmlLocation *smlItemGetSourceParent(SmlItem *item)
558 {
559 smlAssert(item);
560
561 return item->sourceParent;
562 }
563
564 void smlItemSetTargetParent(SmlItem *item, SmlLocation *targetParent)
565 {
566 smlAssert(item);
567 smlAssert(targetParent);
568
569 item->targetParent = targetParent;
570 smlLocationRef(targetParent);
571 }
572
573 SmlLocation *smlItemGetTargetParent(SmlItem *item)
574 {
575 smlAssert(item);
576
577 return item->targetParent;
578 }
579
580 void smlItemSetRaw(SmlItem *item, SmlBool raw)
581 {
582 smlAssert(item);
583
584 item->raw = raw;
585 }
586
587 SmlCred *smlCredNewFromString(const char *type,
588 const char *format,
589 const char *data,
590 SmlError **error)
591 {
592 smlTrace(TRACE_ENTRY, "%s(%s, %s, %s, %p)", __func__, VA_STRING(data), VA_STRING(type), VA_STRING(format), error);
593 CHECK_ERROR_REF
594
595 SmlAuthType smlType = SML_AUTH_TYPE_UNKNOWN;
596 SmlFormatType smlFormat = SML_FORMAT_TYPE_UNKNOWN;
597
598 if (!type || !strcmp(type, SML_AUTH_BASIC)) {
599 smlType = SML_AUTH_TYPE_BASIC;
600 } else if (!strcmp(type, SML_AUTH_MD5)) {
601 smlType = SML_AUTH_TYPE_MD5;
602 } else {
603 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type - %s.", type);
604 goto error;
605 }
606
607 if (!format || !strcmp(format, SML_BASE64)) {
608 smlFormat = SML_FORMAT_TYPE_BASE64;
609 } else {
610 smlErrorSet(error, SML_ERROR_GENERIC, "SyncML credential: Unknown format - %s.", format);
611 goto error;
612 }
613
614 if (!data) {
615 smlErrorSet(error, SML_ERROR_GENERIC, "Data is missing in %s.", __func__);
616 goto error;
617 }
618
619 smlTrace(TRACE_EXIT, "%s", __func__);
620 return smlCredNew(smlType, smlFormat, data, NULL, error);
621 error:
622 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
623 return NULL;
624 }
625
626 SmlCred *smlCredNewAuth(SmlAuthType type,
627 const char *username,
628 const char *password,
629 SmlError **error)
630 {
631 smlTrace(TRACE_ENTRY, "%s(%d, %s, %p)", __func__, type, VA_STRING(username), error);
632 CHECK_ERROR_REF
633
634 SmlCred *cred = NULL;
635
636 if (username == NULL || !strlen(username)) {
637 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
638 "If authentication should be used then the username must be set.");
639 goto error;
640 }
641 if (password == NULL || !strlen(password)) {
642 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
643 "If authentication should be used then the password must be set.");
644 goto error;
645 }
646
647 cred = smlTryMalloc0(sizeof(SmlCred), error);
648 if (!cred)
649 goto error;
650
651 cred->refCount = 1;
652 cred->format = SML_FORMAT_TYPE_BASE64;
653 cred->type = type;
654 cred->username = g_strdup(username);
655 cred->password = g_strdup(password);
656
657 smlTrace(TRACE_EXIT, "%s", __func__);
658 return cred;
659 error:
660 if (cred)
661 smlSafeFree((gpointer *)&cred);
662 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
663 return NULL;
664 }
665
666 SmlCred *smlCredNew(SmlAuthType type,
667 SmlFormatType format,
668 const char *data,
669 const char *username,
670 SmlError **error)
671 {
672 smlTrace(TRACE_ENTRY, "%s(%s, %d, %d, %p)", __func__, VA_STRING(data), type, format, error);
673 CHECK_ERROR_REF
674
675 SmlCred *cred = smlTryMalloc0(sizeof(SmlCred), error);
676 if (!cred)
677 goto error;
678
679 cred->type = type;
680 cred->format = format;
681 cred->data = g_strdup(data);
682 if (username)
683 cred->username = g_strdup(username);
684 else
685 cred->username = NULL;
686 cred->refCount = 1;
687
688 smlTrace(TRACE_EXIT, "%s: %p", __func__, cred);
689 return cred;
690 error:
691 if (cred->data)
692 smlSafeCFree(&(cred->data));
693 if (cred->username)
694 smlSafeCFree(&(cred->username));
695 if (cred)
696 smlSafeFree((gpointer *)&cred);
697 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
698 return NULL;
699 }
700
701 void smlCredRef(SmlCred *cred)
702 {
703 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred);
704 smlAssert(cred);
705
706 g_atomic_int_inc(&(cred->refCount));
707
708 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cred->refCount);
709 }
710
711 void smlCredUnref(SmlCred *cred)
712 {
713 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred);
714 smlAssert(cred);
715
716 if (g_atomic_int_dec_and_test(&(cred->refCount))) {
717 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
718
719 if (cred->data)
720 smlSafeCFree(&(cred->data));
721 if (cred->username)
722 smlSafeCFree(&(cred->username));
723 if (cred->password)
724 smlSafeCFree(&(cred->password));
725
726 smlSafeFree((gpointer *)&cred);
727 }
728
729 smlTrace(TRACE_EXIT, "%s", __func__);
730 }
731
732 /* FIXME: DEPRECATED */
733 void smlCredFree(SmlCred *cred)
734 {
735 smlCredUnref(cred);
736 }
737
738 SmlChal *smlChalNew(SmlAuthType type, SmlError **error)
739 {
740 smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, type, error);
741 CHECK_ERROR_REF
742 SmlChal *chal = NULL;
743
744 /* allocate memory */
745 smlAssert(type != SML_AUTH_TYPE_UNKNOWN);
746 chal = smlTryMalloc0(sizeof(SmlChal), error);
747 if (!chal)
748 goto error;
749 chal->refCount = 1;
750 chal->type = type;
751 chal->format = SML_FORMAT_TYPE_BASE64;
752
753 if (type == SML_AUTH_TYPE_MD5)
754 {
755 /* A nonce must be generated for this type.
756 * minimum strength: 2^128
757 * strength per byte: 2^6 - 2 > 2^5
758 * needed bytes: 128 / 5 < 130 / 5 = 26
759 */
760 chal->nonce_plain = smlRandStr(26, TRUE);
761 chal->nonce_length = 26;
762 chal->nonce_b64 = g_base64_encode(
763 (const unsigned char *) chal->nonce_plain,
764 chal->nonce_length);
765 if (!chal->nonce_b64) {
766 smlErrorSet(error, SML_ERROR_GENERIC,
767 "The nonce of the challenge cannot be base64 encoded.");
768 goto error;
769 }
770 }
771
772 smlTrace(TRACE_EXIT, "%s", __func__);
773 return chal;
774 error:
775 if (chal->nonce_plain)
776 smlSafeCFree(&(chal->nonce_plain));
777 if (chal->nonce_b64)
778 smlSafeCFree(&(chal->nonce_b64));
779 if (chal)
780 smlSafeFree((gpointer *)&chal);
781 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
782 return NULL;
783 }
784
785 SmlChal *smlChalNewFromBinary(
786 SmlAuthType type,
787 const char *nonce,
788 size_t length,
789 SmlError **error)
790 {
791 smlTrace(TRACE_ENTRY, "%s", __func__);
792 CHECK_ERROR_REF
793 SmlChal *chal = NULL;
794
795 /* only syncml:auth-md5 needs a nonce */
796 smlAssert(type == SML_AUTH_TYPE_MD5);
797
798 /* allocate memory */
799 chal = smlTryMalloc0(sizeof(SmlChal), error);
800 if (!chal)
801 goto error;
802 chal->refCount = 1;
803
804 /* copy nonce */
805 chal->type = SML_AUTH_TYPE_MD5;
806 chal->format = SML_FORMAT_TYPE_BASE64;
807 chal->nonce_plain = g_strndup(nonce, length);
808 chal->nonce_length = length;
809
810 /* create base64 nonce */
811 chal->nonce_b64 = g_base64_encode((const unsigned char *) nonce, length);
812 if (!chal->nonce_b64) {
813 smlErrorSet(error, SML_ERROR_GENERIC,
814 "The base64 encoding of the nonce failed.");
815 goto error;
816 }
817
818 smlTrace(TRACE_EXIT, "%s", __func__);
819 return chal;
820 error:
821 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
822 return NULL;
823 }
824
825 SmlChal *smlChalNewFromBase64(
826 SmlAuthType type,
827 const char *nonce,
828 SmlError **error)
829 {
830 smlTrace(TRACE_ENTRY, "%s", __func__);
831 CHECK_ERROR_REF
832 SmlChal *chal = NULL;
833
834 /* only syncml:auth-md5 needs a nonce */
835 smlAssert(type == SML_AUTH_TYPE_MD5);
836
837 /* allocate memory */
838 chal = smlTryMalloc0(sizeof(SmlChal), error);
839 if (!chal)
840 goto error;
841 chal->refCount = 1;
842
843 /* copy nonce */
844 chal->type = SML_AUTH_TYPE_MD5;
845 chal->format = SML_FORMAT_TYPE_BASE64;
846 chal->nonce_b64 = g_strdup(nonce);
847
848 /* create binary nonce */
849 size_t length = 0;
850 chal->nonce_plain = (char *) g_base64_decode(nonce, &length);
851 if (!chal->nonce_plain || length < 1) {
852 smlErrorSet(error, SML_ERROR_GENERIC,
853 "The base64 encoded nonce cannot be decoded.");
854 goto error;
855 }
856 chal->nonce_length = length;
857
858 smlTrace(TRACE_EXIT, "%s", __func__);
859 return chal;
860 error:
861 smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
862 return NULL;
863 }
864
865 void smlChalRef(SmlChal *chal)
866 {
867 smlTrace(TRACE_ENTRY, "%s", __func__);
868 smlAssert(chal);
869
870 g_atomic_int_inc(&(chal->refCount));
871
872 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, chal->refCount);
873 }
874
875 void smlChalUnref(SmlChal *chal)
876 {
877 smlTrace(TRACE_ENTRY, "%s", __func__);
878 smlAssert(chal);
879
880 if (g_atomic_int_dec_and_test(&(chal->refCount))) {
881 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
882
883 if (chal->nonce_plain)
884 smlSafeCFree(&(chal->nonce_plain));
885
886 if (chal->nonce_b64)
887 smlSafeCFree(&(chal->nonce_b64));
888
889 smlSafeFree((gpointer *)&chal);
890 }
891
892 smlTrace(TRACE_EXIT, "%s", __func__);
893 }
894
895 /* FIXME: DEPRECATED */
896 void smlChalFree(SmlChal *chal)
897 {
898 smlChalUnref(chal);
899 }
900
901 SmlMapItem *smlMapItemNew(const char *uid, const char *newuid, SmlError **error)
902 {
903 smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(uid), VA_STRING(newuid), error);
904 CHECK_ERROR_REF
905 smlAssert(uid);
906 smlAssert(newuid);
907
908 SmlMapItem *item = smlTryMalloc0(sizeof(SmlMapItem), error);
909 if (!item)
910 goto error;
911 item->refCount = 1;
912
913 item->source = smlLocationNew(newuid, NULL, error);
914 if (!item->source)
915 goto error_free_item;
916
917 item->target = smlLocationNew(uid, NULL, error);
918 if (!item->target)
919 goto error_free_source;
920
921 smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
922 return item;
923
924 error_free_source:
925 smlLocationUnref(item->source);
926 error_free_item:
927 smlSafeFree((gpointer *)&item);
928 error:
929 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
930 return NULL;
931 }
932
933 SmlMapItem *smlMapItemRef(SmlMapItem *item)
934 {
935 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
936 smlAssert(item);
937
938 g_atomic_int_inc(&(item->refCount));
939
940 smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount);
941 return item;
942 }
943
944 void smlMapItemUnref(SmlMapItem *item)
945 {
946 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
947 smlAssert(item);
948
949 if (g_atomic_int_dec_and_test(&(item->refCount))) {
950 smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
951
952 if (item->source)
953 {
954 smlLocationUnref(item->source);
955 item->source = NULL;
956 }
957
958 if (item->target)
959 {
960 smlLocationUnref(item->target);
961 item->target = NULL;
962 }
963
964 smlSafeFree((gpointer *)&item);
965 }
966
967 smlTrace(TRACE_EXIT, "%s", __func__);
968 }
969