CVS diff again

Aarno Syvänen <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi List,

this one you can actually apply ;)

Aarno
cvs.diff (application/octet-stream, 39.3 KB)
Index: gw/wap_push_ota.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_ota.c,v
retrieving revision 1.17
diff -B -b -u -r1.17 wap_push_ota.c
--- gw/wap_push_ota.c	13 Feb 2003 10:32:01 -0000	1.17
+++ gw/wap_push_ota.c	30 May 2003 10:32:03 -0000
@@ -332,7 +332,8 @@
 }
 
 /*
- * Add push flag into push headers. Push flag is defined in otaa, p. 17-18.
+ * Add push flag into push headers. Push flag is defined in ota, p. 17-18.
+ * If there is no flags set, no Push-Flag header is added.
  */
 static List *add_push_flag(WAPEvent *e)
 {
@@ -377,9 +378,11 @@
     push_flag = 0;
     push_flag = push_flag | authenticated | trusted | last;
     
+    if (push_flag) {
     buf = octstr_format("%d", push_flag);
     http_header_add(headers, "Push-Flag", octstr_get_cstr(buf)); 
     octstr_destroy(buf);
+    }
 
     return headers;
 }
Index: gw/wap_push_pap_compiler.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_pap_compiler.c,v
retrieving revision 1.28
diff -B -b -u -r1.28 wap_push_pap_compiler.c
--- gw/wap_push_pap_compiler.c	28 Mar 2003 13:03:49 -0000	1.28
+++ gw/wap_push_pap_compiler.c	30 May 2003 10:32:04 -0000
@@ -757,8 +757,9 @@
     }
 
     if (i == NUM_ELEMENTS) {
+        debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element:");
+        octstr_dump(name, 0);
         octstr_destroy(name);
-        debug("wap.push.pap.compiler", 0, "PAP COMPILER: unknown element");
         return -2;
     }
 
@@ -1444,8 +1445,14 @@
     if (octstr_get_char(*address, 0) == '/')
         octstr_delete(*address, 0, 1);
 
-    if ((pos = parse_ppg_specifier(address, pos)) < 0) {
-        warning(0, "illegal ppg specifier");
+/*
+ * WAP-209, chapter 8 states that addresses with telephone numbers
+ * should not have a ppg specifier. WAP-151 grammar, however, makes it
+ * mandatory. Best way to solve this contradiction seems to be regarding
+ * ppg specifier optional - MMSC is very important type of pi.
+ */
+    if (octstr_search_char(*address, '@', 0) >= 0) {
+        if ((pos = parse_ppg_specifier(address, pos)) < 0)
         return -2;
     }
 
@@ -1481,7 +1488,8 @@
 }
 
 /*
- * We are not interested of ppg specifier, but we must check its format.
+ * We are not interested of ppg specifier, but we must check its format,
+ * if we find it - it is optional.
  */
 static long parse_ppg_specifier(Octstr **address, long pos)
 {
@@ -1494,8 +1502,6 @@
 	    octstr_delete(*address, pos, 1);
             --pos;
         } else {
-            debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing"
-                  " separator .");
 	    return -2;
         }
 
@@ -1511,8 +1517,6 @@
     }
 
     if (pos < 0) {
-       debug("wap.push.pap.compiler", 0, "PAP COMPILER: missing separator /"
-             " or @");
        return -2;
     }
 
Index: gw/wap_push_pap_mime.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_pap_mime.c,v
retrieving revision 1.5
diff -B -b -u -r1.5 wap_push_pap_mime.c
--- gw/wap_push_pap_mime.c	4 Sep 2002 09:05:06 -0000	1.5
+++ gw/wap_push_pap_mime.c	30 May 2003 10:32:04 -0000
@@ -2,7 +2,7 @@
  * Implementation of a gateway oriented mime parser for pap module. This 
  * parser follows proxy rules stated in Push Message, chapter 7.
  *
- * By Aarno Syvänen for Wiral Ltd
+ * By Aarno Syvänen for Wiral Ltd and Global Networks Inc.
  */
 
 #include "wap_push_pap_mime.h"
@@ -47,7 +47,7 @@
 			    long pos);
 static long pass_field_value(Octstr **body_part, Octstr **content_header, 
                              long pos);
-static void parse_epilogue(Octstr **mime_content);
+static int parse_epilogue(Octstr **mime_content);
 static int parse_tail(Octstr **multipart, Octstr *part_delimiter, 
                       long boundary_pos, long *next_part_pos);
 
@@ -103,8 +103,8 @@
         return 0;
     } else if (ret == 0) {
         gw_assert(*rdf_content == NULL);
+        if (octstr_len(mime_content) != 0)
         parse_epilogue(&mime_content);
-        gw_assert(octstr_len(mime_content) == 0);
         return 1;
     }
 
@@ -112,6 +112,7 @@
         warning(0, "erroneous capacity (rdf) headers");
         return 0;
     }
+    if (octstr_len(mime_content) != 0)
     parse_epilogue(&mime_content);
     gw_assert(octstr_len(mime_content) == 0);
     
@@ -141,6 +142,7 @@
     return c == '\t' || c == ' ';
 }
 
+/* These thingies we after normally have after delimiters. */
 static int parse_tail(Octstr **multipart, Octstr *delimiter, 
                       long boundary_pos, long *next_part_pos)
 {
@@ -153,6 +155,16 @@
     return 0;
 }
 
+/* But if we have no epilogue, we do not have crlf after close delimiter either.*/
+static int parse_short_tail(Octstr **multipart, Octstr *delimiter, long boundary_pos,
+                            long *next_part_pos)
+{
+    *next_part_pos = parse_transport_padding(*multipart,
+         boundary_pos + octstr_len(delimiter));
+
+    return 0;
+}
+
 /*
  * Boundary misses crlf here. This is intentional: Kannel header parsing pro-
  * cess drops this terminator.
@@ -200,18 +212,28 @@
 
 static long parse_transport_padding(Octstr *mime_content, long pos)
 {
-    while (islwspchar(octstr_get_char(mime_content, 0)))
+    while (islwspchar(octstr_get_char(mime_content, pos)))
         ++pos;
 
     return pos;
 }
 
+static long parse_close_delimiter(Octstr *close_delimiter, Octstr *mime_content,
+                                  long pos)
+{
+    if (octstr_ncompare(close_delimiter, mime_content, 
+                        octstr_len(close_delimiter)) != 0)
+        return -1;
+    pos += octstr_len(close_delimiter);
+
+    return pos;
+}
+
 /*
- * Splits the first body part away from the multipart message, if there is 
- * more than one left. A body part end with either with another body or with 
- * a close delimiter. If there is more than one body part left, we first split
- * the first one and then remove the stuff separating bodies from the remaind-
- * er. If there is none just remove the ending stuff.
+ * Splits the first body part away from the multipart message. A body part end with
+ * either with another body or with a close delimiter. We first split the body and
+ * then remove the separating stuff  from the remainder. If we have the last body
+ * part, we must parse all closing stuff. 
  * Returns 1, there is still another body part in the multipart message
  *         0, if there is none
  *         -1, when parsing error.
@@ -224,7 +246,8 @@
     long boundary_pos,          /* start of the boundary */
          close_delimiter_pos,   /* start of the close delimiter */
          end_pos,               /* end of the message */
-         next_part_pos;         /* start of the next part */
+         next_part_pos,         /* start of the next part */
+         epilogue_pos;          /* start of the epilogue */
  
     part_delimiter = make_part_delimiter(boundary);
     close_delimiter = make_close_delimiter(boundary);
@@ -235,17 +258,15 @@
 
     boundary_pos = octstr_search(*multipart, part_delimiter, 0);
     if (boundary_pos == close_delimiter_pos) {
-        if (parse_tail(multipart, close_delimiter, close_delimiter_pos,
-                       &end_pos) < 0) {
+        *body_part = octstr_create("");
+        octstr_split_by_pos(multipart, body_part, close_delimiter_pos);
+        if ((epilogue_pos = 
+                parse_close_delimiter(close_delimiter, *multipart, 0)) < 0)
             goto error;
-        } else {
-            octstr_delete(*multipart, close_delimiter_pos, 
-                          end_pos - close_delimiter_pos);
-            *body_part = octstr_duplicate(*multipart);
-            octstr_delete(*multipart, 0, end_pos);
+        epilogue_pos = parse_transport_padding(*multipart, epilogue_pos);
+        octstr_delete(*multipart, 0, epilogue_pos);
 	        goto last_part;
         }
-    }
 
     *body_part = octstr_create("");
     octstr_split_by_pos(multipart, body_part, boundary_pos);
@@ -727,13 +748,17 @@
     return pos;
 }
 
-static void parse_epilogue(Octstr **mime_content)
+/* This is actually CRLF epilogue. */
+static int parse_epilogue(Octstr **mime_content)
 {
+    long pos;
+
     if (octstr_len(*mime_content) == 0)
-        return;
+        return 0;
+    
+    if ((pos = parse_terminator(*mime_content, 0)) < 0)
+        return -1;
 
-    debug("wap.push.pap.mime", 0, "our epilogue was");
-    octstr_dump(*mime_content, 0);
     octstr_delete(*mime_content, 0, octstr_len(*mime_content));
 }
 
Index: gw/wap_push_ppg.c
===================================================================
RCS file: /home/cvs/gateway/gw/wap_push_ppg.c,v
retrieving revision 1.53
diff -B -b -u -r1.53 wap_push_ppg.c
--- gw/wap_push_ppg.c	20 Mar 2003 14:11:49 -0000	1.53
+++ gw/wap_push_ppg.c	30 May 2003 10:32:05 -0000
@@ -266,6 +266,7 @@
                              Octstr **boundary);
 static void change_header_value(List **push_headers, char *name, char *value);
 static void remove_mime_headers(List **push_headers);
+static void remove_link_headers(List **push_headers);
 
 /*
  * Communicating with pi.
@@ -374,6 +375,7 @@
          octstr_destroy(ppg_deny_ip);
          octstr_destroy(ppg_allow_ip);
          octstr_destroy(global_sender);
+         octstr_destroy(ppg_default_smsc);
 
          gwthread_join_every(http_read_thread);
 #ifdef HAVE_LIBSSL
@@ -745,6 +747,7 @@
         
         http_remove_hop_headers(push_headers);
         remove_mime_headers(&push_headers);
+        remove_link_headers(&push_headers);
 
         if (!headers_acceptable(push_headers, &content_header)) {
 	        warning(0,  "PPG: Unparsable push headers, the request"
@@ -2670,7 +2673,23 @@
     "wta.ua", 
     "mms.ua", 
     "push.syncml", 
-    "loc.ua" 
+    "loc.ua",
+    "syncml.dm",
+    "drm.ua",
+    "emn.ua",
+    "wv.ua",
+    "x-wap-microsoft:localcontent.ua",
+    "x-wap-microsoft:IMclient.ua",
+    "x-wap-docomo:imode.mail.ua",
+    "x-wap-docomo:imode.mr.ua",
+    "x-wap-docomo:imode.mf.ua",
+    "x-motorola:location.ua",
+    "x-motorola:now.ua",
+    "x-motorola:otaprov.ua",
+    "x-motorola:browser.ua",
+    "x-motorola:splash.ua",
+    "x-wap-nai:mvsw.command",
+    "x-wap-openwave:iota.ua" 
 };
 
 #define NUMBER_OF_WINA_URIS sizeof(wina_uri)/sizeof(wina_uri[0])
@@ -2680,14 +2699,9 @@
  * First check do we a header with an app-encoding field and a coded value. 
  * If not, try to find push application id from table of wina approved values.
  * Return coded value value of application id in question, or an error code:
- *        -1, error
+ *        -1, no coded value (but defaults may be applied)
  *         0, * (meaning any application acceptable)
- *         1, push.sia
- *         2, wml.ua
- *         3, wta.ua 
- *         4, mms.ua
- *         5, push.syncml 
- *         6, loc.ua 
+ *         greater or equal as 1: code for this application id 
  */
 static long parse_appid_header(Octstr **appid_content)
 {
@@ -2844,12 +2858,21 @@
 
 /*
  * Some application level protocols may use MIME headers. This may cause problems
- * to them. 
+ * to them. (MIME version is a mandatory header).
  */
 static void remove_mime_headers(List **push_headers)
 {
     http_header_remove_all(*push_headers, "MIME-Version");
 }
+
+/*
+ * There are headers used only for HTTP POST pi->ppg. (For debugging, mainly.)
+ */
+static void remove_link_headers(List **push_headers)
+{
+    http_header_remove_all(*push_headers, "Host");
+}
+
 
 /*
  * Badmessage-response element is redefined in pap, implementation note, 
Index: gw/wapbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/wapbox.c,v
retrieving revision 1.157
diff -B -b -u -r1.157 wapbox.c
--- gw/wapbox.c	27 Mar 2003 08:55:01 -0000	1.157
+++ gw/wapbox.c	30 May 2003 10:32:05 -0000
@@ -49,6 +49,10 @@
 int wsp_smart_errors = 0;
 Octstr *device_home = NULL;
 
+/* Controlling segmentation of sms messages sent by wapbox (push related).*/
+int concatenation = 0;
+long max_messages = 10;
+
 #ifdef HAVE_WTLS_OPENSSL
 RSA* private_key = NULL;
 X509* x509_cert = NULL;
@@ -176,6 +180,8 @@
      * error information instread of signaling using the HTTP reply codes
      */
     cfg_get_bool(&wsp_smart_errors, grp, octstr_imm("smart-errors"));
+    cfg_get_bool(&concatenation, grp, octstr_imm("concatenation"));
+    cfg_get_integer(&max_messages, grp, octstr_imm("max-messages"));
 
     /* configure the 'wtls' group */
 #if (HAVE_WTLS_OPENSSL)
@@ -396,13 +402,13 @@
         } else {
 	    msg = pack_sms_datagram(dgram);
             msg_sequence = counter_increase(sequence_counter) & 0xff;
-            msg_len = octstr_len(msg->sms.msgdata);
-            max_msgs = (msg_len / MAX_SMS_OCTETS) + 1; 
-            sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, 1, 
-                                      msg_sequence, max_msgs, MAX_SMS_OCTETS);
-
-            while ((part = list_extract_first(sms_datagrams)) != NULL)
+            /*msg_len = octstr_len(msg->sms.msgdata);
+            max_msgs = (msg_len / MAX_SMS_OCTETS) + 1;*/ 
+            sms_datagrams = sms_split(msg, NULL, NULL, NULL, NULL, concatenation, 
+                                      msg_sequence, max_messages, MAX_SMS_OCTETS);
+            while ((part = list_extract_first(sms_datagrams)) != NULL) {
 	            write_to_bearerbox(part);
+            }
 
             list_destroy(sms_datagrams, NULL);
             msg_destroy(msg);
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.85
diff -B -b -u -r1.85 cfg.def
--- gwlib/cfg.def	3 Apr 2003 12:18:18 -0000	1.85
+++ gwlib/cfg.def	30 May 2003 10:32:05 -0000
@@ -77,6 +77,8 @@
     OCTSTR(syslog-level)
     OCTSTR(smart-errors)
     OCTSTR(access-log)
+    OCTSTR(concatenation)
+    OCTSTR(max-messages)
 )
 
 
Index: gwlib/http.c
===================================================================
RCS file: /home/cvs/gateway/gwlib/http.c,v
retrieving revision 1.190
diff -B -b -u -r1.190 http.c
--- gwlib/http.c	3 Apr 2003 12:18:36 -0000	1.190
+++ gwlib/http.c	30 May 2003 10:32:06 -0000
@@ -2374,12 +2374,14 @@
         if (octstr_case_compare(current_name, name) == 0) {
             value = octstr_copy(os, colon + 1, octstr_len(os));
             octstr_strip_blanks(value);
+            octstr_destroy(current_name);
             return value;
         }
+        octstr_destroy(current_name);
         ++i;
     }
     
-    return value;
+    return NULL;
 }
 
 List *http_header_duplicate(List *headers)
Index: test/test_ppg.c
===================================================================
RCS file: /home/cvs/gateway/test/test_ppg.c,v
retrieving revision 1.23
diff -B -b -u -r1.23 test_ppg.c
--- test/test_ppg.c	19 May 2003 07:37:52 -0000	1.23
+++ test/test_ppg.c	30 May 2003 10:32:06 -0000
@@ -27,15 +27,22 @@
            num_urls = 0,
            wait = 0,
            use_headers = 0,
-           use_config = 0;
+           use_config = 0,
+           accept_binary = 0, 
+           use_numeric = 0,
+           use_string = 0,
+           add_epilogue = 0,
+           add_preamble = 0;
 static double wait_seconds = 0.0;
 static Counter *counter = NULL;
 static char **push_data = NULL;
 static char *boundary = NULL;
 static Octstr *content_flag = NULL;
 static Octstr *appid_flag = NULL;
+static Octstr *appid_string = NULL;
 static Octstr *content_transfer_encoding = NULL;
 static Octstr *connection = NULL;
+static Octstr *delimiter = NULL;
 
 enum { SSL_CONNECTION_OFF = 0,
        DEFAULT_NUMBER_OF_RELOGS = 2};
@@ -90,43 +97,74 @@
     cfg_destroy(cfg);
 }
 
-static void add_push_application_id(List **push_headers, Octstr *appid_flag)
+static void add_delimiter(Octstr **content)
+{
+    if (octstr_compare(delimiter, octstr_imm("crlf")) == 0) {
+        octstr_format_append(*content, "%c", '\r');
+    }
+
+    octstr_format_append(*content, "%c", '\n');
+}
+
+static void add_push_application_id(List **push_headers, Octstr *appid_flag,
+                                    int use_string)
 {
-    if (octstr_compare(appid_flag, octstr_imm("any")) == 0)
+    if (use_string) {
+        list_append(*push_headers, appid_string);
+        return;
+    }
+
+    if (octstr_compare(appid_flag, octstr_imm("any")) == 0) {
+        if (!use_numeric)
         http_header_add(*push_headers, "X-WAP-Application-Id", 
                         "http://www.wiral.com:*");
-    else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0)
+        else
+            http_header_add(*push_headers, "X-WAP-Application-Id", "0");
+    } else if (octstr_compare(appid_flag, octstr_imm("ua")) == 0) {
+        if (!use_numeric)
         http_header_add(*push_headers, "X-WAP-Application-Id", 
                         "http://www.wiral.com:wml.ua");
-    else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0)
+        else
+            http_header_add(*push_headers, "X-WAP-Application-Id", "2");
+    } else if (octstr_compare(appid_flag, octstr_imm("mms")) == 0) {
+        if (!use_numeric)
         http_header_add(*push_headers, "X-WAP-Application-Id", 
                         "mms.ua");
-    else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0)
+        else
+            http_header_add(*push_headers, "X-WAP-Application-Id", "4");
+    } else if (octstr_compare(appid_flag, octstr_imm("scrap")) == 0) {
+        if (!use_numeric)
         http_header_add(*push_headers, "X-WAP-Application-Id", 
                         "no appid at all");
+        else
+            http_header_add(*push_headers, "X-WAP-Application-Id", 
+                            "this is not a numeric header");
+    }
 }
 
 static void add_content_type(Octstr *content_flag, Octstr **wap_content)
 {
     if (octstr_compare(content_flag, octstr_imm("wml")) == 0)
         *wap_content = octstr_format("%s", 
-            "Content-Type: text/vnd.wap.wml\r\n");
+            "Content-Type: text/vnd.wap.wml");
     else if (octstr_compare(content_flag, octstr_imm("si")) == 0)
 	    *wap_content = octstr_format("%s",
-            "Content-Type: text/vnd.wap.si\r\n");
+            "Content-Type: text/vnd.wap.si");
     else if (octstr_compare(content_flag, octstr_imm("sl")) == 0)
 	    *wap_content = octstr_format("%s",
-            "Content-Type: text/vnd.wap.sl\r\n");
+            "Content-Type: text/vnd.wap.sl");
     else if (octstr_compare(content_flag, octstr_imm("multipart")) == 0)
         *wap_content = octstr_format("%s",
             "Content-Type: multipart/related; boundary=fsahgwruijkfldsa\r\n");
     else if (octstr_compare(content_flag, octstr_imm("mms")) == 0) 
         *wap_content = octstr_format("%s", 
-            "Content-Type: application/vnd.wap.mms-message\r\n"); 
+            "Content-Type: application/vnd.wap.mms-message"); 
     else if (octstr_compare(content_flag, octstr_imm("scrap")) == 0)
-        *wap_content = octstr_format("%s", "no type at all\r\n"); 
+        *wap_content = octstr_format("%s", "no type at all"); 
     else if (octstr_compare(content_flag, octstr_imm("nil")) == 0)
         *wap_content = octstr_create("");
+    if (octstr_len(*wap_content) > 0)
+        add_delimiter(wap_content);
 }
 
 static void add_content_transfer_encoding_type(Octstr *content_flag, 
@@ -136,7 +174,9 @@
 	     return;
 
     if (octstr_compare(content_flag, octstr_imm("base64")) == 0)
-	    octstr_append_cstr(wap_content, "Content-transfer-encoding: base64\r\n");
+	octstr_append_cstr(wap_content, "Content-transfer-encoding: base64");
+
+    add_delimiter(&wap_content);
 }
 
 static void add_connection_header(Octstr *connection, Octstr *wap_content)
@@ -145,9 +185,11 @@
         return;
 
     if (octstr_compare(connection, octstr_imm("close")) == 0)
-        octstr_format_append(wap_content, "%s", "Connection: close\r\n");
+        octstr_format_append(wap_content, "%s", "Connection: close");
     else if (octstr_compare(connection, octstr_imm("keep-alive")) == 0) 
-        octstr_format_append(wap_content, "%s", "Connection: keep-alive\r\n");
+        octstr_format_append(wap_content, "%s", "Connection: keep-alive");
+
+    add_delimiter(&wap_content);
 }
 
 static void transfer_encode (Octstr *cte, Octstr *content)
@@ -180,12 +222,10 @@
     Octstr *part_delimiter;
 
     part_delimiter = octstr_create("");
-    octstr_format_append(part_delimiter, "%c", '\r');
-    octstr_format_append(part_delimiter, "%c", '\n');
+    add_delimiter(&part_delimiter);
     octstr_format_append(part_delimiter, "%s", "--");
     octstr_append(part_delimiter, boundary);
-    octstr_format_append(part_delimiter, "%c", '\r');
-    octstr_format_append(part_delimiter, "%c", '\n');
+    add_delimiter(&part_delimiter);
     
     return part_delimiter;
 }
@@ -195,14 +235,11 @@
     Octstr *close_delimiter;
 
     close_delimiter = octstr_create("");
-    octstr_format_append(close_delimiter, "%c", '\r');
-    octstr_format_append(close_delimiter, "%c", '\n');
+    add_delimiter(&close_delimiter);
     octstr_format_append(close_delimiter, "%s", "--");
     octstr_append(close_delimiter, boundary);
     octstr_format_append(close_delimiter, "%s", "--");
-    octstr_format_append(close_delimiter, "%c", '\r');
-    octstr_format_append(close_delimiter, "%c", '\n');
-    
+    /*add_delimiter(&close_delimiter);*/
 
     return close_delimiter;
 }
@@ -222,7 +259,7 @@
                         octstr_get_cstr(mos = make_multipart_value(boundary)));
     if (use_headers)
         http_add_basic_auth(push_headers, username, password);
-    add_push_application_id(&push_headers, appid_flag);
+    add_push_application_id(&push_headers, appid_flag, use_string);
 
     octstr_destroy(mos);
 
@@ -288,18 +325,30 @@
                                            wap_content);
         add_connection_header(connection, wap_content);
 
+        /* Read the content file. (To be pushed)*/
         if ((wap_file_content = 
                 octstr_read_file(octstr_get_cstr(content_file))) == NULL)
 	         panic(0, "Stopping");
+        if (accept_binary) {
+            octstr_delete_matching(wap_file_content, octstr_imm(" "));
+            octstr_delete_matching(wap_file_content, octstr_imm("\n"));
+            octstr_delete_matching(wap_file_content, octstr_imm("\r"));
+            if (!octstr_is_all_hex(wap_file_content))
+                panic(0, "non-hex chars in the content file, cannot continue");
+            octstr_hex_to_binary(wap_file_content);            
+        }
 
 	    transfer_encode (content_transfer_encoding, wap_file_content);
         octstr_append(wap_content, wap_file_content);
         octstr_destroy(wap_file_content);
 
-        pap_content = octstr_format("%s", "Content-Type: application/xml\r\n");
+        /* Read the control file. (To control pushing)*/
+        pap_content = octstr_format("%s", "Content-Type: application/xml");
+        add_delimiter(&pap_content);
         if ((pap_file_content = 
                 octstr_read_file(octstr_get_cstr(pap_file))) ==  NULL)
 	        panic(0, "Stopping");
+        
         octstr_append(pap_content, pap_file_content);
         octstr_destroy(pap_file_content);
 
@@ -307,14 +356,22 @@
 	        panic(0, "Cannot open the push content files");
 
         push_content = octstr_create("");
+        if (add_preamble)
+            octstr_append(push_content, octstr_imm("the parser should discard this"));
         octstr_append(push_content, 
             bpos = make_part_delimiter(octstr_imm(boundary)));
+        /*octstr_append(push_content, octstr_imm("\r\n"));*/ /* Do we accept an additional 
+                                                          * clrf ? */
         octstr_append(push_content, pap_content);
         octstr_append(push_content, bpos);
         octstr_destroy(bpos);
         octstr_append(push_content, wap_content);
         octstr_append(push_content, 
             bcos = make_close_delimiter(octstr_imm(boundary)));
+        if (add_epilogue) {
+            octstr_append(push_content, octstr_imm("\r\n"));
+            octstr_append(push_content, octstr_imm("the parser should discard this"));
+        }
         octstr_destroy(bcos);
         octstr_destroy(pap_content);
         octstr_destroy(wap_content);
@@ -574,6 +631,13 @@
     info(0, "-a application id");
     info(0, "Define the client application that will handle the push. Any,"); 
     info(0, "ua, mms, nil and scrap accepted, default ua.");
+    info(0, "-n");
+    info(0, "if set, use numeric appid values instead of string ones. For");
+    info(0, "instance, '4' instead of 'mms.ua'. Default is off.");
+    info(0, "-s string");
+    info(0, "supply application id as a plain string. For instance"); 
+    info(0, "-s x-wap-application-id:mms.ua equals -a ua. Default is");
+    info(0, "x-wap-application-id:mms.ua.");
     info(0, "-b");
     info(0, "If true, send username/password in headers. Default false");
     info(0, "-v number");
@@ -598,6 +662,17 @@
     info(0, "Default: read components from files");
     info(0, "-t");
     info(0, "number of threads, maximum 1024, default 1");
+    info(0, "-B");
+    info(0, "accept binary push content. Default: off.");
+    info(0, "Binary content consist of hex numbers. In addition, crs, lfs and");
+    info(0, "spaces are accepted, and ignored.");
+    info(0, "-d value");
+    info(0, "set delimiter to be used. Accepted values crlf and lf. Default crlf.");
+    info(0, "-E");
+    info(0, "If set, add a hardcoded epilogue (epilogue is to be discarded anyway).");
+    info(0, "Default off.");
+    info(0, "-p");
+    info(0, "If set, add hardcoded preamble. Default is off.");
 }
 
 int main(int argc, char **argv)
@@ -614,7 +689,7 @@
     gwlib_init();
     num_threads = 1;
 
-    while ((opt = getopt(argc, argv, "Hhbv:qr:t:c:a:i:e:k:")) != EOF) {
+    while ((opt = getopt(argc, argv, "HhBbnEpv:qr:t:c:a:i:e:k:d:s:")) != EOF) {
         switch(opt) {
 	    case 'v':
 	        log_set_output_level(atoi(optarg));
@@ -652,7 +727,7 @@
                     octstr_compare(content_flag, octstr_imm("mms")) != 0 &&
                     octstr_compare(content_flag, octstr_imm("scrap")) != 0 &&
                     octstr_compare(content_flag, 
-                    octstr_imm("multipart")) != 0){
+                    octstr_imm("multipart")) != 0) {
 		        octstr_destroy(content_flag);
 		        error(0, "TEST_PPG: Content type not known");
 		        help();
@@ -674,14 +749,21 @@
            }
 	    break;
 
+            case 'n':
+                use_numeric = 1;
+            break;
+
+            case 's':
+                appid_string = octstr_create(optarg);
+                use_string = 1;
+            break;
+
 	    case 'e':
 		    content_transfer_encoding = octstr_create(optarg);
-            if (octstr_compare(content_transfer_encoding, 
-                               octstr_imm("base64")) != 0) {
+                if (octstr_compare(content_transfer_encoding, octstr_imm("base64")) != 0) {
 		        octstr_destroy(content_transfer_encoding);
 		        error(0, "TEST_PPG: unknown content transfer" 
-                      " encoding \"%s\"",
-			          octstr_get_cstr(content_transfer_encoding));
+                      " encoding \"%s\"", octstr_get_cstr(content_transfer_encoding));
 		        help();
                 exit(1);
 		    }
@@ -690,8 +772,7 @@
 	    case 'k':
 	        connection = octstr_create(optarg);
             if (octstr_compare(connection, octstr_imm("close")) != 0 && 
-                    octstr_compare(connection, 
-                        octstr_imm("keep-alive")) != 0) {
+                        octstr_compare(connection, octstr_imm("keep-alive")) != 0) {
 		        octstr_destroy(connection);
 		        error(0, "TEST_PPG: Connection-header unacceptable");
 		        help();
@@ -707,6 +788,29 @@
 	        use_headers = 1;
 	    break;
 
+            case 'B':
+                accept_binary = 1;
+            break;
+
+            case 'd':
+                delimiter = octstr_create(optarg);
+                if (octstr_compare(delimiter, octstr_imm("crlf")) != 0 &&
+                        octstr_compare(delimiter, octstr_imm("lf")) != 0) {
+                    octstr_destroy(delimiter);
+                    error(0, "illegal d value");
+                    help();
+                    exit(1);
+                }
+            break;
+
+            case 'E':
+                add_epilogue = 1;
+            break;
+
+            case 'p':
+                add_preamble = 1;
+            break;
+
 	    case '?':
 	    default:
 	        error(0, "TEST_PPG: Invalid option %c", opt);
@@ -730,6 +834,12 @@
     if (appid_flag == NULL)
         appid_flag = octstr_imm("ua");
 
+    if (appid_string == NULL)
+        appid_string = octstr_imm("x-wap-application-id: wml.ua");
+
+    if (delimiter == NULL)
+        delimiter = octstr_imm("crlf");
+
     if (use_hardcoded) {
         username = octstr_imm("troo");
         password = octstr_imm("far");
@@ -792,6 +902,7 @@
     octstr_destroy(password);
     octstr_destroy(push_url);
     octstr_destroy(connection);
+    octstr_destroy(delimiter);;
     counter_destroy(counter);
     gwlib_shutdown();
 
Index: wap/wsp_headers.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_headers.c,v
retrieving revision 1.6
diff -B -b -u -r1.6 wsp_headers.c
--- wap/wsp_headers.c	19 Oct 2002 10:07:39 -0000	1.6
+++ wap/wsp_headers.c	30 May 2003 10:32:07 -0000
@@ -250,7 +250,8 @@
     return convert_q_value(c);
 }
 
-/* Version-value is defined in 8.4.2.3 */
+/* Version-value is defined in 8.4.2.3. Encoding-Version uses coding
+ * defined in this chapter, see 8.4.2.70.  */
 static Octstr *unpack_version_value(long value)
 {
     Octstr *result;
@@ -269,6 +270,19 @@
     return result;
 }
 
+static Octstr *unpack_encoding_version(ParseContext *context)
+{
+    int ch;
+
+    ch = parse_get_char(context);
+    if (ch < 128) {
+        warning(0, "WSP: bad Encoding-Version value");
+        return NULL;
+    }
+
+    return unpack_version_value(((long) ch) - 128);
+}
+
 /* Called with the parse limit set to the end of the parameter data,
  * and decoded containing the unpacked header line so far.
  * Parameter is defined in 8.4.2.4. */
@@ -1155,6 +1169,10 @@
             decoded = unpack_disposition(context);
             break;
 
+        case WSP_HEADER_ENCODING_VERSION:
+            decoded = unpack_encoding_version(context);
+            break;
+
         default:
             if (headername) {
                 warning(0, "Did not expect value-length with "
@@ -1331,6 +1349,7 @@
 static int pack_transfer_encoding(Octstr *packet, Octstr *value);
 static int pack_uri(Octstr *packet, Octstr *value);
 static int pack_warning(Octstr *packet, Octstr *value);
+static int pack_version_value(Octstr *packet, Octstr *value);
 
 /* LIST is a comma-separated list such as is described in the "#rule"
  * entry of RFC2616 section 2.1. */
@@ -1396,10 +1415,11 @@
         { WSP_HEADER_WARNING, pack_warning, LIST },
         { WSP_HEADER_WWW_AUTHENTICATE, pack_challenge, BROKEN_LIST },
         { WSP_HEADER_CONTENT_DISPOSITION, pack_content_disposition, 0 },
-        { WSP_HEADER_PUSH_FLAG, pack_integer_string, 0},
-        { WSP_HEADER_X_WAP_CONTENT_URI, pack_uri, 0},
-        { WSP_HEADER_X_WAP_INITIATOR_URI, pack_uri, 0},
-        { WSP_HEADER_X_WAP_APPLICATION_ID, pack_integer_string, 0}
+        { WSP_HEADER_PUSH_FLAG, pack_integer_string, 0 },
+        { WSP_HEADER_X_WAP_CONTENT_URI, pack_uri, 0 },
+        { WSP_HEADER_X_WAP_INITIATOR_URI, pack_uri, 0 },
+        { WSP_HEADER_X_WAP_APPLICATION_ID, pack_integer_string, 0 },
+        { WSP_HEADER_ENCODING_VERSION, pack_version_value, 0 }
     };
 
 static Parameter *parm_create(Octstr *key, Octstr *value)
@@ -1743,7 +1763,7 @@
     return -1;
 }
 
-static void pack_version_value(Octstr *packed, Octstr *version)
+static int pack_version_value(Octstr *packed, Octstr *version)
 {
     long major, minor;
     long pos;
@@ -1763,10 +1783,11 @@
     }
 
     pack_short_integer(packed, major << 4 | minor);
-    return;
+    return 0;
 
 usetext:
     pack_text(packed, version);
+    return 0;
 }
 
 static int pack_constrained_value(Octstr *packed, Octstr *text, long value)
Index: wap/wsp_session.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_session.c,v
retrieving revision 1.13
diff -B -b -u -r1.13 wsp_session.c
--- wap/wsp_session.c	14 May 2002 11:05:08 -0000	1.13
+++ wap/wsp_session.c	30 May 2003 10:32:07 -0000
@@ -87,6 +87,10 @@
 static unsigned long next_wsp_session_id(void);
 
 static List *make_capabilities_reply(WSPMachine *m);
+static List *make_reply_headers(WSPMachine *m);
+static int is_default_version(WSPMachine *m);
+static int is_higher_version(WSPMachine *m);
+static int is_lower_version(WSPMachine *m);
 static Octstr *make_connectreply_pdu(WSPMachine *m);
 static Octstr *make_resume_reply_pdu(WSPMachine *m, List *headers);
 static WSP_PDU *make_confirmedpush_pdu(WAPEvent *e);
@@ -946,11 +950,91 @@
 	return caps;
 }
 
+static int is_default_version(WSPMachine *m)
+{
+    Octstr *request_version;
+
+    request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+    if (request_version == NULL) {
+        return 1;
+    } else {
+        octstr_destroy(request_version);
+        return 0;
+    }
+}
+
+static int is_higher_version(WSPMachine *m)
+{
+    Octstr *request_version;
+
+    request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+    if (request_version && octstr_compare(request_version, octstr_imm("1.1")) != 0 &&
+            octstr_compare(request_version, octstr_imm("1.2")) != 0 &&
+            octstr_compare(request_version, octstr_imm("1.3")) != 0) {
+        octstr_destroy(request_version);
+        return 1;
+    } else {
+        octstr_destroy(request_version);
+        return 0;
+    }
+}
+
+static int is_lower_version(WSPMachine *m)
+{
+    Octstr *request_version;
+
+    request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+    if (request_version && (octstr_compare(request_version, octstr_imm("1.1")) == 0 ||
+            octstr_compare(request_version, octstr_imm("1.2")) == 0)) {
+        octstr_destroy(request_version);
+        return 1;        
+    } else {
+        octstr_destroy(request_version);
+        return 0;
+    }
+}
+
+static List *make_reply_headers(WSPMachine *m)
+{
+    List *headers;
+    Octstr *encoding_version;
+    Octstr *request_version;
+
+    /* Add all server wsp level hop-by-hop headers. Currently only 
+     * Encoding-Version, as defined by wsp, chapter 8.4.2.70. 
+     * What headers belong to which version is defined in appendix A,
+     * table 39.. 
+    encoding_version = request_version = NULL;
+     * Essentially, if the client sends us an Encoding-Version
+     * higher than ours (1.3) we send our version number to it,
+     * if it is lower, we left version number intact. */
+    /* First the case that we have no Encoding-Version header at all. 
+     * This case we must assume that the client supports version 1.2
+     * or lower. */
+    if (is_default_version(m)) {
+        encoding_version = octstr_create("1.2");
+    } else if (is_higher_version(m)) {
+        encoding_version = octstr_create("1.3");
+    } else if (is_lower_version(m)) {
+        request_version = http_header_value(m->http_headers, octstr_imm("Encoding-Version"));
+        encoding_version = octstr_duplicate(request_version);
+        octstr_destroy(request_version);
+    }  else {   
+        encoding_version = octstr_create("1.3");
+    }
+
+    headers = http_create_empty_headers();
+    http_header_add(headers, "Encoding-Version", octstr_get_cstr(encoding_version));
+    octstr_destroy(encoding_version);
+
+    return headers;
+}
 
 static Octstr *make_connectreply_pdu(WSPMachine *m) {
 	WSP_PDU *pdu;
 	Octstr *os;
 	List *caps;
+        List *reply_headers;
 	
 	pdu = wsp_pdu_create(ConnectReply);
 
@@ -959,7 +1043,10 @@
 	caps = make_capabilities_reply(m);
 	pdu->u.ConnectReply.capabilities = wsp_cap_pack_list(caps);
 	wsp_cap_destroy_list(caps);
-	pdu->u.ConnectReply.headers = NULL;
+
+        reply_headers = make_reply_headers(m);
+	pdu->u.ConnectReply.headers = wsp_headers_pack(reply_headers, 0);
+        http_destroy_headers(reply_headers);
 	
 	os = wsp_pdu_pack(pdu);
 	wsp_pdu_destroy(pdu);
Index: wap/wsp_strings.def
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_strings.def,v
retrieving revision 1.6
diff -B -b -u -r1.6 wsp_strings.def
--- wap/wsp_strings.def	4 Sep 2002 09:16:31 -0000	1.6
+++ wap/wsp_strings.def	30 May 2003 10:32:08 -0000
@@ -109,7 +109,7 @@
 NSTRING("Encoding-Version", WSP_HEADER_ENCODING_VERSION)
 )
 
-/* Table 40. Content Type Assignments */
+/* Table 40. Content Type Assignments. Only to wsp version 1.3. */
 LINEAR(content_type,
 STRING("*/*")
 STRING("text/*")
@@ -166,14 +166,14 @@
 STRING("application/vnd.wap.sia")
 STRING("text/vnd.wap.connectivity-xml")
 STRING("application/vnd.wap.connectivity-wbxml")
-STRING("application/pkcs7-mime")
+/*STRING("application/pkcs7-mime")
 STRING("application/vnd.wap.hashed-certificate")
 STRING("application/vnd.wap.signed-certificate")
 STRING("application/vnd.wap.cert-response")
 STRING("application/xhtml+xml")
 STRING("application/wml+xml")
 STRING("text/css")
-STRING("application/vnd.wap.mms-message") 
+STRING("application/vnd.wap.mms-message")*/ 
 )
 
 /* Table 42, Character Set Assignment (partial) */
@@ -465,6 +465,22 @@
 ASSIGN("mms.ua", 0x04) 
 ASSIGN("push.syncml", 0x05) 
 ASSIGN("loc.ua", 0x06) 
+ASSIGN("syncml.dm", 0x07)
+ASSIGN("drm.ua", 0x08)
+ASSIGN("emn.ua", 0x09)
+ASSIGN("wv.ua", 0x0A)
+ASSIGN("x-wap-microsoft:localcontent.ua", 0x8000)
+ASSIGN("x-wap-microsoft:IMclient.ua", 0x8001)
+ASSIGN("x-wap-docomo:imode.mail.ua", 0x8002)
+ASSIGN("x-wap-docomo:imode.mr.ua", 0x8003)
+ASSIGN("x-wap-docomo:imode.mf.ua", 0x8004)
+ASSIGN("x-motorola:location.ua", 0x8005)
+ASSIGN("x-motorola:now.ua", 0x8006)
+ASSIGN("x-motorola:otaprov.ua", 0x8007)
+ASSIGN("x-motorola:browser.ua", 0x8008)
+ASSIGN("x-motorola:splash.ua", 0x8009)
+ASSIGN("x-wap-nai:mvsw.command", 0x800B)
+ASSIGN("x-wap-openvawe:iota.ua", 0x8010)
 )
 
 /**** More preprocessor magic ****/
Index: wap/wsp_unit.c
===================================================================
RCS file: /home/cvs/gateway/wap/wsp_unit.c,v
retrieving revision 1.12
diff -B -b -u -r1.12 wsp_unit.c
--- wap/wsp_unit.c	13 Feb 2003 10:34:09 -0000	1.12
+++ wap/wsp_unit.c	30 May 2003 10:32:08 -0000
@@ -192,7 +192,10 @@
 
 /*
  * We do not set TUnitData.ind's SMS-specific fields here, because we do not
- * support sending results to the phone over SMS.
+ * support sending results to the phone over SMS. Wsp, chapter 8.4.1 states
+ * that "that each peer entity is always associated with an encoding version.".
+ * So we add Encoding-Version when we are sending something to the client.
+ * (This includes push, which is not directly mentioned in chapter 8.4.2.70). 
  */
 static WAPEvent *pack_into_result_datagram(WAPEvent *event) {
 	WAPEvent *datagram;
@@ -204,6 +207,8 @@
 	gw_assert(event->type == S_Unit_MethodResult_Req);
 	p = &event->u.S_Unit_MethodResult_Req;
 
+        http_header_add(p->response_headers, "Encoding-Version", "1.3");
+
 	pdu = wsp_pdu_create(Reply);
 	pdu->u.Reply.status = wsp_convert_http_status_to_wsp_status(p->status);
 	pdu->u.Reply.headers = wsp_headers_pack(p->response_headers, 1);
@@ -236,6 +241,10 @@
 
         gw_assert(event->type == S_Unit_Push_Req);
         debug("wap.wsp.unit", 0, "WSP_UNIT: Connectionless push accepted");
+
+        http_header_add(event->u.S_Unit_Push_Req.push_headers, 
+                        "Encoding-Version", "1.3");
+
         pdu = wsp_pdu_create(Push);
 	pdu->u.Push.headers = wsp_headers_pack(
             event->u.S_Unit_Push_Req.push_headers, 1);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.