static unsigned int html_reply(struct http_request *request, void *data) { int ret, fd=-1; char *path = NULL; char *buffer = NULL; struct stat sbuf; struct agent_core_t *core = data; struct http_response *resp; struct html_priv_t *html; GET_PRIV(data, html); const char *url_stub = (strlen(request->url) > strlen("/html/")) ? request->url + strlen("/html/") : "index.html"; if (url_stub[0] == '/' || strstr(url_stub,"/../") || !strncmp(url_stub,"../",strlen("../"))) { send_response_fail(request->connection, "Invalid URL"); return 0; } ret = asprintf(&path, "%s/%s", core->config->H_arg, url_stub); assert(ret>0); ret = stat(path, &sbuf); if (ret < 0) { warnlog(html->logger, "Stat failed for %s. Errnno %d: %s.", path,errno,strerror(errno)); send_response_fail(request->connection, "stat() was not happy"); goto out; } fd = open(path, O_RDONLY); if (fd < 0) { warnlog(html->logger, "open() failed for %s: %s", path, strerror(errno)); send_response_fail(request->connection, "open() was not happy"); goto out; } if (!S_ISREG(sbuf.st_mode)) { warnlog(html->logger, "%s isn't a regular file.", path); send_response_fail(request->connection, "not a file"); goto out; } buffer = malloc(sbuf.st_size); assert(buffer); ret = read(fd, buffer, sbuf.st_size); assert(ret>0); assert(ret==sbuf.st_size); resp = http_mkresp(request->connection, 200, NULL); resp->data = buffer; resp->ndata = ret; send_response2(resp); http_free_resp(resp); out: if (fd >= 0) close(fd); if (buffer) free(buffer); if (path) free(path); return 0; }
static unsigned int vban_reply(struct http_request *request, void *data) { struct vban_priv_t *vban; struct agent_plugin_t *plug; char *body; plug = plugin_find(data,"vban"); vban = plug->data; if (request->method == M_GET) { run_and_respond(vban->vadmin, request->connection, "ban.list"); return 0; } else { char *mark; assert(((char *)request->data)[request->ndata] == '\0'); body = strdup(request->data); mark = index(body,'\n'); if (mark) *mark = '\0'; if (strlen(request->url) == strlen("/ban")) run_and_respond(vban->vadmin, request->connection, "ban %s",body); else { const char *path = request->url + strlen("/ban"); if (request->ndata != 0) { send_response_fail(request->connection, "Banning with both a url and request body? Pick one or the other please."); } else { assert(request->ndata == 0); run_and_respond(vban->vadmin, request->connection, "ban " BAN_SHORTHAND "%s",path); } } free(body); return 0; } return 0; }
/* * Run a varnishadm-command and send the result of that command back to the * http connection. If varnishd returns 200, then so do we. Otherwise: 500. */ void run_and_respond(int vadmin, struct MHD_Connection *conn, const char *fmt, ...) { struct ipc_ret_t vret; va_list ap; char *buffer; int iret; va_start(ap, fmt); iret = vasprintf(&buffer, fmt, ap); assert(iret>0); va_end(ap); ipc_run(vadmin, &vret, "%s", buffer); free(buffer); if (vret.status == 200) send_response_ok(conn, vret.answer); else send_response_fail(conn, vret.answer); free(vret.answer); }
static int answer_to_connection (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls) { struct agent_core_t *core = (struct agent_core_t *)cls; struct http_priv_t *http; struct agent_plugin_t *plug; struct http_request request; struct connection_info_struct *con_info = NULL; int ret; (void)version; plug = plugin_find(core,"http"); http = (struct http_priv_t *) plug->data; assert(plug); assert(http); if (NULL == *con_cls) { con_info = malloc (sizeof (struct connection_info_struct)); assert(con_info); con_info->answerstring[0] = '\0'; con_info->progress = 0; con_info->authed = 0; *con_cls = con_info; return MHD_YES; } con_info = *con_cls; assert(core->config->userpass); log_request(connection, http, method, url); if (0 == strcmp (method, "GET") || !strcmp(method, "HEAD") || !strcmp(method,"DELETE")) { ret = check_auth(connection, core, con_info); if (ret == 1) return MHD_YES; if (!strcmp(method,"DELETE")) { request.method = M_DELETE; } else { request.method = M_GET; } request.connection = connection; request.url = url; request.ndata = 0; if (find_listener(&request, http)) return MHD_YES; } if (!strcmp(method, "POST") || !strcmp(method, "PUT")) { if (*upload_data_size != 0) { if (*upload_data_size + con_info->progress >= RCV_BUFFER) { warnlog(http->logger, "Client input exceeded buffer size of %u bytes. Dropping client.", RCV_BUFFER); return MHD_NO; } memcpy(con_info->answerstring + con_info->progress, upload_data, *upload_data_size); con_info->progress += *upload_data_size; *upload_data_size = 0; return MHD_YES; } else if (NULL != con_info->answerstring){ ret = check_auth(connection, core, con_info); if (ret == 1) return MHD_YES; if (!strcmp(method,"POST")) { request.method = M_POST; } else { request.method = M_PUT; } request.connection = connection; request.url = url; request.ndata = con_info->progress; request.data = con_info->answerstring; /* * FIXME */ ((char *)request.data)[con_info->progress] = '\0'; if (find_listener(&request, http)) return MHD_YES; } } if (request.method == M_GET && !strcmp(url, "/")) { if (http->help_page == NULL) http->help_page = make_help(http); assert (http->help_page); return send_response_ok(connection, http->help_page); } return send_response_fail (connection, "Failed\n"); }
static unsigned int vlog_reply(struct httpd_request *request, void *data) { struct vlog_priv_t *vlog; int ret; char *limit = NULL; char *p; char *tag = NULL; char *itag = NULL; struct agent_core_t *core = data; GET_PRIV(data,vlog); p = next_slash(request->url + 1); assert(vlog->tag==NULL); assert(vlog->answer == NULL); if (p) { limit = strdup(p); assert(limit); char *tmp2 = index(limit,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; if(!(atoi(limit) > 0)) { free(limit); send_response_fail(request->connection,"Not a number"); return 0; } p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = index(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { itag = strdup(p); char *tmp2 = index(itag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vlog->answer = VSB_new_auto(); assert(vlog->answer != NULL); vlog->vd = VSM_New(); assert(VSL_Arg(vlog->vd, 'n', core->config->n_arg)); VSL_Setup(vlog->vd); VSL_Arg(vlog->vd, 'd', ""); if (tag) { VSL_Arg(vlog->vd, 'i', tag); if (itag) VSL_Arg(vlog->vd,'I',itag); } else { VSL_Arg(vlog->vd, 'k', limit ? limit : "10"); } if (limit) free(limit); VSB_printf(vlog->answer, "{ \"log\": ["); ret = VSL_Open(vlog->vd, 1); assert(!ret); if (tag == NULL) { do_order(vlog); } else { do_unorder(vlog); } if (tag) free(tag); if (itag) free(itag); VSB_printf(vlog->answer, "\n] }\n"); assert(VSB_finish(vlog->answer) == 0); if (VSB_len(vlog->answer) > 1) { send_response(request->connection, 200, VSB_data(vlog->answer), VSB_len(vlog->answer)); } else { send_response_fail(request->connection, "FAIL"); } VSB_clear(vlog->answer); VSM_Close(vlog->vd); vlog->answer = NULL; vlog->entries = 0; return 0; }