--- main/manager.c.orig 2009-01-19 20:56:27.000000000 -0500
+++ main/manager.c      2009-01-19 17:01:55.000000000 -0500
@@ -2163,7 +2163,7 @@
        int format = AST_FORMAT_SLINEAR;

        pthread_t th;
-       if (!ast_strlen_zero(name)) {
+       if (ast_strlen_zero(name)) {
                astman_send_error(s, m, "Channel not specified");
                return 0;
        }
@@ -3198,12 +3198,14 @@
        FORMAT_RAW,
        FORMAT_HTML,
        FORMAT_XML,
+       FORMAT_JSON,
 };

 static char *contenttype[] = {
-       [FORMAT_RAW] = "plain",
-       [FORMAT_HTML] = "html",
-       [FORMAT_XML] =  "xml",
+       [FORMAT_RAW] = "text/plain",
+       [FORMAT_HTML] = "text/html",
+       [FORMAT_XML] = "text/xml",
+       [FORMAT_JSON] = "text/plain",
 };

 /*!
@@ -3423,7 +3425,9 @@
        const char *objtype = NULL;
        int in_data = 0;        /* parsing data */
        int inobj = 0;
+       int html = (format == FORMAT_HTML);
        int xml = (format == FORMAT_XML);
+       int json = (format == FORMAT_JSON);
        struct variable_count *vc = NULL;
        struct ao2_container *vco = NULL;

@@ -3447,12 +3451,21 @@
                ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
                if (ast_strlen_zero(val)) {
                        if (in_data) { /* close data */
-                               ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
+                               if (html)
+                                       ast_str_append(out, 0, "</td></tr>\n");
+                               else if (xml)
+                                       ast_str_append(out, 0, "'");
+                               else if (json)
+                                       ast_str_append(out, 0, "\"");
                                in_data = 0;
                        }
                        if (inobj) {
-                               ast_str_append(out, 0, xml ? " /></response>\n" :
-                                       "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+                               if (html)
+                                       ast_str_append(out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+                               else if (xml)
+                                       ast_str_append(out, 0, " /></response>\n");
+                               else if (json)
+                                       ast_str_append(out, 0, "},");
                                inobj = 0;
                                ao2_ref(vco, -1);
                                vco = NULL;
@@ -3475,16 +3488,23 @@
                }

                if (!inobj) {
-                       if (xml)
-                               ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
-                       else
+                       if (html)
                                ast_str_append(out, 0, "<body>\n");
+                       else if (xml)
+                               ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
+                       else if (json)
+                               ast_str_append(out, 0, "{\"id\":\"%s\",\"type\":\"%s\"", dest, objtype);
                        vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
                        inobj = 1;
                }

                if (!in_data) { /* build appropriate line start */
-                       ast_str_append(out, 0, xml ? " " : "<tr><td>");
+                       if (html)
+                               ast_str_append(out, 0, "<tr><td>");
+                       else if (xml)
+                               ast_str_append(out, 0, " ");
+                       else if (json)
+                               ast_str_append(out, 0, ",\"");
                        if ((vc = ao2_find(vco, var, 0)))
                                vc->count++;
                        else {
@@ -3494,23 +3514,47 @@
                                vc->count = 1;
                                ao2_link(vco, vc);
                        }
-                       xml_copy_escape(out, var, xml ? 1 | 2 : 0);
+                       xml_copy_escape(out, var, xml || json ? 1 | 2 : 0);
                        if (vc->count > 1)
                                ast_str_append(out, 0, "-%d", vc->count);
                        ao2_ref(vc, -1);
-                       ast_str_append(out, 0, xml ? "='" : "</td><td>");
+                       if (html)
+                               ast_str_append(out, 0, "</td><td>");
+                       else if (xml)
+                               ast_str_append(out, 0, "='");
+                       else if (json)
+                               ast_str_append(out, 0, "\":\"");
                        if (!strcmp(var, "Opaque-data"))
                                in_data = 1;
                }
-               xml_copy_escape(out, val, 0);   /* data field */
-               if (!in_data)
-                       ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
+               /* data field */
+               if (json)
+                       ast_str_append(out, 0, val);
                else
-                       ast_str_append(out, 0, xml ? "\n" : "<br>\n");
+                       xml_copy_escape(out, val, 0);
+               if (!in_data) {
+                       if (html)
+                               ast_str_append(out, 0, "</td></tr>\n");
+                       else if (xml)
+                               ast_str_append(out, 0, "'");
+                       else if (json)
+                               ast_str_append(out, 0, "\"");
+               } else {
+                       if (html)
+                               ast_str_append(out, 0, "<br>\n");
+                       else if (xml)
+                               ast_str_append(out, 0, "\n");
+                       else if (json)
+                               ast_str_append(out, 0, "\n");
+               }
        }
        if (inobj) {
-               ast_str_append(out, 0, xml ? " /></response>\n" :
-                       "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+               if (html)
+                       ast_str_append(out, 0, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
+               else if (xml)
+                       ast_str_append(out, 0, " /></response>\n");
+               else if (json)
+                       ast_str_append(out, 0, "}");
                ao2_ref(vco, -1);
        }
 }
@@ -3597,7 +3641,7 @@
        }

        ast_str_append(&out, 0,
-                      "Content-type: text/%s\r\n"
+                      "Content-type: %s\r\n"
                       "Cache-Control: no-cache;\r\n"
                       "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n"
                       "\r\n",
@@ -3606,6 +3650,8 @@

        if (format == FORMAT_XML) {
                ast_str_append(&out, 0, "<ajax-response>\n");
+       } else if (format == FORMAT_JSON) {
+               ast_str_append(&out, 0, "[");
        } else if (format == FORMAT_HTML) {

 #define ROW_FMT        "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
@@ -3626,13 +3672,13 @@

                if (l) {
                        if ((buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, 0))) {
-                               if (format == FORMAT_XML || format == FORMAT_HTML)
+                               if (format == FORMAT_XML || format == FORMAT_HTML || format == FORMAT_JSON)
                                        xml_translate(&out, buf, params, format);
                                else
                                        ast_str_append(&out, 0, "%s", buf);
                                munmap(buf, l);
                        }
-               } else if (format == FORMAT_XML || format == FORMAT_HTML) {
+               } else if (format == FORMAT_XML || format == FORMAT_HTML || format == FORMAT_JSON) {
                        xml_translate(&out, "", params, format);
                }
                fclose(s->f);
@@ -3642,6 +3688,8 @@

        if (format == FORMAT_XML) {
                ast_str_append(&out, 0, "</ajax-response>\n");
+       } else if (format == FORMAT_JSON) {
+               ast_str_append(&out, 0, "0]");
        } else if (format == FORMAT_HTML)
                ast_str_append(&out, 0, "</table></body>\r\n");

@@ -3681,6 +3729,11 @@
        return generic_http_callback(FORMAT_XML, &ser->requestor, uri, params, status, title, contentlength);
 }

+static struct ast_str *mjson_http_callback(struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
+{
+       return generic_http_callback(FORMAT_JSON, &ser->requestor, uri, params, status, title, contentlength);
+}
+
 static struct ast_str *rawman_http_callback(struct ast_tcptls_session_instance *ser, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength)
 {
        return generic_http_callback(FORMAT_RAW, &ser->requestor, uri, params, status, title, contentlength);
@@ -3707,6 +3760,13 @@
        .callback = mxml_http_callback,
 };

+struct ast_http_uri managerjsonuri = {
+       .description = "JSON Manager Event Interface",
+       .uri = "mjson",
+       .has_subtree = 0,
+       .callback = mjson_http_callback,
+};
+
 static int registered = 0;
 static int webregged = 0;

@@ -4033,6 +4093,7 @@
                        ast_http_uri_link(&rawmanuri);
                        ast_http_uri_link(&manageruri);
                        ast_http_uri_link(&managerxmluri);
+                       ast_http_uri_link(&managerjsonuri);
                        webregged = 1;
                }
        } else {
@@ -4040,6 +4101,7 @@
                        ast_http_uri_unlink(&rawmanuri);
                        ast_http_uri_unlink(&manageruri);
                        ast_http_uri_unlink(&managerxmluri);
+                       ast_http_uri_unlink(&managerjsonuri);
                        webregged = 0;
                }
        }