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