Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ota_compiler.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * ota_compiler.c: Tokenizes OTA provisioning documents 
00059  * 
00060  * This compiler handles the following OTA config formats:
00061  * 
00062  *   - Nokia/Ericsson OTA settings specificaion. DTD is defined in 
00063  *     Over The Air Settings Specification (hereafter called OTA), chapter 6. 
00064  *     (See http://www.americas.nokia.com/messaging/default.asp)
00065  * 
00066  *   - OMA OTA client provisionig content specification, as defined in
00067  *     document OMA-WAP-ProvCont-V1.1-20050428-C.pdf. (hereafter called OMA)
00068  *     (See http://www.openmobilealliance.com/release_program/cp_v1_1.htm)
00069  * 
00070  * Histrorically the Nokia/Ericsson OTA config format was the first scratch 
00071  * in allowing remote WAP profile configuration via SMS bearer. While the WAP
00072  * Forum transfered into the Open Mobile Alliance (OMA), the technical working
00073  * groups addopted the provisioning concept to a more generic OTA provisioning
00074  * concept. The OMA client provisioning specs v1.1 are part of the WAP 2.0 
00075  * protocol stack. 
00076  * 
00077  * Aarno Syvänen for Wiral Ltd
00078  * Stipe Tolj <stolj@kannel.org> for Wapme Systems AG
00079  * Paul Bagyenda for digital solutions Ltd.
00080  */
00081 
00082 #include <ctype.h>
00083 #include <libxml/xmlmemory.h>
00084 #include <libxml/tree.h>
00085 #include <libxml/debugXML.h>
00086 #include <libxml/encoding.h>
00087 
00088 #include "shared.h"
00089 #include "xml_shared.h"
00090 #include "ota_compiler.h"
00091 
00092 /****************************************************************************
00093  *
00094  * Global variables
00095  *
00096  * Two token table types, one and two token fields
00097  */
00098 
00099 struct ota_2table_t {
00100     char *name;
00101     unsigned char token;
00102 };
00103 
00104 typedef struct ota_2table_t ota_2table_t;
00105 
00106 /*
00107  * Ota tokenizes whole of attribute value, or uses an inline string. See ota, 
00108  * chapter 8.2.
00109  */
00110 struct ota_3table_t {
00111     char *name;
00112     char *value;
00113     unsigned char token;
00114     unsigned char code_page;
00115 };
00116 
00117 typedef struct ota_3table_t ota_3table_t;
00118 
00119 /*
00120  * Elements from tag code page zero. These are defined in OTA, chapter 8.1
00121  * and OMA, chapter 7.1.
00122  */
00123 
00124 static ota_2table_t ota_elements[] = {
00125     { "SYNCSETTINGS", 0x15 },
00126     { "WAP-PROVISIONINGDOC", 0x05 },
00127     { "CHARACTERISTIC-LIST", 0x05 },
00128     { "CHARACTERISTIC", 0x06 },
00129     { "PARM", 0x07 }
00130 };
00131 
00132 #define NUMBER_OF_ELEMENTS sizeof(ota_elements)/sizeof(ota_elements[0])
00133 
00134 /*
00135  * SYNCSETTINGS tags are defined in OTA specs 7.0, chapter 11.1
00136  */
00137 
00138 static ota_2table_t ota_syncsettings_elements[] = {
00139     { "Version", 0x58 },
00140     { "HostAddr", 0x50 },
00141     { "Port", 0x52 },
00142     { "RemoteDB", 0x54 },
00143     { "CTType", 0x4E },
00144     { "CTVer", 0x4F },
00145     { "URI", 0x56 },
00146     { "Name", 0x51 },
00147     { "Auth", 0x47 },
00148     { "AuthLevel", 0x48 },
00149     { "AuthScheme", 0x49 },
00150     { "Username", 0x57 },
00151     { "Cred", 0x4D },
00152     { "ConRef", 0x4B },
00153     { "ConType", 0x4E },
00154     { "Bearer", 0x4A },
00155     { "AddrType", 0x46 },
00156     { "Addr", 0x45 },
00157     { "RefID", 0x53 }
00158 };
00159 
00160 #define NUMBER_OF_SYNCSETTINGS_ELEMENTS sizeof(ota_syncsettings_elements)/sizeof(ota_syncsettings_elements[0])
00161 
00162 /*
00163  * Attribute names and values from code page zero. These are defined in ota,
00164  * chapter 8.2. Some values are presented as inline strings; in this case 
00165  * value "INLINE" is used. (Note a quirk: there is an attribute with name 
00166  * "VALUE".)
00167  *
00168  * For a documentation of the single attributes see gw/ota_prov_attr.h.
00169  */
00170 
00171 static ota_3table_t ota_attributes[] = {
00172     { "TYPE", "ADDRESS", 0x06 },
00173     { "TYPE", "URL", 0x07 },
00174     { "TYPE", "MMSURL", 0x7c },
00175     { "TYPE", "NAME", 0x08 },
00176     { "TYPE", "ID", 0x7d },
00177     { "TYPE", "BOOKMARK", 0x7f },
00178     { "NAME", "BEARER", 0x12 },
00179     { "NAME", "PROXY", 0x13 },
00180     { "NAME", "PORT", 0x14 },
00181     { "NAME", "NAME", 0x15 },
00182     { "NAME", "PROXY_TYPE", 0x16 },
00183     { "NAME", "URL", 0x17 },
00184     { "NAME", "PROXY_AUTHNAME", 0x18 },
00185     { "NAME", "PROXY_AUTHSECRET", 0x19 },
00186     { "NAME", "SMS_SMSC_ADDRESS", 0x1a },
00187     { "NAME", "USSD_SERVICE_CODE", 0x1b },
00188     { "NAME", "GPRS_ACCESSPOINTNAME", 0x1c },
00189     { "NAME", "PPP_LOGINTYPE", 0x1d },
00190     { "NAME", "PROXY_LOGINTYPE", 0x1e },
00191     { "NAME", "CSD_DIALSTRING", 0x21 },
00192     { "NAME", "CSD_CALLTYPE", 0x28 },
00193     { "NAME", "CSD_CALLSPEED", 0x29 },
00194     { "NAME", "PPP_AUTHTYPE", 0x22 },
00195     { "NAME", "PPP_AUTHNAME", 0x23 },
00196     { "NAME", "PPP_AUTHSECRET", 0x24 },
00197     { "NAME", "ISP_NAME", 0x7e },
00198     { "NAME", "INLINE", 0x10 },
00199     { "VALUE", "GSM/CSD", 0x45 },
00200     { "VALUE", "GSM/SMS", 0x46 },
00201     { "VALUE", "GSM/USSD", 0x47 },
00202     { "VALUE", "IS-136/CSD", 0x48 },
00203     { "VALUE", "GPRS", 0x49 },
00204     { "VALUE", "9200", 0x60 },
00205     { "VALUE", "9201", 0x61 },
00206     { "VALUE", "9202", 0x62 },
00207     { "VALUE", "9203", 0x63 },
00208     { "VALUE", "AUTOMATIC", 0x64 },
00209     { "VALUE", "MANUAL", 0x65 },
00210     { "VALUE", "AUTO", 0x6a },
00211     { "VALUE", "9600", 0x6b },
00212     { "VALUE", "14400", 0x6c },
00213     { "VALUE", "19200", 0x6d },
00214     { "VALUE", "28800", 0x6e },
00215     { "VALUE", "38400", 0x6f },
00216     { "VALUE", "PAP", 0x70 },
00217     { "VALUE", "CHAP", 0x71 },
00218     { "VALUE", "ANALOGUE", 0x72 },
00219     { "VALUE", "ISDN", 0x73 },
00220     { "VALUE", "43200", 0x74 },
00221     { "VALUE", "57600", 0x75 },
00222     { "VALUE", "MSISDN_NO", 0x76 },
00223     { "VALUE", "IPV4", 0x77 },
00224     { "VALUE", "MS_CHAP", 0x78 },
00225     { "VALUE", "INLINE", 0x11 }
00226 };
00227 
00228 #define NUMBER_OF_ATTRIBUTES sizeof(ota_attributes)/sizeof(ota_attributes[0])
00229 
00230 /*
00231  * Defines OMA ProvCont WBXML tokens, see chapter 7.
00232  * Value 'INLINE' has to be always last in attribute group, since this
00233  * is a break condition within a while loop.
00234  */
00235 
00236 static ota_3table_t oma_ota_attributes[] = {
00237     { "VERSION", "1.0", 0x46 },
00238     { "VERSION", "INLINE", 0x45 },  
00239     { "TYPE", "PXLOGICAL", 0x51 },
00240     { "TYPE", "PXPHYSICAL", 0x52 },
00241     { "TYPE", "PORT", 0x53 },
00242     { "TYPE", "VALIDITY", 0x54 },
00243     { "TYPE", "NAPDEF", 0x55 },
00244     { "TYPE", "BOOTSTRAP", 0x56 },
00245     { "TYPE", "VENDORCONFIG", 0x57 },
00246     { "TYPE", "PXAUTHINFO", 0x59 },
00247     { "TYPE", "NAPAUTHINFO", 0x5A },
00248     { "TYPE", "ACCESS", 0x5B },
00249     { "TYPE", "BEARERINFO", 0x5C },
00250     { "TYPE", "DNS-ADDRINFO", 0x5D },
00251     { "TYPE", "CLIENTIDENTITY", 0x58 },
00252     { "TYPE", "APPLICATION", 0x55, 1 },
00253     { "TYPE", "APPADDR", 0x56, 1 },
00254     { "TYPE", "APPAUTH", 0x57, 1 },
00255     { "TYPE", "RESOURCE", 0x59, 1 },
00256     { "TYPE", "WLAN", 0x5A, 1 },
00257     { "TYPE", "SEC-SSID", 0x5B, 1 },
00258     { "TYPE", "EAP", 0x5C, 1 },
00259     { "TYPE", "CERT", 0x5D, 1 },
00260     { "TYPE", "WEPKEY", 0x5E, 1 },
00261     { "TYPE", "INLINE", 0x50 },
00262     { "NAME", "NAME", 0x7 },
00263     { "NAME", "NAP-ADDRESS", 0x8 },
00264     { "NAME", "NAP-ADDRTYPE", 0x9 },
00265     { "NAME", "CALLTYPE", 0xA },
00266     { "NAME", "VALIDUNTIL", 0xB },
00267     { "NAME", "AUTHTYPE", 0xC },
00268     { "NAME", "AUTHNAME", 0xD },
00269     { "NAME", "AUTHSECRET", 0xE },
00270     { "NAME", "LINGER", 0xF },
00271     { "NAME", "BEARER", 0x10 },
00272     { "NAME", "NAPID", 0x11 },
00273     { "NAME", "COUNTRY", 0x12 },
00274     { "NAME", "NETWORK", 0x13 },
00275     { "NAME", "INTERNET", 0x14 },
00276     { "NAME", "PROXY-ID", 0x15 },
00277     { "NAME", "PROXY-PROVIDER-ID", 0x16 },
00278     { "NAME", "DOMAIN", 0x17 },
00279     { "NAME", "PROVURL", 0x18 },
00280     { "NAME", "PXAUTH-TYPE", 0x19 },
00281     { "NAME", "PXAUTH-ID", 0x1A },
00282     { "NAME", "PXAUTH-PW", 0x1B },
00283     { "NAME", "STARTPAGE", 0x1C },
00284     { "NAME", "BASAUTH-ID", 0x1D },
00285     { "NAME", "BASAUTH-PW", 0x1E },
00286     { "NAME", "PUSHENABLED", 0x1F },
00287     { "NAME", "PXADDR", 0x20 },
00288     { "NAME", "PXADDRTYPE", 0x21 },
00289     { "NAME", "TO-NAPID", 0x22 },
00290     { "NAME", "PORTNBR", 0x23 },
00291     { "NAME", "SERVICE", 0x24 },
00292     { "NAME", "LINKSPEED", 0x25 },
00293     { "NAME", "DNLINKSPEED", 0x26 },
00294     { "NAME", "LOCAL-ADDR", 0x27 },
00295     { "NAME", "LOCAL-ADDRTYPE", 0x28 },
00296     { "NAME", "CONTEXT-ALLOW", 0x29 },
00297     { "NAME", "TRUST", 0x2A },
00298     { "NAME", "MASTER", 0x2B },
00299     { "NAME", "SID", 0x2C },
00300     { "NAME", "SOC", 0x2D },
00301     { "NAME", "WSP-VERSION", 0x2E },
00302     { "NAME", "PHYSICAL-PROXY-ID", 0x2F },
00303     { "NAME", "CLIENT-ID", 0x30 },
00304     { "NAME", "DELIVERY-ERR-SDU", 0x31 },
00305     { "NAME", "DELIVERY-ORDER", 0x32 },
00306     { "NAME", "TRAFFIC-CLASS", 0x33 },
00307     { "NAME", "MAX-SDU-SIZE", 0x34 },
00308     { "NAME", "MAX-BITRATE-UPLINK", 0x35 },
00309     { "NAME", "MAX-BITRATE-DNLINK", 0x36 },
00310     { "NAME", "RESIDUAL-BER", 0x37 },
00311     { "NAME", "SDU-ERROR-RATIO", 0x38 },
00312     { "NAME", "TRAFFIC-HANDL-PRIO", 0x39 },
00313     { "NAME", "TRANSFER-DELAY", 0x3A },
00314     { "NAME", "GUARANTEED-BITRATE-UPLINK", 0x3B },
00315     { "NAME", "GUARANTEED-BITRATE-DNLINK", 0x3C },
00316     { "NAME", "PXADDR-FQDN", 0x3D },
00317     { "NAME", "PROXY-PW", 0x3E },
00318     { "NAME", "PPGAUTH-TYPE", 0x3F },
00319     { "NAME", "PULLENABLED", 0x47 },
00320     { "NAME", "DNS-ADDR", 0x48 },
00321     { "NAME", "MAX-NUM-RETRY", 0x49 },
00322     { "NAME", "FIRST-RETRY-TIMEOUT", 0x4A },
00323     { "NAME", "REREG-THRESHOLD", 0x4B },
00324     { "NAME", "T-BIT", 0x4C },
00325     { "NAME", "AUTH-ENTITY", 0x4E },
00326     { "NAME", "SPI", 0x4F },
00327     { "NAME", "AACCEPT", 0x2E, 1 },
00328     { "NAME", "AAUTHDATA", 0x2F, 1 },
00329     { "NAME", "AAUTHLEVEL", 0x30, 1 },
00330     { "NAME", "AAUTHNAME", 0x31, 1 },
00331     { "NAME", "AAUTHSECRET", 0x32, 1 },
00332     { "NAME", "AAUTHTYPE", 0x33, 1 },
00333     { "NAME", "ADDR", 0x34, 1 },
00334     { "NAME", "ADDRTYPE", 0x35, 1 },
00335     { "NAME", "APPID", 0x36, 1 },
00336     { "NAME", "APROTOCOL", 0x37, 1 },
00337     { "NAME", "PROVIDER-ID", 0x38, 1 },
00338     { "NAME", "TO-PROXY", 0x39, 1 },
00339     { "NAME", "URI", 0x3A, 1 },
00340     { "NAME", "RULE", 0x3B, 1 },
00341     { "NAME", "APPREF", 0x3C, 1 },
00342     { "NAME", "TO-APPREF", 0x3D, 1 },
00343     { "NAME", "PRI-SSID", 0x3E, 1 },
00344     { "NAME", "PRI-U-SSID", 0x3F, 1 },
00345     { "NAME", "PRI-H-SSID", 0x40, 1 },
00346     { "NAME", "S-SSID", 0x41, 1 },
00347     { "NAME", "S-U-SSID", 0x42, 1 },
00348     { "NAME", "NETMODE", 0x43, 1 },
00349     { "NAME", "SECMODE", 0x44, 1 },
00350     { "NAME", "EAPTYPE", 0x45, 1 },
00351     { "NAME", "USERNAME", 0x46, 1 },
00352     { "NAME", "PASSWORD", 0x47, 1 },
00353     { "NAME", "REALM", 0x48, 1 },
00354     { "NAME", "USE-PSEUD", 0x49, 1 },
00355     { "NAME", "ENCAPS", 0x5B, 1 },
00356     { "NAME", "VER-SER-REALM", 0x4C, 1 },
00357     { "NAME", "CLIENT-AUTH", 0x4D, 1 },
00358     { "NAME", "SES-VAL-TIME", 0x4E, 1 },
00359     { "NAME", "CIP-SUIT", 0x4F, 1 },
00360     { "NAME", "PEAP-V0", 0x60, 1 },
00361     { "NAME", "PEAP-V1", 0x61, 1 },
00362     { "NAME", "PEAP-V2", 0x62, 1 },
00363     { "NAME", "ISS-NAME", 0x63, 1 },
00364     { "NAME", "SUB-NAME", 0x64, 1 },
00365     { "NAME", "CERT-TYPE", 0x65, 1 },
00366     { "NAME", "SER-NUM", 0x66, 1 },
00367     { "NAME", "SUB-KEY-ID", 0x67, 1 },
00368     { "NAME", "THUMBPRINT", 0x68, 1 },
00369     { "NAME", "WPA-PRES-KEY-ASC", 0x69, 1 },
00370     { "NAME", "WPA-PRES-KEY-HEX", 0x6A, 1 },
00371     { "NAME", "WEPKEYIND", 0x6B, 1 },
00372     { "NAME", "WEPAUTHMODE", 0x6C, 1 },
00373     { "NAME", "LENGTH", 0x6D, 1 },
00374     { "NAME", "INDEX", 0x6E, 1 },
00375     { "NAME", "DATA", 0x6F, 1 },
00376     { "NAME", "WLANHAND", 0x70, 1 },
00377     { "NAME", "EDIT-SET", 0x71, 1 },
00378     { "NAME", "VIEW-SET", 0x72, 1 },
00379     { "NAME", "FORW-SET", 0x73, 1 },
00380     { "NAME", "INLINE", 0x5 },
00381     { "VALUE", "IPV4", 0x85 },
00382     { "VALUE", "IPV6", 0x86 },
00383     { "VALUE", "E164", 0x87 },
00384     { "VALUE", "ALPHA", 0x88 },
00385     { "VALUE", "APN", 0x89 },
00386     { "VALUE", "SCODE", 0x8A },
00387     { "VALUE", "TETRA-ITSI", 0x8B },
00388     { "VALUE", "MAN", 0x8C },
00389     { "VALUE", "APPSRV", 0x8D, 1 },
00390     { "VALUE", "OBEX", 0x8E, 1 },
00391     { "VALUE", "ANALOG-MODEM", 0x90 },
00392     { "VALUE", "V.120", 0x91 },
00393     { "VALUE", "V.110", 0x92 },
00394     { "VALUE", "X.31", 0x93 },
00395     { "VALUE", "BIT-TRANSPARENT", 0x94 },
00396     { "VALUE", "DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0x95 },
00397     { "VALUE", "PAP", 0x9A },
00398     { "VALUE", "CHAP", 0x9B },
00399     { "VALUE", "HTTP-BASIC", 0x9C },
00400     { "VALUE", "HTTP-DIGEST", 0x9D },
00401     { "VALUE", "WTLS-SS", 0x9E },
00402     { "VALUE", "MD5", 0x9F },
00403     { "VALUE", "GSM-USSD", 0xA2 },
00404     { "VALUE", "GSM-SMS", 0xA3 },
00405     { "VALUE", "ANSI-136-GUTS", 0xA4 },
00406     { "VALUE", "IS-95-CDMA-SMS", 0xA5 },
00407     { "VALUE", "IS-95-CDMA-CSD", 0xA6 },
00408     { "VALUE", "IS-95-CDMA-PACKET", 0xA7 },
00409     { "VALUE", "ANSI-136-CSD", 0xA8 },
00410     { "VALUE", "ANSI-136-GPRS", 0xA9 },
00411     { "VALUE", "GSM-CSD", 0xAA },
00412     { "VALUE", "GSM-GPRS", 0xAB },
00413     { "VALUE", "AMPS-CDPD", 0xAC },
00414     { "VALUE", "PDC-CSD", 0xAD },
00415     { "VALUE", "PDC-PACKET", 0xAE },
00416     { "VALUE", "IDEN-SMS", 0xAF },
00417     { "VALUE", "IDEN-CSD", 0xB0 },
00418     { "VALUE", "IDEN-PACKET", 0xB1 },
00419     { "VALUE", "FLEX/REFLEX", 0xB2 },
00420     { "VALUE", "PHS-SMS", 0xB3 },
00421     { "VALUE", "PHS-CSD", 0xB4 },
00422     { "VALUE", "TETRA-SDS", 0xB5 },
00423     { "VALUE", "TETRA-PACKET", 0xB6 },
00424     { "VALUE", "ANSI-136-GHOST", 0xB7 },
00425     { "VALUE", "MOBITEX-MPAK", 0xB8 },
00426     { "VALUE", "CDMA2000-1X-SIMPLE-IP", 0xB9 },
00427     { "VALUE", "CDMA2000-1X-MOBILE-IP", 0xBA },
00428     { "VALUE", "3G-GSM", 0xBB },
00429     { "VALUE", "WLAN", 0xBC },
00430     { "VALUE", "AUTOBAUDING", 0xC5 },
00431     { "VALUE", "CL-WSP", 0xCA },
00432     { "VALUE", "CO-WSP", 0xCB },
00433     { "VALUE", "CL-SEC-WSP", 0xCC },
00434     { "VALUE", "CO-SEC-WSP", 0xCD },
00435     { "VALUE", "CL-SEC-WTA", 0xCE },
00436     { "VALUE", "CO-SEC-WTA", 0xCF },
00437     { "VALUE", "OTA-HTTP-TO", 0xD0 },
00438     { "VALUE", "OTA-HTTP-TLS-TO", 0xD1 },
00439     { "VALUE", "OTA-HTTP-PO", 0xD2 },
00440     { "VALUE", "OTA-HTTP-TLS-PO", 0xD3 },
00441     { "VALUE", ",", 0x90, 1 },
00442     { "VALUE", "HTTP-", 0x91, 1 },
00443     { "VALUE", "BASIC", 0x92, 1 },
00444     { "VALUE", "DIGEST", 0x93, 1 },
00445     { "VALUE", "AAA", 0xE0 },
00446     { "VALUE", "HA", 0xE1 },
00447     { "VALUE", "INLINE", 0x6 },     
00448 };
00449 
00450 #define OMA_VALUE_TAG 0x06
00451 
00452 #define NUMBER_OF_OMA_ATTRIBUTES sizeof(oma_ota_attributes)/sizeof(oma_ota_attributes[0])
00453 
00454 #include "xml_definitions.h"
00455 
00456 /****************************************************************************
00457  *
00458  * Prototypes of internal functions. Note that 'Ptr' means here '*'.
00459  */
00460 
00461 static int parse_document(xmlDocPtr document, Octstr *charset, 
00462                           simple_binary_t **ota_binary);
00463 static int parse_node(xmlNodePtr node, simple_binary_t **otabxml);    
00464 static int parse_element(xmlNodePtr node, simple_binary_t **otabxml);
00465 static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml); 
00466 
00467 /***************************************************************************
00468  *
00469  * Implementation of the external function
00470  */
00471 
00472 int ota_compile(Octstr *ota_doc, Octstr *charset, Octstr **ota_binary)
00473 {
00474     simple_binary_t *otabxml;
00475     int ret;
00476     xmlDocPtr pDoc;
00477     size_t size;
00478     char *ota_c_text;
00479 
00480     *ota_binary = octstr_create(""); 
00481     otabxml = simple_binary_create();
00482 
00483     octstr_strip_blanks(ota_doc);
00484     octstr_shrink_blanks(ota_doc);
00485     set_charset(ota_doc, charset);
00486     size = octstr_len(ota_doc);
00487     ota_c_text = octstr_get_cstr(ota_doc);
00488     pDoc = xmlParseMemory(ota_c_text, size);
00489 
00490     ret = 0;
00491     if (pDoc) {
00492         ret = parse_document(pDoc, charset, &otabxml);
00493         simple_binary_output(*ota_binary, otabxml);
00494         xmlFreeDoc(pDoc);
00495     } else {
00496         xmlFreeDoc(pDoc);
00497         octstr_destroy(*ota_binary);
00498         simple_binary_destroy(otabxml);
00499         error(0, "OTA: No document to parse. Probably an error in OTA source");
00500         return -1;
00501     }
00502 
00503     simple_binary_destroy(otabxml);
00504 
00505     return ret;
00506 }
00507 
00508 /*****************************************************************************
00509  *
00510  * Implementation of internal functions
00511  *
00512  * Parse document node. Store wbmxl version number and character set into the 
00513  * start of the document. There are no wapforum public identifier for ota. 
00514  * FIXME: Add parse_prologue!
00515  */
00516 
00517 static int parse_document(xmlDocPtr document, Octstr *charset, 
00518                           simple_binary_t **otabxml)
00519 {
00520     xmlNodePtr node;
00521 
00522     if (document->intSubset && document->intSubset->ExternalID 
00523         && strcmp((char *)document->intSubset->ExternalID, "-//WAPFORUM//DTD PROV 1.0//EN") == 0) {
00524         /* OMA ProvCont */
00525         (*otabxml)->wbxml_version = 0x03; /* WBXML Version number 1.3  */
00526         (*otabxml)->public_id = 0x0B; /* Public id for this kind of doc */  
00527     } else {
00528         /* OTA */
00529         (*otabxml)->wbxml_version = 0x01; /* WBXML Version number 1.1  */
00530         (*otabxml)->public_id = 0x01; /* Public id for an unknown document type */
00531     }
00532     (*otabxml)->code_page = 0;
00533     
00534     charset = octstr_create("UTF-8");
00535     (*otabxml)->charset = parse_charset(charset);
00536     octstr_destroy(charset);
00537 
00538     node = xmlDocGetRootElement(document);
00539     return parse_node(node, otabxml);
00540 }
00541 
00542 /*
00543  * The recursive parsing function for the parsing tree. Function checks the 
00544  * type of the node, calls for the right parse function for the type, then 
00545  * calls itself for the first child of the current node if there's one and 
00546  * after that calls itself for the next child on the list.
00547  */
00548 
00549 static int parse_node(xmlNodePtr node, simple_binary_t **otabxml)
00550 {
00551     int status = 0;
00552     
00553     /* Call for the parser function of the node type. */
00554     switch (node->type) {
00555         case XML_ELEMENT_NODE:
00556             status = parse_element(node, otabxml);
00557             break;
00558         case XML_TEXT_NODE:
00559         case XML_COMMENT_NODE:
00560         case XML_PI_NODE:
00561             /* Text nodes, comments and PIs are ignored. */
00562             break;
00563         /*
00564          * XML has also many other node types, these are not needed with 
00565          * OTA. Therefore they are assumed to be an error.
00566          */
00567         default:
00568             error(0, "OTA compiler: Unknown XML node in the OTA source.");
00569             return -1;
00570             break;
00571     }
00572 
00573     /* 
00574      * If node is an element with content, it will need an end tag after it's
00575      * children. The status for it is returned by parse_element.
00576      */
00577     switch (status) {
00578         case 0:
00579             if (node->children != NULL && parse_node(node->children, otabxml) == -1)
00580                 return -1;
00581             break;
00582         case 1:
00583             if (node->children != NULL && parse_node(node->children, otabxml) == -1)
00584                 return -1;
00585             parse_end(otabxml);
00586             break;
00587         case -1: /* Something went wrong in the parsing. */
00588             return -1;
00589             break;
00590         default:
00591             warning(0,"OTA compiler: Undefined return value in a parse function.");
00592             return -1;
00593             break;
00594     }
00595 
00596     if (node->next != NULL && parse_node(node->next, otabxml) == -1)
00597         return -1;
00598 
00599     return 0;
00600 }
00601 
00602 /*
00603  * Parse only valid syncsettings tags. Output element tags as binary
00604  *  tokens. If the element has CDATA content, output it.
00605  * Returns:      1, add an end tag (element node has no children)
00606  *               0, do not add an end tag (it has children)
00607  *              -1, an error occurred
00608  */
00609 static int parse_ota_syncsettings(xmlNodePtr node, simple_binary_t **otabxml)
00610 {
00611     Octstr *name, *content;
00612     unsigned char status_bits, ota_hex;
00613     int add_end_tag;
00614     size_t i;
00615 
00616     name = NULL;
00617     content = NULL;
00618     name = octstr_create((char *)node->name);
00619     if (octstr_len(name) == 0) {
00620         goto error;
00621     }
00622 
00623     i = 0;
00624     while (i < NUMBER_OF_SYNCSETTINGS_ELEMENTS) {
00625         if (octstr_case_compare(name, octstr_imm(ota_syncsettings_elements[i].name)) == 0)
00626             break;
00627         ++i;
00628     }
00629 
00630     if (i == NUMBER_OF_SYNCSETTINGS_ELEMENTS) {
00631         goto error;
00632     }
00633 
00634     ota_hex = ota_syncsettings_elements[i].token;
00635     output_char(ota_syncsettings_elements[i].token, otabxml);
00636 
00637     /* if the node has CDATA content output it. 
00638      * Else expect child tags */
00639     if (!only_blanks((char *)node->children->content)) {
00640         content = octstr_create((char *)node->children->content);
00641         parse_inline_string(content, otabxml);
00642     }
00643 
00644     add_end_tag = 0;
00645     if ((status_bits = element_check_content(node)) > 0) {
00646         ota_hex = ota_hex | status_bits;
00647         /* If this node has children, the end tag must be added after them. */
00648         if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT) {
00649             add_end_tag = 1;
00650         }
00651     }
00652 
00653     octstr_destroy(content);
00654     octstr_destroy(name);
00655     return add_end_tag;
00656 
00657     error:
00658         warning(0, "OTA compiler: Unknown tag '%s' in OTA SyncSettings source",
00659                 octstr_get_cstr(name));
00660         octstr_destroy(content);
00661         octstr_destroy(name);
00662         return -1;
00663 }
00664 
00665 /*
00666  * Parse an element node. Check if there is a token for an element tag; if not
00667  * output the element as a string, else output the token. After that, call 
00668  * attribute parsing functions
00669  * Returns:      1, add an end tag (element node has no children)
00670  *               0, do not add an end tag (it has children)
00671  *              -1, an error occurred
00672  */
00673 static int parse_element(xmlNodePtr node, simple_binary_t **otabxml)
00674 {
00675     Octstr *name;
00676     size_t i;
00677     unsigned char status_bits, ota_hex;
00678     int add_end_tag, syncstat;
00679     xmlAttrPtr attribute;
00680 
00681     /* if compiling a syncsettings document there's no need to
00682        continue with the parsing of ota or oma tags. */
00683     syncstat = -1;
00684     if (octstr_search_char((**otabxml).binary, 0x55, 0) == 0) {
00685         syncstat = parse_ota_syncsettings(node, otabxml);
00686         if (syncstat >= 0) {
00687             return syncstat;
00688         }
00689     }
00690 
00691     name = octstr_create((char *)node->name);
00692     if (octstr_len(name) == 0) {
00693         octstr_destroy(name);
00694         return -1;
00695     }
00696 
00697     i = 0;
00698     while (i < NUMBER_OF_ELEMENTS) {
00699         if (octstr_case_compare(name, octstr_imm(ota_elements[i].name)) == 0)
00700             break;
00701         ++i;
00702     }
00703 
00704     status_bits = 0x00;
00705     ota_hex = 0x00;
00706     add_end_tag = 0;
00707 
00708     if (i != NUMBER_OF_ELEMENTS) {
00709         ota_hex = ota_elements[i].token;
00710         if ((status_bits = element_check_content(node)) > 0) {
00711             ota_hex = ota_hex | status_bits;
00712             if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
00713                 add_end_tag = 1;
00714         }
00715         output_char(ota_hex, otabxml);
00716     } else {
00717         warning(0, "OTA compiler: Unknown tag '%s' in OTA source", octstr_get_cstr(name));
00718         ota_hex = WBXML_LITERAL;
00719         if ((status_bits = element_check_content(node)) > 0) {
00720             ota_hex = ota_hex | status_bits;
00721             /* If this node has children, the end tag must be added after them. */
00722             if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
00723                 add_end_tag = 1;
00724         }
00725         output_char(ota_hex, otabxml);
00726         output_octet_string(octstr_duplicate(name), otabxml);
00727     }
00728 
00729     if (node->properties != NULL) {
00730         attribute = node->properties;
00731         while (attribute != NULL) {
00732             parse_attribute(attribute, otabxml);
00733             attribute = attribute->next;
00734         }
00735         parse_end(otabxml);
00736     }
00737 
00738     octstr_destroy(name);
00739     return add_end_tag;
00740 }
00741 
00742 /*
00743  * Tokenises an attribute, and in most cases, its value. (Some values are re-
00744  * presented as an inline string). Tokenisation is based on tables in ota, 
00745  * chapters 8.1 and 8.2. 
00746  * Returns 0 when success, -1 when error.
00747  */
00748 static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml)
00749 {
00750     Octstr *name, *value, *valueos, *nameos;
00751     unsigned char ota_hex;
00752     size_t i, limit;
00753     ota_3table_t *alist;
00754 
00755     name = octstr_create((char *)attr->name);
00756 
00757     if (attr->children != NULL)
00758         value = create_octstr_from_node((char *)attr->children);
00759     else 
00760         value = NULL;
00761 
00762     if (value == NULL)
00763         goto error;
00764 
00765     /* OMA has it's own dedicated public ID, so use this */        
00766     if ((*otabxml)->public_id == 0x0B) { 
00767         alist = oma_ota_attributes;
00768         limit = NUMBER_OF_OMA_ATTRIBUTES;
00769     } else {
00770         alist = ota_attributes;
00771         limit = NUMBER_OF_ATTRIBUTES;
00772     }
00773 
00774     i = 0;
00775     valueos = NULL;
00776     nameos = NULL;
00777     while (i < limit) {
00778         nameos = octstr_imm(alist[i].name);
00779         if (octstr_case_compare(name, nameos) == 0) {
00780             if (alist[i].value != NULL) {
00781                 valueos = octstr_imm(alist[i].value);
00782             }
00783             if (octstr_case_compare(value, valueos) == 0) {
00784                 break;
00785             }
00786             if (octstr_compare(valueos, octstr_imm("INLINE")) == 0) {
00787                 break;
00788             }
00789         }
00790        ++i;
00791     }
00792 
00793     if (i == limit) {
00794         warning(0, "OTA compiler: Unknown attribute '%s' in OTA source, "
00795                    "with value '%s'.", 
00796                 octstr_get_cstr(name), octstr_get_cstr(value));
00797         goto error;
00798     }
00799 
00800     ota_hex = alist[i].token;
00801     /* if not inline used */
00802     if (octstr_compare(valueos, octstr_imm("INLINE")) != 0) {
00803         /* Switch code page. */
00804         if (alist[i].code_page != (*otabxml)->code_page) { 
00805             output_char(0, otabxml);
00806             output_char(alist[i].code_page, otabxml);
00807             (*otabxml)->code_page = alist[i].code_page;
00808         }
00809         /* if OMA add value tag */
00810         if ((*otabxml)->public_id == 0x0B && name 
00811             && octstr_case_compare(name, octstr_imm("value")) == 0)
00812             output_char(OMA_VALUE_TAG, otabxml);
00813         output_char(ota_hex, otabxml);
00814     } else {
00815         /* Switch code page. */
00816         if (alist[i].code_page != (*otabxml)->code_page) {
00817             output_char(0, otabxml);
00818             output_char(alist[i].code_page, otabxml);
00819             (*otabxml)->code_page = alist[i].code_page;
00820         }
00821         output_char(ota_hex, otabxml);
00822         parse_inline_string(value, otabxml);
00823     }  
00824 
00825     octstr_destroy(name);
00826     octstr_destroy(value);
00827     return 0;
00828 
00829 error:
00830     octstr_destroy(name);
00831     octstr_destroy(value);
00832     return -1;
00833 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.