Compare commits

..

2 Commits

Author SHA1 Message Date
679d651023 repo: implement tests and response parsing 2024-09-04 20:36:31 +02:00
0xdeadbeer
7525e8af77 tmp: start working on parsing response messages 2024-09-04 12:16:40 +02:00
6 changed files with 299 additions and 31 deletions

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
*.o
compile_commands.json
tinyparser
test

View File

@ -1,14 +1,23 @@
CC=gcc
CFLAGS=-g3
CFILES=parslib.c strings.c
CFILES_STREECMP=streecmp/streecmp.c
OUTPUT=parslib
TEST_FILES=test.c
OUTPUT=parslib.o
TOUTPUT=test
all:
$(CC) $(CFLAGS) $(CFILES) $(CFILES_STREECMP) -o $(OUTPUT)
all: $(FILES)
$(CC) -c $(CFLAGS) -o parslib.o parslib.c
$(CC) -c $(CFLAGS) -o strings.o strings.c
$(CC) -c $(CFLAGS) -o streecmp/streecmp.o streecmp/streecmp.c
test: all
$(CC) $(CFLAGS) $(TEST_FILES) parslib.o strings.o streecmp/streecmp.o -o $(TOUTPUT)
run_test:
./$(TOUTPUT)
run:
./$(OUTPUT)
clean:
rm -rf $(OUTPUT)
rm -rf *.o $(TOUTPUT)

8
README
View File

@ -27,14 +27,10 @@ TECHNICALS
LEAKS
LEAKS file contains the most recent valgrind memory leaks
dump ran on main.c
LEAKS.TEST.[id] files respectively contain the most recent
valgrind memory leaks dump ran on a test with an id=[id]
LEAKS file contains the most recent valgrind
memory leaks dump ran on a test program.
TODO
* implement tests
* integrations with tinyproxy..?

185
parslib.c
View File

@ -10,19 +10,77 @@ extern char *headers;
static struct nod *method_tree = NULL;
static struct nod *header_tree = NULL;
void printfpars(struct httpars *pars) {
static int stoin(char *str, int len, int *out) {
int ret = 0;
int place = 1;
for (char *chr = str+len-1; chr >= str; chr--) {
if (chr == str) {
if (*chr == '+') {
goto _proceed;
}
if (*chr == '-') {
goto _proceed;
}
}
if (*chr >= '0' && *chr <= '9') {
goto _proceed;
}
return -1;
_proceed:
if (*chr == '-') {
ret = -ret;
continue;
}
if (*chr == '+') {
continue;
}
int number = *chr-'0';
ret += number * place;
place *= 10;
}
*out = ret;
return 0;
}
void printfpareq(struct httpareq *req) {
fprintf(stderr, "\tstats:\n"
"\t\tmethod\t: %d\n"
"\t\turi\t: %.*s\n"
"\t\tver\t: %.*s\n",
pars->titl.method,
pars->titl.uri.len, pars->titl.uri.er,
pars->titl.ver.len, pars->titl.ver.er
req->titl.method,
req->titl.uri.len, req->titl.uri.er,
req->titl.ver.len, req->titl.ver.er
);
fprintf(stdout, "\theaders:\n");
for (int i = 0; i < header_count; i++) {
struct point *pnt = &pars->hentries[i];
struct point *pnt = &req->hentries[i];
if (!pnt->er) {
continue;
}
fprintf(stdout, "\t\t%d\t: %.*s\n", i, pnt->len, pnt->er);
}
}
void printfpares(struct httpares *res) {
fprintf(stderr, "\tstats:\n"
"\t\tver\t: %.*s\n"
"\t\tcode\t: %d\n"
"\t\tstext\t: %.*s\n",
res->titl.ver.len, res->titl.ver.er,
res->titl.code,
res->titl.stxt.len, res->titl.stxt.er
);
fprintf(stdout, "\theaders:\n");
for (int i = 0; i < header_count; i++) {
struct point *pnt = &res->hentries[i];
if (!pnt->er) {
continue;
}
@ -58,8 +116,8 @@ int initres(void) {
}
void fretres(void) {
free(method_tree);
free(header_tree);
frenod(method_tree);
frenod(header_tree);
}
int readlin(char **buff, char **buff_lim) {
@ -100,7 +158,7 @@ int parshfield(char *offset, int len, struct point *hentries) {
diff = htitle_lim-cursor;
ret = streencmp(header_tree, cursor, diff);
if (!ret) {
return -1;
return 0; // skip it
}
key = ret;
@ -129,14 +187,14 @@ _loop:
return 0;
}
int parstitle(char *offset, int len, struct httitle *titl) {
int pareqtitl(char *offset, int len, struct httitlereq *titl) {
int ret = 0;
int diff = 0;
char *cursor = offset;
char *cursor_lim = cursor+len;
// method
char *method_lim = strchr(offset, ' ');
char *method_lim = strchr(cursor, ' ');
if (!method_lim) {
return -1;
}
@ -198,13 +256,83 @@ _loop2:
return 0;
}
int parsme(char *buff, struct httpars *pars) {
int parestitl(char *offset, int len, struct httitleres *titl) {
int ret = 0;
int diff = 0;
char *cursor = offset;
char *cursor_lim = cursor+len;
// ver
char *ver_lim = strchr(cursor, ' ');
if (!ver_lim) {
return -1;
}
if (ver_lim > cursor_lim) {
return -1;
}
diff = ver_lim-cursor;
titl->ver.er = cursor;
titl->ver.len = diff;
cursor += diff;
// white space
_loop1:
if (cursor > cursor_lim) {
return -1;
}
if (*cursor == ' ') {
cursor++;
goto _loop1;
}
// code
char *code_lim = strchr(cursor, ' ');
if (!code_lim) {
return -1;
}
if (code_lim > cursor_lim) {
return -1;
}
diff = code_lim-cursor;
int code;
ret = stoin(cursor, diff, &code);
if (ret < 0) {
return -1;
}
titl->code = code;
cursor += diff;
// white space
_loop2:
if (cursor > cursor_lim) {
return -1;
}
if (*cursor == ' ') {
cursor++;
goto _loop2;
}
// status text
diff = cursor_lim-cursor;
titl->stxt.er = cursor;
titl->stxt.len = diff;
cursor += diff;
return 0;
}
int pareq(char *buff, struct httpareq *req) {
int ret;
char *buff_lim = buff+strlen(buff);
char *title_offset = buff;
int title_len = readlin(&buff, &buff_lim);
if ((ret = parstitle(title_offset, title_len, &pars->titl)) < 0) {
if ((ret = pareqtitl(title_offset, title_len, &req->titl)) < 0) {
fprintf(stderr, "Failed parsing title\n");
return -1;
}
@ -221,7 +349,7 @@ int parsme(char *buff, struct httpars *pars) {
if ((ret = parshfield(header_offset,
header_len,
pars->hentries)) < 0) {
req->hentries)) < 0) {
fprintf(stderr, "Failed parsing header\n");
return -1;
}
@ -230,3 +358,34 @@ int parsme(char *buff, struct httpars *pars) {
return 0;
}
int pares(char *buff, struct httpares *res) {
int ret;
char *buff_lim = buff+strlen(buff);
char *title_offset = buff;
int title_len = readlin(&buff, &buff_lim);
if ((ret = parestitl(title_offset, title_len, &res->titl)) < 0) {
fprintf(stderr, "Failed parsing title\n");
return -1;
}
for (int bound = 0; bound < MAX_BOUND; bound++) {
char *header_offset = buff;
int header_len = readlin(&buff, &buff_lim);
char *header_limit = header_offset+header_len;
// IF END OF MESSAGE
if (!header_len) {
break;
}
if ((ret = parshfield(header_offset,
header_len,
res->hentries)) < 0) {
fprintf(stderr, "Failed parsing header\n");
return -1;
}
}
return 0;
}

View File

@ -143,14 +143,25 @@ struct point {
int len;
};
struct httitle {
struct httitlereq {
int method;
struct point uri;
struct point ver;
};
struct httpars {
struct httitle titl;
struct httitleres {
struct point ver;
int code;
struct point stxt;
};
struct httpareq {
struct httitlereq titl;
struct point hentries[header_count];
};
struct httpares {
struct httitleres titl;
struct point hentries[header_count];
};
@ -158,8 +169,14 @@ int initres(void);
void fretres(void);
int readlin(char **buff, char **buff_lim);
int parshfield(char *offset, int len, /* out */ struct point *hentries);
int parstitle(char *offset, int len, /* out */ struct httitle *titl);
int parsme(char *buff, /* out */ struct httpars *pars);
void printfpars(struct httpars *pars);
int pareqtitl(char *offset, int len, struct httitlereq *titl);
int parestitl(char *offset, int len, struct httitleres *titl);
int pareq(char *buff, /* out */ struct httpareq *req);
int pares(char *buff, /* out */ struct httpares *res);
void printfpareq(struct httpareq *req);
void printfpares(struct httpares *res);
#endif

87
test.c Normal file
View File

@ -0,0 +1,87 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "parslib.h"
char *req_test_data = {
"GET / HTTP/1.1\r\n"
"Host: archive.0xdeadbeer.xyz\r\n"
"User-Agent: curl/8.9.1\r\n"
"Accept: */*\r\n"
"\r\n"
"{\"key\": \"kefjoiawejfojgorgjbosejrgo\"}|"
"GET / HTTP/1.1\r\n"
"Host: google.com\r\n"
"User-Agent: curl/8.9.1\r\n"
"Accept: */*\r\n|"
};
char *res_test_data = {
"HTTP/1.1 301 Moved Permanently\r\n"
"Location: http://www.google.com/\r\n"
"Content-Type: text/html; charset=UTF-8\r\n"
"Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-7hRaJZVpUAa6E54ys6qpuA' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp\r\n"
"Date: Wed, 04 Sep 2024 17:52:02 GMT\r\n"
"Expires: Fri, 04 Oct 2024 17:52:02 GMT\r\n"
"Cache-Control: public, max-age=2592000\r\n"
"Server: gws\r\n"
"Content-Length: 219\r\n"
"X-XSS-Protection: 0\r\n"
"X-Frame-Options: SAMEORIGIN\r\n|"
};
int main(void) {
int ret = 0;
char *reqs = strdup(req_test_data);
if (!reqs) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
char *reses = strdup(res_test_data);
if (!reses) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
struct httpareq *req = (struct httpareq *) calloc(1, sizeof(struct httpareq));
if (!req) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
struct httpares *res = (struct httpares *) calloc(1, sizeof(struct httpares));
if (!res) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
ret = initres();
if (ret < 0) {
fprintf(stderr, "Failed initializing parser\n");
return -1;
}
fprintf(stdout, "xxxREQxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
for (char *ch = strtok(reqs, "|"); ch != NULL; ch = strtok(NULL, "|")) {
ret = pareq(ch, req);
fprintf(stdout, "-------------------------------------\n");
printfpareq(req);
fprintf(stdout, "-------------------------------------\n");
}
fprintf(stdout, "xxxRESxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
for (char *ch = strtok(reses, "|"); ch != NULL; ch = strtok(NULL, "|")) {
ret = pares(ch, res);
fprintf(stdout, "-------------------------------------\n");
printfpares(res);
fprintf(stdout, "-------------------------------------\n");
}
fprintf(stdout, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
fretres();
free(res);
free(req);
free(reses);
free(reqs);
return 0;
}