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