Kannel: Open Source WAP and SMS gateway  svn-r5335
ota_compiler.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * ota_compiler.c: Tokenizes OTA provisioning documents
59  *
60  * This compiler handles the following OTA config formats:
61  *
62  * - Nokia/Ericsson OTA settings specificaion. DTD is defined in
63  * Over The Air Settings Specification (hereafter called OTA), chapter 6.
64  * (See http://www.americas.nokia.com/messaging/default.asp)
65  *
66  * - OMA OTA client provisionig content specification, as defined in
67  * document OMA-WAP-ProvCont-V1.1-20050428-C.pdf. (hereafter called OMA)
68  * (See http://www.openmobilealliance.com/release_program/cp_v1_1.htm)
69  *
70  * Histrorically the Nokia/Ericsson OTA config format was the first scratch
71  * in allowing remote WAP profile configuration via SMS bearer. While the WAP
72  * Forum transfered into the Open Mobile Alliance (OMA), the technical working
73  * groups addopted the provisioning concept to a more generic OTA provisioning
74  * concept. The OMA client provisioning specs v1.1 are part of the WAP 2.0
75  * protocol stack.
76  *
77  * Aarno Syvänen for Wiral Ltd
78  * Stipe Tolj <stolj@kannel.org> for Wapme Systems AG
79  * Paul Bagyenda for digital solutions Ltd.
80  */
81 
82 #include <ctype.h>
83 #include <inttypes.h>
84 #include <libxml/xmlmemory.h>
85 #include <libxml/tree.h>
86 #include <libxml/debugXML.h>
87 #include <libxml/encoding.h>
88 
89 #include "shared.h"
90 #include "xml_shared.h"
91 #include "ota_compiler.h"
92 
93 /****************************************************************************
94  *
95  * Global variables
96  *
97  * Two token table types, one and two token fields
98  */
99 
100 struct ota_2table_t {
101  char *name;
102  unsigned char token;
103 };
104 
105 typedef struct ota_2table_t ota_2table_t;
106 
107 /*
108  * Ota tokenizes whole of attribute value, or uses an inline string. See ota,
109  * chapter 8.2.
110  */
111 struct ota_3table_t {
112  char *name;
113  char *value;
114  unsigned char token;
115  unsigned char code_page;
116 };
117 
118 typedef struct ota_3table_t ota_3table_t;
119 
120 /*
121  * Elements from tag code page zero. These are defined in OTA, chapter 8.1
122  * and OMA, chapter 7.1.
123  */
124 
126  { "SYNCSETTINGS", 0x15 },
127  { "WAP-PROVISIONINGDOC", 0x05 },
128  { "CHARACTERISTIC-LIST", 0x05 },
129  { "CHARACTERISTIC", 0x06 },
130  { "PARM", 0x07 }
131 };
132 
133 #define NUMBER_OF_ELEMENTS sizeof(ota_elements)/sizeof(ota_elements[0])
134 
135 /*
136  * SYNCSETTINGS tags are defined in OTA specs 7.0, chapter 11.1
137  */
138 
140  { "Addr", 0x45 },
141  { "AddrType", 0x46 },
142  { "Auth", 0x47 },
143  { "AuthLevel", 0x48 },
144  { "AuthScheme", 0x49 },
145  { "Bearer", 0x4A },
146  { "ConRef", 0x4B },
147  { "ConType", 0x4C },
148  { "Cred", 0x4D },
149  { "CTType", 0x4E },
150  { "CTVer", 0x4F },
151  { "HostAddr", 0x50 },
152  { "Name", 0x51 },
153  { "Port", 0x52 },
154  { "RefID", 0x53 },
155  { "RemoteDB", 0x54 },
156  { "URI", 0x56 },
157  { "Username", 0x57 },
158  { "Version", 0x58 }
159 };
160 
161 #define NUMBER_OF_SYNCSETTINGS_ELEMENTS sizeof(ota_syncsettings_elements)/sizeof(ota_syncsettings_elements[0])
162 
163 /*
164  * Attribute names and values from code page zero. These are defined in ota,
165  * chapter 8.2. Some values are presented as inline strings; in this case
166  * value "INLINE" is used. (Note a quirk: there is an attribute with name
167  * "VALUE".)
168  *
169  * For a documentation of the single attributes see gw/ota_prov_attr.h.
170  */
171 
173  { "TYPE", "ADDRESS", 0x06 },
174  { "TYPE", "URL", 0x07 },
175  { "TYPE", "MMSURL", 0x7c },
176  { "TYPE", "NAME", 0x08 },
177  { "TYPE", "ID", 0x7d },
178  { "TYPE", "BOOKMARK", 0x7f },
179  { "NAME", "BEARER", 0x12 },
180  { "NAME", "PROXY", 0x13 },
181  { "NAME", "PORT", 0x14 },
182  { "NAME", "NAME", 0x15 },
183  { "NAME", "PROXY_TYPE", 0x16 },
184  { "NAME", "URL", 0x17 },
185  { "NAME", "PROXY_AUTHNAME", 0x18 },
186  { "NAME", "PROXY_AUTHSECRET", 0x19 },
187  { "NAME", "SMS_SMSC_ADDRESS", 0x1a },
188  { "NAME", "USSD_SERVICE_CODE", 0x1b },
189  { "NAME", "GPRS_ACCESSPOINTNAME", 0x1c },
190  { "NAME", "PPP_LOGINTYPE", 0x1d },
191  { "NAME", "PROXY_LOGINTYPE", 0x1e },
192  { "NAME", "CSD_DIALSTRING", 0x21 },
193  { "NAME", "CSD_CALLTYPE", 0x28 },
194  { "NAME", "CSD_CALLSPEED", 0x29 },
195  { "NAME", "PPP_AUTHTYPE", 0x22 },
196  { "NAME", "PPP_AUTHNAME", 0x23 },
197  { "NAME", "PPP_AUTHSECRET", 0x24 },
198  { "NAME", "ISP_NAME", 0x7e },
199  { "NAME", "INLINE", 0x10 },
200  { "VALUE", "GSM/CSD", 0x45 },
201  { "VALUE", "GSM/SMS", 0x46 },
202  { "VALUE", "GSM/USSD", 0x47 },
203  { "VALUE", "IS-136/CSD", 0x48 },
204  { "VALUE", "GPRS", 0x49 },
205  { "VALUE", "9200", 0x60 },
206  { "VALUE", "9201", 0x61 },
207  { "VALUE", "9202", 0x62 },
208  { "VALUE", "9203", 0x63 },
209  { "VALUE", "AUTOMATIC", 0x64 },
210  { "VALUE", "MANUAL", 0x65 },
211  { "VALUE", "AUTO", 0x6a },
212  { "VALUE", "9600", 0x6b },
213  { "VALUE", "14400", 0x6c },
214  { "VALUE", "19200", 0x6d },
215  { "VALUE", "28800", 0x6e },
216  { "VALUE", "38400", 0x6f },
217  { "VALUE", "PAP", 0x70 },
218  { "VALUE", "CHAP", 0x71 },
219  { "VALUE", "ANALOGUE", 0x72 },
220  { "VALUE", "ISDN", 0x73 },
221  { "VALUE", "43200", 0x74 },
222  { "VALUE", "57600", 0x75 },
223  { "VALUE", "MSISDN_NO", 0x76 },
224  { "VALUE", "IPV4", 0x77 },
225  { "VALUE", "MS_CHAP", 0x78 },
226  { "VALUE", "INLINE", 0x11 }
227 };
228 
229 #define NUMBER_OF_ATTRIBUTES sizeof(ota_attributes)/sizeof(ota_attributes[0])
230 
231 /*
232  * Defines OMA ProvCont WBXML tokens, see chapter 7.
233  * Value 'INLINE' has to be always last in attribute group, since this
234  * is a break condition within a while loop.
235  */
236 
238  { "VERSION", "1.0", 0x46 },
239  { "VERSION", "INLINE", 0x45 },
240  { "TYPE", "PXLOGICAL", 0x51 },
241  { "TYPE", "PXPHYSICAL", 0x52 },
242  { "TYPE", "PORT", 0x53 },
243  { "TYPE", "VALIDITY", 0x54 },
244  { "TYPE", "NAPDEF", 0x55 },
245  { "TYPE", "BOOTSTRAP", 0x56 },
246  { "TYPE", "VENDORCONFIG", 0x57 },
247  { "TYPE", "PXAUTHINFO", 0x59 },
248  { "TYPE", "NAPAUTHINFO", 0x5A },
249  { "TYPE", "ACCESS", 0x5B },
250  { "TYPE", "BEARERINFO", 0x5C },
251  { "TYPE", "DNS-ADDRINFO", 0x5D },
252  { "TYPE", "CLIENTIDENTITY", 0x58 },
253  { "TYPE", "APPLICATION", 0x55, 1 },
254  { "TYPE", "APPADDR", 0x56, 1 },
255  { "TYPE", "APPAUTH", 0x57, 1 },
256  { "TYPE", "RESOURCE", 0x59, 1 },
257  { "TYPE", "WLAN", 0x5A, 1 },
258  { "TYPE", "SEC-SSID", 0x5B, 1 },
259  { "TYPE", "EAP", 0x5C, 1 },
260  { "TYPE", "CERT", 0x5D, 1 },
261  { "TYPE", "WEPKEY", 0x5E, 1 },
262  { "TYPE", "INLINE", 0x50 },
263  { "NAME", "NAME", 0x7 },
264  { "NAME", "NAP-ADDRESS", 0x8 },
265  { "NAME", "NAP-ADDRTYPE", 0x9 },
266  { "NAME", "CALLTYPE", 0xA },
267  { "NAME", "VALIDUNTIL", 0xB },
268  { "NAME", "AUTHTYPE", 0xC },
269  { "NAME", "AUTHNAME", 0xD },
270  { "NAME", "AUTHSECRET", 0xE },
271  { "NAME", "LINGER", 0xF },
272  { "NAME", "BEARER", 0x10 },
273  { "NAME", "NAPID", 0x11 },
274  { "NAME", "COUNTRY", 0x12 },
275  { "NAME", "NETWORK", 0x13 },
276  { "NAME", "INTERNET", 0x14 },
277  { "NAME", "PROXY-ID", 0x15 },
278  { "NAME", "PROXY-PROVIDER-ID", 0x16 },
279  { "NAME", "DOMAIN", 0x17 },
280  { "NAME", "PROVURL", 0x18 },
281  { "NAME", "PXAUTH-TYPE", 0x19 },
282  { "NAME", "PXAUTH-ID", 0x1A },
283  { "NAME", "PXAUTH-PW", 0x1B },
284  { "NAME", "STARTPAGE", 0x1C },
285  { "NAME", "BASAUTH-ID", 0x1D },
286  { "NAME", "BASAUTH-PW", 0x1E },
287  { "NAME", "PUSHENABLED", 0x1F },
288  { "NAME", "PXADDR", 0x20 },
289  { "NAME", "PXADDRTYPE", 0x21 },
290  { "NAME", "TO-NAPID", 0x22 },
291  { "NAME", "PORTNBR", 0x23 },
292  { "NAME", "SERVICE", 0x24 },
293  { "NAME", "LINKSPEED", 0x25 },
294  { "NAME", "DNLINKSPEED", 0x26 },
295  { "NAME", "LOCAL-ADDR", 0x27 },
296  { "NAME", "LOCAL-ADDRTYPE", 0x28 },
297  { "NAME", "CONTEXT-ALLOW", 0x29 },
298  { "NAME", "TRUST", 0x2A },
299  { "NAME", "MASTER", 0x2B },
300  { "NAME", "SID", 0x2C },
301  { "NAME", "SOC", 0x2D },
302  { "NAME", "WSP-VERSION", 0x2E },
303  { "NAME", "PHYSICAL-PROXY-ID", 0x2F },
304  { "NAME", "CLIENT-ID", 0x30 },
305  { "NAME", "DELIVERY-ERR-SDU", 0x31 },
306  { "NAME", "DELIVERY-ORDER", 0x32 },
307  { "NAME", "TRAFFIC-CLASS", 0x33 },
308  { "NAME", "MAX-SDU-SIZE", 0x34 },
309  { "NAME", "MAX-BITRATE-UPLINK", 0x35 },
310  { "NAME", "MAX-BITRATE-DNLINK", 0x36 },
311  { "NAME", "RESIDUAL-BER", 0x37 },
312  { "NAME", "SDU-ERROR-RATIO", 0x38 },
313  { "NAME", "TRAFFIC-HANDL-PRIO", 0x39 },
314  { "NAME", "TRANSFER-DELAY", 0x3A },
315  { "NAME", "GUARANTEED-BITRATE-UPLINK", 0x3B },
316  { "NAME", "GUARANTEED-BITRATE-DNLINK", 0x3C },
317  { "NAME", "PXADDR-FQDN", 0x3D },
318  { "NAME", "PROXY-PW", 0x3E },
319  { "NAME", "PPGAUTH-TYPE", 0x3F },
320  { "NAME", "PULLENABLED", 0x47 },
321  { "NAME", "DNS-ADDR", 0x48 },
322  { "NAME", "MAX-NUM-RETRY", 0x49 },
323  { "NAME", "FIRST-RETRY-TIMEOUT", 0x4A },
324  { "NAME", "REREG-THRESHOLD", 0x4B },
325  { "NAME", "T-BIT", 0x4C },
326  { "NAME", "AUTH-ENTITY", 0x4E },
327  { "NAME", "SPI", 0x4F },
328  { "NAME", "AACCEPT", 0x2E, 1 },
329  { "NAME", "AAUTHDATA", 0x2F, 1 },
330  { "NAME", "AAUTHLEVEL", 0x30, 1 },
331  { "NAME", "AAUTHNAME", 0x31, 1 },
332  { "NAME", "AAUTHSECRET", 0x32, 1 },
333  { "NAME", "AAUTHTYPE", 0x33, 1 },
334  { "NAME", "ADDR", 0x34, 1 },
335  { "NAME", "ADDRTYPE", 0x35, 1 },
336  { "NAME", "APPID", 0x36, 1 },
337  { "NAME", "APROTOCOL", 0x37, 1 },
338  { "NAME", "PROVIDER-ID", 0x38, 1 },
339  { "NAME", "TO-PROXY", 0x39, 1 },
340  { "NAME", "URI", 0x3A, 1 },
341  { "NAME", "RULE", 0x3B, 1 },
342  { "NAME", "APPREF", 0x3C, 1 },
343  { "NAME", "TO-APPREF", 0x3D, 1 },
344  { "NAME", "PRI-SSID", 0x3E, 1 },
345  { "NAME", "PRI-U-SSID", 0x3F, 1 },
346  { "NAME", "PRI-H-SSID", 0x40, 1 },
347  { "NAME", "S-SSID", 0x41, 1 },
348  { "NAME", "S-U-SSID", 0x42, 1 },
349  { "NAME", "NETMODE", 0x43, 1 },
350  { "NAME", "SECMODE", 0x44, 1 },
351  { "NAME", "EAPTYPE", 0x45, 1 },
352  { "NAME", "USERNAME", 0x46, 1 },
353  { "NAME", "PASSWORD", 0x47, 1 },
354  { "NAME", "REALM", 0x48, 1 },
355  { "NAME", "USE-PSEUD", 0x49, 1 },
356  { "NAME", "ENCAPS", 0x5B, 1 },
357  { "NAME", "VER-SER-REALM", 0x4C, 1 },
358  { "NAME", "CLIENT-AUTH", 0x4D, 1 },
359  { "NAME", "SES-VAL-TIME", 0x4E, 1 },
360  { "NAME", "CIP-SUIT", 0x4F, 1 },
361  { "NAME", "PEAP-V0", 0x60, 1 },
362  { "NAME", "PEAP-V1", 0x61, 1 },
363  { "NAME", "PEAP-V2", 0x62, 1 },
364  { "NAME", "ISS-NAME", 0x63, 1 },
365  { "NAME", "SUB-NAME", 0x64, 1 },
366  { "NAME", "CERT-TYPE", 0x65, 1 },
367  { "NAME", "SER-NUM", 0x66, 1 },
368  { "NAME", "SUB-KEY-ID", 0x67, 1 },
369  { "NAME", "THUMBPRINT", 0x68, 1 },
370  { "NAME", "WPA-PRES-KEY-ASC", 0x69, 1 },
371  { "NAME", "WPA-PRES-KEY-HEX", 0x6A, 1 },
372  { "NAME", "WEPKEYIND", 0x6B, 1 },
373  { "NAME", "WEPAUTHMODE", 0x6C, 1 },
374  { "NAME", "LENGTH", 0x6D, 1 },
375  { "NAME", "INDEX", 0x6E, 1 },
376  { "NAME", "DATA", 0x6F, 1 },
377  { "NAME", "WLANHAND", 0x70, 1 },
378  { "NAME", "EDIT-SET", 0x71, 1 },
379  { "NAME", "VIEW-SET", 0x72, 1 },
380  { "NAME", "FORW-SET", 0x73, 1 },
381  { "NAME", "INLINE", 0x5 },
382  { "VALUE", "IPV4", 0x85 },
383  { "VALUE", "IPV6", 0x86 },
384  { "VALUE", "E164", 0x87 },
385  { "VALUE", "ALPHA", 0x88 },
386  { "VALUE", "APN", 0x89 },
387  { "VALUE", "SCODE", 0x8A },
388  { "VALUE", "TETRA-ITSI", 0x8B },
389  { "VALUE", "MAN", 0x8C },
390  { "VALUE", "APPSRV", 0x8D, 1 },
391  { "VALUE", "OBEX", 0x8E, 1 },
392  { "VALUE", "ANALOG-MODEM", 0x90 },
393  { "VALUE", "V.120", 0x91 },
394  { "VALUE", "V.110", 0x92 },
395  { "VALUE", "X.31", 0x93 },
396  { "VALUE", "BIT-TRANSPARENT", 0x94 },
397  { "VALUE", "DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0x95 },
398  { "VALUE", "PAP", 0x9A },
399  { "VALUE", "CHAP", 0x9B },
400  { "VALUE", "HTTP-BASIC", 0x9C },
401  { "VALUE", "HTTP-DIGEST", 0x9D },
402  { "VALUE", "WTLS-SS", 0x9E },
403  { "VALUE", "MD5", 0x9F },
404  { "VALUE", "GSM-USSD", 0xA2 },
405  { "VALUE", "GSM-SMS", 0xA3 },
406  { "VALUE", "ANSI-136-GUTS", 0xA4 },
407  { "VALUE", "IS-95-CDMA-SMS", 0xA5 },
408  { "VALUE", "IS-95-CDMA-CSD", 0xA6 },
409  { "VALUE", "IS-95-CDMA-PACKET", 0xA7 },
410  { "VALUE", "ANSI-136-CSD", 0xA8 },
411  { "VALUE", "ANSI-136-GPRS", 0xA9 },
412  { "VALUE", "GSM-CSD", 0xAA },
413  { "VALUE", "GSM-GPRS", 0xAB },
414  { "VALUE", "AMPS-CDPD", 0xAC },
415  { "VALUE", "PDC-CSD", 0xAD },
416  { "VALUE", "PDC-PACKET", 0xAE },
417  { "VALUE", "IDEN-SMS", 0xAF },
418  { "VALUE", "IDEN-CSD", 0xB0 },
419  { "VALUE", "IDEN-PACKET", 0xB1 },
420  { "VALUE", "FLEX/REFLEX", 0xB2 },
421  { "VALUE", "PHS-SMS", 0xB3 },
422  { "VALUE", "PHS-CSD", 0xB4 },
423  { "VALUE", "TETRA-SDS", 0xB5 },
424  { "VALUE", "TETRA-PACKET", 0xB6 },
425  { "VALUE", "ANSI-136-GHOST", 0xB7 },
426  { "VALUE", "MOBITEX-MPAK", 0xB8 },
427  { "VALUE", "CDMA2000-1X-SIMPLE-IP", 0xB9 },
428  { "VALUE", "CDMA2000-1X-MOBILE-IP", 0xBA },
429  { "VALUE", "3G-GSM", 0xBB },
430  { "VALUE", "WLAN", 0xBC },
431  { "VALUE", "AUTOBAUDING", 0xC5 },
432  { "VALUE", "CL-WSP", 0xCA },
433  { "VALUE", "CO-WSP", 0xCB },
434  { "VALUE", "CL-SEC-WSP", 0xCC },
435  { "VALUE", "CO-SEC-WSP", 0xCD },
436  { "VALUE", "CL-SEC-WTA", 0xCE },
437  { "VALUE", "CO-SEC-WTA", 0xCF },
438  { "VALUE", "OTA-HTTP-TO", 0xD0 },
439  { "VALUE", "OTA-HTTP-TLS-TO", 0xD1 },
440  { "VALUE", "OTA-HTTP-PO", 0xD2 },
441  { "VALUE", "OTA-HTTP-TLS-PO", 0xD3 },
442  { "VALUE", ",", 0x90, 1 },
443  { "VALUE", "HTTP-", 0x91, 1 },
444  { "VALUE", "BASIC", 0x92, 1 },
445  { "VALUE", "DIGEST", 0x93, 1 },
446  { "VALUE", "AAA", 0xE0 },
447  { "VALUE", "HA", 0xE1 },
448  { "VALUE", "INLINE", 0x6 },
449 };
450 
451 #define OMA_VALUE_TAG 0x06
452 
453 #define NUMBER_OF_OMA_ATTRIBUTES sizeof(oma_ota_attributes)/sizeof(oma_ota_attributes[0])
454 
455 #include "xml_definitions.h"
456 
457 /****************************************************************************
458  *
459  * Prototypes of internal functions. Note that 'Ptr' means here '*'.
460  */
461 
462 static int parse_document(xmlDocPtr document, Octstr *charset,
463  simple_binary_t **ota_binary);
464 static int parse_node(xmlNodePtr node, simple_binary_t **otabxml);
465 static int parse_element(xmlNodePtr node, simple_binary_t **otabxml);
466 static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml);
467 
468 /***************************************************************************
469  *
470  * Implementation of the external function
471  */
472 
473 int ota_compile(Octstr *ota_doc, Octstr *charset, Octstr **ota_binary)
474 {
475  simple_binary_t *otabxml;
476  int ret;
477  xmlDocPtr pDoc;
478  size_t size;
479  char *ota_c_text;
480 
481  *ota_binary = octstr_create("");
482  otabxml = simple_binary_create();
483 
484  octstr_strip_blanks(ota_doc);
485  octstr_shrink_blanks(ota_doc);
486  set_charset(ota_doc, charset);
487  size = octstr_len(ota_doc);
488  ota_c_text = octstr_get_cstr(ota_doc);
489  pDoc = xmlParseMemory(ota_c_text, size);
490 
491  ret = 0;
492  if (pDoc) {
493  ret = parse_document(pDoc, charset, &otabxml);
494  simple_binary_output(*ota_binary, otabxml);
495  xmlFreeDoc(pDoc);
496  } else {
497  xmlFreeDoc(pDoc);
498  octstr_destroy(*ota_binary);
499  simple_binary_destroy(otabxml);
500  error(0, "OTA: No document to parse. Probably an error in OTA source");
501  return -1;
502  }
503 
504  simple_binary_destroy(otabxml);
505 
506  return ret;
507 }
508 
509 /*****************************************************************************
510  *
511  * Implementation of internal functions
512  *
513  * Parse document node. Store wbmxl version number and character set into the
514  * start of the document. There are no wapforum public identifier for ota.
515  * FIXME: Add parse_prologue!
516  */
517 
518 static int parse_document(xmlDocPtr document, Octstr *charset,
519  simple_binary_t **otabxml)
520 {
521  xmlNodePtr node;
522 
523  if (document->intSubset && document->intSubset->ExternalID
524  && strcmp((char *)document->intSubset->ExternalID, "-//WAPFORUM//DTD PROV 1.0//EN") == 0) {
525  /* OMA ProvCont */
526  (*otabxml)->wbxml_version = 0x03; /* WBXML Version number 1.3 */
527  (*otabxml)->public_id = 0x0B; /* Public id for this kind of doc */
528  } else {
529  /* OTA */
530  (*otabxml)->wbxml_version = 0x01; /* WBXML Version number 1.1 */
531  (*otabxml)->public_id = 0x01; /* Public id for an unknown document type */
532  }
533  (*otabxml)->code_page = 0;
534 
535  charset = octstr_create("UTF-8");
536  (*otabxml)->charset = parse_charset(charset);
538 
539  node = xmlDocGetRootElement(document);
540  return parse_node(node, otabxml);
541 }
542 
543 /*
544  * The recursive parsing function for the parsing tree. Function checks the
545  * type of the node, calls for the right parse function for the type, then
546  * calls itself for the first child of the current node if there's one and
547  * after that calls itself for the next child on the list.
548  */
549 
550 static int parse_node(xmlNodePtr node, simple_binary_t **otabxml)
551 {
552  int status = 0;
553 
554  /* Call for the parser function of the node type. */
555  switch (node->type) {
556  case XML_ELEMENT_NODE:
557  status = parse_element(node, otabxml);
558  break;
559  case XML_TEXT_NODE:
560  case XML_COMMENT_NODE:
561  case XML_PI_NODE:
562  /* Text nodes, comments and PIs are ignored. */
563  break;
564  /*
565  * XML has also many other node types, these are not needed with
566  * OTA. Therefore they are assumed to be an error.
567  */
568  default:
569  error(0, "OTA compiler: Unknown XML node in the OTA source.");
570  return -1;
571  break;
572  }
573 
574  /*
575  * If node is an element with content, it will need an end tag after it's
576  * children. The status for it is returned by parse_element.
577  */
578  switch (status) {
579  case 0:
580  if (node->children != NULL && parse_node(node->children, otabxml) == -1)
581  return -1;
582  break;
583  case 1:
584  if (node->children != NULL && parse_node(node->children, otabxml) == -1)
585  return -1;
586  parse_end(otabxml);
587  break;
588  case -1: /* Something went wrong in the parsing. */
589  return -1;
590  break;
591  default:
592  warning(0,"OTA compiler: Undefined return value in a parse function.");
593  return -1;
594  break;
595  }
596 
597  if (node->next != NULL && parse_node(node->next, otabxml) == -1)
598  return -1;
599 
600  return 0;
601 }
602 
603 /*
604  * Parse only valid syncsettings tags. Output element tags as binary
605  * tokens. If the element has CDATA content, output it.
606  * Returns: 1, add an end tag (element node has no children)
607  * 0, do not add an end tag (it has children)
608  * -1, an error occurred
609  */
610 static int parse_ota_syncsettings(xmlNodePtr node, simple_binary_t **otabxml)
611 {
612  Octstr *name, *content;
613  unsigned char status_bits, ota_hex;
614  int add_end_tag;
615  size_t i;
616 
617  name = NULL;
618  content = NULL;
619  name = octstr_create((char *)node->name);
620  if (octstr_len(name) == 0) {
621  goto error;
622  }
623 
624  i = 0;
625  while (i < NUMBER_OF_SYNCSETTINGS_ELEMENTS) {
627  break;
628  ++i;
629  }
630 
632  goto error;
633  }
634 
635  ota_hex = ota_syncsettings_elements[i].token;
637 
638  /* if the node has CDATA content output it.
639  * Else expect child tags */
640  if (!only_blanks((char *)node->children->content)) {
641  content = octstr_create((char *)node->children->content);
642  parse_inline_string(content, otabxml);
643  }
644 
645  add_end_tag = 0;
646  if ((status_bits = element_check_content(node)) > 0) {
647  ota_hex = ota_hex | status_bits;
648  /* If this node has children, the end tag must be added after them. */
649  if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT) {
650  add_end_tag = 1;
651  }
652  }
653 
656  return add_end_tag;
657 
658  error:
659  warning(0, "OTA compiler: Unknown tag '%s' in OTA SyncSettings source",
663  return -1;
664 }
665 
666 /*
667  * Parse an element node. Check if there is a token for an element tag; if not
668  * output the element as a string, else output the token. After that, call
669  * attribute parsing functions
670  * Returns: 1, add an end tag (element node has no children)
671  * 0, do not add an end tag (it has children)
672  * -1, an error occurred
673  */
674 static int parse_element(xmlNodePtr node, simple_binary_t **otabxml)
675 {
676  Octstr *name;
677  size_t i;
678  unsigned char status_bits, ota_hex;
679  int add_end_tag, syncstat;
680  xmlAttrPtr attribute;
681 
682  /* if compiling a syncsettings document there's no need to
683  continue with the parsing of ota or oma tags. */
684  syncstat = -1;
685  if (octstr_search_char((**otabxml).binary, 0x55, 0) == 0) {
686  syncstat = parse_ota_syncsettings(node, otabxml);
687  if (syncstat >= 0) {
688  return syncstat;
689  }
690  }
691 
692  name = octstr_create((char *)node->name);
693  if (octstr_len(name) == 0) {
695  return -1;
696  }
697 
698  i = 0;
699  while (i < NUMBER_OF_ELEMENTS) {
701  break;
702  ++i;
703  }
704 
705  status_bits = 0x00;
706  ota_hex = 0x00;
707  add_end_tag = 0;
708 
709  if (i != NUMBER_OF_ELEMENTS) {
710  ota_hex = ota_elements[i].token;
711  if ((status_bits = element_check_content(node)) > 0) {
712  ota_hex = ota_hex | status_bits;
713  if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
714  add_end_tag = 1;
715  }
716  output_char(ota_hex, otabxml);
717  } else {
718  warning(0, "OTA compiler: Unknown tag '%s' in OTA source", octstr_get_cstr(name));
719  ota_hex = WBXML_LITERAL;
720  if ((status_bits = element_check_content(node)) > 0) {
721  ota_hex = ota_hex | status_bits;
722  /* If this node has children, the end tag must be added after them. */
723  if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
724  add_end_tag = 1;
725  }
726  output_char(ota_hex, otabxml);
728  }
729 
730  if (node->properties != NULL) {
731  attribute = node->properties;
732  while (attribute != NULL) {
733  parse_attribute(attribute, otabxml);
734  attribute = attribute->next;
735  }
736  parse_end(otabxml);
737  }
738 
740  return add_end_tag;
741 }
742 
743 /*
744  * Tokenises an attribute, and in most cases, its value. (Some values are re-
745  * presented as an inline string). Tokenisation is based on tables in ota,
746  * chapters 8.1 and 8.2.
747  * Returns 0 when success, -1 when error.
748  */
749 static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml)
750 {
751  Octstr *name, *value, *valueos, *nameos;
752  unsigned char ota_hex;
753  size_t i, limit;
754  ota_3table_t *alist;
755 
756  name = octstr_create((char *)attr->name);
757 
758  if (attr->children != NULL)
759  value = create_octstr_from_node((char *)attr->children);
760  else
761  value = NULL;
762 
763  if (value == NULL)
764  goto error;
765 
766  /* OMA has it's own dedicated public ID, so use this */
767  if ((*otabxml)->public_id == 0x0B) {
768  alist = oma_ota_attributes;
769  limit = NUMBER_OF_OMA_ATTRIBUTES;
770  } else {
771  alist = ota_attributes;
772  limit = NUMBER_OF_ATTRIBUTES;
773  }
774 
775  i = 0;
776  valueos = NULL;
777  nameos = NULL;
778  while (i < limit) {
779  nameos = octstr_imm(alist[i].name);
780  if (octstr_case_compare(name, nameos) == 0) {
781  if (alist[i].value != NULL) {
782  valueos = octstr_imm(alist[i].value);
783  }
784  if (octstr_case_compare(value, valueos) == 0) {
785  break;
786  }
787  if (octstr_compare(valueos, octstr_imm("INLINE")) == 0) {
788  break;
789  }
790  }
791  ++i;
792  }
793 
794  if (i == limit) {
795  warning(0, "OTA compiler: Unknown attribute '%s' in OTA source, "
796  "with value '%s'.",
798  goto error;
799  }
800 
801  ota_hex = alist[i].token;
802  /* if not inline used */
803  if (octstr_compare(valueos, octstr_imm("INLINE")) != 0) {
804  /* Switch code page. */
805  if (alist[i].code_page != (*otabxml)->code_page) {
806  output_char(0, otabxml);
807  output_char(alist[i].code_page, otabxml);
808  (*otabxml)->code_page = alist[i].code_page;
809  }
810  /* if OMA add value tag */
811  if ((*otabxml)->public_id == 0x0B && name
812  && octstr_case_compare(name, octstr_imm("value")) == 0)
813  output_char(OMA_VALUE_TAG, otabxml);
814  output_char(ota_hex, otabxml);
815  } else {
816  /* Switch code page. */
817  if (alist[i].code_page != (*otabxml)->code_page) {
818  output_char(0, otabxml);
819  output_char(alist[i].code_page, otabxml);
820  (*otabxml)->code_page = alist[i].code_page;
821  }
822  output_char(ota_hex, otabxml);
823  parse_inline_string(value, otabxml);
824  }
825 
828  return 0;
829 
830 error:
833  return -1;
834 }
void error(int err, const char *fmt,...)
Definition: log.c:648
int ota_compile(Octstr *ota_doc, Octstr *charset, Octstr **ota_binary)
Definition: ota_compiler.c:473
int size
Definition: wsasm.c:84
void output_octet_string(Octstr *os, simple_binary_t **sibxml)
Definition: xml_shared.c:349
unsigned char element_check_content(xmlNodePtr node)
Definition: xml_shared.c:242
unsigned char token
Definition: ota_compiler.c:102
#define NUMBER_OF_SYNCSETTINGS_ELEMENTS
Definition: ota_compiler.c:161
static ota_2table_t ota_syncsettings_elements[]
Definition: ota_compiler.c:139
#define NUMBER_OF_ATTRIBUTES
Definition: ota_compiler.c:229
static ota_3table_t ota_attributes[]
Definition: ota_compiler.c:172
void octstr_strip_blanks(Octstr *text)
Definition: octstr.c:1346
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static ota_2table_t ota_elements[]
Definition: ota_compiler.c:125
long octstr_search_char(const Octstr *ostr, int ch, long pos)
Definition: octstr.c:1012
static ota_3table_t oma_ota_attributes[]
Definition: ota_compiler.c:237
Octstr * charset
Definition: test_ota.c:68
void simple_binary_destroy(simple_binary_t *binary)
Definition: xml_shared.c:298
#define OMA_VALUE_TAG
Definition: ota_compiler.c:451
static int parse_node(xmlNodePtr node, simple_binary_t **otabxml)
Definition: ota_compiler.c:550
void parse_inline_string(Octstr *temp, simple_binary_t **binary)
Definition: xml_shared.c:339
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
int parse_charset(Octstr *os)
Definition: xml_shared.c:189
int token
Definition: wslexer.c:159
#define WBXML_LITERAL
#define octstr_duplicate(ostr)
Definition: octstr.h:187
char * name
Definition: smsc_cimd2.c:212
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:903
static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml)
Definition: ota_compiler.c:749
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
static int parse_ota_syncsettings(xmlNodePtr node, simple_binary_t **otabxml)
Definition: ota_compiler.c:610
static int parse_element(xmlNodePtr node, simple_binary_t **otabxml)
Definition: ota_compiler.c:674
#define NUMBER_OF_ELEMENTS
Definition: ota_compiler.c:133
long octstr_len(const Octstr *ostr)
Definition: octstr.c:342
void simple_binary_output(Octstr *os, simple_binary_t *binary)
Definition: xml_shared.c:311
Definition: octstr.c:118
unsigned char code_page
Definition: ota_compiler.c:115
static int parse_document(xmlDocPtr document, Octstr *charset, simple_binary_t **ota_binary)
Definition: ota_compiler.c:518
void set_charset(Octstr *document, Octstr *charset)
Definition: xml_shared.c:111
int only_blanks(const char *text)
Definition: xml_shared.c:171
void parse_end(simple_binary_t **binary)
Definition: xml_shared.c:321
#define NUMBER_OF_OMA_ATTRIBUTES
Definition: ota_compiler.c:453
void output_char(int byte, simple_binary_t **binary)
Definition: xml_shared.c:326
#define WBXML_CONTENT_BIT
static Octstr * content
Definition: mtbatch.c:87
#define create_octstr_from_node(node)
simple_binary_t * simple_binary_create(void)
Definition: xml_shared.c:284
void octstr_shrink_blanks(Octstr *text)
Definition: octstr.c:1433
unsigned char token
Definition: ota_compiler.c:114
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.