Пример #1
0
/*
 * Get request URI path
 * @return [String]
 * @return [nil]
 */
static VALUE t_get_uri_path(VALUE self) {
    Libevent_HttpRequest *http_request;
    const char *path;

    Data_Get_Struct(self, Libevent_HttpRequest, http_request);

    path = evhttp_uri_get_path(http_request->ev_request->uri_elems);

    return(path ? rb_str_new2(path) : Qnil);
}
static void parseRequest(RequestInfo& requestInfo) {
  const struct evhttp_uri* uri = evhttp_request_get_evhttp_uri(requestInfo.req);
  /*const*/ struct evhttp_connection* conn = evhttp_request_get_connection(requestInfo.req);
  
  requestInfo.method = evhttp_request_get_command(requestInfo.req);
  requestInfo.uriHost = evhttp_uri_get_host(uri);
  requestInfo.uriPath = evhttp_uri_get_path(uri);
  requestInfo.uriQuery = evhttp_uri_get_query(uri);
  requestInfo.uriScheme = evhttp_uri_get_scheme(uri);
  requestInfo.requestHeaders = evhttp_request_get_input_headers(requestInfo.req);
  requestInfo.requestBody = evhttp_request_get_input_buffer(requestInfo.req);
  evhttp_connection_get_peer(conn, &requestInfo.remoteAddress, (ev_uint16_t*) &requestInfo.remotePort);
}
Пример #3
0
void get_master_pgn(struct evhttp_request *req, void *context) {
    if (evhttp_request_get_command(req) != EVHTTP_REQ_GET) {
        evhttp_send_error(req, HTTP_BADMETHOD, "Method Not Allowed");
        return;
    }

    const struct evhttp_uri *uri = evhttp_request_get_evhttp_uri(req);
    if (!uri) {
        puts("evhttp_request_get_evhttp_uri failed");
        return;
    }

    const char *path = evhttp_uri_get_path(uri);
    if (!path) {
        puts("evhttp_uri_get_path failed");
        return;
    }

    char game_id[9] = {};
    int end;
    if (1 != sscanf(path, "/master/pgn/%8s%n", game_id, &end) ||
            strlen(game_id) != 8 ||
            strlen(path) != end) {
        evhttp_send_error(req, HTTP_NOTFOUND, "Not Found");
        return;
    }

    size_t pgn_size;
    char *pgn = kcdbget(master_pgn_db, game_id, 8, &pgn_size);
    if (!pgn) {
        evhttp_send_error(req, HTTP_NOTFOUND, "Master PGN Not Found");
        return;
    }

    struct evbuffer *res = evbuffer_new();
    if (!res) {
        puts("could not allocate response buffer");
        abort();
    }

    struct evkeyvalq *headers = evhttp_request_get_output_headers(req);
    evhttp_add_header(headers, "Content-Type", "application/vnd.chess-pgn; charset=utf-8");

    evbuffer_add(res, pgn, pgn_size);
    kcfree(pgn);

    evhttp_send_reply(req, HTTP_OK, "OK", res);
    evbuffer_free(res);
}
Пример #4
0
int
match_route(struct restgres_route *route, struct restgres_request *req)
{
	int score;

	/* Check method - req->cmd_type should have just one bit set but route->cmd_type is a mask */
	if((req->cmd_type & route->cmd_type) == 0)
		return -1;

	/* Now check to make sure the path matches the path pattern */
	score = match_route_uri_pattern(evhttp_uri_get_path(req->uri), route->pattern);
	if(score < 0)
		return -1;

	/* TODO Check the accept and content-type headers */

	return score;
}
Пример #5
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;
    }
}
Пример #6
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);
}
Пример #7
0
// connect (if necessary) to the server and send an HTTP request
gboolean s3http_client_start_request (S3HttpClient *http, S3HttpClientRequestMethod method, const gchar *url)
{
    http->method = method;
    
    http->http_uri = evhttp_uri_parse_with_flags (url, 0);
    if (!http->http_uri) {
        LOG_err (HTTP_LOG, "Failed to parse URL string: %s", url);
        return FALSE;
    }
    g_free (http->url);
    http->url = g_strdup (url);

    LOG_debug (HTTP_LOG, "Start Req: %s %s", http->url, evhttp_uri_get_path (http->http_uri));

    // connect if it's not
    if (!s3http_client_is_connected (http)) {
        s3http_client_connect (http);
    } else {
        return s3http_client_send_initial_request (http);
    }

    return TRUE;
}
Пример #8
0
int
main(int argc, char **argv)
{
	int r;

	struct evhttp_uri *http_uri = NULL;
	const char *url = NULL, *data_file = NULL;
	const char *crt = "/etc/ssl/certs/ca-certificates.crt";
	const char *scheme, *host, *path, *query;
	char uri[256];
	int port;
	int retries = 0;
	int timeout = -1;

	SSL_CTX *ssl_ctx = NULL;
	SSL *ssl = NULL;
	struct bufferevent *bev;
	struct evhttp_connection *evcon = NULL;
	struct evhttp_request *req;
	struct evkeyvalq *output_headers;
	struct evbuffer *output_buffer;

	int i;
	int ret = 0;
	enum { HTTP, HTTPS } type = HTTP;

	for (i = 1; i < argc; i++) {
		if (!strcmp("-url", argv[i])) {
			if (i < argc - 1) {
				url = argv[i + 1];
			} else {
				syntax();
				goto error;
			}
		} else if (!strcmp("-crt", argv[i])) {
			if (i < argc - 1) {
				crt = argv[i + 1];
			} else {
				syntax();
				goto error;
			}
		} else if (!strcmp("-ignore-cert", argv[i])) {
			ignore_cert = 1;
		} else if (!strcmp("-data", argv[i])) {
			if (i < argc - 1) {
				data_file = argv[i + 1];
			} else {
				syntax();
				goto error;
			}
		} else if (!strcmp("-retries", argv[i])) {
			if (i < argc - 1) {
				retries = atoi(argv[i + 1]);
			} else {
				syntax();
				goto error;
			}
		} else if (!strcmp("-timeout", argv[i])) {
			if (i < argc - 1) {
				timeout = atoi(argv[i + 1]);
			} else {
				syntax();
				goto error;
			}
		} else if (!strcmp("-help", argv[i])) {
			syntax();
			goto error;
		}
	}

	if (!url) {
		syntax();
		goto error;
	}

#ifdef _WIN32
	{
		WORD wVersionRequested;
		WSADATA wsaData;
		int err;

		wVersionRequested = MAKEWORD(2, 2);

		err = WSAStartup(wVersionRequested, &wsaData);
		if (err != 0) {
			printf("WSAStartup failed with error: %d\n", err);
			goto error;
		}
	}
#endif // _WIN32

	http_uri = evhttp_uri_parse(url);
	if (http_uri == NULL) {
		err("malformed url");
		goto error;
	}

	scheme = evhttp_uri_get_scheme(http_uri);
	if (scheme == NULL || (strcasecmp(scheme, "https") != 0 &&
	                       strcasecmp(scheme, "http") != 0)) {
		err("url must be http or https");
		goto error;
	}

	host = evhttp_uri_get_host(http_uri);
	if (host == NULL) {
		err("url must have a host");
		goto error;
	}

	port = evhttp_uri_get_port(http_uri);
	if (port == -1) {
		port = (strcasecmp(scheme, "http") == 0) ? 80 : 443;
	}

	path = evhttp_uri_get_path(http_uri);
	if (strlen(path) == 0) {
		path = "/";
	}

	query = evhttp_uri_get_query(http_uri);
	if (query == NULL) {
		snprintf(uri, sizeof(uri) - 1, "%s", path);
	} else {
		snprintf(uri, sizeof(uri) - 1, "%s?%s", path, query);
	}
	uri[sizeof(uri) - 1] = '\0';

#if OPENSSL_VERSION_NUMBER < 0x10100000L
	// Initialize OpenSSL
	SSL_library_init();
	ERR_load_crypto_strings();
	SSL_load_error_strings();
	OpenSSL_add_all_algorithms();
#endif

	/* This isn't strictly necessary... OpenSSL performs RAND_poll
	 * automatically on first use of random number generator. */
	r = RAND_poll();
	if (r == 0) {
		err_openssl("RAND_poll");
		goto error;
	}

	/* Create a new OpenSSL context */
	ssl_ctx = SSL_CTX_new(SSLv23_method());
	if (!ssl_ctx) {
		err_openssl("SSL_CTX_new");
		goto error;
	}

#ifndef _WIN32
	/* TODO: Add certificate loading on Windows as well */

	/* Attempt to use the system's trusted root certificates.
	 * (This path is only valid for Debian-based systems.) */
	if (1 != SSL_CTX_load_verify_locations(ssl_ctx, crt, NULL)) {
		err_openssl("SSL_CTX_load_verify_locations");
		goto error;
	}
	/* Ask OpenSSL to verify the server certificate.  Note that this
	 * does NOT include verifying that the hostname is correct.
	 * So, by itself, this means anyone with any legitimate
	 * CA-issued certificate for any website, can impersonate any
	 * other website in the world.  This is not good.  See "The
	 * Most Dangerous Code in the World" article at
	 * https://crypto.stanford.edu/~dabo/pubs/abstracts/ssl-client-bugs.html
	 */
	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
	/* This is how we solve the problem mentioned in the previous
	 * comment.  We "wrap" OpenSSL's validation routine in our
	 * own routine, which also validates the hostname by calling
	 * the code provided by iSECPartners.  Note that even though
	 * the "Everything You've Always Wanted to Know About
	 * Certificate Validation With OpenSSL (But Were Afraid to
	 * Ask)" paper from iSECPartners says very explicitly not to
	 * call SSL_CTX_set_cert_verify_callback (at the bottom of
	 * page 2), what we're doing here is safe because our
	 * cert_verify_callback() calls X509_verify_cert(), which is
	 * OpenSSL's built-in routine which would have been called if
	 * we hadn't set the callback.  Therefore, we're just
	 * "wrapping" OpenSSL's routine, not replacing it. */
	SSL_CTX_set_cert_verify_callback(ssl_ctx, cert_verify_callback,
					  (void *) host);
#else // _WIN32
	(void)crt;
#endif // _WIN32

	// Create event base
	base = event_base_new();
	if (!base) {
		perror("event_base_new()");
		goto error;
	}

	// Create OpenSSL bufferevent and stack evhttp on top of it
	ssl = SSL_new(ssl_ctx);
	if (ssl == NULL) {
		err_openssl("SSL_new()");
		goto error;
	}

	#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
	// Set hostname for SNI extension
	SSL_set_tlsext_host_name(ssl, host);
	#endif

	if (strcasecmp(scheme, "http") == 0) {
		bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
	} else {
		type = HTTPS;
		bev = bufferevent_openssl_socket_new(base, -1, ssl,
			BUFFEREVENT_SSL_CONNECTING,
			BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
	}

	if (bev == NULL) {
		fprintf(stderr, "bufferevent_openssl_socket_new() failed\n");
		goto error;
	}

	bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);

	// For simplicity, we let DNS resolution block. Everything else should be
	// asynchronous though.
	evcon = evhttp_connection_base_bufferevent_new(base, NULL, bev,
		host, port);
	if (evcon == NULL) {
		fprintf(stderr, "evhttp_connection_base_bufferevent_new() failed\n");
		goto error;
	}

	if (retries > 0) {
		evhttp_connection_set_retries(evcon, retries);
	}
	if (timeout >= 0) {
		evhttp_connection_set_timeout(evcon, timeout);
	}

	// Fire off the request
	req = evhttp_request_new(http_request_done, bev);
	if (req == NULL) {
		fprintf(stderr, "evhttp_request_new() failed\n");
		goto error;
	}

	output_headers = evhttp_request_get_output_headers(req);
	evhttp_add_header(output_headers, "Host", host);
	evhttp_add_header(output_headers, "Connection", "close");

	if (data_file) {
		/* NOTE: In production code, you'd probably want to use
		 * evbuffer_add_file() or evbuffer_add_file_segment(), to
		 * avoid needless copying. */
		FILE * f = fopen(data_file, "rb");
		char buf[1024];
		size_t s;
		size_t bytes = 0;

		if (!f) {
			syntax();
			goto error;
		}

		output_buffer = evhttp_request_get_output_buffer(req);
		while ((s = fread(buf, 1, sizeof(buf), f)) > 0) {
			evbuffer_add(output_buffer, buf, s);
			bytes += s;
		}
		evutil_snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)bytes);
		evhttp_add_header(output_headers, "Content-Length", buf);
		fclose(f);
	}

	r = evhttp_make_request(evcon, req, data_file ? EVHTTP_REQ_POST : EVHTTP_REQ_GET, uri);
	if (r != 0) {
		fprintf(stderr, "evhttp_make_request() failed\n");
		goto error;
	}

	event_base_dispatch(base);
	goto cleanup;

error:
	ret = 1;
cleanup:
	if (evcon)
		evhttp_connection_free(evcon);
	if (http_uri)
		evhttp_uri_free(http_uri);
	event_base_free(base);

	if (ssl_ctx)
		SSL_CTX_free(ssl_ctx);
	if (type == HTTP && ssl)
		SSL_free(ssl);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
	EVP_cleanup();
	ERR_free_strings();

#ifdef EVENT__HAVE_ERR_REMOVE_THREAD_STATE
	ERR_remove_thread_state(NULL);
#else
	ERR_remove_state(0);
#endif
	CRYPTO_cleanup_all_ex_data();

	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif /*OPENSSL_VERSION_NUMBER < 0x10100000L */

#ifdef _WIN32
	WSACleanup();
#endif

	return ret;
}
Пример #9
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 {
Пример #10
0
static void
handle_request(void *ctx) {
  conn_t *conn = ctx;
  struct evbuffer *rsps = evbuffer_new();
  struct state *s = conn->state;

  if (strcmp(conn->method, "GET") == 0) {

    if (strcmp(conn->url, "/getproxies") == 0) 
      get_proxies(rsps);

    else if (strcmp(conn->url, "/getlists") == 0) 
      get_lists(rsps);

    else if (strncmp(conn->url, "/query?", 7) == 0)
      query(rsps, evhttp_decode_uri(conn->url + 7));

    else if (strcmp(conn->url, "/getlog") == 0) 
      get_log(rsps);

    else if (strcmp(conn->url, "/gettrylist") == 0) 
      get_trylist(rsps);

    else if (strcmp(conn->url, "/getversion") == 0) 
      evbuffer_add_printf(rsps, VERSION);

  }
  else if (strcmp(conn->method, "POST") == 0) {

    struct evkeyvalq kv;
    struct evhttp_uri *uri = evhttp_uri_parse_with_flags(conn->url, 0);

    evhttp_parse_query_str(evhttp_uri_get_query(uri), &kv);

    char *cont;
    if (s->length) 
      cont = s->body;

    const char *path = evhttp_uri_get_path(uri);

    if (strcmp(path, "/addrule") == 0 || strcmp(path, "/rmrule") == 0) {

      struct evkeyvalq kvc;
      evhttp_parse_query_str(cont, &kvc);

      char *list = evhttp_decode_uri(evhttp_find_header(&kvc, "list"));
      char *rule = evhttp_decode_uri(evhttp_find_header(&kvc, "rule"));

      if (get_domain(rule) == NULL) 
	evbuffer_add_printf(rsps, "Invalid rule.");
      
      else {
	if (strcmp(path, "/addrule") == 0)
	  update_rule(list, rule);
      
	else 
	  remove_rule(list, rule);

	evbuffer_add_printf(rsps, "OK");
      }
      free(list);
      free(rule);

      free(cont);
    }

    else if (strcmp(path, "/flush") == 0) {
      flush_list();
      evbuffer_add_printf(rsps, "OK");
    }
    else if (strcmp(path, "/rmlog") == 0) {
      rm_log(rsps);
    }
    else if (strcmp(path, "/purgetrylist") == 0) {
      purgetrylist(rsps);
    }

    evhttp_uri_free(uri);
  }
  ret(conn->be_client, rsps);
  evbuffer_free(rsps);

}
Пример #11
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;
}
Пример #12
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);
}
Пример #13
0
 size_t i;
 
 for (i = 0; i < uri_length; ++i) {
Пример #14
0
//Main
int main(int argc, char *argv[])
{
    //Get args
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <snapshot_file>\n", argv[0]);
        return 1;
    }
    snap_path = argv[1];

    //Allocate memory
    fprintf(stderr, "Allocating arena with size %.2f MBytes ...\n", (float)m / CHAR_BIT / MEGA);
    Bloom = malloc( (m + ( CHAR_BIT - 1)) / CHAR_BIT ); // Ceil byte length: bytes = bits + 7 / 8


    //Load or create snapshot file
    if (!access(snap_path, F_OK)) {
        fputs("Loading snapshot...\n", stderr);
        if (LoadSnap(Bloom, snap_path)) {
            fputs("Unable to load snapshot!\n", stderr);
            return -1;
        }
        fputs("Snapshot loaded.\n", stderr);
    } else {
        fputs("Initializing new file storage...\n", stderr);
        size_t shouldwrite = (m + (CHAR_BIT - 1)) / CHAR_BIT;
        memset(Bloom, 0, shouldwrite); 

        if (SaveSnap(Bloom, snap_path)) {
            fputs("Unable to save initial snapshot!\n", stderr);
            return -1;
        }
        fputs("Initial snapshot written.\n", stderr);
    }


    void OnReq(struct evhttp_request *req, void *arg)
    {
        struct evbuffer *OutBuf = evhttp_request_get_output_buffer(req);
        if (!OutBuf) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        struct evkeyvalq *Headers = evhttp_request_get_output_headers(req);
        if (!Headers) {
            evhttp_send_reply(req, HTTP_INTERNAL, "Internal Error", OutBuf);
            return;
        }
        const struct evhttp_uri *HTTPURI =  evhttp_request_get_evhttp_uri(req);
        if (!HTTPURI) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
            return;
        }
        const char *path =  evhttp_uri_get_path(HTTPURI);
        if (!path) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Bad Request", OutBuf);
        }
        const char *query_string = evhttp_uri_get_query(HTTPURI);
        if (!query_string) {
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }
        struct evkeyvalq params;
        evhttp_parse_query_str(query_string, &params);
        const char *element = evhttp_find_header(&params, "e");
        if (!element) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_BADREQUEST, "Element Required", OutBuf);
            return;
        }

        int i;
        const char* (*Operation)(bloom_cell *, size_t []) = NULL;
        for (i=0; i< sizeof HandlerTable/ sizeof HandlerTable[0] ; i++)
            if (strncmp(HandlerTable[i][0], path, STR_MAX) == 0) {
                Operation = HandlerTable[i][1];
                break;
            }
        if (!Operation) {
            evhttp_clear_headers(&params);
            evhttp_send_reply(req, HTTP_NOTFOUND, "Not Found", OutBuf);
            return;
        }

        const char *response = Operation(Bloom, Hashes(element));

        evhttp_add_header(Headers, MIME_TYPE);
        evbuffer_add_printf(OutBuf, response);
        evhttp_send_reply(req, HTTP_OK, "OK", OutBuf);
        evhttp_clear_headers(&params);
    };

    if (!(base = event_base_new()))
        crash("Couldn't create an event_base: exiting\n", -1);

    if (!(http = evhttp_new(base)))
        crash("Couldn't create evhttp. Exiting.\n", -1);
    evhttp_set_gencb(http, OnReq, NULL);

    if (!(handle = evhttp_bind_socket_with_handle(http, BIND_ADDRESS, BIND_PORT)))
        crash("couldn't bind to port 8888. Exiting.\n", -1);

    if (signal(SIGINT, term_handler) == SIG_ERR)
        crash("Unable to set SIGINT handler!", -1);

    if (signal(SIGTERM, term_handler) == SIG_ERR)
        crash("Unable to set SIGTERM handler!", -1);

    if (signal(SIGCHLD, child_collector) == SIG_ERR)
        crash("Unable to set SIGCHLD handler!", -1);
    
    //This signal handled by event loop in order to avoid malloc deadlock
    if ((dump_event = evsignal_new(base, SIGUSR1, dump_handler, NULL)) == NULL)
        crash("Unable to create SIGUSR1 handler!", -1);
    else 
        if (event_add(dump_event, NULL) == -1)
            crash("Unable to add SIGUSR1 handler!", -1);

    if (event_base_dispatch(base) == -1)
        crash("Failed to run message loop.\n", -1);

    fputs("Exiting...\n", stderr);
    SaveSnap(Bloom, snap_path);
    evhttp_del_accept_socket(http, handle);
    evhttp_free(http);
    event_free(dump_event);
    event_base_free(base);
    free(Bloom);
    return 0;
}
Пример #15
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);
}
Пример #16
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);
    }*/
}
Пример #17
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;
}
Пример #18
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);
        }
    }
}
Пример #19
0
// create HTTP headers and send first part of buffer
static gboolean s3http_client_send_initial_request (S3HttpClient *http)
{
    struct evbuffer *out_buf;
    GList *l;

    // output length must be set !
    /*
    if (!http->output_length) {
        LOG_err (HTTP_LOG, "Output length is not set !");
        return FALSE;
    }
    */

    out_buf = evbuffer_new ();

    // first line
    evbuffer_add_printf (out_buf, "%s %s HTTP/1.1\r\n", 
        s3http_client_method_to_string (http->method),
        evhttp_uri_get_path (http->http_uri)
    );

    // host
    // evbuffer_add_printf (out_buf, "Host: %s\r\n",
    //     evhttp_uri_get_host (http->http_uri)
    // );

    // length
    // XXX:
    
    // must be set by the user !!!
   // if (http->output_length > 0) {
        evbuffer_add_printf (out_buf, "Content-Length: %"G_GUINT64_FORMAT"\r\n",
            http->output_length
        );
    //}

    // add headers
    for (l = g_list_first (http->l_output_headers); l; l = g_list_next (l)) {
        S3HttpClientHeader *header = (S3HttpClientHeader *) l->data;
        evbuffer_add_printf (out_buf, "%s: %s\r\n",
            header->key, header->value
        );
    }

    // end line
    evbuffer_add_printf (out_buf, "\r\n");

    // add current data in the output buffer
    LOG_debug (HTTP_LOG, "OUTPUT len: %zd", evbuffer_get_length (http->output_buffer));
    evbuffer_add_buffer (out_buf, http->output_buffer);
    
    http->output_sent += evbuffer_get_length (out_buf);

    LOG_debug (HTTP_LOG, "Request is sent !");
   // g_printf ("\n==============================\n%s\n======================\n",
   //     evbuffer_pullup (out_buf, -1));

    // send it
    bufferevent_write_buffer (http->bev, out_buf);


    // free memory
    evbuffer_free (out_buf);

    return TRUE;
}