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