This patch use wget to download PAC file of the  network. It
also can support chunked encoding.
---
 src/mozjs.c |  205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 201 insertions(+), 4 deletions(-)

diff --git a/src/mozjs.c b/src/mozjs.c
index ab4606e..b575a29 100644
--- a/src/mozjs.c
+++ b/src/mozjs.c
@@ -37,12 +37,201 @@
 
 #include <jsapi.h>
 
+#include <gweb/gweb.h>
+
 #include "javascript.h"
 
 #include "pacrunner.h"
 
+#define MAX_PAC_LEN    102400
+
+struct web_data {
+       GWeb *web;
+       char buf[MAX_PAC_LEN];
+       int len;
+};
+
 static char *current_interface = NULL;
 static char *current_pacfile = NULL;
+static struct web_data *current_web = NULL;
+
+static char *get_line(char *buf, const char *last)
+{
+       char *ptr = buf;
+
+       if (ptr == NULL)
+               return NULL;
+
+       while ((*ptr != '\n') && (*ptr != '\0') && (ptr < last))
+               ptr++;
+
+       if (ptr == last)
+               return NULL;
+
+       *ptr = '\0';
+       ptr++;
+
+       return ptr;
+}
+
+static void free_web_data(struct web_data *web_data)
+{
+       if (web_data != NULL) {
+               if (web_data->web != NULL)
+                       g_web_unref(web_data->web);
+
+               web_data->web = NULL;
+
+               g_free(web_data);
+       }
+}
+
+static void decode_chunked(char *buf, const char *last)
+{
+       char *ptr, *next_line, *line;
+       int skip_next, ret;
+       unsigned int counter;
+
+       next_line = buf;
+       ptr = current_pacfile;
+       skip_next = 0;
+
+       do {
+               line = next_line;
+               next_line = get_line(line, last);
+
+               if (skip_next != 0) {
+                       line = next_line;
+                       next_line = get_line(line, last);
+               }
+               skip_next = 1;
+
+               ret = sscanf(line, "%x", &counter);
+               if ((ret != 1) || (counter == 0) || (next_line == NULL))
+                       break;
+               if ((next_line + counter) > last)
+                       break;
+
+               memcpy(ptr, next_line, counter);
+               ptr += counter;
+
+               next_line = next_line + counter;
+       } while (next_line != NULL);
+
+       ptr++;
+       *ptr = 0;
+}
+
+static void web_result(uint16_t status, gpointer user_data)
+{
+       struct web_data *web_data = user_data;
+       char *last, *next_line, *line;
+       int ret, len;
+       unsigned long int http_status;
+       gchar *str;
+       gboolean use_chunked;
+
+       if ((status == 200) && (web_data != NULL) && (web_data->len > 0)) {
+               last = web_data->buf + web_data->len;
+               line = web_data->buf;
+
+               next_line = get_line(line, last);
+               if (next_line == NULL)
+                       goto done;
+
+               http_status = 0;
+               ret = sscanf(line, "HTTP/1.%*d %lu", &http_status);
+               if ((ret != 1) || (http_status != 200))
+                       goto done;
+
+               use_chunked = FALSE;
+               do {
+                       line = next_line;
+                       next_line = get_line(line, last);
+
+                       if (next_line == NULL)
+                               break;
+
+                       if ((strcmp(line, "\r") == 0) || (*line == '\0')) {
+                               len = web_data->len -
+                                               (next_line - web_data->buf);
+                               if (len > 0) {
+                                       current_pacfile = g_try_malloc(len+1);
+                                       if (use_chunked)
+                                               decode_chunked(next_line, last);
+                                       else {
+                                               memcpy(current_pacfile,
+                                                               next_line, len);
+                                               current_pacfile[len] = 0;
+                                       }
+                               }
+                               break;
+                       }
+                       str = g_strrstr(line, "Transfer-Encoding: chunked");
+                       if (str != NULL)
+                               use_chunked = TRUE;;
+               } while (1);
+       }
+done:
+       free_web_data(web_data);
+
+       current_web = NULL;
+}
+
+static void web_received_data(const char *buf, int len, gpointer user_data)
+{
+       struct web_data *web_data = user_data;
+       char *ptr;
+
+       if (web_data == NULL)
+               return;
+
+       if ((web_data->len + len) >= MAX_PAC_LEN)
+               return;
+
+       ptr = (web_data->buf + web_data->len);
+
+       memcpy(ptr, buf, len);
+
+       web_data->len += len;
+}
+
+static int pacrunner_load_from_network(const char *interface, const char *url)
+{
+       int index = 0;
+
+       if (current_web != NULL)
+               free_web_data(current_web);
+
+       current_web = NULL;
+
+       current_web = g_try_new0(struct web_data, 1);
+
+       if (current_web == NULL) {
+               pacrunner_error("failed to web service\n");
+               return -ENOMEM;
+       }
+
+       current_web->web = g_web_new(index);
+       if (current_web->web == NULL) {
+               g_free(current_web);
+               current_web = NULL;
+               pacrunner_error("failed to web service\n");
+               return -ENOMEM;
+       }
+
+       if (g_web_request(current_web->web, G_WEB_METHOD_GET,
+                               url, web_received_data,
+                               web_result, current_web) == 0) {
+               free_web_data(current_web);
+               current_web = NULL;
+
+               pacrunner_error("failed to start request\n");
+               return -EIO;
+       }
+
+       return 0;
+}
 
 int __pacrunner_mozjs_load(const char *interface, const char *url)
 {
@@ -62,7 +251,7 @@ int __pacrunner_mozjs_load(const char *interface, const char 
*url)
        current_pacfile = NULL;
 
        if (g_str_has_prefix(url, "file://") == FALSE)
-               return -EINVAL;
+               return pacrunner_load_from_network(interface, url);
 
        filename = url + 7;
 
@@ -101,6 +290,12 @@ void __pacrunner_mozjs_clear(void)
 
        g_free(current_pacfile);
        current_pacfile = NULL;
+
+       if (current_web != NULL)
+               free_web_data(current_web);
+
+       current_web = NULL;
+
 }
 
 static int getaddr(const char *node, char *host, size_t hostlen)
@@ -262,12 +457,14 @@ void __pacrunner_mozjs_cleanup(void)
 {
        DBG("");
 
-       g_free(current_interface);
-       current_interface = NULL;
-
        g_free(current_pacfile);
        current_pacfile = NULL;
 
+       if (current_web != NULL)
+               free_web_data(current_web);
+
+       current_web = NULL;
+
        //JS_DestroyContext(jsctx);
        JS_DestroyRuntime(jsrun);
 }
-- 
1.6.2.5

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to