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