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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * wap_push_pap_compiler.c - implementation of wap_push_pap_compiler.h inter-
  3.  * face (compiling pap documents to Kannel WAPEvents)
  4.  *
  5.  * This module implements PAP document DTD and status codes, defined in   
  6.  *       WAP-164-PAP-19991108-a (called hereafter pap), chapter 9 and
  7.  * PPG client addressing (it is. parsing client address of a pap document), 
  8.  * defined in
  9.  *       WAP-151-PPGService-19990816-a (ppg), chapter 7.
  10.  *
  11.  * In addition, Wapforum specification WAP-200-WDP-20001212-a (wdp) is re-
  12.  * ferred.
  13.  *
  14.  * Compiler can be used by PI or PPG (it will handle all possible PAP DTD 
  15.  * elements). It checks that attribute values are legal and that an element 
  16.  * has only legal attributes, but does not otherwise validate PAP documents 
  17.  * against PAP DTD. (XML validation is quite another matter, of course.) 
  18.  * Client address is parsed out from the relevant PAP message attribute 
  19.  * containing lots of additional data, see ppg, 7.1. We do not yet support 
  20.  * user defined addresses.
  21.  *
  22.  * After compiling, some semantic analysing of the resulted event, and sett-
  23.  * ing some defaults (however, relying on them is quite a bad policy). In 
  24.  * addition changing undefined values (any) to defined ones.
  25.  *
  26.  * By  Aarno Syv鋘en for Wapit Ltd and for Wiral Ltd.
  27.  */
  28. #include <libxml/xmlmemory.h>
  29. #include <libxml/parser.h>
  30. #include <libxml/tree.h>
  31. #include <libxml/debugXML.h>
  32. #include <libxml/encoding.h>
  33. #include <ctype.h>
  34. #include <string.h>
  35. #include "shared.h"
  36. #include "wap_push_pap_compiler.h"
  37. #include "wap_push_ppg.h"
  38. /****************************************************************************
  39.  *
  40.  * Global data structures
  41.  *
  42.  * Table for pap elements. These are defined in PAP, Chapter 9.
  43.  */
  44. static char *pap_elements[] = {
  45.     "pap",
  46.     "push-message",
  47.     "address",
  48.     "quality-of-service",
  49.     "push-response",
  50.     "progress-note",
  51.     "response-result",
  52.     "cancel-message",
  53.     "cancel-result",
  54.     "cancel-response",
  55.     "resultnotification-message",
  56.     "resultnotification-response",
  57.     "statusquery-message",
  58.     "statusquery-response",
  59.     "statusquery-result",
  60.     "ccq-message",
  61.     "ccq-response",
  62.     "badmessage-response"
  63. };
  64. #define NUM_ELEMENTS sizeof(pap_elements)/sizeof(pap_elements[0])
  65. /*
  66.  * Table for PAP attributes. These are defined in pap, Chapter 9.
  67.  */
  68. struct pap_attributes_t {
  69.     char *name;
  70.     char *value;
  71. };
  72. typedef struct pap_attributes_t pap_attributes_t;
  73. static pap_attributes_t pap_attributes[] = {
  74.     { "product-name", NULL },
  75.     { "push-id", NULL },
  76.     { "deliver-before-timestamp", NULL },
  77.     { "deliver-after-timestamp", NULL },
  78.     { "source-reference", NULL },
  79.     { "progress-notes-requested", "true" },
  80.     { "progress-notes-requested", "false" },
  81.     { "ppg-notify-requested-to", NULL },
  82.     { "address-value", NULL },
  83.     { "priority", "high" },
  84.     { "priority", "medium" },
  85.     { "priority", "low" },
  86.     { "delivery-method", "confirmed" },
  87.     { "delivery-method", "preferconfirmed" },
  88.     { "delivery-method", "unconfirmed" },
  89.     { "delivery-method", "notspecified" },
  90.     { "network", NULL },
  91.     { "network-required", "true" },
  92.     { "network-required", "false" },
  93.     { "bearer", NULL },
  94.     { "bearer-required", "true" },
  95.     { "bearer-required", "false" },
  96.     { "sender-address", NULL },
  97.     { "sender-name", NULL },
  98.     { "reply-time", NULL },
  99.     { "stage", NULL },
  100.     { "note", NULL },
  101.     { "time", NULL },
  102.     { "code", NULL },
  103.     { "desc", NULL },
  104.     { "received-time", NULL },
  105.     { "event-time", NULL },
  106.     { "message-state", NULL },
  107.     { "query-id", NULL },
  108.     { "app-id", NULL },
  109.     { "bad-message-fragment", NULL}
  110. };
  111. #define NUM_ATTRIBUTES sizeof(pap_attributes)/sizeof(pap_attributes[0])
  112. /*
  113.  * Status codes are defined in pap, chapter 9.13.
  114.  */
  115. static int pap_codes[] = {
  116.     PAP_ACCEPTED_FOR_PROCESSING,
  117.     PAP_BAD_REQUEST,
  118.     PAP_FORBIDDEN,
  119.     PAP_ADDRESS_ERROR,
  120.     PAP_CAPABILITIES_MISMATCH,
  121.     PAP_DUPLICATE_PUSH_ID,
  122.     PAP_TRANSFORMATION_FAILURE,
  123.     PAP_REQUIRED_BEARER_NOT_AVAILABLE,
  124.     PAP_ABORT_USERPND
  125. };
  126. #define NUM_CODES sizeof(pap_codes)/sizeof(pap_codes[0])
  127. /*
  128.  * Possible bearer types. These are defined in wdp, appendix C.
  129.  */
  130. static char *pap_bearer_types[] = {
  131.     "Any",
  132.     "USSD",
  133.     "SMS",
  134.     "GUTS/R-Data",
  135.     "CSD",
  136.     "Packet Data",
  137.     "GPRS",
  138.     "CDPD",
  139.     "FLEX",
  140.     "SDS",
  141.     "ReFLEX",
  142.     "MPAK",
  143.     "GHOST/R_DATA"
  144. };
  145. #define NUM_BEARER_TYPES sizeof(pap_bearer_types)/sizeof(pap_bearer_types[0])
  146. /*
  147.  * Possible network types. These are defined in wdp, appendix C.
  148.  */
  149. static char *pap_network_types[] = {
  150.     "Any",
  151.     "GSM",
  152.     "ANSI-136",
  153.     "IS-95 CDMA",
  154.     "AMPS",
  155.     "PDC",
  156.     "IDEN",
  157.     "Paging network",
  158.     "PHS",
  159.     "TETRA",
  160.     "Mobitex",
  161. };
  162. #define NUM_NETWORK_TYPES sizeof(pap_network_types)/ 
  163.                           sizeof(pap_network_types[0])
  164. /****************************************************************************
  165.  *
  166.  * Prototypes of internal functions. Note that suffix 'Ptr' means '*'.
  167.  */
  168. static int parse_document(xmlDocPtr doc_p, WAPEvent **e);
  169. static int parse_node(xmlNodePtr node, WAPEvent **e, long *type_of_address,
  170.                       int *is_any);  
  171. static int parse_element(xmlNodePtr node, WAPEvent **e, 
  172.                          long *type_of_address, int *is_any); 
  173. static int parse_attribute(Octstr *element_name, xmlAttrPtr attribute, 
  174.                            WAPEvent **e, long *type_of_address, int *is_any);
  175. static int parse_attr_value(Octstr *element_name, Octstr *attr_name, 
  176.                             Octstr *attr_value, WAPEvent **e,
  177.                             long *type_of_address, int *is_any);
  178. static int set_attribute_value(Octstr *element_name, Octstr *attr_value, 
  179.                                Octstr *attr_name, WAPEvent **e);
  180. static int return_flag(Octstr *ros);
  181. static void wap_event_accept_or_create(Octstr *element_name, WAPEvent **e);
  182. static int parse_push_message_value(Octstr *attr_name, Octstr *attr_value,
  183.                                      WAPEvent **e);
  184. static int parse_address_value(Octstr *attr_name, Octstr *attr_value, 
  185.                                WAPEvent **e, long *type_of_address);
  186. static int parse_quality_of_service_value(Octstr *attr_name, 
  187.                                           Octstr *attr_value, WAPEvent **e,
  188.                                           int *is_any);
  189. static int parse_push_response_value(Octstr *attr_name, Octstr *attr_value,
  190.                                      WAPEvent **e);
  191. static int parse_progress_note_value(Octstr *attr_name, Octstr *attr_value,
  192.                                      WAPEvent **e);
  193. static int parse_bad_message_response_value(Octstr *attr_name, 
  194.                                             Octstr *attr_value, WAPEvent **e);
  195. static int parse_response_result_value(Octstr *attr_name, 
  196.                                       Octstr *attr_value, WAPEvent **e);
  197. static int parse_code(Octstr *attr_value);
  198. static Octstr *parse_bearer(Octstr *attr_value);
  199. static Octstr *parse_network(Octstr *attr_value);
  200. static int parse_requirement(Octstr *attr_value);
  201. static int parse_priority(Octstr *attr_value);
  202. static int parse_delivery_method(Octstr *attr_value);
  203. static int parse_state(Octstr *attr_value);
  204. static int parse_address(Octstr **attr_value, long *type_of_address);
  205. static long parse_wappush_client_address(Octstr **address, long pos,
  206.                                          long *type_of_address);
  207. static long parse_ppg_specifier(Octstr **address, long pos);
  208. static long parse_client_specifier(Octstr **address, long pos, 
  209.                                    long *type_of_address);
  210. static long parse_constant(const char *field_name, Octstr **address, long pos);
  211. static long parse_dom_fragment(Octstr **address, long pos);
  212. static long drop_character(Octstr **address, long pos);
  213. static long parse_type(Octstr **address, Octstr **type_value, long pos);
  214. static long parse_ext_qualifiers(Octstr **address, long pos, 
  215.                                  Octstr *type_value);
  216. static long parse_global_phone_number(Octstr **address, long pos);
  217. static long parse_ipv4(Octstr **address, long pos);
  218. static long parse_ipv6(Octstr **address, long pos);
  219. static long parse_escaped_value(Octstr **address, long pos); 
  220. static Octstr *prepend_char(Octstr *address, unsigned char c);
  221. static int qualifiers(Octstr *address, long pos, Octstr *type);
  222. static long parse_qualifier_value(Octstr **address, long pos);
  223. static long parse_qualifier_keyword(Octstr **address, long pos);
  224. static long parse_ipv4_fragment(Octstr **address, long pos);
  225. static long parse_ipv6_fragment(Octstr **address, long pos);
  226. static int wina_bearer_identifier(Octstr *type_value);
  227. static int create_peek_window(Octstr **address, long *pos);
  228. static long rest_unescaped(Octstr **address, long pos);
  229. static int issafe(Octstr **address, long pos);
  230. static long accept_safe(Octstr **address, long pos);
  231. static long accept_escaped(Octstr **address, long pos);
  232. static long handle_two_terminators (Octstr **address, long pos, 
  233.     unsigned char comma, unsigned char point, unsigned char c, 
  234.     long fragment_parsed, long fragment_length);
  235. static int uses_gsm_msisdn_address(long bearer_required, Octstr *bearer);
  236. static int uses_ipv4_address(long bearer_required, Octstr *bearer);
  237. static int uses_ipv6_address(long bearer_required, Octstr *bearer);
  238. static int event_semantically_valid(WAPEvent *e, long type_of_address);
  239. static char *address_type(long type_of_address);
  240. static void set_defaults(WAPEvent **e, long type_of_address);
  241. static void set_bearer_defaults(WAPEvent **e, long type_of_address);
  242. static void set_network_defaults(WAPEvent **e, long type_of_address);
  243. static int set_anys(WAPEvent **e, long type_of_address, int is_any);
  244. static void set_any_value(int *is_any, Octstr *attr_name, Octstr *attr_value);
  245. /*
  246.  * Macro for creating an octet string from a node content. This has two 
  247.  * versions for different libxml node content implementation methods.
  248.  */
  249. #ifdef XML_USE_BUFFER_CONTENT
  250. #define create_octstr_from_node(node) (octstr_create(node->content->content))
  251. #else
  252. #define create_octstr_from_node(node) (octstr_create(node->content))
  253. #endif
  254. /****************************************************************************
  255.  *
  256.  * Compile PAP control document to a corresponding Kannel event. Checks vali-
  257.  * dity of the document. The caller must initialize wap event to NULL. In add-
  258.  * ition, it must free memory allocated by this function. 
  259.  *
  260.  * After compiling, some semantic analysing of the resulted event. 
  261.  *
  262.  * Note that entities in the DTD are parameter entities and they can appear 
  263.  * only in DTD (See site http://www.w3.org/TR/REC-xml, Chapter 4.1). So we do 
  264.  * not need to worry about them in the document itself.
  265.  *
  266.  * Returns 0, when success
  267.  *        -1, when a non-implemented pap feature is asked for
  268.  *        -2, when error
  269.  * In addition, returns a newly created wap event corresponding the pap 
  270.  * control message, if success, wap event NULL otherwise. 
  271.  */
  272. int pap_compile(Octstr *pap_content, WAPEvent **e)
  273. {
  274.     xmlDocPtr doc_p;
  275.     size_t oslen;
  276.     int ret;
  277.     if (octstr_search_char(pap_content, '', 0) != -1) {
  278.         warning(0, "PAP COMPILER: pap_compile: pap source contained a \0"
  279.                    " character");
  280.         return -2;
  281.     }
  282.     octstr_strip_blanks(pap_content);
  283.     oslen = octstr_len(pap_content);
  284.     doc_p = xmlParseMemory(octstr_get_cstr(pap_content), oslen);
  285.     if (doc_p == NULL) {
  286.         goto error;
  287.     }
  288.     if ((ret = parse_document(doc_p, e)) < 0) { 
  289.         goto parserror;
  290.     }
  291.     xmlFreeDoc(doc_p);
  292.     return 0;
  293. parserror:
  294.     xmlFreeDoc(doc_p);
  295.     wap_event_destroy(*e);
  296.     *e = NULL;
  297.     return ret;
  298. error:
  299.     warning(0, "PAP COMPILER: pap_compile: parse error in pap source");
  300.     xmlFreeDoc(doc_p);
  301.     wap_event_destroy(*e);
  302.     *e = NULL;
  303.     return -2;
  304. }
  305. /****************************************************************************
  306.  *
  307.  * Implementation of internal functions
  308.  *
  309.  */
  310. enum {
  311.     NEITHER = 0,
  312.     BEARER_ANY = 1,
  313.     NETWORK_ANY = 2,
  314.     EITHER = 3,
  315.     ERROR_ANY = 4
  316. };
  317. /*
  318.  * Parse the document node of libxml syntax tree. FIXME: Add parsing of pap
  319.  * version.
  320.  * After parsing, some semantic analysing of the resulted event. Then set
  321.  * a default network and bearer deduced from address type, if the correspond-
  322.  * ing pap attribute is missing.
  323.  * 
  324.  * Returns 0, when success
  325.  *        -1, when a non-implemented pap feature is requested
  326.  *        -2, when error
  327.  * In addition, return a newly created wap event corresponding the pap 
  328.  * control message, if success, or partially parsed pap document, if not. Set
  329.  * a field containing address type.
  330.  */
  331. static int parse_document(xmlDocPtr doc_p, WAPEvent **e)
  332. {
  333.     xmlNodePtr node;
  334.     int ret,
  335.         is_any;                   /* is bearer and/or network set any in qos
  336.                                      attribute */
  337.     long type_of_address;
  338.     gw_assert(doc_p);
  339.     node = xmlDocGetRootElement(doc_p);
  340.     is_any = NEITHER;
  341.     if ((ret = parse_node(node, e, &type_of_address, &is_any)) < 0)
  342.         return ret;
  343.     (*e)->u.Push_Message.address_type = type_of_address;
  344.     if ((ret= event_semantically_valid(*e, type_of_address)) == 0) {
  345.         warning(0, "wrong type of address for requested bearer");
  346.         return -2;
  347.     } else if (ret == -1) {
  348.         info(0, "reverting to default bearer and network");
  349.         set_defaults(e, type_of_address);
  350.         return 0;
  351.     }
  352.     if (!set_anys(e, type_of_address, is_any)) {
  353.         warning(0, "unable to handle any values in qos");
  354.         return -2;
  355.     } else {
  356.         debug("wap.push.pap.compiler", 0, "using defaults instead of anys");
  357.     }
  358.     wap_event_assert(*e);
  359.     return 0;
  360. }
  361. static int set_anys(WAPEvent **e, long type_of_address, int is_any)
  362. {
  363.     switch (is_any) {
  364.     case NEITHER:
  365.     return 1;
  366.     case BEARER_ANY:
  367.         set_bearer_defaults(e, type_of_address);
  368.     return 1;
  369.     case NETWORK_ANY:
  370.         set_network_defaults(e, type_of_address);
  371.     return 1;
  372.     case EITHER:
  373.         set_defaults(e, type_of_address);
  374.     return 1;
  375.     default:
  376.     return 0;
  377.     }
  378. }
  379. /*
  380.  * We actually use address_type field of a wap event for cotrolling the bearer
  381.  * selection. Bearer and network filed are used for debugging purposes.
  382.  */
  383. static void set_defaults(WAPEvent **e, long type_of_address)
  384. {
  385.     set_bearer_defaults(e, type_of_address);
  386.     set_network_defaults(e, type_of_address);   
  387. }
  388. static void set_bearer_defaults(WAPEvent **e, long type_of_address)
  389. {
  390.     gw_assert(type_of_address == ADDR_USER || type_of_address == ADDR_PLMN ||
  391.               type_of_address == ADDR_IPV4 || type_of_address == ADDR_IPV6 ||
  392.               type_of_address == ADDR_WINA);
  393.     if ((*e)->type != Push_Message)
  394.         return;
  395.     (*e)->u.Push_Message.bearer_required = PAP_TRUE;
  396.     octstr_destroy((*e)->u.Push_Message.bearer);
  397.     switch (type_of_address) {
  398.     case ADDR_PLMN:
  399. (*e)->u.Push_Message.bearer = octstr_format("%s", "SMS"); 
  400.     break;   
  401.  
  402.     case ADDR_IPV4:
  403. (*e)->u.Push_Message.bearer = octstr_format("%s", "CSD");     
  404.     break;
  405.     case ADDR_IPV6:
  406.     break;
  407.     }
  408. }
  409. static void set_network_defaults(WAPEvent **e, long type_of_address)
  410. {
  411.     gw_assert(type_of_address == ADDR_USER || type_of_address == ADDR_PLMN ||
  412.               type_of_address == ADDR_IPV4 || type_of_address == ADDR_IPV6 ||
  413.               type_of_address == ADDR_WINA);
  414.     if ((*e)->type != Push_Message)
  415.         return;
  416.     (*e)->u.Push_Message.network_required = PAP_TRUE;
  417.     octstr_destroy((*e)->u.Push_Message.network);
  418.     switch (type_of_address) {
  419.     case ADDR_PLMN:
  420. (*e)->u.Push_Message.network = octstr_format("%s", "GSM");
  421.     break;   
  422.  
  423.     case ADDR_IPV4:
  424.         (*e)->u.Push_Message.network = octstr_format("%s", "GSM");   
  425.     break;
  426.     case ADDR_IPV6: 
  427.     break;
  428.     }
  429. }
  430. static char *address_type(long type_of_address)
  431. {
  432.     switch(type_of_address) {
  433.     case ADDR_USER:
  434.     return "user defined address";
  435.     case ADDR_PLMN:
  436.     return "a phone number";
  437.     case ADDR_IPV4:
  438.     return "a IPv4 address";
  439.     case ADDR_IPV6:
  440.     return "a IPv6 address";
  441.     case ADDR_WINA:
  442.     return "a WINA accepted address";
  443.     default:
  444.     return "unknown address";
  445.     }
  446. }
  447. /*
  448.  * Do semantic analysis, when the event was Push_Message. Do not accept an IP 
  449.  * address, when a non-IP bearer is requested, and a phone number, when an IP
  450.  * bearer is requested.
  451.  * Return 0, when event is unacceptable
  452.  *        1, when it is acceptable
  453.  *       -1, when there are no bearer or network specified
  454.  */
  455. static int event_semantically_valid(WAPEvent *e, long type_of_address)
  456. {
  457.     int ret;
  458.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: doing semantic analysis"
  459.           " for address type %s", address_type(type_of_address));
  460.     if (e->type != Push_Message) {
  461.         return 1;
  462.     }
  463.     
  464.     if (e->u.Push_Message.network_required != 
  465.      e->u.Push_Message.bearer_required) {
  466.        debug("wap.push.pap.compiler", 0, "PAP COMPILER: network-required and"
  467.              " bearer-required must have same value");
  468.        return 0;
  469.     }
  470.     if (type_of_address == ADDR_PLMN) {
  471.             if ((ret = uses_gsm_msisdn_address(
  472.                      e->u.Push_Message.bearer_required,
  473.                      e->u.Push_Message.bearer)) == 0) {
  474.                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: bearer does"
  475.                       " not accept PLMN address");
  476.                 return 0;
  477.             } else if (ret == -1) {
  478.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
  479.                       "bearer missing, reverting to GSM+SMS");
  480.                 return -1;
  481.             } else
  482.         return 1;
  483.                 
  484.     }
  485.     
  486.     if (type_of_address == ADDR_IPV4) { 
  487.             if ((ret = uses_ipv4_address(e->u.Push_Message.bearer_required,
  488.                     e->u.Push_Message.bearer)) == 0) {
  489.                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: bearer does"
  490.                       " not accept IPv4 address");
  491.                 return 0;
  492.             } else if (ret == -1) {
  493.                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
  494.                       " bearer missing, reverting to GSM+CSD");
  495.         return -1;
  496.             } else
  497.         return 1;
  498.     }
  499.     
  500.     if (type_of_address == ADDR_IPV6) { 
  501.         if ((ret = uses_ipv6_address(e->u.Push_Message.bearer_required,
  502.                  e->u.Push_Message.bearer)) == 0) {
  503.              debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
  504.                    " bearer does not accept IPv6 address");
  505.              return 0;
  506.         } else if (ret == -1) {
  507.              debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
  508.                    " bearer missing, reverting Any+Any");
  509.      return -1;
  510.         } else
  511.      return 1;
  512.     }
  513.     
  514.     return 0;
  515. }
  516. /*
  517.  * Bearers accepting IP addresses. These are defined in wdp, appendix c. Note
  518.  * that when ipv6 bearers begin to appear, they must be added to the following
  519.  * table. Currently none are specified.
  520.  */
  521. static char *ip6_bearers[] = {
  522.     "Any"
  523. };
  524. #define NUMBER_OF_IP6_BEARERS sizeof(ip6_bearers)/sizeof(ip6_bearers[0])
  525. static char *ip4_bearers[] = {
  526.     "Any",
  527.     "CSD",
  528.     "Packet Data",
  529.     "GPRS",
  530.     "USSD"
  531. };
  532. #define NUMBER_OF_IP4_BEARERS sizeof(ip4_bearers)/sizeof(ip4_bearers[0])
  533. /*
  534.  * Bearers accepting gsm msisdn addresses are defined in wdp, appendix c. We
  535.  * add any, because Kannel PPG will change this to SMS.
  536.  * Return -1, when there are no bearer defined
  537.  *        0, when a bearer not accepting msisdn address is found
  538.  *        1, when a bearer is accepting msisdn addresesses 
  539.  */
  540. static int uses_gsm_msisdn_address(long bearer_required, Octstr *bearer)
  541. {
  542.     if (!bearer_required)
  543.         return -1;
  544.     
  545.     if (!bearer)
  546.         return 1;
  547.     
  548.     return (octstr_case_compare(bearer, octstr_imm("SMS")) == 0 ||
  549.             octstr_case_compare(bearer, octstr_imm("GHOST/R_DATA")) == 0 ||
  550.             octstr_case_compare(bearer, octstr_imm("Any")) == 0);
  551. }
  552. /*
  553.  * Bearers accepting ipv4 addresses are defined in wdp, appendix c.
  554.  * Return -1, when there are no bearer defined
  555.  *        0, when a bearer not accepting ipv4  address is found
  556.  *        1, when a bearer is accepting ipv4 addresesses 
  557.  */
  558. static int uses_ipv4_address(long bearer_required, Octstr *bearer)
  559. {
  560.     long i;
  561.     if (!bearer_required) {
  562.         return -1;
  563.     }
  564.     if (!bearer)
  565.         return -1;
  566.     
  567.     i = 0;
  568.     while (i < NUMBER_OF_IP4_BEARERS) {
  569.         if (octstr_case_compare(bearer, octstr_imm(ip4_bearers[i])) == 0) {
  570.     return 1;
  571.         }
  572.         ++i;
  573.     }
  574.     return 0;
  575. }
  576. /*
  577.  * Bearers accepting ipv6 addresses (currently *not* accepting) are defined in
  578.  * wdp, appendix c.
  579.  * Return -1, when there are no bearer defined
  580.  *        0, when a bearer not accepting ipv6 address is found
  581.  *        1, when a bearer is accepting ipv6 addresesses 
  582.  */
  583. static int uses_ipv6_address(long bearer_required, Octstr *bearer)
  584. {
  585.     long i;
  586.     if (!bearer_required)
  587.         return -1;
  588.     if (!bearer)
  589.         return -1;
  590.     i = 0;
  591.     while (i < NUMBER_OF_IP6_BEARERS) {
  592.         if (octstr_case_compare(bearer, octstr_imm(ip6_bearers[i])) == 0) {
  593.     return 1;
  594.         }
  595.         ++i;
  596.     }
  597.     return 0;
  598. }
  599. /*
  600.  * Parse node of the syntax tree. DTD, as defined in pap, chapter 9, contains
  601.  * only elements (entities are restricted to DTDs). 
  602.  * The caller must initialize the value of is_any to 0.
  603.  *
  604.  * Output: a) a newly created wap event containing attributes from pap 
  605.  *         document node, if success; partially parsed node, if not. 
  606.  *         b) the type of of the client address 
  607.  *         c) is bearer and/or network any
  608.  * Returns 0, when success
  609.  *        -1, when a non-implemented feature is requested
  610.  *        -2, when error
  611.  */
  612. static int parse_node(xmlNodePtr node, WAPEvent **e, long *type_of_address,
  613.                       int *is_any)
  614. {
  615.     int ret;
  616.     switch (node->type) {
  617.     case XML_COMMENT_NODE:        /* ignore text, comments and pi nodes */
  618.     case XML_PI_NODE:
  619.     case XML_TEXT_NODE:
  620.     break;
  621.     case XML_ELEMENT_NODE:
  622.         if ((ret = parse_element(node, e, type_of_address, is_any)) < 0) {
  623.     return ret;
  624.         }
  625.     break;
  626.     default:
  627.         warning(0, "PAP COMPILER: parse_node: Unknown XML node in PAP source");
  628.         return -2;
  629.     }
  630.     if (node->children != NULL)
  631.         if ((ret = parse_node(node->children, e, type_of_address, 
  632.                 is_any)) < 0) {
  633.             return ret;
  634. }
  635.     if (node->next != NULL)
  636.         if ((ret = parse_node(node->next, e, type_of_address, is_any)) < 0) {
  637.             return ret;
  638.         }
  639.     
  640.     return 0;
  641. }
  642. /*
  643.  * Parse elements of a PAP source. 
  644.  *
  645.  * Output: a) a newly created wap event containing attributes from the
  646.  *         element, if success; containing some unparsed attributes, if not.
  647.  *         b) the type of the client address
  648.  *         c) is bearer and/or network any
  649.  * Returns 0, when success
  650.  *        -1, when a non-implemented feature is requested
  651.  *        -2, when error
  652.  * In addition, return 
  653.  */
  654. static int parse_element(xmlNodePtr node, WAPEvent **e, long *type_of_address,
  655.                          int *is_any)
  656. {
  657.     Octstr *name;
  658.     xmlAttrPtr attribute;
  659.     size_t i;
  660.     int ret;
  661.     name = octstr_create(node->name);
  662.     if (octstr_len(name) == 0) {
  663.         octstr_destroy(name);
  664.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: element name length"
  665.               " zero");
  666.         return -2;
  667.     }
  668.     
  669.     i = 0;
  670.     while (i < NUM_ELEMENTS) {
  671.         if (octstr_compare(name, octstr_imm(pap_elements[i])) == 0)
  672.             break;
  673.         ++i;
  674.     }
  675.     if (i == NUM_ELEMENTS) {
  676.         octstr_destroy(name);
  677.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element");
  678.         return -2;
  679.     }
  680.     if (node->properties != NULL) {
  681.         attribute = node->properties;
  682.         while (attribute != NULL) {
  683.     if ((ret = parse_attribute(name, attribute, e,
  684.                     type_of_address, is_any)) < 0) {
  685.         octstr_destroy(name);
  686.                 return ret;
  687.             }
  688.             attribute = attribute->next;
  689.         }
  690.     }
  691.     octstr_destroy(name);
  692.     return 0;                     /* If we reach this point, our node does not
  693.                                      have any attributes left (or it had no 
  694.                                      attributes to start with). This is *not* 
  695.                                      an error. */
  696. }
  697. /*
  698.  * Parse attribute updates corresponding fields of the  wap event. Check that 
  699.  * both attribute name and value are papwise legal. If value is enumerated, 
  700.  * legal values are stored in the attributes table. Otherwise, call a separate
  701.  * parsing function. If an attribute value is empty, use value "erroneous".
  702.  * 
  703.  * Output: a) a newly created wap event containing parsed attribute from pap 
  704.  *         source, if successfull, an uncomplete wap event otherwise.
  705.  *         b) the type of the client address 
  706.  *         c) is bearer and/or network set any
  707.  * Returns 0, when success
  708.  *        -1, when a non-implemented feature is requested
  709.  *        -2, when error
  710.  */
  711. static int parse_attribute(Octstr *element_name, xmlAttrPtr attribute, 
  712.                            WAPEvent **e, long *type_of_address, int *is_any)
  713. {
  714.     Octstr *attr_name, *value, *nameos;
  715.     size_t i;
  716.     int ret;
  717.     nameos = octstr_imm("erroneous");
  718.     attr_name = octstr_create(attribute->name);
  719.     if (attribute->children != NULL)
  720.         value = create_octstr_from_node(attribute->children);
  721.     else
  722.         value = octstr_imm("erroneous");
  723.     i = 0;
  724.     while (i < NUM_ATTRIBUTES) {
  725.         if (octstr_compare(attr_name, nameos = 
  726.                            octstr_imm(pap_attributes[i].name)) == 0)
  727.     break;
  728.         ++i;
  729.     }
  730.     if (i == NUM_ATTRIBUTES) {
  731.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown attribute");
  732.         goto error;
  733.     }
  734. /*
  735.  * Parse an attribute (it is, check cdata is has for a value) that is *not* an
  736.  * enumeration. Legal values are defined in pap, chapter 9. 
  737.  */
  738.     if (pap_attributes[i].value == NULL) {
  739.         ret = parse_attr_value(element_name, attr_name, value, e, 
  740.                                type_of_address, is_any);
  741. if (ret == -2) {
  742.     goto error;
  743.         } else {
  744.     goto parsed;
  745.         }
  746.     }
  747.     while (octstr_compare(attr_name, 
  748.             nameos = octstr_imm(pap_attributes[i].name)) == 0) {
  749.         if (octstr_compare(value, octstr_imm(pap_attributes[i].value)) == 0)
  750.     break;
  751.         ++i;
  752.     }
  753.     if (octstr_compare(attr_name, nameos) != 0) {
  754.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown attribute"
  755.               " value");
  756.         goto error;
  757.     }
  758. /*
  759.  * Check that the value of the attribute is one enumerated for this attribute
  760.  * in pap, chapter 9.
  761.  */
  762.     if (set_attribute_value(element_name, value, attr_name, e) == -1) 
  763.         goto error;
  764.     octstr_destroy(attr_name);
  765.     octstr_destroy(value);
  766.     return 0;
  767. error:
  768.     octstr_destroy(attr_name);
  769.     octstr_destroy(value);
  770.     return -2;
  771. parsed:
  772.     octstr_destroy(attr_name);
  773.     octstr_destroy(value);
  774.     return ret;
  775. }
  776. /* 
  777.  * Value parsing functions return the newly created wap event containing 
  778.  * attribute value from pap source, if successfull; NULL otherwise . Value 
  779.  * types of attributes are defined in pap, chapter 9.  
  780.  */
  781. static int parse_push_message_value(Octstr *attr_name, Octstr *attr_value, 
  782.                                     WAPEvent **e)
  783. {
  784.     Octstr *ros;
  785.     ros = octstr_imm("erroneous");
  786.     if (octstr_compare(attr_name, octstr_imm("push-id")) == 0) {
  787.         octstr_destroy((**e).u.Push_Message.pi_push_id);
  788. (**e).u.Push_Message.pi_push_id = octstr_duplicate(attr_value);
  789.         return 0;
  790.     } else if (octstr_compare(attr_name, 
  791.              octstr_imm("deliver-before-timestamp")) == 0) {
  792. (**e).u.Push_Message.deliver_before_timestamp = 
  793.              (ros = parse_date(attr_value)) ? 
  794.              octstr_duplicate(attr_value) : octstr_imm("erroneous");  
  795.         return return_flag(ros);
  796.     } else if (octstr_compare(attr_name, 
  797.              octstr_imm("deliver-after-timestamp")) == 0) {
  798. (**e).u.Push_Message.deliver_after_timestamp = 
  799.              (ros = parse_date(attr_value)) ? 
  800.              octstr_duplicate(attr_value) : octstr_imm("erroneous");
  801.         return return_flag(ros);
  802.     } else if (octstr_compare(attr_name, 
  803.              octstr_imm("source-reference")) == 0) {
  804. (**e).u.Push_Message.source_reference = octstr_duplicate(attr_value);
  805.         return 0;
  806.     } else if (octstr_compare(attr_name, 
  807.              octstr_imm("ppg-notify-requested-to")) == 0) {
  808. (**e).u.Push_Message.ppg_notify_requested_to = 
  809.              octstr_duplicate(attr_value);
  810.         return 0;
  811.     }
  812.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown push message"
  813.           " element attribute");
  814.     return -2;
  815. }  
  816. /*
  817.  * When there is no legal address to be stored in field (either parsing was
  818.  * unsuccessfull or an unimplemented address format was requested by the push
  819.  * initiator) we use value "erroneous". This is necessary, because this a 
  820.  * mandatory field.
  821.  *
  822.  * Output a) a newly created wap event
  823.  *        b) the type of the client address
  824.  */
  825. static int parse_address_value(Octstr *attr_name, Octstr *attr_value, 
  826.                                WAPEvent **e, long *type_of_address)
  827. {
  828.     int ret;
  829.     ret = -2;
  830.     if (octstr_compare(attr_name, octstr_imm("address-value")) == 0) {
  831.         octstr_destroy((**e).u.Push_Message.address_value);
  832. (**e).u.Push_Message.address_value = 
  833.              (ret = parse_address(&attr_value, type_of_address)) > -1 ? 
  834.              octstr_duplicate(attr_value) : octstr_imm("erroneous");
  835.         return ret;
  836.     } 
  837.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown address element"
  838.           " attribute");
  839.     return -2;
  840. }
  841. static int parse_quality_of_service_value(Octstr *attr_name, 
  842.                                           Octstr *attr_value, WAPEvent **e,
  843.                                           int *is_any)
  844. {
  845.     Octstr *ros;
  846.     ros = octstr_imm("erroneous");
  847.     if (octstr_compare(attr_name, octstr_imm("network")) == 0) {
  848. (**e).u.Push_Message.network = (ros = parse_network(attr_value)) ? 
  849.             octstr_duplicate(attr_value) : octstr_imm("erroneous");
  850.         set_any_value(is_any, attr_name, attr_value);
  851.         return return_flag(ros);
  852.     }
  853.     if (octstr_compare(attr_name, octstr_imm("bearer")) == 0) {
  854. (**e).u.Push_Message.bearer = (ros = parse_bearer(attr_value)) ? 
  855.             octstr_duplicate(attr_value) : octstr_imm("erroneous");
  856.         set_any_value(is_any, attr_name, attr_value);
  857.         return return_flag(ros);
  858.     }
  859.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown quality of"
  860.           " service attribute");
  861.     return -2;
  862. }
  863. static void set_any_value(int *is_any, Octstr *attr_name, Octstr *attr_value)
  864. {
  865.     switch (*is_any) {
  866.     case NEITHER:
  867.         if (octstr_compare(attr_name, octstr_imm("bearer")) == 0 &&
  868.                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
  869.     *is_any = BEARER_ANY;
  870.         else if (octstr_compare(attr_name, octstr_imm("network")) == 0 &&
  871.                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
  872.     *is_any = NETWORK_ANY;
  873.     return;
  874.     case BEARER_ANY:
  875.         if (octstr_compare(attr_name, octstr_imm("network")) == 0 &&
  876.                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
  877.     *is_any = EITHER;
  878.     return;
  879.     case NETWORK_ANY:
  880.         if (octstr_compare(attr_name, octstr_imm("bearer")) == 0 &&
  881.                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
  882.     *is_any = EITHER;
  883.     return;
  884.     case EITHER:
  885.          debug("wap.push.pap.compiler", 0, "PAP COMPILER: problems with"
  886.                " setting any");
  887.          *is_any = ERROR_ANY;
  888.     return;
  889.     default:
  890.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong any value");
  891.         *is_any = ERROR_ANY;
  892.     return;
  893.     }
  894. }
  895. static int parse_push_response_value(Octstr *attr_name, Octstr *attr_value,
  896.                                      WAPEvent **e)
  897. {
  898.     Octstr *ros;
  899.     int ret;
  900.     ret = -2;
  901.     ros = octstr_imm("erroneous");
  902.     if (octstr_compare(attr_name, octstr_imm("push-id")) == 0) {
  903.         octstr_destroy((**e).u.Push_Response.pi_push_id);
  904. (**e).u.Push_Response.pi_push_id = octstr_duplicate(attr_value);
  905.         return 0;
  906.     } else if (octstr_compare(attr_name, octstr_imm("sender-address")) == 0) {
  907. (**e).u.Push_Response.sender_address = octstr_duplicate(attr_value);
  908.         return 0;
  909.     } else if (octstr_compare(attr_name, octstr_imm("reply-time")) == 0) {
  910. (**e).u.Push_Response.reply_time = (ros = parse_date(attr_value)) ?
  911.              octstr_duplicate(attr_value) : NULL;
  912.         return return_flag(ros);
  913.     } else if (octstr_compare(attr_name, octstr_imm("sender-name")) == 0) {
  914. (**e).u.Push_Response.sender_name = octstr_duplicate(attr_value);
  915.         return 0;
  916.     }
  917.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown push response"
  918.           " element attribute");
  919.     return -2;
  920. }
  921. static int parse_progress_note_value(Octstr *attr_name, Octstr *attr_value,
  922.                                      WAPEvent **e)
  923. {
  924.     Octstr *ros;
  925.     int ret;
  926.     ret = -2;
  927.     ros = octstr_imm("erroneous");
  928.     if (octstr_compare(attr_name, octstr_imm("stage")) == 0) {
  929.         (**e).u.Progress_Note.stage = 
  930.              (ret = parse_state(attr_value)) ? ret : 0;
  931.         return ret;
  932.     } else if (octstr_compare(attr_name, octstr_imm("note")) == 0) {
  933. (**e).u.Progress_Note.note = octstr_duplicate(attr_value);
  934.         return 0;
  935.     } else if (octstr_compare(attr_name, octstr_imm("time")) == 0) {
  936. (**e).u.Progress_Note.time = (ros = parse_date(attr_value)) ?
  937.              octstr_duplicate(attr_value) : octstr_imm("erroneous");
  938. return return_flag(ros);
  939.     }
  940.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown progress note"
  941.           " element attribute");
  942.     return -2;
  943. }
  944. static int parse_bad_message_response_value(Octstr *attr_name, 
  945.                                             Octstr *attr_value, WAPEvent **e)
  946. {
  947.     if (octstr_compare(attr_name, octstr_imm("code")) == 0) {
  948. (**e).u.Bad_Message_Response.code = parse_code(attr_value);
  949.         return 0;
  950.     } else if (octstr_compare(attr_name, octstr_imm("desc")) == 0) {
  951. (**e).u.Bad_Message_Response.desc = octstr_duplicate(attr_value);
  952.         return 0;
  953.     } else if (octstr_compare(attr_name, 
  954.     octstr_imm("bad-message-fragment")) == 0) {
  955.         (**e).u.Bad_Message_Response.bad_message_fragment = 
  956.             octstr_duplicate(attr_value);
  957.         return 0;
  958.     }
  959.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown bad message"
  960.           " response element attribute");
  961.     return -2;
  962. }
  963. static int parse_response_result_value(Octstr *attr_name, 
  964.                                       Octstr *attr_value, WAPEvent **e)
  965. {
  966.     if (octstr_compare(attr_name, octstr_imm("code")) == 0) {
  967. (**e).u.Push_Response.code = parse_code(attr_value);
  968.         return 0;
  969.     } else if (octstr_compare(attr_name, octstr_imm("desc")) == 0) {
  970. (**e).u.Push_Response.desc = octstr_duplicate(attr_value);
  971.         return 0;
  972.     }
  973.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown response result"
  974.           " attribute");
  975.     return -2;
  976. /*
  977.  * Do not create multiple events. If *e points to NULL, we have not yet creat-
  978.  * ed a wap event. Create a wap event mandatory fields set to error values 
  979.  * (these will be latter overwritten). This hack will disappear when we have
  980.  * PAP validation.
  981.  */
  982. static void wap_event_accept_or_create(Octstr *element_name, WAPEvent **e)
  983. {
  984.     if (octstr_compare(element_name, octstr_imm("push-message")) == 0 
  985.             && *e == NULL) {         
  986.         *e = wap_event_create(Push_Message); 
  987.         (**e).u.Push_Message.pi_push_id = octstr_format("%s", "erroneous");
  988.         (**e).u.Push_Message.address_value = octstr_format("%s", "erroneous");
  989.     } else if (octstr_compare(element_name, octstr_imm("push-response")) == 0 
  990.             && *e == NULL) {
  991.         *e = wap_event_create(Push_Response);
  992.         (**e).u.Push_Response.pi_push_id = octstr_format("%s", "erroneous");
  993.     } else if (octstr_compare(element_name, octstr_imm("progress-note")) == 0 
  994.             && *e == NULL) {
  995.         *e = wap_event_create(Progress_Note);
  996.     } else if (octstr_compare(element_name, 
  997.             octstr_imm("badmessage-response")) == 0 && *e == NULL) {
  998.         *e = wap_event_create(Bad_Message_Response);
  999.     } 
  1000. }
  1001. static int return_flag(Octstr *ros)
  1002. {
  1003.     if (ros) {
  1004.         return 0;
  1005.     } else {
  1006.         return -2;
  1007.     }
  1008. }
  1009. /*
  1010.  * Validates non-enumeration attributes and stores their value to a newly
  1011.  * created wap event e. (Even when attribute value parsing was not success-
  1012.  * full.) We do not accept NULL or empty attributes (if this kind of an 
  1013.  * attribute is optional, we just drop it from the tokenised document).
  1014.  *
  1015.  * Output: a) a wap event, as created by subroutines
  1016.  *         b) the type of the client address
  1017.  *         c) is bearer or network set any
  1018.  * Returns 0, when success,
  1019.  *        -1, when a non-implemented feature requested.
  1020.  *        -2, when an error
  1021.  */
  1022. static int parse_attr_value(Octstr *element_name, Octstr *attr_name, 
  1023.                             Octstr *attr_value, WAPEvent **e, 
  1024.                             long *type_of_address, int *is_any)
  1025. {
  1026.     if (octstr_compare(attr_value, octstr_imm("erroneous")) == 0) {
  1027.         debug("wap.push.pap.compiler", 0, "unknown value for an attribute");
  1028.         return -2;
  1029.     }
  1030.     wap_event_accept_or_create(element_name, e);
  1031.     if (octstr_compare(element_name, octstr_imm("push-message")) == 0) {
  1032.         return parse_push_message_value(attr_name, attr_value, e);
  1033.     } else if (octstr_compare(element_name, octstr_imm("address")) == 0) {
  1034.         return parse_address_value(attr_name, attr_value, e, type_of_address);
  1035.     } else if (octstr_compare(element_name, 
  1036.                    octstr_imm("quality-of-service")) == 0) {
  1037.         return parse_quality_of_service_value(attr_name, attr_value, e, 
  1038.                                               is_any);
  1039.     } else if (octstr_compare(element_name, 
  1040.                               octstr_imm("push-response")) == 0) {
  1041.         return parse_push_response_value(attr_name, attr_value, e);
  1042.     } else if (octstr_compare(element_name, 
  1043.                    octstr_imm("progress-note")) == 0) {
  1044.         return parse_progress_note_value(attr_name, attr_value, e);
  1045.     } else if (octstr_compare(element_name, 
  1046.                    octstr_imm("badmessage-response")) == 0) {
  1047.         return parse_bad_message_response_value(attr_name, attr_value, e);
  1048.     } else if (octstr_compare(element_name, 
  1049.                    octstr_imm("response-result")) == 0) {
  1050.         return parse_response_result_value(attr_name, attr_value, e);
  1051.     }
  1052.     return -2; 
  1053. }
  1054. /*
  1055.  * Stores values of enumeration fields of a pap control message to wap event e.
  1056.  */
  1057. static int set_attribute_value(Octstr *element_name, Octstr *attr_value, 
  1058.                                Octstr *attr_name, WAPEvent **e)
  1059. {
  1060.     int ret;
  1061.     ret = -2;
  1062.     if (octstr_compare(element_name, octstr_imm("push-message")) == 0) {
  1063.         if (octstr_compare(attr_name, 
  1064.                           octstr_imm("progress-notes-requested")) == 0)
  1065.             (**e).u.Push_Message.progress_notes_requested = 
  1066.                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
  1067.     } else if (octstr_compare(element_name, 
  1068.      octstr_imm("quality-of-service")) == 0) {
  1069.         if (octstr_compare(attr_name, octstr_imm("priority")) == 0)
  1070.             (**e).u.Push_Message.priority = 
  1071.                  (ret = parse_priority(attr_value)) >= 0 ? ret : 0;
  1072.         else if (octstr_compare(attr_name, octstr_imm("delivery-method")) == 0)
  1073.             (**e).u.Push_Message.delivery_method = 
  1074.                  (ret = parse_delivery_method(attr_value)) >= 0 ? ret : 0;
  1075.         else if (octstr_compare(attr_name, 
  1076.                                octstr_imm("network-required")) == 0)
  1077.             (**e).u.Push_Message.network_required = 
  1078.                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
  1079.         else if (octstr_compare(attr_name, octstr_imm("bearer-required")) == 0)
  1080.             (**e).u.Push_Message.bearer_required = 
  1081.                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
  1082.     }
  1083.     return ret;
  1084. }
  1085. /*
  1086.  * We must recognize status class and treat unrecognized codes as a x000 code,
  1087.  * as required by pap, 9.13, p 27.
  1088.  */
  1089. static int parse_code(Octstr *attr_value)
  1090. {
  1091.     long attr_as_number,
  1092.          len;
  1093.     size_t i;
  1094.     Octstr *ros;
  1095.     for (i = 0; i < NUM_CODES; i++) {
  1096.          ros = octstr_format("%d", pap_codes[i]);
  1097.          if (octstr_compare(attr_value, ros) == 0) {
  1098.      octstr_destroy(ros);
  1099.      return pap_codes[i];
  1100.          }
  1101.          octstr_destroy(ros);
  1102.     }
  1103.     warning(0, "PAP COMPILER: parse_code: no such return code, reversing to"
  1104.                " x000 code");
  1105.     len = octstr_parse_long(&attr_as_number, attr_value, 0, 10);
  1106.     if (attr_as_number >= PAP_OK && attr_as_number < PAP_BAD_REQUEST) {
  1107.         attr_as_number = PAP_OK;
  1108.     } else if (attr_as_number >= PAP_BAD_REQUEST && 
  1109.             attr_as_number < PAP_INTERNAL_SERVER_ERROR) {
  1110.         attr_as_number = PAP_BAD_REQUEST;
  1111.     } else if (attr_as_number >= PAP_INTERNAL_SERVER_ERROR &&
  1112.     attr_as_number < PAP_SERVICE_FAILURE) {
  1113.         attr_as_number = PAP_INTERNAL_SERVER_ERROR;
  1114.     } else if (attr_as_number >= PAP_SERVICE_FAILURE &&
  1115.     attr_as_number < PAP_CLIENT_ABORTED) {
  1116.         attr_as_number = PAP_SERVICE_FAILURE;
  1117.     } else {
  1118.         attr_as_number = PAP_CLIENT_ABORTED;
  1119.     }
  1120.     
  1121.     return attr_as_number;
  1122. }
  1123. static Octstr *parse_bearer(Octstr *attr_value)
  1124. {
  1125.     size_t i;
  1126.     Octstr *ros;
  1127.     for (i = 0; i < NUM_BEARER_TYPES; i++) {
  1128.          if (octstr_case_compare(attr_value, 
  1129.                  ros = octstr_imm(pap_bearer_types[i])) == 0)
  1130.      return ros;
  1131.     }
  1132.     warning(0, "no such bearer");
  1133.     return NULL;
  1134. }
  1135. static Octstr *parse_network(Octstr *attr_value)
  1136. {
  1137.     size_t i;
  1138.     Octstr *ros;
  1139.     for (i = 0; i < NUM_NETWORK_TYPES; i++) {
  1140.          if (octstr_case_compare(attr_value, 
  1141.          ros = octstr_imm(pap_network_types[i])) == 0) {
  1142.      return ros;
  1143.          }
  1144.     }
  1145.     warning(0, "no such network");
  1146.     return NULL;
  1147. }
  1148. /*
  1149.  * Used for attributes accepting logical values.
  1150.  */
  1151. static int parse_requirement(Octstr *attr_value)
  1152. {
  1153.     long attr_as_number;
  1154.     attr_as_number = -2;
  1155.     if (octstr_case_compare(attr_value, octstr_imm("false")) == 0)
  1156.         attr_as_number = PAP_FALSE;
  1157.     else if (octstr_case_compare(attr_value, octstr_imm("true")) == 0)
  1158.         attr_as_number = PAP_TRUE;
  1159.     else
  1160.         warning(0, "in a requirement, value not a truth value");
  1161.     return attr_as_number;
  1162. }
  1163. /*
  1164.  * Priority is defined in pap, chapter 9.2.2.
  1165.  */
  1166. static int parse_priority(Octstr *attr_value)
  1167. {
  1168.     long attr_as_number;
  1169.     attr_as_number = -2;
  1170.     if (octstr_case_compare(attr_value, octstr_imm("high")) == 0)
  1171.         attr_as_number = PAP_HIGH;
  1172.     else if (octstr_case_compare(attr_value, octstr_imm("medium")) == 0)
  1173.         attr_as_number = PAP_MEDIUM;
  1174.     else if (octstr_case_compare(attr_value, octstr_imm("low")) == 0)
  1175.         attr_as_number = PAP_LOW;
  1176.     else
  1177.         warning(0, "illegal priority");
  1178.     return attr_as_number;
  1179. }
  1180. /*
  1181.  * Delivery-method is defined in pap, chapter 9.2.2.
  1182.  */
  1183. static int parse_delivery_method(Octstr *attr_value)
  1184. {
  1185.     long attr_as_number;
  1186.     attr_as_number = -2;
  1187.     if (octstr_case_compare(attr_value, octstr_imm("confirmed")) == 0)
  1188.         attr_as_number = PAP_CONFIRMED;
  1189.     else if (octstr_case_compare(attr_value, 
  1190.             octstr_imm("preferconfirmed")) == 0)
  1191.         attr_as_number = PAP_PREFERCONFIRMED;
  1192.     else if (octstr_case_compare(attr_value, octstr_imm("unconfirmed")) == 0)
  1193.         attr_as_number = PAP_UNCONFIRMED;
  1194.     else if (octstr_case_compare(attr_value, octstr_imm("notspecified")) == 0)
  1195. attr_as_number = PAP_NOT_SPECIFIED;
  1196.     else
  1197.         warning(0, "illegal delivery method");
  1198.     
  1199.     return attr_as_number;
  1200. }
  1201. /*
  1202.  * PAP states are defined in ppg, chapter 6.
  1203.  */
  1204. static int parse_state(Octstr *attr_value)
  1205. {
  1206.     long attr_as_number;
  1207.     attr_as_number = -2;
  1208.     if (octstr_case_compare(attr_value, octstr_imm("undeliverable")) == 0)
  1209.         attr_as_number = PAP_UNDELIVERABLE; 
  1210.     else if (octstr_case_compare(attr_value, octstr_imm("pending")) == 0)
  1211.         attr_as_number = PAP_PENDING; 
  1212.     else if (octstr_case_compare(attr_value, octstr_imm("expired")) == 0)
  1213.         attr_as_number = PAP_EXPIRED;
  1214.     else if (octstr_case_compare(attr_value, octstr_imm("delivered")) == 0)
  1215.         attr_as_number = PAP_DELIVERED;
  1216.     else if (octstr_case_compare(attr_value, octstr_imm("aborted")) == 0)
  1217.         attr_as_number = PAP_ABORTED;
  1218.     else if (octstr_case_compare(attr_value, octstr_imm("timeout")) == 0)
  1219.         attr_as_number = PAP_TIMEOUT;
  1220.     else if (octstr_case_compare(attr_value, octstr_imm("cancelled")) == 0)
  1221.         attr_as_number = PAP_CANCELLED;
  1222.     else 
  1223.          warning(0, "illegal ppg state");
  1224.     return attr_as_number;
  1225. }
  1226. /*
  1227.  * Check legality of pap client address attribute and transform it to the 
  1228.  * client address usable in Kannel wap address tuple data type. The grammar 
  1229.  * for client address is specified in ppg, chapter 7.1.
  1230.  *
  1231.  * Output: the address type of the client address
  1232.  * Returns:   0, when success
  1233.  *           -1, a non-implemented pap feature requested by pi
  1234.  *           -2, address parsing error  
  1235.  */
  1236. static int parse_address(Octstr **address, long *type_of_address)
  1237. {
  1238.     long pos;
  1239.     Octstr *copy;
  1240.     pos = octstr_len(*address) - 1;
  1241. /*
  1242.  * Delete first separator, if there is one. This will help our parsing later.
  1243.  */
  1244.     if (octstr_get_char(*address, 0) == '/')
  1245.         octstr_delete(*address, 0, 1);
  1246.     if ((pos = parse_ppg_specifier(address, pos)) < 0) {
  1247.         warning(0, "illegal ppg specifier");
  1248.         return -2;
  1249.     }
  1250.     if ((pos = parse_wappush_client_address(address, pos, 
  1251.             type_of_address)) == -2) {
  1252.         warning(0, "illegal client address");
  1253.         return -2;
  1254.     } else if (pos == -1) {
  1255.         warning(0, "unimplemented feature");
  1256.         return -1;
  1257.     }
  1258.     info(0, "client address was <%s>, accepted", 
  1259.          octstr_get_cstr(copy = octstr_duplicate(*address)));    
  1260.     octstr_destroy(copy);
  1261.     return pos;
  1262. }
  1263. /*
  1264.  * Output: the type of the client address
  1265.  */
  1266. static long parse_wappush_client_address(Octstr **address, long pos, 
  1267.                                          long *type_of_address)
  1268. {
  1269.     if ((pos = parse_client_specifier(address, pos, type_of_address)) < 0) {
  1270.         return pos;
  1271.     }
  1272.     pos = parse_constant("WAPPUSH", address, pos);
  1273.     
  1274.     return pos;
  1275. }
  1276. /*
  1277.  * We are not interested of ppg specifier, but we must check its format.
  1278.  */
  1279. static long parse_ppg_specifier(Octstr **address, long pos)
  1280. {
  1281.     if (pos >= 0) {
  1282.         pos = parse_dom_fragment(address, pos);
  1283.     }
  1284.     while (octstr_get_char(*address, pos) != '@' && pos >= 0) {
  1285.         if (octstr_get_char(*address, pos) == '.') {
  1286.     octstr_delete(*address, pos, 1);
  1287.             --pos;
  1288.         } else {
  1289.             debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing"
  1290.                   " separator .");
  1291.     return -2;
  1292.         }
  1293.         pos = parse_dom_fragment(address, pos);
  1294.     } 
  1295.     pos = drop_character(address, pos);
  1296.     if (octstr_get_char(*address, pos) == '/' && pos >= 0) {
  1297.         octstr_delete(*address, pos, 1);
  1298.         if (pos > 0)
  1299.             --pos;
  1300.     }
  1301.     if (pos < 0) {
  1302.        debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator /"
  1303.              " or @");
  1304.        return -2;
  1305.     }
  1306.     return pos;
  1307. }
  1308. /*
  1309.  * Output: the type of a client address.
  1310.  *
  1311.  * Return a negative value, when error, positive (the position of the parsing 
  1312.  * cursor) otherwise.
  1313.  */
  1314. static long parse_client_specifier(Octstr **address, long pos, 
  1315.                                    long *type_of_address)
  1316. {
  1317.     Octstr *type_value;
  1318.     type_value = octstr_create("");
  1319.     if ((pos = parse_type(address, &type_value, pos)) < 0) {
  1320.         goto parse_error;
  1321.     }
  1322.     pos = drop_character(address, pos);
  1323.     if ((pos = parse_constant("/TYPE", address, pos)) < 0) {
  1324.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: constant TYPE"
  1325.               " missing from the client address");
  1326.         goto parse_error;
  1327.     }
  1328.     if (octstr_case_compare(type_value, octstr_imm("USER")) == 0) {
  1329.         *type_of_address = ADDR_USER;
  1330.         goto not_implemented;
  1331.     }
  1332.     if ((pos = parse_ext_qualifiers(address, pos, type_value)) < 0) {
  1333.         goto parse_error;
  1334.     }
  1335.     if (octstr_case_compare(type_value, octstr_imm("PLMN")) == 0) {
  1336.         *type_of_address = ADDR_PLMN;
  1337.         pos = parse_global_phone_number(address, pos);
  1338.     }
  1339.     else if (octstr_case_compare(type_value, octstr_imm("IPv4")) == 0) {
  1340.         *type_of_address = ADDR_IPV4;
  1341.         pos = parse_ipv4(address, pos);
  1342.     }
  1343.     else if (octstr_case_compare(type_value, octstr_imm("IPv6")) == 0) {
  1344.         *type_of_address = ADDR_IPV6;
  1345.         pos = parse_ipv6(address, pos);
  1346.     }
  1347.     else if (wina_bearer_identifier(type_value)) {
  1348.         *type_of_address = ADDR_WINA;
  1349.         pos = parse_escaped_value(address, pos); 
  1350.     }    
  1351.     else {
  1352.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong address type"
  1353.               " in the client address");
  1354.         goto parse_error; 
  1355.     }
  1356.     octstr_destroy(type_value);
  1357.     return pos;
  1358. not_implemented:
  1359.     octstr_destroy(type_value);
  1360.     return -1;
  1361. parse_error:
  1362.     octstr_destroy(type_value);
  1363.     return -2;
  1364. }
  1365. static long parse_constant(const char *field_name, Octstr **address, long pos)
  1366. {
  1367.     size_t i,    
  1368.            size;
  1369.     Octstr *nameos;
  1370.     nameos = octstr_format("%s", field_name);
  1371.     size = octstr_len(nameos);
  1372.     i = 0;
  1373.     
  1374.     while (octstr_get_char(*address, pos - i)  == 
  1375.                octstr_get_char(nameos, size-1 - i) && i <  size) {
  1376.         ++i;
  1377.     }
  1378.     while (octstr_get_char(*address, pos) != 
  1379.                octstr_get_char(nameos, 0) && pos >= 0) {
  1380.         pos = drop_character(address, pos);
  1381.     }
  1382.     pos = drop_character(address, pos);    
  1383.     if (pos < 0 || i != size) {
  1384.         debug("wap.push.pap.compiler", 0, "parse_constant: unparsable"
  1385.               " constant %s", field_name);
  1386.         octstr_destroy(nameos);
  1387.         return -2;
  1388.     }
  1389.     octstr_destroy(nameos);
  1390.     return pos;
  1391. }
  1392. static long parse_dom_fragment(Octstr **address, long pos)
  1393. {
  1394.     unsigned char c;
  1395.     if (pos >= 0) { 
  1396.         if (isalnum(octstr_get_char(*address, pos))) {
  1397.     pos = drop_character(address, pos);
  1398.         } else
  1399.     return -2;
  1400.     }
  1401.     while ((c = octstr_get_char(*address, pos)) != '@' && 
  1402.                octstr_get_char(*address, pos) != '.' && pos >= 0)  {
  1403.         if (isalnum(c) || c == '-') {
  1404.     pos = drop_character(address, pos);
  1405.         } else
  1406.     return -2;
  1407.     } 
  1408.     return pos;
  1409. }
  1410. static long drop_character(Octstr **address, long pos)
  1411. {
  1412.     if (pos >= 0) {
  1413.         octstr_delete(*address, pos, 1);
  1414.         if (pos > 0)
  1415.             --pos;
  1416.     }
  1417.     return pos;
  1418. }
  1419. static long parse_type(Octstr **address, Octstr **type_value, long pos)
  1420. {
  1421.     unsigned char c;
  1422.     while ((c = octstr_get_char(*address, pos)) != '=' && pos >= 0) {   
  1423.         *type_value = prepend_char(*type_value, c);
  1424.         pos = drop_character(address, pos);
  1425.     } 
  1426.     if (pos < 0)
  1427.         return -2;
  1428.     return pos;
  1429. }
  1430. static long parse_ext_qualifiers(Octstr **address, long pos, 
  1431.                                  Octstr *type)
  1432. {
  1433.     int ret;
  1434.     while ((ret = qualifiers(*address, pos, type)) == 1) {
  1435.         if ((pos = parse_qualifier_value(address, pos)) < 0)
  1436.             return pos;
  1437.         if ((pos = parse_qualifier_keyword(address, pos)) < 0)
  1438.             return pos;
  1439.     }
  1440.     if (ret == 1) {
  1441.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: erroneous qualifiers"
  1442.               " in the client address");
  1443.         return -2;
  1444.     }
  1445.     return pos;
  1446. }
  1447. /*
  1448.  * According to ppg, chapter 7.1, global phone number starts with +. Phone
  1449.  * number is here an unique identifier, so if it does not conform the inter-
  1450.  * national format, we return an error. (Is up to bearerbox to transform it
  1451.  * to an usable phone number)
  1452.  */
  1453. static long parse_global_phone_number(Octstr **address, long pos)
  1454. {
  1455.     unsigned char c;
  1456.     while ((c = octstr_get_char(*address, pos)) != '+' && pos >= 0) {
  1457.          if (!isdigit(c) && c != '-' && c != '.') {
  1458.              debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator"
  1459.                    " in a phone number (- and . allowed)");
  1460.              return -2;
  1461.  } else {
  1462.      --pos;
  1463.          }
  1464.     }
  1465.     if (pos == 0) {
  1466.         debug("wap.push.pap.compiler", 0, "PAP COMPILER:a phone number must"
  1467.               " start with +");
  1468.         return -2;
  1469.     }
  1470.     if (pos > 0)
  1471.         --pos;
  1472.     pos = drop_character(address, pos);
  1473.     return pos;
  1474. }
  1475. static long parse_ipv4(Octstr **address, long pos)
  1476. {
  1477.     long i;
  1478.     if ((pos = parse_ipv4_fragment(address, pos)) < 0) {
  1479.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator in a"
  1480.               " ipv4 address");
  1481.         return -2;
  1482.     }
  1483.     i = 1;
  1484.     while (i <= 3 && octstr_get_char(*address, pos) != '=' && pos >= 0) {
  1485.         pos = parse_ipv4_fragment(address, pos);
  1486.         ++i;
  1487.     }
  1488.     if (pos == 0) {
  1489.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator at"
  1490.               " beginning of a client address (=)");
  1491.         return -2;
  1492.     }
  1493.     return pos;
  1494. }
  1495. static long parse_ipv6(Octstr **address, long pos)
  1496. {
  1497.     long i;
  1498.     if ((pos = parse_ipv6_fragment(address, pos)) < 0) {
  1499.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator in a"
  1500.               " ipv6 address");
  1501.         return -2;
  1502.     }
  1503.     i = 1;
  1504.     while (i <= 7 && octstr_get_char(*address, pos) != '=' && pos >= 0) {
  1505.         pos = parse_ipv6_fragment(address, pos);
  1506.         ++i;
  1507.     }
  1508.     if (pos == 0) {
  1509.         debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator at"
  1510.               " beginning of a client address (=)");
  1511.         return -2;
  1512.     }
  1513.     return pos;
  1514. }
  1515. /*
  1516.  * WINA web page does not include address type identifiers. Following ones are
  1517.  * from wdp, Appendix C.
  1518.  */
  1519. static char *bearer_address[] = {
  1520.     "GSM_MSISDN",
  1521.     "ANSI_136_MSISDN",
  1522.     "IS_637_MSISDN",
  1523.     "iDEN_MSISDN",
  1524.     "FLEX_MSISDN",
  1525.     "PHS_MSISDN",
  1526.     "GSM_Service_Code",
  1527.     "TETRA_ITSI",
  1528.     "TETRA_MSISDN",
  1529.     "ReFLEX_MSIDDN",
  1530.     "MAN",
  1531. };
  1532. static size_t bearer_address_size = sizeof(bearer_address) / 
  1533.                                     sizeof(bearer_address[0]);
  1534. static int wina_bearer_identifier(Octstr *type_value)
  1535. {
  1536.     size_t i;
  1537.     i = 0;
  1538.     while (i < bearer_address_size) {
  1539.         if (octstr_case_compare(type_value, 
  1540.                 octstr_imm(bearer_address[i])) == 0)
  1541.     return 1;
  1542.         ++i;
  1543.     }
  1544.     debug("wap.push.pap.compiler", 0, "PAP COMPILER: a bearer not registered"
  1545.           " by wina");
  1546.     return 0;
  1547. }
  1548. /*
  1549.  * Note that we parse backwards. First we create a window of three characters
  1550.  * (representing a possible escaped character). If the first character of the 
  1551.  * window is not escape, we handle the last character and move the window one
  1552.  * character backwards; if it is, we handle escaped sequence and create a new
  1553.  * window. If we cannot create a window, rest of characters are unescaped.
  1554.  */
  1555. static long parse_escaped_value(Octstr **address, long pos)
  1556. {
  1557.     int ret;
  1558.     if (create_peek_window(address, &pos) == 0)
  1559.          if ((pos = rest_unescaped(address, pos)) == -2)
  1560.              return -2;
  1561.     while (octstr_get_char(*address, pos) != '=' && pos >= 0) {
  1562.         if ((ret = issafe(address, pos)) == 1) {
  1563.     pos = accept_safe(address, pos);
  1564.         } else if (ret == 0) {
  1565.     if ((pos = accept_escaped(address, pos)) < 0)
  1566.                 return -2;  
  1567.             if (create_peek_window(address, &pos) == 0)
  1568.                 if ((pos = rest_unescaped(address, pos)) == -2)
  1569.                     return -2;
  1570.         }
  1571.     }
  1572.     pos = drop_character(address, pos);
  1573.     return pos;
  1574. }
  1575. static Octstr *prepend_char(Octstr *os, unsigned char c)
  1576. {
  1577.     Octstr *tmp;
  1578.     tmp = octstr_format("%c", c);
  1579.     octstr_insert(os, tmp, 0);
  1580.     octstr_destroy(tmp);
  1581.     return os;
  1582. }
  1583. /*
  1584.  * Ext qualifiers contain /, ipv4 address contains . , ipv6 address contains :.
  1585.  * phone number contains + and escaped-value contain no specific tokens. Lastly
  1586.  * mentioned are for future extensions, but we must parse them.
  1587.  * Return 1, when qualifiers found
  1588.  *        0, when not
  1589.  *       -1, when an error was found during the process
  1590.  */
  1591. static int qualifiers(Octstr *address, long pos, Octstr *type)
  1592. {
  1593.     unsigned char term,
  1594.          c;
  1595.     long i;
  1596.     i = pos;
  1597.     c = 'E';
  1598.     if (octstr_case_compare(type, octstr_imm("PLMN")) == 0)
  1599.         term = '+';
  1600.     else if (octstr_case_compare(type, octstr_imm("IPv4")) == 0)
  1601.         term = '.';
  1602.     else if (octstr_case_compare(type, octstr_imm("IPv6")) == 0)
  1603.         term = ':';
  1604.     else
  1605.         term = 'N';
  1606.     if (term != 'N') {
  1607.         while ((c = octstr_get_char(address, i)) != term && i != 0) {
  1608.             if (c == '/')
  1609.                 return 1;
  1610.             --i;
  1611.         }
  1612.         if (i == 0)
  1613.     return 0;
  1614.     }
  1615.     if (term == 'N') {
  1616.         while (i != 0) {
  1617.             if (c == '/')
  1618.                 return 1;
  1619.             --i;
  1620.         }
  1621.     } 
  1622.     return 0;
  1623. }
  1624. static long parse_qualifier_value(Octstr **address, long pos)
  1625. {
  1626.     unsigned char c;
  1627.     while ((c = octstr_get_char(*address, pos)) != '=' && pos >= 0) {
  1628.         if (c < 0x20 || (c > 0x2e && c < 0x30) || (c > 0x3c && c < 0x3e) ||
  1629.             c > 0x7e)
  1630.             return -2;
  1631.         pos = drop_character(address, pos);
  1632.     }
  1633.     pos = drop_character(address, pos);
  1634.   
  1635.     return pos;
  1636. }
  1637. static long parse_qualifier_keyword(Octstr **address, long pos)
  1638. {
  1639.     unsigned char c;  
  1640.     while ((c = octstr_get_char(*address, pos)) != '/') {
  1641.         if (isalnum(c) || c == '-') {
  1642.     pos = drop_character(address, pos);
  1643.         } else
  1644.     return -2;
  1645.     }
  1646.     pos = drop_character(address, pos);       
  1647.     return pos;
  1648. }
  1649. static long parse_ipv4_fragment(Octstr **address, long pos)
  1650. {
  1651.     long i;
  1652.     unsigned char c;
  1653.     i = 0;
  1654.     c = '=';
  1655.     if (isdigit(c = octstr_get_char(*address, pos)) && pos >= 0) {
  1656.         --pos;
  1657.         ++i;
  1658.     } else {
  1659.         debug("wap.push.pap.compiler", 0, "non-digit found in ip address,"
  1660.               " address unacceptable");
  1661.         return -2;
  1662.     }
  1663.     
  1664.     while (i <= 3 && ((c = octstr_get_char(*address, pos)) != '.' &&  c != '=')
  1665.             && pos >= 0) {
  1666.         if (isdigit(c)) {
  1667.             --pos;
  1668.             ++i;
  1669.         } else {
  1670.     debug("wap.push.pap.compiler", 0, "parse_ipv4_fragment: non-digit"
  1671.                   " in ipv4 address, address unacceptable");
  1672.     return -2;
  1673.         }
  1674.     }
  1675.     pos = handle_two_terminators(address, pos, '.', '=', c, i, 3);
  1676.     return pos;
  1677. }
  1678. static long parse_ipv6_fragment(Octstr **address, long pos)
  1679. {
  1680.     long i;
  1681.     unsigned char c;
  1682.     i = 0;
  1683.     if (isxdigit(octstr_get_char(*address, pos)) && pos >= 0) {
  1684.         --pos;
  1685.         ++i;
  1686.     } else {
  1687.         return -2;
  1688.     }
  1689.     c = '=';
  1690.     while (i <= 4 && ((c = octstr_get_char(*address, pos)) != ':' && c != '=')
  1691.             && pos >= 0) {
  1692.         if (isxdigit(c)) {
  1693.     --pos;
  1694.             ++i;
  1695.         } else {
  1696.     return -2;
  1697.         }
  1698.     }
  1699.     pos = handle_two_terminators(address, pos, ':', '=', c, i, 4);
  1700.     return pos;
  1701. }
  1702. /*
  1703.  * Return -1, it was impossible to create the window because of there is no
  1704.  * more enough characters left and 0 if OK.
  1705.  */
  1706. static int create_peek_window(Octstr **address, long *pos)
  1707. {
  1708.    long i;
  1709.     unsigned char c;
  1710.     i = 0;
  1711.     c = '=';
  1712.     while (i < 2 && (c = octstr_get_char(*address, *pos)) != '=') {
  1713.         if (*pos > 0)
  1714.             --*pos;
  1715.         ++i;
  1716.     }
  1717.     if (c == '=')
  1718.         return 0;
  1719.     return 1; 
  1720. }
  1721. static long rest_unescaped(Octstr **address, long pos)
  1722. {
  1723.     long i,
  1724.          ret;
  1725.     for (i = 2; i > 0; i--) {
  1726.          if ((ret = accept_safe(address, pos)) == -2)
  1727.      return -2;
  1728.          else if (ret == -1)
  1729.      return pos;
  1730.     }
  1731.     return pos;
  1732. }
  1733. static int issafe(Octstr **address, long pos)
  1734. {
  1735.     if (octstr_get_char(*address, pos) == '%')
  1736.         return 0;
  1737.     else
  1738.         return 1;
  1739. }
  1740. static long accept_safe(Octstr **address, long pos)
  1741. {
  1742.     unsigned char c;
  1743.     c = octstr_get_char(*address, pos);
  1744.     if ((isalnum(c) || c == '+' || c == '-' || c == '.' || c == '_') && 
  1745.             pos >= 0)
  1746. --pos;
  1747.     else if (c == '=')
  1748.         return -1;
  1749.     else
  1750.         return -2;
  1751.     return pos;
  1752. }
  1753. static long accept_escaped(Octstr **address, long pos)
  1754. {
  1755.     Octstr *temp;
  1756.     long i;
  1757.     unsigned char c;
  1758.     pos = drop_character(address, pos);
  1759.     temp = octstr_create("");
  1760.     for (i = 2; i > 0; i--) {
  1761.         c = octstr_get_char(*address, pos + i);
  1762.         temp = prepend_char(temp, c);
  1763.         pos = drop_character(address, pos + i);
  1764.         if (pos > 0)
  1765.   --pos;
  1766.     }
  1767.     if (octstr_hex_to_binary(temp) < 0) {
  1768.         octstr_destroy(temp);
  1769.         return -2;
  1770.     }
  1771.     octstr_insert(*address, temp, pos + 2);   /* To the end of the window */
  1772.     octstr_destroy(temp);
  1773.     return pos + 1;                           /* The position preceding the 
  1774.                                                  inserted character */
  1775.               
  1776. }
  1777. /*
  1778.  * Point ends the string to be parsed, comma separates its fragments.
  1779.  */
  1780. static long handle_two_terminators (Octstr **address, long pos, 
  1781.     unsigned char comma, unsigned char point, unsigned char c, 
  1782.     long fragment_parsed, long fragment_length)
  1783. {
  1784.     if (fragment_parsed == fragment_length && c != comma && c != point)
  1785.         return -2;
  1786.     if (c == point) 
  1787.         octstr_delete(*address, pos, 1);
  1788.     --pos;
  1789.     return pos;
  1790. }