libsyncml  0.5.4
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 
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlErrorType type
SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:470
char * smlRandStr(int maxlength, SmlBool exact)
Creates a random string.
Definition: sml_support.c:302
SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:495
SmlBool smlItemCheck(SmlItem *item)
Definition: sml_elements.c:444
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
Definition: sml_support.c:335
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
Represent an error.