/* ********************************** * Websocket * **********************************/ static int do_ws_handshake(evhtp_request_t *req) { const char *upgrade = evhtp_header_find(req->headers_in, "Upgrade"); const char *connection = evhtp_header_find(req->headers_in, "Connection"); const char *ws_key = evhtp_header_find(req->headers_in, "Sec-WebSocket-Key"); if (upgrade && connection && ws_key) { if (!strstrcase(upgrade, "websocket") || !strstrcase(connection, "Upgrade")){ return EVHTP_RES_ERROR; } static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; unsigned char *str = calloc(strlen(ws_key)+strlen(magic)+1, sizeof(unsigned char)); strcpy((char *)str, ws_key); strcat((char *)str, magic); unsigned char hash[SHA_DIGEST_LENGTH]; SHA1(str, strlen((char *)str), hash); free(str); char ws_accept[29]; ws_accept[28] = '\0'; base64encode(&hash[0], sizeof(hash), &ws_accept[0], sizeof(ws_accept)-1); ws_headers_add_header(req->headers_out, "Connection", "Upgrade" ); ws_headers_add_header(req->headers_out, "Sec-WebSocket-Accept", &ws_accept[0]); ws_headers_add_header(req->headers_out, "Upgrade", "websocket"); evhtp_send_reply(req, EVHTP_RES_SWITCH_PROTO); return EVHTP_RES_SWITCH_PROTO; } return EVHTP_RES_OK; }
int binary_parse(evhtp_request_t *req, const char *content_type, const char *address, const char *buff, int post_size) { int err_no = 0; if(is_img(content_type) != 1) { LOG_PRINT(LOG_DEBUG, "fileType[%s] is Not Supported!", content_type); LOG_PRINT(LOG_ERROR, "%s fail post type", address); err_no = 1; goto done; } char md5sum[33]; evthr_t *thread = get_request_thr(req); thr_arg_t *thr_arg = (thr_arg_t *)evthr_get_aux(thread); const char *filename = evhtp_header_find(req->headers_in, "zimg-filename"); LOG_PRINT(LOG_DEBUG, "Begin to Save Image %s...", filename); if(save_img(thr_arg, filename, buff, post_size, md5sum) == -1) { LOG_PRINT(LOG_DEBUG, "Image Save Failed!"); LOG_PRINT(LOG_ERROR, "%s fail post save", address); goto done; } err_no = -1; LOG_PRINT(LOG_INFO, "%s succ post pic:%s size:%d", address, md5sum, post_size); json_return(req, err_no, md5sum, post_size); done: return err_no; }
static void send_reply_header(evhtp_request_t * req, const char * header) { evbuf_t * buf = evbuffer_new(); const char* found = evhtp_header_find(req->headers_in, header); evhtp_send_reply_chunk_start(req, EVHTP_RES_OK); evbuffer_add(buf, found, strlen(found)); evhtp_send_reply_chunk(req, buf); evbuffer_drain(buf, -1); evhtp_send_reply_chunk_end(req); evbuffer_free(buf); }
const std::string zxy_get_http_header( zxy_request_context *context, const std::string& name ) { std::string result; evhtp_headers_t *headers = context->request->headers_in; const char *header_val = evhtp_header_find(headers, name.c_str()); if ( header_val != NULL ) { result = header_val; } return result; }
bool zxy_get_http_header( zxy_request_context *context, const std::string& key, std::string& value ) { bool ret = false; evhtp_headers_t *headers = context->request->headers_in; const char *header_val = evhtp_header_find(headers, key.c_str()); if ( header_val != NULL ) { ret = true; value = header_val; } return ret; }
/** * @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; }
int mimetype_normalizer_int(evhtp_request_t *req, const char *header) { const char * accept_h = NULL; /* Search the HTTP headers for the 'accept:' tag */ if ((accept_h = evhtp_header_find(req->headers_in, header))) { if (strncmp("application/json", accept_h, strlen("application/json")) == 0) { return TYPE_APP_JSON; } else if (strncmp("application/xml", accept_h, strlen("application/xml")) == 0) { return TYPE_APP_XML; } else if (strncmp("application/xacml+xml", accept_h, strlen("application/xacml+xml")) == 0) { return TYPE_APP_XACML_XML; } else if (strncmp("application/xacml+json", accept_h, strlen("application/xacml+json")) == 0) { return TYPE_APP_XACML_JSON; } else { return TYPE_APP_UNKNOWN; } } /* The default answer is *//* */ return TYPE_APP_UNKNOWN; }
/** * @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); }
/** * @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); }
/** * @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)); }
const char *wshtp_request_get_header(wshtp_conn_t *conn, const char *key) { return evhtp_header_find(conn->request->headers_in, key); }
/** * @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); }
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 */