00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <libsyncml/syncml.h>
00023
00024 #include <libsyncml/syncml_internals.h>
00025 #include <libsyncml/sml_elements_internals.h>
00026 #include <libsyncml/sml_command_internals.h>
00027 #include <libsyncml/sml_devinf_internals.h>
00028 #include <libsyncml/sml_session_internals.h>
00029 #include "libsyncml/sml_error_internals.h"
00030
00031 #include "sml_xml_assm.h"
00032 #include "sml_xml_assm_internals.h"
00033
00034 #define BUFFER_SIZE 500
00035
00043
00044 static SmlBool _smlXmlAssemblerStartNodeNS(SmlXmlAssembler *assm, const char *name, const char *uri, SmlError **error)
00045 {
00046 CHECK_ERROR_REF
00047 smlAssert(assm);
00048 smlAssert(assm->writer);
00049 smlAssert(name != NULL);
00050 smlAssert(strlen(name) > 0);
00051 smlTrace(TRACE_INTERNAL, "%s: Starting \"%s\"", __func__, VA_STRING(name));
00052 int rc = xmlTextWriterStartElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri);
00053 if (rc < 0) {
00054 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to start node");
00055 return FALSE;
00056 }
00057 return TRUE;
00058 }
00059
00060 static SmlBool _smlXmlAssemblerStartNode(SmlXmlAssembler *assm, const char *name, SmlError **error)
00061 {
00062 CHECK_ERROR_REF
00063 return _smlXmlAssemblerStartNodeNS(assm, name, NULL, error);
00064 }
00065
00066 static SmlBool _smlXmlAssemblerEndNode(SmlXmlAssembler *assm, SmlError **error)
00067 {
00068 CHECK_ERROR_REF
00069 smlTrace(TRACE_INTERNAL, "%s: Ending node", __func__);
00070 int rc = xmlTextWriterEndElement(assm->writer);
00071 if (rc < 0) {
00072 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end node (%d).", rc);
00073 return FALSE;
00074 }
00075 return TRUE;
00076 }
00077
00078 static SmlBool _smlXmlAssemblerAddStringNS(SmlXmlAssembler *assm, const char *name, const char *uri, const char *value, SmlError **error)
00079 {
00080 CHECK_ERROR_REF
00081 int rc = xmlTextWriterWriteElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri, (xmlChar *)value);
00082 if (rc < 0) {
00083 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add string (%d - %s:%s -> %s).", rc, VA_STRING(uri), VA_STRING(name), VA_STRING(value));
00084 return FALSE;
00085 }
00086 return TRUE;
00087 }
00088
00089 static SmlBool _smlXmlAssemblerAddString(SmlXmlAssembler *assm, const char *name, const char *value, SmlError **error)
00090 {
00091 CHECK_ERROR_REF
00092 int rc = xmlTextWriterWriteElement(assm->writer, (xmlChar *)name, (xmlChar *)value);
00093 if (rc < 0) {
00094 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add pure string (%d - %s -> %s).", rc, VA_STRING(name), VA_STRING(value));
00095 return FALSE;
00096 }
00097 return TRUE;
00098 }
00099
00100 static SmlBool _smlXmlAssemblerAddData(SmlXmlAssembler *assm, const char *name, const char *value, unsigned int size, SmlBool raw, SmlError **error)
00101 {
00102 CHECK_ERROR_REF
00103 int rc = 0;
00104 if (!_smlXmlAssemblerStartNode(assm, name, error))
00105 return FALSE;
00106
00107 if (raw)
00108 rc = xmlTextWriterWriteRawLen(assm->writer, (xmlChar *)value, size);
00109 else
00110 rc = xmlTextWriterWriteFormatCDATA(assm->writer, "%*s", size, (xmlChar *)value);
00111
00112 if (rc < 0) {
00113 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data (%d).", rc);
00114 return FALSE;
00115 }
00116
00117 if (!_smlXmlAssemblerEndNode(assm, error))
00118 return FALSE;
00119
00120 return TRUE;
00121 }
00122
00123 static SmlBool _smlXmlAssemblerAddID(SmlXmlAssembler *assm, const char *name, unsigned int id, SmlError **error)
00124 {
00125 CHECK_ERROR_REF
00126 int rc = xmlTextWriterWriteFormatElement(assm->writer, (xmlChar *)name, "%i", id);
00127 if (rc < 0) {
00128 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add id");
00129 return FALSE;
00130 }
00131 return TRUE;
00132 }
00133
00134 static SmlBool _smlXmlAssemblerAddIDNS(SmlXmlAssembler *assm, const char *name, const char *uri, unsigned int id, SmlError **error)
00135 {
00136 CHECK_ERROR_REF
00137 int rc = xmlTextWriterWriteFormatElementNS(assm->writer, NULL, (xmlChar *)name, (xmlChar *)uri, "%i", id);
00138 if (rc < 0) {
00139 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add id");
00140 return FALSE;
00141 }
00142 return TRUE;
00143 }
00144
00145 static SmlBool _smlAssembleUseMaxObjSize(SmlXmlAssembler *assm)
00146 {
00147 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
00148
00149
00150 const char *opt = smlAssemblerGetOption(assm->assembler, "USE_LARGEOBJECTS");
00151 SmlBool supportsLargeObjects = (opt && !atoi(opt)) ? FALSE : TRUE;
00152
00153
00154 if (assm->session->sessionType == SML_SESSION_TYPE_SERVER)
00155 {
00156 if (smlAssemblerGetRemoteMaxObjSize(assm->assembler) <= 0)
00157 supportsLargeObjects = FALSE;
00158 if (smlAssemblerGetRemoteMaxMsgSize(assm->assembler) <= 0)
00159 supportsLargeObjects = FALSE;
00160 }
00161
00162
00163 if (assm->session->version == SML_VERSION_10)
00164 supportsLargeObjects = FALSE;
00165
00166
00167
00168
00169 if (smlSessionGetLocalMaxObjSize(assm->session) <= 0)
00170 supportsLargeObjects = FALSE;
00171
00172 smlTrace(TRACE_EXIT, "%s - %d", __func__, supportsLargeObjects);
00173 return supportsLargeObjects;
00174 }
00175
00176 static SmlBool _smlAssembleMaxObjSize(SmlXmlAssembler *assm, SmlError **error)
00177 {
00178 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
00179 CHECK_ERROR_REF
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_MAXOBJSIZE, SML_NAMESPACE_METINF, smlSessionGetLocalMaxObjSize(assm->session), error))
00200 goto error;
00201
00202 smlTrace(TRACE_EXIT, "%s", __func__);
00203 return TRUE;
00204
00205 error:
00206 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00207 return FALSE;
00208 }
00209
00210 SmlBool smlLocationAssemble(SmlLocation *location, SmlXmlAssembler *assm, const char *name, SmlError **error)
00211 {
00212 smlTrace(TRACE_ENTRY, "%s(%p, %p, %s, %p)", __func__, location, assm, VA_STRING(name), error);
00213 CHECK_ERROR_REF
00214 smlAssert(assm);
00215 smlAssert(location);
00216
00217 if (name) {
00218 if (!_smlXmlAssemblerStartNode(assm, name, error))
00219 goto error;
00220 }
00221
00222 if (!location->locURI) {
00223 smlErrorSet(error, SML_ERROR_GENERIC, "No locURI set");
00224 goto error;
00225 }
00226
00227 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_LOCURI, location->locURI, error))
00228 goto error;
00229
00230 if (location->locName) {
00231 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_LOCNAME, location->locName, error))
00232 goto error;
00233 }
00234
00235 if (name) {
00236 if (!_smlXmlAssemblerEndNode(assm, error))
00237 goto error;
00238 }
00239
00240 smlTrace(TRACE_EXIT, "%s", __func__);
00241 return TRUE;
00242
00243 error:
00244 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00245 return FALSE;
00246 }
00247
00248
00249
00250 SmlBool smlAnchorAssemble(SmlAnchor *anchor, SmlXmlAssembler *assm, SmlError **error)
00251 {
00252 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, anchor, assm, error);
00253 CHECK_ERROR_REF
00254 smlAssert(assm);
00255 smlAssert(anchor);
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_ANCHOR, SML_NAMESPACE_METINF, error))
00266 goto error;
00267
00268 if (!anchor->next) {
00269 smlErrorSet(error, SML_ERROR_GENERIC, "No next set");
00270 goto error;
00271 }
00272
00273
00274
00275
00276 if (anchor->last) {
00277 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_LAST, SML_NAMESPACE_METINF, anchor->last, error))
00278 goto error;
00279
00280 }
00281
00282 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_NEXT, SML_NAMESPACE_METINF, anchor->next, error))
00283 goto error;
00284
00285 if (!_smlXmlAssemblerEndNode(assm, error))
00286 goto error;
00287
00288 smlTrace(TRACE_EXIT, "%s", __func__);
00289 return TRUE;
00290
00291 error:
00292 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00293 return FALSE;
00294 }
00295
00296 SmlBool smlItemAssemble(SmlItem *item, SmlXmlAssembler *assm, SmlError **error)
00297 {
00298 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, item, assm, error);
00299 CHECK_ERROR_REF
00300 smlAssert(assm);
00301 smlAssert(item);
00302
00303 if (assm->moreDataSet) {
00304 smlErrorSet(error, SML_ERROR_GENERIC, "Trying to start a new item while last item had more data");
00305 goto error;
00306 }
00307
00308
00309 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error))
00310 goto error;
00311
00312
00313 if (smlItemGetTarget(item)) {
00314 if (!smlLocationAssemble(smlItemGetTarget(item), assm, SML_ELEMENT_TARGET, error))
00315 goto error;
00316 }
00317
00318
00319 if (smlItemGetSource(item)) {
00320 if (!smlLocationAssemble(smlItemGetSource(item), assm, SML_ELEMENT_SOURCE, error))
00321 goto error;
00322 }
00323
00324
00325 if (smlItemGetSourceParent(item)) {
00326 if (!smlLocationAssemble(smlItemGetSourceParent(item), assm, SML_ELEMENT_SOURCE_PARENT, error))
00327 goto error;
00328 }
00329
00330
00331 if (smlItemGetTargetParent(item)) {
00332 if (!smlLocationAssemble(smlItemGetTargetParent(item), assm, SML_ELEMENT_TARGET_PARENT, error))
00333 goto error;
00334 }
00335
00336
00337 if (smlItemHasData(item)) {
00338 if (item->disabled) {
00339 if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, "", 0, item->raw, error))
00340 goto error;
00341 } else {
00342 char *data = NULL;
00343 unsigned int size = 0;
00344 if (!smlItemGetData(item, &data, &size, error))
00345 goto error;
00346
00347 if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, data, size, item->raw, error))
00348 goto error;
00349 }
00350 }
00351
00352
00353 if (item->moreData) {
00354 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MOREDATA, "", error))
00355 goto error;
00356
00357 assm->moreDataSet = TRUE;
00358 }
00359
00360
00361 if (!_smlXmlAssemblerEndNode(assm, error))
00362 goto error;
00363
00364 smlTrace(TRACE_EXIT, "%s", __func__);
00365 return TRUE;
00366
00367 error:
00368 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00369 return FALSE;
00370 }
00371
00372 SmlBool smlCredAssemble(SmlCred *cred, SmlXmlAssembler *assm, SmlError **error)
00373 {
00374 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, cred, assm, error);
00375 CHECK_ERROR_REF
00376 smlAssert(assm);
00377 smlAssert(cred);
00378
00379 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CRED, error))
00380 goto error;
00381
00382
00383 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00384 goto error;
00385
00386 switch (cred->format) {
00387 case SML_FORMAT_TYPE_BASE64:
00388 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_FORMAT, SML_NAMESPACE_METINF, SML_BASE64, error))
00389 goto error;
00390 break;
00391 default:
00392 smlErrorSet(error, SML_ERROR_GENERIC, "SyncML credential: Unknown format %d.", cred->format);
00393 goto error;
00394 }
00395
00396 switch (cred->type) {
00397 case SML_AUTH_TYPE_BASIC:
00398 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_BASIC, error))
00399 goto error;
00400 break;
00401 case SML_AUTH_TYPE_MD5:
00402 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_MD5, error))
00403 goto error;
00404 break;
00405 default:
00406 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown format");
00407 goto error;
00408 }
00409
00410
00411 if (!_smlXmlAssemblerEndNode(assm, error))
00412 goto error;
00413
00414 if (!_smlXmlAssemblerAddData(assm, SML_ELEMENT_DATA, cred->data, strlen(cred->data), TRUE, error))
00415 goto error;
00416
00417 if (!_smlXmlAssemblerEndNode(assm, error))
00418 goto error;
00419
00420 smlTrace(TRACE_EXIT, "%s", __func__);
00421 return TRUE;
00422
00423 error:
00424 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00425 return FALSE;
00426 }
00427
00428 SmlBool smlAccessAssemble(SmlXmlAssembler *assm, SmlCommand *change, SmlError **error)
00429 {
00430 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, change, error);
00431 CHECK_ERROR_REF
00432 smlAssert(change);
00433 smlAssert(assm);
00434
00435 if (!change->private.access.item) {
00436 smlErrorSet(error, SML_ERROR_GENERIC, "Missing item");
00437 goto error;
00438 }
00439
00440 if (!change->private.access.item->contenttype) {
00441 smlErrorSet(error, SML_ERROR_GENERIC, "Missing contenttype");
00442 goto error;
00443 }
00444
00445
00446 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00447 goto error;
00448
00449 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, change->private.access.item->contenttype, error))
00450 goto error;
00451
00452
00453 if (!_smlXmlAssemblerEndNode(assm, error))
00454 goto error;
00455
00456 if (!smlItemAssemble(change->private.access.item, assm, error))
00457 goto error;
00458
00459 smlTrace(TRACE_EXIT, "%s", __func__);
00460 return TRUE;
00461
00462 error:
00463 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00464 return FALSE;
00465 }
00466
00467 SmlBool smlChangeAssemble(SmlXmlAssembler *assm, SmlCommand *change, SmlError **error)
00468 {
00469 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, change, error);
00470 CHECK_ERROR_REF
00471 smlAssert(change);
00472 smlAssert(assm);
00473
00474 if (!change->private.change.items ||
00475 !g_list_length(change->private.change.items)) {
00476 smlErrorSet(error, SML_ERROR_GENERIC, "Missing items");
00477 goto error;
00478 }
00479
00480
00481 smlAssert(g_list_length(change->private.change.items) == 1);
00482 SmlItem *item = g_list_nth_data(change->private.change.items, 0);
00483
00484 if (!item) {
00485 smlErrorSet(error, SML_ERROR_GENERIC, "One item of the item list is NULL.");
00486 goto error;
00487 }
00488 if (!item->contenttype) {
00489 smlErrorSet(error, SML_ERROR_GENERIC, "Missing contenttype");
00490 goto error;
00491 }
00492
00493
00494 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00495 goto error;
00496
00497 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, item->contenttype, error))
00498 goto error;
00499
00500
00501
00502 const char *opt = smlAssemblerGetOption(assm->assembler, "USE_LARGEOBJECTS");
00503 SmlBool supportsLargeObjects = (opt && !atoi(opt)) ? FALSE : TRUE;
00504
00505 smlTrace(TRACE_INTERNAL, "%s: Large object: use %i, server %i, requestedSize %i", __func__, supportsLargeObjects, assm->session->sessionType == SML_SESSION_TYPE_SERVER ? 1 : 0, smlAssemblerGetRemoteMaxObjSize(assm->assembler));
00506
00507 if (supportsLargeObjects && change->size) {
00508 if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_SIZE, SML_NAMESPACE_METINF, change->size, error))
00509 goto error;
00510 }
00511
00512
00513 if (!_smlXmlAssemblerEndNode(assm, error))
00514 goto error;
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 SmlSessionType sessionType = assm->session->sessionType;
00543 opt = smlAssemblerGetOption(assm->assembler, "ONLY_REPLACE");
00544 if (change->type == SML_COMMAND_TYPE_ADD)
00545 {
00546 if (opt && atoi(opt) &&
00547 sessionType == SML_SESSION_TYPE_SERVER) {
00548
00549 if (item->target)
00550 smlLocationUnref(item->target);
00551 item->target = item->source;
00552 item->source = NULL;
00553 } else {
00554
00555 if (item->target)
00556 smlLocationUnref(item->target);
00557 item->target = NULL;
00558 }
00559 } else {
00560 if (sessionType == SML_SESSION_TYPE_SERVER) {
00561
00562 if (item->source)
00563 smlLocationUnref(item->source);
00564 item->source = NULL;
00565 } else {
00566
00567 if (item->target)
00568 smlLocationUnref(item->target);
00569 item->target = NULL;
00570 }
00571 }
00572
00573 if (!smlItemAssemble(item, assm, error))
00574 goto error;
00575
00576 smlTrace(TRACE_EXIT, "%s", __func__);
00577 return TRUE;
00578
00579 error:
00580 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00581 return FALSE;
00582 }
00583
00584 SmlBool smlSyncAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error)
00585 {
00586 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error);
00587 CHECK_ERROR_REF
00588 smlAssert(cmd);
00589 smlAssert(assm);
00590
00591 if (!cmd->target) {
00592 smlErrorSet(error, SML_ERROR_GENERIC, "No target set");
00593 goto error;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602 if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error))
00603 goto error;
00604
00605 if (!cmd->source) {
00606 smlErrorSet(error, SML_ERROR_GENERIC, "No source set");
00607 goto error;
00608 }
00609
00610 if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error))
00611 goto error;
00612
00613 if (_smlAssembleUseMaxObjSize(assm))
00614 {
00615 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00616 goto error;
00617
00618 if (!_smlAssembleMaxObjSize(assm, error))
00619 goto error;
00620
00621 if (!_smlXmlAssemblerEndNode(assm, error))
00622 goto error;
00623 }
00624
00625 const char *opt = smlAssemblerGetOption(assm->assembler, "USE_NUMBEROFCHANGES");
00626 SmlBool supportsNumberOfChanges = (opt && !atoi(opt)) ? FALSE : TRUE;
00627 if (supportsNumberOfChanges && assm->session->version != SML_VERSION_10) {
00628 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_NUMBEROFCHANGES, cmd->private.sync.numChanged, error))
00629 goto error;
00630 }
00631
00632 smlTrace(TRACE_EXIT, "%s", __func__);
00633 return TRUE;
00634
00635 error:
00636 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00637 return FALSE;
00638 }
00639
00640 SmlBool smlMapItemAssemble(SmlXmlAssembler *assm, SmlMapItem *item, SmlError **error)
00641 {
00642 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, item, error);
00643 CHECK_ERROR_REF
00644 smlAssert(assm);
00645 smlAssert(item);
00646
00647 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_MAPITEM, error))
00648 goto error;
00649
00650 if (item->source) {
00651 if (!smlLocationAssemble(item->source, assm, SML_ELEMENT_SOURCE, error))
00652 goto error;
00653 }
00654
00655 if (item->target) {
00656 if (!smlLocationAssemble(item->target, assm, SML_ELEMENT_TARGET, error))
00657 goto error;
00658 }
00659
00660
00661 if (!_smlXmlAssemblerEndNode(assm, error))
00662 goto error;
00663
00664 smlTrace(TRACE_EXIT, "%s", __func__);
00665 return TRUE;
00666
00667 error:
00668 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00669 return FALSE;
00670 }
00671
00672 SmlBool smlMapAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error)
00673 {
00674 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error);
00675 CHECK_ERROR_REF
00676 smlAssert(cmd);
00677 smlAssert(assm);
00678
00679 if (!cmd->target) {
00680 smlErrorSet(error, SML_ERROR_GENERIC, "No target set");
00681 goto error;
00682 }
00683
00684 if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error))
00685 goto error;
00686
00687 if (!cmd->source) {
00688 smlErrorSet(error, SML_ERROR_GENERIC, "No source set");
00689 goto error;
00690 }
00691
00692 if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error))
00693 goto error;
00694
00695 GList *m = NULL;
00696 for (m = cmd->private.map.items; m; m = m->next) {
00697 SmlMapItem *item = m->data;
00698 if (!smlMapItemAssemble(assm, item, error))
00699 goto error;
00700 }
00701
00702 smlTrace(TRACE_EXIT, "%s", __func__);
00703 return TRUE;
00704
00705 error:
00706 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00707 return FALSE;
00708 }
00709
00710 SmlBool smlAlertAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error)
00711 {
00712 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error);
00713 CHECK_ERROR_REF
00714 smlAssert(cmd);
00715 smlAssert(assm);
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_DATA, cmd->private.alert.type, error))
00727 goto error;
00728
00729
00730
00731
00732 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error))
00733 goto error;
00734
00735
00736 if (cmd->target) {
00737 if (!smlLocationAssemble(cmd->target, assm, SML_ELEMENT_TARGET, error))
00738 goto error;
00739 }
00740
00741
00742 if (cmd->source) {
00743 if (!smlLocationAssemble(cmd->source, assm, SML_ELEMENT_SOURCE, error))
00744 goto error;
00745 } else {
00746
00747 if (cmd->private.alert.type != SML_ALERT_NEXT_MESSAGE) {
00748 smlErrorSet(error, SML_ERROR_GENERIC, "No source set");
00749 goto error;
00750 }
00751 }
00752
00753
00754
00755
00756
00757
00758
00759 SmlBool meta = FALSE;
00760 if (cmd->private.alert.contentType)
00761 meta = TRUE;
00762 if (cmd->private.alert.anchor)
00763 meta = TRUE;
00764 if (_smlAssembleUseMaxObjSize(assm))
00765 meta = TRUE;
00766
00767 if (meta && !_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00768 goto error;
00769
00770 if (cmd->private.alert.contentType &&
00771 !_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF,
00772 cmd->private.alert.contentType, error))
00773 goto error;
00774
00775 if (cmd->private.alert.anchor &&
00776 !smlAnchorAssemble(cmd->private.alert.anchor, assm, error))
00777 goto error;
00778
00779 if (_smlAssembleUseMaxObjSize(assm) &&
00780 !_smlAssembleMaxObjSize(assm, error))
00781 goto error;
00782
00783 if (meta && !_smlXmlAssemblerEndNode(assm, error))
00784 goto error;
00785
00786
00787
00788
00789 if (!_smlXmlAssemblerEndNode(assm, error))
00790 goto error;
00791
00792 smlTrace(TRACE_EXIT, "%s", __func__);
00793 return TRUE;
00794
00795 error:
00796 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00797 return FALSE;
00798 }
00799
00800 SmlBool smlResultsAssemble(SmlXmlAssembler *assm, SmlCommand *cmd, SmlError **error)
00801 {
00802 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, cmd, error);
00803 CHECK_ERROR_REF
00804 smlAssert(cmd);
00805 smlAssert(assm);
00806
00807
00808
00809
00810
00811
00812 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGREF, cmd->private.results.status->msgRef, error))
00813 goto error;
00814
00815
00816 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDREF, cmd->private.results.status->cmdRef, error))
00817 goto error;
00818
00819
00820 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00821 goto error;
00822 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, cmd->private.results.status->item->contenttype, error))
00823 goto error;
00824 if (!_smlXmlAssemblerEndNode(assm, error))
00825 goto error;
00826
00827
00828 if (cmd->private.results.status->targetRef) {
00829 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_TARGETREF, cmd->private.results.status->targetRef->locURI, error))
00830 goto error;
00831 }
00832
00833
00834 if (cmd->private.results.status->sourceRef) {
00835 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, cmd->private.results.status->sourceRef->locURI, error))
00836 goto error;
00837 }
00838
00839
00840 if (!smlItemAssemble(cmd->private.results.status->item, assm, error))
00841 goto error;
00842
00843 smlTrace(TRACE_EXIT, "%s", __func__);
00844 return TRUE;
00845
00846 error:
00847 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
00848 return FALSE;
00849 }
00850
00851 SmlBool smlXmlAssemblerAddHeader(SmlXmlAssembler *assm, SmlSession *session, SmlError **error)
00852 {
00853 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error);
00854 CHECK_ERROR_REF
00855 smlAssert(assm);
00856 smlAssert(g_mutex_trylock(assm->mutex));
00857 smlAssert(session);
00858
00859
00860 if (assm->header_buffer) {
00861 xmlBufferFree(assm->header_buffer);
00862 assm->header_buffer = NULL;
00863 }
00864
00865
00866 assm->header_buffer = xmlBufferCreateSize(BUFFER_SIZE);
00867 if (!assm->header_buffer) {
00868 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
00869 goto error;
00870 }
00871
00872 assm->writer = xmlNewTextWriterMemory(assm->header_buffer, 0);
00873 if (!assm->writer) {
00874 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
00875 goto error;
00876 }
00877
00878 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCHDR, error))
00879 goto error;
00880
00881 if (!session->protocol) {
00882 smlErrorSet(error, SML_ERROR_GENERIC, "No version set");
00883 goto error;
00884 }
00885
00886 if (!session->version) {
00887 smlErrorSet(error, SML_ERROR_GENERIC, "No dtd set");
00888 goto error;
00889 }
00890
00891 switch (session->protocol) {
00892 case SML_PROTOCOL_SYNCML:
00893 switch (session->version) {
00894 case SML_VERSION_10:
00895 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.0", error))
00896 goto error;
00897
00898 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_10, error))
00899 goto error;
00900 break;
00901 case SML_VERSION_11:
00902 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.1", error))
00903 goto error;
00904
00905 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_11, error))
00906 goto error;
00907 break;
00908 case SML_VERSION_12:
00909 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.2", error))
00910 goto error;
00911
00912 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERPROTO, SML_VERSION_STRING_12, error))
00913 goto error;
00914 break;
00915 default:
00916 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version");
00917 goto error;
00918 }
00919 break;
00920 default:
00921 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown protocol");
00922 goto error;
00923 }
00924
00925 if (session->sessionID) {
00926 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SESSIONID, session->sessionID, error))
00927 goto error;
00928 }
00929
00930 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGID, session->lastMessageID, error))
00931 goto error;
00932
00933 if (!smlLocationAssemble(session->target, assm, SML_ELEMENT_TARGET, error))
00934 goto error;
00935
00936 if (!smlLocationAssemble(session->source, assm, SML_ELEMENT_SOURCE, error))
00937 goto error;
00938
00939 if (session->responseURI &&
00940 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_RESPURI, session->responseURI, error))
00941 goto error;
00942
00943
00944
00945
00946 if (session->cred != NULL && session->cred->data != NULL) {
00947 if (!smlCredAssemble(session->cred, assm, error))
00948 goto error;
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 if (session->protocol == SML_PROTOCOL_SYNCML &&
00965 session->version > SML_VERSION_10)
00966 {
00967
00968
00969
00970 if (session->sessionType == SML_SESSION_TYPE_SERVER ||
00971 smlSessionGetLocalMaxObjSize(session) > 0)
00972 {
00973
00974 if (smlSessionGetLocalMaxMsgSize(session) < 1)
00975 {
00976 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00977 "MaxMsgSize must be set.");
00978 goto error;
00979 }
00980 if (smlSessionGetLocalMaxObjSize(session) < 1)
00981 {
00982 smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
00983 "MaxObjSize must be set.");
00984 goto error;
00985 }
00986 }
00987 }
00988
00989
00990 unsigned int localMaxMsgSize = smlSessionGetLocalMaxMsgSize(session);
00991 if (localMaxMsgSize) {
00992 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
00993 goto error;
00994
00995
00996
00997
00998 if (!_smlXmlAssemblerAddIDNS(assm, SML_ELEMENT_MAXMSGSIZE, SML_NAMESPACE_METINF, localMaxMsgSize, error))
00999 goto error;
01000
01001
01002 if (!_smlXmlAssemblerEndNode(assm, error))
01003 goto error;
01004 }
01005
01006 if (!_smlXmlAssemblerEndNode(assm, error))
01007 goto error;
01008
01009
01010 if (xmlTextWriterEndDocument(assm->writer) < 0) {
01011 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer");
01012 goto error;
01013 }
01014
01015 xmlFreeTextWriter(assm->writer);
01016 assm->writer = NULL;
01017
01018 g_mutex_unlock(assm->mutex);
01019 smlTrace(TRACE_EXIT, "%s", __func__);
01020 return TRUE;
01021
01022 error:
01023 if (assm->writer) {
01024 xmlFreeTextWriter(assm->writer);
01025 assm->writer = NULL;
01026 }
01027 if (assm->header_buffer) {
01028 xmlBufferFree(assm->header_buffer);
01029 assm->header_buffer = NULL;
01030 }
01031 g_mutex_unlock(assm->mutex);
01032 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01033 return FALSE;
01034 }
01035
01036 SmlBool smlXmlAssemblerStartCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlCommand *cmd, SmlError **error)
01037 {
01038 CHECK_ERROR_REF
01039 smlAssert(assm);
01040 smlAssert(cmd);
01041
01042 if (cmd->type == SML_COMMAND_TYPE_UNKNOWN) {
01043 smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set");
01044 goto error;
01045 }
01046
01047 if (!cmd->cmdID) {
01048 smlErrorSet(error, SML_ERROR_GENERIC, "No cmd ID set");
01049 goto error;
01050 }
01051
01052
01053 if (!assm->header_buffer) {
01054 smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added");
01055 goto error;
01056 }
01057
01058 SmlXmlAssemblerCommand *assmcmd = smlTryMalloc0(sizeof(SmlXmlAssemblerCommand), error);
01059 if (!assmcmd)
01060 goto error;
01061 assmcmd->nodeType = SML_ASSEMBLER_NODE_OPEN;
01062 assmcmd->cmdID = cmd->cmdID;
01063 assmcmd->cmdType = cmd->type;
01064
01065 GList **appendto = &(assm->commands);
01066 if (parentID) {
01067
01068 SmlXmlAssemblerCommand *excmd = NULL;
01069 GList *b = NULL;
01070 for (b = assm->commands; b; b = b->next) {
01071 excmd = b->data;
01072 if (excmd->cmdID == parentID)
01073 appendto = &(excmd->children);
01074 }
01075 }
01076
01077
01078 assmcmd->buffer = xmlBufferCreateSize(BUFFER_SIZE);
01079 if (!assmcmd->buffer) {
01080 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
01081 goto error_free_cmd;
01082 }
01083
01084 assm->writer = xmlNewTextWriterMemory(assmcmd->buffer, 0);
01085 if (!assm->writer) {
01086 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
01087 goto error_free_buffer;
01088 }
01089
01090
01091 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDID, cmd->cmdID, error))
01092 goto error_free_writer;
01093
01094 switch (cmd->type) {
01095 case SML_COMMAND_TYPE_ALERT:
01096 if (!smlAlertAssemble(assm, cmd, error))
01097 goto error_free_writer;
01098 break;
01099 case SML_COMMAND_TYPE_SYNC:
01100 if (!smlSyncAssemble(assm, cmd, error))
01101 goto error_free_writer;
01102 break;
01103 case SML_COMMAND_TYPE_ADD:
01104 case SML_COMMAND_TYPE_REPLACE:
01105 case SML_COMMAND_TYPE_DELETE:
01106 if (!smlChangeAssemble(assm, cmd, error))
01107 goto error_free_writer;
01108 break;
01109 case SML_COMMAND_TYPE_PUT:
01110 case SML_COMMAND_TYPE_GET:
01111 if (!smlAccessAssemble(assm, cmd, error))
01112 goto error_free_writer;
01113 break;
01114 case SML_COMMAND_TYPE_MAP:
01115 if (!smlMapAssemble(assm, cmd, error))
01116 goto error_free_writer;
01117 break;
01118 case SML_COMMAND_TYPE_RESULTS:
01119 if (!smlResultsAssemble(assm, cmd, error))
01120 goto error_free_writer;
01121 break;
01122 default:
01123 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown command type");
01124 goto error_free_writer;
01125 }
01126
01127
01128 if (xmlTextWriterEndDocument(assm->writer) < 0) {
01129 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer");
01130 goto error_free_writer;
01131 }
01132
01133 xmlFreeTextWriter(assm->writer);
01134 assm->writer = NULL;
01135
01136
01137 *appendto = g_list_append(*appendto, assmcmd);
01138
01139 return TRUE;
01140
01141 error_free_writer:
01142 xmlFreeTextWriter(assm->writer);
01143 assm->writer = NULL;
01144 error_free_buffer:
01145 xmlBufferFree(assmcmd->buffer);
01146 error_free_cmd:
01147 smlSafeFree((gpointer *)&assmcmd);
01148 error:
01149 return FALSE;
01150 }
01151
01152 SmlBool smlXmlAssemblerEndCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlError **error)
01153 {
01154 CHECK_ERROR_REF
01155 smlAssert(assm);
01156
01157
01158 if (!assm->header_buffer) {
01159 smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added");
01160 goto error;
01161 }
01162
01163 SmlXmlAssemblerCommand *assmcmd = smlTryMalloc0(sizeof(SmlXmlAssemblerCommand), error);
01164 if (!assmcmd)
01165 goto error;
01166 assmcmd->nodeType = SML_ASSEMBLER_NODE_CLOSE;
01167
01168 GList **appendto = &(assm->commands);
01169 if (parentID) {
01170
01171 SmlXmlAssemblerCommand *excmd = NULL;
01172 GList *b = NULL;
01173 for (b = assm->commands; b; b = b->next) {
01174 excmd = b->data;
01175 if (excmd->cmdID == parentID)
01176 appendto = &(excmd->children);
01177 }
01178 }
01179
01180
01181 *appendto = g_list_append(*appendto, assmcmd);
01182
01183 return TRUE;
01184
01185 error:
01186 return FALSE;
01187 }
01188
01189 SmlBool smlXmlAssemblerRemCommand(SmlXmlAssembler *assm, unsigned int parentID, SmlError **error)
01190 {
01191 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, assm, parentID, error);
01192 CHECK_ERROR_REF
01193 smlAssert(assm);
01194
01195 GList **removefrom = &(assm->commands);
01196 if (parentID) {
01197
01198 SmlXmlAssemblerCommand *excmd = NULL;
01199 GList *b = NULL;
01200 for (b = assm->commands; b; b = b->next) {
01201 excmd = b->data;
01202 if (excmd->cmdID == parentID)
01203 removefrom = &(excmd->children);
01204 }
01205 }
01206
01207 if (!*removefrom) {
01208 smlErrorSet(error, SML_ERROR_GENERIC, "Nothing to remove");
01209 goto error;
01210 }
01211
01212 GList *b = g_list_last(*removefrom);
01213 SmlXmlAssemblerCommand *cmd = b->data;
01214 *removefrom = g_list_delete_link(*removefrom, b);
01215 if (cmd->nodeType != SML_ASSEMBLER_NODE_OPEN) {
01216 smlErrorSet(error, SML_ERROR_GENERIC, "Trying to remove not a starting command");
01217 goto error;
01218 }
01219
01220 assm->moreDataSet = FALSE;
01221
01222 xmlBufferFree(cmd->buffer);
01223 smlSafeFree((gpointer *)&cmd);
01224
01225 smlTrace(TRACE_EXIT, "%s", __func__);
01226 return TRUE;
01227
01228 error:
01229 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01230 return FALSE;
01231 }
01232
01233 SmlBool smlXmlAssemblerRemStatus(SmlXmlAssembler *assm, SmlError **error)
01234 {
01235 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, error);
01236 CHECK_ERROR_REF
01237 smlAssert(assm);
01238
01239 if (!assm->statuses) {
01240 smlErrorSet(error, SML_ERROR_GENERIC, "Trying to remove status but no status available");
01241 goto error;
01242 }
01243
01244 GList *b;
01245 SmlXmlAssemblerStatus *last = NULL;
01246 for (b = assm->statuses; b; b = b->next) {
01247 SmlXmlAssemblerStatus *status = b->data;
01248
01249 if (!status->buffer)
01250 break;
01251 last = status;
01252 }
01253
01254 if (last) {
01255 xmlBufferFree(last->buffer);
01256 last->buffer = NULL;
01257 }
01258
01259 assm->added_statuses--;
01260
01261 smlTrace(TRACE_EXIT, "%s", __func__);
01262 return TRUE;
01263
01264 error:
01265 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01266 return FALSE;
01267 }
01268
01269 SmlBool smlXmlAssemblerReserveStatus(SmlXmlAssembler *assm, unsigned int cmdRef, unsigned int msgRef, unsigned int cmdID, SmlError **error)
01270 {
01271 smlTrace(TRACE_ENTRY, "%s(%p, %i, %i, %i, %p)", __func__, assm, cmdRef, msgRef, cmdID, error);
01272 CHECK_ERROR_REF
01273 smlAssert(assm);
01274
01275
01276 SmlXmlAssemblerStatus *res = smlTryMalloc0(sizeof(SmlXmlAssemblerStatus), error);
01277 if (!res)
01278 goto error;
01279 res->cmdRef = cmdRef;
01280 res->cmdID = cmdID;
01281 res->msgRef = msgRef;
01282
01283
01284 if (cmdRef != 0)
01285 assm->statuses = g_list_append(assm->statuses, res);
01286 else
01287 assm->statuses = g_list_prepend(assm->statuses, res);
01288 assm->reserved_statuses++;
01289
01290 smlTrace(TRACE_EXIT, "%s", __func__);
01291 return TRUE;
01292
01293 error:
01294 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01295 return FALSE;
01296 }
01297
01298 SmlBool smlXmlAssemblerAddStatus(SmlXmlAssembler *assm, SmlStatus *status, SmlError **error)
01299 {
01300 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, status, error);
01301 CHECK_ERROR_REF
01302 smlAssert(assm);
01303 smlAssert(g_mutex_trylock(assm->mutex));
01304 smlAssert(status);
01305 SmlXmlAssemblerStatus *res = NULL;
01306
01307 smlTrace(TRACE_INTERNAL, "Adding status with cmdRef %i, msgRef %i, cmd %s", status->cmdRef, status->msgRef, smlCommandTypeToString(status->type, error));
01308
01309 if (*error)
01310 goto error;
01311
01312 if (!status->msgRef) {
01313 smlErrorSet(error, SML_ERROR_GENERIC, "No msgref set");
01314 goto error;
01315 }
01316
01317 if (status->type == SML_COMMAND_TYPE_UNKNOWN) {
01318 smlErrorSet(error, SML_ERROR_GENERIC, "No cmd set");
01319 goto error;
01320 }
01321
01322
01323 if (!assm->header_buffer) {
01324 smlErrorSet(error, SML_ERROR_GENERIC, "Header not yet added");
01325 goto error;
01326 }
01327
01328
01329 GList *s = NULL;
01330 for (s = assm->statuses; s; s = s->next) {
01331 res = s->data;
01332 if (res->cmdRef == status->cmdRef && res->msgRef == status->msgRef)
01333 break;
01334 res = NULL;
01335 }
01336
01337 if (!res) {
01338 smlErrorSet(error, SML_ERROR_GENERIC, "Status not reserved");
01339 goto error;
01340 }
01341
01342 if (!res->cmdID) {
01343 smlErrorSet(error, SML_ERROR_GENERIC, "No cmd ID set");
01344 goto error;
01345 }
01346
01347 if (res->buffer) {
01348 smlErrorSet(error, SML_ERROR_GENERIC, "Status already added");
01349 goto error;
01350 }
01351
01352
01353 res->buffer = xmlBufferCreateSize(BUFFER_SIZE);
01354 if (!res->buffer) {
01355 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
01356 goto error;
01357 }
01358
01359 assm->writer = xmlNewTextWriterMemory(res->buffer, 0);
01360 if (!assm->writer) {
01361 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
01362 goto error_free_buffer;
01363 }
01364
01365
01366 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_STATUS, error))
01367 goto error;
01368
01369
01370 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDID, res->cmdID, error))
01371 goto error;
01372
01373
01374 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MSGREF, status->msgRef, error))
01375 goto error;
01376
01377
01378 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_CMDREF, res->cmdRef, error))
01379 goto error;
01380
01381
01382 const char *cmdname = smlCommandTypeToString(status->type, error);
01383 if (!cmdname)
01384 goto error;
01385 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CMD, cmdname, error))
01386 goto error;
01387
01388
01389 if (status->targetRef) {
01390 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_TARGETREF, status->targetRef->locURI, error))
01391 goto error;
01392 }
01393
01394
01395 if (status->sourceRef) {
01396 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, status->sourceRef->locURI, error))
01397 goto error;
01398 }
01399
01400
01401
01402
01403 if (status->type == SML_COMMAND_TYPE_HEADER && status->chal)
01404 {
01405 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CHAL, error))
01406 goto error;
01407
01408 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_META, error))
01409 goto error;
01410
01411 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_FORMAT, SML_NAMESPACE_METINF, SML_BASE64, error))
01412 goto error;
01413
01414 switch (status->chal->type) {
01415 case SML_AUTH_TYPE_BASIC:
01416 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_BASIC, error))
01417 goto error;
01418 break;
01419 case SML_AUTH_TYPE_MD5:
01420 if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_MD5, error))
01421 goto error;
01422 if (status->chal->nonce_b64 &&
01423 !_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_NEXTNONCE, SML_NAMESPACE_METINF, status->chal->nonce_b64, error))
01424 goto error;
01425 break;
01426 default:
01427 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth type");
01428 goto error;
01429 }
01430
01431
01432 if (!_smlXmlAssemblerEndNode(assm, error))
01433 goto error;
01434
01435
01436 if (!_smlXmlAssemblerEndNode(assm, error))
01437 goto error;
01438 }
01439
01440
01441 if (status->data) {
01442 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATA, status->data, error))
01443 goto error;
01444 }
01445
01446
01447 if (status->type == SML_COMMAND_TYPE_ALERT && status->anchor)
01448 {
01449 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_ITEM, error))
01450 goto error;
01451
01452 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DATA, error))
01453 goto error;
01454
01455 if (!smlAnchorAssemble(status->anchor, assm, error))
01456 goto error;
01457
01458
01459 if (!_smlXmlAssemblerEndNode(assm, error))
01460 goto error;
01461
01462
01463 if (!_smlXmlAssemblerEndNode(assm, error))
01464 goto error;
01465 }
01466
01467
01468 if (!_smlXmlAssemblerEndNode(assm, error))
01469 goto error;
01470
01471
01472 if (xmlTextWriterEndDocument(assm->writer) < 0) {
01473 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer");
01474 goto error_free_writer;
01475 }
01476
01477 xmlFreeTextWriter(assm->writer);
01478 assm->writer = NULL;
01479
01480 assm->added_statuses++;
01481
01482 g_mutex_unlock(assm->mutex);
01483 smlTrace(TRACE_EXIT, "%s", __func__);
01484 return TRUE;
01485
01486 error_free_writer:
01487 xmlFreeTextWriter(assm->writer);
01488 assm->writer = NULL;
01489 error_free_buffer:
01490 xmlBufferFree(res->buffer);
01491 res->buffer = NULL;
01492 error:
01493 g_mutex_unlock(assm->mutex);
01494 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01495 return FALSE;
01496 }
01497
01498 SmlBool smlXmlAssemblerMissingStatus(SmlXmlAssembler *assm)
01499 {
01500 smlAssert(assm);
01501
01502 if (assm->reserved_statuses - assm->added_statuses > 0)
01503 return TRUE;
01504
01505 return FALSE;
01506 }
01507
01508 static void flush_list(GList *list)
01509 {
01510 GList *l = NULL;
01511 for (l = list; l; l = l->next) {
01512 SmlXmlAssemblerCommand *cmd = l->data;
01513
01514 if (cmd->nodeType != SML_ASSEMBLER_NODE_CLOSE && cmd->children)
01515 flush_list(cmd->children);
01516
01517 xmlBufferFree(cmd->buffer);
01518 smlSafeFree((gpointer *)&cmd);
01519 }
01520
01521 g_list_free(list);
01522 }
01523
01524 void smlXmlAssemblerFree(SmlXmlAssembler *assm)
01525 {
01526 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
01527 smlAssert(assm);
01528
01529 if (assm->header_buffer) {
01530 xmlBufferFree(assm->header_buffer);
01531 assm->header_buffer = NULL;
01532 }
01533
01534 while (assm->statuses) {
01535 SmlXmlAssemblerStatus *status = assm->statuses->data;
01536
01537 if (status->buffer)
01538 xmlBufferFree(status->buffer);
01539
01540 smlSafeFree((gpointer *)&status);
01541 assm->statuses = g_list_delete_link(assm->statuses, assm->statuses);
01542 }
01543
01544 flush_list(assm->commands);
01545 flush_list(assm->last_commands);
01546
01547 g_mutex_free(assm->mutex);
01548 smlSafeFree((gpointer *)&assm);
01549
01550 smlTrace(TRACE_EXIT, "%s", __func__);
01551 }
01552
01553
01554
01555 unsigned int smlXmlAssemblerFlush(SmlXmlAssembler *assm)
01556 {
01557 smlTrace(TRACE_ENTRY, "%s(%p)", __func__, assm);
01558 smlAssert(assm);
01559
01560 unsigned int newid = 1;
01561 SmlBool missing = FALSE;
01562
01563
01564 GList *s = NULL;
01565 GList *s2 = g_list_copy(assm->statuses);
01566 for (s = s2; s; s = s->next) {
01567 SmlXmlAssemblerStatus *status = s->data;
01568
01569 if (!status->buffer) {
01570
01571
01572
01573 newid++;
01574
01575 missing = TRUE;
01576 } else if (!missing) {
01577 xmlBufferFree(status->buffer);
01578 assm->statuses = g_list_remove(assm->statuses, status);
01579 smlSafeFree((gpointer *)&status);
01580 assm->reserved_statuses--;
01581 assm->added_statuses--;
01582 }
01583 }
01584 g_list_free(s2);
01585
01586
01587
01588
01589
01590
01591 if (assm->last_commands)
01592 flush_list(assm->last_commands);
01593 assm->last_commands = assm->commands;
01594 assm->commands = NULL;
01595
01596
01597 assm->moreDataSet = FALSE;
01598
01599 smlTrace(TRACE_EXIT, "%s: %i", __func__, newid);
01600 return newid;
01601 }
01602
01603 SmlBool smlXmlAssemblerStart(SmlXmlAssembler *assm, SmlSession *session, SmlError **error)
01604 {
01605 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, session, error);
01606 CHECK_ERROR_REF
01607 smlAssert(assm);
01608 smlAssert(g_mutex_trylock(assm->mutex));
01609 smlAssert(session);
01610
01611 assm->session = session;
01612
01613 g_mutex_unlock(assm->mutex);
01614 smlTrace(TRACE_EXIT, "%s", __func__);
01615 return TRUE;
01616 }
01617
01618
01619 SmlBool smlXmlAssemblerEnd(SmlXmlAssembler *assm, SmlError **error)
01620 {
01621 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, error);
01622 CHECK_ERROR_REF
01623 smlAssert(assm);
01624 smlAssert(g_mutex_trylock(assm->mutex));
01625
01626
01627 if (!_smlXmlAssemblerEndNode(assm, error))
01628 goto error;
01629
01630 if (_smlXmlAssemblerEndNode(assm, NULL)) {
01631 smlErrorSet(error, SML_ERROR_GENERIC, "Extra node open");
01632 goto error;
01633 }
01634
01635 g_mutex_unlock(assm->mutex);
01636 smlTrace(TRACE_EXIT, "%s", __func__);
01637 return TRUE;
01638
01639 error:
01640 g_mutex_unlock(assm->mutex);
01641 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01642 return FALSE;
01643 }
01644
01645 SmlBool smlXmlAssemblerAddChildren(SmlXmlAssembler *assm, GList *b, SmlError **error)
01646 {
01647 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assm, b, error);
01648 CHECK_ERROR_REF
01649 smlAssert(assm);
01650 const char *opt = smlAssemblerGetOption(assm->assembler, "ONLY_REPLACE");
01651 SmlBool onlyReplace = (opt && atoi(opt)) ? TRUE : FALSE;
01652
01653 SmlXmlAssemblerCommand *cmd = NULL;
01654 const char *cmdname = NULL;
01655
01656 for (; b; b = b->next) {
01657 cmd = b->data;
01658 switch (cmd->nodeType) {
01659 case SML_ASSEMBLER_NODE_OPEN:
01660
01661
01662 if (cmd->cmdType == SML_COMMAND_TYPE_ADD && onlyReplace)
01663 cmdname = SML_ELEMENT_REPLACE;
01664 else {
01665 cmdname = smlCommandTypeToString(cmd->cmdType, error);
01666 if (!cmdname)
01667 goto error;
01668 }
01669 smlTrace(TRACE_INTERNAL, "opening node %s", cmdname);
01670
01671 if (!_smlXmlAssemblerStartNode(assm, cmdname, error))
01672 goto error;
01673
01674 int rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(cmd->buffer), xmlBufferLength(cmd->buffer));
01675 if (rc < 0) {
01676 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw node data (%d).", rc);
01677 goto error;
01678 }
01679
01680 if (cmd->children) {
01681 if (!smlXmlAssemblerAddChildren(assm, cmd->children, error))
01682 goto error;
01683 }
01684
01685 smlTrace(TRACE_INTERNAL, "%s: closing node", __func__);
01686 if (!_smlXmlAssemblerEndNode(assm, error))
01687 goto error;
01688 break;
01689 case SML_ASSEMBLER_NODE_CLOSE:
01690
01691
01692
01693 break;
01694 }
01695 }
01696
01697 smlTrace(TRACE_EXIT, "%s", __func__);
01698 return TRUE;
01699
01700 error:
01701 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01702 return FALSE;
01703 }
01704
01705 SmlBool smlXmlAssemblerRunFull(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, SmlBool check, unsigned int maxsize, SmlError **error)
01706 {
01707 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p, %i, %i, %i, %p)", __func__, assm, data, size, end, final, check, maxsize, error);
01708 CHECK_ERROR_REF
01709 smlAssert(assm);
01710 smlAssert(g_mutex_trylock(assm->mutex));
01711 smlAssert(data);
01712 smlAssert(size);
01713 smlAssert(assm->session);
01714 unsigned int buffersize = 0;
01715
01716
01717 if (!assm->header_buffer) {
01718 smlErrorSet(error, SML_ERROR_GENERIC, "No header available");
01719 goto error;
01720 }
01721
01722
01723
01724
01725 if (check && !assm->statuses && !assm->commands) {
01726 smlErrorSet(error, SML_ERROR_GENERIC, "No status/command available");
01727 goto error;
01728 }
01729
01730 if (check && assm->statuses && final) {
01731 SmlXmlAssemblerStatus *status = assm->statuses->data;
01732 if (!status->buffer) {
01733 smlErrorSet(error, SML_ERROR_GENERIC, "Missing the first status with cmdRef %i", status->cmdRef);
01734 goto error;
01735 }
01736 }
01737
01738
01739 xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE);
01740 if (!buffer) {
01741 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
01742 goto error;
01743 }
01744
01745 assm->writer = xmlNewTextWriterMemory(buffer, 0);
01746 if (!assm->writer) {
01747 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
01748 goto error_free_buffer;
01749 }
01750
01751
01752
01753
01754
01755 if (xmlTextWriterStartDocument(assm->writer, NULL, "UTF-8", NULL) < 0) {
01756 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
01757 goto error_free_writer;
01758 }
01759
01760
01761 switch (assm->session->version) {
01762 case SML_VERSION_10:
01763 xmlTextWriterWriteRaw(assm->writer, (xmlChar *)"<!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.0//EN\" \"http://www.syncml.org/docs/syncml_represent_v10_20001207.dtd\">");
01764 if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML10, error))
01765 goto error_free_writer;
01766 break;
01767 case SML_VERSION_11:
01768 xmlTextWriterWriteRaw(assm->writer, (xmlChar *)"<!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.1//EN\" \"http://www.syncml.org/docs/syncml_represent_v11_20020213.dtd\">");
01769 if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML11, error))
01770 goto error_free_writer;
01771 break;
01772 case SML_VERSION_12:
01773 xmlTextWriterWriteRaw(assm->writer, (xmlChar *)"<!DOCTYPE SyncML PUBLIC \"-//SYNCML//DTD SyncML 1.2//EN\" \"http://www.openmobilealliance.org/tech/DTD/OMA-TS-SyncML_RepPro_DTD-V1_2.dtd\">");
01774 if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_SYNCML, SML_NAMESPACE_SYNCML12, error))
01775 goto error_free_writer;
01776 break;
01777 default:
01778 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown version");
01779 goto error_free_writer;
01780 }
01781
01782
01783 int rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(assm->header_buffer), xmlBufferLength(assm->header_buffer));
01784 if (rc < 0) {
01785 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw header data (%d).", rc);
01786 goto error_free_writer;
01787 }
01788
01789
01790 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCBODY, error))
01791 goto error_free_writer;
01792
01793
01794
01795 buffersize += 20 + xmlBufferLength(assm->header_buffer);
01796
01797
01798 GList *b = NULL;
01799 SmlBool missingstatus = FALSE;
01800 smlTrace(TRACE_INTERNAL, "%s: Now adding %i statuses",
01801 __func__, g_list_length(assm->statuses));
01802 for (b = assm->statuses; b; b = b->next) {
01803 SmlXmlAssemblerStatus *status = b->data;
01804 if (!status->buffer || xmlBufferLength(status->buffer) == 0) {
01805 if (status->cmdRef == 0 && check) {
01806 smlErrorSet(error, SML_ERROR_GENERIC, "Reserved status 0 has not been added");
01807 goto error_free_writer;
01808 }
01809 smlTrace(TRACE_INTERNAL, "%s: Reserved status %i is missing",
01810 __func__, status->cmdRef);
01811 missingstatus = TRUE;
01812 break;
01813 }
01814
01815 buffersize += xmlBufferLength(status->buffer);
01816
01817
01818 rc = xmlTextWriterWriteRawLen(assm->writer, xmlBufferContent(status->buffer), xmlBufferLength(status->buffer));
01819 if (rc < 0) {
01820 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to write raw status data (%d - %d of %d: %s).",
01821 rc, xmlBufferLength(status->buffer),
01822 buffersize, xmlBufferContent(status->buffer));
01823 goto error_free_writer;
01824 }
01825 }
01826
01827
01828 if (missingstatus && final && check) {
01829 smlErrorSet(error, SML_ERROR_GENERIC, "Reserved status has not been added");
01830 goto error_free_writer;
01831 }
01832
01833
01834 if (!smlXmlAssemblerAddChildren(assm, assm->commands, error))
01835 goto error_free_writer;
01836
01837 if (final) {
01838 smlTrace(TRACE_INTERNAL, "%s: setting final", __func__);
01839 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_FINAL, "", error))
01840 goto error_free_writer;
01841 }
01842
01843
01844 if (!_smlXmlAssemblerEndNode(assm, error))
01845 goto error_free_writer;
01846
01847
01848 if (!_smlXmlAssemblerEndNode(assm, error))
01849 goto error_free_writer;
01850
01851 if (xmlTextWriterEndDocument(assm->writer) < 0) {
01852 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer");
01853 goto error;
01854 }
01855
01856
01857 xmlFreeTextWriter(assm->writer);
01858 assm->writer = NULL;
01859
01860
01861
01862 *size = xmlBufferLength(buffer);
01863 *data = g_strndup((const char *) xmlBufferContent(buffer), *size);
01864 xmlBufferFree(buffer);
01865 if (end) {
01866 if (final && !assm->commands)
01867 *end = TRUE;
01868 else
01869 *end = FALSE;
01870 }
01871 smlTrace(TRACE_INTERNAL, "%s: Message Assembled: %s",
01872 __func__, VA_STRING(*data));
01873
01874 g_mutex_unlock(assm->mutex);
01875 smlTrace(TRACE_EXIT, "%s", __func__);
01876 return TRUE;
01877
01878 error_free_writer:
01879 xmlFreeTextWriter(assm->writer);
01880 assm->writer = NULL;
01881 error_free_buffer:
01882 xmlBufferFree(buffer);
01883 error:
01884 g_mutex_unlock(assm->mutex);
01885 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
01886 return FALSE;
01887 }
01888
01889 static unsigned int calc_list(GList *list)
01890 {
01891 unsigned int size = 0;
01892
01893 for (; list; list = list->next) {
01894 SmlXmlAssemblerCommand *cmd = list->data;
01895 size += 15;
01896 if (cmd->nodeType != SML_ASSEMBLER_NODE_CLOSE) {
01897 size += xmlBufferLength(cmd->buffer);
01898 if (cmd->children)
01899 size += calc_list(cmd->children);
01900 }
01901 }
01902
01903 return size;
01904 }
01905
01906 SmlBool smlXmlAssemblerRun(SmlXmlAssembler *assm, char **data, unsigned int *size, SmlBool *end, SmlBool final, unsigned int maxsize, SmlError **error)
01907 {
01908 CHECK_ERROR_REF
01909 SmlBool ans = smlXmlAssemblerRunFull(assm, data, size, end, final, TRUE, maxsize, error);
01910
01911 if (ans)
01912 smlLog("sent-%i.xml", *data, *size);
01913 else
01914 smlTrace(TRACE_ERROR, "%s - %s", __func__, smlErrorPrint(error));
01915
01916 return ans;
01917 }
01918
01919 unsigned int smlXmlAssemblerCheckSize(SmlXmlAssembler *assm, SmlBool headeronly, SmlError **error)
01920 {
01921 CHECK_ERROR_REF
01922 smlAssert(assm);
01923 SmlXmlAssemblerStatus *status = NULL;
01924 unsigned int size = 0;
01925
01926
01927 size += 20;
01928
01929
01930 if (assm->header_buffer)
01931 size += xmlBufferLength(assm->header_buffer);
01932
01933 if (!headeronly) {
01934
01935 GList *b = NULL;
01936 for (b = assm->statuses; b; b = b->next) {
01937 status = b->data;
01938 if (!status->buffer)
01939 break;
01940
01941 size += xmlBufferLength(status->buffer);
01942 }
01943
01944
01945 size += calc_list(assm->commands);
01946 }
01947
01948 return size;
01949 }
01950
01951 SmlBool smlXmlAssemblerNextCmdRef(SmlXmlAssembler *assm, unsigned int *cmdRef, unsigned int *msgRef)
01952 {
01953 smlAssert(assm);
01954 smlAssert(cmdRef);
01955 smlAssert(msgRef);
01956 SmlXmlAssemblerStatus *status = NULL;
01957
01958 GList *b = NULL;
01959 for (b = assm->statuses; b; b = b->next) {
01960 status = b->data;
01961 if (!status->buffer) {
01962 *cmdRef = status->cmdRef;
01963 *msgRef = status->msgRef;
01964 return TRUE;
01965 }
01966 }
01967
01968 return FALSE;
01969 }
01970
01978 SmlXmlAssembler *smlXmlAssemblerNew(SmlAssembler *assembler, SmlAssemblerFunctions *functions, SmlError **error)
01979 {
01980 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, assembler, functions, error);
01981 CHECK_ERROR_REF
01982
01983 SmlXmlAssembler *assm = smlTryMalloc0(sizeof(SmlXmlAssembler), error);
01984 if (!assm)
01985 goto error;
01986 assm->assembler = assembler;
01987 assm->mutex = g_mutex_new();
01988 if (!assm->mutex)
01989 goto error_mutex;
01990
01991 functions->start = (SmlAssemblerStartFunction)smlXmlAssemblerStart;
01992 functions->free = (SmlAssemblerFreeFunction)smlXmlAssemblerFree;
01993 functions->run = (SmlAssemblerRunFunction)smlXmlAssemblerRun;
01994 functions->end = (SmlAssemblerEndFunction)smlXmlAssemblerEnd;
01995 functions->add_header = (SmlAssemblerHeaderFunction)smlXmlAssemblerAddHeader;
01996 functions->start_cmd = (SmlAssemblerStartCommandFunction)smlXmlAssemblerStartCommand;
01997 functions->end_cmd = (SmlAssemblerEndCommandFunction)smlXmlAssemblerEndCommand;
01998 functions->rem_cmd = (SmlAssemblerRemCommandFunction)smlXmlAssemblerRemCommand;
01999 functions->add_status = (SmlAssemblerStatusFunction)smlXmlAssemblerAddStatus;
02000 functions->rem_status = (SmlAssemblerRemStatusFunction)smlXmlAssemblerRemStatus;
02001 functions->reserve_status = (SmlAssemblerReserveStatusFunction)smlXmlAssemblerReserveStatus;
02002 functions->missing_status = (SmlAssemblerStatusMissingFunction)smlXmlAssemblerMissingStatus;
02003 functions->check_size = (SmlAssemblerCheckFunction)smlXmlAssemblerCheckSize;
02004 functions->next_cmdref = (SmlAssemblerNextCmdRefFunction)smlXmlAssemblerNextCmdRef;
02005 functions->flush = (SmlAssemblerFlushFunction)smlXmlAssemblerFlush;
02006 functions->restore_cmds = (SmlAssemblerRestoreCommandsFunction)smlXmlAssemblerRestoreCommands;
02007
02008 smlTrace(TRACE_EXIT, "%s: %p", __func__, assm);
02009 return assm;
02010
02011 error_mutex:
02012 smlSafeFree((gpointer *)&assm);
02013 smlErrorSet(error, SML_ERROR_GENERIC, "%s - Cannot create new mutex.", __func__);
02014 error:
02015 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02016 return NULL;
02017 }
02018
02019 static SmlBool _smlXmlDevInfDataStoreAssembleRxTx(SmlXmlAssembler *assm, const char *element, const char *cttype, const char *version, SmlError **error)
02020 {
02021 smlTrace(TRACE_ENTRY, "%s(%p, %s, %s, %s, %p)", __func__, assm, VA_STRING(element), VA_STRING(cttype), VA_STRING(version), error);
02022 CHECK_ERROR_REF
02023 smlAssert(assm);
02024 smlAssert(element);
02025 smlAssert(cttype);
02026
02027 if (!_smlXmlAssemblerStartNode(assm, element, error))
02028 goto error;
02029
02030 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CTTYPE, cttype, error))
02031 goto error;
02032
02033 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERCT, version, error))
02034 goto error;
02035
02036 if (!_smlXmlAssemblerEndNode(assm, error))
02037 goto error;
02038
02039 smlTrace(TRACE_EXIT, "%s", __func__);
02040 return TRUE;
02041
02042 error:
02043 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02044 return FALSE;
02045 }
02046
02047 static SmlBool _smlXmlDevInfDataStoreAssembleCTCap(
02048 SmlXmlAssembler *assm,
02049 const SmlDevInfCTCap *ctcap,
02050 SmlBool flat,
02051 SmlError **error)
02052 {
02053 smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, assm, ctcap, error);
02054 CHECK_ERROR_REF
02055 smlAssert(assm);
02056 smlAssert(ctcap);
02057
02058 if (!flat)
02059 {
02060
02061 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CTCAP, error))
02062 goto error;
02063 }
02064
02065
02066 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_CTTYPE, ctcap->ct->cttype, error))
02067 goto error;
02068
02069
02070
02071
02072 if (!flat)
02073 {
02074 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERCT, ctcap->ct->verct, error))
02075 goto error;
02076 }
02077
02078
02079 GList *hprop = NULL;
02080 for (hprop = ctcap->properties; hprop; hprop = hprop->next)
02081 {
02082 SmlDevInfProperty *property = hprop->data;
02083
02084 if (!flat)
02085 {
02086
02087 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_PROPERTY, error))
02088 goto error;
02089 }
02090
02091
02092 if (property->propName != NULL &&
02093 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_PROPNAME, property->propName, error))
02094 goto error;
02095
02096
02097 if (property->dataType != NULL &&
02098 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATATYPE, property->dataType, error))
02099 goto error;
02100
02101
02102 if (property->maxOccur > 0 &&
02103 !_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXOCCUR, property->maxOccur, error))
02104 goto error;
02105
02106
02107 if (property->maxSize > 0) {
02108
02109 if (flat) {
02110 if (!_smlXmlAssemblerAddID(
02111 assm,
02112 SML_ELEMENT_SIZE,
02113 property->maxSize,
02114 error))
02115 goto error;
02116 } else {
02117 if (!_smlXmlAssemblerAddID(
02118 assm,
02119 SML_ELEMENT_MAXSIZE,
02120 property->maxSize,
02121 error))
02122 goto error;
02123 }
02124 }
02125
02126
02127 if (property->noTruncate)
02128 {
02129 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_NOTRUNCATE, error))
02130 goto error;
02131 if (!_smlXmlAssemblerEndNode(assm, error))
02132 goto error;
02133 }
02134
02135
02136 if (property->displayName != NULL &&
02137 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, property->displayName, error))
02138 goto error;
02139
02140
02141 GList *hvalue = NULL;
02142 for (hvalue = property->valEnums; hvalue; hvalue = hvalue->next)
02143 {
02144 char *valEnum = hvalue->data;
02145
02146
02147 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VALENUM, valEnum, error))
02148 goto error;
02149
02150 }
02151
02152
02153 GList *hparam = NULL;
02154 for (hparam = property->propParams; hparam; hparam = hparam->next)
02155 {
02156 SmlDevInfPropParam *param = hparam->data;
02157
02158 if (!flat)
02159 {
02160
02161 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_PROPPARAM, error))
02162 goto error;
02163 }
02164
02165
02166 if (param->paramName != NULL &&
02167 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_PARAMNAME, param->paramName, error))
02168 goto error;
02169
02170
02171 if (param->dataType != NULL &&
02172 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DATATYPE, param->dataType, error))
02173 goto error;
02174
02175
02176 if (param->displayName != NULL &&
02177 !_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, param->displayName, error))
02178 goto error;
02179
02180
02181 hvalue = NULL;
02182 for (hvalue = param->valEnums; hvalue; hvalue = hvalue->next)
02183 {
02184 char *valEnum = hvalue->data;
02185
02186
02187 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VALENUM, valEnum, error))
02188 goto error;
02189
02190 }
02191
02192 if (!flat)
02193 {
02194
02195 if (!_smlXmlAssemblerEndNode(assm, error))
02196 goto error;
02197 }
02198
02199 }
02200
02201 if (!flat)
02202 {
02203
02204 if (!_smlXmlAssemblerEndNode(assm, error))
02205 goto error;
02206 }
02207
02208 }
02209
02210 if (!flat)
02211 {
02212
02213 if (!_smlXmlAssemblerEndNode(assm, error))
02214 goto error;
02215 }
02216
02217 smlTrace(TRACE_EXIT, "%s", __func__);
02218 return TRUE;
02219
02220 error:
02221 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02222 return FALSE;
02223 }
02224
02225 static SmlBool _smlXmlDevInfDataStoreAssemble(
02226 SmlXmlAssembler *assm,
02227 SmlDevInfDataStore *datastore,
02228 SmlDevInf *devinf,
02229 SmlError **error)
02230 {
02231 smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, assm, datastore, devinf, error);
02232 CHECK_ERROR_REF
02233 smlAssert(datastore);
02234 smlAssert(assm);
02235
02236 GList *contentTypes = NULL;
02237
02238 if (!datastore->sourceref) {
02239 smlErrorSet(error, SML_ERROR_GENERIC, "Missing sourceref");
02240 goto error;
02241 }
02242
02243 if (!datastore->rxPrefContentType) {
02244 smlErrorSet(error, SML_ERROR_GENERIC, "Missing rx-pref");
02245 goto error;
02246 }
02247
02248 if (!datastore->txPrefContentType) {
02249 smlErrorSet(error, SML_ERROR_GENERIC, "Missing tx-pref");
02250 goto error;
02251 }
02252
02253 if (!datastore->synccap) {
02254 smlErrorSet(error, SML_ERROR_GENERIC, "No sync capabilities");
02255 goto error;
02256 }
02257
02258
02259 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DATASTORE, error))
02260 goto error;
02261
02262
02263 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SOURCEREF, datastore->sourceref, error))
02264 goto error;
02265
02266
02267 if (datastore->displayname) {
02268 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DISPLAYNAME, datastore->displayname, error))
02269 goto error;
02270 }
02271
02272
02273 if (datastore->maxGUIDSize) {
02274 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXGUIDSIZE, datastore->maxGUIDSize, error))
02275 goto error;
02276 }
02277
02278
02279 if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_RXPREF, datastore->rxPrefContentType, datastore->rxPrefVersion, error))
02280 goto error;
02281 contentTypes = g_list_append(
02282 contentTypes,
02283 smlDevInfNewContentType(
02284 datastore->rxPrefContentType,
02285 datastore->rxPrefVersion, error));
02286
02287
02288 if (datastore->rx) {
02289 GList *hl;
02290 for (hl = datastore->rx; hl; hl = hl->next)
02291 {
02292 SmlDevInfContentType *ct = hl->data;
02293 if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_RX, ct->cttype, ct->verct, error))
02294 goto error;
02295 contentTypes = g_list_append(
02296 contentTypes,
02297 smlDevInfNewContentType(ct->cttype, ct->verct, error));
02298 }
02299 }
02300
02301
02302 if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_TXPREF, datastore->txPrefContentType, datastore->txPrefVersion, error))
02303 goto error;
02304 contentTypes = g_list_append(
02305 contentTypes,
02306 smlDevInfNewContentType(
02307 datastore->txPrefContentType,
02308 datastore->txPrefVersion, error));
02309
02310
02311 if (datastore->tx) {
02312 GList *hl;
02313 for (hl = datastore->tx; hl; hl = hl->next)
02314 {
02315 SmlDevInfContentType *ct = hl->data;
02316 if (!_smlXmlDevInfDataStoreAssembleRxTx(assm, SML_ELEMENT_TX, ct->cttype, ct->verct, error))
02317 goto error;
02318 contentTypes = g_list_append(
02319 contentTypes,
02320 smlDevInfNewContentType(ct->cttype, ct->verct, error));
02321 }
02322 }
02323
02324
02325 if (devinf->version >= SML_DEVINF_VERSION_12)
02326 {
02327 GList *hct = NULL;
02328 for (hct = contentTypes; hct; hct = hct->next) {
02329 SmlDevInfContentType *ct = hct->data;
02330 const SmlDevInfCTCap *ctcap = smlDevInfGetCTCap(devinf, ct);
02331 if (ctcap != NULL)
02332 {
02333
02334
02335 if (!_smlXmlDevInfDataStoreAssembleCTCap(assm, ctcap, FALSE, error))
02336 goto error;
02337 } else {
02338
02339
02340
02341 smlTrace(TRACE_INTERNAL, "%s: found a content type (%s %d) without CTCap",
02342 __func__, VA_STRING(ct->cttype), ct->verct);
02343 }
02344 }
02345 }
02346
02347
02348 while(contentTypes)
02349 {
02350 SmlDevInfContentType *ct = contentTypes->data;
02351 contentTypes = g_list_remove(contentTypes, ct);
02352 smlDevInfFreeContentType(ct);
02353 }
02354
02355
02356 if (datastore->maxmem || datastore->maxid) {
02357
02358 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_DSMEM, error))
02359 goto error;
02360
02361
02362 if (datastore->sharedMem) {
02363 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SHAREDMEM, "", error))
02364 goto error;
02365 }
02366
02367
02368 if (datastore->maxid) {
02369 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXID, datastore->maxid, error))
02370 goto error;
02371 }
02372
02373
02374 if (datastore->maxmem) {
02375 if (!_smlXmlAssemblerAddID(assm, SML_ELEMENT_MAXMEM, datastore->maxmem, error))
02376 goto error;
02377 }
02378
02379
02380 if (!_smlXmlAssemblerEndNode(assm, error))
02381 goto error;
02382 }
02383
02384
02385 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_SYNCCAP, error))
02386 goto error;
02387
02388
02389 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_TWO_WAY)) {
02390 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "1", error))
02391 goto error;
02392 }
02393 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SLOW_SYNC)) {
02394 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "2", error))
02395 goto error;
02396 }
02397 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_CLIENT)) {
02398 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "3", error))
02399 goto error;
02400 }
02401 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_REFRESH_FROM_CLIENT)) {
02402 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "4", error))
02403 goto error;
02404 }
02405 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_ONE_WAY_FROM_SERVER)) {
02406 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "5", error))
02407 goto error;
02408 }
02409 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_REFRESH_FROM_SERVER)) {
02410 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "6", error))
02411 goto error;
02412 }
02413 if (smlDevInfDataStoreGetSyncCap(datastore, SML_DEVINF_SYNCTYPE_SERVER_ALERTED_SYNC)) {
02414 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SYNCTYPE, "7", error))
02415 goto error;
02416 }
02417
02418
02419 if (!_smlXmlAssemblerEndNode(assm, error))
02420 goto error;
02421
02422
02423 if (!_smlXmlAssemblerEndNode(assm, error))
02424 goto error;
02425
02426 smlTrace(TRACE_EXIT, "%s", __func__);
02427 return TRUE;
02428
02429 error:
02430 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02431 return FALSE;
02432 }
02433
02434 SmlBool smlXmlDevInfAssemble(SmlDevInf *devinf, SmlDevInfVersion version, char **data, unsigned int *size, SmlError **error)
02435 {
02436 smlTrace(TRACE_ENTRY, "%s(%p, %i, %p, %p, %p)", __func__, devinf, version, data, size, error);
02437 CHECK_ERROR_REF
02438 smlAssert(devinf);
02439 smlAssert(data);
02440 smlAssert(size);
02441
02442
02443
02444 smlTrace(TRACE_INTERNAL, "%s: devinf version: %i, version: %i", __func__, devinf->version, version);
02445 if (devinf->version == SML_DEVINF_VERSION_UNKNOWN)
02446 devinf->version = version;
02447 if (version == SML_DEVINF_VERSION_UNKNOWN)
02448 version = devinf->version;
02449 smlAssert(devinf->version == version);
02450
02451 SmlXmlAssembler *assm = smlTryMalloc0(sizeof(SmlXmlAssembler), error);
02452 if (!assm)
02453 goto error;
02454
02455
02456 xmlBuffer *buffer = xmlBufferCreateSize(BUFFER_SIZE);
02457 if (!buffer) {
02458 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new buffer");
02459 goto error_free_assm;
02460 }
02461
02462 assm->writer = xmlNewTextWriterMemory(buffer, 0);
02463 if (!assm->writer) {
02464 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to create new writer");
02465 goto error_free_buffer;
02466 }
02467
02468
02469 if (!_smlXmlAssemblerStartNodeNS(assm, SML_ELEMENT_DEVINF, SML_NAMESPACE_DEVINF, error))
02470 goto error_free_writer;
02471
02472
02473 switch (version) {
02474 case SML_DEVINF_VERSION_12:
02475 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.2", error))
02476 goto error_free_writer;
02477 break;
02478 case SML_DEVINF_VERSION_11:
02479 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.1", error))
02480 goto error_free_writer;
02481 break;
02482 case SML_DEVINF_VERSION_10:
02483 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_VERDTD, "1.0", error))
02484 goto error_free_writer;
02485 break;
02486 case SML_DEVINF_VERSION_UNKNOWN:
02487 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown devinf version");
02488 goto error_free_writer;
02489 break;
02490 }
02491
02492
02493 if (devinf->manufacturer) {
02494 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MAN, devinf->manufacturer, error))
02495 goto error_free_writer;
02496 }
02497
02498
02499 if (devinf->model) {
02500 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_MOD, devinf->model, error))
02501 goto error_free_writer;
02502 }
02503
02504
02505 if (devinf->oem) {
02506 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_OEM, devinf->oem, error))
02507 goto error_free_writer;
02508 }
02509
02510
02511 if (devinf->firmwareVersion) {
02512 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_FWV, devinf->firmwareVersion, error))
02513 goto error_free_writer;
02514 }
02515
02516
02517 if (devinf->softwareVersion) {
02518 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SWV, devinf->softwareVersion, error))
02519 goto error_free_writer;
02520 }
02521
02522
02523 if (devinf->hardwareVersion) {
02524 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_HWV, devinf->hardwareVersion, error))
02525 goto error_free_writer;
02526 }
02527
02528
02529 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DEVID, devinf->devid, error))
02530 goto error_free_writer;
02531
02532
02533 const char *devtype = smlDevInfDevTypeToString(devinf->devtyp, error);
02534 if (!devtype)
02535 goto error_free_writer;
02536
02537 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_DEVTYPE, devtype, error))
02538 goto error_free_writer;
02539
02540
02541 if (devinf->supportsUTC && version != SML_DEVINF_VERSION_10) {
02542 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_UTC, "", error))
02543 goto error_free_writer;
02544 }
02545
02546
02547 if (devinf->supportsLargeObjs && version != SML_DEVINF_VERSION_10) {
02548 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SUPPORTLARGEOBJS, "", error))
02549 goto error_free_writer;
02550 }
02551
02552
02553 if (devinf->supportsNumberOfChanges && version != SML_DEVINF_VERSION_10) {
02554 if (!_smlXmlAssemblerAddString(assm, SML_ELEMENT_SUPPORTNUMBEROFCHANGES, "", error))
02555 goto error_free_writer;
02556 }
02557
02558
02559 GList *d = NULL;
02560 for (d = devinf->datastores; d; d = d->next) {
02561 SmlDevInfDataStore *datastore = d->data;
02562 if (!_smlXmlDevInfDataStoreAssemble(assm, datastore, devinf, error))
02563 goto error_free_writer;
02564 }
02565
02566
02567 if (
02568 devinf->version < SML_DEVINF_VERSION_12 &&
02569 devinf->ctcaps) {
02570 if (!_smlXmlAssemblerStartNode(assm, SML_ELEMENT_CTCAP, error))
02571 goto error_free_writer;
02572
02573 for (d = devinf->ctcaps; d; d = d->next) {
02574 SmlDevInfCTCap *ctcap = d->data;
02575
02576 if (!_smlXmlDevInfDataStoreAssembleCTCap(assm, ctcap, TRUE, error))
02577 goto error_free_writer;
02578 }
02579
02580 if (!_smlXmlAssemblerEndNode(assm, error))
02581 goto error_free_writer;
02582 }
02583
02584
02585 if (!_smlXmlAssemblerEndNode(assm, error))
02586 goto error_free_writer;
02587
02588
02589 if (xmlTextWriterEndDocument(assm->writer) < 0) {
02590 smlErrorSet(error, SML_ERROR_GENERIC, "Unable to end writer");
02591 goto error_free_writer;
02592 }
02593
02594 xmlFreeTextWriter(assm->writer);
02595 assm->writer = NULL;
02596
02597 *size = xmlBufferLength(buffer);
02598 *data = g_strndup((const char *) xmlBufferContent(buffer), *size);
02599
02600 xmlBufferFree(buffer);
02601
02602 smlSafeFree((gpointer *)&assm);
02603
02604 smlTrace(TRACE_INTERNAL, "Message Assembled: %s", *data);
02605
02606 smlTrace(TRACE_EXIT, "%s", __func__);
02607 return TRUE;
02608
02609 error_free_writer:
02610 xmlFreeTextWriter(assm->writer);
02611 assm->writer = NULL;
02612 error_free_buffer:
02613 xmlBufferFree(buffer);
02614 error_free_assm:
02615 smlSafeFree((gpointer *)&assm);
02616 error:
02617 g_warning("%s: %s", __func__, smlErrorPrint(error));
02618 smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
02619 return FALSE;
02620 }
02621
02622 void smlXmlAssemblerRestoreCommands(SmlXmlAssembler *assm)
02623 {
02624 smlTrace(TRACE_ENTRY, "%s", __func__);
02625 smlAssert(assm->commands == NULL);
02626
02627 assm->commands = assm->last_commands;
02628 assm->last_commands = NULL;
02629
02630 smlTrace(TRACE_EXIT, "%s", __func__);
02631 }
02632