Exemple #1
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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);
        }
    }
}
Exemple #5
0
/*
 * 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);
	}
}
Exemple #7
0
 /*
  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;
}
Exemple #10
0
/**
 * @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));
    }
Exemple #11
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;
}
Exemple #12
0
/**
 * @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);
    }
}
Exemple #13
0
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);
        }
    }
}
Exemple #14
0
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);
}
Exemple #16
0
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;
}
Exemple #17
0
/**
 * @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);
}
Exemple #20
0
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);
}
Exemple #21
0
//
// 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;
}