Index: gwlib/http.c
===================================================================
--- gwlib/http.c	(revision 5278)
+++ gwlib/http.c	(working copy)
@@ -658,7 +658,7 @@
  * Order is sequenced by the enum in the header
  */
 static char *http_methods[] = {
-    "GET", "POST", "HEAD"
+    "GET", "POST", "HEAD", "PUT"
 };
 
 /*
@@ -1603,7 +1603,7 @@
     char buf[128];    
     Octstr *request = NULL;
 
-    if (trans->method == HTTP_METHOD_POST) {
+    if (trans->method == HTTP_METHOD_POST || trans->method == HTTP_METHOD_PUT) {
         /* 
          * Add a Content-Length header.  Override an existing one, if
          * necessary.  We must have an accurate one in order to use the
@@ -2222,6 +2222,8 @@
         *method = HTTP_METHOD_POST;
     else if (octstr_compare(method_str, octstr_imm("HEAD")) == 0)
         *method = HTTP_METHOD_HEAD;
+    else if (octstr_compare(method_str, octstr_imm("PUT")) == 0)
+        *method = HTTP_METHOD_PUT;
     else
         goto error;
 
@@ -2530,59 +2532,47 @@
 
 
 /*
- * Parse CGI variables from the path given in a GET. Return a list
- * of HTTPCGIvar pointers. Modify the url so that the variables are
- * removed.
+ * Parse CGI variables in <pairs> (query string in url or request body)
+ * Expected format: var1=value1&var2&var3=value3...
+ * Append HTTPCGIvar pointers to supplied list
  */
-static List *parse_cgivars(Octstr *url)
+static void parse_cgivars(List *cgivars, Octstr *pairs)
 {
     HTTPCGIVar *v;
-    List *list;
-    int query, et, equals;
-    Octstr *arg, *args;
+    Octstr *pair;
+    long ampersand, equal, start;
+    long pairs_len = octstr_len(pairs);
 
-    query = octstr_search_char(url, '?', 0);
-    if (query == -1)
-        return gwlist_create();
+    for (start = 0; start < pairs_len; start = ampersand + 1) {
+        ampersand = octstr_search_char(pairs, '&', start);
+        if (ampersand == -1)
+            ampersand = pairs_len;
+        pair = octstr_copy(pairs, start, ampersand - start);
 
-    args = octstr_copy(url, query + 1, octstr_len(url));
-    octstr_truncate(url, query);
+        equal = octstr_search_char(pair, '=', 0);
+        if (equal == -1)
+            equal = octstr_len(pair);
 
-    list = gwlist_create();
-
-    while (octstr_len(args) > 0) {
-        et = octstr_search_char(args, '&', 0);
-        if (et == -1)
-            et = octstr_len(args);
-        arg = octstr_copy(args, 0, et);
-        octstr_delete(args, 0, et + 1);
-
-        equals = octstr_search_char(arg, '=', 0);
-        if (equals == -1)
-            equals = octstr_len(arg);
-
         v = gw_malloc(sizeof(HTTPCGIVar));
-        v->name = octstr_copy(arg, 0, equals);
-        v->value = octstr_copy(arg, equals + 1, octstr_len(arg));
+        v->name = octstr_copy(pair, 0, equal);
+        v->value = octstr_copy(pair, equal + 1, octstr_len(pair));
         octstr_url_decode(v->name);
         octstr_url_decode(v->value);
+        gwlist_append(cgivars, v);
 
-        octstr_destroy(arg);
-
-        gwlist_append(list, v);
+        octstr_destroy(pair);
     }
-    octstr_destroy(args);
-
-    return list;
 }
 
 
-HTTPClient *http_accept_request(int port, Octstr **client_ip, Octstr **url, 
-    	    	    	    	List **headers, Octstr **body, 
+HTTPClient *http_accept_request(int port, Octstr **client_ip, Octstr **url,
+                                List **headers, Octstr **body,
                                 List **cgivars)
 {
     HTTPClient *client;
-    
+    Octstr *query, *content_type, *charset;
+    int question_mark;
+
     do {
         client = port_get_request(port);
         if (client == NULL) {
@@ -2596,33 +2586,58 @@
             client = NULL;
         }
     } while(client == NULL);
-    
+
+    debug("gwlib.http", 0, "HTTP: Got %s request with url='%s' and body='%s'",
+          http_method2name(client->method), octstr_get_cstr(client->url), octstr_get_cstr(client->request->body));
+
     *client_ip = octstr_duplicate(client->ip);
     *url = client->url;
     *headers = client->request->headers;
     *body = client->request->body;
-    *cgivars = parse_cgivars(client->url);
-    
-    if (client->method != HTTP_METHOD_POST) {
+    *cgivars = gwlist_create();
+
+    /* is there a query string in the url? */
+    question_mark = octstr_search_char(*url, '?', 0);
+    if (question_mark >= 0) {
+        /* parse the query string */
+        query = octstr_copy(*url, question_mark + 1, octstr_len(*url));
+        parse_cgivars(*cgivars, query);
+        octstr_destroy(query);
+
+        /* remove query string from url */
+        octstr_truncate(*url, question_mark);
+    }
+
+    if (client->method == HTTP_METHOD_POST || client->method == HTTP_METHOD_PUT) {
+        if (octstr_len(*body) > 0) {
+            http_header_get_content_type(*headers, &content_type, &charset);
+            if (octstr_str_compare(content_type, "application/x-www-form-urlencoded") == 0) {
+                /* parse the body */
+                parse_cgivars(*cgivars, *body);
+            }
+            octstr_destroy(content_type);
+            octstr_destroy(charset);
+        }
+    } else {
         octstr_destroy(*body);
         *body = NULL;
     }
-    
+
     client->persistent_conn = client_is_persistent(client->request->headers,
                                                    client->use_version_1_0);
-    
+
     client->url = NULL;
     client->request->headers = NULL;
     client->request->body = NULL;
     entity_destroy(client->request);
     client->request = NULL;
-    
+
     return client;
 }
 
 /*
  * The http_send_reply(...) uses this function to determinate the
- * reason pahrase for a status code.
+ * reason phrase for a status code.
  */
 static const char *http_reason_phrase(int status)
 {
@@ -3646,6 +3661,9 @@
     else if (octstr_str_compare(method, "HEAD") == 0) {
         return HTTP_METHOD_HEAD;
     } 
+    else if (octstr_str_compare(method, "PUT") == 0) {
+        return HTTP_METHOD_PUT;
+    }
 
     return -1;
 }
@@ -3653,7 +3671,7 @@
 
 char *http_method2name(int method)
 {
-    gw_assert(method > 0 && method <= 3);
+    gw_assert(method >= HTTP_METHOD_GET && method <= HTTP_METHOD_PUT);
 
     return http_methods[method-1];
 }
Index: gwlib/http.h
===================================================================
--- gwlib/http.h	(revision 5278)
+++ gwlib/http.h	(working copy)
@@ -200,9 +200,10 @@
  * probably should be.
  */
 enum {
-	HTTP_METHOD_GET = 1,
+	HTTP_METHOD_GET  = 1,
 	HTTP_METHOD_POST = 2,
-	HTTP_METHOD_HEAD = 3
+	HTTP_METHOD_HEAD = 3,
+	HTTP_METHOD_PUT  = 4
 };
 
 /*
