summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2016-08-28 03:22:19 -0400
committerPaul Duncan <pabs@pablotron.org>2016-08-28 03:22:19 -0400
commitc10bcfa7def7a1093d78dcb15fd95388a633fc99 (patch)
treeaf553857dd28a0c2e3880a15390de3c16afb6a74
parente0b6b017ce80f468499ed60b1b6a95b5218fa814 (diff)
downloadlibfhp-c10bcfa7def7a1093d78dcb15fd95388a633fc99.tar.bz2
libfhp-c10bcfa7def7a1093d78dcb15fd95388a633fc99.zip
add cl-parser.c
-rw-r--r--Makefile2
-rw-r--r--cl-parser.c150
-rw-r--r--error.c10
-rw-r--r--include/fhp/fhp.h25
4 files changed, 184 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 0ab3d8f..0de2951 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
CC ?= cc
CFLAGS=-std=c99 -W -Wall -pedantic -O2 -Iinclude -fPIC
-OBJS=fhp.o hash.o error.o token.o env.o te-parser.o header-value-parser.o
+OBJS=fhp.o hash.o error.o token.o env.o te-parser.o cl-parser.o header-value-parser.o
SONAME=libfhp.so
LIB=libfhp.so
STATIC_LIB=libfhp.a
diff --git a/cl-parser.c b/cl-parser.c
new file mode 100644
index 0000000..83863c5
--- /dev/null
+++ b/cl-parser.c
@@ -0,0 +1,150 @@
+#include "internal.h"
+
+//
+// content length functions
+//
+
+static const fhp_cl_parser_t FHP_DEFAULT_CL_PARSER = {
+ .state = FHP_CL_STATE_INIT,
+ .val = 0,
+ .err = FHP_OK,
+};
+
+fhp_err_t
+fhp_cl_parser_init(fhp_cl_parser_t * const p) {
+ // init parser
+ *p = FHP_DEFAULT_CL_PARSER;
+
+ // return succes
+ return FHP_OK;
+}
+
+static fhp_err_t
+fhp_cl_parser_push_byte(
+ fhp_cl_parser_t * const p,
+ uint8_t byte
+) {
+retry:
+ switch (p->state) {
+ case FHP_CL_STATE_INIT:
+ switch (byte) {
+ CASE_OWS_CHARS
+ // ignore
+ break;
+ CASE_DIGIT_CHARS
+ // set state
+ p->state = FHP_CL_STATE_DATA;
+ goto retry;
+
+ break;
+ default:
+ // invalid character before content-length
+ return FHP_ERR_INVALID_CHAR_BEFORE_CL;
+ }
+
+ break;
+ case FHP_CL_STATE_DATA:
+ switch (byte) {
+ CASE_OWS_CHARS
+ // set state
+ p->state = FHP_CL_STATE_TRAILING_SPACES;
+ goto retry;
+
+ break;
+ CASE_DIGIT_CHARS
+ {
+ // cache old value
+ uint64_t old_val = p->val;
+
+ // update value
+ p->val = p->val * 10 + (byte - '0');
+
+ // check for overflow
+ if (p->val < old_val)
+ return FHP_ERR_CL_OVERFLOW;
+ }
+
+ break;
+ default:
+ // invalid character in content-length
+ return FHP_ERR_INVALID_CHAR_IN_CL;
+ }
+
+ break;
+ case FHP_CL_STATE_TRAILING_SPACES:
+ switch (byte) {
+ CASE_OWS_CHARS
+ // ignore trailing spaces
+
+ break;
+ default:
+ // invalid character after content-length
+ return FHP_ERR_INVALID_CHAR_AFTER_CL;
+ }
+
+ break;
+ case FHP_CL_STATE_ERROR:
+ // return last error
+ return p->err;
+
+ break;
+ case FHP_CL_STATE_DONE:
+ // shouldn't be reached
+ return FHP_ERR_CL_PARSER_DONE;
+
+ break;
+ default:
+ // never reached
+ return FHP_ERR_BAD_CL_STATE;
+ }
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_cl_parser_push(
+ fhp_cl_parser_t *p,
+ uint8_t * const buf,
+ size_t len
+) {
+ for (size_t i = 0; i < len; i++) {
+ // push byte
+ fhp_err_t err = fhp_cl_parser_push_byte(p, buf[i]);
+
+ // check error
+ if (err != FHP_OK) {
+ // cache error
+ p->err = err;
+
+ // set state
+ p->state = FHP_CL_STATE_ERROR;
+
+ // return error
+ return err;
+ }
+ }
+
+ // return succes
+ return FHP_OK;
+}
+
+fhp_err_t
+fhp_cl_parser_done(
+ fhp_cl_parser_t * const p,
+ uint64_t * const ret_val
+) {
+ // check for error
+ if (p->err != FHP_OK)
+ return p->err;
+
+ // set state
+ p->state = FHP_TE_STATE_DONE;
+
+ // save number of tes
+ if (ret_val)
+ *ret_val = p->val;
+
+ // return success
+ return FHP_OK;
+}
diff --git a/error.c b/error.c
index 43ec598..9850de8 100644
--- a/error.c
+++ b/error.c
@@ -22,10 +22,16 @@ fhp_errors[] = {
"too many transfer encodings",
"invalid character in transfer encoding name",
"invalid character in transfer encoding",
- "bad transfer encoding state",
- "transfer encoding parser already done",
+ "bad transfer-encoding parser state",
+ "transfer-encoding parser already done",
"NULL transfer encoding hash output buffer",
"transfer encoding hash output buffer is too small",
+ "invalid character before content-length header value",
+ "invalid character in content-length header value",
+ "invalid character after content-length header value",
+ "content-length parser already done",
+ "bad content-length parser state",
+ "overflow in content-length header value",
};
fhp_err_t
diff --git a/include/fhp/fhp.h b/include/fhp/fhp.h
index 46efb44..1e32a0d 100644
--- a/include/fhp/fhp.h
+++ b/include/fhp/fhp.h
@@ -41,6 +41,12 @@ typedef enum {
FHP_ERR_TE_PARSER_DONE,
FHP_ERR_NULL_TE_BUF,
FHP_ERR_SMALL_TE_BUF,
+ FHP_ERR_INVALID_CHAR_BEFORE_CL,
+ FHP_ERR_INVALID_CHAR_IN_CL,
+ FHP_ERR_INVALID_CHAR_AFTER_CL,
+ FHP_ERR_CL_PARSER_DONE,
+ FHP_ERR_BAD_CL_STATE,
+ FHP_ERR_CL_OVERFLOW,
FHP_ERR_LAST
} fhp_err_t;
@@ -114,6 +120,25 @@ void fhp_env_init(fhp_env_t * const env);
fhp_env_t *fhp_get_default_env(void);
//
+// content length parser functions
+//
+
+typedef enum {
+ FHP_CL_STATE_INIT,
+ FHP_CL_STATE_DATA,
+ FHP_CL_STATE_TRAILING_SPACES,
+ FHP_CL_STATE_ERROR,
+ FHP_CL_STATE_DONE,
+ FHP_CL_STATE_LAST
+} fhp_cl_state_t;
+
+typedef struct {
+ fhp_cl_state_t state;
+ fhp_err_t err;
+ uint64_t val;
+} fhp_cl_parser_t;
+
+//
// transfer encoding parser functions
//