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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * wap_push_sl_compiler.c: Tokenizes a SL document. SL DTD is defined in 
  3.  * Wapforum specification WAP-168-ServiceLoad-20010731-a (hereafter called sl),
  4.  * chapter 9.2.
  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 "xml_shared.h"
  14. #include "wap_push_sl_compiler.h"
  15. /******************************************************************************
  16.  *
  17.  * Following global variables are unique to SL compiler. See sl, chapter 10.3.
  18.  *
  19.  * Two token table types, with one and two token fields.
  20.  */
  21. struct sl_2table_t {
  22.     char *name;
  23.     unsigned char token;
  24. };
  25. typedef struct sl_2table_t sl_2table_t;
  26. /*
  27.  * Value part can mean whole or part of the value. It can be NULL, too; then 
  28.  * no part of the value will be tokenized, see sl, chapter 10.3.2.
  29.  */
  30. struct sl_3table_t {
  31.     char *name;
  32.     char *value_part;
  33.     unsigned char token;
  34. };
  35. typedef struct sl_3table_t sl_3table_t;
  36. /*
  37.  * Element from tag code page zero. It is defined in sl, chapter 10.3.1.
  38.  */
  39. static sl_2table_t sl_elements[] = {
  40.     { "sl", 0x05 }
  41. };
  42. #define NUMBER_OF_ELEMENTS sizeof(sl_elements)/sizeof(sl_elements[0])
  43. /*
  44.  * Attributes (and sometimes start or whole of their value) from code page 
  45.  * zero. These are defined in sl, chapter 10.3.2. 
  46.  */
  47. static sl_3table_t sl_attributes[] = {
  48.     { "action", "execute-low", 0x05 }, 
  49.     { "action", "execute-high", 0x06 }, 
  50.     { "action", "cache", 0x07 }, 
  51.     { "href", "http://", 0x09 },
  52.     { "href", "http://www.", 0x0a }, 
  53.     { "href", "https://", 0x0b },    
  54.     { "href", "https://www.", 0x0c },
  55.     { "href", NULL, 0x08 }
  56. };
  57. #define NUMBER_OF_ATTRIBUTES sizeof(sl_attributes)/sizeof(sl_attributes[0])
  58. /*
  59.  * URL value codes from code page zero. These are defined in sl, chapter 
  60.  * 10.3.3.
  61.  */
  62. static sl_2table_t sl_url_values[] = {
  63.     { ".com/", 0x85 },
  64.     { ".edu/", 0x86 },
  65.     { ".net/", 0x87 },
  66.     { ".org/", 0x88 },
  67. };
  68. #define NUMBER_OF_URL_VALUES sizeof(sl_url_values)/sizeof(sl_url_values[0])
  69. #include "xml_definitions.h"
  70. /****************************************************************************
  71.  *
  72.  * Prototypes of internal functions. Note that 'Ptr' means here '*'.
  73.  */
  74. static int parse_document(xmlDocPtr document, Octstr *charset, 
  75.                           simple_binary_t **slbxml);
  76. static int parse_node(xmlNodePtr node, simple_binary_t **slbxml);
  77. static int parse_element(xmlNodePtr node, simple_binary_t **slbxml);
  78. static int parse_attribute(xmlAttrPtr attr, simple_binary_t **slbxml);
  79. static int url(int hex);
  80. static int action(int hex);
  81. static void parse_url_value(Octstr *value, simple_binary_t **slbxml);
  82. /****************************************************************************
  83.  *
  84.  * Implementation of the external function
  85.  */
  86. int sl_compile(Octstr *sl_doc, Octstr *charset, Octstr **sl_binary)
  87. {
  88.     simple_binary_t *slbxml;
  89.     int ret;
  90.     xmlDocPtr pDoc;
  91.     size_t size;
  92.     char *sl_c_text;
  93.     *sl_binary = octstr_create(""); 
  94.     slbxml = simple_binary_create();
  95.     octstr_strip_blanks(sl_doc);
  96.     set_charset(sl_doc, charset);
  97.     size = octstr_len(sl_doc);
  98.     sl_c_text = octstr_get_cstr(sl_doc);
  99.     pDoc = xmlParseMemory(sl_c_text, size);
  100.     ret = 0;
  101.     if (pDoc) {
  102.         ret = parse_document(pDoc, charset, &slbxml);
  103.         simple_binary_output(*sl_binary, slbxml);
  104.         xmlFreeDoc(pDoc);
  105.     } else {
  106.         xmlFreeDoc(pDoc);
  107.         octstr_destroy(*sl_binary);
  108.         simple_binary_destroy(slbxml);
  109.         error(0, "SL: No document to parse. Probably an error in SL source");
  110.         return -1;
  111.     }
  112.     simple_binary_destroy(slbxml);
  113.     return ret;
  114. }
  115. /****************************************************************************
  116.  *
  117.  * Implementation of internal functions
  118.  *
  119.  * Parse document node. Store sl version number, public identifier and 
  120.  * character set at the start of the document
  121.  */
  122. static int parse_document(xmlDocPtr document, Octstr *charset, 
  123.                           simple_binary_t **slbxml)
  124. {
  125.     xmlNodePtr node;
  126.     (**slbxml).wbxml_version = 0x02; /* WBXML Version number 1.2  */
  127.     (**slbxml).public_id = 0x06;  /* SL 1.0 Public ID */
  128.     
  129.     charset = octstr_create("UTF-8");
  130.     (**slbxml).charset = parse_charset(charset);
  131.     octstr_destroy(charset);
  132.     node = xmlDocGetRootElement(document);
  133.     return parse_node(node, slbxml);
  134. }
  135. /*
  136.  * The recursive parsing function for the parsing tree. Function checks the 
  137.  * type of the node, calls for the right parse function for the type, then 
  138.  * calls itself for the first child of the current node if there's one and 
  139.  * after that calls itself for the next child on the list. We parse whole 
  140.  * tree, even though SL DTD defines only one node (see sl, chapter 9.2); this
  141.  * allows us throw an error message when an unknown element is found.
  142.  */
  143. static int parse_node(xmlNodePtr node, simple_binary_t **slbxml)
  144. {
  145.     int status = 0;
  146.     
  147.     /* Call for the parser function of the node type. */
  148.     switch (node->type) {
  149.     case XML_ELEMENT_NODE:
  150. status = parse_element(node, slbxml);
  151. break;
  152.     case XML_TEXT_NODE:
  153.     case XML_COMMENT_NODE:
  154.     case XML_PI_NODE:
  155. /* Text nodes, comments and PIs are ignored. */
  156. break;
  157. /*
  158.  * XML has also many other node types, these are not needed with 
  159.  * SL. Therefore they are assumed to be an error.
  160.  */
  161.     default:
  162. error(0, "SL COMPILER: Unknown XML node in the SL source.");
  163. return -1;
  164. break;
  165.     }
  166.     /* 
  167.      * If node is an element with content, it will need an end tag after it's
  168.      * children. The status for it is returned by parse_element.
  169.      */
  170.     switch (status) {
  171.     case 0:
  172. if (node->children != NULL)
  173.     if (parse_node(node->children, slbxml) == -1)
  174. return -1;
  175. break;
  176.     case 1:
  177. if (node->children != NULL)
  178.     if (parse_node(node->children, slbxml) == -1)
  179. return -1;
  180. parse_end(slbxml);
  181. break;
  182.     case -1: /* Something went wrong in the parsing. */
  183. return -1;
  184.     default:
  185. warning(0,"SL compiler: undefined return value in a parse function.");
  186. return -1;
  187. break;
  188.     }
  189.     if (node->next != NULL)
  190. if (parse_node(node->next, slbxml) == -1)
  191.     return -1;
  192.     return 0;
  193. }
  194. /*
  195.  * Parse an element node. Check if there is a token for an element tag; if not
  196.  * output the element as a string, else ouput the token. After that, call 
  197.  * attribute parsing functions. Note that we take advantage of the fact that
  198.  * sl documents have only one element (see sl, chapter 6.2).
  199.  * Returns:      1, add an end tag (element node has no children)
  200.  *               0, do not add an end tag (it has children)
  201.  *              -1, an error occurred
  202.  */
  203. static int parse_element(xmlNodePtr node, simple_binary_t **slbxml)
  204. {
  205.     Octstr *name,
  206.            *nameos;
  207.     unsigned char status_bits,
  208.              sl_hex;
  209.     int add_end_tag;
  210.     xmlAttrPtr attribute;
  211.     name = octstr_create(node->name);
  212.     if (octstr_len(name) == 0) {
  213.         octstr_destroy(name);
  214.         return -1;
  215.     }
  216.     status_bits = 0x00;
  217.     sl_hex = 0x00;
  218.     add_end_tag = 0;
  219.     if (octstr_compare(name, octstr_imm(sl_elements[0].name)) != 0) {
  220.         warning(0, "unknown tag %s in SL source", octstr_get_cstr(name));
  221.         sl_hex = WBXML_LITERAL;
  222.         if ((status_bits = element_check_content(node)) > 0) {
  223.     sl_hex = sl_hex | status_bits;
  224.     /* If this node has children, the end tag must be added after 
  225.        them. */
  226.     if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT)
  227. add_end_tag = 1;
  228. }
  229. output_char(sl_hex, slbxml);
  230.         output_octet_string(nameos = octstr_duplicate(name), slbxml);
  231.         octstr_destroy(nameos);
  232.     } else {
  233.         sl_hex = sl_elements[0].token;
  234.         if ((status_bits = element_check_content(node)) > 0) {
  235.     sl_hex = sl_hex | status_bits;
  236.     
  237.     if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT) {
  238.         add_end_tag = 1;
  239.             }
  240.             output_char(sl_hex, slbxml);
  241.         }
  242.     }
  243.     if (node->properties != NULL) {
  244. attribute = node->properties;
  245. while (attribute != NULL) {
  246.     parse_attribute(attribute, slbxml);
  247.     attribute = attribute->next;
  248. }
  249. parse_end(slbxml);
  250.     }
  251.     octstr_destroy(name);
  252.     return add_end_tag;
  253. }
  254. static int parse_attribute(xmlAttrPtr attr, simple_binary_t **slbxml)
  255. {
  256.     Octstr *name,
  257.            *value,
  258.            *valueos;
  259.     unsigned char sl_hex;
  260.     size_t i,
  261.            value_len;
  262.     name = octstr_create(attr->name);
  263.     if (attr->children != NULL)
  264.         value = create_octstr_from_node(attr->children);
  265.     else
  266.         value = NULL;
  267.     if (value == NULL)
  268.         goto error;
  269.     i = 0;
  270.     valueos = NULL;
  271.     while (i < NUMBER_OF_ATTRIBUTES) {
  272.         if (octstr_compare(name, octstr_imm(sl_attributes[i].name)) == 0) {
  273.     if (sl_attributes[i].value_part == NULL) {
  274.         debug("wap.push.sl.compiler", 0, "value part was NULL");
  275.         break; 
  276.             } else {
  277.                 value_len = octstr_len(valueos = 
  278.                     octstr_imm(sl_attributes[i].value_part));
  279.         if (octstr_ncompare(value, valueos, value_len) == 0) {
  280.     break;
  281.                 }
  282.             }
  283.         }
  284.        ++i;
  285.     }
  286.     if (i == NUMBER_OF_ATTRIBUTES) {
  287.         warning(0, "unknown attribute in SL source");
  288.         goto error;
  289.     }
  290.     sl_hex = sl_attributes[i].token;
  291.     if (action(sl_hex)) {
  292.         output_char(sl_hex, slbxml);
  293.     } else if (url(sl_hex)) {
  294.         output_char(sl_hex, slbxml);
  295.         octstr_delete(value, 0, octstr_len(valueos));
  296.         parse_url_value(value, slbxml);
  297.     } else {
  298.         output_char(sl_hex, slbxml);
  299.         parse_inline_string(value, slbxml);
  300.     } 
  301.     octstr_destroy(name);
  302.     octstr_destroy(value);
  303.     return 0;
  304. error:
  305.     octstr_destroy(name);
  306.     octstr_destroy(value);
  307.     return -1;    
  308. }
  309. /*
  310.  * checks whether a sl attribute value is an URL or some other kind of value. 
  311.  * Returns 1 for an URL and 0 otherwise.
  312.  */
  313. static int url(int hex)
  314. {
  315.     switch ((unsigned char) hex) {
  316.     case 0x08:            /* href */
  317.     case 0x09: case 0x0b: /* href http://, href https:// */
  318.     case 0x0a: case 0x0c: /* href http://www., href https://www. */
  319. return 1;
  320.     }
  321.     return 0;
  322. }
  323. /*
  324.  * checks whether a sl attribute value is an action attribute or some other 
  325.  * kind of value. 
  326.  * Returns 1 for an action attribute and 0 otherwise.
  327.  */
  328. static int action(int hex)
  329. {
  330.     switch ((unsigned char) hex) {
  331.     case 0x05: case 0x06: /* action execute-low, action execute-high */
  332.     case 0x07:            /* action cache */
  333. return 1;
  334.     }
  335.     return 0;
  336. }
  337. /*
  338.  * In the case of SL document, only attribute values to be tokenised are parts
  339.  * of urls. See sl, chapter 10.3.3. The caller removes the start of the url.
  340.  * Check whether we can find one of tokenisable values in value. If not, parse
  341.  * value as a inline string, else parse parts before and after the tokenisable
  342.  * url value as a inline string.
  343.  */
  344. static void parse_url_value(Octstr *value, simple_binary_t **slbxml)
  345. {
  346.     size_t i;
  347.     long pos;
  348.     Octstr *urlos,
  349.            *first_part,
  350.    *last_part;
  351.     size_t first_part_len;
  352.     i = 0;
  353.     first_part_len = 0;
  354.     first_part = NULL;
  355.     last_part = NULL;
  356.     while (i < NUMBER_OF_URL_VALUES) {
  357.         pos = octstr_search(value, 
  358.             urlos = octstr_imm(sl_url_values[i].name), 0);
  359.         if (pos >= 0) {
  360.     first_part = octstr_duplicate(value);
  361.             octstr_delete(first_part, pos, octstr_len(first_part) - pos);
  362.             first_part_len = octstr_len(first_part);
  363.             parse_inline_string(first_part, slbxml);
  364.             output_char(sl_url_values[i].token, slbxml);
  365.             last_part = octstr_duplicate(value);
  366.             octstr_delete(last_part, 0, first_part_len + octstr_len(urlos));
  367.             parse_inline_string(last_part, slbxml);
  368.     octstr_destroy(first_part);
  369.             octstr_destroy(last_part);
  370.             break;
  371.         }
  372.         octstr_destroy(urlos);
  373.         ++i;
  374.     }
  375.     if (pos < 0) 
  376. parse_inline_string(value, slbxml);
  377.         
  378. }