/* Asterisk Manager Proxy Copyright (c) 2005 David C. Troy This program is free software, distributed under the terms of the GNU General Public License. HTTP Input Handler */ #include "astmanproxy.h" int ParseHTTPInput(char *buf, struct message *m) { char *n, *v; n = buf; while ( (v = strstr(n, "=")) ) { v += 1; debugmsg("n: %s, v: %s", n, v); strncat(m->headers[m->hdrcount], n, v-n-1); strcat(m->headers[m->hdrcount], ": "); if ( (n = strstr(v, "&")) ) { n += 1; } else { n = (v + strlen(v) + 1); } strncat(m->headers[m->hdrcount], v, n-v-1); debugmsg("got hdr: %s", m->headers[m->hdrcount]); m->hdrcount++; } return (m->hdrcount > 0); } int HTTPHeader(struct mansession *s, char *status) { time_t t; struct tm tm; char date[80]; char ctype[15], hdr[MAX_LEN]; time(&t); localtime_r(&t, &tm); strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm); if ( !strcasecmp("xml", s->output->formatname) ) sprintf(ctype, "text/xml"); else sprintf(ctype, "text/plain"); if (!strcmp("200 OK", status) ) sprintf(hdr, "HTTP/1.1 %s\r\n" "Date: %s\r\n" "Content-Type: %s\r\n" "Connection: close\r\n" "Server: %s/%s\r\n\r\n", status, date, ctype, PROXY_BANNER, PROXY_VERSION); else sprintf(hdr, "HTTP/1.1 %s\r\n" "Date: %s\r\n" "Status: %s\r\n" "Server: %s/%s\r\n\r\n", status, date, status, PROXY_BANNER, PROXY_VERSION); pthread_mutex_lock(&s->lock); s->inputcomplete = 1; ast_carefulwrite(s->fd, hdr, strlen(hdr), s->writetimeout); pthread_mutex_unlock(&s->lock); debugmsg("http header: %s", hdr); return 0; } int _read(struct mansession *s, struct message *m) { /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */ /* No HTTP Input may be longer than BUFSIZE */ char line[MAX_LEN], method[10], formdata[MAX_LEN], status[15]; int res, clength = 0; memset(method, 0, sizeof method); memset(formdata, 0, sizeof formdata); memset(status, 0, sizeof status); /* for http, don't do get_input forever */ for (;;) { if (s->inputcomplete && !s->outputcomplete) continue; else if (s->inputcomplete && s->outputcomplete) return -1; memset(line, 0, sizeof line); res = get_input(s, line); debugmsg("res=%d, line: %s",res, line); if (res > 0) { debugmsg("Got http: %s", line); if ( !clength && !strncasecmp(line, "Content-Length: ", 16) ) clength = atoi(line+16); if (!*method) { if ( !strncmp(line,"POST",4) ) { strncpy(method, line, 4); } else if ( !strncmp(line,"GET",3)) { if ( strlen(line) > 14 ) { /* GET / HTTP/1.1 ---- this is bad */ /* GET /?Action=Ping&ActionID=Foo HTTP/1.1 */ strncpy(method, line, 3); memcpy(formdata, line+6, strstr(line, " HTTP")-line-6); sprintf(status, "200 OK"); } else sprintf(status, "501 Not Implemented"); } } } else if (res == 0) { /* x-www-form-urlencoded handler */ /* Content-Type: application/x-www-form-urlencoded */ if (*method && !*formdata) { if ( !strcasecmp(method, "POST") && clength && s->inlen==clength) { pthread_mutex_lock(&s->lock); strncpy(formdata, s->inbuf, clength); s->inlen = 0; pthread_mutex_unlock(&s->lock); sprintf(status, "200 OK"); } } } if (res < 0) break; if (*status) { HTTPHeader(s, status); /* now, let's transform and copy into a standard message block */ if (!strcmp("200 OK", status) ) { res = ParseHTTPInput(formdata, m); return res; } else { pthread_mutex_lock(&s->lock); s->outputcomplete = 1; pthread_mutex_unlock(&s->lock); return 0; } } } return -1; } int _autodisconnect() { return 1; } /* We do not define a _write or _onconnect method */