joes 2003/04/10 19:48:01
Modified: src apreq.c apreq.h apreq_env.h apreq_params.c
apreq_params.h apreq_parsers.c apreq_parsers.h
apreq_tables.c
Log:
Completing work on upload-hook API. Next phase is to get current /src to a
compilable state.
Revision Changes Path
1.8 +16 -11 httpd-apreq-2/src/apreq.c
Index: apreq.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- apreq.c 6 Apr 2003 05:57:17 -0000 1.7
+++ apreq.c 11 Apr 2003 02:48:01 -0000 1.8
@@ -4,24 +4,29 @@
#define MIN(a,b) ( (a) < (b) ? (a) : (b) )
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
-APREQ_DECLARE(apreq_value_t *)apreq_make_value(apr_pool_t *p,
- const char *name,
- const char *d,
- apr_size_t size)
+APREQ_DECLARE(apreq_value_t *)apreq_make_value(apr_pool_t *p,
+ const char *name,
+ const apr_ssize_t nlen,
+ const char *val,
+ const apr_ssize_t vlen)
{
- apreq_value_t *v = apr_palloc(p, size + sizeof *v);
- if (d == NULL || v == NULL)
+ apreq_value_t *v = apr_palloc(p, vlen + nlen + 1 + sizeof *v);
+ if (v == NULL)
return NULL;
- memcpy(v->data, d, size);
- v->size = size;
+ v->size = vlen;
+ memcpy(v->data, val, vlen);
+ v->data[vlen] = 0;
+
+ v->name = v->data + vlen + 1;
+ memcpy((char *)v->name, name, nlen);
+ ((char *)v->name)[nlen] = 0;
v->status = APR_SUCCESS;
- v->name = name;
- v->data[size] = 0;
return v;
}
+
APREQ_DECLARE(apreq_value_t *)apreq_copy_value(apr_pool_t *p,
const apreq_value_t *val)
{
@@ -210,7 +215,7 @@
}
APREQ_DECLARE(apr_ssize_t) apreq_decode(char *d, const char *s,
- const apr_size_t slen)
+ const apr_ssize_t slen)
{
register int badesc = 0;
char *start = d;
1.8 +5 -4 httpd-apreq-2/src/apreq.h
Index: apreq.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- apreq.h 26 Jan 2003 02:39:08 -0000 1.7
+++ apreq.h 11 Apr 2003 02:48:01 -0000 1.8
@@ -52,9 +52,10 @@
#define apreq_strlen(ptr) (apreq_strtoval(ptr)->size)
APREQ_DECLARE(apreq_value_t *) apreq_make_value(apr_pool_t *p,
- const char *name,
- const char *data,
- const apr_size_t size);
+ const char *name,
+ const apr_ssize_t nlen,
+ const char *val,
+ const apr_ssize_t vlen);
APREQ_DECLARE(apreq_value_t *) apreq_copy_value(apr_pool_t *p,
const apreq_value_t *val);
@@ -83,7 +84,7 @@
/* url-escapes non-alphanumeric characters */
apr_size_t apreq_quote(char *dest, const char *src, const apr_size_t slen);
apr_size_t apreq_encode(char *dest, const char *src, const apr_size_t slen);
-apr_ssize_t apreq_decode(char *dest, const char *src, apr_size_t slen);
+apr_ssize_t apreq_decode(char *dest, const char *src, apr_ssize_t slen);
APREQ_DECLARE(char *) apreq_escape(apr_pool_t *p,
const char *src, const apr_size_t slen);
1.6 +1 -0 httpd-apreq-2/src/apreq_env.h
Index: apreq_env.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_env.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- apreq_env.h 26 Jan 2003 02:39:08 -0000 1.5
+++ apreq_env.h 11 Apr 2003 02:48:01 -0000 1.6
@@ -48,6 +48,7 @@
#define apreq_env_jar(c,j) APREQ_ENV.jar(c,j)
#define apreq_env_request(c,r) APREQ_ENV.jar(c,r)
#define apreq_env_pool(c) APREQ_ENV.pool(c)
+#define apreq_env_content_type(c) APREQ_ENV.in(c, "Content-Type");
#define apreq_env_cookie(c) APREQ_ENV.in(c, "Cookie")
#define apreq_env_cookie2(c) APREQ_ENV.in(c, "Cookie2")
#define apreq_env_set_cookie(c,s) APREQ_ENV.out(c,"Set-Cookie",s)
1.5 +34 -8 httpd-apreq-2/src/apreq_params.c
Index: apreq_params.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- apreq_params.c 26 Jan 2003 02:39:08 -0000 1.4
+++ apreq_params.c 11 Apr 2003 02:48:01 -0000 1.5
@@ -63,6 +63,31 @@
#define UPGRADE(s) apreq_value_to_param(apreq_char_to_value(s))
+APREQ_DECLARE(apreq_param_t *) apreq_make_param(apr_pool_t *p,
+ const char *name,
+ const apr_ssize_t nlen,
+ const char *val,
+ const apr_ssize_t vlen)
+{
+ apreq_param_t *param = apr_palloc(p, nlen + vlen + 1 + sizeof *param);
+ apreq_value_t *v = ¶m->v;
+ param->charset = APREQ_CHARSET;
+ param->language = NULL;
+ param->info = NULL;
+ param->bb = NULL;
+
+ v->size = vlen;
+ memcpy(v->data, val, vlen);
+ v->data[vlen] = 0;
+ v->name = v->data + vlen + 1;
+ memcpy((char *)v->name, name, nlen);
+ ((char *)v->name)[nlen] = 0;
+ v->status = APR_SUCCESS;
+
+ return param;
+}
+
+
APREQ_DECLARE(apreq_request_t *) apreq_request(void *ctx)
{
@@ -78,7 +103,7 @@
req->status = APR_EINIT;
req->ctx = ctx;
- req->args = apreq_table_make(p, APREQ_NELTS);
+ req->args = apreq_make_table(p, APREQ_NELTS);
req->body = NULL;
/* XXX get/set race condition here wrt apreq_env_request.
@@ -106,15 +131,16 @@
APREQ_DECLARE(apr_status_t) apreq_parse(apreq_request_t *req)
{
- if (req->body == NULL)
- if (req->status == APR_SUCCESS)
+ if (req->body == NULL) {
+ if (req->status == APR_SUCCESS) {
+ req->body = apreq_table_make(req->pool, APREQ_DEFAULT_NELTS);
return apreq_env_parse(req);
+ }
else
return req->status;
-
- else if (req->status == APR_EAGAIN)
+ }
+ else if (req->status == APR_EAGAIN || req->status == APR_INCOMPLETE)
return apreq_env_parse(req);
-
else
return req->status;
}
@@ -141,10 +167,10 @@
APREQ_DECLARE(apr_status_t) apreq_split_params(apr_pool_t *pool,
apreq_table_t *t,
const char *data,
- apr_size_t dlen)
+ apr_ssize_t dlen)
{
const char *start = data, *end = data + dlen;
- apr_size_t nlen = 0;
+ apr_ssize_t nlen = 0;
apr_status_t status = APR_SUCCESS;
for (; data < end; ++data) {
1.5 +8 -1 httpd-apreq-2/src/apreq_params.h
Index: apreq_params.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- apreq_params.h 26 Jan 2003 02:39:08 -0000 1.4
+++ apreq_params.h 11 Apr 2003 02:48:01 -0000 1.5
@@ -71,8 +71,10 @@
*
*/
+#define APREQ_CHARSET UTF_8;
+
typedef struct apreq_param_t {
- enum { ASCII, UTF_8, UTF_16, IS0_LATIN_1 } charset;
+ enum { ASCII, UTF_8, UTF_16, ISO_LATIN_1 } charset;
char *language;
apreq_table_t *info;
@@ -86,6 +88,11 @@
#define apreq_param_name(p) ((p)->v.name)
#define apreq_param_value(p) ((p)->v.data)
+APREQ_DECLARE(apreq_param_t *) apreq_make_param(apr_pool_t *p,
+ const char *name,
+ const apr_ssize_t nlen,
+ const char *val,
+ const apr_ssize_t vlen);
typedef struct apreq_request_t {
1.2 +222 -93 httpd-apreq-2/src/apreq_parsers.c
Index: apreq_parsers.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_parsers.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- apreq_parsers.c 9 Apr 2003 03:25:09 -0000 1.1
+++ apreq_parsers.c 11 Apr 2003 02:48:01 -0000 1.2
@@ -75,6 +75,8 @@
apr_pool_t *p,
const char *enctype,
APREQ_PARSER(*parser),
+ APREQ_HOOK(*hook),
+ void *hook_data,
void *out)
{
apreq_parser_t *p = apr_palloc(pool, APREQ_CTX_MAXSIZE + sizeof *p);
@@ -428,9 +430,9 @@
switch (data[off++]) {
case '\n':
- /* No more headers: split, shift & bail out */
- if (off < dlen)
- apr_bucket_split(e, off);
+ if (off < dlen) {
+ apr_bucket_split(e, off);
+ }
e = APR_BUCKET_NEXT(e);
@@ -443,6 +445,7 @@
++glen;
++off;
parser->v.status = HDR_GAP;
+ saw_newline = 0;
goto parse_hdr_bucket;
default:
@@ -552,6 +555,7 @@
}
struct mfd_ctx {
+ void *hook_data;
apreq_table_t *t;
apr_bucket_brigade *bb;
char bdry[1];
@@ -561,7 +565,7 @@
static apr_status_t split_on_bdry(apr_pool_t *pool,
apr_bucket_brigade *out,
apr_bucket_brigade *in,
- char *bdry, apreq_parser_t *parser)
+ char *bdry)
{
apr_bucket_t *e = APR_BRIGADE_FIRST(in);
apr_size_t blen = strlen(bdry);
@@ -626,6 +630,53 @@
return APR_INCOMPLETE;
}
+static apr_status_t getval(const char **line, const char *name,
+ const char **val, apr_size_t *vlen)
+{
+ const char *v = strstr(*line, name), *rv;
+ int in_quotes = 0;
+
+ if (v == NULL)
+ return APR_NOT_FOUND;
+
+ v += strlen(name);
+
+ while (*v) {
+ if (v == '=' || apr_isspace(val))
+ ++v;
+ else
+ break;
+ }
+
+ if (v == '"') {
+ ++v;
+ in_quotes = 1;
+ }
+
+ for(*val = v; *v; ++v) {
+ switch (*v) {
+ case ';':
+ if (in_quotes)
+ continue;
+ /* else fall through */
+ case '"':
+ break;
+ case '\\':
+ if (in_quotes && v[1] != 0)
+ ++v;
+ break;
+ default:
+ break;
+ }
+ }
+
+ *vlen = v - *val;
+ *line = (*v == 0) ? val : val + 1;
+ return APR_SUCCESS;
+}
+
+static const char crlf[] = "\r\n";
+
APREQ_DECLARE(apr_status_t) apreq_parse_multipart(apr_pool_t *pool,
apr_bucket_brigade *bb,
apreq_parser_t *parser)
@@ -636,135 +687,213 @@
#define MAX_BLEN 100
-#define MFD_HEADER 0
-#define MFD_PARAM 1
-#define MFD_UPLOAD 2
+#define MFD_INIT 0
+#define MFD_HEADER 1
+#define MFD_PARAM 2
+#define MFD_UPLOAD 3
#define MFD_ERROR -1
if (parser->v.size == 0) {
- apr_ssize_t total = 0;
- char blen = 0;
+ char off = 0;
+ char *bdry, *ct = apreq_env_content_type(req->ctx);
+ apr_size_t blen;
+ apr_status_t s;
- ctx->bdry[blen++] = '\r';
- ctx->bdry[blen++] = '\n';
+ ctx->bdry[off++] = '\r';
+ ctx->bdry[off++] = '\n';
+ ctx->bdry[off++] = '-';
+ ctx->bdry[off++] = '-';
- /* parse first line for mfd boundary */
- while (1) {
- apr_size_t dlen;
- char *data, *newline;
- apr_bucket_t *f = APR_BRIGADE_FIRST(bb);
- apr_status_t s;
+ s = getval(&ct, "boundary", &bdry, &blen);
+
+ if (s != APR_SUCCESS)
+ return s;
+
+ memcpy(ctx->bdry + off, bdry, blen);
+ ctx->bdry[off + blen] = 0;
- if (f == APR_BRIGADE_SENTINEL(bb))
- return APR_EAGAIN;
+ APR_BRIGADE_INSERT_HEAD(bb,
+ apr_bucket_immortal_create(crlf,2,bb->bucket_alloc));
- if (APR_BUCKET_IS_EOS(f))
- return APR_EOS;
+ ctx->bb ||= apr_brigade_create(pool, bb->bucket_alloc);
- s = apr_bucket_read(f, &data, &dlen, APR_BLOCK_READ);
+ parser->v.status == MFD_INIT;
+ parser->v.size = sizeof *ctx;
+ }
+
+ parse_mfd_brigade:
+ switch (parser->v.status) {
+
+ case MFD_INIT:
+ {
+ apr_status_t s;
+ s = split_on_bdry(pool, ctx->bb, bb, ctx->bdry);
if (s != APR_SUCCESS)
return s;
- newline = memchr(data, '\n', dlen);
+ parser->v.status = MFD_NEXTLINE;
+ }
+ /* fall through */
- if (newline != NULL) {
- if (newline + 1 < data + dlen)
- apr_bucket_split(f, newline + 1 - data);
- else
- dlen = newline - data;
+ case MFD_NEXTLINE:
+ {
+ apr_status_t s;
+ s = split_on_bdry(pool, ctx->bb, bb, crlf);
+ if (s != APR_SUCCESS)
+ return s;
- if (blen + dlen >= MAX_BLEN)
- return APR_BADARG;
- memcpy(ctx->bdry + blen, data, dlen);
- apr_bucket_delete(f);
- blen += dlen;
- break;
+ parser->v.status = MFD_HEADER;
+ apr_brigade_cleanup(ctx->bb);
+ ctx->t = NULL;
+ }
+ /* fall through */
+
+ case MFD_HEADER:
+ {
+ apreq_parser_t par = {0};
+ apr_status_t s;
+ char *cd, *name, *filename;
+ apr_size_t nlen, flen;
+
+ ctx->t ||= apreq_make_table(pool, APREQ_NELTS);
+ par.out = (void *)ctx->t;
+ s = apreq_parse_headers(pool, bb, &par);
+
+ if (s != APR_SUCCESS)
+ return s;
+
+ parser->v.status = MFD_VALUE;
+
+ /* parse Content-Disposition header to determine value type */
+ cd = apreq_table_get(ctx->t, "Content-Disposition");
+ if (cd == NULL) {
+ parser->v.status = MFD_ERROR;
+ return APR_BADARG;
}
- if (blen + dlen >= MAX_BLEN)
+ s = getval(&cd, "name", &name, &nlen);
+ if (s != APR_SUCCESS) {
+ parser->v.status = MFD_ERROR;
return APR_BADARG;
- memcpy(ctx->bdry + blen, data, dlen);
- apr_bucket_delete(f);
- blen += dlen;
- }
+ }
- blen -= 2; /* ignore trailing CRLF */
- ctx->bdry[blen] = 0;
- parser->v.size = blen + sizeof *ctx;
- parser->v.status = MFD_HEADER;
+ s = getval(&cd, "filename", &filename, &flen);
- }
+ if (s != APR_SUCCESS) {
+ apr_bucket__t *e;
+ name = apr_pstrmemdup(pool, name, nlen);
+ e = apr_bucket_transient_create(name, nlen,
+ ctx->bb->bucket_alloc);
+ APR_BRIGADE_INSERT_HEAD(ctx->bb,e);
+ parser->v.status = MFD_PARAM;
+ }
+ else {
+ apreq_param_t *param = apreq_make_param(pool, name, nlen,
+ filename, flen);
+ param->info = ctx->t;
+ param->bb = apr_brigade_create(pool,
+
apr_bucket_alloc_create(pool));
- switch (parser->v.status) {
+ apreq_table_add(req->body, param);
+ parser->v.status = MFD_UPLOAD;
+ }
+ }
+ goto mfd_parse_brigade;
- case MFD_HEADER:
- {
- apreq_parser_t par = {0};
- apr_status_t s;
- char *cd;
+ case MFD_PARAM:
+ {
+ apr_status_t s = split_on_bdry(pool, ctx->bb, bb, ctx->bdry);
+ apr_bucket_t *e;
+ apreq_param_t *param;
+ apreq_value_t *v;
+ char *name;
+ apr_size_t len;
- if (ctx->t == NULL)
- ctx->t = apreq_make_table(pool, APREQ_NELTS);
+ switch (s) {
- par.out = (void *)ctx->t;
-
- s = apreq_parse_headers(pool, bb, &par);
+ case APR_INCOMPLETE:
+ return s;
- if (s != APR_SUCCESS)
- return s;
+ case APR_SUCCESS:
+ e = APR_BRIGADE_FIRST(ctx->bb);
+ apr_bucket_read(e, &name, &len, APR_READ_BLOCK);
+ apr_bucket_delete(e);
+
+ s = apr_brigade_length(ctx->bb, 1, &len);
+ if (s != APR_SUCCESS) {
+ parser->v.status = MFD_ERROR;
+ return s;
+ }
- parser->v.status = MFD_VALUE;
- ctx->bb = apr_brigade_create(pool, apr_bucket_alloc_create(pool));
+ param = apr_palloc(pool, len + sizeof *param);
+ param->charset = APREQ_CHARSET;
+ param->language = NULL;
+ param->bb = NULL;
+ param->info = ctx->t;
+
+ v = ¶m->v;
+ v->name = name;
+ v->status = APR_SUCCESS;
+ apr_brigade_flatten(ctx->bb, v->data, len);
+ v->size = len;
+ v->data[v->size] = 0;
- /* parse Content-Disposition header to determine value type */
- cd = apreq_table_get(ctx->t, "Content-Disposition");
+ parser->v.status == MFD_NEXTLINE;
+ goto parse_mfd_brigade;
+ default:
+ parser->v.status == MFD_ERROR;
+ return s;
+ }
- /* fall thru */
- }
+ }
+ break;
- case MFD_PARAM:
case MFD_UPLOAD:
- {
- apr_status_t s = split_on_bdry(pool, ctx->bb, bb,
- ctx->bdry, parser);
- if (s != APR_SUCCESS)
- return s;
-
- if (parser->v.status == MFD_PARAM) {
- apr_size_t len;
+ {
+ apr_status_t s = split_on_bdry(pool, ctx->bb, bb, ctx->bdry);
apreq_param_t *param;
apreq_value_t *v;
- apr_status_t s;
+ int dummy;
- s = apr_brigade_length(ctx->bb, 1, &len);
+ switch (s) {
- if (s != APR_SUCCESS) {
- parser->v.status = MFD_ERROR;
- return s;
- }
+ case APR_INCOMPLETE:
+ apreq_table_last(req->body, &v, &off);
+ param = apreq_value_to_param(v);
+ if (parser->hook)
+ return parser->hook(pool, param->bb, ctx->bb, parser);
+ else {
+ APR_BRIGADE_CONCAT(param->bb, ctx->bb);
+ return s;
+ }
- param = apr_palloc(pool, len + sizeof *param);
- v = ¶m->v;
- param->charset = UTF_8;
- param->language = NULL;
- param->info = ctx->t;
- param->bb = ctx->bb;
- v->size = len;
- v->status = apr_brigade_flatten(ctx->bb, v->data, &v->size);
+ case APR_SUCCESS:
+ apreq_table_last(req->body, &v, &dummy);
+ param = apreq_value_to_param(v);
+
+ /* XXX: push an eos bucket onto ctx->bb */
+
+ if (parser->hook) {
+ do s = parser->hook(pool, param->bb, ctx->bb, parser);
+ while s == APR_INCOMPLETE;
+ }
+ else
+ APR_BRIGADE_CONCAT(param->bb, ctx->bb);
- apreq_table_add(req->body, v);
- }
+ parser->v.status == MFD_NEXTLINE;
+ goto parse_mfd_brigade;
+ default:
+ parser->v.status == MFD_ERROR;
+ return s;
+ }
- parser->v.status = MFD_VALUE;
- ctx->t = NULL;
- ctx->bb = NULL;
- }
- break;
+ }
+ break;
case MFD_ERROR:
return APR_EGENERAL;
1.2 +7 -6 httpd-apreq-2/src/apreq_parsers.h
Index: apreq_parsers.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_parsers.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- apreq_parsers.h 9 Apr 2003 03:25:09 -0000 1.1
+++ apreq_parsers.h 11 Apr 2003 02:48:01 -0000 1.2
@@ -15,24 +15,25 @@
typedef struct apreq_parser_t apreq_parser_t;
-#define APREQ_PARSER(f) apr_status_t (f)(apr_pool_t *p, apr_bucket_brigade
*bb,
- apreq_parser_t *parser)
+#define APREQ_PARSER(f) apr_status_t(f)(apr_pool_t *p, apr_bucket_brigade
*bb,\
+ apreq_parser_t *parser)
+#define APREQ_HOOK(f) apr_status_t(f)(apr_pool_t *p, apr_bucket_brigade
*out, \
+ apr_bucket_brigade *in, \
+ apreq_parser_t *parser)
#define APREQ_CTX_MAXSIZE 128
struct apreq_parser_t {
APREQ_PARSER (*parser);
+ APREQ_HOOK (*hook);
void *out;
- apreq_parser_t *ext;
apreq_value_t v; /* maintains (internal) parser state */
};
-#define apreq_value_to_parser(ptr) apreq_attr_to_type(apreq_parser_t, \
- v, ptr)
+#define apreq_value_to_parser(ptr) apreq_attr_to_type(apreq_parser_t,v,ptr)
#define apreq_ctx_to_parser(ptr) apreq_value_to_parser(apreq_strtoval(ptr))
-#define apreq_parser_hook(p) ((p)->next)
#define apreq_parser_enctype(p) ((p)->v.name)
#define apreq_parser_data(p) ((p)->v.data)
1.9 +5 -4 httpd-apreq-2/src/apreq_tables.c
Index: apreq_tables.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_tables.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- apreq_tables.c 26 Jan 2003 02:39:08 -0000 1.8
+++ apreq_tables.c 11 Apr 2003 02:48:01 -0000 1.9
@@ -601,10 +601,11 @@
t->flags = f;
- for ( ; e < end; e++) {
- apreq_value_t *v = e->val ?
- apreq_make_value(p,e->key,e->val,strlen(e->val)) :
- NULL;
+ for ( ; e < end; ++e) {
+ apreq_value_t *v = apreq_make_value(p, e->key, strlen(e->key),
+ e->val, e->val ?
+ strlen(e->val) :
+ 0);
apreq_table_add(t, v);
}
return t;