Mime parsing

FossilOrigin-Name: e6a37f930fb748cdf6828053bc6df089e4ea426602863ae77aefb62c8ff773f2
This commit is contained in:
me@ow.nekobit.net 2022-04-08 22:43:48 +00:00
parent 4114bac685
commit 8d4b8f77d4
4 changed files with 105 additions and 23 deletions

3
.gitignore vendored
View file

@ -4,4 +4,5 @@ filec
**/*.chtml
mastodont-c
config.h
treebird
treebird
test/tests

View file

@ -1,3 +1,5 @@
# NOTE: This software is not finished. Any bugs are likely noted
# Treebird
![Treebird logo](./meta/treebird.png)

View file

@ -20,6 +20,7 @@
#include <fcgi_stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "mime.h"
char* get_mime_boundary(char* content_type_str, char** bound)
@ -64,49 +65,118 @@ error:
return NULL;
}
char* strnws(char* str)
static char* strnws(char* str)
{
for (; isblank(*str); ++str);
return str;
}
#define STRSCMP(begin, str) strncmp((begin), (str), sizeof(str))
// Function assumes character is at ';' char
static char* read_key(char** r, char* key)
{
char* val, *read_val;
size_t key_len = strlen(key);
*r = strnws(*r+1);
if (strncmp(*r, key, key_len) != 0)
return NULL;
*r = strnws(*r + key_len);
if (**r != '=')
return NULL;
*r = strnws(*r + 1);
if (**r == '\"') ++(*r);
val = *r;
// Chop off string
if ((read_val = strchr(*r, '\"')) ||
(read_val = strchr(*r, ';')) ||
(read_val = strchr(*r, '\r')))
*read_val = '\0';
// Jump to end
*r += strlen(val)+1;
return val;
}
#define STRSCMP(begin, str) strncmp((begin), (str), sizeof(str)-1)
char* read_form_data(char* boundary, char* begin, struct http_form_info* info)
{
char* r, *name;
ptrdiff_t data_size;
// Step 1: Parse name
// Parser variables
char* r, *read_val;
size_t bound_len = strlen(boundary);
if (strncmp(begin, "--", 2) != 0 ||
strncmp(begin+2, boundary, bound_len) != 0)
return NULL;
// Check if this is the end
if (strncmp(begin + 2 + bound_len, "--", 2) == 0)
return NULL;
r = begin + 2 + bound_len + 2; /* Skip over LRSF */
if (STRSCMP(r, "Content-Disposition") != 0)
return NULL;
r = strnws(r + sizeof("Content-Disposition")+1);
if (*r != ':' ||
STRSCMP(r, "form-data") != 0) // Fucked up
r = strnws(r + sizeof("Content-Disposition")-1);
if (*r != ':') // Fucked up
return NULL;
r = strnws(r + sizeof("form-data")+1);
r = strnws(r + 1);
if (STRSCMP(r, "form-data") != 0)
return NULL;
r = strnws(r + sizeof("form-data")-1);
if (*r != ';')
return NULL;
r = strnws(r+1);
if (STRSCMP(r, "name") != 0)
return NULL;
r = strnws(r + sizeof("name")+1);
if (*r != '=')
return NULL;
r = strnws(r + 1);
if (*r == '\"')
info->name = read_key(&r, "name");
// Step 2: Parse filename (if there)
if (*r == ';')
{
info->filename = read_key(&r, "filename");
}
else
info->filename = NULL;
if (*r == '\r')
r += 2;
if (*r == '\"') ++r;
name = r;
if ((r = strchr(r, '\"')))
*r = '\0';
printf("nameparsed: %s\r\n", name);
// Step 3: Parse Content-type (if there)
if (STRSCMP(r, "Content-Type") == 0)
{
r = strnws(r + sizeof("Content-type")-1);
if (*r != ':')
return NULL;
return name;
r = strnws(r + 1);
info->content_type = r;
if ((r = strchr(r, '\r')))
*r = '\0';
else
return NULL;
r += 4;
}
else if (*r == '\r') {
info->content_type = NULL;
r += 2;
}
// Last step: Find data
info->value = r;
// Look for end
if ((r = strstr(r, boundary)) &&
r && strstr(r-4, "\r\n--"))
{
r[-4] = '\0';
data_size = (r-4) - info->value;
info->value_size = data_size;
}
else
return NULL;
// Go back for next read
r -= 2;
return r;
}

View file

@ -19,7 +19,16 @@
#ifndef MIME_H
#define MIME_H
struct http_form_info
{
char* name;
char* filename;
char* content_type;
char* value;
size_t value_size;
};
char* get_mime_boundary(char* content_type, char** res);
char* read_mime_data(char* boundary, char* begin, struct http_form_info* info);
char* read_form_data(char* boundary, char* begin, struct http_form_info* info);
#endif /* MIME_H */