diff options
Diffstat (limited to 'ext/kcar/kcar.rl')
-rw-r--r-- | ext/kcar/kcar.rl | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/ext/kcar/kcar.rl b/ext/kcar/kcar.rl index 5b620ac..78437e7 100644 --- a/ext/kcar/kcar.rl +++ b/ext/kcar/kcar.rl @@ -70,12 +70,27 @@ struct http_parser { #define MARK(M,FPC) (hp->M = (FPC) - buffer) #define PTR_TO(F) (buffer + hp->F) #define STR_NEW(M,FPC) rb_str_new(PTR_TO(M), LEN(M, FPC)) +#define STRIPPED_STR_NEW(M,FPC) stripped_str_new(PTR_TO(M), LEN(M, FPC)) #define HP_FL_TEST(hp,fl) ((hp)->flags & (UH_FL_##fl)) #define HP_FL_SET(hp,fl) ((hp)->flags |= (UH_FL_##fl)) #define HP_FL_UNSET(hp,fl) ((hp)->flags &= ~(UH_FL_##fl)) #define HP_FL_ALL(hp,fl) (HP_FL_TEST(hp, fl) == (UH_FL_##fl)) +static int is_lws(char c) +{ + return (c == ' ' || c == '\t'); +} + +static VALUE stripped_str_new(const char *str, long len) +{ + long end; + + for (end = len - 1; end >= 0 && is_lws(str[end]); end--); + + return rb_str_new(str, end + 1); +} + static void finalize_header(struct http_parser *hp) { if ((HP_FL_TEST(hp, HASTRAILER) && ! HP_FL_TEST(hp, CHUNKED))) @@ -144,6 +159,9 @@ static void write_cont_value(struct http_parser *hp, char *buffer, const char *p) { char *vptr; + long end; + long len = LEN(mark, p); + long cont_len; if (hp->cont == Qfalse) rb_raise(eParserError, "invalid continuation line"); @@ -154,19 +172,24 @@ static void write_cont_value(struct http_parser *hp, assert(TYPE(hp->cont) == T_STRING && "continuation line is not a string"); assert(hp->mark > 0 && "impossible continuation line offset"); - if (LEN(mark, p) == 0) + if (len == 0) return; - if (RSTRING_LEN(hp->cont) > 0) + cont_len = RSTRING_LEN(hp->cont); + if (cont_len > 0) { --hp->mark; + len = LEN(mark, p); + } vptr = PTR_TO(mark); - if (RSTRING_LEN(hp->cont) > 0) { + /* normalize tab to space */ + if (cont_len > 0) { assert((' ' == *vptr || '\t' == *vptr) && "invalid leading white space"); *vptr = ' '; } - rb_str_buf_cat(hp->cont, vptr, LEN(mark, p)); + for (end = len - 1; end >= 0 && is_lws(vptr[end]); end--); + rb_str_buf_cat(hp->cont, vptr, end + 1); } static void write_value(VALUE hdr, struct http_parser *hp, @@ -192,7 +215,7 @@ static void write_value(VALUE hdr, struct http_parser *hp, VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE); VALIDATE_MAX_LENGTH(flen, FIELD_NAME); f = rb_str_new(fptr, (long)flen); - v = rb_str_new(vptr, (long)vlen); + v = stripped_str_new(vptr, (long)vlen); /* needs more tests for error-checking here */ /* |