2024-08-15 23:12:06 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "tinyparser.h"
|
2024-09-02 22:03:32 +00:00
|
|
|
#include "streecmp/streecmp.h"
|
|
|
|
|
|
|
|
extern char *headers;
|
2024-08-15 23:12:06 +00:00
|
|
|
|
|
|
|
enum errs err = err_init;
|
|
|
|
enum states state = state_init;
|
|
|
|
enum methods method = method_init;
|
|
|
|
char *uri = NULL;
|
|
|
|
char *ver = NULL;
|
|
|
|
int uri_len = 0;
|
|
|
|
int ver_len = 0;
|
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
struct nod *header_tree = NULL;
|
|
|
|
char **header_table = NULL;
|
|
|
|
|
|
|
|
int read_line(char **buffer, char **buffer_limit) {
|
2024-08-15 23:12:06 +00:00
|
|
|
int diff = 0;
|
2024-09-02 22:03:32 +00:00
|
|
|
if ((*buffer) >= (*buffer_limit)) {
|
|
|
|
return diff;
|
|
|
|
}
|
2024-08-15 23:12:06 +00:00
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
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;
|
2024-08-15 23:12:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int cmp_orig(char *ch, char *orig, char *limit) {
|
|
|
|
int diff = 0;
|
|
|
|
for (; *orig != '\0' && *ch != '\0' && ch < limit; orig++, ch++, diff++)
|
|
|
|
if (*orig != *ch)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cmp_ascii(char *ch, char *limit) {
|
|
|
|
int diff = 0;
|
|
|
|
for (; *ch != '\0' && *ch != ' ' && ch < limit; ch++, diff++) {
|
|
|
|
if (*ch >= '0' && *ch <= '9') continue;
|
|
|
|
if (*ch >= 'A' && *ch <= 'Z') continue;
|
|
|
|
if (*ch >= 'a' && *ch <= 'z') continue;
|
|
|
|
if (*ch >= '#' && *ch <= '/') continue;
|
|
|
|
if (*ch == '!') continue;
|
|
|
|
if (*ch == ':') continue;
|
|
|
|
if (*ch == ';') continue;
|
|
|
|
if (*ch == '=') continue;
|
|
|
|
if (*ch == '?') continue;
|
|
|
|
if (*ch == '@') continue;
|
|
|
|
if (*ch == '[') continue;
|
|
|
|
if (*ch == ']') continue;
|
|
|
|
if (*ch == '_') continue;
|
|
|
|
if (*ch == '~') continue;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
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 cursor = 0;
|
2024-08-15 23:12:06 +00:00
|
|
|
|
|
|
|
while (state != state_title_ok && state != state_title_err) {
|
2024-09-02 22:03:32 +00:00
|
|
|
if (cursor >= len) {
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_err;
|
|
|
|
err = err_parse_title;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = 0;
|
2024-09-02 22:03:32 +00:00
|
|
|
char *ch = offset+cursor;
|
|
|
|
char *lim = offset+len-1;
|
2024-08-15 23:12:06 +00:00
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case state_init:
|
|
|
|
state = state_title_method;
|
|
|
|
break;
|
|
|
|
case state_title_method:
|
|
|
|
if ((ret = cmp_orig(ch, "GET", lim))) {
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor += ret;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_after_method;
|
|
|
|
method = method_get;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((ret = cmp_orig(ch, "POST", lim))) {
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor += ret;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_after_method;
|
|
|
|
method = method_post;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((ret = cmp_orig(ch, "HEAD", lim))) {
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor += ret;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_after_method;
|
|
|
|
method = method_head;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_parse_title_method;
|
|
|
|
break;
|
|
|
|
case state_title_after_method:
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor++;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_uri;
|
|
|
|
break;
|
|
|
|
case state_title_uri:
|
|
|
|
if ((ret = cmp_ascii(ch, lim)) <= 0) {
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_parse_title_uri;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(uri = strndup(ch, ret))) {
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_memory;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
uri_len = ret;
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor += ret;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_after_uri;
|
|
|
|
break;
|
|
|
|
case state_title_after_uri:
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor++;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_version;
|
|
|
|
break;
|
|
|
|
case state_title_version:
|
|
|
|
if ((ret = cmp_ascii(ch, lim)) <= 0) {
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_parse_title_version;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(ver = strndup(ch, ret))) {
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_memory;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ver_len = ret;
|
2024-09-02 22:03:32 +00:00
|
|
|
cursor += ret;
|
2024-08-15 23:12:06 +00:00
|
|
|
state = state_title_ok;
|
|
|
|
break;
|
|
|
|
case state_title_ok:
|
|
|
|
for (;ch < lim;ch++) {
|
|
|
|
if (*ch == ' ') continue;
|
|
|
|
if (*ch == '\t') continue;
|
|
|
|
if (*ch == '\0') continue;
|
2024-09-02 22:03:32 +00:00
|
|
|
if (*ch == '\r') continue;
|
2024-08-15 23:12:06 +00:00
|
|
|
|
|
|
|
state = state_title_err;
|
|
|
|
err = err_parse_title;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case state_title_err:
|
|
|
|
fprintf(stderr, "failed\n");
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parse_request(char *buffer) {
|
|
|
|
int ret;
|
2024-09-02 22:03:32 +00:00
|
|
|
char *buffer_limit = buffer+strlen(buffer);
|
2024-08-15 23:12:06 +00:00
|
|
|
|
|
|
|
char *title_offset = buffer;
|
2024-09-02 22:03:32 +00:00
|
|
|
int title_len = read_line(&buffer, &buffer_limit);
|
2024-08-15 23:12:06 +00:00
|
|
|
if ((ret = parse_title(title_offset, title_len)) < 0) {
|
|
|
|
fprintf(stderr, "Failed parsing title\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
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) {
|
|
|
|
state = state_fin;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ret = parse_header(header_offset, header_len)) < 0) {
|
|
|
|
fprintf(stderr, "Failed parsing header\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(uri);
|
|
|
|
free(ver);
|
|
|
|
|
2024-08-15 23:12:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
int ret;
|
|
|
|
char *str = strdup(TEST_ONE);
|
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = gentree(header_tree, headers, NULL);
|
|
|
|
if (gentree < 0) {
|
|
|
|
fprintf(stderr, "Failed generating the header comparison tree\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-08-15 23:12:06 +00:00
|
|
|
ret = parse_request(str);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr, "Failed parsing request\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Finished parsing request\n");
|
|
|
|
|
2024-09-02 22:03:32 +00:00
|
|
|
frenod(header_tree);
|
|
|
|
free(header_table);
|
2024-08-15 23:12:06 +00:00
|
|
|
free(str);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|