summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2016-08-28 23:23:10 -0400
committerPaul Duncan <pabs@pablotron.org>2016-08-28 23:23:10 -0400
commit0308b0cc9fab95f0f12aa874ae1fcded31d7f573 (patch)
tree47e40528e1439e161b3f855e2bab7c7233b6d94a
parent845ddb43da8aa2a8c80a9d9638d63386ddf97d7e (diff)
downloadlibfhp-0308b0cc9fab95f0f12aa874ae1fcded31d7f573.tar.bz2
libfhp-0308b0cc9fab95f0f12aa874ae1fcded31d7f573.zip
add content-type parser
-rw-r--r--Makefile2
-rw-r--r--ct-parser.c49
-rw-r--r--ctx.c6
-rw-r--r--env.c3
-rw-r--r--header-value-parser.c19
-rw-r--r--include/fhp/fhp.h33
-rw-r--r--internal.h3
-rw-r--r--test.c1
-rw-r--r--token.c1
9 files changed, 115 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 29e9424..b36c1b3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
CC ?= cc
CFLAGS=-std=c99 -W -Wall -pedantic -O2 -Iinclude -fPIC
-OBJS=ctx.o hash.o error.o token.o env.o te-parser.o cl-parser.o header-value-parser.o
+OBJS=ctx.o hash.o error.o token.o env.o te-parser.o cl-parser.o ct-parser.o header-value-parser.o
SONAME=libfhp.so
LIB=libfhp.so
STATIC_LIB=libfhp.a
diff --git a/ct-parser.c b/ct-parser.c
new file mode 100644
index 0000000..0eb98b3
--- /dev/null
+++ b/ct-parser.c
@@ -0,0 +1,49 @@
+#include "internal.h"
+
+//
+// content-type parser
+//
+
+fhp_err_t
+fhp_ct_parser_init(
+ fhp_ct_parser_t * const p,
+ fhp_env_t * const env
+) {
+ // init parser
+ p->env = env;
+ p->hash = fhp_hash_init();
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_ct_parser_push(
+ fhp_ct_parser_t *p,
+ uint8_t * const buf,
+ size_t len
+) {
+ p->hash = fhp_lc_hash_push(p->hash, buf, len);
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_ct_parser_done(
+ fhp_ct_parser_t * const p,
+ fhp_content_type_t * const ret_val
+) {
+ if (ret_val) {
+ if (p->hash == p->env->hashes[FHP_STR_APPLICATION_X_WWW_FORM_URLENCODED]) {
+ *ret_val = FHP_CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED;
+ } else if (p->hash == p->env->hashes[FHP_STR_MULTIPART_FORM_DATA]) {
+ *ret_val = FHP_CONTENT_TYPE_MULTIPART_FORM_DATA;
+ } else {
+ *ret_val = FHP_CONTENT_TYPE_OTHER;
+ }
+ }
+
+ // return success
+ return FHP_OK;
+}
diff --git a/ctx.c b/ctx.c
index d2d7245..60b379e 100644
--- a/ctx.c
+++ b/ctx.c
@@ -112,6 +112,7 @@ static const fhp_ctx_t FHP_CTX_DEFAULT = {
.body_type = FHP_BODY_TYPE_NONE,
.content_length = 0,
.num_tes = 0,
+ .content_type = FHP_CONTENT_TYPE_NONE,
};
fhp_err_t
@@ -884,3 +885,8 @@ uint64_t
fhp_ctx_get_content_length(fhp_ctx_t * const ctx) {
return ctx->content_length;
}
+
+fhp_content_type_t
+fhp_ctx_get_content_type(fhp_ctx_t * const ctx) {
+ return ctx->content_type;
+}
diff --git a/env.c b/env.c
index 6b94f0c..77c90f9 100644
--- a/env.c
+++ b/env.c
@@ -11,6 +11,7 @@ fhp_strings[] = {
"HTTP/1.0",
"HTTP/1.1",
"content-length",
+ "content-type",
"transfer-encoding",
"gzip",
"x-gzip",
@@ -19,6 +20,8 @@ fhp_strings[] = {
"compress",
"x-compress",
"chunked",
+ "application/x-www-form-urlencoded",
+ "multipart/form-data",
NULL
};
diff --git a/header-value-parser.c b/header-value-parser.c
index e3c4107..d899889 100644
--- a/header-value-parser.c
+++ b/header-value-parser.c
@@ -33,6 +33,13 @@ fhp_header_value_parser_init(fhp_ctx_t * const ctx) {
// init parser
if ((err = fhp_cl_parser_init(&(ctx->parsers.cl))) != FHP_OK)
return err;
+ } else if (hash == ctx->env->hashes[FHP_STR_CONTENT_TYPE]) {
+ // set parser type
+ parser = FHP_HEADER_VALUE_PARSER_CONTENT_TYPE;
+
+ // init parser
+ if ((err = fhp_ct_parser_init(&(ctx->parsers.ct), ctx->env)) != FHP_OK)
+ return err;
} else {
// set default parser type
parser = FHP_HEADER_VALUE_PARSER_NONE;
@@ -60,6 +67,9 @@ fhp_header_value_parser_push(
case FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH:
r = fhp_cl_parser_push(&(ctx->parsers.cl), buf, len);
break;
+ case FHP_HEADER_VALUE_PARSER_CONTENT_TYPE:
+ r = fhp_ct_parser_push(&(ctx->parsers.ct), buf, len);
+ break;
default:
// do nothing
r = FHP_OK;
@@ -151,6 +161,15 @@ fhp_header_value_parser_done(fhp_ctx_t * const ctx) {
return FHP_ERR_CB;
break;
+ case FHP_HEADER_VALUE_PARSER_CONTENT_TYPE:
+ // finish parsing content-length and copy to context
+ if ((r = fhp_ct_parser_done(&(ctx->parsers.ct), &(ctx->content_type))) != FHP_OK)
+ return r;
+
+ // notify callback
+ if (!ctx->cb(ctx, FHP_TOKEN_HEADER_CONTENT_TYPE, 0, 0))
+ return FHP_ERR_CB;
+
default:
// do nothing
r = FHP_OK;
diff --git a/include/fhp/fhp.h b/include/fhp/fhp.h
index 3aa020d..6225843 100644
--- a/include/fhp/fhp.h
+++ b/include/fhp/fhp.h
@@ -96,6 +96,7 @@ typedef enum {
FHP_TOKEN_HEADER_TRANSFER_ENCODING,
FHP_TOKEN_HEADER_CONTENT_LENGTH,
+ FHP_TOKEN_HEADER_CONTENT_TYPE,
FHP_TOKEN_HEADERS_END,
@@ -127,7 +128,7 @@ typedef enum {
// env functions
//
-#define FHP_ENV_NUM_HASHES 17
+#define FHP_ENV_NUM_HASHES 20
typedef struct {
uint32_t hashes[FHP_ENV_NUM_HASHES];
@@ -165,6 +166,32 @@ fhp_err_t
fhp_cl_parser_done(fhp_cl_parser_t * const, uint64_t * const);
//
+// content-type parser functions
+//
+
+typedef enum {
+ FHP_CONTENT_TYPE_NONE,
+ FHP_CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED,
+ FHP_CONTENT_TYPE_MULTIPART_FORM_DATA,
+ FHP_CONTENT_TYPE_OTHER,
+ FHP_CONTENT_TYPE_LAST
+} fhp_content_type_t;
+
+typedef struct {
+ fhp_env_t *env;
+ uint32_t hash;
+} fhp_ct_parser_t;
+
+fhp_err_t
+fhp_ct_parser_init(fhp_ct_parser_t * const, fhp_env_t * const);
+
+fhp_err_t
+fhp_ct_parser_push(fhp_ct_parser_t *, uint8_t * const, size_t);
+
+fhp_err_t
+fhp_ct_parser_done(fhp_ct_parser_t * const, fhp_content_type_t * const);
+
+//
// transfer-encoding parser functions
//
@@ -257,6 +284,7 @@ typedef enum {
FHP_HEADER_VALUE_PARSER_NONE,
FHP_HEADER_VALUE_PARSER_TRANSFER_ENCODING,
FHP_HEADER_VALUE_PARSER_CONTENT_LENGTH,
+ FHP_HEADER_VALUE_PARSER_CONTENT_TYPE,
FHP_HEADER_VALUE_PARSER_LAST
} fhp_header_value_parser_t;
@@ -302,6 +330,7 @@ struct fhp_ctx_t_ {
union {
fhp_te_parser_t te;
fhp_cl_parser_t cl;
+ fhp_ct_parser_t ct;
} parsers;
// request body type
@@ -310,6 +339,8 @@ struct fhp_ctx_t_ {
// content length
uint64_t content_length;
+ fhp_content_type_t content_type;
+
// transfer encodings
uint32_t tes[FHP_CTX_MAX_TRANSFER_ENCODINGS];
size_t num_tes;
diff --git a/internal.h b/internal.h
index 1e2733a..0f557a9 100644
--- a/internal.h
+++ b/internal.h
@@ -194,6 +194,7 @@ typedef enum {
FHP_STR_HTTP_10,
FHP_STR_HTTP_11,
FHP_STR_CONTENT_LENGTH,
+ FHP_STR_CONTENT_TYPE,
FHP_STR_TRANSFER_ENCODING,
FHP_STR_GZIP,
FHP_STR_X_GZIP,
@@ -202,6 +203,8 @@ typedef enum {
FHP_STR_COMPRESS,
FHP_STR_X_COMPRESS,
FHP_STR_CHUNKED,
+ FHP_STR_APPLICATION_X_WWW_FORM_URLENCODED,
+ FHP_STR_MULTIPART_FORM_DATA,
FHP_STR_LAST
} fhp_str_t;
diff --git a/test.c b/test.c
index 7bcb360..280eab0 100644
--- a/test.c
+++ b/test.c
@@ -31,6 +31,7 @@ static const char *
basic_str =
"GET / HTTP/1.1\r\n"
"Host: pablotron.org\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
"Connection: close\r\n"
"Content-Length: 15\r\n"
"\r\n"
diff --git a/token.c b/token.c
index 721740d..d061692 100644
--- a/token.c
+++ b/token.c
@@ -40,6 +40,7 @@ fhp_tokens[] = {
"HEADER_TRANSFER_ENCODING",
"HEADER_CONTENT_LENGTH",
+ "HEADER_CONTENT_TYPE",
"HEADERS_END",