parslib/tinyparser.c
2024-09-03 21:07:52 +02:00

200 lines
4.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tinyparser.h"
#include "streecmp/streecmp.h"
extern char *headers;
extern char *methods;
int method = 0;
char *uri = NULL;
char *ver = NULL;
int uri_len = 0;
int ver_len = 0;
struct nod *header_tree = NULL;
struct nod *method_tree = NULL;
char **header_table = NULL;
int read_line(char **buffer, char **buffer_limit) {
int diff = 0;
if ((*buffer) >= (*buffer_limit)) {
return diff;
}
int ret = 0;
char *match = strstr(*buffer, "\r\n");
if (match) {
ret = match-(*buffer);
*buffer += 2;
} else {
ret = (*buffer_limit)-(*buffer);
}
*buffer += ret;
return ret;
}
int parse_header(char *offset, int len) {
int cursor = 0;
int ret = 0;
char *header_limit = offset+len;
char *sep = strchr(offset, ':');
if (!sep) {
return -1;
}
if (sep > header_limit) {
return -1;
}
int htitle_len = sep-offset;
ret = streencmp(header_tree, offset, htitle_len);
if (ret == 0) {
return -1;
}
char *hvalue = sep+1;
header_table[ret] = hvalue;
return 0;
}
int parse_title(char *offset, int len) {
int ret = 0;
int diff = 0;
char *cursor = offset;
char *cursor_lim = cursor+len;
// method
char *method_lim = strchr(offset, ' ');
if (!method_lim) {
return -1;
}
diff = method_lim-cursor;
ret = streencmp(method_tree, cursor, diff);
if (ret == 0) {
return -1;
}
method = ret;
cursor += diff;
// white space
while (*cursor == ' ') {
cursor++;
}
// uri
char *uri_lim = strchr(cursor, ' ');
if (!uri_lim) {
return -1;
}
diff = uri_lim-cursor;
uri = cursor;
uri_len = diff;
cursor += diff;
// white space
while (*cursor == ' ') {
cursor++;
}
// ver
diff = cursor_lim-cursor;
ver = cursor;
ver_len = diff;
cursor += diff;
return 0;
}
int parse_request(char *buffer) {
int ret;
char *buffer_limit = buffer+strlen(buffer);
char *title_offset = buffer;
int title_len = read_line(&buffer, &buffer_limit);
if ((ret = parse_title(title_offset, title_len)) < 0) {
fprintf(stderr, "Failed parsing title\n");
return -1;
}
for (int bound = 0; bound < MAX_BOUND; bound++) {
char *header_offset = buffer;
int header_len = read_line(&buffer, &buffer_limit);
char *header_limit = header_offset+header_len;
// IF END OF MESSAGE
if (!header_len) {
break;
}
if ((ret = parse_header(header_offset, header_len)) < 0) {
fprintf(stderr, "Failed parsing header\n");
return -1;
}
}
return 0;
}
int main(void) {
int ret;
char *str = strdup(TEST_ONE);
header_table = (char **) calloc(header_count, sizeof(char *));
if (!header_table) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
header_tree = allocnod();
if (!header_tree) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
method_tree = allocnod();
if (!method_tree) {
fprintf(stderr, "Not enough dynamic memory\n");
return -1;
}
ret = gentree(header_tree, headers, NULL);
if (ret < 0) {
fprintf(stderr, "Failed generating the header comparison tree\n");
return -1;
}
ret = gentree(method_tree, methods, NULL);
if (ret < 0) {
fprintf(stderr, "Failed generating the header comparison tree\n");
return -1;
}
ret = parse_request(str);
if (ret < 0) {
fprintf(stderr, "Failed parsing request\n");
return -1;
}
fprintf(stderr, "[+] Finished parsing request\n"
" method: %d\n"
" uri : %.*s\n"
" ver : %.*s\n",
method, uri_len, uri, ver_len, ver
);
frenod(method_tree);
frenod(header_tree);
free(header_table);
free(str);
return 0;
}