#include "asterisk.h"
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include "asterisk/cli.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/version.h"
#include "asterisk/manager.h"
Go to the source code of this file.
Data Structures | |
struct | ast_http_server_instance |
Defines | |
#define | DEFAULT_PREFIX "/asterisk" |
#define | MAX_PREFIX 80 |
Functions | |
static int | __ast_http_load (int reload) |
char * | ast_http_error (int status, const char *title, const char *extra_header, const char *text) |
Return a malloc()'d string containing an HTTP error message. | |
int | ast_http_init (void) |
int | ast_http_reload (void) |
char * | ast_http_setcookie (const char *var, const char *val, int expires, char *buf, size_t buflen) |
int | ast_http_uri_link (struct ast_http_uri *urih) |
Link into the Asterisk HTTP server. | |
void | ast_http_uri_unlink (struct ast_http_uri *urih) |
Destroy an HTTP server. | |
static void * | ast_httpd_helper_thread (void *data) |
AST_RWLOCK_DEFINE_STATIC (uris_lock) | |
static const char * | ftype2mtype (const char *ftype, char *wkspace, int wkspacelen) |
static int | handle_show_http (int fd, int argc, char *argv[]) |
static char * | handle_uri (struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies, unsigned int *static_content) |
static void * | http_root (void *data) |
static void | http_server_start (struct sockaddr_in *sin) |
static char * | httpstatus_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength) |
static struct ast_variable * | parse_cookies (char *cookies) |
static char * | static_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength) |
Variables | |
static struct ast_cli_entry | cli_http [] |
static int | enablestatic |
static int | httpfd = -1 |
static pthread_t | master = AST_PTHREADT_NULL |
struct { | |
const char * ext | |
const char * mtype | |
} | mimetypes [] |
Limit the kinds of files we're willing to serve up. | |
static struct sockaddr_in | oldsin |
static char | prefix [MAX_PREFIX] |
static int | prefix_len |
static char | show_http_help [] |
static struct ast_http_uri | staticuri |
static struct ast_http_uri | statusuri |
static struct ast_http_uri * | uris |
This program implements a tiny http server and was inspired by micro-httpd by Jef Poskanzer
AMI over HTTP support - AMI over the http protocol
Definition in file http.c.
#define DEFAULT_PREFIX "/asterisk" |
#define MAX_PREFIX 80 |
static int __ast_http_load | ( | int | reload | ) | [static] |
Definition at line 635 of file http.c.
References ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable_browse(), DEFAULT_PREFIX, enabled, hp, http_server_start(), LOG_WARNING, MAX_PREFIX, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by ast_http_init(), and ast_http_reload().
00636 { 00637 struct ast_config *cfg; 00638 struct ast_variable *v; 00639 int enabled=0; 00640 int newenablestatic=0; 00641 struct sockaddr_in sin; 00642 struct hostent *hp; 00643 struct ast_hostent ahp; 00644 char newprefix[MAX_PREFIX]; 00645 00646 memset(&sin, 0, sizeof(sin)); 00647 sin.sin_port = htons(8088); 00648 00649 strcpy(newprefix, DEFAULT_PREFIX); 00650 00651 cfg = ast_config_load("http.conf"); 00652 if (cfg) { 00653 v = ast_variable_browse(cfg, "general"); 00654 while(v) { 00655 if (!strcasecmp(v->name, "enabled")) 00656 enabled = ast_true(v->value); 00657 else if (!strcasecmp(v->name, "enablestatic")) 00658 newenablestatic = ast_true(v->value); 00659 else if (!strcasecmp(v->name, "bindport")) 00660 sin.sin_port = ntohs(atoi(v->value)); 00661 else if (!strcasecmp(v->name, "bindaddr")) { 00662 if ((hp = ast_gethostbyname(v->value, &ahp))) { 00663 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00664 } else { 00665 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value); 00666 } 00667 } else if (!strcasecmp(v->name, "prefix")) { 00668 if (!ast_strlen_zero(v->value)) { 00669 newprefix[0] = '/'; 00670 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1); 00671 } else { 00672 newprefix[0] = '\0'; 00673 } 00674 00675 } 00676 v = v->next; 00677 } 00678 ast_config_destroy(cfg); 00679 } 00680 if (enabled) 00681 sin.sin_family = AF_INET; 00682 if (strcmp(prefix, newprefix)) { 00683 ast_copy_string(prefix, newprefix, sizeof(prefix)); 00684 prefix_len = strlen(prefix); 00685 } 00686 enablestatic = newenablestatic; 00687 00688 http_server_start(&sin); 00689 00690 00691 return 0; 00692 }
char* ast_http_error | ( | int | status, | |
const char * | title, | |||
const char * | extra_header, | |||
const char * | text | |||
) |
Return a malloc()'d string containing an HTTP error message.
Definition at line 231 of file http.c.
References asprintf.
Referenced by ast_httpd_helper_thread(), generic_http_callback(), handle_uri(), and static_callback().
00232 { 00233 char *c = NULL; 00234 asprintf(&c, 00235 "Content-type: text/html\r\n" 00236 "%s" 00237 "\r\n" 00238 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 00239 "<html><head>\r\n" 00240 "<title>%d %s</title>\r\n" 00241 "</head><body>\r\n" 00242 "<h1>%s</h1>\r\n" 00243 "<p>%s</p>\r\n" 00244 "<hr />\r\n" 00245 "<address>Asterisk Server</address>\r\n" 00246 "</body></html>\r\n", 00247 (extra_header ? extra_header : ""), status, title, title, text); 00248 return c; 00249 }
int ast_http_init | ( | void | ) |
Definition at line 738 of file http.c.
References __ast_http_load(), ast_cli_register_multiple(), and ast_http_uri_link().
Referenced by main().
00739 { 00740 ast_http_uri_link(&statusuri); 00741 ast_http_uri_link(&staticuri); 00742 ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry)); 00743 00744 return __ast_http_load(0); 00745 }
int ast_http_reload | ( | void | ) |
Definition at line 723 of file http.c.
References __ast_http_load().
00724 { 00725 return __ast_http_load(1); 00726 }
char* ast_http_setcookie | ( | const char * | var, | |
const char * | val, | |||
int | expires, | |||
char * | buf, | |||
size_t | buflen | |||
) |
Definition at line 563 of file http.c.
References ast_build_string().
Referenced by generic_http_callback().
00564 { 00565 char *c; 00566 c = buf; 00567 ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val); 00568 if (expires) 00569 ast_build_string(&c, &buflen, "; Max-Age=%d", expires); 00570 ast_build_string(&c, &buflen, "\r\n"); 00571 return buf; 00572 }
int ast_http_uri_link | ( | struct ast_http_uri * | urih | ) |
Link into the Asterisk HTTP server.
Definition at line 251 of file http.c.
References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, and ast_http_uri::uri.
Referenced by ast_http_init(), and init_manager().
00252 { 00253 struct ast_http_uri *prev; 00254 00255 ast_rwlock_wrlock(&uris_lock); 00256 prev = uris; 00257 if (!uris || strlen(uris->uri) <= strlen(urih->uri)) { 00258 urih->next = uris; 00259 uris = urih; 00260 } else { 00261 while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri))) 00262 prev = prev->next; 00263 /* Insert it here */ 00264 urih->next = prev->next; 00265 prev->next = urih; 00266 } 00267 ast_rwlock_unlock(&uris_lock); 00268 00269 return 0; 00270 }
void ast_http_uri_unlink | ( | struct ast_http_uri * | urih | ) |
Destroy an HTTP server.
Definition at line 272 of file http.c.
References ast_rwlock_unlock(), ast_rwlock_wrlock(), and ast_http_uri::next.
Referenced by init_manager().
00273 { 00274 struct ast_http_uri *prev; 00275 00276 ast_rwlock_wrlock(&uris_lock); 00277 if (!uris) { 00278 ast_rwlock_unlock(&uris_lock); 00279 return; 00280 } 00281 prev = uris; 00282 if (uris == urih) { 00283 uris = uris->next; 00284 } 00285 while(prev->next) { 00286 if (prev->next == urih) { 00287 prev->next = urih->next; 00288 break; 00289 } 00290 prev = prev->next; 00291 } 00292 ast_rwlock_unlock(&uris_lock); 00293 }
static void* ast_httpd_helper_thread | ( | void * | data | ) | [static] |
Definition at line 419 of file http.c.
References ast_cli(), ast_http_error(), ast_strlen_zero(), ast_variables_destroy(), ASTERISK_VERSION, ast_http_server_instance::f, ast_http_server_instance::fd, free, handle_uri(), parse_cookies(), ast_http_server_instance::requestor, and t.
Referenced by http_root().
00420 { 00421 char buf[4096]; 00422 char cookie[4096]; 00423 char timebuf[256]; 00424 struct ast_http_server_instance *ser = data; 00425 struct ast_variable *vars = NULL; 00426 char *uri, *c, *title=NULL; 00427 int status = 200, contentlength = 0; 00428 time_t t; 00429 unsigned int static_content = 0; 00430 00431 if (fgets(buf, sizeof(buf), ser->f)) { 00432 /* Skip method */ 00433 uri = buf; 00434 while(*uri && (*uri > 32)) 00435 uri++; 00436 if (*uri) { 00437 *uri = '\0'; 00438 uri++; 00439 } 00440 00441 /* Skip white space */ 00442 while (*uri && (*uri < 33)) 00443 uri++; 00444 00445 if (*uri) { 00446 c = uri; 00447 while (*c && (*c > 32)) 00448 c++; 00449 if (*c) { 00450 *c = '\0'; 00451 } 00452 } 00453 00454 while (fgets(cookie, sizeof(cookie), ser->f)) { 00455 /* Trim trailing characters */ 00456 while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) { 00457 cookie[strlen(cookie) - 1] = '\0'; 00458 } 00459 if (ast_strlen_zero(cookie)) 00460 break; 00461 if (!strncasecmp(cookie, "Cookie: ", 8)) { 00462 vars = parse_cookies(cookie); 00463 } 00464 } 00465 00466 if (*uri) { 00467 if (!strcasecmp(buf, "get")) 00468 c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content); 00469 else 00470 c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\ 00471 } else 00472 c = ast_http_error(400, "Bad Request", NULL, "Invalid Request"); 00473 00474 /* If they aren't mopped up already, clean up the cookies */ 00475 if (vars) 00476 ast_variables_destroy(vars); 00477 00478 if (!c) 00479 c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error"); 00480 if (c) { 00481 time(&t); 00482 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); 00483 ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK"); 00484 ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION); 00485 ast_cli(ser->fd, "Date: %s\r\n", timebuf); 00486 ast_cli(ser->fd, "Connection: close\r\n"); 00487 if (!static_content) 00488 ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n"); 00489 /* We set the no-cache headers only for dynamic content. 00490 * If you want to make sure the static file you requested is not from cache, 00491 * append a random variable to your GET request. Ex: 'something.html?r=109987734' 00492 */ 00493 00494 if (contentlength) { 00495 char *tmp; 00496 tmp = strstr(c, "\r\n\r\n"); 00497 if (tmp) { 00498 ast_cli(ser->fd, "Content-length: %d\r\n", contentlength); 00499 write(ser->fd, c, (tmp + 4 - c)); 00500 write(ser->fd, tmp + 4, contentlength); 00501 } 00502 } else 00503 ast_cli(ser->fd, "%s", c); 00504 free(c); 00505 } 00506 if (title) 00507 free(title); 00508 } 00509 fclose(ser->f); 00510 free(ser); 00511 return NULL; 00512 }
AST_RWLOCK_DEFINE_STATIC | ( | uris_lock | ) |
static const char* ftype2mtype | ( | const char * | ftype, | |
char * | wkspace, | |||
int | wkspacelen | |||
) | [static] |
Definition at line 95 of file http.c.
References ext, mimetypes, and mtype.
Referenced by static_callback().
00096 { 00097 int x; 00098 if (ftype) { 00099 for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) { 00100 if (!strcasecmp(ftype, mimetypes[x].ext)) 00101 return mimetypes[x].mtype; 00102 } 00103 } 00104 snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain"); 00105 return wkspace; 00106 }
static int handle_show_http | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 694 of file http.c.
References ast_cli(), ast_inet_ntoa(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_http_uri::description, ast_http_uri::has_subtree, ast_http_uri::next, oldsin, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_http_uri::uri.
00695 { 00696 struct ast_http_uri *urih; 00697 00698 if (argc != 3) 00699 return RESULT_SHOWUSAGE; 00700 00701 ast_cli(fd, "HTTP Server Status:\n"); 00702 ast_cli(fd, "Prefix: %s\n", prefix); 00703 if (oldsin.sin_family) 00704 ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n", 00705 ast_inet_ntoa(oldsin.sin_addr), 00706 ntohs(oldsin.sin_port)); 00707 else 00708 ast_cli(fd, "Server Disabled\n\n"); 00709 ast_cli(fd, "Enabled URI's:\n"); 00710 ast_rwlock_rdlock(&uris_lock); 00711 urih = uris; 00712 while(urih){ 00713 ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description); 00714 urih = urih->next; 00715 } 00716 if (!uris) 00717 ast_cli(fd, "None.\n"); 00718 ast_rwlock_unlock(&uris_lock); 00719 00720 return RESULT_SUCCESS; 00721 }
static char* handle_uri | ( | struct sockaddr_in * | sin, | |
char * | uri, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength, | |||
struct ast_variable ** | cookies, | |||
unsigned int * | static_content | |||
) | [static] |
Definition at line 295 of file http.c.
References ast_http_error(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strlen_zero(), ast_uri_decode(), ast_variable_new(), ast_variables_destroy(), ast_http_uri::callback, ast_http_uri::has_subtree, len, ast_http_uri::next, ast_variable::next, ast_http_uri::static_content, strdup, strsep(), ast_http_uri::uri, and var.
Referenced by ast_httpd_helper_thread().
00298 { 00299 char *c; 00300 char *turi; 00301 char *params; 00302 char *var; 00303 char *val; 00304 struct ast_http_uri *urih=NULL; 00305 int len; 00306 struct ast_variable *vars=NULL, *v, *prev = NULL; 00307 00308 00309 params = strchr(uri, '?'); 00310 if (params) { 00311 *params = '\0'; 00312 params++; 00313 while ((var = strsep(¶ms, "&"))) { 00314 val = strchr(var, '='); 00315 if (val) { 00316 *val = '\0'; 00317 val++; 00318 ast_uri_decode(val); 00319 } else 00320 val = ""; 00321 ast_uri_decode(var); 00322 if ((v = ast_variable_new(var, val))) { 00323 if (vars) 00324 prev->next = v; 00325 else 00326 vars = v; 00327 prev = v; 00328 } 00329 } 00330 } 00331 if (prev) 00332 prev->next = *cookies; 00333 else 00334 vars = *cookies; 00335 *cookies = NULL; 00336 ast_uri_decode(uri); 00337 if (!strncasecmp(uri, prefix, prefix_len)) { 00338 uri += prefix_len; 00339 if (!*uri || (*uri == '/')) { 00340 if (*uri == '/') 00341 uri++; 00342 ast_rwlock_rdlock(&uris_lock); 00343 urih = uris; 00344 while(urih) { 00345 len = strlen(urih->uri); 00346 if (!strncasecmp(urih->uri, uri, len)) { 00347 if (!uri[len] || uri[len] == '/') { 00348 turi = uri + len; 00349 if (*turi == '/') 00350 turi++; 00351 if (!*turi || urih->has_subtree) { 00352 uri = turi; 00353 break; 00354 } 00355 } 00356 } 00357 urih = urih->next; 00358 } 00359 if (!urih) 00360 ast_rwlock_unlock(&uris_lock); 00361 } 00362 } 00363 if (urih) { 00364 if (urih->static_content) 00365 *static_content = 1; 00366 c = urih->callback(sin, uri, vars, status, title, contentlength); 00367 ast_rwlock_unlock(&uris_lock); 00368 } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) { 00369 /* Special case: If no prefix, and no URI, send to /static/index.html */ 00370 c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for..."); 00371 *status = 302; 00372 *title = strdup("Moved Temporarily"); 00373 } else { 00374 c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); 00375 *status = 404; 00376 *title = strdup("Not Found"); 00377 } 00378 ast_variables_destroy(vars); 00379 return c; 00380 }
static void* http_root | ( | void * | data | ) | [static] |
Definition at line 514 of file http.c.
References ast_calloc, ast_httpd_helper_thread(), ast_log(), ast_pthread_create_background, ast_wait_for_input(), errno, ast_http_server_instance::f, ast_http_server_instance::fd, free, LOG_WARNING, and ast_http_server_instance::requestor.
Referenced by http_server_start().
00515 { 00516 int fd; 00517 struct sockaddr_in sin; 00518 socklen_t sinlen; 00519 struct ast_http_server_instance *ser; 00520 pthread_t launched; 00521 pthread_attr_t attr; 00522 00523 for (;;) { 00524 int flags; 00525 00526 ast_wait_for_input(httpfd, -1); 00527 sinlen = sizeof(sin); 00528 fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen); 00529 if (fd < 0) { 00530 if ((errno != EAGAIN) && (errno != EINTR)) 00531 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00532 continue; 00533 } 00534 ser = ast_calloc(1, sizeof(*ser)); 00535 if (!ser) { 00536 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00537 close(fd); 00538 continue; 00539 } 00540 flags = fcntl(fd, F_GETFL); 00541 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00542 ser->fd = fd; 00543 memcpy(&ser->requestor, &sin, sizeof(ser->requestor)); 00544 if ((ser->f = fdopen(ser->fd, "w+"))) { 00545 pthread_attr_init(&attr); 00546 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00547 00548 if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) { 00549 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00550 fclose(ser->f); 00551 free(ser); 00552 } 00553 pthread_attr_destroy(&attr); 00554 } else { 00555 ast_log(LOG_WARNING, "fdopen failed!\n"); 00556 close(ser->fd); 00557 free(ser); 00558 } 00559 } 00560 return NULL; 00561 }
static void http_server_start | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 575 of file http.c.
References ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, errno, http_root(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, and oldsin.
Referenced by __ast_http_load().
00576 { 00577 int flags; 00578 int x = 1; 00579 00580 /* Do nothing if nothing has changed */ 00581 if (!memcmp(&oldsin, sin, sizeof(oldsin))) { 00582 ast_log(LOG_DEBUG, "Nothing changed in http\n"); 00583 return; 00584 } 00585 00586 memcpy(&oldsin, sin, sizeof(oldsin)); 00587 00588 /* Shutdown a running server if there is one */ 00589 if (master != AST_PTHREADT_NULL) { 00590 pthread_cancel(master); 00591 pthread_kill(master, SIGURG); 00592 pthread_join(master, NULL); 00593 } 00594 00595 if (httpfd != -1) 00596 close(httpfd); 00597 00598 /* If there's no new server, stop here */ 00599 if (!sin->sin_family) 00600 return; 00601 00602 00603 httpfd = socket(AF_INET, SOCK_STREAM, 0); 00604 if (httpfd < 0) { 00605 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00606 return; 00607 } 00608 00609 setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00610 if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) { 00611 ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n", 00612 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00613 strerror(errno)); 00614 close(httpfd); 00615 httpfd = -1; 00616 return; 00617 } 00618 if (listen(httpfd, 10)) { 00619 ast_log(LOG_NOTICE, "Unable to listen!\n"); 00620 close(httpfd); 00621 httpfd = -1; 00622 return; 00623 } 00624 flags = fcntl(httpfd, F_GETFL); 00625 fcntl(httpfd, F_SETFL, flags | O_NONBLOCK); 00626 if (ast_pthread_create_background(&master, NULL, http_root, NULL)) { 00627 ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n", 00628 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00629 strerror(errno)); 00630 close(httpfd); 00631 httpfd = -1; 00632 } 00633 }
static char* httpstatus_callback | ( | struct sockaddr_in * | req, | |
const char * | uri, | |||
struct ast_variable * | vars, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 179 of file http.c.
References ast_build_string(), ast_inet_ntoa(), ast_variable::name, ast_variable::next, oldsin, strdup, and ast_variable::value.
00180 { 00181 char result[4096]; 00182 size_t reslen = sizeof(result); 00183 char *c=result; 00184 struct ast_variable *v; 00185 00186 ast_build_string(&c, &reslen, 00187 "\r\n" 00188 "<title>Asterisk HTTP Status</title>\r\n" 00189 "<body bgcolor=\"#ffffff\">\r\n" 00190 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n" 00191 "<h2> Asterisk™ HTTP Status</h2></td></tr>\r\n"); 00192 00193 ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix); 00194 ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n", 00195 ast_inet_ntoa(oldsin.sin_addr)); 00196 ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n", 00197 ntohs(oldsin.sin_port)); 00198 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00199 v = vars; 00200 while(v) { 00201 if (strncasecmp(v->name, "cookie_", 7)) 00202 ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00203 v = v->next; 00204 } 00205 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00206 v = vars; 00207 while(v) { 00208 if (!strncasecmp(v->name, "cookie_", 7)) 00209 ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00210 v = v->next; 00211 } 00212 ast_build_string(&c, &reslen, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n"); 00213 return strdup(result); 00214 }
static struct ast_variable* parse_cookies | ( | char * | cookies | ) | [static, read] |
Definition at line 382 of file http.c.
References ast_log(), ast_strip_quoted(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, name, option_debug, strsep(), and var.
Referenced by ast_httpd_helper_thread().
00383 { 00384 char *cur; 00385 struct ast_variable *vars = NULL, *var; 00386 00387 /* Skip Cookie: */ 00388 cookies += 8; 00389 00390 while ((cur = strsep(&cookies, ";"))) { 00391 char *name, *val; 00392 00393 name = val = cur; 00394 strsep(&val, "="); 00395 00396 if (ast_strlen_zero(name) || ast_strlen_zero(val)) { 00397 continue; 00398 } 00399 00400 name = ast_strip(name); 00401 val = ast_strip_quoted(val, "\"", "\""); 00402 00403 if (ast_strlen_zero(name) || ast_strlen_zero(val)) { 00404 continue; 00405 } 00406 00407 if (option_debug) { 00408 ast_log(LOG_DEBUG, "mmm ... cookie! Name: '%s' Value: '%s'\n", name, val); 00409 } 00410 00411 var = ast_variable_new(name, val); 00412 var->next = vars; 00413 vars = var; 00414 } 00415 00416 return vars; 00417 }
static char* static_callback | ( | struct sockaddr_in * | req, | |
const char * | uri, | |||
struct ast_variable * | vars, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 108 of file http.c.
References ast_config_AST_DATA_DIR, ast_http_error(), ast_strlen_zero(), free, ftype2mtype(), len, malloc, mtype, and strdup.
00109 { 00110 char result[4096]; 00111 char *c=result; 00112 char *path; 00113 char *ftype; 00114 const char *mtype; 00115 char wkspace[80]; 00116 struct stat st; 00117 int len; 00118 int fd; 00119 void *blob; 00120 00121 /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration 00122 substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */ 00123 if (!enablestatic || ast_strlen_zero(uri)) 00124 goto out403; 00125 /* Disallow any funny filenames at all */ 00126 if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) 00127 goto out403; 00128 if (strstr(uri, "/..")) 00129 goto out403; 00130 00131 if ((ftype = strrchr(uri, '.'))) 00132 ftype++; 00133 mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace)); 00134 00135 /* Cap maximum length */ 00136 len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5; 00137 if (len > 1024) 00138 goto out403; 00139 00140 path = alloca(len); 00141 sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri); 00142 if (stat(path, &st)) 00143 goto out404; 00144 if (S_ISDIR(st.st_mode)) 00145 goto out404; 00146 fd = open(path, O_RDONLY); 00147 if (fd < 0) 00148 goto out403; 00149 00150 len = st.st_size + strlen(mtype) + 40; 00151 00152 blob = malloc(len); 00153 if (blob) { 00154 c = blob; 00155 sprintf(c, "Content-type: %s\r\n\r\n", mtype); 00156 c += strlen(c); 00157 *contentlength = read(fd, c, st.st_size); 00158 if (*contentlength < 0) { 00159 close(fd); 00160 free(blob); 00161 goto out403; 00162 } 00163 } 00164 close(fd); 00165 return blob; 00166 00167 out404: 00168 *status = 404; 00169 *title = strdup("Not Found"); 00170 return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); 00171 00172 out403: 00173 *status = 403; 00174 *title = strdup("Access Denied"); 00175 return ast_http_error(403, "Access Denied", NULL, "Sorry, I cannot let you do that, Dave."); 00176 }
struct ast_cli_entry cli_http[] [static] |
Initial value:
{ { { "http", "show", "status", NULL }, handle_show_http, "Display HTTP server status", show_http_help }, }
int enablestatic [static] |
const char* ext |
Definition at line 82 of file http.c.
Referenced by ast_filehelper(), ast_rtp_read(), console_transfer(), console_transfer_deprecated(), do_directory(), exts_compare(), ftype2mtype(), iax_park_thread(), misdn_call(), misdn_request(), mixmonitor_thread(), moh_scan_files(), oh323_request(), pbx_load_config(), record_exec(), register_peer_exten(), sip_park_thread(), and sip_request_call().
pthread_t master = AST_PTHREADT_NULL [static] |
struct { ... } mimetypes[] [static] |
const char* mtype |
struct sockaddr_in oldsin [static] |
Definition at line 77 of file http.c.
Referenced by handle_show_http(), http_server_start(), and httpstatus_callback().
char prefix[MAX_PREFIX] [static] |
Definition at line 75 of file http.c.
Referenced by _while_exec(), ast_db_deltree(), ast_db_gettree(), database_show(), handle_verbose(), read_config(), realtime_exec(), and while_continue_exec().
int prefix_len [static] |
char show_http_help[] [static] |
struct ast_http_uri staticuri [static] |
struct ast_http_uri statusuri [static] |
struct ast_http_uri* uris [static] |