void cm_img(evhtp_request_t *req, void *arg) { int fd = open("../resource/players.png", O_RDONLY); if (fd == -1){ evhtp_send_reply(req, EVHTP_RES_OK); return; } int len = lseek(fd , 0 , SEEK_END); evbuffer_add_file(req->buffer_out, fd, 0, len); evhtp_send_reply(req, EVHTP_RES_OK); //close(fd); }
gboolean s3http_connection_file_send (S3HttpConnection *con, int fd, const gchar *resource_path, S3HttpConnection_on_entry_sent_cb on_entry_sent_cb, gpointer ctx) { gchar *req_path; gboolean res; FileSendData *data; struct evbuffer *output_buf = NULL; struct stat st; data = g_new0 (FileSendData, 1); data->on_entry_sent_cb = on_entry_sent_cb; data->ctx = ctx; LOG_debug (CON_SEND_LOG, "Sending file.. %p", data); if (fstat (fd, &st) < 0) { LOG_err (CON_SEND_LOG, "Failed to stat temp file !"); s3http_connection_on_file_send_error (con, (void *) data); return FALSE; } output_buf = evbuffer_new (); if (!output_buf || evbuffer_add_file (output_buf, fd, 0, st.st_size) < 0) { LOG_err (CON_SEND_LOG, "Failed to read temp file !"); s3http_connection_on_file_send_error (con, (void *) data); if (output_buf) evbuffer_free (output_buf); return FALSE; } req_path = g_strdup_printf ("%s", resource_path); LOG_debug (CON_SEND_LOG, "[%p %p] Sending %s file, req: %s, %"OFF_FMT" buff: %zd", con, data, resource_path, req_path, st.st_size, evbuffer_get_length (output_buf)); res = s3http_connection_make_request (con, resource_path, req_path, "PUT", output_buf, s3http_connection_on_file_send_done, s3http_connection_on_file_send_error, data ); g_free (req_path); evbuffer_free (output_buf); if (!res) { LOG_err (CON_SEND_LOG, "Failed to create HTTP request !"); s3http_connection_on_file_send_error (con, (void *) data); return FALSE; } return TRUE; }
static int answer_file(struct evbuffer *buf, const char *path, struct stat *st, const char *ck, int cklen, int offset, int maxlen) { struct stat local_st; int fd; int ret = 0; if (st == NULL) st = &local_st; if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, st) < 0) { ret = SELECT_ENOTFOUND; goto answer_file_errout; } if (ck && cklen) { char ckbuf[128]; snprintf(ckbuf, sizeof(ckbuf), "%d-%d", (int) st->st_dev, (int) st->st_ino); if ((size_t) cklen != strlen(ckbuf) || strncmp(ck, ckbuf, cklen) != 0) { ret = SELECT_ECHANGED; goto answer_file_errout; } } if (offset < 0) offset += st->st_size; if (offset < 0) offset = 0; if (offset > st->st_size) { ret = SELECT_ERANGE; goto answer_file_errout; } if (maxlen < 0 || offset + maxlen > st->st_size) maxlen = st->st_size - offset; if (maxlen == 0) { close(fd); return 0; } if (evbuffer_add_file(buf, fd, offset, maxlen) == 0) return 0; answer_file_errout: if (fd >= 0) close(fd); if (ret < 0) return ret; return SELECT_EUNKNOWN; }
void wshtp_send_file(wshtp_conn_t *conn, const char *filename) { if (conn->is_websocket) { } else { int fd = open(filename, O_RDONLY); if (fd >= 0) { off_t size = lseek(fd, 0L, SEEK_END); lseek(fd, 0L, SEEK_SET); const char * type = get_mime_type(filename); wshtp_add_header(conn, "Content-Type", type); evbuffer_add_file(conn->reply.out, fd, 0, size); wshtp_send_reply(conn); close(fd); } } }
/* * request start - end * if file_size < end; * return start - file_size * */ void read_chunk(uint64_t chunkid, struct evhttp_request *req) { DBG(); struct evbuffer *evb = evbuffer_new(); hdd_chunk *chunk = chunk_hashtable_get(chunkid); if (chunk == NULL) { reply_error(req, HTTP_NOTFOUND, "not found chunk %" PRIx64 ";", chunkid); return; } hdd_chunk_printf(chunk); uint64_t start = 0, end = 0; const char *range = evhttp_find_header(req->input_headers, "Range"); struct stat st; logging(LOG_DEUBG, "get range : %s", range); int fd = open(chunk->path, O_RDONLY); if (fstat(fd, &st) < 0) { reply_error(req, HTTP_NOTFOUND, "file not exist : %s", chunk->path); return; } logging(LOG_DEUBG, "st.st_size = : %d", st.st_size); if (range) { sscanf(range, "bytes=%" SCNu64 "-%" SCNu64, &start, &end); //假设文件st_size = 2 //if end = 0, 应该返回1个字节 end=end //if end = 1, 应该返回0,1 共2个字节. end = st_size - 1 || end = end //if end = 2, 还是应该2个字节. end = st_size - 1 if (st.st_size <= end) end = st.st_size - 1; } else { start = 0; end = st.st_size - 1; } logging(LOG_DEUBG, "get return range : %" PRIu64 " - %" PRIu64, start, end); logging(LOG_DEUBG, "d : %" PRIu64, end - start + 1); lseek(fd, start, SEEK_SET); evbuffer_add_file(evb, fd, (int)start, end - start + 1); //如果编译的时候加上 -D_FILE_OFFSET_BITS=64 ,,evbuffer认为length = 0 evhttp_send_reply(req, HTTP_OK, "OK", evb); evbuffer_free(evb); }
static void send_document_cb(struct evhttp_request *req, void *arg) { struct evbuffer *evb = NULL; const char *uri = evhttp_request_get_uri(req); char *whole_path = NULL; int fd = -1, fsize; printf("Got a GET request for <%s>\n", uri); fsize = encode_request_to_file_path(uri, &whole_path); if (!fsize) { goto err; } evb = evbuffer_new(); const char *type = guess_content_type(whole_path); if ((fd = open(whole_path, O_RDONLY)) < 0) { perror("open"); goto err; } evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", type); evbuffer_add_file(evb, fd, 0, fsize); evhttp_send_reply(req, 200, "OK", evb); goto done; err: evhttp_send_error(req, 404, "Document was not found"); if (fd>=0) { close(fd); } done: if (whole_path) { free(whole_path); } if (evb) { evbuffer_free(evb); } }
/* Either file size was sent and now we send the file, or the file was sent and we delete the connection */ inline void FileServer::write_cb(struct bufferevent *bev, void *context) { try { auto u_ctx = static_cast<UploadContext*>(context); if(u_ctx->size_sent()) { LOG_DEBUG("File size was sent, sending file "); evbuffer_add_file(bufferevent_get_output(bev), u_ctx->fd(), 0, u_ctx->file()->size()); bufferevent_setwatermark(bev, EV_WRITE, 0, 0); u_ctx->size_sent(false); u_ctx->transfer_started(true); LOG_DEBUG("File transfer has started "); } else if(u_ctx->transfer_started()) { LOG_DEBUG("Transfer Completed"); FileServer * server = static_cast<FileServer*>(u_ctx->reader()); server->TransferDone(u_ctx); } } catch(std::exception& e) { LOG_ERR(e.what()); delete static_cast<ConnectionContext*>(context); exit(EXIT_FAILURE); } }
static void start_srv (OutData *out) { struct sockaddr_in sin; int port = 8080; struct stat st; int fd; char in_file[] = "./file.in"; // read input file if (stat (in_file, &st) == -1) { LOG_err (HTTP_TEST, "Failed to stat file %s", in_file); return; } out->in_file_size = st.st_size; fd = open (in_file, O_RDONLY); if (fd < 0) { LOG_err (HTTP_TEST, "Failed to open file %s", in_file); return; } out->in_file = evbuffer_new (); evbuffer_add_file (out->in_file, fd, 0, st.st_size); LOG_debug (HTTP_TEST, "SRV: filesize %ld bytes, in buf: %zd", out->in_file_size, evbuffer_get_length (out->in_file)); // start listening on port memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons (port); out->listener = evconnlistener_new_bind (out->evbase, accept_cb, out, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE, -1, (struct sockaddr*)&sin, sizeof (sin) ); if (!out->listener) LOG_err (HTTP_TEST, "OPS !"); }
bool NFCHttpServer::ResponseFile(const NFHttpRequest& req, const std::string& strPath, const std::string& strFileName) { //Add response type std::map<std::string, std::string> typeMap; typeMap["txt"] = "text/plain"; typeMap["txt"] = "text/plain"; typeMap["c"] = "text/plain"; typeMap["h"] = "text/plain"; typeMap["html"] = "text/html"; typeMap["htm"] = "text/htm"; typeMap["css"] = "text/css"; typeMap["gif"] = "image/gif"; typeMap["jpg"] = "image/jpeg"; typeMap["jpeg"] = "image/jpeg"; typeMap["png"] = "image/png"; typeMap["pdf"] = "application/pdf"; typeMap["ps"] = "application/postsript"; std::string strFilePath = strPath; if (strFilePath.find_last_of("/") != strFilePath.size()) { strFilePath += "/"; } strFilePath = strFilePath + req.url; int fd = -1; struct stat st; if (stat(strFilePath.c_str(), &st) < 0) { std::string errMsg = strFilePath + strFileName; ResponseMsg(req, errMsg.c_str(), NFWebStatus::WEB_ERROR, errMsg.c_str()); return false; } if (S_ISDIR(st.st_mode)) { strFilePath += "/" + strFileName; } if (stat(strFilePath.c_str(), &st) < 0) { std::string errMsg = strFilePath + strFilePath; ResponseMsg(req, errMsg.c_str(), NFWebStatus::WEB_ERROR, errMsg.c_str()); return false; } #if NF_PLATFORM == NF_PLATFORM_WIN if ((fd = open(strFilePath.c_str(), O_RDONLY | O_BINARY)) < 0) { #else if ((fd = open(strFilePath.c_str(), O_RDONLY)) < 0) { #endif ResponseMsg(req, "error", NFWebStatus::WEB_ERROR, "error"); return false; } if (fstat(fd, &st) < 0) { ResponseMsg(req, "error", NFWebStatus::WEB_ERROR, "error"); return false; } const char* last_period = strrchr(strFilePath.c_str(), '.'); std::string strType = last_period + 1; if (typeMap.find(strType) == typeMap.end()) { strType = "application/misc"; } else { strType = typeMap[strType]; } ResponseFile(req, fd, st, strType); return false; } bool NFCHttpServer::ResponseFile(const NFHttpRequest& req, const int fd, struct stat st, const std::string& strType) { evhttp_request* pHttpReq = (evhttp_request*) req.req; //create buffer struct evbuffer* eventBuffer = evbuffer_new(); //send data evbuffer_add_file(eventBuffer, fd, 0, st.st_size); evhttp_add_header(evhttp_request_get_output_headers(pHttpReq), "Content-Type", strType.c_str()); evhttp_send_reply(pHttpReq, 200, "OK", eventBuffer); //free evbuffer_free(eventBuffer); return true; }
/** * @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)); }
/** * This callback gets invoked when we get any http request that doesn't match * any other callback. Like any evhttp server callback, it has a simple job: * it must eventually call evhttp_send_error() or evhttp_send_reply(). */ static void generic_request_cb(struct evhttp_request *req, void *arg) { std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); // if this is not a GET request error out if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) { std::cerr << "Invalid request! Needs to be GET" << std::endl; evhttp_send_error(req, HTTP_BADREQUEST, 0); } else { struct evbuffer *evb = NULL; const char *docroot = (char *) arg; const char *uri = evhttp_request_get_uri(req); struct evhttp_uri *decoded = NULL; const char *path; char *decoded_path; char *whole_path = NULL; size_t len; int fd = -1; struct stat st; printf("Got a GET request for %s\n", uri); // Decode the URI decoded = evhttp_uri_parse(uri); if (!decoded) { printf("It's not a good URI. Sending BADREQUEST\n"); evhttp_send_error(req, HTTP_BADREQUEST, 0); return; } // Let's see what path the user asked for path = evhttp_uri_get_path(decoded); if (!path) { path = zsearch::server::ROOT.c_str(); } // We need to decode it, to see what path the user really wanted decoded_path = evhttp_uridecode(path, 0, NULL); bool error = false; if (decoded_path == NULL) { error = true; } else { // This holds the content we're sending evb = evbuffer_new(); // add headers evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html"); if (zsearch::server::POST_HTM.compare(decoded_path) == 0) { len = strlen(decoded_path)+strlen(docroot)+2; whole_path = (char *) malloc(len); if (whole_path) { evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path); if (stat(whole_path, &st)<0) { error = true; } else { if ((fd = open(whole_path, O_RDONLY)) < 0) { perror("open"); error = true; } else { if (fstat(fd, &st)<0) { // Make sure the length still matches, now that we opened the file :/ perror("fstat"); error = true; } else { evbuffer_add_file(evb, fd, 0, st.st_size); } } } } else { perror("malloc"); error = true; } } else // if (ROOT.compare(decoded_path) == 0) { evbuffer_add_printf(evb, "Invalid request <br />\n"); evbuffer_add_printf(evb, "%s to post data manually or %s to post via api<br />\n", zsearch::server::POST_HTM.c_str(), zsearch::server::INDEX_PATH.c_str()); evbuffer_add_printf(evb, "%s to search <br />\n", zsearch::server::SEARCH_PATH.c_str()); evbuffer_add_printf(evb, "%s to get document by id <br />\n", zsearch::server::DOC_PATH.c_str()); } } if (error) { if (fd >= 0) close(fd); evhttp_send_error(req, 404, "Document not found."); } else { evhttp_send_reply(req, 200, "OK", evb); } if (decoded) evhttp_uri_free(decoded); if (decoded_path) free(decoded_path); if (whole_path) free(whole_path); if (evb) evbuffer_free(evb); } std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds timeTaken = std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0); std::cout << ZUtil::printTimeTaken(timeTaken) << std::endl; }
/** * @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); } }
static void cd_StaticRequest (struct evhttp_request* request, CDServer* server) { int error = HTTP_OK; const char* message = "OK"; const char* uri = evhttp_request_get_uri(request); struct evhttp_uri* decoded = evhttp_uri_parse(uri); if (evhttp_request_get_command(request) != EVHTTP_REQ_GET) { error = HTTP_BADMETHOD; message = "Invalid request method"; goto end; } if (!decoded || strstr(evhttp_uri_get_path(decoded), "..")) { error = HTTP_BADREQUEST; message = "Bad request"; goto end; } DO { CDString* path = CD_CreateStringFromFormat("%s/%s", server->config->cache.httpd.root, evhttp_uri_get_path(decoded) ? evhttp_uri_get_path(decoded) : "index.html"); if (CD_IsDirectory(CD_StringContent(path))) { CD_AppendCString(path, "/index.html"); } if (!CD_IsReadable(CD_StringContent(path))) { error = HTTP_NOTFOUND; message = "File not found"; CD_DestroyString(path); goto end; } struct evbuffer* buffer = evbuffer_new(); int fd = open(CD_StringContent(path), O_RDONLY); evhttp_add_header(evhttp_request_get_output_headers(request), "Content-Type", cd_GuessContentType(CD_StringContent(path))); evbuffer_add_file(buffer, fd, 0, CD_FileSize(CD_StringContent(path))); evhttp_send_reply(request, HTTP_OK, "OK", buffer); evbuffer_free(buffer); CD_DestroyString(path); } end: { if (decoded) { evhttp_uri_free(decoded); } if (error != HTTP_OK) { evhttp_send_error(request, error, message); } } }
static void answer_key(struct evbuffer *buf, const char *key) { int bid; boardheader_t *bptr; if (isdigit(*key)) { char *p; if ((bid = atoi(key)) == 0 || bid > MAX_BOARD) return; if ((p = strchr(key, '.')) == NULL) return; bptr = getbcache(bid); if (!bptr->brdname[0] || BOARD_HIDDEN(bptr)) return; key = p + 1; if (strcmp(key, "isboard") == 0) evbuffer_add_printf(buf, "%d", (bptr->brdattr & BRD_GROUPBOARD) ? 0 : 1); else if (strcmp(key, "over18") == 0) evbuffer_add_printf(buf, "%d", (bptr->brdattr & BRD_OVER18) ? 1 : 0); else if (strcmp(key, "hidden") == 0) evbuffer_add_printf(buf, "%d", BOARD_HIDDEN(bptr) ? 1 : 0); else if (strcmp(key, "brdname") == 0) evbuffer_add(buf, bptr->brdname, strlen(bptr->brdname)); else if (strcmp(key, "title") == 0) evbuffer_add(buf, bptr->title + 7, strlen(bptr->title) - 7); else if (strcmp(key, "class") == 0) evbuffer_add(buf, bptr->title, 4); else if (strcmp(key, "BM") == 0) evbuffer_add(buf, bptr->BM, strlen(bptr->BM)); else if (strcmp(key, "parent") == 0) evbuffer_add_printf(buf, "%d", bptr->parent); else if (strcmp(key, "count") == 0) { char path[PATH_MAX]; setbfile(path, bptr->brdname, FN_DIR); evbuffer_add_printf(buf, "%d", get_num_records(path, sizeof(fileheader_t))); } else if (strcmp(key, "children") == 0) { if (!(bptr->brdattr & BRD_GROUPBOARD)) return; for (bid = bptr->firstchild[1]; bid > 0; bid = bptr->next[1]) { bptr = getbcache(bid); evbuffer_add_printf(buf, "%d,", bid); } } else if (strncmp(key, "articles.", 9) == 0) { int offset, length; key += 9; if (!isdigit(*key) && *key != '-') return; offset = atoi(key); p = strchr(key, '.'); if (!p || (length = atoi(p+1)) == 0) length = DEFAULT_ARTICLE_LIST; article_list(buf, bptr, offset, length); } else if (strncmp(key, "article.", 8) == 0) { if (!is_valid_article_filename(key + 8)) return; char path[PATH_MAX]; struct stat st; int fd; setbfile(path, bptr->brdname, key + 8); if ((fd = open(path, O_RDONLY)) < 0) return; if (fstat(fd, &st) < 0 || st.st_size == 0 || evbuffer_add_file(buf, fd, 0, st.st_size) != 0) close(fd); } else if (strncmp(key, "articlestat.", 12) == 0) { if (!is_valid_article_filename(key + 12)) return; char path[PATH_MAX]; struct stat st; setbfile(path, bptr->brdname, key + 12); if (stat(path, &st) < 0) return; evbuffer_add_printf(buf, "%d-%d,%ld", (int) st.st_dev, (int) st.st_ino, st.st_size); } else if (strncmp(key, "articlepart.", 12) == 0) { answer_articleselect(buf, bptr, key + 12, select_article_part, NULL); } else if (strncmp(key, "articlehead.", 12) == 0) { answer_articleselect(buf, bptr, key + 12, select_article_head, NULL); } else if (strncmp(key, "articletail.", 12) == 0) { answer_articleselect(buf, bptr, key + 12, select_article_tail, NULL); } else return; } else if (strncmp(key, "tobid.", 6) == 0) { bid = getbnum(key + 6); bptr = getbcache(bid); if (!bptr->brdname[0] || BOARD_HIDDEN(bptr)) return; evbuffer_add_printf(buf, "%d", bid); #if HOTBOARDCACHE } else if (strncmp(key, "hotboards", 9) == 0) { for (bid = 0; bid < SHM->nHOTs; bid++) { bptr = getbcache(SHM->HBcache[bid] + 1); if (BOARD_HIDDEN(bptr)) continue; evbuffer_add_printf(buf, "%d,", SHM->HBcache[bid] + 1); } #endif } }
static void static_files_cb(struct evhttp_request *req, void *arg) { http_serverlog_request(req); const char *static_root = arg; apr_pool_t *local_pool; const char *full_name; struct stat64 file_stat; const char *mime_type; if(!static_root) { LOG4C_ERROR(logger, "static root not configured"); evhttp_send_error(req, HTTP_NOTFOUND, "Static file server not configured"); return; } const char *uri = evhttp_request_get_uri(req); if (strstr(uri, "..") != NULL) { LOG4C_ERROR(logger, "illegal URL"); evhttp_send_error(req, HTTP_BADREQUEST, "Illegal URL"); return; } CREATE_POOL(local_pool, NULL); const char *path = get_path_from_uri(local_pool, uri); mime_type = guess_mime_type(uri); LOG4C_DEBUG(logger, "mime type is %s", mime_type); full_name = apr_pstrcat(local_pool, static_root, "/", path, NULL); if (lstat64(full_name, &file_stat) < 0) { LOG4C_ERROR(logger, "file not found"); evhttp_send_error(req, HTTP_NOTFOUND, NULL); return; } int fd = open(full_name, O_RDONLY); if (fd < 0) { LOG4C_ERROR(logger, "open failed"); evhttp_send_error(req, HTTP_NOTFOUND, NULL); return; } struct evbuffer *rep_buf = evbuffer_new(); evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", mime_type); evbuffer_set_flags(rep_buf, EVBUFFER_FLAG_DRAINS_TO_FD); //TODO: LIBEVENT DOES NOT SUPPORT LARGE FILES - USES off_t BUT _FILE_OFFSET_BITS=64 IS NOT DEFINED! evbuffer_add_file(rep_buf, fd, 0, file_stat.st_size); // evhttp_send_reply(req, HTTP_OK, "OK", rep_buf); evbuffer_free(rep_buf); RELEASE_POOL(local_pool); }
void createResponse(bufferevent *pBufferEvent) { struct evbuffer* pInputBuffer = bufferevent_get_input(pBufferEvent); struct evbuffer* pOutputBuffer = bufferevent_get_output(pBufferEvent); char *line; size_t size = 0; line = evbuffer_readln(pInputBuffer, &size, EVBUFFER_EOL_CRLF); std::string Request = std::string(line); //std::cout << Request << "\n"; //read method and path size_t nMethodEnd = Request.find(" "); std::string sMethod = std::string(Request, 0, nMethodEnd); //std::cout << sMethod << "\n"; size_t nPathEnd = Request.find(" ", nMethodEnd+1); std::string sRawPath = std::string(Request, nMethodEnd+1, nPathEnd-nMethodEnd-1); //std::cout << sRawPath << "\n"; size_t nDelimPos = sRawPath.find('?'); std::string sHalfRawPath = sRawPath.substr(0, nDelimPos); //std::cout << sHalfRawPath << "\n"; char* sTempPath = new char[sHalfRawPath.length()+1]; // at most the same size + term\0 urlDecode(sTempPath, sHalfRawPath.c_str()); std::string sPath = std::string(sTempPath); //std::cout << sPath << "\n"; if (Request.find(" ", nPathEnd+1) != std::string::npos) { // extra spaces in request //std::cout << "ERROR: extra spaces\n"; writeHeader(pOutputBuffer, STATUS_BAD_REQUEST, TYPE_HTML, MASSAGE_LENGTH_BAD_REQUEST); evbuffer_add(pOutputBuffer, MASSAGE_BAD_REQUEST, MASSAGE_LENGTH_BAD_REQUEST); return; } //Validate path if(!validatePath(sPath)) { //std::cout << "Warning: forbidden path\n"; writeHeader(pOutputBuffer, STATUS_FORBIDDEN, TYPE_HTML, MASSAGE_LENGTH_FORBIDDEN); evbuffer_add(pOutputBuffer, MASSAGE_FORBIDDEN, MASSAGE_LENGTH_FORBIDDEN); return; } //std::cout << "Ok: path ok\n"; //find target file std::string sRealPath = std::string(DOCUMENT_ROOT); sRealPath.append(std::string(sPath)); bool bIndex = false; if (sRealPath[sRealPath.length()-1] == '/') { //std::cout << "Ok: index\n"; sRealPath.append("index.html"); bIndex = true; } int fFile = open(sRealPath.c_str(), O_NONBLOCK|O_RDONLY); if (fFile == -1) { //std::cout << "Warning: file not opened\n"; if (bIndex) { writeHeader(pOutputBuffer, STATUS_FORBIDDEN, TYPE_HTML, MASSAGE_LENGTH_FORBIDDEN); evbuffer_add(pOutputBuffer, MASSAGE_FORBIDDEN, MASSAGE_LENGTH_FORBIDDEN); } else { writeHeader(pOutputBuffer, STATUS_NOT_FOUND, TYPE_HTML, MASSAGE_LENGTH_NOT_FOUND); evbuffer_add(pOutputBuffer, MASSAGE_NOT_FOUND, MASSAGE_LENGTH_NOT_FOUND); } return; } //std::cout << "Ok: file opened\n"; struct stat FileStats; fstat(fFile, &FileStats); if(!strcmp(sMethod.c_str(), METHOD_GET)) { //std::cout << "Ok: method \"get\"\n"; writeHeader(pOutputBuffer, STATUS_OK, getContentType(sRealPath), FileStats.st_size); evbuffer_add_file(pOutputBuffer, fFile, 0, FileStats.st_size); } else if(!strcmp(sMethod.c_str(), METHOD_HEAD)){ //std::cout << "Ok: method \"head\"\n"; // ctime gives only /n so we'll add proper CRLF writeHeader(pOutputBuffer, STATUS_OK, getContentType(sRealPath), FileStats.st_size); evbuffer_add(pOutputBuffer, CRLF, 2); } else { writeHeader(pOutputBuffer, STATUS_BAD_REQUEST, TYPE_HTML, MASSAGE_LENGTH_BAD_REQUEST); evbuffer_add(pOutputBuffer, MASSAGE_BAD_REQUEST, MASSAGE_LENGTH_BAD_REQUEST); } return; }
/** * @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 void static_list_request_cb(struct evhttp_request *req, void *arg) { struct evbuffer *evb = NULL; struct evhttp_uri *decoded = NULL; const char *path; char *decoded_path; int fd = -1; struct stat st; char uri_root[512] = {0}; struct evhttp_bound_socket *handle = (struct evhttp_bound_socket *)arg; size_t len; char *whole_path = NULL; const char *uri = evhttp_request_get_uri(req); get_uri_root(handle, uri_root, sizeof(uri_root)); decoded = evhttp_uri_parse(uri); if (decoded == NULL) { LOG(LOG_ERROR, "%s", "evhttp_decode_uri error"); evhttp_send_error(req, HTTP_BADREQUEST, 0); exit(1); } path = evhttp_uri_get_path(decoded); if (!path) path = "/"; decoded_path = evhttp_uridecode(path, 0, NULL); if (decoded_path == NULL) goto err; if (strstr(decoded_path, "..")) goto err; len = strlen(decoded_path)+strlen(docroot)+2; if (!(whole_path = malloc(len))) { perror("malloc"); goto err; } evutil_snprintf(whole_path, len, "%s/%s", docroot, decoded_path); if (stat(whole_path, &st)<0) { goto err; } evb = evbuffer_new(); if (S_ISDIR(st.st_mode)) { DIR *d; struct dirent *ent; const char *trailing_slash = ""; if (!strlen(path) || path[strlen(path)-1] != '/') trailing_slash = "/"; if (!(d = opendir(whole_path))) goto err; evbuffer_add_printf(evb, "<html>\n <head>\n" " <title>%s</title>\n" " <base href='%s%s%s'>\n" " </head>\n" " <body>\n" " <h1>%s</h1>\n" " <ul>\n", decoded_path, /* XXX html-escape this. */ uri_root, path, /* XXX html-escape this? */ trailing_slash, decoded_path /* XXX html-escape this */); while((ent = readdir(d))) { const char *name = ent->d_name; evbuffer_add_printf(evb, " <li><a href=\"%s\">%s</a>\n", name, name); evbuffer_add_printf(evb, "</ul></body></html>\n"); } closedir(d); evhttp_add_header(evhttp_request_get_output_headers(req), "Content-type", "text/html"); } else { const char *type = guess_content_type(decoded_path); if ((fd = open(whole_path, O_RDONLY)) < 0) { perror("open"); goto err; } if (fstat(fd, &st)<0) { /* Make sure the length still matches, now that we * opened the file :/ */ perror("fstat"); goto err; } evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", type); evbuffer_add_file(evb, fd, 0, st.st_size); } evhttp_send_reply(req, HTTP_OK, "OK", evb); goto done; err: evhttp_send_error(req, HTTP_NOTFOUND, "Document was not found"); if (fd>=0) close(fd); done: if (decoded) evhttp_uri_free(decoded); if (decoded_path) free(decoded_path); if (whole_path) free(whole_path); if (evb) evbuffer_free(evb); }
/** * Called by libevent when there is data to read. */ void buffered_on_read(struct bufferevent *bev, void *arg) { client_t *client = (client_t *)arg; char *line; size_t n; /* If we have input data, the number of bytes we have is contained in * bev->input->off. Copy the data from the input buffer to the output * buffer in 4096-byte chunks. There is a one-liner to do the whole thing * in one shot, but the purpose of this server is to show actual real-world * reading and writing of the input and output buffers, so we won't take * that shortcut here. */ struct evbuffer *input = bufferevent_get_input(bev); line = evbuffer_readln(input, &n, EVBUFFER_EOL_CRLF); char cmd[256], protocol[256], path[MAX_PATH_SIZE]; httpHeader_t httpHeader; httpHeader.command = UNKNOWN_C; httpHeader.status = OK; if (n != 0) { int scaned = sscanf(line, "%s %s %s\n", cmd, path, protocol); if (scaned == 3) { if (!strcmp(cmd, "GET")) { httpHeader.command = GET; } else if (!strcmp(cmd, "HEAD")) { httpHeader.command = HEAD; } else { httpHeader.command = UNKNOWN_C; } /* if (strcmp(protocol, "HTTP/1.1")) { printf("BAD PROTOCOL%s\n", protocol); httpHeader.status = BAD_REQUEST; }*/ if (path[0] != '/') { printf("BAD INPUtT\n"); httpHeader.status = BAD_REQUEST; } urlDecode(path); httpHeader.type = getContentType(path); if (getDepth(path) == -1) { printf("BAD DEPTH\n"); httpHeader.status = BAD_REQUEST; } } else { printf("Bad scanned\n"); httpHeader.status = BAD_REQUEST; } } else { printf("OOO BAD N\n"); httpHeader.status = BAD_REQUEST; } switch (httpHeader.status) { case BAD_REQUEST: printf("Bad request\n"); break; case OK: printf("OK\n"); break; case NOT_FOUND: printf("NOt found\n"); break; } switch (httpHeader.command) { case UNKNOWN_C: printf("UNKNOWS\n"); break; case GET: printf("GET\n"); break; case HEAD: printf("HEAD\n"); break; } printf("%s\n", path); free(line); if (httpHeader.status != BAD_REQUEST) { char fullPath[2048] = {'\0'}; strcpy(fullPath, ROOT_PATH); strcat(fullPath, path); int fd = open(fullPath, O_RDONLY); if (fd < 0) { httpHeader.status = NOT_FOUND; printf("Can't open %s", fullPath); } client->openFd = -1; struct stat st; httpHeader.length = lseek(fd, 0, SEEK_END); if (httpHeader.length == -1 || lseek(fd, 0, SEEK_SET) == -1) { httpHeader.status = BAD_REQUEST; printf("Cant seek\n"); } addHeader(&httpHeader, client->output_buffer); if (fstat(fd, &st) < 0) { perror("fstat"); } if (fd != -1 && httpHeader.status == OK && httpHeader.command == GET) { evbuffer_set_flags(client->output_buffer, EVBUFFER_FLAG_DRAINS_TO_FD); if(evbuffer_add_file(client->output_buffer, fd, 0, httpHeader.length) != 0) { perror("add file"); } } // printf("%d\n", fd); } //evbuffer_add(client->output_buffer, "AAA", 3); /* while ((line = evbuffer_readln(input, &n, EVBUFFER_EOL_CRLF))) { evbuffer_add(client->output_buffer, line, n); evbuffer_add(client->output_buffer, "\n", 1); free(line); }*/ //evbuffer_add_printf(client->output_buffer, "HTTP/1.1 200 OK\r\rContent-Type: text/html\r\nDate: Sun, 14 Sep 2014 08:39:53 GMT\r\nContent-Length: 5\r\n\r\n OKK\r\n"); // while (evbuffer_get_length(input) > 0) { /* Remove a chunk of data from the input buffer, copying it into our * local array (data). */ // nbytes = evbuffer_remove(input, data, 4096); /* Add the chunk of data from our local array (data) to the client's * output buffer. */ // evbuffer_add(client->output_buffer, data, nbytes); //} /* Send the results to the client. This actually only queues the results * for sending. Sending will occur asynchronously, handled by libevent. */ if (bufferevent_write_buffer(bev, client->output_buffer) == -1) { errorOut("Error sending data to client on fd %d\n", client->fd); } //bufferevent_setcb(bev, NULL, buffered_on_write, NULL, NULL); //bufferevent_enable(bev, EV_WRITE); }
static void http_document_request_cb(struct evhttp_request *req, void *arg) { struct evbuffer *evb = NULL; struct http *http = (struct http *) arg; const char *docroot = http->docroot; const char *uri = evhttp_request_get_uri(req); struct evhttp_uri *decoded = NULL; const char *path; char *decoded_path; char *whole_path = NULL; size_t len; int fd = -1; struct stat st; if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) { evhttp_send_error(req, HTTP_BADREQUEST, 0); return; } printf("GET: %s\n", uri); /* Decode the URI */ decoded = evhttp_uri_parse(uri); if (!decoded) { evhttp_send_error(req, HTTP_BADREQUEST, 0); return; } /* Let's see what path the user asked for. */ path = evhttp_uri_get_path(decoded); if (!path) path = "/"; /* We need to decode it, to see what path the user really wanted. */ decoded_path = evhttp_uridecode(path, 0, NULL); if (decoded_path == NULL) goto err; /* 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(decoded_path, "..")) goto err; len = strlen(decoded_path) + strlen(docroot) + 2; if (!(whole_path = malloc(len))) { goto err; } snprintf(whole_path, len, "%s/%s", docroot, decoded_path); if (stat(whole_path, &st) < 0) { goto err; } /* This holds the content we're sending. */ evb = evbuffer_new(); if (S_ISDIR(st.st_mode)) { /* TODO: send index.html if the request is for a directory */ goto err; } else { /* Otherwise it's a file; add it to the buffer to get * sent via sendfile */ const char *type = guess_content_type(decoded_path); if ((fd = open(whole_path, O_RDONLY)) < 0) { goto err; } if (fstat(fd, &st) < 0) { /* Make sure the length still matches, now that we * opened the file :/ */ goto err; } evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", type); /* TODO: does this read the whole thing into memory?? well, we are only going to be * serving small files out of the static content directory, so its probably OK. */ evbuffer_add_file(evb, fd, 0, st.st_size); } evhttp_send_reply(req, 200, "OK", evb); goto done; err: evhttp_send_error(req, 404, "Document was not found"); if (fd >= 0) close(fd); done: if (decoded) evhttp_uri_free(decoded); if (decoded_path) free(decoded_path); if (whole_path) free(whole_path); if (evb) evbuffer_free(evb); }
// // Function called when a new HTTP request have been recieved. // static void http_handler(struct evhttp_request *request, void *userdata) { struct owl_state* state = userdata; // Setup general response headers struct evkeyvalq *headers = evhttp_request_get_output_headers(request); evhttp_add_header(headers, "Server", USER_AGENT); // Get the requested URI const char* uri = evhttp_request_get_uri(request); const int http_method = evhttp_request_get_command(request); if( http_method != EVHTTP_REQ_GET && http_method != EVHTTP_REQ_PUT && http_method != EVHTTP_REQ_POST) { evhttp_send_error(request, 501, "Not Implemented"); return; } TRACE("Received HTTP request: %s (method %d)\n", uri, http_method); // Keep the request for async usage state->http_request = request; // // Retrieve application state (sync) if(string_starts_with(uri, "/api/state") && http_method == EVHTTP_REQ_GET) { state_action(state); } // // Shutdown owl application (async) else if(string_starts_with(uri, "/api/shutdown") && http_method == EVHTTP_REQ_GET) { shutdown_action(state); } // // Try to login to Spotify (async) else if(string_starts_with(uri, "/api/login") && http_method == EVHTTP_REQ_GET) { char* username = extract_uri_section(2, uri); char* password = extract_uri_section(3, uri); if(username != NULL && password != NULL) { login_to_spotify_action(state, username, password); } else { WARN("Could not extract username and password in order to login to Spotify!\n"); respond_error(request, OWL_HTTO_ERROR_NO_LOGIN_DETAILS, "No username or password given"); } } else if(string_starts_with(uri, "/api/login") && http_method == EVHTTP_REQ_POST) { TRACE("POST LOGIN\n"); get_post_argument(request, "username"); evhttp_send_error(request, 501, "Not Implemented"); } // // Logout from spotify (async) else if(string_starts_with(uri, "/api/logout") && http_method == EVHTTP_REQ_GET) { if(state->state > OWL_STATE_LOGGING_IN && state->state < OWL_STATE_LOGGING_OUT) logout_from_spotify_action(state); else respond_success(request); } // // Clear the entire queue else if(string_starts_with(uri, "/api/queue/clear") && http_method == EVHTTP_REQ_GET) { if(state->state < OWL_STATE_IDLE || state->state > OWL_STATE_PLAYING) { respond_error(request, OWL_HTTP_ERROR_NOT_LOGGED_IN, "Operation not allowed when not logged in"); } else { const int size = queue_size(state->spotify_state->queue); for(int i = 0; i < size; i++) { owl_track *track = pop_from_queue(state->spotify_state->queue); free_track(track); } respond_success(request); } } // // Get the current playback queue (sync) else if(string_starts_with(uri, "/api/queue") && http_method == EVHTTP_REQ_GET) { if(state->state < OWL_STATE_IDLE || state->state > OWL_STATE_PLAYING) { WARN("Operation not allowed at this state (%d)\n", state->state); respond_error(request, OWL_HTTP_ERROR_NOT_LOGGED_IN, "Operation not allowed when not logged in"); } else { respond_with_queue(state->http_request, state->spotify_state->queue); } } // // Serve static file immediately else { // Create the buffer to retrn as content struct evbuffer *content_buffer = evbuffer_new(); // If not a handler this is a static request char *static_file = (char *) malloc(strlen(doc_root) + strlen(uri) + 1); stpcpy(stpcpy(static_file, doc_root), uri); TRACE("Looking for static file: %s\n", static_file); bool file_exists = 1; struct stat st; if(stat(static_file, &st) == -1 || S_ISDIR(st.st_mode)) { file_exists = 0; evhttp_send_error(request, HTTP_NOTFOUND, "Not Found"); } if(file_exists) { const int file_size = st.st_size; FILE *fp = fopen(static_file, "r"); const char* content_type = resolve_content_type(static_file); evbuffer_add_file(content_buffer, fileno(fp), 0, file_size); // will close TRACE("Resolving content type for filename: %s to: %s\n", static_file, content_type); evhttp_add_header(headers, "Content-Type", content_type); evhttp_send_reply(request, HTTP_OK, "OK", content_buffer); } free(static_file); // Send the data evhttp_send_reply(request, HTTP_OK, USER_AGENT, content_buffer); // Free memrory evbuffer_free(content_buffer); } return; }