libsyncml  0.5.4
sml_parse.c
1 /*
2  * libsyncml - A syncml protocol implementation
3  * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4  * Copyright (C) 2008 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_error_internals.h"
26 #include "sml_parse_internals.h"
27 #include "sml_command_internals.h"
28 #include "sml_elements_internals.h"
29 #include "sml_notification_internals.h"
30 
31 #include "parser/sml_xml_assm.h"
32 #include "parser/sml_xml_parse.h"
33 #include "parser/sml_wbxml.h"
34 
42 
50 SmlParser *smlParserNew(SmlMimeType type, unsigned int limit, SmlError **error)
51 {
52  smlTrace(TRACE_ENTRY, "%s(%i, %i, %p)", __func__, type, limit, error);
53  CHECK_ERROR_REF
54 
55  SmlParser *parser = smlTryMalloc0(sizeof(SmlParser), error);
56  if (!parser)
57  goto error;
58 
59  parser->type = type;
60  parser->limit = limit;
61 
62  switch (type) {
63  case SML_MIMETYPE_XML:
64  if (!(parser->parser_userdata = smlXmlParserNew(&(parser->functions), error)))
65  goto error_free_parser;
66  break;
67  case SML_MIMETYPE_SAN:
68  /* SANs will be converted to normal SyncML 1.1 notifications */
69  if (!(parser->parser_userdata = smlXmlParserNew(&(parser->functions), error)))
70  goto error_free_parser;
71  break;
72  case SML_MIMETYPE_WBXML:
73 #ifdef ENABLE_WBXML
74  if (!(parser->parser_userdata = smlWbxmlParserNew(&(parser->functions), error)))
75  goto error_free_parser;
76  break;
77 #else
78  smlErrorSet(error, SML_ERROR_GENERIC, "Wbxml not enabled in this build");
79  goto error_free_parser;
80 #endif
81  default:
82  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown parser type");
83  goto error_free_parser;
84  }
85 
86  smlTrace(TRACE_EXIT, "%s: %p", __func__, parser);
87  return parser;
88 
89 error_free_parser:
90  smlSafeFree((gpointer *)&parser);
91 error:
92  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
93  return NULL;
94 }
95 
96 void smlParserSetManager(SmlParser *parser, SmlManager *manager)
97 {
98  smlAssert(parser);
99  smlAssert(manager);
100  parser->manager = manager;
101 }
102 
109 {
110  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, parser);
111  smlAssert(parser);
112 
113  if (parser->functions.free)
114  parser->functions.free(parser->parser_userdata);
115 
116  smlSafeFree((gpointer *)&parser);
117 
118  smlTrace(TRACE_EXIT, "%s", __func__);
119 }
120 
132 SmlBool smlParserStart(SmlParser *parser, const char *data, unsigned int size, SmlError **error)
133 {
134  smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, parser, data, size, error);
135  CHECK_ERROR_REF
136  smlAssert(parser);
137  smlAssert(data);
138  smlAssert(size);
139  smlAssert(parser->functions.start);
140  smlAssertMsg(parser->type != SML_MIMETYPE_SAN || parser->manager,
141  SML_ASSERT_MSG_SAN_PARSE_REQUIRES_MANAGER);
142 
143  if (parser->limit && size > parser->limit) {
144  smlErrorSet(error, SML_ERROR_GENERIC, "Input data too large");
145  goto error;
146  }
147 
148  if (parser->type == SML_MIMETYPE_SAN) {
149  /* convert OMA DS 1.2 SAN into an SyncML 1.1 notification */
150  smlTrace(TRACE_INTERNAL, "%s - detected an OMA DS 1.2 SAN", __func__);
151 
152  /* parse the SAN */
153  SmlNotification *san = smlNotificationParse(data, size, error);
154  if (!san)
155  goto error;
156 
157  /* fix 1.2 SAN for use with SyncML 1.1 */
158  smlNotificationSetManager(san, parser->manager);
159  san->type = SML_MIMETYPE_XML;
160  san->sessionType = SML_SESSION_TYPE_CLIENT;
161  san->target = smlLocationNew("/", NULL, error);
162  if (!san->target)
163  goto error;
164 
165  /* assemble a SyncML 1.1 notification */
166  char *xmlData = NULL;
167  unsigned int xmlSize = 0;
168  if (!smlNotificationAssemble11(san, &xmlData, &xmlSize, SML_VERSION_12, error))
169  {
170  smlNotificationFree(san);
171  goto error;
172  }
173  smlTrace(TRACE_INTERNAL,
174  "%s - converted OMA DS 1.2 SAN to SyncML 1.1 server alerted sync - %s",
175  __func__, VA_STRING(xmlData));
176 
177  /* cleanup notification */
178  smlNotificationFree(san);
179  san = NULL;
180 
181  /* run the parser on the converted SAN */
182  if (!parser->functions.start(parser->parser_userdata, xmlData, xmlSize, error)) {
183  smlSafeCFree(&xmlData);
184  goto error;
185  }
186  smlSafeCFree(&xmlData);
187  } else {
188  /* run the parser directly on the data */
189  if (!parser->functions.start(parser->parser_userdata, data, size, error))
190  goto error;
191  }
192 
193  smlTrace(TRACE_EXIT, "%s", __func__);
194  return TRUE;
195 
196 error:
197  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
198  return FALSE;
199 }
200 
216 SmlBool smlParserGetHeader(SmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error)
217 {
218  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, header, cred, error);
219  CHECK_ERROR_REF
220  smlAssert(parser);
221  smlAssert(header);
222  smlAssert(cred);
223  smlAssert(parser->functions.get_header);
224 
225  if (!parser->functions.get_header(parser->parser_userdata, header, cred, error))
226  goto error;
227 
228  smlTrace(TRACE_EXIT, "%s", __func__);
229  return TRUE;
230 
231 error:
232  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
233  return FALSE;
234 }
235 
250 SmlParserResult smlParserGetCommand(SmlParser *parser, SmlCommand **cmd, SmlError **error)
251 {
252  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, cmd, error);
253  CHECK_ERROR_REF
254  smlAssert(parser);
255  smlAssert(cmd);
256  smlAssert(parser->functions.get_cmd);
257  SmlParserResult result = SML_PARSER_RESULT_ERROR;
258 
259  if (!(result = parser->functions.get_cmd(parser->parser_userdata, cmd, error)))
260  goto error;
261 
262  smlTrace(TRACE_EXIT, "%s: %i", __func__, result);
263  return result;
264 
265 error:
266  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
267  return SML_PARSER_RESULT_ERROR;
268 }
269 
284 SmlBool smlParserGetStatus(SmlParser *parser, SmlStatus **status, SmlError **error)
285 {
286  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, parser, status, error);
287  CHECK_ERROR_REF
288  smlAssert(parser);
289  smlAssert(status);
290  smlAssert(parser->functions.get_status);
291 
292  if (!parser->functions.get_status(parser->parser_userdata, status, error))
293  goto error;
294 
295  smlTrace(TRACE_EXIT, "%s", __func__);
296  return TRUE;
297 
298 error:
299  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
300  return FALSE;
301 }
302 
314 SmlBool smlParserEnd(SmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error)
315 {
316  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, parser, final, end, error);
317  CHECK_ERROR_REF
318  smlAssert(parser);
319  smlAssert(parser->functions.end);
320 
321  if (!parser->functions.end(parser->parser_userdata, final, end, error))
322  goto error;
323 
324  smlTrace(TRACE_INTERNAL, "%s: Final %i, End %i", __func__, final ? *final : -1, end ? *end : -1);
325 
326  smlTrace(TRACE_EXIT, "%s", __func__);
327  return TRUE;
328 
329 error:
330  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
331  return FALSE;
332 }
333 
343 
352 SmlAssembler *smlAssemblerNew(SmlMimeType type, unsigned int limit, SmlError **error)
353 {
354  smlTrace(TRACE_ENTRY, "%s(%i, %i, %p)", __func__, type, limit, error);
355  CHECK_ERROR_REF
356 
357  SmlAssembler *assm = smlTryMalloc0(sizeof(SmlAssembler), error);
358  if (!assm)
359  goto error;
360 
361  assm->type = type;
362  assm->remoteMaxMsgSize = limit;
363  assm->empty = TRUE;
364  assm->remoteMaxObjSize = 0;
365 
366  switch (type) {
367  case SML_MIMETYPE_XML:
368  if (!(assm->assm_userdata = smlXmlAssemblerNew(assm, &(assm->functions), error)))
369  goto error_free_assm;
370  break;
371  case SML_MIMETYPE_WBXML:
372 #ifdef ENABLE_WBXML
373  if (!(assm->assm_userdata = smlWbxmlAssemblerNew(assm, &(assm->functions), error)))
374  goto error_free_assm;
375  break;
376 #else
377  smlErrorSet(error, SML_ERROR_GENERIC, "Wbxml not enabled in this build");
378  goto error_free_assm;
379 #endif
380  default:
381  smlErrorSet(error, SML_ERROR_GENERIC, "Unknown assembler type");
382  goto error_free_assm;
383  }
384 
385  assm->options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
386 
387  smlTrace(TRACE_EXIT, "%s: %p", __func__, assm);
388  return assm;
389 
390 error_free_assm:
391  smlSafeFree((gpointer *)&assm);
392 error:
393  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
394  return NULL;
395 }
396 
403 {
404  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
405  smlAssert(assm);
406 
407  if (assm->functions.free)
408  assm->functions.free(assm->assm_userdata);
409 
410  g_hash_table_destroy(assm->options);
411 
412  smlSafeFree((gpointer *)&assm);
413 
414  smlTrace(TRACE_EXIT, "%s", __func__);
415 }
416 
428 SmlBool smlAssemblerStart(SmlAssembler *assm, SmlSession *session, SmlError **error)
429 {
430  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error);
431  CHECK_ERROR_REF
432  smlAssert(assm);
433  smlAssert(session);
434  smlAssert(assm->functions.start);
435 
436  if (!assm->functions.start(assm->assm_userdata, session, error))
437  goto error;
438 
439  smlTrace(TRACE_EXIT, "%s", __func__);
440  return TRUE;
441 
442 error:
443  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
444  return FALSE;
445 }
446 
456 SmlBool smlAssemblerRun(SmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlError **error)
457 {
458  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %i, %p)", __func__, assm, data, size, end, final, error);
459  CHECK_ERROR_REF
460  smlAssert(assm);
461  smlAssert(data);
462  smlAssert(size);
463  smlAssert(assm->functions.run);
464 
465  if (!assm->functions.run(assm->assm_userdata, data, size, end, final, smlAssemblerGetRemoteMaxMsgSize(assm), error))
466  goto error;
467 
468  smlTrace(TRACE_EXIT, "%s", __func__);
469  return TRUE;
470 
471 error:
472  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
473  return FALSE;
474 }
475 
485 unsigned int smlAssemblerCheckSize(SmlAssembler *assm, SmlBool headeronly, SmlError **error)
486 {
487  smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, assm, headeronly, error);
488  CHECK_ERROR_REF
489  smlAssert(assm);
490  smlAssert(assm->functions.check_size);
491 
492  unsigned int size = 0;
493  if (!(size = assm->functions.check_size(assm->assm_userdata, headeronly, error)))
494  goto error;
495 
496  smlTrace(TRACE_EXIT, "%s: %i", __func__, size);
497  return size;
498 
499 error:
500  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
501  return 0;
502 }
503 
514 unsigned int smlAssemblerFlush(SmlAssembler *assm)
515 {
516  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
517  smlAssert(assm);
518  smlAssert(assm->functions.flush);
519 
520  unsigned int ret = assm->functions.flush(assm->assm_userdata);
521  assm->empty = TRUE;
522 
523  smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
524  return ret;
525 }
526 
527 void smlAssemblerRestoreCommands(SmlAssembler *assm)
528 {
529  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
530  smlAssert(assm);
531  smlAssert(assm->functions.restore_cmds);
532 
533  assm->functions.restore_cmds(assm->assm_userdata);
534  assm->empty = FALSE;
535 
536  smlTrace(TRACE_EXIT, "%s", __func__);
537 }
538 
545 SmlBool smlAssemblerGetSpace(SmlAssembler *assm, int *space, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
546 {
547  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %p)", __func__, assm, space, parent, cmd, error);
548  CHECK_ERROR_REF
549  smlAssert(assm);
550  smlAssert(space);
551  smlAssert(cmd);
552  smlAssert(assm->functions.start_cmd);
553  smlAssert(assm->functions.rem_cmd);
554  smlAssert(cmd->type == SML_COMMAND_TYPE_ADD || cmd->type == SML_COMMAND_TYPE_REPLACE);
555  unsigned int parentID = 0;
556 
557  int limit = smlAssemblerGetRemoteMaxMsgSize(assm);
558  if (!limit) {
559  *space = -1;
560  smlTrace(TRACE_EXIT, "%s: No limit", __func__);
561  return TRUE;
562  }
563 
564  /* Add the command */
565  if (parent) {
566  if (!parent->cmdID) {
567  smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before");
568  goto error;
569  }
570  parentID = parent->cmdID;
571  }
572 
573  /* disable the items */
574  if (cmd->private.change.items)
575  {
576  guint i;
577  for (i=0; i < g_list_length(cmd->private.change.items); i++)
578  {
579  SmlItem *item = g_list_nth_data(cmd->private.change.items, i);
580  item->disabled = TRUE;
581  }
582  }
583 
584  SmlBool noCmdID = FALSE;
585  if (!cmd->cmdID) {
586  noCmdID = TRUE;
587  /* FIXME: This code does not support more
588  * FIXME: than 99.999 commands in one session. */
589  cmd->cmdID = 10000;
590  }
591 
592  if (!assm->functions.start_cmd(assm->assm_userdata, parentID, cmd, error))
593  goto error_enable_item;
594 
595  /* Now check the size */
596  int size = 0;
597  if (!(size = smlAssemblerCheckSize(assm, FALSE, error)))
598  goto error_remove;
599 
600  if (limit <= size)
601  *space = 0;
602  else
603  *space = limit - size - 10;
604 
605  /* Remove the command again */
606  if (!assm->functions.rem_cmd(assm->assm_userdata, parentID, error))
607  goto error_remove;
608 
609  /* enable the items again */
610  if (cmd->private.change.items)
611  {
612  guint i;
613  for (i=0; i < g_list_length(cmd->private.change.items); i++)
614  {
615  SmlItem *item = g_list_nth_data(cmd->private.change.items, i);
616  item->disabled = FALSE;
617  }
618  }
619 
620  if (noCmdID)
621  cmd->cmdID = 0;
622 
623  smlTrace(TRACE_EXIT, "%s: %i", __func__, *space);
624  return TRUE;
625 
626 error_remove:
627  assm->functions.rem_cmd(assm->assm_userdata, parentID, NULL);
628 error_enable_item:
629  if (cmd->private.change.items)
630  {
631  guint i;
632  for (i=0; i < g_list_length(cmd->private.change.items); i++)
633  {
634  SmlItem *item = g_list_nth_data(cmd->private.change.items, i);
635  item->disabled = FALSE;
636  }
637  }
638  if (noCmdID)
639  cmd->cmdID = 0;
640 error:
641  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
642  return FALSE;
643 }
644 
659 SmlAssemblerResult smlAssemblerStartCommand(SmlAssembler *assm, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
660 {
661  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, assm, parent, cmd, error);
662  CHECK_ERROR_REF
663  smlAssert(assm);
664  smlAssert(cmd);
665  smlAssert(assm->functions.start_cmd);
666  smlAssert(assm->functions.rem_cmd);
667  unsigned int parentID = 0;
668 
669  /* Add the command */
670  if (parent) {
671  if (!parent->cmdID) {
672  smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before");
673  goto error;
674  }
675  parentID = parent->cmdID;
676  }
677 
678  if (!assm->functions.start_cmd(assm->assm_userdata, parentID, cmd, error))
679  goto error;
680 
681  /* Lets see if the new buffer is small enough */
682  int limit = smlAssemblerGetRemoteMaxMsgSize(assm);
683  if (limit) {
684  /* Now check the size */
685  int size = 0;
686  if (!(size = smlAssemblerCheckSize(assm, FALSE, error)))
687  goto error;
688 
689  if (size > limit) {
690  /* The status does not fit. Remove it again */
691  if (!assm->functions.rem_cmd(assm->assm_userdata, parentID, error))
692  goto error;
693 
694  smlTrace(TRACE_EXIT, "%s: Mismatch", __func__);
695  return SML_ASSEMBLER_RESULT_MISMATCH;
696  }
697  smlTrace(TRACE_INTERNAL, "%s: size %i, limit %i", __func__, size, limit);
698  }
699 
700  if (cmd->cmdID)
701  assm->empty = FALSE;
702 
703  smlTrace(TRACE_EXIT, "%s", __func__);
704  return SML_ASSEMBLER_RESULT_OK;
705 
706 error:
707  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
708  return SML_ASSEMBLER_RESULT_ERROR;
709 }
710 
722 SmlBool smlAssemblerEndCommand(SmlAssembler *assm, SmlCommand *parent, SmlError **error)
723 {
724  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, parent, error);
725  CHECK_ERROR_REF
726  smlAssert(assm);
727  smlAssert(assm->functions.end_cmd);
728 
729  unsigned int parentID = 0;
730 
731  /* Add the command */
732  if (parent) {
733  if (!parent->cmdID) {
734  smlErrorSet(error, SML_ERROR_GENERIC, "Parent has to be added before");
735  goto error;
736  }
737  parentID = parent->cmdID;
738  }
739 
740  /* End the command */
741  if (!assm->functions.end_cmd(assm->assm_userdata, parentID, error))
742  goto error;
743 
744  smlTrace(TRACE_EXIT, "%s", __func__);
745  return TRUE;
746 
747 error:
748  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
749  return FALSE;
750 }
751 
762 SmlBool smlAssemblerAddHeader(SmlAssembler *assm, SmlSession *session, SmlError **error)
763 {
764  smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error);
765  CHECK_ERROR_REF
766  smlAssert(assm);
767  smlAssert(session);
768  smlAssert(assm->functions.add_header);
769 
770  /* Add the command */
771  if (!assm->functions.add_header(assm->assm_userdata, session, error))
772  goto error;
773 
774  /* Now check the size */
775  unsigned int size = 0;
776  if (!(size = smlAssemblerCheckSize(assm, TRUE, error)))
777  goto error;
778 
779  /* Lets see if the new buffer is small enough */
780  if (smlAssemblerGetRemoteMaxMsgSize(assm) && size > smlAssemblerGetRemoteMaxMsgSize(assm)) {
781  smlErrorSet(error, SML_ERROR_GENERIC, "Limit to small. Unable to fit a the header");
782  goto error;
783  }
784 
785  smlTrace(TRACE_EXIT, "%s", __func__);
786  return TRUE;
787 
788 error:
789  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
790  return FALSE;
791 }
792 
806 SmlAssemblerResult smlAssemblerReserveStatus(SmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error)
807 {
808  smlTrace(TRACE_ENTRY, "%s(%p, %i, %i, %i, %p)", __func__, assm, cmdRef, msgRef, cmdID, error);
809  CHECK_ERROR_REF
810  smlAssert(assm);
811  smlAssert(assm->functions.reserve_status);
812 
813  /* Reserve the status */
814  if (!assm->functions.reserve_status(assm->assm_userdata, cmdRef, msgRef, cmdID, error))
815  goto error;
816 
817  smlTrace(TRACE_EXIT, "%s", __func__);
818  return TRUE;
819 
820 error:
821  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
822  return FALSE;
823 }
824 
839 SmlAssemblerResult smlAssemblerAddStatusFull(SmlAssembler *assm, SmlStatus *status, SmlBool force, SmlError **error)
840 {
841  smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, assm, status, force, error);
842  CHECK_ERROR_REF
843  smlAssert(assm);
844  smlAssert(status);
845  smlAssert(assm->functions.add_status);
846  smlAssert(assm->functions.rem_status);
847 
848  /* Add the status */
849  if (!assm->functions.add_status(assm->assm_userdata, status, error))
850  goto error;
851 
852  if (!force) {
853  /* Lets see if the new buffer is small enough */
854  int limit = smlAssemblerGetRemoteMaxMsgSize(assm);
855  if (limit) {
856  /* Now check the size */
857  int size = 0;
858  if (!(size = smlAssemblerCheckSize(assm, FALSE, error)))
859  goto error;
860 
861  if (size > limit) {
862  /* The status does not fit. Remove it again */
863  if (!assm->functions.rem_status(assm->assm_userdata, error))
864  goto error;
865 
866  smlTrace(TRACE_EXIT, "%s: Mismatch", __func__);
867  return SML_ASSEMBLER_RESULT_MISMATCH;
868  }
869  }
870  }
871 
872  /*if (status->cmdRef != 0)
873  assm->empty = FALSE;*/
874 
875  smlTrace(TRACE_EXIT, "%s", __func__);
876  return SML_ASSEMBLER_RESULT_OK;
877 
878 error:
879  smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
880  return SML_ASSEMBLER_RESULT_ERROR;
881 }
882 
883 SmlAssemblerResult smlAssemblerAddStatus(SmlAssembler *assm, SmlStatus *status, SmlError **error)
884 {
885  CHECK_ERROR_REF
886  return smlAssemblerAddStatusFull(assm, status, FALSE, error);
887 }
888 
896 void smlAssemblerSetOption(SmlAssembler *assm, const char *optionname, const char *value)
897 {
898  smlTrace(TRACE_ENTRY, "%s(%p, %s, %s)", __func__, assm, VA_STRING(optionname), VA_STRING(value));
899  smlAssert(assm);
900  smlAssert(optionname);
901 
902  g_hash_table_replace(assm->options, g_strdup(optionname), g_strdup(value));
903 
904  smlTrace(TRACE_EXIT, "%s", __func__);
905 }
906 
914 const char *smlAssemblerGetOption(SmlAssembler *assm, const char *optionname)
915 {
916  smlTrace(TRACE_ENTRY, "%s(%p, %s)", __func__, assm, VA_STRING(optionname));
917  smlAssert(assm);
918  smlAssert(optionname);
919 
920  const char *ret = g_hash_table_lookup(assm->options, optionname);
921 
922  smlTrace(TRACE_EXIT, "%s: %s", __func__, VA_STRING(ret));
923  return ret;
924 }
925 
926 /* FIXME: DEPRECATED */
927 unsigned int smlAssemblerGetLimit(SmlAssembler *assm)
928 {
929  return smlAssemblerGetRemoteMaxMsgSize(assm);
930 }
931 
932 unsigned int smlAssemblerGetRemoteMaxMsgSize(SmlAssembler *assm)
933 {
934  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
935  smlAssert(assm);
936 
937  smlTrace(TRACE_EXIT, "%s: %i", __func__, assm->remoteMaxMsgSize);
938  return assm->remoteMaxMsgSize;
939 }
940 
941 /* FIXME: DEPRECATED */
942 void smlAssemblerSetRequestedLimit(SmlAssembler *assm, unsigned int limit)
943 {
944  smlAssemblerSetRemoteMaxMsgSize(assm, limit);
945 }
946 
947 /* FIXME: DEPRECATED */
948 void smlAssemblerSetLimit(SmlAssembler *assm, unsigned int limit)
949 {
950  smlAssemblerSetRemoteMaxMsgSize(assm, limit);
951 }
952 
953 unsigned int smlAssemblerSetRemoteMaxMsgSize(SmlAssembler *assm, unsigned int limit)
954 {
955  smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, assm, limit);
956  smlAssert(assm);
957 
958  if (limit == 0)
959  {
960  /* Reset MaxMsgSize to unused state */
961  assm->remoteMaxMsgSize = limit;
962  } else {
963  if (limit < assm->remoteMaxMsgSize || assm->remoteMaxMsgSize == 0)
964  {
965  /* There is a real new limit. */
966  assm->remoteMaxMsgSize = limit;
967  } else {
968  smlTrace(TRACE_INTERNAL,
969  "%s: using old limit (%d) because of large new limit (%d).",
970  __func__, assm->remoteMaxMsgSize, limit);
971  }
972  }
973 
974  smlTrace(TRACE_EXIT, "%s - %d", __func__, assm->remoteMaxMsgSize);
975  return assm->remoteMaxMsgSize;
976 }
977 
978 /* FIXME: DEPRECATED */
979 int smlAssemblerGetSendingMaxObjSize(SmlAssembler *assm)
980 {
981  return smlAssemblerGetRemoteMaxObjSize(assm);
982 }
983 
984 /* FIXME: DEPRECATED */
985 int smlAssemblerGetRequestedMaxObjSize(SmlAssembler *assm)
986 {
987  return smlAssemblerGetRemoteMaxObjSize(assm);
988 }
989 
990 
991 unsigned int smlAssemblerGetRemoteMaxObjSize(SmlAssembler *assm)
992 {
993  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
994  smlAssert(assm);
995 
996  smlTrace(TRACE_EXIT, "%s: %i", __func__, assm->remoteMaxObjSize);
997  return assm->remoteMaxObjSize;
998 }
999 
1000 /* FIXME: DEPRECATED */
1001 void smlAssemblerSetRequestedMaxObjSize(SmlAssembler *assm, int limit)
1002 {
1003  smlAssemblerSetRemoteMaxObjSize(assm, limit);
1004 }
1005 
1006 /* FIXME: DEPRECATED */
1007 void smlAssemblerSetSendingMaxObjSize(SmlAssembler *assm, int limit)
1008 {
1009  smlAssemblerSetRemoteMaxObjSize(assm, limit);
1010 }
1011 
1012 unsigned int smlAssemblerSetRemoteMaxObjSize(SmlAssembler *assm, unsigned int limit)
1013 {
1014  smlTrace(TRACE_ENTRY, "%s(%p, %i)", __func__, assm, limit);
1015  smlAssert(assm);
1016 
1017  if (limit == 0)
1018  {
1019  /* Reset MaxObjSize to unused state */
1020  assm->remoteMaxObjSize = limit;
1021  } else {
1022  if (limit < assm->remoteMaxObjSize || assm->remoteMaxObjSize == 0)
1023  {
1024  /* There is a real new limit. */
1025  assm->remoteMaxObjSize = limit;
1026  } else {
1027  smlTrace(TRACE_INTERNAL,
1028  "%s: using old limit (%d) because of large new limit (%d).",
1029  __func__, assm->remoteMaxObjSize, limit);
1030  }
1031  }
1032 
1033  smlTrace(TRACE_EXIT, "%s - %d", __func__, assm->remoteMaxObjSize);
1034  return assm->remoteMaxObjSize;
1035 }
1036 
1037 SmlBool smlAssemblerIsEmpty(SmlAssembler *assm)
1038 {
1039  smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
1040  smlAssert(assm);
1041 
1042  SmlBool ret = assm->empty;
1043 
1044  smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
1045  return ret;
1046 }
1047 
1054 {
1055  smlAssert(assm);
1056  smlAssert(assm->functions.missing_status);
1057 
1058  SmlBool ret = assm->functions.missing_status(assm->assm_userdata);
1059 
1060  return ret;
1061 }
1062 
1063 SmlBool smlAssemblerGetNextCmdRef(SmlAssembler *assm, unsigned int *cmdRef, unsigned int *msgRef)
1064 {
1065  smlAssert(assm);
1066  smlAssert(cmdRef);
1067  smlAssert(msgRef);
1068  smlAssert(assm->functions.next_cmdref);
1069 
1070  return assm->functions.next_cmdref(assm->assm_userdata, cmdRef, msgRef);
1071 }
1072 
void smlAssemblerSetOption(SmlAssembler *assm, const char *optionname, const char *value)
Sets a option on the assembler.
Definition: sml_parse.c:896
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
const char * smlAssemblerGetOption(SmlAssembler *assm, const char *optionname)
Gets a option from the assembler.
Definition: sml_parse.c:914
SmlBool smlParserGetHeader(SmlParser *parser, SmlHeader **header, SmlCred **cred, SmlError **error)
Parses the SyncHdr.
Definition: sml_parse.c:216
SmlErrorType type
void smlParserFree(SmlParser *parser)
Frees a parser.
Definition: sml_parse.c:108
SmlAssemblerResult smlAssemblerStartCommand(SmlAssembler *assm, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
Starts a parent command.
Definition: sml_parse.c:659
SmlAssemblerResult smlAssemblerAddStatusFull(SmlAssembler *assm, SmlStatus *status, SmlBool force, SmlError **error)
Assembles a status.
Definition: sml_parse.c:839
SmlAssemblerResult smlAssemblerReserveStatus(SmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error)
Reserves a place for a status with this assembler.
Definition: sml_parse.c:806
SmlBool smlParserEnd(SmlParser *parser, SmlBool *final, SmlBool *end, SmlError **error)
Ends the parsing.
Definition: sml_parse.c:314
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
SmlBool smlAssemblerIsStatusMissing(SmlAssembler *assm)
Checks if there are reserved statuses missing.
Definition: sml_parse.c:1053
SmlParser * smlParserNew(SmlMimeType type, unsigned int limit, SmlError **error)
Creates a new parser.
Definition: sml_parse.c:50
SmlXmlAssembler * smlXmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error)
Creates a new XML assembler.
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
SmlBool smlParserStart(SmlParser *parser, const char *data, unsigned int size, SmlError **error)
Starts the parser on a given data buffer.
Definition: sml_parse.c:132
SmlBool smlParserGetStatus(SmlParser *parser, SmlStatus **status, SmlError **error)
Parses the next status.
Definition: sml_parse.c:284
SmlAssembler * smlAssemblerNew(SmlMimeType type, unsigned int limit, SmlError **error)
Creates a new assembler.
Definition: sml_parse.c:352
SmlParserResult smlParserGetCommand(SmlParser *parser, SmlCommand **cmd, SmlError **error)
Parses the next command.
Definition: sml_parse.c:250
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
Definition: sml_support.c:335
unsigned int smlAssemblerCheckSize(SmlAssembler *assm, SmlBool headeronly, SmlError **error)
Assembles the complete message and returns the result.
Definition: sml_parse.c:485
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
SmlBool smlAssemblerGetSpace(SmlAssembler *assm, int *space, SmlCommand *parent, SmlCommand *cmd, SmlError **error)
Gets the available space in the assembler.
Definition: sml_parse.c:545
Represent an error.