int make_request(evbase_t * evbase, evthr_t * evthr, const char * const host, const short port, const char * const path, evhtp_headers_t * headers, evhtp_callback_cb cb, void * arg) { evhtp_connection_t * conn; evhtp_request_t * request; conn = evhtp_connection_new(evbase, host, port); conn->thread = evthr; request = evhtp_request_new(cb, arg); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Host", "localhost", 0, 0)); evhtp_headers_add_header(request->headers_out, evhtp_header_new("User-Agent", "libevhtp", 0, 0)); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Connection", "close", 0, 0)); evhtp_headers_add_headers(request->headers_out, headers); printf("Making backend request...\n"); evhtp_make_request(conn, request, htp_method_GET, path); printf("Ok.\n"); return 0; }
/** * @brief echo_cb Callback function of echo test. * * @param req The request of a test url. * @param arg It is not useful. */ void echo_cb(evhtp_request_t *req, void *arg) { evbuffer_add_printf(req->buffer_out, "<html><body><h1>zimg works!</h1></body></html>"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); }
static void redirect_to_upload_error (evhtp_request_t *req, const char *repo_id, const char *parent_dir, const char *filename, int error_code) { char *seahub_url, *escaped_path, *escaped_fn = NULL; char url[1024]; seahub_url = seaf->session->base.service_url; escaped_path = g_uri_escape_string (parent_dir, NULL, FALSE); if (filename) { escaped_fn = g_uri_escape_string (filename, NULL, FALSE); snprintf(url, 1024, "%s/repo/upload_error/%s?p=%s&fn=%s&err=%d", seahub_url, repo_id, escaped_path, escaped_fn, error_code); } else { snprintf(url, 1024, "%s/repo/upload_error/%s?p=%s&err=%d", seahub_url, repo_id, escaped_path, error_code); } g_free (escaped_path); g_free (escaped_fn); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Location", url, 1, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Length", "0", 1, 1)); evhtp_send_reply(req, EVHTP_RES_SEEOTHER); }
/** * @brief dump_request_cb The callback of a dump request. * * @param req The request you want to dump. * @param arg It is not useful. */ void dump_request_cb(evhtp_request_t *req, void *arg) { const char *uri = req->uri->path->full; //switch (evhtp_request_t_get_command(req)) { int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_DEBUG, "Received a %s request for %s", method_strmap[req_method], uri); evbuffer_add_printf(req->buffer_out, "uri : %s\r\n", uri); evbuffer_add_printf(req->buffer_out, "query : %s\r\n", req->uri->query_raw); evhtp_headers_for_each(req->uri->query, print_headers, req->buffer_out); evbuffer_add_printf(req->buffer_out, "Method : %s\n", method_strmap[req_method]); evhtp_headers_for_each(req->headers_in, print_headers, req->buffer_out); evbuf_t *buf = req->buffer_in;; puts("Input data: <<<"); while (evbuffer_get_length(buf)) { int n; char cbuf[128]; n = evbuffer_remove(buf, cbuf, sizeof(buf)-1); if (n > 0) (void) fwrite(cbuf, 1, n, stdout); } puts(">>>"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/plain", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); }
int main(int argc, char ** argv) { evbase_t * evbase; evhtp_connection_t * conn; evhtp_request_t * request; evbase = event_base_new(); conn = evhtp_connection_new(evbase, "75.126.169.52", 80); request = evhtp_request_new(request_cb, evbase); evhtp_set_hook(&request->hooks, evhtp_hook_on_read, print_data, evbase); evhtp_set_hook(&request->hooks, evhtp_hook_on_new_chunk, print_new_chunk_len, NULL); evhtp_set_hook(&request->hooks, evhtp_hook_on_chunk_complete, print_chunk_complete, NULL); evhtp_set_hook(&request->hooks, evhtp_hook_on_chunks_complete, print_chunks_complete, NULL); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Host", "ieatfood.net", 0, 0)); evhtp_headers_add_header(request->headers_out, evhtp_header_new("User-Agent", "libevhtp", 0, 0)); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Connection", "close", 0, 0)); evhtp_make_request(conn, request, htp_method_GET, "/"); event_base_loop(evbase, 0); event_base_free(evbase); return 0; }
/** * Serves a PNG file of the hash. */ void route_image(evhtp_request_t *req, void *arg) { // redisReply *reply; evhtp_uri_t *uri = req->uri; int side = 128; char *hash = ""; char *res = uri->path->full; int ind = 0; res = strtok((char *) res, "/"); while (res != NULL) { if (ind == 0) { if (strlen(res) == 32) { hash = res; } else if (strcmp(res, "avatar") == 0) { ind--; } else { route_400(req); return; } } if (ind == 1) { side = atoi(res); if (side == 0) { side = defsize; } else if (side < minsize) { side = minsize; } else if (side > maxsize) { side = maxsize; } } res = strtok(NULL, "/"); ind++; } char *etag = malloc(sizeof(char) * 1024); sprintf(etag, "\"%s-%d\"", hash, side); evhtp_kv_t *etagin = evhtp_headers_find_header(req->headers_in, "If-None-Match"); if(etagin && strcmp(etag, etagin->val) == 0) { free(etag); evhtp_send_reply(req, 304); return; } make_image(hash, req->buffer_out, side); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/png", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Cache-Control", "public", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("ETag", etag, 0, 1)); free(etag); evhtp_send_reply(req, 200); }
/** * @brief zimg_attachment_set set zimg response Content-Disposition * * @param request the request of evhtp * * @return 1 for set true */ int zimg_attachment_set(evhtp_request_t *request, char* filename) { LOG_PRINT(LOG_DEBUG, "origin url: %s", filename); char att[256]; if ( strlen(filename)>0 ) { zimg_url_decode(filename,strlen(filename)); LOG_PRINT(LOG_DEBUG, "decoded url: %s", filename); } snprintf(att,sizeof(att)-1,"attachment;filename=\"%s\"",filename); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Disposition", att, 0, 1)); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Type", "application/octet-stream", 0, 0)); return 1; }
/** * Index route, serves a static file and handles a redirect. */ void route_index(evhtp_request_t *req, void *arg) { evhtp_uri_t *uri = req->uri; evhtp_query_t *query = uri->query; const char *parq = evhtp_kv_find(query, "q"); const char *pars = evhtp_kv_find(query, "s"); const char *parm = evhtp_kv_find(query, "m"); if (parq) { char *m = malloc(sizeof (char)*64); char *tmp = makelower(parq, strlen(parq)); char *md = md5((const char *) tmp, strlen(parq)); free(tmp); if (parm) { sprintf(m, "/meta/%s", md); } else if (pars) { sprintf(m, "/%s/%d", md, atoi(pars)); } else { sprintf(m, "/%s", md); } free(md); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Location", m, 0, 1)); free(m); evhtp_send_reply(req, 301); } else { serve_static(req, "static/index.html", "text/html"); } }
int json_return(evhtp_request_t *req, int err_no, const char *md5sum, int post_size) { //json sample: //{"ret":true,"info":{"size":"1024", "md5":"edac35fd4b0059d3218f0630bc56a6f4"}} //{"ret":false,"error":{"code":"1","message":"\u9a8c\u8bc1\u5931\u8d25"}} cJSON *j_ret = cJSON_CreateObject(); cJSON *j_ret_info = cJSON_CreateObject(); if(err_no == -1) { cJSON_AddBoolToObject(j_ret, "ret", 1); cJSON_AddStringToObject(j_ret_info, "md5", md5sum); cJSON_AddNumberToObject(j_ret_info, "size", post_size); cJSON_AddItemToObject(j_ret, "info", j_ret_info); } else { cJSON_AddBoolToObject(j_ret, "ret", 0); cJSON_AddNumberToObject(j_ret_info, "code", err_no); LOG_PRINT(LOG_DEBUG, "post_error_list[%d]: %s", err_no, post_error_list[err_no]); cJSON_AddStringToObject(j_ret_info, "message", post_error_list[err_no]); cJSON_AddItemToObject(j_ret, "error", j_ret_info); } char *ret_str_unformat = cJSON_PrintUnformatted(j_ret); LOG_PRINT(LOG_DEBUG, "ret_str_unformat: %s", ret_str_unformat); evbuffer_add_printf(req->buffer_out, "%s", ret_str_unformat); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "application/json", 0, 0)); cJSON_Delete(j_ret); free(ret_str_unformat); return 0; }
/** * @brief admin_img the function to deal with admin reqeust for disk mode * * @param req the evhtp request * @param md5 the file md5 * @param t admin type * * @return 1 for OK, 2 for 404 not found and -1 for fail */ int admin_img(evhtp_request_t *req, thr_arg_t *thr_arg, char *md5, int t) { int result = -1; LOG_PRINT(LOG_DEBUG, "amdin_img() start processing admin request..."); char whole_path[512]; int lvl1 = str_hash(md5); int lvl2 = str_hash(md5 + 3); snprintf(whole_path, 512, "%s/%d/%d/%s", settings.img_path, lvl1, lvl2, md5); LOG_PRINT(LOG_DEBUG, "whole_path: %s", whole_path); if(is_dir(whole_path) == -1) { LOG_PRINT(LOG_DEBUG, "path: %s is not exist!", whole_path); return 2; } if(t == 1) { if(delete_file(whole_path) != -1) { result = 1; evbuffer_add_printf(req->buffer_out, "<html><body><h1>Admin Command Successful!</h1> \ <p>MD5: %s</p> \ <p>Command Type: %d</p> \ </body></html>", md5, t); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); } }
/* It's a bug of libevhtp that it doesn't set Content-Length automatically * in response to a multipart request. * Just add it in our code. */ static void set_content_length_header (evhtp_request_t *req) { char lstr[128]; snprintf(lstr, sizeof(lstr), "%zu", evbuffer_get_length(req->buffer_out)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Length", lstr, 1, 1)); }
/** * @brief zimg_etag_set set zimg response etag * * @param request the request of evhtp * @param buff response body buffer * @param len body buffer len * * @return 1 for set true and 2 for 304 */ int zimg_etag_set(evhtp_request_t *request, char *buff, size_t len) { int result = 1; LOG_PRINT(LOG_DEBUG, "Begin to Caculate MD5..."); md5_state_t mdctx; md5_byte_t md_value[16]; char md5sum[33]; int i; int h, l; md5_init(&mdctx); md5_append(&mdctx, (const unsigned char*)(buff), len); md5_finish(&mdctx, md_value); for(i=0; i<16; ++i) { h = md_value[i] & 0xf0; h >>= 4; l = md_value[i] & 0x0f; md5sum[i * 2] = (char)((h >= 0x0 && h <= 0x9) ? (h + 0x30) : (h + 0x57)); md5sum[i * 2 + 1] = (char)((l >= 0x0 && l <= 0x9) ? (l + 0x30) : (l + 0x57)); } md5sum[32] = '\0'; LOG_PRINT(LOG_DEBUG, "md5: %s", md5sum); const char *etag_var = evhtp_header_find(request->headers_in, "If-None-Match"); LOG_PRINT(LOG_DEBUG, "If-None-Match: %s", etag_var); if(etag_var == NULL) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Etag", md5sum, 0, 1)); } else { if(strncmp(md5sum, etag_var, 32) == 0) { result = 2; } else { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Etag", md5sum, 0, 1)); } } return result; }
void zxy_add_http_header( zxy_request_context *context, const std::string& key, const std::string& val) { const evhtp_request_t *request = context->request; evhtp_headers_add_header( request->headers_out, evhtp_header_new(key.c_str(), val.c_str(), 1, 1)); }
void add_header_to_incoming_req(const std::string& name, const std::string& value) { // This takes the name and value for the new header. These // are copied to avoid memory scribblers (controlled by the 1, 1 // parameters) evhtp_header_t* new_header = evhtp_header_new(name.c_str(), value.c_str(), 1, 1); evhtp_headers_add_header(_req->headers_in, new_header); }
/** * @brief zimg_headers_add add header to evhtp request from conf * * @param req the evhtp request * @param hcf zimg_header_conf * * @return 1 for OK and -1 for fail */ static int zimg_headers_add(evhtp_request_t *req, zimg_headers_conf_t *hcf) { if(hcf == NULL) return -1; zimg_headers_t *headers = hcf->headers; LOG_PRINT(LOG_DEBUG, "headers: %d", hcf->n); while(headers) { evhtp_headers_add_header(req->headers_out, evhtp_header_new(headers->value->key, headers->value->value, 1, 1)); headers = headers->next; } return 1; }
static void redirect_to_success_page (evhtp_request_t *req, const char *repo_id, const char *parent_dir) { char *seahub_url, *escaped_path; char url[1024]; seahub_url = seaf->session->base.service_url; escaped_path = g_uri_escape_string (parent_dir, NULL, FALSE); snprintf(url, 1024, "%s/repo/%s?p=%s", seahub_url, repo_id, escaped_path); g_free (escaped_path); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Location", url, 1, 1)); /* Firefox expects Content-Length header. */ evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Length", "0", 1, 1)); evhtp_send_reply(req, EVHTP_RES_SEEOTHER); }
/** * Serves meta information in JSON about a hash. */ void route_meta(evhtp_request_t *req, void *arg) { evhtp_uri_t *uri = req->uri; char *res = uri->path->full; char *hash = ""; res = strtok((char *) res, "/"); while (res != NULL) { if (strlen(res) == 32) { hash = res; break; } res = strtok(NULL, "/"); } char *color = malloc(sizeof (char)*7); make_color_hex(hash, color); int i[8][8]; make_pattern(hash, i); char *pattern = malloc(sizeof (char)*146); sprintf(pattern, "[[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]," "[%d,%d,%d,%d,%d,%d,%d,%d]]", i[0][0], i[0][1], i[0][2], i[0][3], i[0][4], i[0][5], i[0][6], i[0][7], i[1][0], i[1][1], i[1][2], i[1][3], i[1][4], i[1][5], i[1][6], i[1][7], i[2][0], i[2][1], i[2][2], i[2][3], i[2][4], i[2][5], i[2][6], i[2][7], i[3][0], i[3][1], i[3][2], i[3][3], i[3][4], i[3][5], i[3][6], i[3][7], i[4][0], i[4][1], i[4][2], i[4][3], i[4][4], i[4][5], i[4][6], i[4][7], i[5][0], i[5][1], i[5][2], i[5][3], i[5][4], i[5][5], i[5][6], i[5][7], i[6][0], i[6][1], i[6][2], i[6][3], i[6][4], i[6][5], i[6][6], i[6][7], i[7][0], i[7][1], i[7][2], i[7][3], i[7][4], i[7][5], i[7][6], i[7][7] ); pattern[145] = 0; evbuffer_add_printf(req->buffer_out, "{\"hash\":\"%s\",\"modified\":false,\"color\":\"%s\",\"pattern\":%s}", hash, color, pattern); free(color); free(pattern); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "application/json", 0, 0)); evhtp_send_reply(req, 200); }
static void redirect_to_update_error (evhtp_request_t *req, const char *repo_id, const char *target_file, int error_code) { char *seahub_url, *escaped_path; char url[1024]; seahub_url = seaf->session->base.service_url; escaped_path = g_uri_escape_string (target_file, NULL, FALSE); snprintf(url, 1024, "%s/repo/update_error/%s?p=%s&err=%d", seahub_url, repo_id, escaped_path, error_code); g_free (escaped_path); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Location", url, 0, 0)); evhtp_send_reply(req, EVHTP_RES_FOUND); }
void send_file(evhtp_request_t* req, char* path) { struct stat st; unsigned char data[1024]; int fd; int n; evbuf_t* buf = NULL; if (stat(path, &st) < 0 || S_ISDIR(st.st_mode)) goto file_error; fd = open(path, O_RDONLY); if (fd < 0) goto file_error; buf = evbuffer_new(); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", guess_content_type(path), 0, 0)); evhtp_send_reply_chunk_start(req, EVHTP_RES_OK); do { n = read(fd, data, sizeof(data)); evbuffer_add(buf, data, n); evhtp_send_reply_chunk(req, buf); evbuffer_drain(buf, -1); } while (n > 0); close(fd); evhtp_send_reply_chunk_end(req); evbuffer_free(buf); return; file_error: evbuffer_add_printf(req->buffer_out, "ERROR:%s", path); evhtp_send_reply(req, EVHTP_RES_OK); }
/** * @brief post_request_cb The callback function of a POST request to upload a image. * * @param req The request with image buffer. * @param arg It is not useful. */ void post_request_cb(evhtp_request_t *req, void *arg) { int post_size = 0; char *buff = NULL; int err_no = 0; int ret_json = 1; evhtp_connection_t *ev_conn = evhtp_request_get_connection(req); struct sockaddr *saddr = ev_conn->saddr; struct sockaddr_in *ss = (struct sockaddr_in *)saddr; char address[16]; const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For"); if(xff_address) { inet_aton(xff_address, &ss->sin_addr); } strncpy(address, inet_ntoa(ss->sin_addr), 16); int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_DEBUG, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") != 0) { LOG_PRINT(LOG_DEBUG, "Request Method Not Support."); LOG_PRINT(LOG_INFO, "%s refuse post method", address); err_no = 2; goto err; } if(settings.up_access != NULL) { int acs = zimg_access_inet(settings.up_access, ss->sin_addr.s_addr); LOG_PRINT(LOG_DEBUG, "access check: %d", acs); if(acs == ZIMG_FORBIDDEN) { LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address); LOG_PRINT(LOG_INFO, "%s refuse post forbidden", address); err_no = 3; goto forbidden; } else if(acs == ZIMG_ERROR) { LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address); LOG_PRINT(LOG_ERROR, "%s fail post access %s", address); err_no = 0; goto err; } } const char *content_len = evhtp_header_find(req->headers_in, "Content-Length"); if(!content_len) { LOG_PRINT(LOG_DEBUG, "Get Content-Length error!"); LOG_PRINT(LOG_ERROR, "%s fail post content-length", address); err_no = 5; goto err; } post_size = atoi(content_len); if(post_size <= 0) { LOG_PRINT(LOG_DEBUG, "Image Size is Zero!"); LOG_PRINT(LOG_ERROR, "%s fail post empty", address); err_no = 5; goto err; } if(post_size > settings.max_size) { LOG_PRINT(LOG_DEBUG, "Image Size Too Large!"); LOG_PRINT(LOG_ERROR, "%s fail post large", address); err_no = 7; goto err; } const char *content_type = evhtp_header_find(req->headers_in, "Content-Type"); if(!content_type) { LOG_PRINT(LOG_DEBUG, "Get Content-Type error!"); LOG_PRINT(LOG_ERROR, "%s fail post content-type", address); err_no = 6; goto err; } evbuf_t *buf; buf = req->buffer_in; buff = (char *)malloc(post_size); if(buff == NULL) { LOG_PRINT(LOG_DEBUG, "buff malloc failed!"); LOG_PRINT(LOG_ERROR, "%s fail malloc buff", address); err_no = 0; goto err; } int rmblen, evblen; if(evbuffer_get_length(buf) <= 0) { LOG_PRINT(LOG_DEBUG, "Empty Request!"); LOG_PRINT(LOG_ERROR, "%s fail post empty", address); err_no = 4; goto err; } while((evblen = evbuffer_get_length(buf)) > 0) { LOG_PRINT(LOG_DEBUG, "evblen = %d", evblen); rmblen = evbuffer_remove(buf, buff, evblen); LOG_PRINT(LOG_DEBUG, "rmblen = %d", rmblen); if(rmblen < 0) { LOG_PRINT(LOG_DEBUG, "evbuffer_remove failed!"); LOG_PRINT(LOG_ERROR, "%s fail post parse", address); err_no = 4; goto err; } } if(strstr(content_type, "multipart/form-data") == NULL) { err_no = binary_parse(req, content_type, address, buff, post_size); } else { ret_json = 0; err_no = multipart_parse(req, content_type, address, buff, post_size); } if(err_no != -1) { goto err; } evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_DEBUG, "============post_request_cb() DONE!==============="); goto done; forbidden: json_return(req, err_no, NULL, 0); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_DEBUG, "============post_request_cb() FORBIDDEN!==============="); goto done; err: if(ret_json == 0) { evbuffer_add_printf(req->buffer_out, "<h1>Upload Failed!</h1></body></html>"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); } else { json_return(req, err_no, NULL, 0); } evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_DEBUG, "============post_request_cb() ERROR!==============="); done: free(buff); }
int multipart_parse(evhtp_request_t *req, const char *content_type, const char *address, const char *buff, int post_size) { int err_no = 0; char *boundary = NULL, *boundary_end = NULL; char *boundaryPattern = NULL; int boundary_len = 0; mp_arg_t *mp_arg = NULL; evbuffer_add_printf(req->buffer_out, "<html>\n<head>\n" "<title>Upload Result</title>\n" "</head>\n" "<body>\n" ); if(strstr(content_type, "boundary") == 0) { LOG_PRINT(LOG_DEBUG, "boundary NOT found!"); LOG_PRINT(LOG_ERROR, "%s fail post parse", address); err_no = 6; goto done; } boundary = strchr(content_type, '='); boundary++; boundary_len = strlen(boundary); if(boundary[0] == '"') { boundary++; boundary_end = strchr(boundary, '"'); if (!boundary_end) { LOG_PRINT(LOG_DEBUG, "Invalid boundary in multipart/form-data POST data"); LOG_PRINT(LOG_ERROR, "%s fail post parse", address); err_no = 6; goto done; } } else { /* search for the end of the boundary */ boundary_end = strpbrk(boundary, ",;"); } if (boundary_end) { boundary_end[0] = '\0'; boundary_len = boundary_end-boundary; } LOG_PRINT(LOG_DEBUG, "boundary Find. boundary = %s", boundary); boundaryPattern = (char *)malloc(boundary_len + 3); if(boundaryPattern == NULL) { LOG_PRINT(LOG_DEBUG, "boundarypattern malloc failed!"); LOG_PRINT(LOG_ERROR, "%s fail malloc", address); err_no = 0; goto done; } snprintf(boundaryPattern, boundary_len + 3, "--%s", boundary); LOG_PRINT(LOG_DEBUG, "boundaryPattern = %s, strlen = %d", boundaryPattern, (int)strlen(boundaryPattern)); multipart_parser* parser = multipart_parser_init(boundaryPattern); if(!parser) { LOG_PRINT(LOG_DEBUG, "Multipart_parser Init Failed!"); LOG_PRINT(LOG_ERROR, "%s fail post save", address); err_no = 0; goto done; } mp_arg = (mp_arg_t *)malloc(sizeof(mp_arg_t)); if(!mp_arg) { LOG_PRINT(LOG_DEBUG, "Multipart_parser Arg Malloc Failed!"); LOG_PRINT(LOG_ERROR, "%s fail post save", address); err_no = 0; goto done; } evthr_t *thread = get_request_thr(req); thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread); mp_arg->req = req; mp_arg->thr_arg = thr_arg; str_lcpy(mp_arg->address, address, 16); mp_arg->partno = 0; mp_arg->succno = 0; mp_arg->check_name = 0; multipart_parser_set_data(parser, mp_arg); multipart_parser_execute(parser, buff, post_size); multipart_parser_free(parser); if(mp_arg->succno == 0) { evbuffer_add_printf(req->buffer_out, "<h1>Upload Failed!</h1>\n"); } evbuffer_add_printf(req->buffer_out, "</body>\n</html>\n"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); err_no = -1; done: free(boundaryPattern); free(mp_arg); return err_no; }
/** * Serves the favicon file. */ void route_favicon(evhtp_request_t *req, void *arg) { evhtp_headers_add_header(req->headers_out, evhtp_header_new("Cache-Control", "max-age=90000, public", 0, 0)); serve_static(req, "static/favicon.ico", "image/x-icon"); }
/** * @brief post_request_cb The callback function of a POST request to upload a image. * * @param req The request with image buffer. * @param arg It is not useful. */ void post_request_cb(evhtp_request_t *req, void *arg) { int post_size = 0; char *boundary = NULL, *boundary_end = NULL; int boundary_len = 0; char *fileName = NULL; char *boundaryPattern = NULL; char *buff = NULL; int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_INFO, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") != 0) { LOG_PRINT(LOG_INFO, "Request Method Not Support."); goto err; } const char *content_len = evhtp_header_find(req->headers_in, "Content-Length"); post_size = atoi(content_len); const char *content_type = evhtp_header_find(req->headers_in, "Content-Type"); if(strstr(content_type, "multipart/form-data") == 0) { LOG_PRINT(LOG_ERROR, "POST form error!"); goto err; } else if(strstr(content_type, "boundary") == 0) { LOG_PRINT(LOG_ERROR, "boundary NOT found!"); goto err; } boundary = strchr(content_type, '='); boundary++; boundary_len = strlen(boundary); if (boundary[0] == '"') { boundary++; boundary_end = strchr(boundary, '"'); if (!boundary_end) { LOG_PRINT(LOG_ERROR, "Invalid boundary in multipart/form-data POST data"); goto err; } } else { /* search for the end of the boundary */ boundary_end = strpbrk(boundary, ",;"); } if (boundary_end) { boundary_end[0] = '\0'; boundary_len = boundary_end-boundary; } LOG_PRINT(LOG_INFO, "boundary Find. boundary = %s", boundary); /* 依靠evbuffer自己实现php处理函数 */ evbuf_t *buf; buf = req->buffer_in; buff = (char *)malloc(post_size); int rmblen, evblen; int img_size = 0; if(evbuffer_get_length(buf) <= 0) { LOG_PRINT(LOG_ERROR, "Empty Request!"); goto err; } while((evblen = evbuffer_get_length(buf)) > 0) { LOG_PRINT(LOG_INFO, "evblen = %d", evblen); rmblen = evbuffer_remove(buf, buff, evblen); LOG_PRINT(LOG_INFO, "rmblen = %d", rmblen); if(rmblen < 0) { LOG_PRINT(LOG_ERROR, "evbuffer_remove failed!"); goto err; } } int start = -1, end = -1; const char *fileNamePattern = "filename="; const char *typePattern = "Content-Type"; const char *quotePattern = "\""; const char *blankPattern = "\r\n"; boundaryPattern = (char *)malloc(boundary_len + 4); sprintf(boundaryPattern, "\r\n--%s", boundary); LOG_PRINT(LOG_INFO, "boundaryPattern = %s, strlen = %d", boundaryPattern, (int)strlen(boundaryPattern)); if((start = kmp(buff, post_size, fileNamePattern, strlen(fileNamePattern))) == -1) { LOG_PRINT(LOG_ERROR, "Content-Disposition Not Found!"); goto err; } start += 9; if(buff[start] == '\"') { start++; if((end = kmp(buff+start, post_size-start, quotePattern, strlen(quotePattern))) == -1) { LOG_PRINT(LOG_ERROR, "quote \" Not Found!"); goto err; } } else { if((end = kmp(buff+start, post_size-start, blankPattern, strlen(blankPattern))) == -1) { LOG_PRINT(LOG_ERROR, "quote \" Not Found!"); goto err; } } fileName = (char *)malloc(end + 1); memcpy(fileName, buff+start, end); fileName[end] = '\0'; LOG_PRINT(LOG_INFO, "fileName = %s", fileName); char fileType[32]; if(get_type(fileName, fileType) == -1) { LOG_PRINT(LOG_ERROR, "Get Type of File[%s] Failed!", fileName); goto err; } if(is_img(fileType) != 1) { LOG_PRINT(LOG_ERROR, "fileType[%s] is Not Supported!", fileType); goto err; } end += start; if((start = kmp(buff+end, post_size-end, typePattern, strlen(typePattern))) == -1) { LOG_PRINT(LOG_ERROR, "Content-Type Not Found!"); goto err; } start += end; LOG_PRINT(LOG_INFO, "start = %d", start); if((end = kmp(buff+start, post_size-start, blankPattern, strlen(blankPattern))) == -1) { LOG_PRINT(LOG_ERROR, "Image Not complete!"); goto err; } end += start; LOG_PRINT(LOG_INFO, "end = %d", end); start = end + 4; LOG_PRINT(LOG_INFO, "start = %d", start); if((end = kmp(buff+start, post_size-start, boundaryPattern, strlen(boundaryPattern))) == -1) { LOG_PRINT(LOG_ERROR, "Image Not complete!"); goto err; } end += start; LOG_PRINT(LOG_INFO, "end = %d", end); img_size = end - start; LOG_PRINT(LOG_INFO, "post_size = %d", post_size); LOG_PRINT(LOG_INFO, "img_size = %d", img_size); if(img_size <= 0) { LOG_PRINT(LOG_ERROR, "Image Size is Zero!"); goto err; } char md5sum[33]; LOG_PRINT(LOG_INFO, "Begin to Save Image..."); if(save_img(buff+start, img_size, md5sum) == -1) { LOG_PRINT(LOG_ERROR, "Image Save Failed!"); goto err; } //libevhtp has bug with uri->authority->hostname, so zimg don't show hostname temporarily. //const char *host_name = req->uri->authority->hostname; //const int *host_port = req->uri->authority->port; //LOG_PRINT(LOG_INFO, "hostname: %s", req->uri->authority->hostname); //LOG_PRINT(LOG_INFO, "hostport: %d", host_port); evbuffer_add_printf(req->buffer_out, "<html>\n<head>\n" "<title>Upload Successfully</title>\n" "</head>\n" "<body>\n" "<h1>MD5: %s</h1>\n" "Image upload successfully! You can get this image via this address:<br/><br/>\n" "http://yourhostname:%d/%s?w=width&h=height&g=isgray\n" "</body>\n</html>\n", md5sum, settings.port, md5sum ); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============post_request_cb() DONE!==============="); goto done; err: evbuffer_add_printf(req->buffer_out, "<html><body><h1>Upload Failed!</h1></body><html>"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_200); LOG_PRINT(LOG_INFO, "============post_request_cb() ERROR!==============="); done: if(fileName) free(fileName); if(boundaryPattern) free(boundaryPattern); if(buff) free(buff); }
void wshtp_add_header(wshtp_conn_t *conn, const char *key, const char *val) { evhtp_headers_add_header(conn->reply.headers, evhtp_header_new(key, val, 1,1)); }
static void ws_headers_add_header(evhtp_headers_t *headers, const char *key, const char *val) { evhtp_headers_add_header(headers, evhtp_header_new(key, val, 1, 1)); }
/* Handle AJAX file upload. @return an array of json data, e.g. [{"name": "foo.txt"}] */ static void upload_ajax_cb(evhtp_request_t *req, void *arg) { RecvFSM *fsm = arg; SearpcClient *rpc_client = NULL; char *parent_dir; GError *error = NULL; int error_code = ERROR_INTERNAL; char *filenames_json, *tmp_files_json; evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Headers", "x-requested-with, content-type, accept, origin, authorization", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Allow-Origin", "*", 1, 1)); evhtp_headers_add_header (req->headers_out, evhtp_header_new("Access-Control-Max-Age", "86400", 1, 1)); if (evhtp_request_get_method(req) == htp_method_OPTIONS) { /* If CORS preflight header, then create an empty body response (200 OK) * and return it. */ evhtp_headers_add_header (req->headers_out, evhtp_header_new("Content-Type", "text/html; charset=utf-8", 1, 1)); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); return; } /* After upload_headers_cb() returns an error, libevhtp may still * receive data from the web browser and call into this cb. * In this case fsm will be NULL. */ if (!fsm || fsm->state == RECV_ERROR) return; if (!fsm->files) { seaf_warning ("[upload] No file uploaded.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } parent_dir = g_hash_table_lookup (fsm->form_kvs, "parent_dir"); if (!parent_dir) { seaf_warning ("[upload] No parent dir given.\n"); evbuffer_add_printf(req->buffer_out, "Invalid URL.\n"); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_BADREQ); return; } if (!check_tmp_file_list (fsm->files, &error_code)) goto error; rpc_client = ccnet_create_pooled_rpc_client (seaf->client_pool, NULL, "seafserv-threaded-rpcserver"); if (seafile_check_quota (rpc_client, fsm->repo_id, NULL) < 0) { seaf_warning ("[upload] Out of quota.\n"); error_code = ERROR_QUOTA; goto error; } filenames_json = file_list_to_json (fsm->filenames); tmp_files_json = file_list_to_json (fsm->files); seafile_post_multi_files (rpc_client, fsm->repo_id, parent_dir, filenames_json, tmp_files_json, fsm->user, &error); g_free (filenames_json); g_free (tmp_files_json); if (error) { if (error->code == POST_FILE_ERR_FILENAME) { error_code = ERROR_FILENAME; seaf_warning ("[upload] Bad filename.\n"); } g_clear_error (&error); goto error; } ccnet_rpc_client_free (rpc_client); GString *res_buf = g_string_new (NULL); GList *ptr; g_string_append (res_buf, "["); for (ptr = fsm->filenames; ptr; ptr = ptr->next) { char *filename = ptr->data; if (ptr->next) g_string_append_printf (res_buf, "{\"name\": \"%s\"}, ", filename); else g_string_append_printf (res_buf, "{\"name\": \"%s\"}", filename); } g_string_append (res_buf, "]"); evbuffer_add (req->buffer_out, res_buf->str, res_buf->len); g_string_free (res_buf, TRUE); set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_OK); return; error: if (rpc_client) ccnet_rpc_client_free (rpc_client); switch (error_code) { case ERROR_FILENAME: evbuffer_add_printf(req->buffer_out, "Invalid filename.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_BADFILENAME); break; case ERROR_EXISTS: evbuffer_add_printf(req->buffer_out, "File already exists.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_EXISTS); break; case ERROR_SIZE: evbuffer_add_printf(req->buffer_out, "File size is too large.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_TOOLARGE); break; case ERROR_QUOTA: evbuffer_add_printf(req->buffer_out, "Out of quota.\n"); set_content_length_header (req); evhtp_send_reply (req, SEAF_HTTP_RES_NOQUOTA); break; case ERROR_RECV: case ERROR_INTERNAL: set_content_length_header (req); evhtp_send_reply (req, EVHTP_RES_SERVERR); break; } }
/** * @brief send_document_cb The callback function of get a image request. * * @param req The request with a list of params and the md5 of image. * @param arg It is not useful. */ void send_document_cb(evhtp_request_t *req, void *arg) { char *md5 = NULL; size_t len; zimg_req_t *zimg_req = NULL; char *buff = NULL; int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_INFO, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") == 0) { LOG_PRINT(LOG_INFO, "POST Request."); post_request_cb(req, NULL); return; } else if(strcmp(method_strmap[req_method], "GET") != 0) { LOG_PRINT(LOG_INFO, "Request Method Not Support."); goto err; } const char *uri; uri = req->uri->path->full; const char *rfull = req->uri->path->full; const char *rpath = req->uri->path->path; const char *rfile= req->uri->path->file; LOG_PRINT(LOG_INFO, "uri->path->full: %s", rfull); LOG_PRINT(LOG_INFO, "uri->path->path: %s", rpath); LOG_PRINT(LOG_INFO, "uri->path->file: %s", rfile); if(strlen(uri) == 1 && uri[0] == '/') { LOG_PRINT(LOG_INFO, "Root Request."); int fd = -1; struct stat st; if((fd = open(settings.root_path, O_RDONLY)) == -1) { LOG_PRINT(LOG_WARNING, "Root_page Open Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { if (fstat(fd, &st) < 0) { /* Make sure the length still matches, now that we * opened the file :/ */ LOG_PRINT(LOG_WARNING, "Root_page Length fstat Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { evbuffer_add_file(req->buffer_out, fd, 0, st.st_size); } } evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); goto done; } if(strstr(uri, "favicon.ico")) { LOG_PRINT(LOG_INFO, "favicon.ico Request, Denied."); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); goto done; } LOG_PRINT(LOG_INFO, "Got a GET request for <%s>", uri); /* Don't allow any ".."s in the path, to avoid exposing stuff outside * of the docroot. This test is both overzealous and underzealous: * it forbids aceptable paths like "/this/one..here", but it doesn't * do anything to prevent symlink following." */ if (strstr(uri, "..")) goto err; md5 = (char *)malloc(strlen(uri) + 1); if(uri[0] == '/') strcpy(md5, uri+1); else strcpy(md5, uri); LOG_PRINT(LOG_INFO, "md5 of request is <%s>", md5); if(is_md5(md5) == -1) { LOG_PRINT(LOG_WARNING, "Url is Not a zimg Request."); goto err; } /* This holds the content we're sending. */ int width, height, proportion, gray; evhtp_kvs_t *params; params = req->uri->query; if(!params) { width = 0; height = 0; proportion = 1; gray = 0; } else { const char *str_w, *str_h; str_w = evhtp_kv_find(params, "w"); if(str_w == NULL) str_w = "0"; str_h = evhtp_kv_find(params, "h"); if(str_h == NULL) str_h = "0"; LOG_PRINT(LOG_INFO, "w() = %s; h() = %s;", str_w, str_h); if(strcmp(str_w, "g") == 0 && strcmp(str_h, "w") == 0) { LOG_PRINT(LOG_INFO, "Love is Eternal."); evbuffer_add_printf(req->buffer_out, "<html>\n <head>\n" " <title>Love is Eternal</title>\n" " </head>\n" " <body>\n" " <h1>Single1024</h1>\n" "Since 2008-12-22, there left no room in my heart for another one.</br>\n" "</body>\n</html>\n" ); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); goto done; } else { width = atoi(str_w); height = atoi(str_h); const char *str_p = evhtp_kv_find(params, "p"); const char *str_g = evhtp_kv_find(params, "g"); if(str_p) proportion = atoi(str_p); else proportion = 1; if(str_g) gray = atoi(str_g); else gray = 0; } } zimg_req = (zimg_req_t *)malloc(sizeof(zimg_req_t)); zimg_req -> md5 = md5; zimg_req -> width = width; zimg_req -> height = height; zimg_req -> proportion = proportion; zimg_req -> gray = gray; int get_img_rst = get_img(zimg_req, &buff, &len); if(get_img_rst == -1) { LOG_PRINT(LOG_ERROR, "zimg Requset Get Image[MD5: %s] Failed!", zimg_req->md5); goto err; } LOG_PRINT(LOG_INFO, "get buffer length: %d", len); evbuffer_add(req->buffer_out, buff, len); LOG_PRINT(LOG_INFO, "Got the File!"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/jpeg", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_INFO, "============send_document_cb() DONE!==============="); if(get_img_rst == 2) { if(new_img(buff, len, zimg_req->rsp_path) == -1) { LOG_PRINT(LOG_WARNING, "New Image[%s] Save Failed!", zimg_req->rsp_path); } } goto done; err: evbuffer_add_printf(req->buffer_out, "<html><body><h1>404 Not Found!</h1></body></html>"); //evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", "zimg/1.0.0 (Unix) (OpenSUSE/Linux)", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", server_name, 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_NOTFOUND); LOG_PRINT(LOG_INFO, "============send_document_cb() ERROR!==============="); done: if(buff) free(buff); if(zimg_req) { if(zimg_req->md5) free(zimg_req->md5); if(zimg_req->rsp_path) free(zimg_req->rsp_path); free(zimg_req); } }
/** * @brief get_request_cb The callback function of get a image request. * * @param req The request with a list of params and the md5 of image. * @param arg It is not useful. */ void get_request_cb(evhtp_request_t *req, void *arg) { char *md5 = NULL, *fmt = NULL, *type = NULL; zimg_req_t *zimg_req = NULL; char *buff = NULL; size_t len; evhtp_connection_t *ev_conn = evhtp_request_get_connection(req); struct sockaddr *saddr = ev_conn->saddr; struct sockaddr_in *ss = (struct sockaddr_in *)saddr; char address[16]; const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For"); if(xff_address) { inet_aton(xff_address, &ss->sin_addr); } strncpy(address, inet_ntoa(ss->sin_addr), 16); int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_DEBUG, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") == 0) { LOG_PRINT(LOG_DEBUG, "POST Request."); post_request_cb(req, NULL); return; } else if(strcmp(method_strmap[req_method], "GET") != 0) { LOG_PRINT(LOG_DEBUG, "Request Method Not Support."); LOG_PRINT(LOG_INFO, "%s refuse method", address); goto err; } if(settings.down_access != NULL) { int acs = zimg_access_inet(settings.down_access, ss->sin_addr.s_addr); LOG_PRINT(LOG_DEBUG, "access check: %d", acs); if(acs == ZIMG_FORBIDDEN) { LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address); LOG_PRINT(LOG_INFO, "%s refuse get forbidden", address); goto forbidden; } else if(acs == ZIMG_ERROR) { LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address); LOG_PRINT(LOG_ERROR, "%s fail get access", address); goto err; } } const char *uri; uri = req->uri->path->full; if(strlen(uri) == 1 && uri[0] == '/') { LOG_PRINT(LOG_DEBUG, "Root Request."); int fd = -1; struct stat st; if((fd = open(settings.root_path, O_RDONLY)) == -1) { LOG_PRINT(LOG_DEBUG, "Root_page Open Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { if (fstat(fd, &st) < 0) { /* Make sure the length still matches, now that we * opened the file :/ */ LOG_PRINT(LOG_DEBUG, "Root_page Length fstat Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg World!</h1>\n</body>\n</html>\n"); } else { evbuffer_add_file(req->buffer_out, fd, 0, st.st_size); } } //evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!==============="); LOG_PRINT(LOG_INFO, "%s succ root page", address); goto done; } if(strstr(uri, "favicon.ico")) { LOG_PRINT(LOG_DEBUG, "favicon.ico Request, Denied."); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); zimg_headers_add(req, settings.headers); evhtp_send_reply(req, EVHTP_RES_OK); goto done; } LOG_PRINT(LOG_DEBUG, "Got a GET request for <%s>", uri); /* Don't allow any ".."s in the path, to avoid exposing stuff outside * of the docroot. This test is both overzealous and underzealous: * it forbids aceptable paths like "/this/one..here", but it doesn't * do anything to prevent symlink following." */ if (strstr(uri, "..")) { LOG_PRINT(LOG_DEBUG, "attempt to upper dir!"); LOG_PRINT(LOG_INFO, "%s refuse directory", address); goto forbidden; } size_t md5_len = strlen(uri) + 1; md5 = (char *)malloc(md5_len); if(md5 == NULL) { LOG_PRINT(LOG_DEBUG, "md5 malloc failed!"); LOG_PRINT(LOG_ERROR, "%s fail malloc", address); goto err; } if(uri[0] == '/') str_lcpy(md5, uri+1, md5_len); else str_lcpy(md5, uri, md5_len); LOG_PRINT(LOG_DEBUG, "md5 of request is <%s>", md5); if(is_md5(md5) == -1) { LOG_PRINT(LOG_DEBUG, "Url is Not a zimg Request."); LOG_PRINT(LOG_INFO, "%s refuse url illegal", address); goto err; } /* This holds the content we're sending. */ evthr_t *thread = get_request_thr(req); thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread); int width, height, proportion, gray, x, y, rotate, quality, sv; width = 0; height = 0; proportion = 1; gray = 0; x = -1; y = -1; rotate = 0; quality = 0; sv = 0; evhtp_kvs_t *params; params = req->uri->query; if(params != NULL) { if(settings.disable_args != 1) { const char *str_w = evhtp_kv_find(params, "w"); const char *str_h = evhtp_kv_find(params, "h"); width = (str_w) ? atoi(str_w) : 0; height = (str_h) ? atoi(str_h) : 0; const char *str_p = evhtp_kv_find(params, "p"); proportion = (str_p) ? atoi(str_p) : 1; const char *str_g = evhtp_kv_find(params, "g"); gray = (str_g) ? atoi(str_g) : 0; const char *str_x = evhtp_kv_find(params, "x"); const char *str_y = evhtp_kv_find(params, "y"); x = (str_x) ? atoi(str_x) : -1; y = (str_y) ? atoi(str_y) : -1; if(x != -1 || y != -1) { proportion = 1; } const char *str_r = evhtp_kv_find(params, "r"); rotate = (str_r) ? atoi(str_r) : 0; const char *str_q = evhtp_kv_find(params, "q"); quality = (str_q) ? atoi(str_q) : 0; const char *str_f = evhtp_kv_find(params, "f"); if(str_f) { size_t fmt_len = strlen(str_f) + 1; fmt = (char *)malloc(fmt_len); if(fmt != NULL) str_lcpy(fmt, str_f, fmt_len); LOG_PRINT(LOG_DEBUG, "fmt = %s", fmt); } } if(settings.disable_type != 1) { const char *str_t = evhtp_kv_find(params, "t"); if(str_t) { size_t type_len = strlen(str_t) + 1; type = (char *)malloc(type_len); if(type != NULL) str_lcpy(type, str_t, type_len); LOG_PRINT(LOG_DEBUG, "type = %s", type); } } } else { sv = 1; } quality = (quality != 0 ? quality : settings.quality); zimg_req = (zimg_req_t *)malloc(sizeof(zimg_req_t)); if(zimg_req == NULL) { LOG_PRINT(LOG_DEBUG, "zimg_req malloc failed!"); LOG_PRINT(LOG_ERROR, "%s fail malloc", address); goto err; } zimg_req -> md5 = md5; zimg_req -> type = type; zimg_req -> width = width; zimg_req -> height = height; zimg_req -> proportion = proportion; zimg_req -> gray = gray; zimg_req -> x = x; zimg_req -> y = y; zimg_req -> rotate = rotate; zimg_req -> quality = quality; zimg_req -> fmt = (fmt != NULL ? fmt : settings.format); zimg_req -> sv = sv; zimg_req -> thr_arg = thr_arg; int get_img_rst = -1; get_img_rst = settings.get_img(zimg_req, req); if(get_img_rst == -1) { LOG_PRINT(LOG_DEBUG, "zimg Requset Get Image[MD5: %s] Failed!", zimg_req->md5); if(type) LOG_PRINT(LOG_ERROR, "%s fail pic:%s t:%s", address, md5, type); else LOG_PRINT(LOG_ERROR, "%s fail pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s", address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); goto err; } if(get_img_rst == 2) { LOG_PRINT(LOG_DEBUG, "Etag Matched Return 304 EVHTP_RES_NOTMOD."); if(type) LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s t:%s", address, md5, type); else LOG_PRINT(LOG_INFO, "%s succ 304 pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s", address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt); evhtp_send_reply(req, EVHTP_RES_NOTMOD); goto done; } len = evbuffer_get_length(req->buffer_out); LOG_PRINT(LOG_DEBUG, "get buffer length: %d", len); LOG_PRINT(LOG_DEBUG, "Got the File!"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/jpeg", 0, 0)); zimg_headers_add(req, settings.headers); evhtp_send_reply(req, EVHTP_RES_OK); if(type) LOG_PRINT(LOG_INFO, "%s succ pic:%s t:%s size:%d", address, md5, type, len); else LOG_PRINT(LOG_INFO, "%s succ pic:%s w:%d h:%d p:%d g:%d x:%d y:%d r:%d q:%d f:%s size:%d", address, md5, width, height, proportion, gray, x, y, rotate, quality, zimg_req->fmt, len); LOG_PRINT(LOG_DEBUG, "============get_request_cb() DONE!==============="); goto done; forbidden: evbuffer_add_printf(req->buffer_out, "<html><body><h1>403 Forbidden!</h1></body></html>"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_FORBIDDEN); LOG_PRINT(LOG_DEBUG, "============get_request_cb() FORBIDDEN!==============="); goto done; err: evbuffer_add_printf(req->buffer_out, "<html><body><h1>404 Not Found!</h1></body></html>"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_NOTFOUND); LOG_PRINT(LOG_DEBUG, "============get_request_cb() ERROR!==============="); done: free(fmt); free(md5); free(type); free(zimg_req); free(buff); }
static evbuffer * _evhtp_create_reply(evhtp_request_t * request, evhtp_res code) { evbuffer * buf = evbuffer_new(); if (evbuffer_get_length(request->buffer_out) && request->chunked == 0) { /* add extra headers (like content-length/type) if not already present */ if (!evhtp_header_find(request->headers_out, "Content-Length")) { std::ostringstream oss; oss<<evbuffer_get_length(request->buffer_out); std::string lstr=oss.str(); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Length", lstr.c_str(), 0, 1)); } if (!evhtp_header_find(request->headers_out, "Server")) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Server", "nginx/1.1.0", 0, 0)); } if (!evhtp_header_find(request->headers_out, "Content-Type")) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Type", "text/plain", 0, 0)); } } else { if (!evhtp_header_find(request->headers_out, "Content-Length")) { const char * chunked = evhtp_header_find(request->headers_out, "transfer-encoding"); if (!chunked || !strstr(chunked, "chunked")) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Length", "0", 0, 0)); } } } /* add the proper keep-alive type headers based on http version */ switch (request->proto) { case EVHTP_PROTO_11: if (request->keepalive == 0) { /* protocol is HTTP/1.1 but client wanted to close */ evhtp_headers_add_header(request->headers_out, evhtp_header_new("Connection", "close", 0, 0)); } break; case EVHTP_PROTO_10: if (request->keepalive == 1) { /* protocol is HTTP/1.0 and clients wants to keep established */ evhtp_headers_add_header(request->headers_out, evhtp_header_new("Connection", "keep-alive", 0, 0)); } break; default: /* this sometimes happens when a response is made but paused before * the method has been parsed */ request->conn->parser->set_major(1); request->conn->parser->set_minor(0); break; } /* switch */ /* add the status line */ evbuffer_add_printf(buf, "HTTP/%d.%d %d %s\r\n", request->conn->parser->get_major(), request->conn->parser->get_minor(), code, StatusCodeManager::instance().status_code_to_str(code)); evhtp_headers_for_each(request->headers_out, _evhtp_create_headers, buf); evbuffer_add_reference(buf, "\r\n", 2, NULL, NULL); if (evbuffer_get_length(request->buffer_out)) { evbuffer_add_buffer(buf, request->buffer_out); } return buf; } /* _evhtp_create_reply */
/** * @brief admin_request_cb the callback function of admin requests * * @param req the evhtp request * @param arg the arg of request */ void admin_request_cb(evhtp_request_t *req, void *arg) { char md5[33]; evhtp_connection_t *ev_conn = evhtp_request_get_connection(req); struct sockaddr *saddr = ev_conn->saddr; struct sockaddr_in *ss = (struct sockaddr_in *)saddr; char address[16]; const char *xff_address = evhtp_header_find(req->headers_in, "X-Forwarded-For"); if(xff_address) { inet_aton(xff_address, &ss->sin_addr); } strncpy(address, inet_ntoa(ss->sin_addr), 16); int req_method = evhtp_request_get_method(req); if(req_method >= 16) req_method = 16; LOG_PRINT(LOG_DEBUG, "Method: %d", req_method); if(strcmp(method_strmap[req_method], "POST") == 0) { LOG_PRINT(LOG_DEBUG, "POST Request."); post_request_cb(req, NULL); return; } else if(strcmp(method_strmap[req_method], "GET") != 0) { LOG_PRINT(LOG_DEBUG, "Request Method Not Support."); LOG_PRINT(LOG_INFO, "%s refuse method", address); goto err; } if(settings.admin_access != NULL) { int acs = zimg_access_inet(settings.admin_access, ss->sin_addr.s_addr); LOG_PRINT(LOG_DEBUG, "access check: %d", acs); if(acs == ZIMG_FORBIDDEN) { LOG_PRINT(LOG_DEBUG, "check access: ip[%s] forbidden!", address); LOG_PRINT(LOG_INFO, "%s refuse admin forbidden", address); goto forbidden; } else if(acs == ZIMG_ERROR) { LOG_PRINT(LOG_DEBUG, "check access: check ip[%s] failed!", address); LOG_PRINT(LOG_ERROR, "%s fail admin access", address); goto err; } } const char *uri; uri = req->uri->path->full; if(strstr(uri, "favicon.ico")) { LOG_PRINT(LOG_DEBUG, "favicon.ico Request, Denied."); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); zimg_headers_add(req, settings.headers); evhtp_send_reply(req, EVHTP_RES_OK); return; } LOG_PRINT(LOG_DEBUG, "Got a Admin request for <%s>", uri); int t; evhtp_kvs_t *params; params = req->uri->query; if(!params) { LOG_PRINT(LOG_DEBUG, "Admin Root Request."); int fd = -1; struct stat st; //TODO: use admin_path if((fd = open(settings.admin_path, O_RDONLY)) == -1) { LOG_PRINT(LOG_DEBUG, "Admin_page Open Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg Admin!</h1>\n</body>\n</html>\n"); } else { if (fstat(fd, &st) < 0) { /* Make sure the length still matches, now that we * opened the file :/ */ LOG_PRINT(LOG_DEBUG, "Root_page Length fstat Failed. Return Default Page."); evbuffer_add_printf(req->buffer_out, "<html>\n<body>\n<h1>\nWelcome To zimg Admin!</h1>\n</body>\n</html>\n"); } else { evbuffer_add_file(req->buffer_out, fd, 0, st.st_size); } } //evbuffer_add_printf(req->buffer_out, "<html>\n </html>\n"); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Server", settings.server_name, 0, 1)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); evhtp_send_reply(req, EVHTP_RES_OK); LOG_PRINT(LOG_DEBUG, "============admin_request_cb() DONE!==============="); LOG_PRINT(LOG_INFO, "%s succ admin root page", address); return; } else { const char *str_md5, *str_t; str_md5 = evhtp_kv_find(params, "md5"); if(str_md5 == NULL) { LOG_PRINT(LOG_DEBUG, "md5() = NULL return"); goto err; } str_lcpy(md5, str_md5, sizeof(md5)); if(is_md5(md5) == -1) { LOG_PRINT(LOG_DEBUG, "Admin Request MD5 Error."); LOG_PRINT(LOG_INFO, "%s refuse admin url illegal", address); goto err; } str_t = evhtp_kv_find(params, "t"); LOG_PRINT(LOG_DEBUG, "md5() = %s; t() = %s;", str_md5, str_t); t = (str_t) ? atoi(str_t) : 0; } evthr_t *thread = get_request_thr(req); thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread); int admin_img_rst = -1; admin_img_rst = settings.admin_img(req, thr_arg, md5, t); if(admin_img_rst == -1) { evbuffer_add_printf(req->buffer_out, "<html><body><h1>Admin Command Failed!</h1> \ <p>MD5: %s</p> \ <p>Command Type: %d</p> \ <p>Command Failed.</p> \ </body></html>", md5, t); LOG_PRINT(LOG_ERROR, "%s fail admin pic:%s t:%d", address, md5, t); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "text/html", 0, 0)); }