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