--- /dev/null
+commit b342385531c18b8afb42db64c7a38d7879668566
+Author: Alessio Caiazza <nolith@abisso.org>
+Date: Fri May 16 12:53:15 2014 +0200
+
+ jsoninfo: HTTP headers with CORS (if requested)
+
+ The new "httpheaders" parameter prepends HTTP headers to the reply.
+ If not set it will default to "no" and have the same behaviour as before.
+ Cross-origin resource sharing headers (CORS) are included in reply allowing the
+ json retrieval by javascript applications not served by olsrd itself.
+ This will allow to easily develop js applications running directly in the
+ browser.
+
+ Reviewed-by: Ferry Huberts <ferry.huberts@pelagic.nl>
+
+diff --git a/lib/jsoninfo/README_JSONINFO b/lib/jsoninfo/README_JSONINFO
+index 709c975..8311ade 100644
+--- a/lib/jsoninfo/README_JSONINFO
++++ b/lib/jsoninfo/README_JSONINFO
+@@ -73,6 +73,14 @@ LoadPlugin "olsrd_jsoninfo.so.0.0"
+ # if you set it to 0.0.0.0, it will accept all connections
+ #PlParam "accept" "0.0.0.0"
+
++ # The "httpheaders" parameter prepends HTTP headers to the reply.
++ # If not set it will default to "no" and have the same behaviour as before.
++ # Among with a minimal set of headers also Cross-origin resource sharing
++ # headers (CORS) are included in reply allowing the json retrieval by
++ # javascript applications not served by olsrd itself.
++ # You can enable it uncommenting the following line:
++ #PlParam "httpheaders" "yes"
++
+ # specify a UUID for this node to track it for debugging
+ #PlParam "UUIDFile" "/etc/olsrd/olsrd.uuid"
+ }
+diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.c b/lib/jsoninfo/src/olsrd_jsoninfo.c
+index 817c64a..f29a37c 100644
+--- a/lib/jsoninfo/src/olsrd_jsoninfo.c
++++ b/lib/jsoninfo/src/olsrd_jsoninfo.c
+@@ -96,6 +96,9 @@
+
+ static int ipc_socket;
+
++/* Response types */
++#define HTTP_200 "HTTP/1.1 200 OK"
++
+ /* IPC initialization function */
+ static int plugin_ipc_init(void);
+
+@@ -126,6 +129,18 @@ static void ipc_print_interfaces(struct autobuf *);
+ static void ipc_print_plugins(struct autobuf *);
+ static void ipc_print_olsrd_conf(struct autobuf *abuf);
+
++static size_t build_http_header(const char *status, const char *mime,
++ uint32_t msgsize, char *buf, uint32_t bufsize);
++
++/*
++ * this is the size of the buffer used for build_http_header
++ * the amount of data written into the buffer will be less than
++ * 400 bytes approximatively.
++ * The size may vary because the Content-Length header contains
++ * the length of the json data
++ */
++#define MAX_HTTPHEADER_SIZE 512
++
+ #define TXT_IPC_BUFSIZE 256
+
+ /* these provide all of the runtime status info */
+@@ -1282,6 +1297,9 @@ static void
+ send_info(unsigned int send_what, int the_socket)
+ {
+ struct autobuf abuf;
++ size_t header_len = 0;
++ char header_buf[MAX_HTTPHEADER_SIZE];
++ const char *content_type = "application/json";
+
+ /* global variables for tracking when to put a comma in for JSON */
+ entrynumber[0] = 0;
+@@ -1320,12 +1338,17 @@ send_info(unsigned int send_what, int the_socket)
+ ipc_print_olsrd_conf(&abuf);
+ }
+
+- outbuffer[outbuffer_count] = olsr_malloc(abuf.len, "txt output buffer");
+- outbuffer_size[outbuffer_count] = abuf.len;
++ if(http_headers) {
++ header_len = build_http_header(HTTP_200, content_type, abuf.len, header_buf, sizeof(header_buf));
++ }
++
++ outbuffer[outbuffer_count] = olsr_malloc(header_len + abuf.len, "json output buffer");
++ outbuffer_size[outbuffer_count] = header_len + abuf.len;
+ outbuffer_written[outbuffer_count] = 0;
+ outbuffer_socket[outbuffer_count] = the_socket;
+
+- memcpy(outbuffer[outbuffer_count], abuf.buf, abuf.len);
++ memcpy(outbuffer[outbuffer_count], header_buf, header_len);
++ memcpy((outbuffer[outbuffer_count]) + header_len, abuf.buf, abuf.len);
+ outbuffer_count++;
+
+ if (outbuffer_count == 1) {
+@@ -1340,6 +1363,53 @@ send_info(unsigned int send_what, int the_socket)
+ abuf_free(&abuf);
+ }
+
++static size_t
++build_http_header(const char *status, const char *mime, uint32_t msgsize,
++ char *buf, uint32_t bufsize)
++{
++ time_t currtime;
++ size_t size;
++
++ size = snprintf(buf, bufsize, "%s\r\n", status);
++
++ /* Date */
++ time(&currtime);
++ size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
++
++ /* Server version */
++ size += snprintf(&buf[size], bufsize - size, "Server: OLSRD JSONInfo plugin\r\n");
++
++ /* connection-type */
++ size += snprintf(&buf[size], bufsize - size, "Connection: closed\r\n");
++
++ /* MIME type */
++ if(mime != NULL) {
++ size += snprintf(&buf[size], bufsize - size, "Content-type: %s\r\n", mime);
++ }
++
++ /* CORS data */
++ /**No needs to be strict here, access control is based on source IP*/
++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Origin: *\r\n");
++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n");
++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Headers: Accept, Origin, X-Requested-With\r\n");
++ size += snprintf(&buf[size], bufsize - size, "Access-Control-Max-Age: 1728000\r\n");
++
++ /* Content length */
++ if (msgsize > 0) {
++ size += snprintf(&buf[size], bufsize - size, "Content-length: %i\r\n", msgsize);
++ }
++
++ /* Cache-control
++ * No caching dynamic pages
++ */
++ size += snprintf(&buf[size], bufsize - size, "Cache-Control: no-cache\r\n");
++
++ /* End header */
++ size += snprintf(&buf[size], bufsize - size, "\r\n");
++
++ return size;
++}
++
+ /*
+ * Local Variables:
+ * mode: c
+diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.h b/lib/jsoninfo/src/olsrd_jsoninfo.h
+index 8478f62..56acb70 100644
+--- a/lib/jsoninfo/src/olsrd_jsoninfo.h
++++ b/lib/jsoninfo/src/olsrd_jsoninfo.h
+@@ -62,6 +62,7 @@ extern union olsr_ip_addr jsoninfo_accept_ip;
+ extern union olsr_ip_addr jsoninfo_listen_ip;
+ extern int ipc_port;
+ extern int nompr;
++extern bool http_headers;
+
+ int olsrd_plugin_interface_version(void);
+ int olsrd_plugin_init(void);
+diff --git a/lib/jsoninfo/src/olsrd_plugin.c b/lib/jsoninfo/src/olsrd_plugin.c
+index 36550a8..03aa45f 100644
+--- a/lib/jsoninfo/src/olsrd_plugin.c
++++ b/lib/jsoninfo/src/olsrd_plugin.c
+@@ -64,6 +64,7 @@ union olsr_ip_addr jsoninfo_accept_ip;
+ union olsr_ip_addr jsoninfo_listen_ip;
+ int ipc_port;
+ int nompr;
++bool http_headers;
+
+ static void my_init(void) __attribute__ ((constructor));
+ static void my_fini(void) __attribute__ ((destructor));
+@@ -79,6 +80,7 @@ my_init(void)
+
+ /* defaults for parameters */
+ ipc_port = 9090;
++ http_headers = false;
+ if (olsr_cnf->ip_version == AF_INET) {
+ jsoninfo_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
+ jsoninfo_listen_ip.v4.s_addr = htonl(INADDR_ANY);
+@@ -120,11 +122,26 @@ store_string(const char *value, void *data, set_plugin_parameter_addon addon __a
+ return 0;
+ }
+
++static int
++store_boolean(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused)))
++{
++ bool *dest = data;
++ if(strcmp(value, "yes") == 0)
++ *dest = true;
++ else if (strcmp(value, "no") == 0)
++ *dest = false;
++ else
++ return 1; //error
++
++ return 0;
++}
++
+ static const struct olsrd_plugin_parameters plugin_parameters[] = {
+ {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port},
+ {.name = "accept",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_accept_ip},
+ {.name = "listen",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_listen_ip},
+ {.name = "uuidfile",.set_plugin_parameter = &store_string,.data = uuidfile},
++ {.name = "httpheaders",.set_plugin_parameter = &store_boolean,.data = &http_headers},
+ };
+
+ void