251 lines
6.1 KiB
C
251 lines
6.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
|
|
#include "htparse.h"
|
|
|
|
static int
|
|
_on_msg_start(htparser * p) {
|
|
printf("START {\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_on_msg_end(htparser * p) {
|
|
printf("}\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_path(htparser * p, const char * data, size_t len) {
|
|
printf("\tpath = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_method(htparser * p, const char * data, size_t len) {
|
|
printf("\tmethod = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_uri(htparser * p, const char * data, size_t len) {
|
|
printf("\turi = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_args(htparser * p, const char * data, size_t len) {
|
|
printf("\targs = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_hdrs_end(htparser * p) {
|
|
printf("\t}\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_hdrs_start(htparser * p) {
|
|
printf("\thdrs {\n");
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_hdr_key(htparser * p, const char * data, size_t len) {
|
|
printf("\t\thdr_key = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_hdr_val(htparser * p, const char * data, size_t len) {
|
|
printf("\t\thdr_val = '%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_read_body(htparser * p, const char * data, size_t len) {
|
|
printf("\t'%.*s'\n", (int)len, data);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_on_new_chunk(htparser * p) {
|
|
printf("\t--chunk payload (%zu)--\n", htparser_get_content_length(p));
|
|
/* printf("..chunk..\n"); */
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
_test(htparser * p, htparse_hooks * hooks, const char * l, htp_type type) {
|
|
printf("---- test ----\n");
|
|
printf("%zu, %s\n", strlen(l), l);
|
|
|
|
htparser_init(p, type);
|
|
printf("%zu == %zu\n", htparser_run(p, hooks, l, strlen(l)), strlen(l));
|
|
|
|
if (htparser_get_error(p)) {
|
|
printf("ERROR: %s\n", htparser_get_strerror(p));
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
static void
|
|
_test_fragments(htparser * p, htparse_hooks * hooks, const char ** fragments,
|
|
htp_type type) {
|
|
int i = 0;
|
|
|
|
printf("---- test fragment ----\n");
|
|
htparser_init(p, type);
|
|
|
|
while (1) {
|
|
const char * l = fragments[i++];
|
|
|
|
if (l == NULL) {
|
|
break;
|
|
}
|
|
|
|
htparser_run(p, hooks, l, strlen(l));
|
|
|
|
if (htparser_get_error(p)) {
|
|
printf("ERROR: %s\n", htparser_get_strerror(p));
|
|
}
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
static const char * test_fragment_1[] = {
|
|
"GET \0",
|
|
" /fjdksf\0",
|
|
"jfkdslfds H\0",
|
|
"TTP/1.\0",
|
|
"1\r\0",
|
|
"\n\0",
|
|
"\r\0",
|
|
"\n\0",
|
|
NULL
|
|
};
|
|
|
|
static const char * test_fragment_2[] = {
|
|
"POST /\0",
|
|
"h?a=b HTTP/1.0\r\n\0",
|
|
"Content-Len\0",
|
|
"gth\0",
|
|
": 1\0",
|
|
"0\r\n\0",
|
|
"\r\n\0",
|
|
"12345\0",
|
|
"67890\0",
|
|
NULL
|
|
};
|
|
|
|
static const char * test_chunk_fragment_1[] = {
|
|
"POST /stupid HTTP/1.1\r\n",
|
|
"Transfer-Encoding: chunked\r\n",
|
|
"\r\n",
|
|
"25\r\n",
|
|
"This is the data in the first chunk\r\n",
|
|
"\r\n",
|
|
"1C\r\n",
|
|
"and this is the second one\r\n",
|
|
"\r\n",
|
|
"3\r\n",
|
|
"con\r\n",
|
|
"8\r\n",
|
|
"sequence\r\n",
|
|
"0\r\n",
|
|
"\r\n",
|
|
NULL
|
|
};
|
|
|
|
static const char * test_chunk_fragment_2[] = {
|
|
"POST /stupid HTTP/1.1\r\n",
|
|
"Transfer-Encoding: chunked\r\n",
|
|
"\r\n",
|
|
"25\r\n",
|
|
"This is the data in the first chunk\r\n",
|
|
"\r\n",
|
|
"1C\r\n",
|
|
"and this is the second one\r\n",
|
|
"\r\n",
|
|
"3\r\n",
|
|
"c",
|
|
"on\r\n",
|
|
"8\r\n",
|
|
"sequence\r\n",
|
|
"0\r\n",
|
|
"\r\n",
|
|
"GET /foo?bar/baz? HTTP/1.0\r\n",
|
|
"Host: stupid.com\r\n",
|
|
"\r\n",
|
|
NULL
|
|
};
|
|
int
|
|
main(int argc, char ** argv) {
|
|
htparser * p = htparser_new();
|
|
htparse_hooks hooks = {
|
|
.on_msg_begin = _on_msg_start,
|
|
.method = _method,
|
|
.scheme = NULL,
|
|
.host = NULL,
|
|
.port = NULL,
|
|
.path = _path,
|
|
.args = _args,
|
|
.uri = _uri,
|
|
.on_hdrs_begin = _hdrs_start,
|
|
.hdr_key = _hdr_key,
|
|
.hdr_val = _hdr_val,
|
|
.on_hdrs_complete = _hdrs_end,
|
|
.on_new_chunk = _on_new_chunk,
|
|
.on_chunk_complete = NULL,
|
|
.on_chunks_complete = NULL,
|
|
.body = _read_body,
|
|
.on_msg_complete = _on_msg_end
|
|
};
|
|
|
|
const char * test_1 = "GET / HTTP/1.0\r\n\r\n";
|
|
const char * test_2 = "GET /hi?a=b&c=d HTTP/1.1\r\n\r\n";
|
|
const char * test_3 = "GET /hi/die/?a=b&c=d HTTP/1.1\r\n\r\n";
|
|
const char * test_4 = "POST /fjdls HTTP/1.0\r\n"
|
|
"Content-Length: 4\r\n"
|
|
"\r\n"
|
|
"abcd";
|
|
const char * test_7 = "POST /derp HTTP/1.1\r\n"
|
|
"Transfer-Encoding: chunked\r\n\r\n"
|
|
"1e\r\nall your base are belong to us\r\n"
|
|
"0\r\n"
|
|
"\r\n\0";
|
|
const char * test_8 = "GET /DIE HTTP/1.1\r\n"
|
|
"HERP: DE\r\n"
|
|
"\tRP\r\nthings:stuff\r\n\r\n";
|
|
const char * test_9 = "GET /big_content_len HTTP/1.1\r\n"
|
|
"Content-Length: 18446744073709551615\r\n\r\n";
|
|
|
|
const char * test_fail = "GET /JF HfD]\r\n\r\n";
|
|
const char * test_resp_1 = "HTTP/1.0 200 OK\r\n"
|
|
"Stuff: junk\r\n\r\n";
|
|
|
|
_test(p, &hooks, test_resp_1, htp_type_response);
|
|
_test(p, &hooks, test_1, htp_type_request);
|
|
_test(p, &hooks, test_2, htp_type_request);
|
|
_test(p, &hooks, test_3, htp_type_request);
|
|
_test(p, &hooks, test_4, htp_type_request);
|
|
_test(p, &hooks, test_7, htp_type_request);
|
|
_test(p, &hooks, test_8, htp_type_request);
|
|
_test(p, &hooks, test_9, htp_type_request);
|
|
_test(p, &hooks, test_fail, htp_type_request);
|
|
|
|
_test_fragments(p, &hooks, test_fragment_1, htp_type_request);
|
|
_test_fragments(p, &hooks, test_fragment_2, htp_type_request);
|
|
_test_fragments(p, &hooks, test_chunk_fragment_1, htp_type_request);
|
|
_test_fragments(p, &hooks, test_chunk_fragment_2, htp_type_request);
|
|
|
|
return 0;
|
|
} /* main */
|
|
|