joes 2004/09/13 00:04:02
Modified: . CHANGES STATUS
src apreq_env.c apreq_params.h apreq_parsers.c
apreq_version.h
t parsers.c
Log:
Add apreq_register_parser(), which allows users to add their own parsers to
apreq_parser()'s recognized MIME types. Also add some memory-management todos
in STATUS
Revision Changes Path
1.68 +4 -0 httpd-apreq-2/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -r1.67 -r1.68
--- CHANGES 12 Sep 2004 06:16:43 -0000 1.67
+++ CHANGES 13 Sep 2004 07:04:02 -0000 1.68
@@ -6,6 +6,10 @@
- C API [joes]
+ Add apreq_register_parser(), which allows users to add
+ their own parsers to apreq_parser()'s recognized MIME types.
+
+- C API [joes]
Support "multipart/mixed" file uploads.
Support XForms' "multipart/related" enctype.
1.85 +12 -1 httpd-apreq-2/STATUS
Index: STATUS
===================================================================
RCS file: /home/cvs/httpd-apreq-2/STATUS,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -r1.84 -r1.85
--- STATUS 12 Sep 2004 03:04:12 -0000 1.84
+++ STATUS 13 Sep 2004 07:04:02 -0000 1.85
@@ -40,6 +40,17 @@
TODO:
+ - Move the xs generation code into buildconf (instead of configure),
+ and fix glue/perl/Makefile.PL to clean the ./xs dir instead of
+ removing it entirely. % make release will also need fixing
+ to pick up the xs directory.
+
+ - There are too many calls to apreq_env_pool()- lots of these
+ can be eliminated by caching the pool in the parser's context.
+
+ - Add apreq_env_bucket_alloc(env) function to get a per-request
+ bucket allocator, which will help the parsers to conserve memory.
+
- in glue/perl/t/apreq/cgi.t on Win32, printing to the error log
hangs if the strings involved are about 10000 in size.
This doesn't occur in the env/cgi tests - why?
1.19 +5 -2 httpd-apreq-2/src/apreq_env.c
Index: apreq_env.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_env.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- apreq_env.c 31 Jul 2004 23:56:40 -0000 1.18
+++ apreq_env.c 13 Sep 2004 07:04:02 -0000 1.19
@@ -23,9 +23,12 @@
static const apreq_env_t *apreq_env;
+extern void apreq_parser_initialize(void);
+
APREQ_DECLARE(const apreq_env_t *) apreq_env_module(const apreq_env_t *mod)
{
+ apreq_parser_initialize();
if (mod != NULL) {
const apreq_env_t *old_mod = apreq_env;
apreq_env = mod;
@@ -142,7 +145,7 @@
#define APREQ_MODULE_NAME "CGI"
-#define APREQ_MODULE_MAGIC_NUMBER 20040731
+#define APREQ_MODULE_MAGIC_NUMBER 20040913
static apr_pool_t *cgi_pool(void *env)
{
@@ -210,7 +213,7 @@
static apreq_request_t *cgi_request(void *env,
apreq_request_t *req)
{
-
+ apreq_parser_initialize();
if (req != NULL) {
apreq_request_t *old_req = ctx.req;
ctx.req = req;
1.41 +23 -3 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.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- apreq_params.h 12 Sep 2004 19:21:32 -0000 1.40
+++ apreq_params.h 13 Sep 2004 07:04:02 -0000 1.41
@@ -273,6 +273,8 @@
};
+
+
/**
* Parse the incoming brigade into a table. Parsers normally
* consume all the buckets of the brigade during parsing. However
@@ -389,22 +391,40 @@
APREQ_DECLARE(void) apreq_add_hook(apreq_parser_t *p,
apreq_hook_t *h);
+
/**
* Create the default parser associated with the
* current request's Content-Type (if possible).
* @param env The current environment.
* @param hook Hook(s) to add to the parser.
* @return New parser, NULL if the Content-Type is
- * unrecognized. apreq_parser() currently recognizes
- * APREQ_URL_ENCTYPE and APREQ_MFD_ENCTYPE.
+ * unrecognized.
*
* @param env The current environment.
* @param hook Additional hooks to supply the parser with.
- * @return The built-in parser; NULL if the environment's
+ * @return The parser; NULL if the environment's
* Content-Type is unrecognized.
*/
APREQ_DECLARE(apreq_parser_t *)apreq_parser(void *env,
apreq_hook_t *hook);
+
+
+/**
+ * Register a new parsing function with a MIME enctype.
+ * Registered parsers are added to apreq_parser()'s
+ * internal lookup table.
+ *
+ * @param enctype The MIME type.
+ * @param parser The function to use during parsing. Setting
+ * parser == NULL will remove an existing parser.
+ * @remark This is not a thread-safe operation, so applications
+ * should only call this during process startup,
+ * or within a request-thread mutex.
+ */
+
+APREQ_DECLARE(void) apreq_register_parser(const char *enctype,
+ apr_status_t (*parser) (APREQ_PARSER_ARGS));
+
/**
* Returns APR_EGENERAL. Effectively disables mfd parser
1.66 +47 -11 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.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- apreq_parsers.c 12 Sep 2004 19:21:32 -0000 1.65
+++ apreq_parsers.c 13 Sep 2004 07:04:02 -0000 1.66
@@ -20,6 +20,9 @@
#include "apr_strings.h"
#include "apr_strmatch.h"
#include "apr_xml.h"
+#include "apr_hash.h"
+
+void apreq_parser_initialize(void);
#ifndef MAX
#define MAX(A,B) ( (A) > (B) ? (A) : (B) )
@@ -83,27 +86,60 @@
p->hook = h;
}
+static apr_hash_t *default_parsers;
+static apr_pool_t *default_parser_pool;
+
+void apreq_parser_initialize(void)
+{
+ if (default_parsers != NULL)
+ return;
+ apr_pool_create(&default_parser_pool, NULL);
+ default_parsers = apr_hash_make(default_parser_pool);
+
+ apreq_register_parser("application/x-www-form-urlencoded",
+ apreq_parse_urlencoded);
+ apreq_register_parser("multipart/form-data", apreq_parse_multipart);
+ apreq_register_parser("multipart/related", apreq_parse_multipart);
+}
+
+struct apreq_parser_fcn {
+ apr_status_t (*parser) (APREQ_PARSER_ARGS);
+};
+
+APREQ_DECLARE(void) apreq_register_parser(const char *enctype,
+ apr_status_t (*parser)
(APREQ_PARSER_ARGS))
+{
+ struct apreq_parser_fcn *f = NULL;
+ apreq_parser_initialize();
+ if (parser != NULL) {
+ f = apr_palloc(default_parser_pool, sizeof *f);
+ f->parser = parser;
+ }
+ apr_hash_set(default_parsers, apr_pstrdup(default_parser_pool, enctype),
+ APR_HASH_KEY_STRING, f);
+
+}
+
APREQ_DECLARE(apreq_parser_t *)apreq_parser(void *env, apreq_hook_t *hook)
{
apr_pool_t *pool = apreq_env_pool(env);
const char *type = apreq_env_content_type(env);
+ apr_ssize_t tlen;
+ struct apreq_parser_fcn *f;
- if (type == NULL)
+ if (type == NULL || default_parsers == NULL)
return NULL;
- if (!strncasecmp(type, APREQ_URL_ENCTYPE,strlen(APREQ_URL_ENCTYPE)))
- return apreq_make_parser(pool, type,
- apreq_parse_urlencoded, hook, NULL);
-
- else if (!strncasecmp(type,APREQ_MFD_ENCTYPE,strlen(APREQ_MFD_ENCTYPE))
- || strncasecmp(type, "multipart/related",
- strlen("multipart/related")))
- return apreq_make_parser(pool, type,
- apreq_parse_multipart, hook, NULL);
+ tlen = 0;
+ while(type[tlen] && type[tlen] != ';')
+ ++tlen;
+
+ f = apr_hash_get(default_parsers, type, tlen);
+ if (f != NULL)
+ return apreq_make_parser(pool, type, f->parser, hook, NULL);
else
return NULL;
-
}
1.26 +1 -1 httpd-apreq-2/src/apreq_version.h
Index: apreq_version.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_version.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- apreq_version.h 12 Sep 2004 06:16:43 -0000 1.25
+++ apreq_version.h 13 Sep 2004 07:04:02 -0000 1.26
@@ -61,7 +61,7 @@
#define APREQ_MINOR_VERSION 0
/** patch level */
-#define APREQ_PATCH_VERSION 21
+#define APREQ_PATCH_VERSION 22
/**
* This symbol is defined for internal, "development" copies of libapreq.
1.25 +31 -0 httpd-apreq-2/t/parsers.c
Index: parsers.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/t/parsers.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- parsers.c 12 Sep 2004 19:21:33 -0000 1.24
+++ parsers.c 13 Sep 2004 07:04:02 -0000 1.25
@@ -102,6 +102,36 @@
extern apr_bucket_brigade *bb;
extern apr_table_t *table;
+static void locate_default_parsers(CuTest *tc)
+{
+ apreq_request_t *req;
+ apreq_parser_t *parser;
+
+ req = apreq_request("application/x-www-form-urlencoded", "");
+ CuAssertPtrNotNull(tc, req);
+ CuAssertStrEquals(tc, APREQ_URL_ENCTYPE, apreq_enctype(req->env));
+ parser = apreq_parser(req->env, NULL);
+ CuAssertPtrNotNull(tc, parser);
+ CuAssertStrEquals(tc, APREQ_URL_ENCTYPE, parser->enctype);
+
+ req = apreq_request(APREQ_MFD_ENCTYPE
+ "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"" ,"");
+ CuAssertPtrNotNull(tc, req);
+ parser = apreq_parser(req->env, NULL);
+ CuAssertPtrNotNull(tc, parser);
+ CuAssertStrNEquals(tc, APREQ_MFD_ENCTYPE, parser->enctype,
+ strlen(APREQ_MFD_ENCTYPE));
+
+ req = apreq_request("multipart/related; boundary=f93dcbA3; "
+ "type=application/xml; start=\"<[EMAIL PROTECTED]>\"","");
+ CuAssertPtrNotNull(tc, req);
+ parser = apreq_parser(req->env, NULL);
+ CuAssertPtrNotNull(tc, parser);
+ CuAssertStrNEquals(tc, "multipart/related", parser->enctype,
+ strlen("multipart/related"));
+}
+
+
static void parse_urlencoded(CuTest *tc)
{
const char *val;
@@ -440,6 +470,7 @@
CuSuite *testparser(void)
{
CuSuite *suite = CuSuiteNew("Parsers");
+ SUITE_ADD_TEST(suite, locate_default_parsers);
SUITE_ADD_TEST(suite, parse_urlencoded);
SUITE_ADD_TEST(suite, parse_multipart);
SUITE_ADD_TEST(suite, parse_disable_uploads);