From 4488041fd3352b7c98678324253651178dcd9410 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sun, 15 Apr 2012 08:36:14 +0000 Subject: [PATCH] added QSE_HTRD_STRICT added qse_perdechttpstr() --- qse/include/qse/net/htrd.h | 3 ++- qse/include/qse/net/http.h | 5 ++++ qse/lib/net/htrd.c | 51 ++++++++++++++++++++++++++++++++------ qse/lib/net/http.c | 28 +++++++++++++++++++++ qse/lib/net/httpd.c | 10 +++++--- qse/samples/net/http01.c | 5 ++++ 6 files changed, 90 insertions(+), 12 deletions(-) diff --git a/qse/include/qse/net/htrd.h b/qse/include/qse/net/htrd.h index f234e61b..48f11ea4 100644 --- a/qse/include/qse/net/htrd.h +++ b/qse/include/qse/net/htrd.h @@ -49,7 +49,8 @@ enum qse_htrd_option_t QSE_HTRD_PEEKONLY = (1 << 2), /**< trigger a peek callback after headers without processing contents */ QSE_HTRD_REQUEST = (1 << 3), /**< parse input as a request */ QSE_HTRD_RESPONSE = (1 << 4), /**< parse input as a response */ - QSE_HTRD_TRAILERS = (1 << 5) /**< store trailers in a separate table */ + QSE_HTRD_TRAILERS = (1 << 5), /**< store trailers in a separate table */ + QSE_HTRD_STRICT = (1 << 6) /**< be more picky */ }; typedef enum qse_htrd_option_t qse_htrd_option_t; diff --git a/qse/include/qse/net/http.h b/qse/include/qse/net/http.h index f60956d7..a3c13daa 100644 --- a/qse/include/qse/net/http.h +++ b/qse/include/qse/net/http.h @@ -187,6 +187,11 @@ int qse_parsehttpdatetime ( ); */ +qse_size_t qse_perdechttpstr ( + const qse_mchar_t* str, + qse_mchar_t* buf +); + #ifdef __cplusplus } #endif diff --git a/qse/lib/net/htrd.c b/qse/lib/net/htrd.c index b29a9494..410e6d0f 100644 --- a/qse/lib/net/htrd.c +++ b/qse/lib/net/htrd.c @@ -302,9 +302,7 @@ static qse_mchar_t* parse_initial_line ( /* process the url part */ tmp.ptr = p; /* remember the beginning of path*/ param.ptr = QSE_NULL; - -/* TODO: maintain undecode path....???? */ - +#if 0 out = p; while (*p != QSE_MT('\0') && !is_space_octet(*p)) { @@ -325,7 +323,7 @@ static qse_mchar_t* parse_initial_line ( /* percent enconding contains a null character */ goto badre; } - + *out++ = t; p += 3; } @@ -333,7 +331,7 @@ static qse_mchar_t* parse_initial_line ( } else if (*p == QSE_MT('?')) { - if (!param.ptr) + if (param.ptr == QSE_NULL) { /* ? must be explicit to be an argument instroducer. * %3f is just a literal. */ @@ -346,7 +344,7 @@ static qse_mchar_t* parse_initial_line ( } else *out++ = *p++; } - + /* the url must be followed by a space */ if (!is_space_octet(*p)) goto badre; @@ -365,7 +363,33 @@ static qse_mchar_t* parse_initial_line ( htrd->re.u.q.path = tmp.ptr; htrd->re.u.q.param = QSE_NULL; } +#else + while (*p != QSE_MT('\0') && !is_space_octet(*p)) + { + if (*p == QSE_MT('?') && param.ptr == QSE_NULL) + { + *p++ = QSE_MT('\0'); /* null-terminate the path part */ + param.ptr = p; + } + else p++; + } + /* the url must be followed by a space */ + if (!is_space_octet(*p)) goto badre; + *p = QSE_MT('\0'); /* null-terminate the path or param part */ + + if (param.ptr) + { + htrd->re.u.q.path = tmp.ptr; + htrd->re.u.q.param = param.ptr; + } + else + { + htrd->re.u.q.path = tmp.ptr; + htrd->re.u.q.param = QSE_NULL; + } +#endif + /* skip spaces after the url part */ do { p++; } while (is_space_octet(*p)); @@ -763,7 +787,20 @@ qse_mchar_t* parse_header_field ( } name.len = last - name.ptr; - if (*p != QSE_MT(':')) goto badhdr; + if (*p != QSE_MT(':')) + { + if (!(htrd->option & QSE_HTRD_STRICT)) + { + while (is_space_octet(*p)) p++; + if (*p == QSE_MT('\n')) + { + /* ignore a line without a colon */ + p++; + return p; + } + } + goto badhdr; + } *last = '\0'; /* skip the colon and spaces after it */ diff --git a/qse/lib/net/http.c b/qse/lib/net/http.c index 35411ef5..d339b98e 100644 --- a/qse/lib/net/http.c +++ b/qse/lib/net/http.c @@ -194,5 +194,33 @@ int qse_parsehttpdatetime (const qse_mchar_t* str, qse_ntime_t* t) } #endif +qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf) +{ + const qse_mchar_t* p = str; + qse_mchar_t* out = buf; + + while (*p != QSE_T('\0')) + { + if (*p == QSE_MT('%') && *(p+1) != QSE_MT('\0') && *(p+2) != QSE_MT('\0')) + { + int q = QSE_MXDIGITTONUM (*(p+1)); + if (q >= 0) + { + int w = QSE_MXDIGITTONUM (*(p+2)); + if (w >= 0) + { + /* unlike the path part, we don't care if it + * contains a null character */ + *out++ = ((q << 4) + w); + p += 3; + continue; + } + } + } + *out++ = *p++; + } + *out = QSE_MT('\0'); + return out - buf; +} diff --git a/qse/lib/net/httpd.c b/qse/lib/net/httpd.c index 237efce7..60f085de 100644 --- a/qse/lib/net/httpd.c +++ b/qse/lib/net/httpd.c @@ -717,10 +717,6 @@ qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i); } } - /* feed may have called the request callback multiple times... - * that's because we don't know how many valid requests - * are included in 'buf' */ - httpd->errnum = QSE_HTTPD_ENOERR; qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i); { int i; @@ -728,6 +724,10 @@ for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]); } qse_printf (QSE_T("]\n")); + /* qse_htrd_feed() may call the request callback + * multiple times. that's because we don't know + * how many valid requests are included in 'buf'. */ + httpd->errnum = QSE_HTTPD_ENOERR; if (qse_htrd_feed (client->htrd, buf, m) <= -1) { if (httpd->errnum == QSE_HTTPD_ENOERR) @@ -744,6 +744,8 @@ int i; for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]); } qse_printf (QSE_T("]\n")); + + return -1; } diff --git a/qse/samples/net/http01.c b/qse/samples/net/http01.c index 5968909f..ec81b61e 100644 --- a/qse/samples/net/http01.c +++ b/qse/samples/net/http01.c @@ -1038,6 +1038,11 @@ static int process_request ( method = qse_htre_getqmethodtype(req); content_received = (qse_htre_getcontentlen(req) > 0); + /* percent-decode the query path to the original buffer + * since i'm not gonna need it in the original form + * any more */ + qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req)); + qse_printf (QSE_T("================================\n")); qse_printf (QSE_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"), (unsigned long)time(NULL),