libsyncml  0.5.4
sml_notification.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_notification_internals.h"
26 #include "sml_transport_internals.h"
27 #include "sml_command_internals.h"
28 #include "sml_manager_internals.h"
29 #include "sml_error_internals.h"
30 #include "objects/sml_auth_internals.h"
31 #include "sml_elements_internals.h"
32 
33 SmlNotification *smlNotificationNew(SmlNotificationVersion version, SmlNotificationUIMode mode, SmlNotificationInitiator init, unsigned int sessionID, const char *identifier, const char *target, SmlMimeType type, SmlError **error)
34 {
35  smlTrace(TRACE_ENTRY, "%s(%i, %i, %i, %i, %s, %s, %i, %p)", __func__, version, mode, init, sessionID, VA_STRING(identifier), VA_STRING(target), type, error);
36  CHECK_ERROR_REF
37 
38  SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error);
39  if (!san)
40  goto error;
41 
42  san->version = version;
43  san->mode = mode;
44  san->init = init;
45  san->sessionID = sessionID;
46  san->identifier = g_strdup(identifier);
47  san->type = type;
48  san->cred = NULL;
49  san->sessionType = SML_SESSION_TYPE_SERVER;
50  san->manager = NULL;
51 
52  san->target = smlLocationNew(target, NULL, error);
53  if (!san->target)
54  goto error_free_san;
55 
56  smlTrace(TRACE_EXIT, "%s: %p", __func__, san);
57  return san;
58 
59 error_free_san:
60 
61 error:
62  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
63  return NULL;
64 }
65 
66 void smlNotificationSetCred(SmlNotification *san, SmlCred *cred)
67 {
68  smlTrace(TRACE_ENTRY, "%s", __func__);
69  smlAssert(san);
70  smlAssert(cred);
71  if (san->cred)
72  smlCredUnref(san->cred);
73  san->cred = cred;
74  // we only set credentials if this is a client
75  // if we set no credentials then we always assume a server
76  // FIXME: this is a hack because the original implementation
77  // FIXME: only support server
78  // Only one question which client sends a notification!?
79  san->sessionType = SML_SESSION_TYPE_CLIENT;
80  smlCredRef(cred);
81  smlTrace(TRACE_EXIT, "%s", __func__);
82 }
83 
84 void smlNotificationSetManager(SmlNotification *san, SmlManager *manager)
85 {
86  smlTrace(TRACE_ENTRY, "%s", __func__);
87  smlAssert(san);
88  smlAssert(manager);
89  san->manager = manager;
90  smlTrace(TRACE_EXIT, "%s", __func__);
91 }
92 
93 void smlNotificationFree(SmlNotification *san)
94 {
95  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, san);
96  smlAssert(san);
97 
98  while (san->alerts) {
99  SmlSanAlert *alert = san->alerts->data;
100  san->alerts = g_list_remove(san->alerts, alert);
101  smlNotificationFreeAlert(alert);
102  }
103 
104  if (san->target) {
105  smlLocationUnref(san->target);
106  san->target = NULL;
107  }
108 
109  if (san->cred) {
110  smlCredUnref(san->cred);
111  san->cred = NULL;
112  }
113 
114  if (san->identifier)
115  smlSafeCFree(&(san->identifier));
116  smlSafeFree((gpointer *)&san);
117 
118  smlTrace(TRACE_EXIT, "%s", __func__);
119 }
120 
121 SmlBool smlNotificationNewAlert(SmlNotification *san, SmlAlertType type, const char *contenttype, const char *serverURI, SmlError **error)
122 {
123  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, error);
124  CHECK_ERROR_REF
125  smlAssert(type >= 206 && type <= 210);
126 
127  SmlSanAlert *alert = smlTryMalloc0(sizeof(SmlSanAlert), error);
128  if (!alert)
129  goto error;
130 
131  alert->type = type;
132  alert->contenttype = g_strdup(contenttype);
133  alert->serverURI = g_strdup(serverURI);
134 
135  san->alerts = g_list_append(san->alerts, alert);
136 
137  smlTrace(TRACE_EXIT, "%s: %p", __func__, alert);
138  return TRUE;
139 
140 error:
141  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
142  return FALSE;
143 }
144 
145 void smlNotificationFreeAlert(SmlSanAlert *alert)
146 {
147  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, alert);
148  smlAssert(alert);
149 
150  smlSafeCFree(&(alert->contenttype));
151  smlSafeCFree(&(alert->serverURI));
152  smlSafeFree((gpointer *)&alert);
153 
154  smlTrace(TRACE_EXIT, "%s", __func__);
155 }
156 
157 SmlNotification *smlNotificationParse(const char *data, unsigned int size, SmlError **error)
158 {
159  smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error);
160  CHECK_ERROR_REF
161  smlAssert(data);
162  smlAssert(size);
163 
164  if (size < 25) {
165  smlErrorSet(error, SML_ERROR_GENERIC, "Size too small");
166  goto error;
167  }
168 
169  unsigned int idLength = (uint8_t)data[23];
170  if (size < (25 + idLength)) {
171  smlErrorSet(error, SML_ERROR_GENERIC, "Size too small2");
172  goto error;
173  }
174 
175  SmlNotification *san = smlTryMalloc0(sizeof(SmlNotification), error);
176  if (!san)
177  goto error;
178  san->type = SML_MIMETYPE_SAN;
179 
180  /* Version */
181  unsigned int version = ((uint8_t)data[16]) << 2;
182  version = version | ((uint8_t)data[17]) >> 6;
183  switch (version) {
184  case 12:
185  san->version = SML_SAN_VERSION_12;
186  break;
187  default:
188  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version");
189  goto error_free_san;
190  }
191 
192  /* ui mode */
193  san->mode = (((uint8_t)data[17]) & 0x30) >> 4;
194 
195  /* initiator */
196  san->init = (((uint8_t)data[17]) & 0x08) >> 3;
197 
198  /* session id */
199  san->sessionID = ((uint8_t)data[21]) << 8;
200  san->sessionID = san->sessionID | (uint8_t)data[22];
201 
202  /* server identifier */
203  if (idLength) {
204  /* the trailing NULL byte is usually not present in the SAN */
205  san->identifier = smlTryMalloc0(idLength + 1, error);
206  if (!san->identifier)
207  goto error_free_san;
208 
209  memcpy(san->identifier, data + 24, idLength);
210  }
211 
212  unsigned int numSync = ((uint8_t)data[24 + idLength]) >> 4;
213  data += 25 + idLength;
214  unsigned int alertLength = 25 + idLength;
215 
216  unsigned int i = 0;
217  for (i = 0; i < numSync; i++) {
218  if (size < alertLength + 5) {
219  smlErrorSet(error, SML_ERROR_GENERIC, "Size too small3");
220  goto error_free_san;
221  }
222 
223  idLength = (uint8_t)data[4];
224  if (size < (alertLength + 5 + idLength)) {
225  smlErrorSet(error, SML_ERROR_GENERIC, "Size too small4");
226  goto error_free_san;
227  }
228  alertLength = alertLength + 5 + idLength;
229 
230  /* Alert type + future */
231  SmlAlertType alert_type = (((uint8_t)data[0]) >> 4) + 200;
232  if (alert_type < 206 || alert_type > 210) {
233  smlErrorSet(error, SML_ERROR_GENERIC, "Wrong alert type");
234  goto error_free_san;
235  }
236 
237  unsigned int contenttype = ((uint8_t)data[1]) << 16;
238  contenttype = contenttype | ((uint8_t)data[2]) << 8;
239  contenttype = contenttype | ((uint8_t)data[3]);
240 
241  /* The contenttype */
242  const char *alert_ct;
243  switch (contenttype) {
244  case 0x00:
245  /* This is exactly like defined in "DS Protocol" section
246  * 12.4.13 "Content Type" of the official OMA document
247  * OMA-TS-DS_Protocol-V1_2_1-20070810-A.pdf.
248  */
249  alert_ct = NULL;
250  break;
251  case 0x07:
252  alert_ct = SML_ELEMENT_TEXT_VCARD;
253  break;
254  case 0x06:
255  alert_ct = SML_ELEMENT_TEXT_VCAL;
256  break;
257  case 0x03:
258  alert_ct = SML_ELEMENT_TEXT_PLAIN;
259  break;
260  case 0x0305:
261  alert_ct = SML_ELEMENT_TEXT_ICAL;
262  break;
263  case 0x0306:
264  alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_EMAIL;
265  break;
266  case 0x0307:
267  alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FILE;
268  break;
269  case 0x0308:
270  alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FOLDER;
271  break;
272  case 0x0309:
273  alert_ct = SML_ELEMENT_TEXT_VCARD_30;
274  break;
275  default:
276  /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */
277  smlErrorSet(error, SML_ERROR_GENERIC, "The OMNA WSP Content Type Number 0x%xd is not supported.", contenttype);
278  goto error_free_san;
279  }
280 
281  /* The server uri */
282  char *alert_uri;
283  if (idLength) {
284  /* the trailing NULL byte is usually not present in the SAN */
285  alert_uri = smlTryMalloc0(idLength + 1, error);
286  if (!alert_uri)
287  goto error_free_san;
288 
289  memcpy(alert_uri, data + 5, idLength);
290  }
291  data += 5 + idLength;
292 
293  /* Create new alert */
294  if (!smlNotificationNewAlert(san, alert_type, alert_ct, alert_uri, error))
295  goto error_free_san;
296 
297  /* Cleanup */
298  if (idLength)
299  smlSafeCFree(&alert_uri);
300  }
301 
302  if (size > alertLength) {
303  smlErrorSet(error, SML_ERROR_GENERIC, "Extra chunk at the end of the buffer");
304  goto error_free_san;
305  }
306 
307  smlTrace(TRACE_EXIT, "%s: %p", __func__, san);
308  return san;
309 
310 error_free_san:
311  while (san->alerts) {
312  smlNotificationFreeAlert(san->alerts->data);
313  san->alerts = g_list_delete_link(san->alerts, san->alerts);
314  }
315  if (san->identifier)
316  smlSafeCFree(&(san->identifier));
317  smlSafeFree((gpointer *)&san);
318 error:
319  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
320  return NULL;
321 }
322 
323 SmlBool smlNotificationAssemble11(SmlNotification *san, char **data, unsigned int *size, SmlProtocolVersion version, SmlError **error)
324 {
325  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %i, %p)", __func__, san, data, size, version, error);
326  CHECK_ERROR_REF
327  smlAssert(san);
328  smlAssert(data);
329  smlAssert(size);
330 
331  /* If a notification is sent via a normal SyncML message
332  * then the used session must be managed to guarantee the
333  * consistency of the session.
334  */
335  smlAssert(san->manager);
336 
337  SmlAssembler *assm = NULL;
338  SmlLocation *source = NULL;
339  SmlSession *session = NULL;
340  SmlSanAlert *alert = NULL;
341  SmlCommand *cmd = NULL;
342 
343  source = smlLocationNew(san->identifier, NULL, error);
344  if (!source)
345  goto error;
346 
347  char *sessionString = smlManagerGetNewSessionID(san->manager);
348  session = smlSessionNew(san->sessionType, san->type, version, SML_PROTOCOL_SYNCML, san->target, source, sessionString, 0, error);
349  if (!session) {
350  smlSafeCFree(&sessionString);
351  smlLocationUnref(source);
352  goto error;
353  }
354  smlSafeCFree(&sessionString);
355  smlManagerSessionAdd(san->manager, session, NULL, error);
356 
357  assm = smlAssemblerNew(san->type, 0, error);
358  if (!assm)
359  goto error;
360 
361  if (!smlAssemblerStart(assm, session, error))
362  goto error;
363 
364  if (!smlAssemblerAddHeader(assm, session, error))
365  goto error;
366 
367  GList *a = NULL;
368  int i = 1;
369  for (a = san->alerts; a; a = a->next) {
370  alert = a->data;
371 
372 
373  SmlLocation *loc = smlLocationNew(alert->serverURI, NULL, error);
374  if (!loc)
375  goto error;
376 
377  cmd = smlCommandNewAlert(SML_ALERT_TWO_WAY_BY_SERVER, NULL, loc, NULL, NULL, alert->contenttype, error);
378  if (!cmd) {
379  smlLocationUnref(loc);
380  goto error;
381  }
382 
383  cmd->cmdID = i;
384  i++;
385 
386  if (!smlAssemblerStartCommand(assm, NULL, cmd, error) == SML_ASSEMBLER_RESULT_OK)
387  goto error;
388 
389  if (!smlAssemblerEndCommand(assm, NULL, error))
390  goto error;
391 
392  smlLocationUnref(loc);
393 
394  smlCommandUnref(cmd);
395  }
396 
397  if (!smlAssemblerRun(assm, data, size, NULL, TRUE, error))
398  goto error;
399 
400  smlAssemblerFlush(assm);
401 
402  smlSessionUnref(session);
403 
404  smlLocationUnref(source);
405 
406  smlAssemblerFree(assm);
407 
408  char *hex = smlPrintHex(*data, *size);
409  smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex);
410  smlSafeCFree(&hex);
411 
412  smlTrace(TRACE_EXIT, "%s", __func__);
413  return TRUE;
414 
415 error:
416  if (cmd)
417  smlCommandUnref(cmd);
418  if (session)
419  smlSessionUnref(session);
420  if (assm)
421  smlAssemblerFree(assm);
422  *data = NULL;
423  *size = 0;
424  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
425  return FALSE;
426 }
427 
428 static SmlBool _smlNotificationAssemble12(SmlNotification *san, char **data, unsigned int *size, SmlError **error)
429 {
430  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, san, data, size, error);
431  CHECK_ERROR_REF
432  smlAssert(san);
433  smlAssert(data);
434  smlAssert(*data == NULL);
435  smlAssert(size);
436  unsigned int numsync = 0;
437  SmlSanAlert *alert = NULL;
438 
439  /* Calculate the length of the san data */
440  unsigned int length = 16 /* Digest */ + 8 /* Hdr */ + strlen(san->identifier) /* Identifier */ + 1 /* num-sync + future */;
441  GList *a = NULL;
442  for (a = san->alerts; a; a = a->next) {
443  alert = a->data;
444  length += 5 + strlen(alert->serverURI);
445  numsync++;
446  }
447 
448  /* Malloc the necessary space */
449  char *buffer = smlTryMalloc0(length, error);
450  if (!buffer)
451  goto error;
452  *data = buffer;
453  *size = length;
454 
455  /* the digest must be created at the end */
456 
457  /* Create Header */
458  /* Version - 10 bit */
459  buffer[16] = 0x03;
460 
461  /* ui mode */
462  buffer[17] = buffer[17] | (san->mode << 4);
463 
464  /* initiator */
465  buffer[17] = buffer[17] | (san->init << 3);
466 
467  /* future use is 0 for now - 27 bit */
468 
469  /* session id */
470  buffer[21] = san->sessionID >> 8;
471  buffer[22] = san->sessionID;
472 
473  /* server identifier without trailing NULL byte */
474  buffer[23] = strlen(san->identifier);
475  strncpy(buffer + 24, san->identifier, strlen(san->identifier));
476 
477  buffer += 24 + strlen(san->identifier);
478 
479  /* Num syncs + future */
480  buffer[0] = numsync << 4;
481  buffer++;
482 
483  for (a = san->alerts; a; a = a->next) {
484  alert = a->data;
485  /* Alert type + future */
486  buffer[0] = (alert->type - 200) << 4;
487 
488  /* The contenttype */
489  if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD)) {
490  buffer[3] = 0x07;
491  } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCAL)) {
492  buffer[3] = 0x06;
493  } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_PLAIN)) {
494  buffer[3] = 0x03;
495  } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_ICAL)) {
496  buffer[2] = 0x03;
497  buffer[3] = 0x05;
498  } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_EMAIL)) {
499  buffer[2] = 0x03;
500  buffer[3] = 0x06;
501  } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FILE)) {
502  buffer[2] = 0x03;
503  buffer[3] = 0x07;
504  } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FOLDER)) {
505  buffer[2] = 0x03;
506  buffer[3] = 0x08;
507  } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD_30)) {
508  buffer[2] = 0x03;
509  buffer[3] = 0x09;
510  } else {
511  /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */
512  smlTrace(TRACE_INTERNAL,
513  "%s: The OMNA WSP Content Type Number is unknown for %s.",
514  __func__, alert->contenttype);
515  /* All bytes are already set to zero. */
516  }
517 
518  /* The server uri without a trailing NULL byte */
519  buffer[4] = strlen(alert->serverURI);
520  strncpy(buffer + 5, alert->serverURI, strlen(alert->serverURI));
521  buffer += 5 + strlen(alert->serverURI);
522  }
523 
524  /* Create the digest */
525 
526  /* DO NOT USE buffer because this pointer was manipulated
527  * ALWAYS USE *data.
528  */
529 
530  /* base64 encoded MD5 digest of the notification */
531  unsigned char digest[16];
532  smlMD5GetDigest (*data+16, length - 16 /* digest */, digest);
533  char *b64_san = g_base64_encode(digest, 16);
534  smlTrace(TRACE_INTERNAL, "%s: b64(md5(san)) ::= %s", __func__, b64_san);
535 
536  /* base64 encoded MD5 digest of username:password */
537  const char *username = "";
538  const char *password = "";
539  if (san->cred) {
540  username = san->cred->username;
541  password = san->cred->password;
542  }
543  char *auth = g_strdup_printf("%s:%s", username, password);
544  smlMD5GetDigest (auth, strlen(auth), digest);
545  smlSafeCFree(&auth);
546  char *b64_auth = g_base64_encode(digest, 16);
547  smlTrace(TRACE_INTERNAL, "%s: b64(md5(username:password)) ::= %s", __func__, b64_auth);
548 
549  /* MD5 digest of auth:nonce:notification (empty nonce) */
550  char *complete = g_strdup_printf("%s::%s", b64_auth, b64_san);
551  smlSafeCFree(&b64_auth);
552  smlSafeCFree(&b64_san);
553  smlMD5GetDigest (complete, strlen(complete), digest);
554  smlSafeCFree(&complete);
555  smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) complete", __func__);
556 
557  /* copy digest to buffer */
558  memcpy(*data, digest, 16);
559  smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) copied to san", __func__);
560 
561  /* debug */
562 
563  char *hex = smlPrintHex(*data, *size);
564  smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex);
565  smlSafeCFree(&hex);
566 
567  smlTrace(TRACE_EXIT, "%s", __func__);
568  return TRUE;
569 
570 error:
571  if (*data)
572  smlSafeCFree(data);
573  *size = 0;
574  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
575  return FALSE;
576 }
577 
578 SmlBool smlNotificationAssemble(SmlNotification *san, char **data, unsigned int *size, SmlError **error)
579 {
580  CHECK_ERROR_REF
581  switch (san->version) {
582  case SML_SAN_VERSION_12:
583  return _smlNotificationAssemble12(san, data, size, error);
584  case SML_SAN_VERSION_10:
585  return smlNotificationAssemble11(san, data, size, SML_VERSION_10, error);
586  case SML_SAN_VERSION_11:
587  return smlNotificationAssemble11(san, data, size, SML_VERSION_11, error);
588  case SML_SAN_VERSION_UNKNOWN:
589  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown SAN version.");
590  break;
591  }
592 
593  return FALSE;
594 }
595 
596 SmlBool smlNotificationSend(SmlNotification *san, SmlTransport *tsp, SmlError **error)
597 {
598  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, san, tsp, error);
599  CHECK_ERROR_REF
600  smlAssert(san);
601  smlAssert(tsp);
602 
603  char *data = NULL;
604  unsigned int size = 0;
605  if (!smlNotificationAssemble(san, &data, &size, error))
606  goto error;
607 
608  SmlTransportData *tspdata = NULL;
609  if (san->version == SML_SAN_VERSION_12)
610  tspdata = smlTransportDataNew(data, size, SML_MIMETYPE_SAN, TRUE, error);
611  else
612  tspdata = smlTransportDataNew(data, size, san->type, TRUE, error);
613 
614  if (!tspdata)
615  goto error_free_data;
616  /* Do not free data because smlTransportDateNew does copy by reference. */
617  data = NULL;
618 
619  /* For SyncML 1.2 and OBEX Transport we use SML_MIMETYPE_SAN for PUT and use the regular
620  SyncML message type (xml/wbxml) for GET. To avoid that we response after the PUT with
621  a GET SML_MIMETYPE_SAN request. */
622  if (san->version == SML_SAN_VERSION_12)
623  tspdata->type_get = san->type;
624 
625  if (!smlTransportSend(tsp, NULL, tspdata, error))
626  goto error_free_tspdata;
627 
628  smlTransportDataDeref(tspdata);
629 
630  smlTrace(TRACE_EXIT, "%s", __func__);
631  return TRUE;
632 
633 error_free_tspdata:
634  smlTransportDataDeref(tspdata);
635 error_free_data:
636  smlSafeCFree(&data);
637 error:
638  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
639  return FALSE;
640 }
641 
642 SmlNotificationVersion smlNotificationGetVersion(SmlNotification *san)
643 {
644  smlAssert(san);
645  return san->version;
646 }
647 
648 SmlNotificationUIMode smlNotificationGetMode(SmlNotification *san)
649 {
650  smlAssert(san);
651  return san->mode;
652 }
653 
654 SmlNotificationInitiator smlNotificationGetInitiator(SmlNotification *san)
655 {
656  smlAssert(san);
657  return san->init;
658 }
659 
660 unsigned int smlNotificationGetSessionID(SmlNotification *san)
661 {
662  smlAssert(san);
663  return san->sessionID;
664 }
665 
666 const char *smlNotificationGetIdentifier(SmlNotification *san)
667 {
668  smlAssert(san);
669  return san->identifier;
670 }
671 
672 unsigned int smlNotificationNumAlerts(SmlNotification *san)
673 {
674  smlAssert(san);
675  return g_list_length(san->alerts);
676 }
677 
678 SmlSanAlert *smlNotificationNthAlert(SmlNotification *san, unsigned int nth)
679 {
680  smlAssert(san);
681  return g_list_nth_data(san->alerts, nth);
682 }
683 
684 SmlAlertType smlSanAlertGetType(SmlSanAlert *alert)
685 {
686  smlAssert(alert);
687  return alert->type;
688 }
689 
690 const char *smlSanAlertGetContentType(SmlSanAlert *alert)
691 {
692  smlAssert(alert);
693  return alert->contenttype;
694 }
695 const char *smlSanAlertGetServerURI(SmlSanAlert *alert)
696 {
697  smlAssert(alert);
698  return alert->serverURI;
699 }
SmlBool smlAssemblerAddHeader(SmlAssembler *assm, SmlSession *session, SmlError **error)
Assembles the header.
Definition: sml_parse.c:762
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
char * smlPrintHex(const char *data, int len)
Used for printing binary data in just hex.
Definition: sml_support.c:271
SmlAssemblerResult smlAssemblerStartCommand(SmlAssembler *assm, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
Starts a parent command.
Definition: sml_parse.c:659
SmlBool smlAssemblerRun(SmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlError **error)
Assembles the complete message and returns the result.
Definition: sml_parse.c:456
unsigned int smlAssemblerFlush(SmlAssembler *assm)
Flushes the already parsed commands.
Definition: sml_parse.c:514
SmlBool smlAssemblerStart(SmlAssembler *assm, SmlSession *session, SmlError **error)
Starts a new message.
Definition: sml_parse.c:428
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
void smlAssemblerFree(SmlAssembler *assm)
Frees a assembler.
Definition: sml_parse.c:402
SmlBool smlAssemblerEndCommand(SmlAssembler *assm, SmlCommand *parent, SmlError **error)
Ends a parent command.
Definition: sml_parse.c:722
SmlAssembler * smlAssemblerNew(SmlMimeType type, unsigned int limit, SmlError **error)
Creates a new assembler.
Definition: sml_parse.c:352
SmlSession * smlSessionNew(SmlSessionType sessionType, SmlMimeType mimetype, SmlProtocolVersion version, SmlProtocolType protocol, SmlLocation *target, SmlLocation *source, const char *sessionID, unsigned int messageID, SmlError **error)
Creates a new session.
Definition: sml_session.c:1832
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.