Пример #1
0
std::string urlDecode(const std::string &urlEncoded) {
    std::string res;
    if (!urlEncoded.empty()) {
        char *decoded = evhttp_uridecode(urlEncoded.c_str(), false, nullptr);
        if (decoded) {
            res = std::string(decoded);
            free(decoded);
        }
    }
    return res;
}
Пример #2
0
void gen_handler(struct evhttp_request *req, void *arg)
{
    DBG();
    /*struct evbuffer *evb = evbuffer_new(); */

    const char *uri = evhttp_request_get_uri(req);
    struct evhttp_uri *decoded_uri = NULL;
    const char *path;
    char *decoded_path;

    /* Decode the URI */
    decoded_uri = evhttp_uri_parse(uri);
    if (!decoded_uri) {
        reply_error(req, HTTP_BADREQUEST, "Bad URI: %s", uri);
        return;
    }

    path = evhttp_uri_get_path(decoded_uri);
    if (!path) {
        logging(LOG_INFO, "request path is nil, replace it as /");
        path = "/";
    }

    decoded_path = evhttp_uridecode(path, 0, NULL);

    uint64_t chunkid;
    char *slash = strchr(path + 1, '/');
    *slash = '\0';
    const char *op = path + 1;
    sscanf(slash + 1, "%" SCNu64, &chunkid);

    logging(LOG_INFO, "%s, %" PRIu64, op, chunkid);

    if (strcmp(op, "put") == 0) {
        write_chunk(chunkid, req);
    } else if (strcmp(op, "get") == 0) {
        read_chunk(chunkid, req);
    } else {
        reply_error(req, HTTP_NOTFOUND, "not found: %s", uri);
        return;
    }
}
Пример #3
0
static void on_srv_request (struct evhttp_request *req, void *ctx)
{
    struct evbuffer *in;
    gchar *dir = (gchar *) ctx;
    gchar *path, *decoded_path;
    const gchar *tmp;
    const char *uri = evhttp_request_get_uri(req);
    struct evhttp_uri *decoded = NULL;
    struct evbuffer *evb = NULL;
    char buf[BUFFER_SIZE];
    FILE *f;
    size_t bytes_read;
    size_t total_bytes = 0;

    in = evhttp_request_get_input_buffer (req);

    decoded = evhttp_uri_parse(uri);
    g_assert (decoded);
    tmp = evhttp_uri_get_path (decoded);
    g_assert (tmp);
    decoded_path = evhttp_uridecode(tmp, 0, NULL);

    evb = evbuffer_new();

    path = g_strdup_printf ("%s/%s", dir, decoded_path);
    LOG_debug (POOL_TEST, "SRV: received %d bytes. Req: %s, path: %s", evbuffer_get_length (in), evhttp_request_get_uri (req), path);

    f = fopen (path, "r");
    g_assert (f);

    while ((bytes_read = fread (buf, 1, BUFFER_SIZE, f)) > 0) {
        evbuffer_add (evb, buf, bytes_read);
        total_bytes += bytes_read;
    }
    evhttp_send_reply(req, 200, "OK", evb);

    LOG_debug (POOL_TEST, "Total bytes sent: %u", total_bytes);

    fclose(f);
    evbuffer_free(evb);
}
Пример #4
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);
}
Пример #5
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
send_document_cb(struct evhttp_request *req, void *arg)
{
	struct evbuffer *evb = NULL;
	const char *docroot = 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;

	if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) {
		dump_request_cb(req, arg);
		return;
	}

	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 = "/";

	/* 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))) {
		perror("malloc");
		goto err;
	}
	evutil_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)) {
		/* If it's a directory, read the comments and make a little
		 * index page */
#ifdef WIN32
		HANDLE d;
		WIN32_FIND_DATAA ent;
		char *pattern;
		size_t dirlen;
#else
		DIR *d;
		struct dirent *ent;
#endif
		const char *trailing_slash = "";

		if (!strlen(path) || path[strlen(path)-1] != '/')
			trailing_slash = "/";

#ifdef WIN32
		dirlen = strlen(whole_path);
		pattern = malloc(dirlen+3);
		memcpy(pattern, whole_path, dirlen);
		pattern[dirlen] = '\\';
		pattern[dirlen+1] = '*';
		pattern[dirlen+2] = '\0';
		d = FindFirstFileA(pattern, &ent);
		free(pattern);
		if (d == INVALID_HANDLE_VALUE)
			goto err;
#else
		if (!(d = opendir(whole_path)))
			goto err;
#endif

		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 */);
#ifdef WIN32
		do {
			const char *name = ent.cFileName;
#else
		while ((ent = readdir(d))) {
			const char *name = ent->d_name;
#endif
			evbuffer_add_printf(evb,
			    "    <li><a href=\"%s\">%s</a>\n",
			    name, name);/* XXX escape this */
#ifdef WIN32
		} while (FindNextFileA(d, &ent));
#else
		}
#endif
		evbuffer_add_printf(evb, "</ul></body></html>\n");
#ifdef WIN32
		FindClose(d);
#else
		closedir(d);
#endif
		evhttp_add_header(evhttp_request_get_output_headers(req),
		    "Content-Type", "text/html");
	} else {
Пример #6
0
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);
}
Пример #7
0
void
parse_route_uri_pattern(const char *path_input, const char *path_pattern, struct evkeyvalq *matchdict)
{
	char  keybuf[32];
	char *kp;
	char  valbuf[512];
	char *vp;
	char  looking_for;
	char *val_decoded;
	while(*path_input && *path_pattern)
	{
		if(*path_pattern == '{')
		{
			path_pattern++;
			kp = keybuf;
			while(*path_pattern && *path_pattern != '}')
			{
				int len = (kp - keybuf);
				if(len+1 >= sizeof keybuf)
				{
					*kp = 0;
					elog(ERROR, "Path pattern has varname with >= %d characters: %.*s", (int)sizeof keybuf, (int)len, kp);
					return;
				}
				*kp = *path_pattern;
				kp++;
				path_pattern++;
			}
			*kp = 0;
			if(*path_pattern == '}')
			{
				path_pattern++;

				/* If we reached the end of the string, consider '/' the next separator */
				looking_for = *path_pattern;
				if(!looking_for)
					looking_for='/';
				vp = valbuf;
				while(*path_input && *path_input != looking_for)
				{
					int len = (vp - valbuf);
					if(len+1 >= sizeof valbuf)
					{
						elog(ERROR, "Path URI has component with >= %d characters: %.*s", (int)sizeof valbuf, (int)len, valbuf);
						return;
					}
					*vp = *path_input;
					vp++;
					path_input++;
				}
				*vp = 0;
				/* Save the value if the key is non-empty */
				if(keybuf[0])
				{
					val_decoded = evhttp_uridecode(valbuf, 1, NULL);
					evhttp_add_header(matchdict, keybuf, val_decoded);
					free(val_decoded);
				}
			}

		}
		else
		{
			path_pattern++;
			path_input++;
		}
	}
}
Пример #8
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;
}
Пример #9
0
void NFCHttpServer::listener_cb(struct evhttp_request* req, void* arg)
{
    NFCHttpServer* pNet = (NFCHttpServer*) arg;
    NFHttpRequest request;
    request.req = req;
    //uri
    const char* uri = evhttp_request_get_uri(req);
    //std::cout << "Got a GET request:" << uri << std::endl;

    //get decodeUri
    struct evhttp_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;
    }
    const char* decode1 = evhttp_uri_get_path(decoded);
    if (!decode1)
        decode1 = "/";

    //The returned string must be freed by the caller.
    const char* decodeUri = evhttp_uridecode(decode1, 0, NULL);

    if (decodeUri == NULL)
    {
        printf("uri decode error\n");
        evhttp_send_error(req, HTTP_BADREQUEST, "uri decode error");
        return;
    }
    std::string strUri;
    if (decodeUri[0] == '/')
    {
        strUri = decodeUri;
        strUri.erase(0, 1);
        decodeUri = strUri.c_str();
    }
    //get strCommand
    auto cmdList = Split(strUri, "/");
    std::string strCommand = "";
    if (cmdList.size() > 0)
    {
        strCommand = cmdList[0];
    }

    request.url = decodeUri;

    // call cb
    if (pNet->mRecvCB)
    {
        pNet->mRecvCB(request, strCommand, decodeUri);
    } else
    {
        pNet->ResponseMsg(request, "mRecvCB empty", NFWebStatus::WEB_ERROR);
    }



    //close
    /*{
    if (decoded)
    evhttp_uri_free(decoded);
    if (decodeUri)
    free(decodeUri);
    if (eventBuffer)
    evbuffer_free(eventBuffer);
    }*/
}
Пример #10
0
static int encode_request_to_file_path(const char* uri, char** whole_path) {
	const char *path;
	char *decoded_path;
	struct evhttp_uri *decoded = NULL;
	struct stat st;
	size_t len;

	*whole_path = NULL;

	decoded = evhttp_uri_parse(uri);
	if (!decoded) {
		printf("It's not a good URI. Sending 404.\n");
		return 0;
	}

	/* 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) {
		return 0;
	}

	len = strlen(decoded_path) + strlen(doc_root) + 15;
	*whole_path = (char*)malloc(len);
	if (!*whole_path) {
		perror("malloc");
		evhttp_uri_free(decoded);
		free(decoded_path);
		return 0;
	}
	evutil_snprintf(*whole_path, len, "%s%s", doc_root, decoded_path);

	if (stat(*whole_path, &st) < 0) {
		evhttp_uri_free(decoded);
		free(decoded_path);
		return 0;
	}

	if (S_ISDIR(st.st_mode)) {
		
		// Find index.html of this page
		if ((*whole_path)[strlen(*whole_path) - 1] == '/') {
			strcat(*whole_path, "index.html");
		} else {
			strcat(*whole_path, "/index.html");
		}

		if (stat(*whole_path, &st) < 0) {
			evhttp_uri_free(decoded);
			free(decoded_path);
			return 0;
		}
	}
	evhttp_uri_free(decoded);
	free(decoded_path);
	return st.st_size;
}