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

wap_push_pap_compiler.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * wap_push_pap_compiler.c - implementation of wap_push_pap_compiler.h inter-
00059  * face (compiling pap documents to Kannel WAPEvents)
00060  *
00061  * This module implements PAP document DTD and status codes, defined in   
00062  *       WAP-164-PAP-19991108-a (called hereafter pap), chapter 9 and
00063  * PPG client addressing (it is. parsing client address of a pap document), 
00064  * defined in
00065  *       WAP-151-PPGService-19990816-a (ppg), chapter 7.
00066  *
00067  * In addition, Wapforum specification WAP-200-WDP-20001212-a (wdp) is re-
00068  * ferred.
00069  *
00070  * Compiler can be used by PI or PPG (it will handle all possible PAP DTD 
00071  * elements). It checks that attribute values are legal and that an element 
00072  * has only legal attributes, but does not otherwise validate PAP documents 
00073  * against PAP DTD. (XML validation is quite another matter, of course.) 
00074  * Client address is parsed out from the relevant PAP message attribute 
00075  * containing lots of additional data, see ppg, 7.1. We do not yet support 
00076  * user defined addresses.
00077  *
00078  * After compiling, some semantic analysing of the resulted event, and sett-
00079  * ing some defaults (however, relying on them is quite a bad policy). In 
00080  * addition changing undefined values (any) to defined ones.
00081  *
00082  * By  Aarno Syvänen for Wapit Ltd and for Wiral Ltd.
00083  */
00084 
00085 #include <libxml/xmlmemory.h>
00086 #include <libxml/parser.h>
00087 #include <libxml/tree.h>
00088 #include <libxml/debugXML.h>
00089 #include <libxml/encoding.h>
00090 #include <ctype.h>
00091 #include <string.h>
00092 
00093 #include "shared.h"
00094 #include "wap_push_pap_compiler.h"
00095 #include "wap_push_ppg.h"
00096 
00097 /****************************************************************************
00098  *
00099  * Global data structures
00100  *
00101  * Table for pap elements. These are defined in PAP, Chapter 9.
00102  */
00103 static char *pap_elements[] = {
00104     "pap",
00105     "push-message",
00106     "address",
00107     "quality-of-service",
00108     "push-response",
00109     "progress-note",
00110     "response-result",
00111     "cancel-message",
00112     "cancel-result",
00113     "cancel-response",
00114     "resultnotification-message",
00115     "resultnotification-response",
00116     "statusquery-message",
00117     "statusquery-response",
00118     "statusquery-result",
00119     "ccq-message",
00120     "ccq-response",
00121     "badmessage-response"
00122 };
00123 
00124 #define NUM_ELEMENTS sizeof(pap_elements)/sizeof(pap_elements[0])
00125 
00126 /*
00127  * Table for PAP attributes. These are defined in pap, Chapter 9.
00128  */
00129 struct pap_attributes_t {
00130     char *name;
00131     char *value;
00132 };
00133 
00134 typedef struct pap_attributes_t pap_attributes_t;
00135 
00136 static pap_attributes_t pap_attributes[] = {
00137     { "product-name", NULL },
00138     { "push-id", NULL },
00139     { "deliver-before-timestamp", NULL },
00140     { "deliver-after-timestamp", NULL },
00141     { "source-reference", NULL },
00142     { "progress-notes-requested", "true" },
00143     { "progress-notes-requested", "false" },
00144     { "ppg-notify-requested-to", NULL },
00145     { "address-value", NULL },
00146     { "priority", "high" },
00147     { "priority", "medium" },
00148     { "priority", "low" },
00149     { "delivery-method", "confirmed" },
00150     { "delivery-method", "preferconfirmed" },
00151     { "delivery-method", "unconfirmed" },
00152     { "delivery-method", "notspecified" },
00153     { "network", NULL },
00154     { "network-required", "true" },
00155     { "network-required", "false" },
00156     { "bearer", NULL },
00157     { "bearer-required", "true" },
00158     { "bearer-required", "false" },
00159     { "sender-address", NULL },
00160     { "sender-name", NULL },
00161     { "reply-time", NULL },
00162     { "stage", NULL },
00163     { "note", NULL },
00164     { "time", NULL },
00165     { "code", NULL },
00166     { "desc", NULL },
00167     { "received-time", NULL },
00168     { "event-time", NULL },
00169     { "message-state", NULL },
00170     { "query-id", NULL },
00171     { "app-id", NULL },
00172     { "bad-message-fragment", NULL}
00173 };
00174 
00175 #define NUM_ATTRIBUTES sizeof(pap_attributes)/sizeof(pap_attributes[0])
00176 
00177 /*
00178  * Status codes are defined in pap, chapter 9.13.
00179  */
00180 static int pap_codes[] = {
00181     PAP_ACCEPTED_FOR_PROCESSING,
00182     PAP_BAD_REQUEST,
00183     PAP_FORBIDDEN,
00184     PAP_ADDRESS_ERROR,
00185     PAP_CAPABILITIES_MISMATCH,
00186     PAP_DUPLICATE_PUSH_ID,
00187     PAP_TRANSFORMATION_FAILURE,
00188     PAP_REQUIRED_BEARER_NOT_AVAILABLE,
00189     PAP_ABORT_USERPND
00190 };
00191 
00192 #define NUM_CODES sizeof(pap_codes)/sizeof(pap_codes[0])
00193 
00194 /*
00195  * Possible bearer types. These are defined in wdp, appendix C.
00196  */
00197 static char *pap_bearer_types[] = {
00198     "Any",
00199     "USSD",
00200     "SMS",
00201     "GUTS/R-Data",
00202     "CSD",
00203     "Packet Data",
00204     "GPRS",
00205     "CDPD",
00206     "FLEX",
00207     "SDS",
00208     "ReFLEX",
00209     "MPAK",
00210     "GHOST/R_DATA"
00211 };
00212 
00213 #define NUM_BEARER_TYPES sizeof(pap_bearer_types)/sizeof(pap_bearer_types[0])
00214 
00215 /*
00216  * Possible network types. These are defined in wdp, appendix C.
00217  */
00218 
00219 static char *pap_network_types[] = {
00220     "Any",
00221     "GSM",
00222     "ANSI-136",
00223     "IS-95 CDMA",
00224     "AMPS",
00225     "PDC",
00226     "IDEN",
00227     "Paging network",
00228     "PHS",
00229     "TETRA",
00230     "Mobitex",
00231 };
00232 
00233 #define NUM_NETWORK_TYPES sizeof(pap_network_types)/ \
00234                           sizeof(pap_network_types[0])
00235 
00236 /****************************************************************************
00237  *
00238  * Prototypes of internal functions. Note that suffix 'Ptr' means '*'.
00239  */
00240 
00241 static int parse_document(xmlDocPtr doc_p, WAPEvent **e);
00242 static int parse_node(xmlNodePtr node, WAPEvent **e, long *type_of_address,
00243                       int *is_any);  
00244 static int parse_element(xmlNodePtr node, WAPEvent **e, 
00245                          long *type_of_address, int *is_any); 
00246 static int parse_attribute(Octstr *element_name, xmlAttrPtr attribute, 
00247                            WAPEvent **e, long *type_of_address, int *is_any);
00248 static int parse_attr_value(Octstr *element_name, Octstr *attr_name, 
00249                             Octstr *attr_value, WAPEvent **e,
00250                             long *type_of_address, int *is_any);
00251 static int set_attribute_value(Octstr *element_name, Octstr *attr_value, 
00252                                Octstr *attr_name, WAPEvent **e);
00253 static int return_flag(Octstr *ros);
00254 static void wap_event_accept_or_create(Octstr *element_name, WAPEvent **e);
00255 static int parse_pap_value(Octstr *attr_name, Octstr *attr_value, WAPEvent **e);
00256 static int parse_push_message_value(Octstr *attr_name, Octstr *attr_value,
00257                                      WAPEvent **e);
00258 static int parse_address_value(Octstr *attr_name, Octstr *attr_value, 
00259                                WAPEvent **e, long *type_of_address);
00260 static int parse_quality_of_service_value(Octstr *attr_name, 
00261                                           Octstr *attr_value, WAPEvent **e,
00262                                           int *is_any);
00263 static int parse_push_response_value(Octstr *attr_name, Octstr *attr_value,
00264                                      WAPEvent **e);
00265 static int parse_progress_note_value(Octstr *attr_name, Octstr *attr_value,
00266                                      WAPEvent **e);
00267 static int parse_bad_message_response_value(Octstr *attr_name, 
00268                                             Octstr *attr_value, WAPEvent **e);
00269 static int parse_response_result_value(Octstr *attr_name, 
00270                                       Octstr *attr_value, WAPEvent **e);
00271 static int parse_code(Octstr *attr_value);
00272 static Octstr *parse_bearer(Octstr *attr_value);
00273 static Octstr *parse_network(Octstr *attr_value);
00274 static int parse_requirement(Octstr *attr_value);
00275 static int parse_priority(Octstr *attr_value);
00276 static int parse_delivery_method(Octstr *attr_value);
00277 static int parse_state(Octstr *attr_value);
00278 static long parse_wappush_client_address(Octstr **address, long pos,
00279                                          long *type_of_address);
00280 static long parse_ppg_specifier(Octstr **address, long pos);
00281 static long parse_client_specifier(Octstr **address, long pos, 
00282                                    long *type_of_address);
00283 static long parse_constant(const char *field_name, Octstr **address, long pos);
00284 static long parse_dom_fragment(Octstr **address, long pos);
00285 static long drop_character(Octstr **address, long pos);
00286 static long parse_type(Octstr **address, Octstr **type_value, long pos);
00287 static long parse_ext_qualifiers(Octstr **address, long pos, 
00288                                  Octstr *type_value);
00289 static long parse_global_phone_number(Octstr **address, long pos);
00290 static long parse_ipv4(Octstr **address, long pos);
00291 static long parse_ipv6(Octstr **address, long pos);
00292 static long parse_escaped_value(Octstr **address, long pos); 
00293 static Octstr *prepend_char(Octstr *address, unsigned char c);
00294 static int qualifiers(Octstr *address, long pos, Octstr *type);
00295 static long parse_qualifier_value(Octstr **address, long pos);
00296 static long parse_qualifier_keyword(Octstr **address, long pos);
00297 static long parse_ipv4_fragment(Octstr **address, long pos);
00298 static long parse_ipv6_fragment(Octstr **address, long pos);
00299 static int wina_bearer_identifier(Octstr *type_value);
00300 static int create_peek_window(Octstr **address, long *pos);
00301 static long rest_unescaped(Octstr **address, long pos);
00302 static int issafe(Octstr **address, long pos);
00303 static long accept_safe(Octstr **address, long pos);
00304 static long accept_escaped(Octstr **address, long pos);
00305 static long handle_two_terminators (Octstr **address, long pos, 
00306     unsigned char comma, unsigned char point, unsigned char c, 
00307     long fragment_parsed, long fragment_length);
00308 static int uses_gsm_msisdn_address(long bearer_required, Octstr *bearer);
00309 static int uses_ipv4_address(long bearer_required, Octstr *bearer);
00310 static int uses_ipv6_address(long bearer_required, Octstr *bearer);
00311 static int event_semantically_valid(WAPEvent *e, long type_of_address);
00312 static char *address_type(long type_of_address);
00313 static void set_defaults(WAPEvent **e, long type_of_address);
00314 static void set_bearer_defaults(WAPEvent **e, long type_of_address);
00315 static void set_network_defaults(WAPEvent **e, long type_of_address);
00316 static int set_anys(WAPEvent **e, long type_of_address, int is_any);
00317 static void set_any_value(int *is_any, Octstr *attr_name, Octstr *attr_value);
00318 
00319 /*
00320  * Macro for creating an octet string from a node content. This has two 
00321  * versions for different libxml node content implementation methods.
00322  */
00323 #ifdef XML_USE_BUFFER_CONTENT
00324 #define create_octstr_from_node(node) (octstr_create(node->content->content))
00325 #else
00326 #define create_octstr_from_node(node) (octstr_create(node->content))
00327 #endif
00328 
00329 /****************************************************************************
00330  *
00331  * Compile PAP control document to a corresponding Kannel event. Checks vali-
00332  * dity of the document. The caller must initialize wap event to NULL. In add-
00333  * ition, it must free memory allocated by this function. 
00334  *
00335  * After compiling, some semantic analysing of the resulted event. 
00336  *
00337  * Note that entities in the DTD are parameter entities and they can appear 
00338  * only in DTD (See site http://www.w3.org/TR/REC-xml, Chapter 4.1). So we do 
00339  * not need to worry about them in the document itself.
00340  *
00341  * Returns 0, when success
00342  *        -1, when a non-implemented pap feature is asked for
00343  *        -2, when error
00344  * In addition, returns a newly created wap event corresponding the pap 
00345  * control message, if success, wap event NULL otherwise. 
00346  */
00347 
00348 
00349 int pap_compile(Octstr *pap_content, WAPEvent **e)
00350 {
00351     xmlDocPtr doc_p;
00352     size_t oslen;
00353     int ret;
00354 
00355     if (octstr_search_char(pap_content, '\0', 0) != -1) {
00356         warning(0, "PAP COMPILER: pap_compile: pap source contained a \\0"
00357                    " character");
00358         return -2;
00359     }
00360 
00361     octstr_strip_blanks(pap_content);
00362     oslen = octstr_len(pap_content);
00363     doc_p = xmlParseMemory(octstr_get_cstr(pap_content), oslen);
00364     if (doc_p == NULL) {
00365         goto error;
00366     }
00367 
00368     if ((ret = parse_document(doc_p, e)) < 0) { 
00369         goto parserror;
00370     }
00371 
00372     xmlFreeDoc(doc_p);
00373     return 0;
00374 
00375 parserror:
00376     xmlFreeDoc(doc_p);
00377     wap_event_destroy(*e);
00378     *e = NULL;
00379     return ret;
00380 
00381 error:
00382     warning(0, "PAP COMPILER: pap_compile: parse error in pap source");
00383     xmlFreeDoc(doc_p);
00384     wap_event_destroy(*e);
00385     *e = NULL;
00386     return -2;
00387 }
00388 
00389 /****************************************************************************
00390  *
00391  * Implementation of internal functions
00392  *
00393  */
00394 
00395 enum {
00396     NEITHER = 0,
00397     BEARER_ANY = 1,
00398     NETWORK_ANY = 2,
00399     EITHER = 3,
00400     ERROR_ANY = 4
00401 };
00402 
00403 /*
00404  * Parse the document node of libxml syntax tree. FIXME: Add parsing of pap
00405  * version.
00406  * After parsing, some semantic analysing of the resulted event. Then set
00407  * a default network and bearer deduced from address type, if the correspond-
00408  * ing pap attribute is missing.
00409  * 
00410  * Returns 0, when success
00411  *        -1, when a non-implemented pap feature is requested
00412  *        -2, when error
00413  * In addition, return a newly created wap event corresponding the pap 
00414  * control message, if success, or partially parsed pap document, if not. Set
00415  * a field containing address type.
00416  */
00417 
00418 static int parse_document(xmlDocPtr doc_p, WAPEvent **e)
00419 {
00420     xmlNodePtr node;
00421     int ret,
00422         is_any;                   /* is bearer and/or network set any in qos
00423                                      attribute */
00424     long type_of_address;
00425 
00426     gw_assert(doc_p);
00427     node = xmlDocGetRootElement(doc_p);
00428     is_any = NEITHER;
00429 
00430     if ((ret = parse_node(node, e, &type_of_address, &is_any)) < 0)
00431         return ret;
00432 
00433     (*e)->u.Push_Message.address_type = type_of_address;
00434 
00435     if ((ret= event_semantically_valid(*e, type_of_address)) == 0) {
00436         warning(0, "wrong type of address for requested bearer");
00437         return -2;
00438     } else if (ret == -1) {
00439         info(0, "reverting to default bearer and network");
00440         set_defaults(e, type_of_address);
00441         return 0;
00442     }
00443 
00444     if (!set_anys(e, type_of_address, is_any)) {
00445         warning(0, "unable to handle any values in qos");
00446         return -2;
00447     } else {
00448         debug("wap.push.pap.compiler", 0, "using defaults instead of anys");
00449     }
00450 
00451     wap_event_assert(*e);
00452 
00453     return 0;
00454 }
00455 
00456 static int set_anys(WAPEvent **e, long type_of_address, int is_any)
00457 {
00458     switch (is_any) {
00459     case NEITHER:
00460     return 1;
00461 
00462     case BEARER_ANY:
00463         set_bearer_defaults(e, type_of_address);
00464     return 1;
00465 
00466     case NETWORK_ANY:
00467         set_network_defaults(e, type_of_address);
00468     return 1;
00469 
00470     case EITHER:
00471         set_defaults(e, type_of_address);
00472     return 1;
00473 
00474     default:
00475     return 0;
00476     }
00477 }
00478 
00479 /*
00480  * We actually use address_type field of a wap event for controlling the bearer
00481  * selection. Bearer and network filed are used for debugging purposes.
00482  */
00483 static void set_defaults(WAPEvent **e, long type_of_address)
00484 {
00485     set_bearer_defaults(e, type_of_address);
00486     set_network_defaults(e, type_of_address);   
00487 }
00488 
00489 static void set_bearer_defaults(WAPEvent **e, long type_of_address)
00490 {
00491     gw_assert(type_of_address == ADDR_USER || type_of_address == ADDR_PLMN ||
00492               type_of_address == ADDR_IPV4 || type_of_address == ADDR_IPV6 ||
00493               type_of_address == ADDR_WINA);
00494 
00495     if ((*e)->type != Push_Message)
00496         return;
00497 
00498     (*e)->u.Push_Message.bearer_required = PAP_TRUE;
00499     octstr_destroy((*e)->u.Push_Message.bearer);
00500 
00501     switch (type_of_address) {
00502     case ADDR_PLMN:
00503     (*e)->u.Push_Message.bearer = octstr_format("%s", "SMS"); 
00504     break;   
00505  
00506     case ADDR_IPV4:
00507     (*e)->u.Push_Message.bearer = octstr_format("%s", "CSD");     
00508     break;
00509 
00510     case ADDR_IPV6:
00511     break;
00512     }
00513 }
00514 
00515 static void set_network_defaults(WAPEvent **e, long type_of_address)
00516 {
00517     gw_assert(type_of_address == ADDR_USER || type_of_address == ADDR_PLMN ||
00518               type_of_address == ADDR_IPV4 || type_of_address == ADDR_IPV6 ||
00519               type_of_address == ADDR_WINA);
00520 
00521     if ((*e)->type != Push_Message)
00522         return;
00523 
00524     (*e)->u.Push_Message.network_required = PAP_TRUE;
00525     octstr_destroy((*e)->u.Push_Message.network);
00526 
00527     switch (type_of_address) {
00528     case ADDR_PLMN:
00529     (*e)->u.Push_Message.network = octstr_format("%s", "GSM");
00530     break;   
00531  
00532     case ADDR_IPV4:
00533         (*e)->u.Push_Message.network = octstr_format("%s", "GSM");   
00534     break;
00535 
00536     case ADDR_IPV6: 
00537     break;
00538     }
00539 }
00540 
00541 static char *address_type(long type_of_address)
00542 {
00543     switch(type_of_address) {
00544     case ADDR_USER:
00545     return "user defined address";
00546     case ADDR_PLMN:
00547     return "a phone number";
00548     case ADDR_IPV4:
00549     return "a IPv4 address";
00550     case ADDR_IPV6:
00551     return "a IPv6 address";
00552     case ADDR_WINA:
00553     return "a WINA accepted address";
00554     default:
00555     return "unknown address";
00556     }
00557 }
00558 
00559 /*
00560  * Do semantic analysis, when the event was Push_Message. Do not accept an IP 
00561  * address, when a non-IP bearer is requested, and a phone number, when an IP
00562  * bearer is requested.
00563  * Return 0, when event is unacceptable
00564  *        1, when it is acceptable
00565  *       -1, when there are no bearer or network specified
00566  */
00567 
00568 static int event_semantically_valid(WAPEvent *e, long type_of_address)
00569 {
00570     int ret;
00571 
00572     debug("wap.push.pap.compiler", 0, "PAP COMPILER: doing semantic analysis"
00573           " for address type %s", address_type(type_of_address));
00574     if (e->type != Push_Message) {
00575         return 1;
00576     }
00577     
00578     if (e->u.Push_Message.network_required != 
00579          e->u.Push_Message.bearer_required) {
00580        debug("wap.push.pap.compiler", 0, "PAP COMPILER: network-required and"
00581              " bearer-required must have same value");
00582        return 0;
00583     }
00584 
00585     if (type_of_address == ADDR_PLMN) {
00586             if ((ret = uses_gsm_msisdn_address(
00587                      e->u.Push_Message.bearer_required,
00588                      e->u.Push_Message.bearer)) == 0) {
00589                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: bearer does"
00590                       " not accept PLMN address");
00591                 return 0;
00592             } else if (ret == -1) {
00593             debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
00594                       "bearer missing, reverting to GSM+SMS");
00595                 return -1;
00596             } else
00597             return 1;
00598                 
00599     }
00600     
00601     if (type_of_address == ADDR_IPV4) { 
00602             if ((ret = uses_ipv4_address(e->u.Push_Message.bearer_required,
00603                     e->u.Push_Message.bearer)) == 0) {
00604                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: bearer does"
00605                       " not accept IPv4 address");
00606                 return 0;
00607             } else if (ret == -1) {
00608                 debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
00609                       " bearer missing, reverting to GSM+CSD");
00610             return -1;
00611             } else
00612             return 1;
00613     }
00614     
00615     if (type_of_address == ADDR_IPV6) { 
00616         if ((ret = uses_ipv6_address(e->u.Push_Message.bearer_required,
00617                  e->u.Push_Message.bearer)) == 0) {
00618              debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
00619                    " bearer does not accept IPv6 address");
00620              return 0;
00621         } else if (ret == -1) {
00622              debug("wap.push.pap.compiler", 0, "PAP COMPILER: network or"
00623                    " bearer missing, reverting Any+Any");
00624          return -1;
00625         } else
00626          return 1;
00627     }
00628     
00629     return 0;
00630 }
00631 
00632 /*
00633  * Bearers accepting IP addresses. These are defined in wdp, appendix c. Note
00634  * that when ipv6 bearers begin to appear, they must be added to the following
00635  * table. Currently none are specified.
00636  */
00637 static char *ip6_bearers[] = {
00638     "Any"
00639 };
00640 
00641 #define NUMBER_OF_IP6_BEARERS sizeof(ip6_bearers)/sizeof(ip6_bearers[0])
00642 
00643 static char *ip4_bearers[] = {
00644     "Any",
00645     "CSD",
00646     "Packet Data",
00647     "GPRS",
00648     "USSD"
00649 };
00650 
00651 #define NUMBER_OF_IP4_BEARERS sizeof(ip4_bearers)/sizeof(ip4_bearers[0])
00652 
00653 /*
00654  * Bearers accepting gsm msisdn addresses are defined in wdp, appendix c. We
00655  * add any, because Kannel PPG will change this to SMS.
00656  * Return -1, when there are no bearer defined
00657  *        0, when a bearer not accepting msisdn address is found
00658  *        1, when a bearer is accepting msisdn addresesses 
00659  */
00660 static int uses_gsm_msisdn_address(long bearer_required, Octstr *bearer)
00661 {
00662     if (!bearer_required)
00663         return -1;
00664     
00665     if (!bearer)
00666         return 1;
00667     
00668     return (octstr_case_compare(bearer, octstr_imm("SMS")) == 0 ||
00669             octstr_case_compare(bearer, octstr_imm("GHOST/R_DATA")) == 0 ||
00670             octstr_case_compare(bearer, octstr_imm("Any")) == 0);
00671 }
00672 
00673 /*
00674  * Bearers accepting ipv4 addresses are defined in wdp, appendix c.
00675  * Return -1, when there are no bearer defined
00676  *        0, when a bearer not accepting ipv4  address is found
00677  *        1, when a bearer is accepting ipv4 addresesses 
00678  */
00679 static int uses_ipv4_address(long bearer_required, Octstr *bearer)
00680 {
00681     long i;
00682 
00683     if (!bearer_required) {
00684         return -1;
00685     }
00686 
00687     if (!bearer)
00688         return -1;
00689     
00690     i = 0;
00691     while (i < NUMBER_OF_IP4_BEARERS) {
00692         if (octstr_case_compare(bearer, octstr_imm(ip4_bearers[i])) == 0) {
00693         return 1;
00694         }
00695         ++i;
00696     }
00697 
00698     return 0;
00699 }
00700 
00701 /*
00702  * Bearers accepting ipv6 addresses (currently *not* accepting) are defined in
00703  * wdp, appendix c.
00704  * Return -1, when there are no bearer defined
00705  *        0, when a bearer not accepting ipv6 address is found
00706  *        1, when a bearer is accepting ipv6 addresesses 
00707  */
00708 static int uses_ipv6_address(long bearer_required, Octstr *bearer)
00709 {
00710     long i;
00711 
00712     if (!bearer_required)
00713         return -1;
00714 
00715     if (!bearer)
00716         return -1;
00717 
00718     i = 0;
00719     while (i < NUMBER_OF_IP6_BEARERS) {
00720         if (octstr_case_compare(bearer, octstr_imm(ip6_bearers[i])) == 0) {
00721         return 1;
00722         }
00723         ++i;
00724     }
00725 
00726     return 0;
00727 }
00728 
00729 
00730 /*
00731  * Parse node of the syntax tree. DTD, as defined in pap, chapter 9, contains
00732  * only elements (entities are restricted to DTDs). 
00733  * The caller must initialize the value of is_any to 0.
00734  *
00735  * Output: a) a newly created wap event containing attributes from pap 
00736  *         document node, if success; partially parsed node, if not. 
00737  *         b) the type of of the client address 
00738  *         c) is bearer and/or network any
00739  * Returns 0, when success
00740  *        -1, when a non-implemented feature is requested
00741  *        -2, when error
00742  */
00743 static int parse_node(xmlNodePtr node, WAPEvent **e, long *type_of_address,
00744                       int *is_any)
00745 {
00746     int ret;
00747 
00748     switch (node->type) {
00749     case XML_COMMENT_NODE:        /* ignore text, comments and pi nodes */
00750     case XML_PI_NODE:
00751     case XML_TEXT_NODE:
00752     break;
00753 
00754     case XML_ELEMENT_NODE:
00755         if ((ret = parse_element(node, e, type_of_address, is_any)) < 0) {
00756         return ret;
00757         }
00758     break;
00759 
00760     default:
00761         warning(0, "PAP COMPILER: parse_node: Unknown XML node in PAP source");
00762         return -2;
00763     }
00764 
00765     if (node->children != NULL)
00766         if ((ret = parse_node(node->children, e, type_of_address, 
00767                 is_any)) < 0) {
00768             return ret;
00769     }
00770 
00771     if (node->next != NULL)
00772         if ((ret = parse_node(node->next, e, type_of_address, is_any)) < 0) {
00773             return ret;
00774         }
00775     
00776     return 0;
00777 }
00778 
00779 /*
00780  * Parse elements of a PAP source. 
00781  *
00782  * Output: a) a newly created wap event containing attributes from the
00783  *         element, if success; containing some unparsed attributes, if not.
00784  *         b) the type of the client address
00785  *         c) is bearer and/or network any
00786  * Returns 0, when success
00787  *        -1, when a non-implemented feature is requested
00788  *        -2, when error
00789  * In addition, return 
00790  */
00791 static int parse_element(xmlNodePtr node, WAPEvent **e, long *type_of_address,
00792                          int *is_any)
00793 {
00794     Octstr *name;
00795     xmlAttrPtr attribute;
00796     size_t i;
00797     int ret;
00798 
00799     name = octstr_create((char *)node->name);
00800     if (octstr_len(name) == 0) {
00801         octstr_destroy(name);
00802         debug("wap.push.pap.compiler", 0, "PAP COMPILER: element name length"
00803               " zero");
00804         return -2;
00805     }
00806     
00807     i = 0;
00808     while (i < NUM_ELEMENTS) {
00809         if (octstr_compare(name, octstr_imm(pap_elements[i])) == 0)
00810             break;
00811         ++i;
00812     }
00813 
00814     if (i == NUM_ELEMENTS) {
00815         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element:");
00816         octstr_dump(name, 0);
00817         octstr_destroy(name);
00818         return -2;
00819     }
00820 
00821     if (node->properties != NULL) {
00822         attribute = node->properties;
00823         while (attribute != NULL) {
00824         if ((ret = parse_attribute(name, attribute, e,
00825                     type_of_address, is_any)) < 0) {
00826             octstr_destroy(name);
00827                 return ret;
00828             }
00829             attribute = attribute->next;
00830         }
00831     }
00832 
00833     octstr_destroy(name);
00834 
00835     return 0;                     /* If we reach this point, our node does not
00836                                      have any attributes left (or it had no 
00837                                      attributes to start with). This is *not* 
00838                                      an error. */
00839 }
00840 
00841 /*
00842  * Parse attribute updates corresponding fields of the  wap event. Check that 
00843  * both attribute name and value are papwise legal. If value is enumerated, 
00844  * legal values are stored in the attributes table. Otherwise, call a separate
00845  * parsing function. If an attribute value is empty, use value "erroneous".
00846  * 
00847  * Output: a) a newly created wap event containing parsed attribute from pap 
00848  *         source, if successfull, an uncomplete wap event otherwise.
00849  *         b) the type of the client address 
00850  *         c) is bearer and/or network set any
00851  * Returns 0, when success
00852  *        -1, when a non-implemented feature is requested
00853  *        -2, when error
00854  */
00855 static int parse_attribute(Octstr *element_name, xmlAttrPtr attribute, 
00856                            WAPEvent **e, long *type_of_address, int *is_any)
00857 {
00858     Octstr *attr_name, *value, *nameos;
00859     size_t i;
00860     int ret;
00861 
00862     nameos = octstr_imm("erroneous");
00863     attr_name = octstr_create((char *)attribute->name);
00864 
00865     if (attribute->children != NULL)
00866         value = create_octstr_from_node((char *)attribute->children);
00867     else
00868         value = octstr_imm("erroneous");
00869 
00870     i = 0;
00871     while (i < NUM_ATTRIBUTES) {
00872         if (octstr_compare(attr_name, nameos = 
00873                            octstr_imm(pap_attributes[i].name)) == 0)
00874         break;
00875         ++i;
00876     }
00877 
00878     if (i == NUM_ATTRIBUTES) {
00879         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown attribute `%s' "
00880               "within XML entity `%s'", octstr_get_cstr(attr_name), 
00881               octstr_get_cstr(element_name));
00882         goto error;
00883     }
00884 
00885 /*
00886  * Parse an attribute (it is, check cdata is has for a value) that is *not* an
00887  * enumeration. Legal values are defined in pap, chapter 9. 
00888  */
00889     if (pap_attributes[i].value == NULL) {
00890         ret = parse_attr_value(element_name, attr_name, value, e, 
00891                                type_of_address, is_any);
00892 
00893     if (ret == -2) {
00894         goto error;
00895         } else {
00896         goto parsed;
00897         }
00898     }
00899 
00900     while (octstr_compare(attr_name, 
00901             nameos = octstr_imm(pap_attributes[i].name)) == 0) {
00902         if (octstr_compare(value, octstr_imm(pap_attributes[i].value)) == 0)
00903         break;
00904         ++i;
00905     }
00906 
00907     if (octstr_compare(attr_name, nameos) != 0) {
00908         debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown attribute "
00909               "value `%s' for attribute `%s' within XML entity `%s'", 
00910               octstr_get_cstr(value), octstr_get_cstr(attr_name), 
00911               octstr_get_cstr(element_name));
00912         goto error;
00913     }
00914 
00915 /*
00916  * Check that the value of the attribute is one enumerated for this attribute
00917  * in pap, chapter 9.
00918  */
00919     if (set_attribute_value(element_name, value, attr_name, e) == -1) 
00920         goto error;
00921 
00922     octstr_destroy(attr_name);
00923     octstr_destroy(value);
00924 
00925     return 0;
00926 
00927 error:
00928     octstr_destroy(attr_name);
00929     octstr_destroy(value);
00930     return -2;
00931 
00932 parsed:
00933     octstr_destroy(attr_name);
00934     octstr_destroy(value);
00935     return ret;
00936 }
00937 
00938 /* 
00939  * Attribute value parsing functions for the PAP element.
00940  * Defined in PAP, chapter 8.1.  
00941  */
00942 static int parse_pap_value(Octstr *attr_name, Octstr *attr_value, WAPEvent **e)
00943 {
00944     Octstr *ros;
00945 
00946     if (*e != NULL)
00947         wap_event_dump(*e);
00948 
00949     ros = octstr_imm("erroneous");
00950     if (octstr_compare(attr_name, octstr_imm("product-name")) == 0) {
00951         /* 
00952          * XXX This is a kludge. 
00953          * We can't add the product-name value to the WAPEvent, because
00954          * the wap_event_create() is created in the deeper layer, which
00955          * means as soon as we see <push-message> or <reponse-message>.
00956          * But we would have to decide which WAPEvent to create while 
00957          * being on the higher <pap> level. 
00958          * How's this to be solved?! -- Stipe
00959          */
00960         return 0;
00961     } 
00962 
00963     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown pap"
00964           " element attribute `%s'", octstr_get_cstr(attr_name));
00965     return -2;
00966 }  
00967 
00968 /* 
00969  * Value parsing functions return the newly created wap event containing 
00970  * attribute value from pap source, if successfull; NULL otherwise . Value 
00971  * types of attributes are defined in pap, chapter 9.  
00972  */
00973 
00974 static int parse_push_message_value(Octstr *attr_name, Octstr *attr_value, 
00975                                     WAPEvent **e)
00976 {
00977     Octstr *ros;
00978 
00979     ros = octstr_imm("erroneous");
00980     if (octstr_compare(attr_name, octstr_imm("push-id")) == 0) {
00981         octstr_destroy((**e).u.Push_Message.pi_push_id);
00982     (**e).u.Push_Message.pi_push_id = octstr_duplicate(attr_value);
00983         return 0;
00984     } else if (octstr_compare(attr_name, 
00985              octstr_imm("deliver-before-timestamp")) == 0) {
00986     (**e).u.Push_Message.deliver_before_timestamp = 
00987              (ros = parse_date(attr_value)) ? 
00988              octstr_duplicate(attr_value) : octstr_imm("erroneous");  
00989         return return_flag(ros);
00990     } else if (octstr_compare(attr_name, 
00991              octstr_imm("deliver-after-timestamp")) == 0) {
00992     (**e).u.Push_Message.deliver_after_timestamp = 
00993              (ros = parse_date(attr_value)) ? 
00994              octstr_duplicate(attr_value) : octstr_imm("erroneous");
00995         return return_flag(ros);
00996     } else if (octstr_compare(attr_name, 
00997              octstr_imm("source-reference")) == 0) {
00998     (**e).u.Push_Message.source_reference = octstr_duplicate(attr_value);
00999         return 0;
01000     } else if (octstr_compare(attr_name, 
01001              octstr_imm("ppg-notify-requested-to")) == 0) {
01002     (**e).u.Push_Message.ppg_notify_requested_to = 
01003              octstr_duplicate(attr_value);
01004         return 0;
01005     }
01006 
01007     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown push message"
01008           " element attribute");
01009     return -2;
01010 }  
01011 
01012 /*
01013  * When there is no legal address to be stored in field (either parsing was
01014  * unsuccessful or an unimplemented address format was requested by the push
01015  * initiator) we use value "erroneous". This is necessary, because this a 
01016  * mandatory field.
01017  *
01018  * Output a) a newly created wap event
01019  *        b) the type of the client address
01020  */
01021 static int parse_address_value(Octstr *attr_name, Octstr *attr_value, 
01022                                WAPEvent **e, long *type_of_address)
01023 {
01024     int ret;
01025 
01026     ret = -2;
01027     if (octstr_compare(attr_name, octstr_imm("address-value")) == 0) {
01028         octstr_destroy((**e).u.Push_Message.address_value);
01029     (**e).u.Push_Message.address_value = 
01030              (ret = parse_address(&attr_value, type_of_address)) > -1 ? 
01031              octstr_duplicate(attr_value) : octstr_imm("erroneous");
01032         return ret;
01033     } 
01034 
01035     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown address element"
01036           " attribute");
01037     return -2;
01038 }
01039 
01040 static int parse_quality_of_service_value(Octstr *attr_name, 
01041                                           Octstr *attr_value, WAPEvent **e,
01042                                           int *is_any)
01043 {
01044     Octstr *ros;
01045 
01046     ros = octstr_imm("erroneous");
01047     if (octstr_compare(attr_name, octstr_imm("network")) == 0) {
01048     (**e).u.Push_Message.network = (ros = parse_network(attr_value)) ? 
01049             octstr_duplicate(attr_value) : octstr_imm("erroneous");
01050         set_any_value(is_any, attr_name, attr_value);
01051         return return_flag(ros);
01052     }
01053 
01054     if (octstr_compare(attr_name, octstr_imm("bearer")) == 0) {
01055     (**e).u.Push_Message.bearer = (ros = parse_bearer(attr_value)) ? 
01056             octstr_duplicate(attr_value) : octstr_imm("erroneous");
01057         set_any_value(is_any, attr_name, attr_value);
01058         return return_flag(ros);
01059     }
01060 
01061     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown quality of"
01062           " service attribute");
01063     return -2;
01064 }
01065 
01066 static void set_any_value(int *is_any, Octstr *attr_name, Octstr *attr_value)
01067 {
01068     switch (*is_any) {
01069     case NEITHER:
01070         if (octstr_compare(attr_name, octstr_imm("bearer")) == 0 &&
01071                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
01072         *is_any = BEARER_ANY;
01073         else if (octstr_compare(attr_name, octstr_imm("network")) == 0 &&
01074                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
01075         *is_any = NETWORK_ANY;
01076     return;
01077 
01078     case BEARER_ANY:
01079         if (octstr_compare(attr_name, octstr_imm("network")) == 0 &&
01080                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
01081         *is_any = EITHER;
01082     return;
01083 
01084     case NETWORK_ANY:
01085         if (octstr_compare(attr_name, octstr_imm("bearer")) == 0 &&
01086                 octstr_case_compare(attr_value, octstr_imm("any")) == 0)
01087         *is_any = EITHER;
01088     return;
01089 
01090     case EITHER:
01091          debug("wap.push.pap.compiler", 0, "PAP COMPILER: problems with"
01092                " setting any");
01093          *is_any = ERROR_ANY;
01094     return;
01095 
01096     default:
01097         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong any value");
01098         *is_any = ERROR_ANY;
01099     return;
01100     }
01101 }
01102 
01103 static int parse_push_response_value(Octstr *attr_name, Octstr *attr_value,
01104                                      WAPEvent **e)
01105 {
01106     Octstr *ros;
01107     int ret;
01108 
01109     ret = -2;
01110     ros = octstr_imm("erroneous");
01111 
01112     if (octstr_compare(attr_name, octstr_imm("push-id")) == 0) {
01113         octstr_destroy((**e).u.Push_Response.pi_push_id);
01114     (**e).u.Push_Response.pi_push_id = octstr_duplicate(attr_value);
01115         return 0;
01116     } else if (octstr_compare(attr_name, octstr_imm("sender-address")) == 0) {
01117     (**e).u.Push_Response.sender_address = octstr_duplicate(attr_value);
01118         return 0;
01119     } else if (octstr_compare(attr_name, octstr_imm("reply-time")) == 0) {
01120     (**e).u.Push_Response.reply_time = (ros = parse_date(attr_value)) ?
01121              octstr_duplicate(attr_value) : NULL;
01122         return return_flag(ros);
01123     } else if (octstr_compare(attr_name, octstr_imm("sender-name")) == 0) {
01124     (**e).u.Push_Response.sender_name = octstr_duplicate(attr_value);
01125         return 0;
01126     }
01127 
01128     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown push response"
01129           " element attribute");
01130     return -2;
01131 }
01132 
01133 static int parse_progress_note_value(Octstr *attr_name, Octstr *attr_value,
01134                                      WAPEvent **e)
01135 {
01136     Octstr *ros;
01137     int ret;
01138 
01139     ret = -2;
01140     ros = octstr_imm("erroneous");
01141 
01142     if (octstr_compare(attr_name, octstr_imm("stage")) == 0) {
01143         (**e).u.Progress_Note.stage = 
01144              (ret = parse_state(attr_value)) ? ret : 0;
01145         return ret;
01146     } else if (octstr_compare(attr_name, octstr_imm("note")) == 0) {
01147     (**e).u.Progress_Note.note = octstr_duplicate(attr_value);
01148         return 0;
01149     } else if (octstr_compare(attr_name, octstr_imm("time")) == 0) {
01150     (**e).u.Progress_Note.time = (ros = parse_date(attr_value)) ?
01151              octstr_duplicate(attr_value) : octstr_imm("erroneous");
01152     return return_flag(ros);
01153     }
01154 
01155     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown progress note"
01156           " element attribute");
01157     return -2;
01158 }
01159 
01160 static int parse_bad_message_response_value(Octstr *attr_name, 
01161                                             Octstr *attr_value, WAPEvent **e)
01162 {
01163     if (octstr_compare(attr_name, octstr_imm("code")) == 0) {
01164     (**e).u.Bad_Message_Response.code = parse_code(attr_value);
01165         return 0;
01166     } else if (octstr_compare(attr_name, octstr_imm("desc")) == 0) {
01167     (**e).u.Bad_Message_Response.desc = octstr_duplicate(attr_value);
01168         return 0;
01169     } else if (octstr_compare(attr_name, 
01170         octstr_imm("bad-message-fragment")) == 0) {
01171         (**e).u.Bad_Message_Response.bad_message_fragment = 
01172             octstr_duplicate(attr_value);
01173         return 0;
01174     }
01175 
01176     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown bad message"
01177           " response element attribute");
01178     return -2;
01179 }
01180 
01181 static int parse_response_result_value(Octstr *attr_name, 
01182                                       Octstr *attr_value, WAPEvent **e)
01183 {
01184     if (octstr_compare(attr_name, octstr_imm("code")) == 0) {
01185     (**e).u.Push_Response.code = parse_code(attr_value);
01186         return 0;
01187     } else if (octstr_compare(attr_name, octstr_imm("desc")) == 0) {
01188     (**e).u.Push_Response.desc = octstr_duplicate(attr_value);
01189         return 0;
01190     }
01191 
01192     debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown response result"
01193           " attribute");
01194     return -2;
01195 } 
01196 
01197 /*
01198  * Do not create multiple events. If *e points to NULL, we have not yet creat-
01199  * ed a wap event. Create a wap event mandatory fields set to error values 
01200  * (these will be latter overwritten). This hack will disappear when we have
01201  * PAP validation.
01202  */
01203 
01204 static void wap_event_accept_or_create(Octstr *element_name, WAPEvent **e)
01205 {
01206     if (octstr_compare(element_name, octstr_imm("push-message")) == 0 
01207             && *e == NULL) {         
01208         *e = wap_event_create(Push_Message); 
01209         (**e).u.Push_Message.pi_push_id = octstr_format("%s", "erroneous");
01210         (**e).u.Push_Message.address_value = octstr_format("%s", "erroneous");
01211     } else if (octstr_compare(element_name, octstr_imm("push-response")) == 0 
01212             && *e == NULL) {
01213         *e = wap_event_create(Push_Response);
01214         (**e).u.Push_Response.pi_push_id = octstr_format("%s", "erroneous");
01215     } else if (octstr_compare(element_name, octstr_imm("progress-note")) == 0 
01216             && *e == NULL) {
01217         *e = wap_event_create(Progress_Note);
01218     } else if (octstr_compare(element_name, 
01219             octstr_imm("badmessage-response")) == 0 && *e == NULL) {
01220         *e = wap_event_create(Bad_Message_Response);
01221     } 
01222 }
01223 
01224 static int return_flag(Octstr *ros)
01225 {
01226     if (ros) {
01227         return 0;
01228     } else {
01229         return -2;
01230     }
01231 }
01232 
01233 /*
01234  * Validates non-enumeration attributes and stores their value to a newly
01235  * created wap event e. (Even when attribute value parsing was not success-
01236  * full.) We do not accept NULL or empty attributes (if this kind of an 
01237  * attribute is optional, we just drop it from the tokenised document).
01238  *
01239  * Output: a) a wap event, as created by subroutines
01240  *         b) the type of the client address
01241  *         c) is bearer or network set any
01242  * Returns 0, when success,
01243  *        -1, when a non-implemented feature requested.
01244  *        -2, when an error
01245  */
01246 static int parse_attr_value(Octstr *element_name, Octstr *attr_name, 
01247                             Octstr *attr_value, WAPEvent **e, 
01248                             long *type_of_address, int *is_any)
01249 {
01250     if (octstr_compare(attr_value, octstr_imm("erroneous")) == 0) {
01251         debug("wap.push.pap.compiler", 0, "unknown value for an attribute");
01252         return -2;
01253     }
01254 
01255     wap_event_accept_or_create(element_name, e);
01256 
01257     if (octstr_compare(element_name, octstr_imm("pap")) == 0) {
01258         return parse_pap_value(attr_name, attr_value, e);
01259     } else if (octstr_compare(element_name, octstr_imm("push-message")) == 0) {
01260         return parse_push_message_value(attr_name, attr_value, e);
01261     } else if (octstr_compare(element_name, octstr_imm("address")) == 0) {
01262         return parse_address_value(attr_name, attr_value, e, type_of_address);
01263     } else if (octstr_compare(element_name, 
01264                    octstr_imm("quality-of-service")) == 0) {
01265         return parse_quality_of_service_value(attr_name, attr_value, e, 
01266                                               is_any);
01267     } else if (octstr_compare(element_name, 
01268                               octstr_imm("push-response")) == 0) {
01269         return parse_push_response_value(attr_name, attr_value, e);
01270     } else if (octstr_compare(element_name, 
01271                    octstr_imm("progress-note")) == 0) {
01272         return parse_progress_note_value(attr_name, attr_value, e);
01273     } else if (octstr_compare(element_name, 
01274                    octstr_imm("badmessage-response")) == 0) {
01275         return parse_bad_message_response_value(attr_name, attr_value, e);
01276     } else if (octstr_compare(element_name, 
01277                    octstr_imm("response-result")) == 0) {
01278         return parse_response_result_value(attr_name, attr_value, e);
01279     }
01280 
01281     return -2; 
01282 }
01283 
01284 /*
01285  * Stores values of enumeration fields of a pap control message to wap event e.
01286  */
01287 static int set_attribute_value(Octstr *element_name, Octstr *attr_value, 
01288                                Octstr *attr_name, WAPEvent **e)
01289 {
01290     int ret;
01291 
01292     ret = -2;
01293     if (octstr_compare(element_name, octstr_imm("push-message")) == 0) {
01294         if (octstr_compare(attr_name, 
01295                           octstr_imm("progress-notes-requested")) == 0)
01296             (**e).u.Push_Message.progress_notes_requested = 
01297                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
01298 
01299     } else if (octstr_compare(element_name, 
01300                  octstr_imm("quality-of-service")) == 0) {
01301         if (octstr_compare(attr_name, octstr_imm("priority")) == 0)
01302             (**e).u.Push_Message.priority = 
01303                  (ret = parse_priority(attr_value)) >= 0 ? ret : 0;
01304         else if (octstr_compare(attr_name, octstr_imm("delivery-method")) == 0)
01305             (**e).u.Push_Message.delivery_method = 
01306                  (ret = parse_delivery_method(attr_value)) >= 0 ? ret : 0;
01307         else if (octstr_compare(attr_name, 
01308                                octstr_imm("network-required")) == 0)
01309             (**e).u.Push_Message.network_required = 
01310                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
01311         else if (octstr_compare(attr_name, octstr_imm("bearer-required")) == 0)
01312             (**e).u.Push_Message.bearer_required = 
01313                  (ret = parse_requirement(attr_value)) >= 0 ? ret : 0;
01314     }
01315 
01316     return ret;
01317 }
01318 
01319 /*
01320  * We must recognize status class and treat unrecognized codes as a x000 code,
01321  * as required by pap, 9.13, p 27.
01322  */
01323 static int parse_code(Octstr *attr_value)
01324 {
01325     long attr_as_number,
01326          len;
01327     size_t i;
01328     Octstr *ros;
01329 
01330     for (i = 0; i < NUM_CODES; i++) {
01331          ros = octstr_format("%d", pap_codes[i]);
01332          if (octstr_compare(attr_value, ros) == 0) {
01333          octstr_destroy(ros);
01334          return pap_codes[i];
01335          }
01336          octstr_destroy(ros);
01337     }
01338 
01339     warning(0, "PAP COMPILER: parse_code: no such return code, reversing to"
01340                " x000 code");
01341     len = octstr_parse_long(&attr_as_number, attr_value, 0, 10);
01342     if (attr_as_number >= PAP_OK && attr_as_number < PAP_BAD_REQUEST) {
01343         attr_as_number = PAP_OK;
01344     } else if (attr_as_number >= PAP_BAD_REQUEST && 
01345             attr_as_number < PAP_INTERNAL_SERVER_ERROR) {
01346         attr_as_number = PAP_BAD_REQUEST;
01347     } else if (attr_as_number >= PAP_INTERNAL_SERVER_ERROR &&
01348         attr_as_number < PAP_SERVICE_FAILURE) {
01349         attr_as_number = PAP_INTERNAL_SERVER_ERROR;
01350     } else if (attr_as_number >= PAP_SERVICE_FAILURE &&
01351         attr_as_number < PAP_CLIENT_ABORTED) {
01352         attr_as_number = PAP_SERVICE_FAILURE;
01353     } else {
01354         attr_as_number = PAP_CLIENT_ABORTED;
01355     }
01356     
01357     return attr_as_number;
01358 }
01359 
01360 static Octstr *parse_bearer(Octstr *attr_value)
01361 {
01362     size_t i;
01363     Octstr *ros;
01364 
01365     for (i = 0; i < NUM_BEARER_TYPES; i++) {
01366          if (octstr_case_compare(attr_value, 
01367                  ros = octstr_imm(pap_bearer_types[i])) == 0)
01368          return ros;
01369     }
01370 
01371     warning(0, "no such bearer");
01372     return NULL;
01373 }
01374 
01375 static Octstr *parse_network(Octstr *attr_value)
01376 {
01377     size_t i;
01378     Octstr *ros;
01379 
01380     for (i = 0; i < NUM_NETWORK_TYPES; i++) {
01381          if (octstr_case_compare(attr_value, 
01382              ros = octstr_imm(pap_network_types[i])) == 0) {
01383          return ros;
01384          }
01385     }
01386 
01387     warning(0, "no such network");
01388     return NULL;
01389 }
01390 
01391 /*
01392  * Used for attributes accepting logical values.
01393  */
01394 static int parse_requirement(Octstr *attr_value)
01395 {
01396     long attr_as_number;
01397 
01398     attr_as_number = -2;
01399     if (octstr_case_compare(attr_value, octstr_imm("false")) == 0)
01400         attr_as_number = PAP_FALSE;
01401     else if (octstr_case_compare(attr_value, octstr_imm("true")) == 0)
01402         attr_as_number = PAP_TRUE;
01403     else
01404         warning(0, "in a requirement, value not a truth value");
01405 
01406     return attr_as_number;
01407 }
01408 
01409 /*
01410  * Priority is defined in pap, chapter 9.2.2.
01411  */
01412 static int parse_priority(Octstr *attr_value)
01413 {
01414     long attr_as_number;
01415 
01416     attr_as_number = -2;
01417     if (octstr_case_compare(attr_value, octstr_imm("high")) == 0)
01418         attr_as_number = PAP_HIGH;
01419     else if (octstr_case_compare(attr_value, octstr_imm("medium")) == 0)
01420         attr_as_number = PAP_MEDIUM;
01421     else if (octstr_case_compare(attr_value, octstr_imm("low")) == 0)
01422         attr_as_number = PAP_LOW;
01423     else
01424         warning(0, "illegal priority");
01425 
01426     return attr_as_number;
01427 }
01428 
01429 /*
01430  * Delivery-method is defined in pap, chapter 9.2.2.
01431  */
01432 static int parse_delivery_method(Octstr *attr_value)
01433 {
01434     long attr_as_number;
01435 
01436     attr_as_number = -2;
01437     if (octstr_case_compare(attr_value, octstr_imm("confirmed")) == 0)
01438         attr_as_number = PAP_CONFIRMED;
01439     else if (octstr_case_compare(attr_value, 
01440             octstr_imm("preferconfirmed")) == 0)
01441         attr_as_number = PAP_PREFERCONFIRMED;
01442     else if (octstr_case_compare(attr_value, octstr_imm("unconfirmed")) == 0)
01443         attr_as_number = PAP_UNCONFIRMED;
01444     else if (octstr_case_compare(attr_value, octstr_imm("notspecified")) == 0)
01445     attr_as_number = PAP_NOT_SPECIFIED;
01446     else
01447         warning(0, "illegal delivery method");
01448     
01449     return attr_as_number;
01450 }
01451 
01452 /*
01453  * PAP states are defined in ppg, chapter 6.
01454  */
01455 static int parse_state(Octstr *attr_value)
01456 {
01457     long attr_as_number;
01458 
01459     attr_as_number = -2;
01460     if (octstr_case_compare(attr_value, octstr_imm("undeliverable")) == 0)
01461         attr_as_number = PAP_UNDELIVERABLE; 
01462     else if (octstr_case_compare(attr_value, octstr_imm("pending")) == 0)
01463         attr_as_number = PAP_PENDING; 
01464     else if (octstr_case_compare(attr_value, octstr_imm("expired")) == 0)
01465         attr_as_number = PAP_EXPIRED;
01466     else if (octstr_case_compare(attr_value, octstr_imm("delivered")) == 0)
01467         attr_as_number = PAP_DELIVERED;
01468     else if (octstr_case_compare(attr_value, octstr_imm("aborted")) == 0)
01469         attr_as_number = PAP_ABORTED;
01470     else if (octstr_case_compare(attr_value, octstr_imm("timeout")) == 0)
01471         attr_as_number = PAP_TIMEOUT;
01472     else if (octstr_case_compare(attr_value, octstr_imm("cancelled")) == 0)
01473         attr_as_number = PAP_CANCELLED;
01474     else 
01475          warning(0, "illegal ppg state");
01476 
01477     return attr_as_number;
01478 }
01479 
01480 /*
01481  * Check legality of pap client address attribute and transform it to the 
01482  * client address usable in Kannel wap address tuple data type. The grammar 
01483  * for client address is specified in ppg, chapter 7.1.
01484  *
01485  * Output: the address type of the client address
01486  * Returns:   0, when success
01487  *           -1, a non-implemented pap feature requested by pi
01488  *           -2, address parsing error  
01489  */
01490 
01491 int parse_address(Octstr **address, long *type_of_address)
01492 {
01493     long pos;
01494     Octstr *copy;
01495 
01496     pos = octstr_len(*address) - 1;
01497 /*
01498  * Delete first separator, if there is one. This will help our parsing later.
01499  */
01500     if (octstr_get_char(*address, 0) == '/')
01501         octstr_delete(*address, 0, 1);
01502 
01503 /*
01504  * WAP-209, chapter 8 states that addresses with telephone numbers
01505  * should not have a ppg specifier. WAP-151 grammar, however, makes it
01506  * mandatory. Best way to solve this contradiction seems to be regarding
01507  * ppg specifier optional - MMSC is very important type of pi.
01508  */
01509     if (octstr_search_char(*address, '@', 0) >= 0) {
01510         if ((pos = parse_ppg_specifier(address, pos)) < 0)
01511         return -2;
01512     }
01513 
01514     if ((pos = parse_wappush_client_address(address, pos, 
01515             type_of_address)) == -2) {
01516         warning(0, "illegal client address");
01517         return -2;
01518     } else if (pos == -1) {
01519         warning(0, "unimplemented feature");
01520         return -1;
01521     }
01522 
01523     info(0, "client address was <%s>, accepted", 
01524          octstr_get_cstr(copy = octstr_duplicate(*address)));    
01525     octstr_destroy(copy);
01526 
01527     return pos;
01528 }
01529 
01530 /*
01531  * Output: the type of the client address
01532  */
01533 static long parse_wappush_client_address(Octstr **address, long pos, 
01534                                          long *type_of_address)
01535 {
01536     if ((pos = parse_client_specifier(address, pos, type_of_address)) < 0) {
01537         return pos;
01538     }
01539 
01540     pos = parse_constant("WAPPUSH", address, pos);
01541     
01542     return pos;
01543 }
01544 
01545 /*
01546  * We are not interested of ppg specifier, but we must check its format,
01547  * if we find it - it is optional.
01548  */
01549 static long parse_ppg_specifier(Octstr **address, long pos)
01550 {
01551     if (pos >= 0) {
01552         pos = parse_dom_fragment(address, pos);
01553     }
01554 
01555     while (octstr_get_char(*address, pos) != '@' && pos >= 0) {
01556         if (octstr_get_char(*address, pos) == '.') {
01557         octstr_delete(*address, pos, 1);
01558             --pos;
01559         } else {
01560         return -2;
01561         }
01562 
01563         pos = parse_dom_fragment(address, pos);
01564     } 
01565 
01566     pos = drop_character(address, pos);
01567 
01568     if (octstr_get_char(*address, pos) == '/' && pos >= 0) {
01569         octstr_delete(*address, pos, 1);
01570         if (pos > 0)
01571             --pos;
01572     }
01573 
01574     if (pos < 0) {
01575        return -2;
01576     }
01577 
01578     return pos;
01579 }
01580 
01581 /*
01582  * Output: the type of a client address.
01583  * Return a negative value, when error, positive (the position of the parsing 
01584  * cursor) otherwise.
01585  */
01586 static long parse_client_specifier(Octstr **address, long pos, 
01587                                    long *type_of_address)
01588 {
01589     Octstr *type_value;
01590 
01591     type_value = octstr_create("");
01592 
01593     if ((pos = parse_type(address, &type_value, pos)) < 0) {
01594         goto parse_error;
01595     }
01596 
01597     pos = drop_character(address, pos);
01598 
01599     if ((pos = parse_constant("/TYPE", address, pos)) < 0) {
01600         debug("wap.push.pap.compiler", 0, "PAP COMPILER: constant TYPE"
01601               " missing from the client address");
01602         goto parse_error;
01603     }
01604 
01605     if (octstr_case_compare(type_value, octstr_imm("USER")) == 0) {
01606         *type_of_address = ADDR_USER;
01607         goto not_implemented;
01608     }
01609 
01610     if ((pos = parse_ext_qualifiers(address, pos, type_value)) < 0) {
01611         goto parse_error;
01612     }
01613 
01614     if (octstr_case_compare(type_value, octstr_imm("PLMN")) == 0) {
01615         *type_of_address = ADDR_PLMN;
01616         pos = parse_global_phone_number(address, pos);
01617     }
01618 
01619     else if (octstr_case_compare(type_value, octstr_imm("IPv4")) == 0) {
01620         *type_of_address = ADDR_IPV4;
01621         pos = parse_ipv4(address, pos);
01622     }
01623 
01624     else if (octstr_case_compare(type_value, octstr_imm("IPv6")) == 0) {
01625         *type_of_address = ADDR_IPV6;
01626         pos = parse_ipv6(address, pos);
01627     }
01628 
01629     else if (wina_bearer_identifier(type_value)) {
01630         *type_of_address = ADDR_WINA;
01631         pos = parse_escaped_value(address, pos); 
01632     }    
01633 
01634     else {
01635         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong address type"
01636               " in the client address");
01637         goto parse_error; 
01638     }
01639 
01640     octstr_destroy(type_value);
01641     return pos;
01642 
01643 not_implemented:
01644     octstr_destroy(type_value);
01645     return -1;
01646 
01647 parse_error:
01648     octstr_destroy(type_value);
01649     return -2;
01650 }
01651 
01652 /*
01653  * XXX We have a kludge here. WAP-249-PPGService-20010713-a defines in 
01654  * section 6.1 the constant strings "WAPPUSH" and "TYPE" in upper-case. 
01655  * But in the examples of section 6.2 they use lower-case too. Some PI
01656  * vendors (ie. Jatayuu's MMSC) have implemented lower-case in their PAP 
01657  * documents. So we'll support this too for sake of operatibility -- st.
01658  */
01659 static long parse_constant(const char *field_name, Octstr **address, long pos)
01660 {
01661     size_t i, size;
01662     Octstr *nameos;
01663 
01664     nameos = octstr_format("%s", field_name);
01665     size = octstr_len(nameos);
01666     i = 0;
01667     
01668     /* convert both to lower case, see above note */
01669     octstr_convert_range(nameos, 0, octstr_len(nameos), tolower);
01670     octstr_convert_range(*address, 0, octstr_len(*address), tolower);
01671     
01672     while (octstr_get_char(*address, pos - i)  == 
01673                octstr_get_char(nameos, size-1 - i) && i <  size) {
01674         ++i;
01675     }
01676 
01677     while ((octstr_len(*address) > 0) && octstr_get_char(*address, pos) !=
01678                octstr_get_char(nameos, 0) && pos >= 0) {
01679         pos = drop_character(address, pos);
01680     }
01681 
01682     pos = drop_character(address, pos);    
01683 
01684     if (pos < 0 || i != size) {
01685         debug("wap.push.pap.compiler", 0, "parse_constant: unparsable"
01686               " constant %s", field_name);
01687         octstr_destroy(nameos);
01688         return -2;
01689     }
01690 
01691     octstr_destroy(nameos);
01692     return pos;
01693 }
01694 
01695 static long parse_dom_fragment(Octstr **address, long pos)
01696 {
01697     unsigned char c;
01698 
01699     if (pos >= 0) { 
01700         if (isalnum(octstr_get_char(*address, pos))) {
01701         pos = drop_character(address, pos);
01702         } else
01703         return -2;
01704     }
01705 
01706     while ((c = octstr_get_char(*address, pos)) != '@' && 
01707                octstr_get_char(*address, pos) != '.' && pos >= 0)  {
01708         if (isalnum(c) || c == '-') {
01709         pos = drop_character(address, pos);
01710         } else
01711         return -2;
01712     } 
01713 
01714     return pos;
01715 }
01716 
01717 static long drop_character(Octstr **address, long pos)
01718 {
01719     if (pos >= 0) {
01720         octstr_delete(*address, pos, 1);
01721         if (pos > 0)
01722             --pos;
01723     }
01724 
01725     return pos;
01726 }
01727 
01728 static long parse_type(Octstr **address, Octstr **type_value, long pos)
01729 {
01730     unsigned char c;
01731 
01732     while ((c = octstr_get_char(*address, pos)) != '=' && pos >= 0) {   
01733         *type_value = prepend_char(*type_value, c);
01734         pos = drop_character(address, pos);
01735     } 
01736 
01737     if (pos < 0)
01738         return -2;
01739 
01740     return pos;
01741 }
01742 
01743 static long parse_ext_qualifiers(Octstr **address, long pos, 
01744                                  Octstr *type)
01745 {
01746     int ret;
01747 
01748     while ((ret = qualifiers(*address, pos, type)) == 1) {
01749         if ((pos = parse_qualifier_value(address, pos)) < 0)
01750             return pos;
01751 
01752         if ((pos = parse_qualifier_keyword(address, pos)) < 0)
01753             return pos;
01754     }
01755 
01756     if (ret == 1) {
01757         debug("wap.push.pap.compiler", 0, "PAP COMPILER: erroneous qualifiers"
01758               " in the client address");
01759         return -2;
01760     }
01761 
01762     return pos;
01763 }
01764 
01765 /*
01766  * According to ppg, chapter 7.1, global phone number starts with +. Phone
01767  * number is here an unique identifier, so if it does not conform the inter-
01768  * national format, we return an error. (Is up to bearerbox to transform it
01769  * to an usable phone number)
01770  */
01771 static long parse_global_phone_number(Octstr **address, long pos)
01772 {
01773     unsigned char c;
01774 
01775     while ((c = octstr_get_char(*address, pos)) != '+' && pos >= 0) {
01776          if (!isdigit(c) && c != '-' && c != '.') {
01777              debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator"
01778                    " in a phone number (- and . allowed)");
01779              return -2;
01780      } else {
01781          --pos;
01782          }
01783     }
01784 
01785     if (pos == 0) {
01786         debug("wap.push.pap.compiler", 0, "PAP COMPILER:a phone number must"
01787               " start with +");
01788         return -2;
01789     }
01790 
01791     if (pos > 0)
01792         --pos;
01793 
01794     pos = drop_character(address, pos);
01795 
01796     return pos;
01797 }
01798 
01799 static long parse_ipv4(Octstr **address, long pos)
01800 {
01801     long i;
01802 
01803     if ((pos = parse_ipv4_fragment(address, pos)) < 0) {
01804         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator in a"
01805               " ipv4 address");
01806         return -2;
01807     }
01808 
01809     i = 1;
01810 
01811     while (i <= 3 && octstr_get_char(*address, pos) != '=' && pos >= 0) {
01812         pos = parse_ipv4_fragment(address, pos);
01813         ++i;
01814     }
01815 
01816     if (pos == 0) {
01817         debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator at"
01818               " beginning of a client address (=)");
01819         return -2;
01820     }
01821 
01822     return pos;
01823 }
01824 
01825 static long parse_ipv6(Octstr **address, long pos)
01826 {
01827     long i;
01828 
01829     if ((pos = parse_ipv6_fragment(address, pos)) < 0) {
01830         debug("wap.push.pap.compiler", 0, "PAP COMPILER: wrong separator in a"
01831               " ipv6 address");
01832         return -2;
01833     }
01834 
01835     i = 1;
01836 
01837     while (i <= 7 && octstr_get_char(*address, pos) != '=' && pos >= 0) {
01838         pos = parse_ipv6_fragment(address, pos);
01839         ++i;
01840     }
01841 
01842     if (pos == 0) {
01843         debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator at"
01844               " beginning of a client address (=)");
01845         return -2;
01846     }
01847 
01848     return pos;
01849 }
01850 
01851 /*
01852  * WINA web page does not include address type identifiers. Following ones are
01853  * from wdp, Appendix C.
01854  */
01855 
01856 static char *bearer_address[] = {
01857     "GSM_MSISDN",
01858     "ANSI_136_MSISDN",
01859     "IS_637_MSISDN",
01860     "iDEN_MSISDN",
01861     "FLEX_MSISDN",
01862     "PHS_MSISDN",
01863     "GSM_Service_Code",
01864     "TETRA_ITSI",
01865     "TETRA_MSISDN",
01866     "ReFLEX_MSIDDN",
01867     "MAN",
01868 };
01869 
01870 static size_t bearer_address_size = sizeof(bearer_address) / 
01871                                     sizeof(bearer_address[0]);
01872 
01873 static int wina_bearer_identifier(Octstr *type_value)
01874 {
01875     size_t i;
01876 
01877     i = 0;
01878     while (i < bearer_address_size) {
01879         if (octstr_case_compare(type_value, 
01880                 octstr_imm(bearer_address[i])) == 0)
01881         return 1;
01882         ++i;
01883     }
01884 
01885     debug("wap.push.pap.compiler", 0, "PAP COMPILER: a bearer not registered"
01886           " by wina");
01887     return 0;
01888 }
01889 
01890 /*
01891  * Note that we parse backwards. First we create a window of three characters
01892  * (representing a possible escaped character). If the first character of the 
01893  * window is not escape, we handle the last character and move the window one
01894  * character backwards; if it is, we handle escaped sequence and create a new
01895  * window. If we cannot create a window, rest of characters are unescaped.
01896  */
01897 static long parse_escaped_value(Octstr **address, long pos)
01898 {
01899     int ret;
01900 
01901     if (create_peek_window(address, &pos) == 0)
01902          if ((pos = rest_unescaped(address, pos)) == -2)
01903              return -2;
01904 
01905     while (octstr_get_char(*address, pos) != '=' && pos >= 0) {
01906         if ((ret = issafe(address, pos)) == 1) {
01907         pos = accept_safe(address, pos);
01908 
01909         } else if (ret == 0) {
01910         if ((pos = accept_escaped(address, pos)) < 0)
01911                 return -2;  
01912             if (create_peek_window(address, &pos) == 0)
01913                 if ((pos = rest_unescaped(address, pos)) == -2)
01914                     return -2;
01915         }
01916     }
01917 
01918     pos = drop_character(address, pos);
01919 
01920     return pos;
01921 }
01922 
01923 static Octstr *prepend_char(Octstr *os, unsigned char c)
01924 {
01925     Octstr *tmp;
01926 
01927     tmp = octstr_format("%c", c);
01928     octstr_insert(os, tmp, 0);
01929     octstr_destroy(tmp);
01930     return os;
01931 }
01932 
01933 /*
01934  * Ext qualifiers contain /, ipv4 address contains . , ipv6 address contains :.
01935  * phone number contains + and escaped-value contain no specific tokens. Lastly
01936  * mentioned are for future extensions, but we must parse them.
01937  * Return 1, when qualifiers found
01938  *        0, when not
01939  *       -1, when an error was found during the process
01940  */
01941 static int qualifiers(Octstr *address, long pos, Octstr *type)
01942 {
01943     unsigned char term,
01944          c;
01945     long i;
01946 
01947     i = pos;
01948     c = 'E';
01949 
01950     if (octstr_case_compare(type, octstr_imm("PLMN")) == 0)
01951         term = '+';
01952     else if (octstr_case_compare(type, octstr_imm("IPv4")) == 0)
01953         term = '.';
01954     else if (octstr_case_compare(type, octstr_imm("IPv6")) == 0)
01955         term = ':';
01956     else
01957         term = 'N';
01958 
01959     if (term != 'N') {
01960         while ((c = octstr_get_char(address, i)) != term && i != 0) {
01961             if (c == '/')
01962                 return 1;
01963             --i;
01964         }
01965         if (i == 0)
01966         return 0;
01967     }
01968 
01969     if (term == 'N') {
01970         while (i != 0) {
01971             if (c == '/')
01972                 return 1;
01973             --i;
01974         }
01975     } 
01976 
01977     return 0;
01978 }
01979 
01980 static long parse_qualifier_value(Octstr **address, long pos)
01981 {
01982     unsigned char c;
01983 
01984     while ((c = octstr_get_char(*address, pos)) != '=' && pos >= 0) {
01985         if (c < 0x20 || (c > 0x2e && c < 0x30) || (c > 0x3c && c < 0x3e) ||
01986             c > 0x7e)
01987             return -2;
01988 
01989         pos = drop_character(address, pos);
01990     }
01991 
01992     pos = drop_character(address, pos);
01993   
01994     return pos;
01995 }
01996 
01997 static long parse_qualifier_keyword(Octstr **address, long pos)
01998 {
01999     unsigned char c;  
02000 
02001     while ((c = octstr_get_char(*address, pos)) != '/') {
02002         if (isalnum(c) || c == '-') {
02003         pos = drop_character(address, pos);
02004         } else
02005         return -2;
02006     }
02007 
02008     pos = drop_character(address, pos);       
02009 
02010     return pos;
02011 }
02012 
02013 static long parse_ipv4_fragment(Octstr **address, long pos)
02014 {
02015     long i;
02016     unsigned char c;
02017 
02018     i = 0;
02019     c = '=';
02020 
02021     if (isdigit(c = octstr_get_char(*address, pos)) && pos >= 0) {
02022         --pos;
02023         ++i;
02024     } else {
02025         debug("wap.push.pap.compiler", 0, "non-digit found in ip address,"
02026               " address unacceptable");
02027         return -2;
02028     }
02029     
02030     while (i <= 3 && ((c = octstr_get_char(*address, pos)) != '.' &&  c != '=')
02031             && pos >= 0) {
02032         if (isdigit(c)) {
02033             --pos;
02034             ++i;
02035         } else {
02036         debug("wap.push.pap.compiler", 0, "parse_ipv4_fragment: non-digit"
02037                   " in ipv4 address, address unacceptable");
02038         return -2;
02039         }
02040     }
02041 
02042     pos = handle_two_terminators(address, pos, '.', '=', c, i, 3);
02043 
02044     return pos;
02045 }
02046 
02047 static long parse_ipv6_fragment(Octstr **address, long pos)
02048 {
02049     long i;
02050     unsigned char c;
02051 
02052     i = 0;
02053 
02054     if (isxdigit(octstr_get_char(*address, pos)) && pos >= 0) {
02055         --pos;
02056         ++i;
02057     } else {
02058         return -2;
02059     }
02060 
02061     c = '=';
02062 
02063     while (i <= 4 && ((c = octstr_get_char(*address, pos)) != ':' && c != '=')
02064             && pos >= 0) {
02065         if (isxdigit(c)) {
02066         --pos;
02067             ++i;
02068         } else {
02069         return -2;
02070         }
02071     }
02072 
02073     pos = handle_two_terminators(address, pos, ':', '=', c, i, 4);
02074 
02075     return pos;
02076 }
02077 
02078 /*
02079  * Return -1, it was impossible to create the window because of there is no
02080  * more enough characters left and 0 if OK.
02081  */
02082 static int create_peek_window(Octstr **address, long *pos)
02083 {
02084    long i;
02085     unsigned char c;
02086 
02087     i = 0;
02088     c = '=';
02089     while (i < 2 && (c = octstr_get_char(*address, *pos)) != '=') {
02090         if (*pos > 0)
02091             --*pos;
02092         ++i;
02093     }
02094 
02095     if (c == '=')
02096         return 0;
02097 
02098     return 1; 
02099 }
02100 
02101 static long rest_unescaped(Octstr **address, long pos)
02102 {
02103     long i,
02104          ret;
02105 
02106     for (i = 2; i > 0; i--) {
02107          if ((ret = accept_safe(address, pos)) == -2)
02108          return -2;
02109          else if (ret == -1)
02110          return pos;
02111     }
02112 
02113     return pos;
02114 }
02115 
02116 static int issafe(Octstr **address, long pos)
02117 {
02118     if (octstr_get_char(*address, pos) == '%')
02119         return 0;
02120     else
02121         return 1;
02122 }
02123 
02124 static long accept_safe(Octstr **address, long pos)
02125 {
02126     unsigned char c;
02127 
02128     c = octstr_get_char(*address, pos);
02129     if ((isalnum(c) || c == '+' || c == '-' || c == '.' || c == '_') && 
02130             pos >= 0)
02131     --pos;
02132     else if (c == '=')
02133         return -1;
02134     else
02135         return -2;
02136 
02137     return pos;
02138 }
02139 
02140 static long accept_escaped(Octstr **address, long pos)
02141 {
02142     Octstr *temp;
02143     long i;
02144     unsigned char c;
02145 
02146     pos = drop_character(address, pos);
02147     temp = octstr_create("");
02148 
02149     for (i = 2; i > 0; i--) {
02150         c = octstr_get_char(*address, pos + i);
02151         temp = prepend_char(temp, c);
02152         pos = drop_character(address, pos + i);
02153         if (pos > 0)
02154       --pos;
02155     }
02156 
02157     if (octstr_hex_to_binary(temp) < 0) {
02158         octstr_destroy(temp);
02159         return -2;
02160     }
02161 
02162     octstr_insert(*address, temp, pos + 2);   /* To the end of the window */
02163 
02164     octstr_destroy(temp);
02165     return pos + 1;                           /* The position preceding the 
02166                                                  inserted character */
02167               
02168 }
02169 
02170 /*
02171  * Point ends the string to be parsed, comma separates its fragments.
02172  */
02173 static long handle_two_terminators (Octstr **address, long pos, 
02174     unsigned char comma, unsigned char point, unsigned char c, 
02175     long fragment_parsed, long fragment_length)
02176 {
02177     if (fragment_parsed == fragment_length && c != comma && c != point)
02178         return -2;
02179 
02180     if (c == point) 
02181         octstr_delete(*address, pos, 1);
02182 
02183     --pos;
02184 
02185     return pos;
02186 }
02187 
02188 
02189 
02190 
02191 
02192 
02193 
02194 
02195 
02196 
02197 
02198 
02199 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.