added more lines for http parsing

This commit is contained in:
hyung-hwan 2010-10-27 07:01:16 +00:00
parent f23fd6a4f6
commit 167449e3f1
3 changed files with 100 additions and 26 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: htb.h 356 2010-09-07 12:29:25Z hyunghwan.chung $ * $Id: htb.h 362 2010-10-26 13:01:16Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -444,9 +444,9 @@ void qse_htb_clear (
* The qse_htb_walk() function traverses a hash table. * The qse_htb_walk() function traverses a hash table.
*/ */
void qse_htb_walk ( void qse_htb_walk (
qse_htb_t* htb, /**< hash table */ qse_htb_t* htb, /**< hash table */
qse_htb_walker_t walker, /**< callback function for each pair */ qse_htb_walker_t walker, /**< callback function for each pair */
void* ctx /**< pointer to user-specific data */ void* ctx /**< pointer to user-specific data */
); );
/** /**

View File

@ -7,6 +7,7 @@
#include <qse/types.h> #include <qse/types.h>
#include <qse/macros.h> #include <qse/macros.h>
#include <qse/cmn/htb.h>
typedef struct qse_http_octb_t qse_http_octb_t; typedef struct qse_http_octb_t qse_http_octb_t;
@ -69,14 +70,25 @@ struct qse_http_t
QSE_HTTP_REQ_POST QSE_HTTP_REQ_POST
} method; } method;
const qse_byte_t* path; struct
const qse_byte_t* args; {
qse_byte_t* ptr;
qse_size_t len;
} path;
struct
{
qse_byte_t* ptr;
qse_size_t len;
} args;
struct struct
{ {
short major; short major;
short minor; short minor;
} version; } version;
qse_htb_t hdr;
} req; } req;
}; };

View File

@ -218,6 +218,11 @@ static QSE_INLINE int is_space_octet (qse_byte_t c)
return c == ' ' || c == '\t' || c == '\r'; return c == ' ' || c == '\t' || c == '\r';
} }
static QSE_INLINE int is_purespace_octet (qse_byte_t c)
{
return c == ' ' || c == '\t';
}
static QSE_INLINE int is_upalpha_octet (qse_byte_t c) static QSE_INLINE int is_upalpha_octet (qse_byte_t c)
{ {
return c >= 'A' && c <= 'Z'; return c >= 'A' && c <= 'Z';
@ -370,11 +375,19 @@ qse_http_t* qse_http_init (qse_http_t* http, qse_mmgr_t* mmgr)
http->state.crlf = 0; http->state.crlf = 0;
http->state.plen = 0; http->state.plen = 0;
init_buffer (http, &http->req.raw); init_buffer (http, &http->req.raw);
if (qse_htb_init (&http->req.hdr, mmgr, 60, 70) == QSE_NULL)
{
fini_buffer (http, &http->req.raw);
return QSE_NULL;
}
return http; return http;
} }
void qse_http_fini (qse_http_t* http) void qse_http_fini (qse_http_t* http)
{ {
qse_htb_fini (&http->req.hdr);
fini_buffer (http, &http->req.raw); fini_buffer (http, &http->req.raw);
} }
@ -421,11 +434,11 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line)
while (is_space_octet(*p)) p++; while (is_space_octet(*p)) p++;
/* process the url part */ /* process the url part */
http->req.path = p; http->req.path.ptr = p;
http->req.args = QSE_NULL; http->req.args.ptr = QSE_NULL;
tmp = p; tmp = p;
while (!is_space_octet(*p)) while (*p != '\0' && !is_space_octet(*p))
{ {
if (*p == '%') if (*p == '%')
{ {
@ -448,12 +461,13 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line)
} }
else if (*p == '?') else if (*p == '?')
{ {
if (!http->req.args) if (!http->req.args.ptr)
{ {
/* ? must be explicit to be a argument instroducer. /* ? must be explicit to be a argument instroducer.
* %3f is just a literal. */ * %3f is just a literal. */
*tmp++ = '\0'; http->req.path.len = tmp - http->req.path.ptr;
http->req.args = tmp; /**tmp++ = '\0';*/
http->req.args.ptr = tmp;
p++; p++;
} }
else *tmp++ = *p++; else *tmp++ = *p++;
@ -464,8 +478,11 @@ static qse_byte_t* parse_http_req (qse_http_t* http, qse_byte_t* line)
/* the url must be followed by a space */ /* the url must be followed by a space */
if (!is_space_octet(*p)) goto badreq; if (!is_space_octet(*p)) goto badreq;
/* null-terminate the url part */ if (http->req.args.ptr)
*tmp = '\0'; http->req.args.len = tmp - http->req.args.ptr;
else
http->req.path.len = tmp - http->req.path.ptr;
/* *tmp = '\0'; */ /* null-terminate the url part */
/* skip spaces after the url part */ /* skip spaces after the url part */
do { p++; } while (is_space_octet(*p)); do { p++; } while (is_space_octet(*p));
@ -499,13 +516,14 @@ qse_printf (QSE_T("parse_http_req ....\n"));
return ++p; return ++p;
badreq: badreq:
qse_printf (QSE_T("BADREQ\n"));
http->errnum = QSE_HTTP_EBADREQ; http->errnum = QSE_HTTP_EBADREQ;
return QSE_NULL; return QSE_NULL;
} }
qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line) qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line)
{ {
qse_byte_t* p = line, * mark; qse_byte_t* p = line, * last;
struct struct
{ {
qse_byte_t* ptr; qse_byte_t* ptr;
@ -517,28 +535,65 @@ qse_byte_t* parse_http_header (qse_http_t* http, qse_byte_t* line)
while (is_space_octet(*p)) p++; while (is_space_octet(*p)) p++;
#endif #endif
name.ptr = p; QSE_ASSERT (!is_whspace_octet(*p));
while (!is_whspace_octet(*p) && *p != ':') p++;
name.len = p - name.ptr; /* check the field name */
name.ptr = last = p;
while (*p != '\0' && *p != '\n' && *p != ':')
{
if (!is_space_octet(*p++)) last = p;
}
name.len = last - name.ptr;
mark = p; while (is_space_octet(*p)) p++;
if (*p != ':') goto badhdr; if (*p != ':') goto badhdr;
*mark = '\0'; *last = '\0';
/* skip the colon and spaces after it */ /* skip the colon and spaces after it */
do { p++; } while (is_space_octet(*p)); do { p++; } while (is_space_octet(*p));
value.ptr = p; value.ptr = last = p;
do { p++; } while (!is_whspace_octet(*p)); while (*p != '\0' && *p != '\n')
value.len = p - value.ptr; {
if (!is_space_octet(*p++)) last = p;
}
/* skip trailing spaces on the line */ value.len = last - value.ptr;
mark = p; while (is_space_octet(*p)) p++;
if (*p != '\n') goto badhdr; /* not ending with a new line */ if (*p != '\n') goto badhdr; /* not ending with a new line */
*mark = '\0';
/* peep at the beginning of the next line to check if it is
* the continuation */
if (is_purespace_octet (*++p))
{
qse_byte_t* cpydst;
cpydst = p - 1;
if (*(cpydst-1) == '\r') cpydst--;
/* process all continued lines */
do
{
while (*p != '\0' && *p != '\n')
{
*cpydst = *p++;
if (!is_space_octet(*cpydst++)) last = cpydst;
}
value.len = last - value.ptr;
if (*p != '\n') goto badhdr;
if (*(cpydst-1) == '\r') cpydst--;
}
while (is_purespace_octet(*++p));
}
*last = '\0';
if (qse_htb_insert (&http->req.hdr,
name.ptr, name.len, value.ptr, value.len) == QSE_NULL)
{
http->errnum = QSE_HTTP_ENOMEM;
return QSE_NULL;
}
qse_printf (QSE_T("<<%S>> => <<%S>>\n"), name.ptr, value.ptr);
return p; return p;
badhdr: badhdr:
@ -547,6 +602,10 @@ qse_printf (QSE_T("BADHDR\n"), name.ptr, value.ptr);
return QSE_NULL; return QSE_NULL;
} }
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
{
qse_printf (QSE_T("HEADER OK %d[%S] %d[%S]\n"), (int)pair->klen, pair->kptr, (int)pair->vlen, pair->vptr);
}
/* feed the percent encoded string */ /* feed the percent encoded string */
int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len) int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len)
@ -604,6 +663,9 @@ int qse_http_feed (qse_http_t* http, const qse_byte_t* ptr, qse_size_t len)
} }
while (1); while (1);
qse_htb_walk (&http->req.hdr, walk, QSE_NULL);
/* TODO: do the main job here... before the raw buffer is cleared out... */
clear_buffer (http, &http->req.raw); clear_buffer (http, &http->req.raw);
req = ptr; /* let ptr point to the next character to '\n' */ req = ptr; /* let ptr point to the next character to '\n' */
} }