ota_compiler.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:11k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * ota_compiler.c: Tokenizes an ota settings or bookmarks document. DTD is 
  3.  * defined in Over The Air Settings Specification  (hereafter called ota), 
  4.  * chapter 6. (See http://www.americas.nokia.com/messaging/default.asp)
  5.  *
  6.  * By Aarno Syv鋘en for Wiral Ltd
  7.  */
  8. #include <ctype.h>
  9. #include <libxml/xmlmemory.h>
  10. #include <libxml/tree.h>
  11. #include <libxml/debugXML.h>
  12. #include <libxml/encoding.h>
  13. #include "shared.h"
  14. #include "xml_shared.h"
  15. #include "ota_compiler.h"
  16. /****************************************************************************
  17.  *
  18.  * Global variables
  19.  *
  20.  * Two token table types, one and two token fields
  21.  */
  22. struct ota_2table_t {
  23.     char *name;
  24.     unsigned char token;
  25. };
  26. typedef struct ota_2table_t ota_2table_t;
  27. /*
  28.  * Ota tokenizes whole of attribute value, or uses an inline string. See ota, 
  29.  * chapter 8.2.
  30.  */
  31. struct ota_3table_t {
  32.     char *name;
  33.     char *value;
  34.     unsigned char token;
  35. };
  36. typedef struct ota_3table_t ota_3table_t;
  37. /*
  38.  * Elements from tag code page zero. These are defined in ota, chapter 8.1.
  39.  */
  40. static ota_2table_t ota_elements[] = {
  41.     { "CHARACTERISTIC-LIST", 0x05 },
  42.     { "CHARACTERISTIC", 0x06 },
  43.     { "PARM", 0x07 }
  44. };
  45. #define NUMBER_OF_ELEMENTS sizeof(ota_elements)/sizeof(ota_elements[0])
  46. /*
  47.  * Attribute names and values from code page zero. These are defined in ota,
  48.  * chapter 8.2. Some values are presented as inline strings; in this case 
  49.  * value "INLINE" is used. (Note a quirk: there is an attribute with name 
  50.  * "VALUE".)
  51.  *
  52.  * For a documentation of the single attributes see gw/ota_prov_attr.h.
  53.  */
  54. static ota_3table_t ota_attributes[] = {
  55.     { "TYPE", "ADDRESS", 0x06 },
  56.     { "TYPE", "URL", 0x07 },
  57.     { "TYPE", "MMSURL", 0x7c },
  58.     { "TYPE", "NAME", 0x08 },
  59.     { "TYPE", "ID", 0x7d },
  60.     { "TYPE", "BOOKMARK", 0x7f },
  61.     { "NAME", "BEARER", 0x12 },
  62.     { "NAME", "PROXY", 0x13 },
  63.     { "NAME", "PORT", 0x14 },
  64.     { "NAME", "NAME", 0x15 },
  65.     { "NAME", "PROXY_TYPE", 0x16 },
  66.     { "NAME", "URL", 0x17 },
  67.     { "NAME", "PROXY_AUTHNAME", 0x18 },
  68.     { "NAME", "PROXY_AUTHSECRET", 0x19 },
  69.     { "NAME", "SMS_SMSC_ADDRESS", 0x1a },
  70.     { "NAME", "USSD_SERVICE_CODE", 0x1b },
  71.     { "NAME", "GPRS_ACCESSPOINTNAME", 0x1c },
  72.     { "NAME", "PPP_LOGINTYPE", 0x1d },
  73.     { "NAME", "PROXY_LOGINTYPE", 0x1e },
  74.     { "NAME", "CSD_DIALSTRING", 0x21 },
  75.     { "NAME", "CSD_CALLTYPE", 0x28 },
  76.     { "NAME", "CSD_CALLSPEED", 0x29 },
  77.     { "NAME", "PPP_AUTHTYPE", 0x22 },
  78.     { "NAME", "PPP_AUTHNAME", 0x23 },
  79.     { "NAME", "PPP_AUTHSECRET", 0x24 },
  80.     { "NAME", "ISP_NAME", 0x7e },
  81.     { "NAME", "INLINE", 0x10 },
  82.     { "VALUE", "GSM/CSD", 0x45 },
  83.     { "VALUE", "GSM/SMS", 0x46 },
  84.     { "VALUE", "GSM/USSD", 0x47 },
  85.     { "VALUE", "IS-136/CSD", 0x48 },
  86.     { "VALUE", "GPRS", 0x49 },
  87.     { "VALUE", "9200", 0x60 },
  88.     { "VALUE", "9201", 0x61 },
  89.     { "VALUE", "9202", 0x62 },
  90.     { "VALUE", "9203", 0x63 },
  91.     { "VALUE", "AUTOMATIC", 0x64 },
  92.     { "VALUE", "MANUAL", 0x65 },
  93.     { "VALUE", "AUTO", 0x6a },
  94.     { "VALUE", "9600", 0x6b },
  95.     { "VALUE", "14400", 0x6c },
  96.     { "VALUE", "19200", 0x6d },
  97.     { "VALUE", "28800", 0x6e },
  98.     { "VALUE", "38400", 0x6f },
  99.     { "VALUE", "PAP", 0x70 },
  100.     { "VALUE", "CHAP", 0x71 },
  101.     { "VALUE", "ANALOGUE", 0x72 },
  102.     { "VALUE", "ISDN", 0x73 },
  103.     { "VALUE", "43200", 0x74 },
  104.     { "VALUE", "57600", 0x75 },
  105.     { "VALUE", "MSISDN_NO", 0x76 },
  106.     { "VALUE", "IPV4", 0x77 },
  107.     { "VALUE", "MS_CHAP", 0x78 },
  108.     { "VALUE", "INLINE", 0x11 }
  109. };
  110. #define NUMBER_OF_ATTRIBUTES sizeof(ota_attributes)/sizeof(ota_attributes[0])
  111. #include "xml_definitions.h"
  112. /****************************************************************************
  113.  *
  114.  * Prototypes of internal functions. Note that 'Ptr' means here '*'.
  115.  */
  116. static int parse_document(xmlDocPtr document, Octstr *charset, 
  117.   simple_binary_t **ota_binary);
  118. static int parse_node(xmlNodePtr node, simple_binary_t **otabxml);    
  119. static int parse_element(xmlNodePtr node, simple_binary_t **otabxml);
  120. static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml); 
  121. static int use_inline_string(Octstr *valueos);      
  122. /***************************************************************************
  123.  *
  124.  * Implementation of the external function
  125.  */
  126. int ota_compile(Octstr *ota_doc, Octstr *charset, Octstr **ota_binary)
  127. {
  128.     simple_binary_t *otabxml;
  129.     int ret;
  130.     xmlDocPtr pDoc;
  131.     size_t size;
  132.     char *ota_c_text;
  133.     *ota_binary = octstr_create(""); 
  134.     otabxml = simple_binary_create();
  135.     octstr_strip_blanks(ota_doc);
  136.     octstr_shrink_blanks(ota_doc);
  137.     set_charset(ota_doc, charset);
  138.     size = octstr_len(ota_doc);
  139.     ota_c_text = octstr_get_cstr(ota_doc);
  140.     pDoc = xmlParseMemory(ota_c_text, size);
  141.     ret = 0;
  142.     if (pDoc) {
  143.         ret = parse_document(pDoc, charset, &otabxml);
  144.         simple_binary_output(*ota_binary, otabxml);
  145.         xmlFreeDoc(pDoc);
  146.     } else {
  147.         xmlFreeDoc(pDoc);
  148.         octstr_destroy(*ota_binary);
  149.         simple_binary_destroy(otabxml);
  150.         error(0, "OTA: No document to parse. Probably an error in OTA source");
  151.         return -1;
  152.     }
  153.     simple_binary_destroy(otabxml);
  154.     return ret;
  155. }
  156. /*****************************************************************************
  157.  *
  158.  * Implementation of internal functions
  159.  *
  160.  * Parse document node. Store wbmxl version number and character set into the 
  161.  * start of the document. There are no wapforum public identifier for ota. 
  162.  * FIXME: Add parse_prologue!
  163.  */
  164. static int parse_document(xmlDocPtr document, Octstr *charset, 
  165.                           simple_binary_t **otabxml)
  166. {
  167.     xmlNodePtr node;
  168.     (*otabxml)->wbxml_version = 0x01; /* WBXML Version number 1.1  */
  169.     (*otabxml)->public_id = 0x01; /* Public id for an unknown document type */
  170.     
  171.     charset = octstr_create("UTF-8");
  172.     (*otabxml)->charset = parse_charset(charset);
  173.     octstr_destroy(charset);
  174.     node = xmlDocGetRootElement(document);
  175.     return parse_node(node, otabxml);
  176. }
  177. /*
  178.  * The recursive parsing function for the parsing tree. Function checks the 
  179.  * type of the node, calls for the right parse function for the type, then 
  180.  * calls itself for the first child of the current node if there's one and 
  181.  * after that calls itself for the next child on the list.
  182.  */
  183. static int parse_node(xmlNodePtr node, simple_binary_t **otabxml)
  184. {
  185.     int status = 0;
  186.     
  187.     /* Call for the parser function of the node type. */
  188.     switch (node->type) {
  189.     case XML_ELEMENT_NODE:
  190. status = parse_element(node, otabxml);
  191. break;
  192.     case XML_TEXT_NODE:
  193.     case XML_COMMENT_NODE:
  194.     case XML_PI_NODE:
  195. /* Text nodes, comments and PIs are ignored. */
  196. break;
  197. /*
  198.  * XML has also many other node types, these are not needed with 
  199.  * OTA. Therefore they are assumed to be an error.
  200.  */
  201.     default:
  202. error(0, "OTA compiler: Unknown XML node in the OTA source.");
  203. return -1;
  204. break;
  205.     }
  206.     /* 
  207.      * If node is an element with content, it will need an end tag after it's
  208.      * children. The status for it is returned by parse_element.
  209.      */
  210.     switch (status) {
  211.     case 0:
  212. if (node->children != NULL)
  213.     if (parse_node(node->children, otabxml) == -1)
  214. return -1;
  215. break;
  216.     case 1:
  217. if (node->children != NULL)
  218.     if (parse_node(node->children, otabxml) == -1)
  219. return -1;
  220. parse_end(otabxml);
  221. break;
  222.     case -1: /* Something went wrong in the parsing. */
  223. return -1;
  224.     default:
  225. warning(0,"OTA compiler: undefined return value in a parse function.");
  226. return -1;
  227. break;
  228.     }
  229.     if (node->next != NULL)
  230. if (parse_node(node->next, otabxml) == -1)
  231.     return -1;
  232.     return 0;
  233. }
  234. /*
  235.  * Parse an element node. Check if there is a token for an element tag; if not
  236.  * output the element as a string, else output the token. After that, call 
  237.  * attribute parsing functions
  238.  * Returns:      1, add an end tag (element node has no children)
  239.  *               0, do not add an end tag (it has children)
  240.  *              -1, an error occurred
  241.  */
  242. static int parse_element(xmlNodePtr node, simple_binary_t **otabxml)
  243. {
  244.     Octstr *name;
  245.     size_t i;
  246.     unsigned char status_bits,
  247.              ota_hex;
  248.     int add_end_tag;
  249.     xmlAttrPtr attribute;
  250.     name = octstr_create(node->name);
  251.     if (octstr_len(name) == 0) {
  252.         octstr_destroy(name);
  253.         return -1;
  254.     }
  255.     i = 0;
  256.     while (i < NUMBER_OF_ELEMENTS) {
  257.         if (octstr_compare(name, octstr_imm(ota_elements[i].name)) == 0)
  258.             break;
  259.         ++i;
  260.     }
  261.     status_bits = 0x00;
  262.     ota_hex = 0x00;
  263.     add_end_tag = 0;
  264.     if (i != NUMBER_OF_ELEMENTS) {
  265.         ota_hex = ota_elements[i].token;
  266.         if ((status_bits = element_check_content(node)) > 0) {
  267.     ota_hex = ota_hex | status_bits;
  268.     
  269.     if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
  270.         add_end_tag = 1;
  271.         }
  272.         output_char(ota_hex, otabxml);
  273.     } else {
  274.         warning(0, "unknown tag %s in OTA source", octstr_get_cstr(name));
  275.         ota_hex = WBXML_LITERAL;
  276.         if ((status_bits = element_check_content(node)) > 0) {
  277.     ota_hex = ota_hex | status_bits;
  278.     /* If this node has children, the end tag must be added after 
  279.        them. */
  280.     if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
  281. add_end_tag = 1;
  282. }
  283. output_char(ota_hex, otabxml);
  284.         output_octet_string(octstr_duplicate(name), otabxml);
  285.     }
  286.     if (node->properties != NULL) {
  287. attribute = node->properties;
  288. while (attribute != NULL) {
  289.     parse_attribute(attribute, otabxml);
  290.     attribute = attribute->next;
  291. }
  292. parse_end(otabxml);
  293.     }
  294.     octstr_destroy(name);
  295.     return add_end_tag;
  296. }
  297. /*
  298.  * Tokenises an attribute, and in most cases, its value. (Some values are re-
  299.  * presented as an inline string). Tokenisation is based on tables in ota, 
  300.  * chapters 8.1 and 8.2. 
  301.  * Returns 0 when success, -1 when error.
  302.  */
  303. static int parse_attribute(xmlAttrPtr attr, simple_binary_t **otabxml)
  304. {
  305.     Octstr *name,
  306.            *value,
  307.            *valueos,
  308.            *nameos;
  309.     unsigned char ota_hex;
  310.     size_t i;
  311.     name = octstr_create(attr->name);
  312.     if (attr->children != NULL)
  313. value = create_octstr_from_node(attr->children);
  314.     else 
  315. value = NULL;
  316.     if (value == NULL)
  317.         goto error;
  318.     i = 0;
  319.     valueos = NULL;
  320.     nameos = NULL;
  321.     while (i < NUMBER_OF_ATTRIBUTES) {
  322. nameos = octstr_imm(ota_attributes[i].name);
  323.         if (octstr_compare(name, nameos) == 0) {
  324.     if (ota_attributes[i].value != NULL) {
  325.                 valueos = octstr_imm(ota_attributes[i].value);
  326.             }
  327.             if (octstr_compare(value, valueos) == 0) {
  328.         break;
  329.             }
  330.             if (octstr_compare(valueos, octstr_imm("INLINE")) == 0) {
  331.         break;
  332.             }
  333.         }
  334.        ++i;
  335.     }
  336.     if (i == NUMBER_OF_ATTRIBUTES) {
  337.         warning(0, "unknown attribute %s in OTA source", 
  338.                 octstr_get_cstr(name));
  339.         warning(0, "its value being %s", octstr_get_cstr(value));
  340.         goto error;
  341.     }
  342.     ota_hex = ota_attributes[i].token;
  343.     if (!use_inline_string(valueos)) {
  344.         output_char(ota_hex, otabxml);
  345.     } else {
  346.         output_char(ota_hex, otabxml);
  347.         parse_inline_string(value, otabxml);
  348.     }  
  349.     octstr_destroy(name);
  350.     octstr_destroy(value);
  351.     return 0;
  352. error:
  353.     octstr_destroy(name);
  354.     octstr_destroy(value);
  355.     return -1;
  356. }
  357. static int use_inline_string(Octstr *valueos)
  358. {
  359.     return octstr_compare(valueos, octstr_imm("INLINE")) == 0;
  360. }