Ejemplo n.º 1
0
} END_TEST

/* TODO: find two headers with coliding hash and test it */
START_TEST(test_http_headers)
{
    http_hdr_table *t;

    t = http_headers_init();

    fail_if(http_header_parse(t, "") == 0);
    fail_if(http_header_parse(t, "field") == 0);
    fail_if(http_header_parse(t, "field\r\n") == 0);
    fail_if(http_header_parse(t, "field:") == 0);
    fail_if(http_header_parse(t, "field:\r\n") == 0);
    fail_if(http_header_parse(t, "field:value") == 0);
    fail_if(http_header_parse(t, ":value") == 0);
    fail_if(http_header_parse(t, ":value\r\n") == 0);

    fail_unless(http_header_parse(t, "Host: dsl.sk\r\n") == 0);
    assert_str(http_header_get(t, "Host"), "dsl.sk");
    assert_str(http_header_get(t, "host"), "dsl.sk");
    assert_str(http_header_get(t, "HOST"), "dsl.sk");

    http_headers_destroy(t);
} END_TEST
Ejemplo n.º 2
0
Archivo: main.c Proyecto: Windeal/httpd
int handle_request(struct client *cli)
{
	int ret;
	int hlen;
	char *idxptr = NULL;
//	RequestS req;
//	memset(&req, 0, sizeof (RequestS));

	Logger(LOG_INFO, 0, "%s...\n", __FUNCTION__);

	ret = httpd_tcp_recv(cli, cli->req.buffer, sizeof (cli->req.buffer));
	if ( ret <= 0 )
	{
		Logger(LOG_ERR, 0, "http recv failed!\n");
		return -1;
	}
	idxptr = strStr(cli->req.buffer, ret, "\r\n\r\n", 4);
	if (idxptr == NULL)
	{
		Logger(LOG_ERR, 0, "Get request header failed!\n");
		return -1;
	}
	hlen = (int)(idxptr-cli->req.buffer);
	cli->req.entity = idxptr + 4;
	http_header_parse(cli, hlen);

	return 0;
}
Ejemplo n.º 3
0
int http_header_parse_next_field(struct http_header_parser *parser,
	const char **name_r, const unsigned char **data_r, size_t *size_r,
	const char **error_r)
{
	const uoff_t max_size = parser->limits.max_size;
	const uoff_t max_field_size = parser->limits.max_field_size;
	const unsigned char *data;
	size_t size;
	int ret;

	*error_r = NULL;

	while ((ret=i_stream_read_more(parser->input, &parser->begin, &size)) > 0) {

		/* check header size limits */
		if (parser->size >= max_size) {
			*error_r = "Excessive header size";
			return -1;
		}
		if (parser->field_size > max_field_size) {
			*error_r = "Excessive header field size";
			return -1;
		}

		/* don't parse beyond header size limits */
		if (size > (max_size - parser->size))
			size = max_size - parser->size;
		if (size > (max_field_size - parser->field_size)) {
			size = max_field_size - parser->field_size;
			size = (size == 0 ? 1 : size); /* need to parse one more byte */
		}

		parser->cur = parser->begin;
		parser->end = parser->cur + size;

		if ((ret=http_header_parse(parser)) < 0) {
			*error_r = parser->error;
			return -1;
		}

		i_stream_skip(parser->input, parser->cur - parser->begin);
		parser->size += parser->cur - parser->begin;
		parser->field_size += parser->cur - parser->begin;

		if (ret == 1) {
			parser->field_size = 0;

			if (parser->state != HTTP_HEADER_PARSE_STATE_EOH) {
				data = buffer_get_data(parser->value_buf, &size);
			
				/* trim trailing OWS */
				while (size > 0 &&
					(data[size-1] == ' ' || data[size-1] == '\t'))
					size--;

				*name_r = str_c(parser->name);
				*data_r = data;
				*size_r = size;
				parser->state = HTTP_HEADER_PARSE_STATE_INIT;
			} else {
				*name_r = NULL;
				*data_r = NULL;
			}
			return 1;
		}
	}

	i_assert(ret != -2);
	if (ret < 0) {
		if (i_stream_is_eof(parser->input))
			*error_r = "Premature end of input";
		else
			*error_r = "Stream error";
	}
	return ret;
}
Ejemplo n.º 4
0
int
http_get(char *urlstr, http_req_func_t func, void *farg) {
    url_t url;
    struct sockaddr_in iaddr;
    sockaddrlen_t addrlen;
    int i, err=-1;
    sock_t sock;
    int url_parsed=0;
    char buf[16384], buf1[1024];
    size_t len=0;
    http_header_t http;
    http_req_t req;
    int got_header = 0;
    http_req_error_t req_err = 0;

    do {
	memset(&req, 0, sizeof(req));
	req.req_url = &url;
	req.reply_hdr = &http;

	req_err = HTTP_REQ_ERROR_BAD_URL;
	i = url_parse(&url, urlstr);
	assertb(i==0);
	url_parsed = 1;

	if( strcasecmp(url.proto, "file") == 0 ) {
	    struct stat st;	
	    FILE *f=0;
	    req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND;
	    do {
		i = stat(url.path, &st);
		assertb(i==0);
		http.content_len = st.st_size;
		req.req_state = HTTP_REQ_BODY;
		f = fopen(url.path, "r");
		assertb(f);
		while(1) {
		    len = fread(buf, 1, sizeof(buf), f);
		    if( len < 0 ) {
			req_err = HTTP_REQ_ERROR_INCOMPLETE;
			break;
		    }
		    if( len <= 0 ) break;
		    err = func(&req, buf, len, farg);
		    if( err ) break;
		}
		req_err = 0;
		err = 0;
	    } while(0);
	    if( f ) {
		fclose(f);
	    }
	    break;
	}
	
	req_err = HTTP_REQ_ERROR_BAD_URL;
	assertb( strcasecmp(url.proto, "http") == 0 );

	req_err = HTTP_REQ_ERROR_CONNECT;
	sock = socket(AF_INET, SOCK_STREAM, 0);
	assertb_sockerr(sock>=0);

	req.req_state = HTTP_REQ_RESOLVE;
	i = snprintf(buf, sizeof(buf), "resolving host %s\n", url.host);
	err = func(&req, buf, i, farg);
	if( err != 0 ) break;

	addrlen = iaddr_pack(&iaddr, inet_resolve(url.host), url.port);

	req.req_state = HTTP_REQ_CONNECT;
	i = snprintf(buf, sizeof(buf), "connecting to host %s at %s\n"
		     ,url.host
		     ,iaddr_fmt(&iaddr, buf1, sizeof(buf1))
		     );
	err = func(&req, buf, i, farg);
	if( err != 0 ) break;

	i = connect(sock, (struct sockaddr*)&iaddr, addrlen);
	assertb_sockerr(i==0);
	
	i = snprintf(buf, sizeof(buf),
		     "GET %s HTTP/1.0\r\n"
		     "Host: %s\r\n"
		     "\r\n"
		     ,url.path_args
		     ,url.host
		     );

	req.req_state = HTTP_REQ_SEND;
	err = func(&req, buf, i, farg);
	if( err != 0 ) break;

	i = sock_send_timeout(sock, buf, i, 5000);
	assertb(i>=0);

	len = 0;
	got_header = 0;
	while(1) {
	    assertb( len < sizeof(buf) );
	    i = recv(sock, buf+len, sizeof(buf)-len, 0);
	    if( i < 0 ) {
		warn_sockerr(sock);
		req_err = HTTP_REQ_ERROR_INCOMPLETE;
		break;
	    }

	    if( i == 0 ) {
		req.req_state = HTTP_REQ_EOF;
		err = func(&req, 0, 0, farg);
		break;
	    }
	    len += i;

	    if( !got_header ) {
		http_header_init(&http, 0);
		i = http_header_parse(&http, buf, len);
		if( i < 0 ) {
		    req_err = HTTP_REQ_ERROR_BAD_RESPONSE;
		    break;
		}
		if( i == 0 ) {
		    continue;
		}
		got_header = 1;

		req.reply_max = http.content_len;
		req.req_state = HTTP_REQ_HEAD;
		err = func(&req, buf, http.header_len, farg);
		if( err != 0 ) {
		    break;
		}

		len -= http.header_len;
		if( len > 0 ) {
		    memmove(buf, buf+http.header_len, len);
		}
	    }

	    if( got_header ) {
		req.reply_len += len;
		req.req_state = HTTP_REQ_BODY;
		err = func(&req, buf, len, farg);
		len = 0;
		if( err ) {
		    break;
		}
	    }
	}
	req_err = 0;
    } while(0);

    if( got_header && http.response_code != 200 ) {
	req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND;
    }

    if( req_err ) {
	req.req_state = HTTP_REQ_ERROR;
	req.req_error = req_err;
	err = func(&req, buf, len, farg);
    }

    if( url_parsed ) {
	url_free(&url);
    }

    if( got_header ) {
	http_header_free(&http);
    }
    return err;
}
Ejemplo n.º 5
0
void
http_redirect_client_select_read(fdselect_t *sel, fd_t fd, int state, void *arg) {
    http_redirect_client_t *client = (http_redirect_client_t *)arg;
    http_redirect_t *server = client->server;
    struct stat st;
    int i, n, err=-1;
    char buf[4096];
    char buf1[1024];

    do {
	i = client->recv_max - client->recv_len;
	if( i <= 0 ) {
	    err = 405; /* request too big */
	    break;
	}

	i = recv(client->sock, client->recv_buf+client->recv_len, i, 0);
	if( i <= 0 ) {
	    if( sock_wouldblock(client->sock, i) ) {
		/* ignore spurious blocking reads */
		err = 0;
		break;
	    }
	    assertb_sockerr(i);
	}
	client->recv_len += i;
	client->recv_buf[client->recv_len] = 0;

	debug(DEBUG_INFO,
	      ("http_redirect_client_select_read: addr=%s recv=%d\n"
	       "recv_buf=\n%s\n"
	       ,iaddr_fmt(&client->addr, buf1, sizeof(buf1))
	       ,i
	       ,client->recv_buf
	       ));

	i = http_header_parse(&client->http_req, client->recv_buf, client->recv_len);
	if( i == 0 ) {
	    /* header not complete yet, continue */
	    err = 0;
	    break;
	}
	else if( i < 0 ) {
	    err = -i;
	    break;
	}

	/* find a remote server to redirect to */

	if( strcmp(req_url->path, "/p2p_router", strlen("/p2p_router"))==0 ) {
	    addrlen = iaddr_pack(&addr, INADDR_ANY, 8969);
	}
	else {
	    addrlen = iaddr_pack(&addr, INADDR_ANY, 80);
	}

	/* start connecting to remote server */
	client->redirect_sock = socket(AF_INET, SOCK_STREAM, 0);
	assertb_sockerr(client->redirect_sock>=0);
	i = sock_nonblock(client->redirect_sock, 1);
	assertb_sockerr(i==0);
	i = connect(client->redirect_sock, (struct sockaddr*)&addr, addrlen);
	assertb_sockerr(i==0 || sock_wouldblock(client->redirect_sock, i));
	
	/* stop reading from client, and wait for connection to complete */
	fdselect_unset(server->fdselect, client->sock, FDSELECT_READ);
	fdselect_set(server->fdselect, client->redirect_sock, FDSELECT_READ, 
		     http_redirect_client_select_redirect_connect, client);


	i = snprintf(buf, sizeof(buf), "%s%s", 
		     server->root_dir, client->http_req.uri);
	err = 404; /* file not found */
	i = stat(buf, &st);
	assertb(i==0);
	client->send_file = fopen(buf, "r");
	assertb(client->send_file);

	debug(DEBUG_INFO,
	      ("http_redirect_client_select_read: sending file=%s\n", buf));

	i = snprintf(buf, sizeof(buf),
		     "HTTP/1.0 200 Ok\r\n"
		     "Pragma: no-cache\r\n"
		     "Cache-Control: no-cache\r\n"
		     "Connection: keep-alive\r\n"
		     "Content-Length: %lu\r\n"
		     "Content-Type: text/plain\r\n"
		     "\r\n"
		     ,st.st_size);
	n = i;
	i = send(client->sock, buf, n, 0);
	assertb(i==n);
	
	/* stop reading and start writing */
	fdselect_unset(server->fdselect, client->sock, FDSELECT_READ);
	fdselect_set(server->fdselect, client->sock, FDSELECT_WRITE, 
		     http_redirect_client_select_write, client);

	err = 0;

    } while(0);
    if( err > 0 ) {
	i = snprintf(buf, sizeof(buf),
		     "HTTP/1.0 %d\r\n"
		     "Content-Type: text/html; charset=iso-8859-1\r\n"
		     "\r\n"
		     "<HTML><HEAD>\r\n"
		     "<TITLE>HTTP Error %d</TITLE>\r\n"
		     "</HEAD><BODY>\r\n"
		     "<H1>HTTP Error %d</H1>\r\n"
		     "%s<br>\r\n"
		     "<HR>\r\n"
		     "</BODY></HTML>\r\n"
		     
		     , err, err, err
		     , client->http_req.uri);
	send(client->sock, buf, i, 0);
    }
    if( err ) {
	http_redirect_client_free(client);
    }
}
Ejemplo n.º 6
0
void
http_response_parse/*_and_read*/(struct http_ctx *c, http_response_t *r, buffer_t *d) {
	char buf[LIBNET_HTTP_SIZE_CHUNK] = {0}, *tok;
	uint32_t len, i = 0, chunk_size = 0;
	bool chunked = false;
	http_header_field_t *hf_e;

	if(c == NULL || r == NULL || d == NULL) {
		libnet_error_set(LIBNET_E_INV_ARG);
		return;
	}

	htbl_create(&r->header, 0);
	buffer_create(&r->body, LIBNET_BM_FILE);

	len = buffer_size(d);
	buffer_seek(d, 0);

	/* read status line */
	while(len > 0) {
		buffer_read(d, buf + i, 1);
		
		if(strstr(buf, LIBNET_HTTP_DEL)) {
			break;
		}

		++i; --len;
	}

	//printf("status line: %s", buf);

	/* do something with the http version */

	/* get status code */
	tok = strstr(buf, " ") + 1;
	sprintf(buf, "%s", tok);
	sscanf(buf, "%3d", &r->code);

	/* get reason */
	i = strcspn(buf+4, LIBNET_HTTP_DEL) + 1;

	if(i > LIBNET_HTTP_SIZE_REASON) {
		i -= LIBNET_HTTP_SIZE_REASON; // LIBNET_HTTP_DEL;
	}

	snprintf(r->reason, i, "%s", buf+4);

	/* now parse header */
	http_header_parse(&r->header, d);

	/* chunked? */
	hf_e = (http_header_field_t *)htbl_get(&r->header, "transfer-encoding");
	chunked = (!strcmp(hf_e->value, "chunked") ? true : false);

	uint32_t get_chunk_size(socket_t *s) {
		uint32_t i = 0, size;
		char buf[LIBNET_HTTP_SIZE_CHUNK] = {0};

		while(!strstr(buf, LIBNET_HTTP_DEL)) {
			if(0 == socket_read(s, buf+i++, 1)) {
				return 0;
			}
		}

		if(i >= 3) {
			buf[i-2] = 0;
		} else {
			return 0;
		}

		sscanf(buf, "%x", &size);
		return size;
	}