b58920903d60801327536bd7cf10dbc1673c58e1
[platform/upstream/syncevolution.git] / src / synthesis / src / syncml_tk / src / sml / xlt / all / xltdevinf.c
1 /**
2  * @file
3  * DeviceInf DTD related functions for the en-/decoder
4  *
5  * @target_system   all
6  * @target_os       all
7  */
8
9 /*
10  * Copyright Notice
11  * Copyright (c) Ericsson, IBM, Lotus, Matsushita Communication
12  * Industrial Co., Ltd., Motorola, Nokia, Openwave Systems, Inc.,
13  * Palm, Inc., Psion, Starfish Software, Symbian, Ltd. (2001).
14  * All Rights Reserved.
15  * Implementation of all or part of any Specification may require
16  * licenses under third party intellectual property rights,
17  * including without limitation, patent rights (such a third party
18  * may or may not be a Supporter). The Sponsors of the Specification
19  * are not responsible and shall not be held responsible in any
20  * manner for identifying or failing to identify any or all such
21  * third party intellectual property rights.
22  *
23  * THIS DOCUMENT AND THE INFORMATION CONTAINED HEREIN ARE PROVIDED
24  * ON AN "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND AND ERICSSON, IBM,
25  * LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO. LTD, MOTOROLA,
26  * NOKIA, PALM INC., PSION, STARFISH SOFTWARE AND ALL OTHER SYNCML
27  * SPONSORS DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
28  * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
29  * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
30  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
31  * SHALL ERICSSON, IBM, LOTUS, MATSUSHITA COMMUNICATION INDUSTRIAL CO.,
32  * LTD, MOTOROLA, NOKIA, PALM INC., PSION, STARFISH SOFTWARE OR ANY
33  * OTHER SYNCML SPONSOR BE LIABLE TO ANY PARTY FOR ANY LOSS OF
34  * PROFITS, LOSS OF BUSINESS, LOSS OF USE OF DATA, INTERRUPTION OF
35  * BUSINESS, OR FOR DIRECT, INDIRECT, SPECIAL OR EXEMPLARY, INCIDENTAL,
36  * PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH
37  * THIS DOCUMENT OR THE INFORMATION CONTAINED HEREIN, EVEN IF ADVISED
38  * OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE.
39  *
40  * The above notice and this paragraph must be included on all copies
41  * of this document that are made.
42  *
43  */
44 #include "syncml_tk_prefix_file.h" // %%% luz: needed for precompiled headers in eVC++
45
46 #include "define.h"
47 #ifdef __USE_DEVINF__
48
49 #include "smldevinfdtd.h"
50 #include "smlmetinfdtd.h"
51 #include "xlttags.h"
52 #include "xltdevinf.h"
53 #include "xlttagtbl.h"
54 #include "xltenc.h"
55 #include "xltencwbxml.h"
56
57 #include <libstr.h>
58 #include <smlerr.h>
59 #include <smldtd.h>
60 #include <libmem.h>
61 #include <libutil.h>
62 #include <mgrutil.h>
63
64 /* decoder callbacks */
65 Ret_t buildDevInfDevInfContent(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem);
66 Ret_t buildDevInfCtcap(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem, Boolean_t datastoreLocal);
67
68
69 Ret_t buildDevInfDevInfCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
70     XltDecScannerPtr_t pScanner;
71     SmlDevInfDevInfPtr_t pElem = NULL;
72     Ret_t rc;
73
74     pScanner = pDecoder->scanner;
75
76     if (*ppElem != NULL)
77         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDevInfCmd");
78
79     if (IS_EMPTY(pScanner->curtok)) {
80         *ppElem = pElem;
81         return SML_ERR_OK;
82     }
83
84     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
85         smlLibFree(pElem);
86         return rc;
87     }
88
89     switch (pScanner->curtok->tagid) {
90         case TN_DEVINF_DEVINF:
91             rc = buildDevInfDevInfContent(pDecoder, (VoidPtr_t)&pElem);
92             break;
93         default:
94             rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDevInfCmd");
95     }
96     if (rc != SML_ERR_OK) {
97         smlLibFree(pElem);
98         return rc;
99     }
100     *ppElem = pElem;
101
102     return SML_ERR_OK;
103 }
104
105 Ret_t buildDevInfDevInfContent(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
106     XltDecScannerPtr_t pScanner;
107     SmlDevInfDevInfPtr_t pElem;
108     Ret_t rc;
109
110     pScanner = pDecoder->scanner;
111
112     if (*ppElem != NULL)
113         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDevInfContent");
114
115     if ((pElem = (SmlDevInfDevInfPtr_t)smlLibMalloc(sizeof(SmlDevInfDevInf_t))) == NULL)
116         return SML_ERR_NOT_ENOUGH_SPACE;
117     smlLibMemset(pElem, 0, sizeof(SmlDevInfDevInf_t));
118
119     if (IS_EMPTY(pScanner->curtok)) {
120         *ppElem = pElem;
121         return SML_ERR_OK;
122     }
123
124     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
125         smlLibFree(pElem);
126         return rc;
127     }
128
129     while (pScanner->curtok->type != TOK_TAG_END) {
130         switch (pScanner->curtok->tagid) {
131             case TN_DEVINF_VERDTD:
132                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->verdtd);
133                 break;
134             case TN_DEVINF_MAN:
135                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->man);
136                 break;
137             case TN_DEVINF_MOD:
138                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->mod);
139                 break;
140             case TN_DEVINF_OEM:
141                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->oem);
142                 break;
143             case TN_DEVINF_FWV:
144                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->fwv);
145                 break;
146             case TN_DEVINF_SWV:
147                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->swv);
148                 break;
149             case TN_DEVINF_HWV:
150                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->hwv);
151                 break;
152             case TN_DEVINF_DEVID:
153                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->devid);
154                 break;
155             case TN_DEVINF_DEVTYP:
156                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->devtyp);
157                 break;
158             case TN_DEVINF_DATASTORE:
159                 rc = buildDevInfDataStoreList(pDecoder, (VoidPtr_t)&pElem->datastore);
160                 break;
161             case TN_DEVINF_CTCAP:
162                 rc = buildDevInfCtcap(pDecoder, (VoidPtr_t)&pElem->ctcap,FALSE);  // CTCap which is global in devInf itself (pre-DS 1.2)
163                 break;
164             case TN_DEVINF_EXT:
165                 rc = buildDevInfExtList(pDecoder, (VoidPtr_t)&pElem->ext);
166                 break;
167             /* SCTSTK - 18/03/2002 S.H. 2002-04-05 : SyncML 1.1 */
168             case TN_DEVINF_UTC:
169                 pElem->flags |= SmlDevInfUTC_f;
170                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
171                 break;
172             case TN_DEVINF_NOFM:
173                 pElem->flags |= SmlDevInfNOfM_f;
174                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
175                 break;
176             case TN_DEVINF_LARGEOBJECT:
177                 pElem->flags |= SmlDevInfLargeObject_f;
178                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
179                 break;
180             default:
181                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDevInfContent");
182         }
183         if (rc != SML_ERR_OK) {
184             smlLibFree(pElem);
185             return rc;
186         }
187         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
188             smlLibFree(pElem);
189             return rc;
190         }
191     }
192     *ppElem = pElem;
193
194     return SML_ERR_OK;
195 }
196
197
198 static Ret_t buildDevInfFilterCapList(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem)
199 {
200   SmlDevInfFilterCapListPtr_t  *ppListElem   = NULL;
201   SmlDevInfFilterCapListPtr_t  pFiltercap    = NULL;
202   SmlPcdataListPtr_t           *ppList       = NULL;
203   SmlPcdataListPtr_t           pList         = NULL;
204   XltDecScannerPtr_t           pScanner      = pDecoder->scanner;
205
206   Ret_t rc;
207
208   // if empty, that's ok and treated as NOP:  <FilterCap/>
209   if (IS_EMPTY(pScanner->curtok)) {
210     return SML_ERR_OK;
211   }
212   // get next token
213   if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
214     return rc;
215   }
216   // get pointer to where we'd insert the next list element
217   ppListElem   = (SmlDevInfFilterCapListPtr_t *) ppElem;
218   while (*ppListElem!=NULL) {
219     ppListElem = &((*ppListElem)->next);
220   }
221   // create new list element now
222   pFiltercap = (SmlDevInfFilterCapListPtr_t)smlLibMalloc(sizeof(SmlDevInfFilterCapList_t));
223   if (pFiltercap == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
224   smlLibMemset(pFiltercap, 0, sizeof(SmlDevInfFilterCapList_t));
225   pFiltercap->data = (SmlDevInfFilterCapPtr_t)smlLibMalloc(sizeof(SmlDevInfFilterCap_t));
226   if (pFiltercap->data == NULL) {
227     smlFreeDevInfFilterCapList(pFiltercap);
228     return SML_ERR_NOT_ENOUGH_SPACE;
229   }
230   smlLibMemset(pFiltercap->data, 0, sizeof(SmlDevInfFilterCap_t));
231   // scan until we hit end of enclosure (</FilterCap>)
232   while (pScanner->curtok->type != TOK_TAG_END) {
233     // process tags
234     switch (pScanner->curtok->tagid) {
235       /* PCDATA elements */
236       case TN_DEVINF_CTTYPE:
237         rc = buildPCData(pDecoder, (VoidPtr_t)&pFiltercap->data->cttype);
238         break;
239       case TN_DEVINF_VERCT:
240         rc = buildPCData(pDecoder, (VoidPtr_t)&pFiltercap->data->verct);
241         break;
242       case TN_DEVINF_FILTERKEYWORD:
243         ppList = &pFiltercap->data->filterkeyword;
244         goto keywordOrPropname;
245       case TN_DEVINF_PROPNAME:
246         ppList = &pFiltercap->data->propname;
247         goto keywordOrPropname;
248       keywordOrPropname:
249         // find last existing valenum
250         while (*ppList!=NULL)
251           ppList=&((*ppList)->next);
252         // create new list element
253         pList = (SmlPcdataListPtr_t)smlLibMalloc(sizeof(SmlPcdataList_t));
254         if (pList == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
255         smlLibMemset(pList, 0, sizeof(SmlPcdataList_t));
256         // insert contents
257         rc = buildPCData(pDecoder, (VoidPtr_t)&pList->data);
258         if (rc==SML_ERR_OK) {
259           // ok, add element to list
260           *ppList = pList;
261           ppList = &(pList->next);
262         }
263         else
264           smlFreePcdataList(pList); // invalid, get rid of it
265         break;
266       default:
267         rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfFilterCapList");
268     }
269     if (rc != SML_ERR_OK) {
270       smlFreeDevInfFilterCapList(pFiltercap);
271       return rc;
272     }
273     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
274       smlFreeDevInfFilterCapList(pFiltercap);
275       return rc;
276     }
277   } /* while we do not see an end tag */
278   // link into list
279   *ppListElem = pFiltercap;
280   // set elem link to where we must link in next element
281   ppListElem = &(pFiltercap->next);
282   // done ok
283   return SML_ERR_OK;
284 }
285
286
287 Ret_t buildDevInfDataStoreCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
288     XltDecScannerPtr_t pScanner;
289     SmlDevInfDatastorePtr_t pElem;
290     Ret_t rc;
291
292     pScanner = pDecoder->scanner;
293
294     if (*ppElem != NULL)
295         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDataStoreCmd");
296
297     if ((pElem = (SmlDevInfDatastorePtr_t)smlLibMalloc(sizeof(SmlDevInfDatastore_t))) == NULL)
298         return SML_ERR_NOT_ENOUGH_SPACE;
299     smlLibMemset(pElem, 0, sizeof(SmlDevInfDatastore_t));
300
301     if (IS_EMPTY(pScanner->curtok)) {
302         *ppElem = pElem;
303         return SML_ERR_OK;
304     }
305
306     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
307         smlLibFree(pElem);
308         return rc;
309     }
310
311     while (pScanner->curtok->type != TOK_TAG_END) {
312         switch (pScanner->curtok->tagid) {
313             /* PCDATA elements */
314             case TN_DEVINF_SOURCEREF:
315                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->sourceref);
316                 break;
317             case TN_DEVINF_DISPLAYNAME:
318                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->displayname);
319                 break;
320             case TN_DEVINF_MAXGUIDSIZE:
321                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->maxguidsize);
322                 break;
323             /* other elements */
324             case TN_DEVINF_RXPREF:
325                 if (pElem->rxpref!=NULL) {
326                   // we already have a RxPref - simply ignore further ones
327                   // (in DS 1.2, some implementations send an other rx-pref for the folder object apart from the main type)
328                   SmlDevInfXmitPtr_t dummyP = NULL;
329                   rc = buildDevInfXmitCmd(pDecoder, (VoidPtr_t)&dummyP);
330                   smlFreeDevInfXmit(dummyP); // simply discard after parsing
331                 }
332                 else
333                   rc = buildDevInfXmitCmd(pDecoder, (VoidPtr_t)&pElem->rxpref);
334                 break;
335             case TN_DEVINF_TXPREF:
336                 if (pElem->txpref!=NULL) {
337                   // we already have a txpref - simply ignore further ones
338                   // (in DS 1.2, some implementations send an other tx-pref for the folder object apart from the main type)
339                   SmlDevInfXmitPtr_t dummyP = NULL;
340                   rc = buildDevInfXmitCmd(pDecoder, (VoidPtr_t)&dummyP);
341                   smlFreeDevInfXmit(dummyP); // simply discard after parsing
342                 }
343                 else
344                   rc = buildDevInfXmitCmd(pDecoder, (VoidPtr_t)&pElem->txpref);
345                 break;
346             case TN_DEVINF_RX:
347                 rc = buildDevInfXmitList(pDecoder, (VoidPtr_t)&pElem->rx);
348                 break;
349             case TN_DEVINF_TX:
350                 rc = buildDevInfXmitList(pDecoder, (VoidPtr_t)&pElem->tx);
351                 break;
352             case TN_DEVINF_CTCAP:
353                 rc = buildDevInfCtcap(pDecoder, (VoidPtr_t)&pElem->ctcap,TRUE); // CTCap which is local to datastore (DS 1.2 style)
354                 break;
355             case TN_DEVINF_DSMEM:
356                 rc = buildDevInfDSMemCmd(pDecoder, (VoidPtr_t)&pElem->dsmem);
357                 break;
358             case TN_DEVINF_SYNCCAP:
359                 rc = buildDevInfSyncCapCmd(pDecoder, (VoidPtr_t)&pElem->synccap);
360                 break;
361
362
363
364             /* SyncML DS 1.2, Synthesis/luz 2005-08-25 */
365             case TN_DEVINF_FILTERCAP:
366                 rc = buildDevInfFilterCapList(pDecoder, (VoidPtr_t)&pElem->filtercap);
367                 break;
368             case TN_DEVINF_FILTERRX:
369                 rc = buildDevInfXmitList(pDecoder, (VoidPtr_t)&pElem->filterrx);
370                 break;
371             case TN_DEVINF_HIERARCHICAL:
372                 pElem->flags |= SmlDevInfHierarchical_f;
373                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
374                 break;
375             case TN_DEVINF_FIELDLEVEL:
376                 pElem->flags |= SmlDevInfFieldLevel_f;
377                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
378                 break;
379
380             default:
381                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDataStoreCmd");
382         }
383         if (rc != SML_ERR_OK) {
384             smlLibFree(pElem);
385             return rc;
386         }
387         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
388             smlLibFree(pElem);
389             return rc;
390         }
391     }
392     *ppElem = pElem;
393
394     return SML_ERR_OK;
395 }
396
397 Ret_t buildDevInfXmitCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
398     XltDecScannerPtr_t pScanner;
399     SmlDevInfXmitPtr_t pXmit;
400     Ret_t rc;
401
402     pScanner = pDecoder->scanner;
403
404     if (*ppElem != NULL)
405         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfXmitCmd");
406
407     if ((pXmit = (SmlDevInfXmitPtr_t)smlLibMalloc(sizeof(SmlDevInfXmit_t))) == NULL)
408         return SML_ERR_NOT_ENOUGH_SPACE;
409     smlLibMemset(pXmit, 0, sizeof(SmlDevInfXmit_t));
410
411     if (IS_EMPTY(pScanner->curtok)) {
412         *ppElem = pXmit;
413         return SML_ERR_OK;
414     }
415
416     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
417         smlLibFree(pXmit);
418         return rc;
419     }
420
421     while (pScanner->curtok->type != TOK_TAG_END) {
422         switch (pScanner->curtok->tagid) {
423             /* PCDATA elements */
424             case TN_DEVINF_CTTYPE:
425                 rc = buildPCData(pDecoder, (VoidPtr_t)&pXmit->cttype);
426                 break;
427             case TN_DEVINF_VERCT:
428                 rc = buildPCData(pDecoder, (VoidPtr_t)&pXmit->verct);
429                 break;
430             default:
431                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfXmitCmd");
432         }
433         if (rc != SML_ERR_OK) {
434             smlLibFree(pXmit);
435             return rc;
436         }
437         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
438             smlLibFree(pXmit);
439             return rc;
440         }
441     }
442     *ppElem = pXmit;
443
444     return SML_ERR_OK;
445 }
446
447 Ret_t buildDevInfXmitList(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
448     SmlDevInfXmitListPtr_t pElem = NULL, pPrev = NULL;
449
450     pElem = (SmlDevInfXmitListPtr_t) *ppElem;
451
452     /* advance to the end of the list, and create ther an empty list element */
453     while (pElem != NULL) {
454       pPrev = pElem;
455       pElem = pPrev->next;
456     }
457     if ((pElem = (SmlDevInfXmitListPtr_t)smlLibMalloc(sizeof(SmlDevInfXmitList_t))) == NULL)
458         return SML_ERR_NOT_ENOUGH_SPACE;
459     smlLibMemset(pElem, 0, sizeof(SmlDevInfXmitList_t));
460     if (pPrev != NULL) /* we already had some entries in the list */
461       pPrev->next = pElem;
462     else /* nope we created a new list */
463       *ppElem = pElem;
464     pElem->data = NULL;
465     /* at this point pElem should point to an valid list element */
466     return buildDevInfXmitCmd(pDecoder, (VoidPtr_t)&pElem->data);
467 }
468
469 Ret_t buildDevInfDataStoreList(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
470     SmlDevInfDatastoreListPtr_t pElem = NULL, pPrev = NULL;
471
472     pElem = (SmlDevInfDatastoreListPtr_t) *ppElem;
473
474     /* advance to the end of the list, and create ther an empty list element */
475     while (pElem != NULL) {
476       pPrev = pElem;
477       pElem = pPrev->next;
478     }
479     if ((pElem = (SmlDevInfDatastoreListPtr_t)smlLibMalloc(sizeof(SmlDevInfDatastoreList_t))) == NULL)
480         return SML_ERR_NOT_ENOUGH_SPACE;
481     smlLibMemset(pElem, 0, sizeof(SmlDevInfDatastoreList_t));
482     if (pPrev != NULL) /* we already had some entries in the list */
483       pPrev->next = pElem;
484     else /* nope we created a new list */
485       *ppElem = pElem;
486     pElem->data = NULL;
487     /* at this point pElem should point to an valid list element */
488     return buildDevInfDataStoreCmd(pDecoder, (VoidPtr_t)&pElem->data);
489 }
490
491 Ret_t buildDevInfExtList(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
492     SmlDevInfExtListPtr_t pElem = NULL, pPrev = NULL;
493
494     pElem = (SmlDevInfExtListPtr_t) *ppElem;
495
496     /* advance to the end of the list, and create ther an empty list element */
497     while (pElem != NULL) {
498       pPrev = pElem;
499       pElem = pPrev->next;
500     }
501     if ((pElem = (SmlDevInfExtListPtr_t)smlLibMalloc(sizeof(SmlDevInfExtList_t))) == NULL)
502         return SML_ERR_NOT_ENOUGH_SPACE;
503     smlLibMemset(pElem, 0, sizeof(SmlDevInfExtList_t));
504     if (pPrev != NULL) /* we already had some entries in the list */
505       pPrev->next = pElem;
506     else /* nope we created a new list */
507       *ppElem = pElem;
508     pElem->data = NULL;
509     /* at this point pElem should point to an valid list element */
510     return buildDevInfExtCmd(pDecoder, (VoidPtr_t)&pElem->data);
511 }
512
513
514 /// @brief scans common elements of Properties and PropParams
515 /// @return SML_ERR_XLT_INVAL_PROTO_ELEM if unknown tag is encountered
516 static Ret_t scanPropOrParamElement(XltDecoderPtr_t pDecoder, SmlDevInfCTDataPtr_t pPropOrParam)
517 {
518   SmlPcdataListPtr_t *ppValenums = &(pPropOrParam->valenum);
519   SmlPcdataListPtr_t pValenum;
520   XltDecScannerPtr_t pScanner = pDecoder->scanner;
521   Ret_t rc;
522
523   // process tags
524   switch (pScanner->curtok->tagid) {
525     case TN_DEVINF_DISPLAYNAME:
526       rc = buildPCData(pDecoder, (VoidPtr_t)&pPropOrParam->dname);
527       break;
528     case TN_DEVINF_DATATYPE:
529       rc = buildPCData(pDecoder, (VoidPtr_t)&pPropOrParam->datatype);
530       break;
531     case TN_DEVINF_MAXSIZE:
532     case TN_DEVINF_SIZE:
533       rc = buildPCData(pDecoder, (VoidPtr_t)&pPropOrParam->maxsize);
534       break;
535     case TN_DEVINF_MAXOCCUR:
536       rc = buildPCData(pDecoder, (VoidPtr_t)&pPropOrParam->maxoccur);
537       break;
538     /* Flags */
539     case TN_DEVINF_NOTRUNCATE:
540       pPropOrParam->flags |= SmlDevInfNoTruncate_f;
541       rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
542       break;
543     /* Valenum* */
544     case TN_DEVINF_VALENUM:
545       // find last existing valenum
546       while (*ppValenums!=NULL)
547         ppValenums=&((*ppValenums)->next);
548       // create new list element
549       pValenum = (SmlPcdataListPtr_t)smlLibMalloc(sizeof(SmlPcdataList_t));
550       if (pValenum == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
551       smlLibMemset(pValenum, 0, sizeof(SmlPcdataList_t));
552       // insert contents
553       rc = buildPCData(pDecoder, (VoidPtr_t)&pValenum->data);
554       if (rc==SML_ERR_OK) {
555         // ok, add element to list
556         *ppValenums = pValenum;
557         ppValenums = &(pValenum->next);
558       }
559       else
560         smlFreePcdataList(pValenum); // invalid, get rid of it
561       break;
562     default:
563       rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_PROTO_ELEM,pScanner,"scanPropOrParamElement");
564   }
565   return rc;
566 }
567
568
569 // @brief scan a single <PropParam></PropParam> bracket, or a <1.2 type list where a new <PropName> implies end of current PropParam and start of a new one
570 static Ret_t buildDevInfPropParam(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem, int datastoreLocal) {
571     SmlDevInfCTDataListPtr_t      *ppListElem   = NULL;
572     SmlDevInfCTDataListPtr_t      pParam        = NULL;
573     Boolean_t                     newElement    = FALSE;
574     XltDecScannerPtr_t            pScanner      = pDecoder->scanner;
575     Ret_t rc;
576
577     if (IS_EMPTY(pScanner->curtok)) {
578         return SML_ERR_OK;
579     }
580
581     if (datastoreLocal) {
582       // DS 1.2: we have no initial tag to process right away, get next tag now
583       if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
584         return rc;
585       }
586       newElement=TRUE; // new <property> has already started here
587     }
588
589     // get pointer to where we'd insert the next list element
590     ppListElem   = (SmlDevInfCTDataListPtr_t *)ppElem;
591     while (*ppListElem!=NULL) {
592       ppListElem = &((*ppListElem)->next);
593     }
594     pParam=NULL;
595     // now ppListElem points to a SmlDevInfCTDataListPtr_t which is NULL and
596     // can be overwritten with the link to a new element
597
598     // scan until we hit end of enclosure (</PropParam>) or an unknown other tag
599     while (pScanner->curtok->type != TOK_TAG_END) {
600       if (!datastoreLocal && pScanner->curtok->tagid==TN_DEVINF_PARAMNAME) {
601         // DS 1.1-style CTCap, seeing <ParamName> implies new element
602         newElement=TRUE;
603       }
604       // create new element if needed
605       if (newElement) {
606         newElement=FALSE;
607         pParam = (SmlDevInfCTDataListPtr_t)smlLibMalloc(sizeof(SmlDevInfCTDataList_t));
608         if (pParam == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
609         smlLibMemset(pParam, 0, sizeof(SmlDevInfCTDataList_t));
610         pParam->data = (SmlDevInfCTDataPtr_t)smlLibMalloc(sizeof(SmlDevInfCTData_t));
611         if (pParam->data == NULL) {
612           smlFreeDevInfCTDataList(pParam);
613           return SML_ERR_NOT_ENOUGH_SPACE;
614         }
615         smlLibMemset(pParam->data, 0, sizeof(SmlDevInfCTData_t));
616         // link into list
617         *ppListElem = pParam;
618         // set elem link to where we must link in next element
619         ppListElem = &(pParam->next);
620       }
621       // now, if we don't have a pParam, this is an invalid <DS 1.2 devinf
622       if (pParam==NULL)
623         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfPropParam");
624
625       // process tags
626       switch (pScanner->curtok->tagid) {
627         /* PCDATA */
628         case TN_DEVINF_PARAMNAME:
629           rc = buildPCData(pDecoder, (VoidPtr_t)&pParam->data->name);
630           break;
631         default:
632           rc = scanPropOrParamElement(pDecoder, pParam->data);
633           if (rc==SML_ERR_XLT_INVAL_PROTO_ELEM && !datastoreLocal)
634             return SML_ERR_OK; // parser signals unknown tag, this is ok for pre-1.2
635           break;
636       }
637       if (rc != SML_ERR_OK)
638         return rc;
639       if (((rc = nextToken(pDecoder)) != SML_ERR_OK))
640         return rc;
641     } /* while we do not see an end tag */
642     return SML_ERR_OK;
643 }
644
645
646 // @brief scan a single <Property></Property> bracket, or a <1.2 type list where a new <PropName> implies end of current property and start of a new one
647 static Ret_t buildDevInfProperty(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem, int datastoreLocal) {
648     SmlDevInfCTDataPropListPtr_t  *ppListElem   = NULL;
649     SmlDevInfCTDataPropListPtr_t  pProp         = NULL;
650     Boolean_t                     newElement    = FALSE;
651     XltDecScannerPtr_t            pScanner      = pDecoder->scanner;
652     Ret_t rc;
653
654     if (IS_EMPTY(pScanner->curtok)) {
655         return SML_ERR_OK;
656     }
657
658     if (datastoreLocal) {
659       // DS 1.2: we have no initial tag to process right away, get next tag now
660       if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
661         return rc;
662       }
663       newElement=TRUE; // new <property> has already started here
664     }
665
666     // get pointer to where we'd insert the next list element
667     ppListElem   = (SmlDevInfCTDataPropListPtr_t *) ppElem;
668     while (*ppListElem!=NULL) {
669       ppListElem = &((*ppListElem)->next);
670     }
671     pProp=NULL;
672     // now ppListElem points to a SmlDevInfCTDataPropListPtr_t which is NULL and
673     // can be overwritten with the link to a new element
674
675     // scan until we hit end of enclosure (</Property>) or an unknown other tag
676     while (pScanner->curtok->type != TOK_TAG_END) {
677       if (!datastoreLocal && pScanner->curtok->tagid==TN_DEVINF_PROPNAME) {
678         // DS 1.1-style CTCap, seeing <PropName> implies new element
679         newElement=TRUE;
680       }
681       // create new element if needed
682       if (newElement) {
683         newElement=FALSE;
684         pProp = (SmlDevInfCTDataPropListPtr_t)smlLibMalloc(sizeof(SmlDevInfCTDataPropList_t));
685         if (pProp == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
686         smlLibMemset(pProp, 0, sizeof(SmlDevInfCTDataPropList_t));
687         pProp->data = (SmlDevInfCTDataPropPtr_t)smlLibMalloc(sizeof(SmlDevInfCTDataProp_t));
688         if (pProp->data == NULL) {
689           smlFreeDevInfCTDataPropList(pProp);
690           return SML_ERR_NOT_ENOUGH_SPACE;
691         }
692         smlLibMemset(pProp->data, 0, sizeof(SmlDevInfCTDataProp_t));
693         pProp->data->prop = (SmlDevInfCTDataPtr_t)smlLibMalloc(sizeof(SmlDevInfCTData_t));
694         if (pProp->data->prop == NULL) {
695           smlFreeDevInfCTDataPropList(pProp);
696           return SML_ERR_NOT_ENOUGH_SPACE;
697         }
698         smlLibMemset(pProp->data->prop, 0, sizeof(SmlDevInfCTData_t));
699         // link into list
700         *ppListElem = pProp;
701         // set elem link to where we must link in next element
702         ppListElem = &(pProp->next);
703       }
704       // now, if we don't have a pProp, this is an invalid <DS 1.2 devinf
705       if (pProp==NULL)
706         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfProperty");
707
708       // process tags
709       switch (pScanner->curtok->tagid) {
710         case TN_DEVINF_PROPPARAM:
711           // DS 1.2 case: only </PropParam> ends the param building process
712           rc = buildDevInfPropParam(pDecoder, (VoidPtr_t)&pProp->data->param,datastoreLocal);
713           break;
714         case TN_DEVINF_PARAMNAME:
715           // <DS 1.2 case: current token TN_DEVINF_PARAMNAME is processed by builder
716           if (datastoreLocal) {
717                 // found <ParamName> directly within <Property> (instead of enclosed in a <PropParam>) - Nokia 2630 style
718             // -> do not reject it but try to process in DS 1.1 style even if this is a DS 1.2 devInf
719             rc = buildDevInfPropParam(pDecoder, (VoidPtr_t)&pProp->data->param,FALSE); // force DS 1.1 style
720             if (rc==SML_ERR_OK)
721               continue; // re-evaluate current tag (tag that caused buildDevInfPropParam() to end, either next <PropName>, unknown or closing </CTCap>
722           }
723           else {
724             rc = buildDevInfPropParam(pDecoder, (VoidPtr_t)&pProp->data->param,datastoreLocal);
725             if (rc==SML_ERR_OK)
726               continue; // re-evaluate current tag (tag that caused buildDevInfPropParam() to end, either next <PropName>, unknown or closing </CTCap>
727           }
728           break;
729
730         /* PCDATA */
731         case TN_DEVINF_PROPNAME:
732           rc = buildPCData(pDecoder, (VoidPtr_t)&pProp->data->prop->name);
733           break;
734
735         default:
736           rc = scanPropOrParamElement(pDecoder, pProp->data->prop);
737           if (rc==SML_ERR_XLT_INVAL_PROTO_ELEM && !datastoreLocal)
738             return SML_ERR_OK; // parser signals unknown tag, this is ok for pre-1.2
739       }
740       if (rc != SML_ERR_OK)
741         return rc;
742       if (((rc = nextToken(pDecoder)) != SML_ERR_OK))
743         return rc;
744     } /* while we do not see an end tag */
745     return SML_ERR_OK;
746 }
747
748
749
750 // @brief scan a single <ctcap></ctcap> bracket, which may contain serveral ctcaps for <DS 1.2, and only one single ctcap for >=DS 1.2
751 Ret_t buildDevInfCtcap(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem, Boolean_t datastoreLocal)
752 {
753     SmlDevInfCtcapListPtr_t       *ppListElem   = NULL;
754     SmlDevInfCtcapListPtr_t       pCtcap        = NULL;
755     Boolean_t                     newElement    = FALSE;
756     XltDecScannerPtr_t            pScanner      = pDecoder->scanner;
757     Ret_t rc;
758
759     if (IS_EMPTY(pScanner->curtok)) {
760         return SML_ERR_OK;
761     }
762
763     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
764         return rc;
765     }
766
767     // get pointer to where we'd insert the next list element
768     ppListElem   = (SmlDevInfCtcapListPtr_t *)ppElem;
769     while (*ppListElem!=NULL) {
770       ppListElem = &((*ppListElem)->next);
771     }
772     pCtcap=NULL;
773     // now ppListElem points to a SmlDevInfCtcapListPtr_t which is NULL and
774     // can be overwritten with the link to a new element
775
776     // datastore local CTCap is DS 1.2 or later, and implies that every type description has its own <CTCap></CTCap>
777     // So starting a CTCap implies creating a new element
778     newElement=datastoreLocal;
779
780     while (pScanner->curtok->type != TOK_TAG_END) {
781         if (!datastoreLocal && pScanner->curtok->tagid==TN_DEVINF_CTTYPE) {
782           // DS 1.1-style CTCap, seeing CTTYPE implies new element
783           newElement=TRUE;
784         }
785         // create new element if needed
786         if (newElement) {
787           newElement=FALSE;
788           pCtcap = (SmlDevInfCtcapListPtr_t)smlLibMalloc(sizeof(SmlDevInfCtcapList_t));
789           if (pCtcap == NULL) return SML_ERR_NOT_ENOUGH_SPACE;
790           smlLibMemset(pCtcap, 0, sizeof(SmlDevInfCtcapList_t));
791           pCtcap->data = (SmlDevInfCTCapPtr_t)smlLibMalloc(sizeof(SmlDevInfCTCap_t));
792           if (pCtcap->data == NULL) {
793             smlFreeDevInfCtcapList(pCtcap);
794             return SML_ERR_NOT_ENOUGH_SPACE;
795           }
796           smlLibMemset(pCtcap->data, 0, sizeof(SmlDevInfCTCap_t));
797           // link into list
798           *ppListElem = pCtcap;
799           // set elem link to where we must link in next element
800           ppListElem = &(pCtcap->next);
801         }
802         // now, if we don't have a pCtcap, this is an invalid <DS 1.2 devinf where another tag than <CTType> follows <CTCap>
803         if (pCtcap==NULL)
804           return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfCtcap");
805         // process tags
806         switch (pScanner->curtok->tagid) {
807           case TN_DEVINF_CTTYPE:
808             rc = buildPCData(pDecoder, (VoidPtr_t)&pCtcap->data->cttype);
809             break;
810           case TN_DEVINF_VERCT:
811             rc = buildPCData(pDecoder, (VoidPtr_t)&pCtcap->data->verct);
812             break;
813           case TN_DEVINF_PROPERTY:
814             // DS 1.2 case: only </Property> ends the property building process, next token must be read first
815             rc = buildDevInfProperty(pDecoder, (VoidPtr_t)&pCtcap->data->prop,datastoreLocal);
816             break;
817           case TN_DEVINF_PROPNAME:
818             // <DS 1.2 case: current token TN_DEVINF_PROPNAME is processed by builder, next occurence of TN_DEVINF_PROPNAME ends property as well
819             if (datastoreLocal)
820               rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfCtcap"); // <PropName> must be inside <Property>
821             else {
822               rc = buildDevInfProperty(pDecoder, (VoidPtr_t)&pCtcap->data->prop,datastoreLocal);
823               if (rc==SML_ERR_OK)
824                 continue; // re-evaluate current tag (tag that caused buildDevInfProperty() to end, either unknown or closing </CTCap>
825             }
826             break;
827
828         default:
829             rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfCtcap");
830         }
831         if (rc != SML_ERR_OK) {
832             return rc;
833         }
834         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
835             return rc;
836         }
837     } /* eof while */
838     return SML_ERR_OK;
839 }
840
841
842 Ret_t buildDevInfDSMemCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
843     XltDecScannerPtr_t pScanner;
844     SmlDevInfDSMemPtr_t pElem;
845     Ret_t rc;
846
847     pScanner = pDecoder->scanner;
848
849     if (*ppElem != NULL)
850         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDSMemCmd");
851
852     if ((pElem = (SmlDevInfDSMemPtr_t)smlLibMalloc(sizeof(SmlDevInfDSMem_t))) == NULL)
853         return SML_ERR_NOT_ENOUGH_SPACE;
854     smlLibMemset(pElem, 0, sizeof(SmlDevInfDSMem_t));
855
856     if (IS_EMPTY(pScanner->curtok)) {
857         *ppElem = pElem;
858         return SML_ERR_OK;
859     }
860
861     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
862         smlLibFree(pElem);
863         return rc;
864     }
865
866     while (pScanner->curtok->type != TOK_TAG_END) {
867         switch (pScanner->curtok->tagid) {
868             /* PCDATA elements */
869             case TN_DEVINF_SHAREDMEM:
870                 // %%% luz:2003-04-28: made work as a flag
871                 pElem->flags |= SmlDevInfSharedMem_f;
872                 rc = buildEmptyTag(pDecoder); // allow for <tag></tag> instead of <tag/>
873                 break;
874             case TN_DEVINF_MAXMEM:
875                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->maxmem);
876                 break;
877             case TN_DEVINF_MAXID:
878                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->maxid);
879                 break;
880             default:
881                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfDSMemCmd");
882         }
883         if (rc != SML_ERR_OK) {
884             smlLibFree(pElem);
885             return rc;
886         }
887         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
888             smlLibFree(pElem);
889             return rc;
890         }
891     }
892     *ppElem = pElem;
893
894     return SML_ERR_OK;
895 }
896
897 Ret_t buildDevInfCTCapCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
898     XltDecScannerPtr_t pScanner;
899     SmlDevInfCTCapPtr_t pElem;
900     Ret_t rc;
901
902     pScanner = pDecoder->scanner;
903
904     if (*ppElem != NULL)
905         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfCTCapCmd");
906
907     if ((pElem = (SmlDevInfCTCapPtr_t)smlLibMalloc(sizeof(SmlDevInfCTCap_t))) == NULL)
908         return SML_ERR_NOT_ENOUGH_SPACE;
909     smlLibMemset(pElem, 0, sizeof(SmlDevInfCTCap_t));
910
911     if (IS_EMPTY(pScanner->curtok)) {
912         *ppElem = pElem;
913         return SML_ERR_OK;
914     }
915
916     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
917         smlLibFree(pElem);
918         return rc;
919     }
920
921     while (pScanner->curtok->type != TOK_TAG_END) {
922         switch (pScanner->curtok->tagid) {
923             case TN_DEVINF_CTTYPE:
924                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->cttype);
925                 break;
926             default:
927                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfCTCapCmd");
928         }
929         if (rc != SML_ERR_OK) {
930             smlLibFree(pElem);
931             return rc;
932         }
933         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
934             smlLibFree(pElem);
935             return rc;
936         }
937     }
938     *ppElem = pElem;
939
940     return SML_ERR_OK;
941 }
942
943 Ret_t buildDevInfSyncCapCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
944     XltDecScannerPtr_t pScanner;
945     SmlDevInfSyncCapPtr_t pElem;
946     Ret_t rc;
947
948     pScanner = pDecoder->scanner;
949
950     if (*ppElem != NULL)
951         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfSyncCapCmd");
952
953     if ((pElem = (SmlDevInfSyncCapPtr_t)smlLibMalloc(sizeof(SmlDevInfSyncCap_t))) == NULL)
954         return SML_ERR_NOT_ENOUGH_SPACE;
955     smlLibMemset(pElem, 0, sizeof(SmlDevInfSyncCap_t));
956
957     if (IS_EMPTY(pScanner->curtok)) {
958         *ppElem = pElem;
959         return SML_ERR_OK;
960     }
961
962     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
963         smlLibFree(pElem);
964         return rc;
965     }
966
967     while (pScanner->curtok->type != TOK_TAG_END) {
968         switch (pScanner->curtok->tagid) {
969             case TN_DEVINF_SYNCTYPE:
970                 rc = buildPCDataList(pDecoder, (VoidPtr_t)&pElem->synctype);
971                 break;
972             default:
973                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfSyncCapCmd");
974         }
975         if (rc != SML_ERR_OK) {
976             smlLibFree(pElem);
977             return rc;
978         }
979         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
980             smlLibFree(pElem);
981             return rc;
982         }
983     }
984     *ppElem = pElem;
985
986     return SML_ERR_OK;
987 }
988
989 Ret_t buildDevInfExtCmd(XltDecoderPtr_t pDecoder, VoidPtr_t *ppElem) {
990     XltDecScannerPtr_t pScanner;
991     SmlDevInfExtPtr_t pElem;
992     Ret_t rc;
993
994     pScanner = pDecoder->scanner;
995
996     if (*ppElem != NULL)
997         return SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfExtCmd");
998
999     if ((pElem = (SmlDevInfExtPtr_t)smlLibMalloc(sizeof(SmlDevInfExt_t))) == NULL)
1000         return SML_ERR_NOT_ENOUGH_SPACE;
1001     smlLibMemset(pElem, 0, sizeof(SmlDevInfExt_t));
1002
1003     if (IS_EMPTY(pScanner->curtok)) {
1004         *ppElem = pElem;
1005         return SML_ERR_OK;
1006     }
1007
1008     if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
1009         smlLibFree(pElem);
1010         return rc;
1011     }
1012
1013     while (pScanner->curtok->type != TOK_TAG_END) {
1014         switch (pScanner->curtok->tagid) {
1015             case TN_DEVINF_XNAM:
1016                 rc = buildPCData(pDecoder, (VoidPtr_t)&pElem->xnam);
1017                 break;
1018             case TN_DEVINF_XVAL:
1019                 rc = buildPCDataList(pDecoder, (VoidPtr_t)&pElem->xval);
1020                 break;
1021             default:
1022                 rc = SML_DECODEERROR(SML_ERR_XLT_INVAL_SYNCML_DOC,pScanner,"buildDevInfExtCmd");
1023         }
1024         if (rc != SML_ERR_OK) {
1025             smlLibFree(pElem);
1026             return rc;
1027         }
1028         if (((rc = nextToken(pDecoder)) != SML_ERR_OK)) {
1029             smlLibFree(pElem);
1030             return rc;
1031         }
1032     }
1033     *ppElem = pElem;
1034
1035     return SML_ERR_OK;
1036 }
1037
1038
1039 /* see xltenc.c:XltEncBlock for description of parameters */
1040 Ret_t devinfEncBlock(XltTagID_t tagId, XltRO_t reqOptFlag, const VoidPtr_t pContent, SmlEncoding_t enc, BufferMgmtPtr_t pBufMgr, SmlPcdataExtension_t attFlag) {
1041   //Return variable
1042   Ret_t _err;
1043   SmlPcdataListPtr_t           pList     = NULL;
1044   SmlDevInfDatastoreListPtr_t  dsList    = NULL;
1045   SmlDevInfCtcapListPtr_t      ctList    = NULL;
1046   SmlDevInfExtListPtr_t        exList    = NULL;
1047   SmlDevInfXmitListPtr_t       xmList    = NULL;
1048   SmlDevInfFilterCapListPtr_t  fcapList  = NULL;
1049   SmlDevInfCTDataPropListPtr_t propList  = NULL;
1050   SmlDevInfCTDataListPtr_t     paramList = NULL;
1051   XltTagID_t                   nameTagID = TN_UNDEF;
1052   SmlDevInfCTDataPtr_t         pPropOrParam = NULL;
1053
1054
1055     //Check if pContent of a required field is missing
1056   if ((reqOptFlag == REQUIRED) && (pContent == NULL))
1057     return SML_ERR_XLT_MISSING_CONT;
1058   //Check if pContent of a optional field is missing -> if yes we are done
1059   else if (pContent == NULL)
1060     return SML_ERR_OK;
1061
1062   //Generate the commands -> see DTD
1063   switch (tagId) {
1064     case TN_DEVINF_EXT:
1065       if ((_err = xltGenerateTag(TN_DEVINF_EXT, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1066       if ((_err = devinfEncBlock(TN_DEVINF_XNAM, REQUIRED, ((SmlDevInfExtPtr_t) pContent)->xnam, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1067       pList = ((SmlDevInfExtPtr_t)pContent)->xval;
1068           while (pList != NULL) {
1069               if ((_err = devinfEncBlock(TN_DEVINF_XVAL, OPTIONAL, pList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1070               pList = pList->next;
1071           };
1072       if ((_err = xltGenerateTag(TN_DEVINF_EXT, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1073       break;
1074     case TN_DEVINF_SYNCCAP:
1075       if ((_err = xltGenerateTag(TN_DEVINF_SYNCCAP, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1076       pList = ((SmlDevInfSyncCapPtr_t)pContent)->synctype;
1077           while (pList != NULL) {
1078               if ((_err = devinfEncBlock(TN_DEVINF_SYNCTYPE, OPTIONAL, pList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1079               pList = pList->next;
1080           };
1081       if ((_err = xltGenerateTag(TN_DEVINF_SYNCCAP, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1082       break;
1083     case TN_DEVINF_SHAREDMEM:
1084       //set the flag in the (WB)XML document if the flag is in the pContent
1085       if ((*((Flag_t *) pContent)) & (SmlDevInfSharedMem_f))
1086           if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1087       break;
1088     // %%% luz:2003-04-28 added missing 1.1 devinf tags here
1089     case TN_DEVINF_UTC:
1090       //set the flag in the (WB)XML document if the flag is in the pContent
1091       if ((*((Flag_t *) pContent)) & (SmlDevInfUTC_f)) {
1092         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1093       }
1094       break;
1095     case TN_DEVINF_NOFM:
1096       //set the flag in the (WB)XML document if the flag is in the pContent
1097       if ((*((Flag_t *) pContent)) & (SmlDevInfNOfM_f)) {
1098         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1099       }
1100       break;
1101     case TN_DEVINF_LARGEOBJECT:
1102       //set the flag in the (WB)XML document if the flag is in the pContent
1103       if ((*((Flag_t *) pContent)) & (SmlDevInfLargeObject_f)) {
1104         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1105       }
1106       break;
1107
1108     /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1109     case TN_DEVINF_FIELDLEVEL:
1110       //set the flag in the (WB)XML document if the flag is in the pContent
1111       if ((*((Flag_t *) pContent)) & (SmlDevInfFieldLevel_f)) {
1112         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1113       }
1114       break;
1115     case TN_DEVINF_HIERARCHICAL:
1116       //set the flag in the (WB)XML document if the flag is in the pContent
1117       if ((*((Flag_t *) pContent)) & (SmlDevInfHierarchical_f)) {
1118         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1119       }
1120       break;
1121     case TN_DEVINF_NOTRUNCATE:
1122       //set the flag in the (WB)XML document if the flag is in the pContent
1123       if ((*((Flag_t *) pContent)) & (SmlDevInfNoTruncate_f)) {
1124         if ((_err = xltGenerateTag(tagId, TT_ALL, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1125       }
1126       break;
1127
1128     case TN_DEVINF_PROPERTY:
1129       // pContent is SmlDevInfCTDataPropPtr_t
1130       paramList = ((SmlDevInfCTDataPropPtr_t)pContent)->param; // get param list
1131       // modify pContent
1132       pPropOrParam = ((SmlDevInfCTDataPropPtr_t)pContent)->prop; // common property/propparam description record
1133       // set the tag to be used for name
1134       nameTagID=TN_DEVINF_PROPNAME; // is a property, use <PropName>
1135       goto param_or_property;
1136     case TN_DEVINF_PROPPARAM:
1137       // pContent is SmlDevInfCTDataPtr_t (common data structure for <Property> and <PropParam>)
1138       paramList=NULL;
1139       // set the tag to be used for name
1140       nameTagID=TN_DEVINF_PARAMNAME; // is a propparam, use <ParamName>
1141       // set content
1142       pPropOrParam = (SmlDevInfCTDataPtr_t)pContent;
1143       goto param_or_property;
1144     param_or_property:
1145       // - pPropOrParam is SmlDevInfCTDataPtr_t (common data structure for <Property> and <PropParam>)
1146       // - paramList is either NULL (for params, which do not have params themselves) or SmlDevInfCTDataListPtr_t (for properties)
1147       // DS 1.2 or higher : open <Property>/<PropParam> to properly group all property related elements
1148       if (pBufMgr->vers>=SML_VERS_1_2) {
1149         if ((_err = xltGenerateTag(tagId, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1150       }
1151       /* -- Propname or ParamName */
1152       if ((_err = devinfEncBlock(nameTagID, REQUIRED, pPropOrParam->name, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1153       /* -- (ValEnum+ | (Datatype, Size?))? */
1154       //%%% luz 2007-08-14 empty datatype is allowed as well (as this is what e.g. Nokia E90 sends, and when using SML to translate back to XML, we'd failed here before)
1155       if (pPropOrParam->valenum != NULL && pPropOrParam->datatype != NULL && pPropOrParam->datatype->length!=0)
1156         return SML_ERR_XLT_INVAL_INPUT_DATA;
1157       if (pPropOrParam->valenum != NULL) {
1158           // ValEnum+
1159           pList = pPropOrParam->valenum;
1160           while (pList != NULL) {
1161               if ((_err = devinfEncBlock(TN_DEVINF_VALENUM, REQUIRED, pList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1162               pList = pList->next;
1163           };
1164       } else if (pPropOrParam->datatype != NULL) {
1165           // Datatype?
1166           if ((_err = devinfEncBlock(TN_DEVINF_DATATYPE, REQUIRED, pPropOrParam->datatype, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1167       }
1168       /* (Max)Size? (note, in <1.2, the tag was called "Size", in >=1.2, the tag is called "MaxSize" - but both have the same WBXML token) */
1169       if ((_err = devinfEncBlock(pBufMgr->vers>=SML_VERS_1_2 ? TN_DEVINF_MAXSIZE : TN_DEVINF_SIZE, OPTIONAL, pPropOrParam->maxsize, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1170       /* -- DS 1.2: MaxOccur?, is valid for Properties only, not for PropParams */
1171       if ((_err = devinfEncBlock(TN_DEVINF_MAXOCCUR, OPTIONAL, pPropOrParam->maxoccur, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1172       /* -- DS 1.2: (NoTruncate?), is valid for Properties only, not for PropParams */
1173       if ((_err = devinfEncBlock(TN_DEVINF_NOTRUNCATE, OPTIONAL, &(pPropOrParam->flags), enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1174
1175       /* -- DisplayName ? */
1176       if ((_err = devinfEncBlock(TN_DEVINF_DISPLAYNAME, OPTIONAL, pPropOrParam->dname, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1177
1178       /* -- now the paramList */
1179       while (paramList != NULL) {
1180           /* Synthesis/luz 2005-08-24 : separated generation of <PropParam> element into own case */
1181           if ((_err = devinfEncBlock(TN_DEVINF_PROPPARAM, REQUIRED, paramList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1182           paramList = paramList->next;
1183       }
1184       // DS 1.2 or higher : close </Property>/</PropParam> encapsulation
1185       if (pBufMgr->vers>=SML_VERS_1_2) {
1186         if ((_err = xltGenerateTag(tagId, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1187       }
1188       break;
1189
1190     case TN_DEVINF_CTCAP:
1191       ctList = ((SmlDevInfCtcapListPtr_t)pContent);
1192       if (ctList == NULL)
1193         break; // empty CTCap - is ok, do not output anything
1194       // before DS 1.2 : all types are encapsulated in a single CTCap
1195       if (pBufMgr->vers<SML_VERS_1_2) {
1196         if ((_err = xltGenerateTag(TN_DEVINF_CTCAP, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1197       }
1198       while (ctList != NULL) {
1199           if (ctList->data == NULL) return SML_ERR_XLT_INVAL_INPUT_DATA;
1200           // DS 1.2 or higher : every content type is separately enclosed in a CTCap
1201           if (pBufMgr->vers>=SML_VERS_1_2) {
1202             if ((_err = xltGenerateTag(TN_DEVINF_CTCAP, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1203           }
1204           if ((_err = devinfEncBlock(TN_DEVINF_CTTYPE, REQUIRED, ctList->data->cttype, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1205           /* SyncML DS 1.2, Synthesis/luz 2005-09-28, required for DS 1.2 only, therefore OPTIONAL here */
1206           if ((_err = devinfEncBlock(TN_DEVINF_VERCT, OPTIONAL, ctList->data->verct, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1207           /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1208           if ((_err = devinfEncBlock(TN_DEVINF_FIELDLEVEL, OPTIONAL, &(ctList->data->flags), enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1209
1210           /* now the propList */
1211           // %%% luz 2002-11-27: made property list optional (e.g. text/message of P800 has none)
1212           propList = ctList->data->prop;
1213           // %%% original: if (propList == NULL) return SML_ERR_XLT_INVAL_INPUT_DATA;
1214           while (propList != NULL) {
1215               if (propList->data == NULL) return SML_ERR_XLT_INVAL_INPUT_DATA;
1216               if (propList->data->prop == NULL) return SML_ERR_XLT_INVAL_INPUT_DATA;
1217               /* Synthesis/luz 2005-08-24 : separated generation of <property> element into own case */
1218               if ((_err = devinfEncBlock(TN_DEVINF_PROPERTY, REQUIRED, propList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1219               propList = propList->next;
1220           }
1221           // DS 1.2 or higher : every content type is separately enclosed in a CTCap
1222           if (pBufMgr->vers>=SML_VERS_1_2) {
1223             if ((_err = xltGenerateTag(TN_DEVINF_CTCAP, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1224           }
1225           /* eof propList */
1226           ctList = ctList->next;
1227       };
1228       // before DS 1.2 : all types are encapsulated in a single CTCap
1229       if (pBufMgr->vers<SML_VERS_1_2) {
1230         if ((_err = xltGenerateTag(TN_DEVINF_CTCAP, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1231       }
1232       break;
1233
1234     case TN_DEVINF_DSMEM:
1235       if ((_err = xltGenerateTag(TN_DEVINF_DSMEM, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1236       if ((_err = devinfEncBlock(TN_DEVINF_SHAREDMEM, OPTIONAL, &(((SmlDevInfDSMemPtr_t) pContent)->flags), enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1237       if ((_err = devinfEncBlock(TN_DEVINF_MAXMEM,    OPTIONAL, ((SmlDevInfDSMemPtr_t) pContent)->maxmem, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1238       if ((_err = devinfEncBlock(TN_DEVINF_MAXID,     OPTIONAL, ((SmlDevInfDSMemPtr_t) pContent)->maxid,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1239       if ((_err = xltGenerateTag(TN_DEVINF_DSMEM, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1240       break;
1241
1242     // special case, the following 5 have the same structure, only the tag name differs
1243     case TN_DEVINF_RX:
1244     case TN_DEVINF_TX:
1245     case TN_DEVINF_RXPREF:
1246     case TN_DEVINF_TXPREF:
1247     case TN_DEVINF_FILTERRX: /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1248       if ((_err = xltGenerateTag(tagId, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1249       if ((_err = devinfEncBlock(TN_DEVINF_CTTYPE, REQUIRED, ((SmlDevInfXmitPtr_t) pContent)->cttype, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1250       if ((_err = devinfEncBlock(TN_DEVINF_VERCT,  REQUIRED, ((SmlDevInfXmitPtr_t) pContent)->verct,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1251       if ((_err = xltGenerateTag(tagId, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1252       break;
1253
1254     /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1255     case TN_DEVINF_FILTERCAP:
1256       if ((_err = xltGenerateTag(tagId, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1257       if ((_err = devinfEncBlock(TN_DEVINF_CTTYPE, REQUIRED, ((SmlDevInfFilterCapPtr_t) pContent)->cttype, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1258       if ((_err = devinfEncBlock(TN_DEVINF_VERCT,  REQUIRED, ((SmlDevInfFilterCapPtr_t) pContent)->verct,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1259       pList = ((SmlDevInfFilterCapPtr_t) pContent)->filterkeyword;
1260       while (pList != NULL) {
1261         if ((_err = devinfEncBlock(TN_DEVINF_FILTERKEYWORD, REQUIRED, pList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1262         pList=pList->next;
1263       }
1264       pList = ((SmlDevInfFilterCapPtr_t) pContent)->propname;
1265       while (pList != NULL) {
1266         if ((_err = devinfEncBlock(TN_DEVINF_PROPNAME, REQUIRED, pList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1267         pList=pList->next;
1268       }
1269       if ((_err = xltGenerateTag(tagId, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1270       break;
1271
1272
1273     case TN_DEVINF_DATASTORE:
1274       if ((_err = xltGenerateTag(TN_DEVINF_DATASTORE, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1275       if ((_err = devinfEncBlock(TN_DEVINF_SOURCEREF,    REQUIRED, ((SmlDevInfDatastorePtr_t) pContent)->sourceref,    enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1276       if ((_err = devinfEncBlock(TN_DEVINF_DISPLAYNAME,  OPTIONAL, ((SmlDevInfDatastorePtr_t) pContent)->displayname,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1277       if ((_err = devinfEncBlock(TN_DEVINF_MAXGUIDSIZE,  OPTIONAL, ((SmlDevInfDatastorePtr_t) pContent)->maxguidsize,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1278       if ((_err = devinfEncBlock(TN_DEVINF_RXPREF,       REQUIRED, ((SmlDevInfDatastorePtr_t) pContent)->rxpref,       enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1279       xmList = ((SmlDevInfDatastorePtr_t)pContent)->rx;
1280       while (xmList != NULL) {
1281           if ((_err = devinfEncBlock(TN_DEVINF_RX, OPTIONAL, xmList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1282           xmList = xmList->next;
1283       };
1284       if ((_err = devinfEncBlock(TN_DEVINF_TXPREF,       REQUIRED, ((SmlDevInfDatastorePtr_t) pContent)->txpref,       enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1285       xmList = ((SmlDevInfDatastorePtr_t)pContent)->tx;
1286       while (xmList != NULL) {
1287           if ((_err = devinfEncBlock(TN_DEVINF_TX, OPTIONAL, xmList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1288           xmList = xmList->next;
1289       };
1290       /* For SyncML DS 1.2, CTCaps are local to datastore, no longer global in DevInf */
1291       if ((_err = devinfEncBlock(TN_DEVINF_CTCAP,        OPTIONAL, ((SmlDevInfDatastorePtr_t) pContent)->ctcap,        enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1292
1293       if ((_err = devinfEncBlock(TN_DEVINF_DSMEM,        OPTIONAL, ((SmlDevInfDatastorePtr_t) pContent)->dsmem,        enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1294       /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1295       if ((_err = devinfEncBlock(TN_DEVINF_HIERARCHICAL, OPTIONAL, &(((SmlDevInfDatastorePtr_t) pContent)->flags),     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1296
1297       if ((_err = devinfEncBlock(TN_DEVINF_SYNCCAP,      REQUIRED, ((SmlDevInfDatastorePtr_t) pContent)->synccap,      enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1298
1299       /* SyncML DS 1.2, Synthesis/luz 2005-08-24 */
1300       xmList = ((SmlDevInfDatastorePtr_t)pContent)->filterrx;
1301       while (xmList != NULL) {
1302           if ((_err = devinfEncBlock(TN_DEVINF_FILTERRX, OPTIONAL, xmList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1303           xmList = xmList->next;
1304       };
1305       /* SyncML DS 1.2, Synthesis/luz 2005-08-25 */
1306       fcapList = ((SmlDevInfDatastorePtr_t)pContent)->filtercap;
1307       while (fcapList != NULL) {
1308           if ((_err = devinfEncBlock(TN_DEVINF_FILTERCAP, OPTIONAL, fcapList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1309           fcapList = fcapList->next;
1310       };
1311
1312       if ((_err = xltGenerateTag(TN_DEVINF_DATASTORE, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1313       break;
1314
1315     case TN_DEVINF_DEVINF:
1316       if ((_err = xltGenerateTag(TN_DEVINF_DEVINF, TT_BEG, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1317       if ((_err = devinfEncBlock(TN_DEVINF_VERDTD,  REQUIRED, ((SmlDevInfDevInfPtr_t) pContent)->verdtd,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1318       if ((_err = devinfEncBlock(TN_DEVINF_MAN,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->man,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1319       if ((_err = devinfEncBlock(TN_DEVINF_MOD,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->mod,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1320       if ((_err = devinfEncBlock(TN_DEVINF_OEM,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->oem,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1321       if ((_err = devinfEncBlock(TN_DEVINF_FWV,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->fwv,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1322       if ((_err = devinfEncBlock(TN_DEVINF_SWV,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->swv,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1323       if ((_err = devinfEncBlock(TN_DEVINF_HWV,     OPTIONAL, ((SmlDevInfDevInfPtr_t) pContent)->hwv,     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1324       if ((_err = devinfEncBlock(TN_DEVINF_DEVID,   REQUIRED, ((SmlDevInfDevInfPtr_t) pContent)->devid,   enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1325       if ((_err = devinfEncBlock(TN_DEVINF_DEVTYP,  REQUIRED, ((SmlDevInfDevInfPtr_t) pContent)->devtyp,  enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1326       if ((_err = devinfEncBlock(TN_DEVINF_UTC,     OPTIONAL, &(((SmlDevInfDevInfPtr_t) pContent)->flags),     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1327       if ((_err = devinfEncBlock(TN_DEVINF_NOFM,    OPTIONAL, &(((SmlDevInfDevInfPtr_t) pContent)->flags),     enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1328       if ((_err = devinfEncBlock(TN_DEVINF_LARGEOBJECT, OPTIONAL, &(((SmlDevInfDevInfPtr_t) pContent)->flags), enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1329       // According to SyncML standard, the dsList must not be empty. However as some implementations send such devInf,
1330       // and the RTK is also used to convert WBXML to XML for human readable message dumps, we now allow
1331       // generating such devInf (for the XML log output). 
1332       dsList = ((SmlDevInfDevInfPtr_t)pContent)->datastore;
1333       //if (dsList == NULL) return SML_ERR_XLT_MISSING_CONT;
1334       if(dsList != NULL) {
1335           if ((_err = devinfEncBlock(TN_DEVINF_DATASTORE, REQUIRED, dsList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1336           dsList = dsList->next;
1337           while (dsList != NULL) {
1338               if ((_err = devinfEncBlock(TN_DEVINF_DATASTORE, OPTIONAL, dsList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1339               dsList = dsList->next;
1340           };
1341       }
1342       // for pre DS 1.2, CTCaps are global (i.e at the devInf level):
1343       if ((_err = devinfEncBlock(TN_DEVINF_CTCAP, OPTIONAL, ((SmlDevInfDevInfPtr_t)pContent)->ctcap, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1344       // extensions
1345       exList = ((SmlDevInfDevInfPtr_t)pContent)->ext;
1346       while (exList != NULL) {
1347           if ((_err = devinfEncBlock(TN_DEVINF_EXT, OPTIONAL, exList->data, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1348           exList = exList->next;
1349       };
1350
1351       if ((_err = xltGenerateTag(TN_DEVINF_DEVINF, TT_END, enc, pBufMgr, SML_EXT_DEVINF)) != SML_ERR_OK) return _err;
1352       break;
1353
1354     default: { // all leaf nodes (PCDATA#)
1355       return xltEncPcdata(tagId, reqOptFlag, pContent, enc, pBufMgr, attFlag);
1356     } //* eof default statement from switch tagid
1357   } // eof switch tagid
1358   return SML_ERR_OK;
1359 }
1360 #endif /* __USE_DEVINF__ */