httpd-apreq-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject cvs commit: httpd-apreq-2/t parsers.c
Date Fri, 10 Sep 2004 23:54:08 GMT
joes        2004/09/10 16:54:08

  Modified:    .        CHANGES STATUS
               src      apreq_params.h apreq_parsers.c
               t        parsers.c
  Log:
  Add multipart/related support to mfd parser, completing basic XForms support.  Reimplement
the apr_xml parser as a hook + a generic parser.
  
  Revision  Changes    Path
  1.66      +6 -2      httpd-apreq-2/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
  retrieving revision 1.65
  retrieving revision 1.66
  diff -u -r1.65 -r1.66
  --- CHANGES	6 Sep 2004 21:21:06 -0000	1.65
  +++ CHANGES	10 Sep 2004 23:54:08 -0000	1.66
  @@ -6,9 +6,13 @@
   
   
   - C API [joes]
  -  Add apreq_parse_xml parser, which is a simple wrapper
  -  around APR's expat-based apr_xml_parser.
  +  Support XForms' "multipart/related" enctype.
   
  +- C API [joes]
  +  Add apreq_hook_apr_xml_parser(), which is a simple wrapper
  +  hook around APR's expat-based apr_xml_parser.  Add a generic
  +  parser apreq_parse_generic() to parse arbitrary enctypes using
  +  the hook API.
   
   @section v2_04_dev Changes with libapreq2-2.04-dev (released August 30, 2004)
   
  
  
  
  1.83      +1 -3      httpd-apreq-2/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/STATUS,v
  retrieving revision 1.82
  retrieving revision 1.83
  diff -u -r1.82 -r1.83
  --- STATUS	30 Aug 2004 16:25:56 -0000	1.82
  +++ STATUS	10 Sep 2004 23:54:08 -0000	1.83
  @@ -62,8 +62,6 @@
   
       - Write parser/hook API documentation, and add perl glue for the API.
   
  -    - Add XForms logic to the mfd parser.
  -
       - symbol exports files:
         -# aix needs .exp files
   
  
  
  
  1.39      +17 -11    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.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- apreq_params.h	6 Sep 2004 21:21:06 -0000	1.38
  +++ apreq_params.h	10 Sep 2004 23:54:08 -0000	1.39
  @@ -320,25 +320,31 @@
   APREQ_DECLARE_PARSER(apreq_parse_urlencoded);
   
   /**
  - * Rfc2388 multipart/form-data parser. It will reject
  - * any buckets representing preamble and postamble text
  - * (this is normal behavior, not an error condition).
  + * Rfc2388 multipart/form-data (and XForms 1.0 multipart/related)
  + * parser. It will reject any buckets representing preamble and 
  + * postamble text (this is normal behavior, not an error condition).
    * See #APREQ_RUN_PARSER for more info on rejected data.
    */
   APREQ_DECLARE_PARSER(apreq_parse_multipart);
   
  -
  +/**
  + * Generic parser.  No table entries will be added to
  + * the req->body table by this parser.  The parser creates
  + * a dummy apreq_param_t to pass to any configured hooks.  If
  + * no hooks are configured, the dummy param's bb slot will
  + * contain a copy of the request body.  It can be retrieved
  + * by casting the parser's ctx pointer to (apreq_param_t **).
  + */
  +APREQ_DECLARE_PARSER(apreq_parse_generic);
   
   /**
  - * application/xml expat-based parser. It will reject
  - * metabuckets, and it will parse until EOS appears.
  + * apr_xml_parser hook. It will parse until EOS appears.
    * The parsed document isn't available until parsing has
  - * completed successfully.  The parser's ctx pointer may 
  - * be cast as (const apr_xml_doc **) to retrieve the 
  - * parsed document.  No table entries will be added to 
  - * req->body by this parser.
  + * completed successfully.  The hook's ctx pointer may 
  + * be cast as (apr_xml_doc **) to retrieve the 
  + * parsed document.
    */
  -APREQ_DECLARE_PARSER(apreq_parse_xml);
  +APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser);
   
   /**
    * Construct a parser.
  
  
  
  1.63      +95 -28    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.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- apreq_parsers.c	6 Sep 2004 21:21:06 -0000	1.62
  +++ apreq_parsers.c	10 Sep 2004 23:54:08 -0000	1.63
  @@ -95,7 +95,9 @@
           return apreq_make_parser(pool, type, 
                                    apreq_parse_urlencoded, hook, NULL);
   
  -    else if (!strncasecmp(type,APREQ_MFD_ENCTYPE,strlen(APREQ_MFD_ENCTYPE)))
  +    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);
   
  @@ -847,6 +849,7 @@
           ctx->bb = apr_brigade_create(pool, bucket_alloc);
           ctx->in = apr_brigade_create(pool, bucket_alloc);
           ctx->eos = apr_bucket_eos_create(bucket_alloc);
  +
       }
       else if (ctx->status == MFD_COMPLETE) {
           apreq_log(APREQ_DEBUG APR_SUCCESS, env, 
  @@ -961,19 +964,28 @@
   
               cd = apr_table_get(ctx->info, "Content-Disposition");
   
  -            if (cd == NULL) {
  -                ctx->status = MFD_ERROR;
  -                return APR_EGENERAL;
  -            }
  +            if (cd != NULL) {
  +                s = apreq_header_attribute(cd, "name", 4, &name, &nlen);
   
  -            s = apreq_header_attribute(cd, "name", 4, &name, &nlen);
  +                if (s != APR_SUCCESS) {
  +                    ctx->status = MFD_ERROR;
  +                    return APR_EGENERAL;
  +                }
   
  -            if (s != APR_SUCCESS) {
  -                ctx->status = MFD_ERROR;
  -                return APR_EGENERAL;
  +                s = apreq_header_attribute(cd, "filename", 8, &filename, &flen);
  +            }
  +            else {
  +                cd = apr_table_get(ctx->info, "Content-ID");
  +                if (cd == NULL) {
  +                    ctx->status = MFD_ERROR;
  +                    return APR_EGENERAL;
  +                }
  +                name = cd;
  +                nlen = strlen(name);
  +                filename = "";
  +                flen = 0;
  +                s = APR_SUCCESS;
               }
  -
  -            s = apreq_header_attribute(cd, "filename", 8, &filename, &flen);
   
               if (s != APR_SUCCESS) {
                   name = apr_pstrmemdup(pool, name, nlen);
  @@ -1110,7 +1122,71 @@
   }
   
   
  -/* XML parser */
  +/* generic parser */
  +
  +struct gen_ctx {
  +    apreq_param_t               *param;
  +    enum {
  +        GEN_INCOMPLETE,
  +        GEN_COMPLETE,
  +        GEN_ERROR
  +    }                            status;
  +};
  +
  +
  +APREQ_DECLARE_PARSER(apreq_parse_generic)
  +{
  +    struct gen_ctx *ctx = parser->ctx;
  +    apr_pool_t *pool = apreq_env_pool(env);
  +    apr_status_t s = APR_SUCCESS;
  +    apr_bucket *e = APR_BRIGADE_LAST(bb);
  +    unsigned saw_eos = 0;
  +
  +    if (ctx == NULL) {
  +        parser->ctx = ctx = apr_palloc(pool, sizeof *ctx);
  +        ctx->status = GEN_INCOMPLETE;
  +        ctx->param = apreq_make_param(pool, 
  +                                      "_dummy_", strlen("_dummy_"), "", 0);
  +        ctx->param->bb = apr_brigade_create(pool, 
  +                                            apr_bucket_alloc_create(pool));
  +        ctx->param->info = apr_table_make(pool, APREQ_NELTS);
  +    }
  +
  +
  +    PARSER_STATUS_CHECK(GEN);
  +
  +    while (e != APR_BRIGADE_SENTINEL(bb)) {
  +        if (APR_BUCKET_IS_EOS(e)) {
  +            saw_eos = 1;
  +            break;
  +        }
  +        e = APR_BUCKET_PREV(e);
  +    }
  +
  +    if (parser->hook) {
  +        s = APREQ_RUN_HOOK(parser->hook, env, ctx->param, bb);
  +        if (s != APR_SUCCESS) {
  +            ctx->status = GEN_ERROR;
  +            return s;
  +        }
  +    }
  +
  +    APREQ_BRIGADE_SETASIDE(bb, pool);
  +    s = apreq_brigade_concat(bb, ctx->param->bb, bb);
  +
  +    if (s != APR_SUCCESS) {
  +        ctx->status = GEN_ERROR;
  +        return s;
  +    }
  +
  +    if (saw_eos) {
  +        ctx->status = GEN_COMPLETE;
  +        return APR_SUCCESS;
  +    }
  +    else
  +        return APR_INCOMPLETE;
  +}
  +
   
   struct xml_ctx {
       apr_xml_doc                 *doc;
  @@ -1123,24 +1199,24 @@
   };
   
   
  -APREQ_DECLARE_PARSER(apreq_parse_xml)
  +APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser)
   {
       apr_pool_t *pool = apreq_env_pool(env);
  -    struct xml_ctx *ctx = parser->ctx;
  +    struct xml_ctx *ctx = hook->ctx;
       apr_status_t s = APR_SUCCESS;
  -    apr_bucket *e = APR_BRIGADE_FIRST(bb);
  +    apr_bucket *e;
   
       if (ctx == NULL) {
  -        parser->ctx = ctx = apr_palloc(pool, sizeof *ctx);
  +        hook->ctx = ctx = apr_palloc(pool, sizeof *ctx);
           ctx->doc = NULL;
           ctx->xml_parser = apr_xml_parser_create(pool);
           ctx->status = XML_INCOMPLETE;
       }
  -    
   
       PARSER_STATUS_CHECK(XML);
   
  -    while (e != APR_BRIGADE_SENTINEL(bb))
  +    for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb);
  +         e = APR_BUCKET_NEXT(e))
       {
           const char *data;
           apr_size_t dlen;
  @@ -1149,7 +1225,6 @@
               s = apr_xml_parser_done(ctx->xml_parser, &ctx->doc);
               if (s == APR_SUCCESS) {
                   ctx->status = XML_COMPLETE;
  -                apr_bucket_delete(e);
               }
               else {
                   ctx->status = XML_ERROR;
  @@ -1159,7 +1234,6 @@
              return s;
           }
           else if (APR_BUCKET_IS_METADATA(e)) {
  -            e = APR_BUCKET_NEXT(e);
               continue;
           }
   
  @@ -1174,13 +1248,7 @@
   
           s = apr_xml_parser_feed(ctx->xml_parser, data, dlen);
   
  -        if (s == APR_SUCCESS) {
  -            apr_bucket *f = e;
  -            e = APR_BUCKET_NEXT(e);
  -            apr_bucket_delete(f);
  -            continue;
  -        }
  -        else {
  +        if (s != APR_SUCCESS) {
               ctx->status = XML_ERROR;
               apreq_log(APREQ_ERROR s, env, "apreq_parse_xml: "
                         "apr_xml_parser_feed failed");
  @@ -1190,5 +1258,4 @@
       }
   
       return APR_INCOMPLETE;
  -
   }
  
  
  
  1.22      +105 -11   httpd-apreq-2/t/parsers.c
  
  Index: parsers.c
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/t/parsers.c,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- parsers.c	6 Sep 2004 21:21:06 -0000	1.21
  +++ parsers.c	10 Sep 2004 23:54:08 -0000	1.22
  @@ -38,7 +38,7 @@
   "--AaB03x--" CRLF;
   
   static char xml_data[] =
  -"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" /* length == 42 */
  +"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
   "<methodCall>"
   "  <methodName>foo.bar</methodName>"
   "  <params>"
  @@ -46,6 +46,35 @@
   "  </params>"
   "</methodCall>";
   
  +static char rel_data[] = /*offsets: 122, 522, */
  +"--f93dcbA3" CRLF
  +"Content-Type: application/xml; charset=UTF-8" CRLF
  +"Content-Length: 400" CRLF
  +"Content-ID: <980119.X53GGT@example.com>" CRLF CRLF /*122*/
  +"<?xml version=\"1.0\"?>" CRLF
  +"<uploadDocument>"
  +"  <title>My Proposal</title>"
  +"  <author>E. X. Ample</author>"
  +"  <summary>A proposal for a new project.</summary>"
  +"  <notes image=\"cid:980119.X17AXM@example.com\">(see handwritten region)</notes>"
  +"  <keywords>project proposal funding</keywords>"
  +"  <readonly>false</readonly>"
  +"  <filename>image.png</filename>"
  +"  <content>cid:980119.X25MNC@example.com</content>"
  +"</uploadDocument>" /*400*/ CRLF
  +"--f93dcbA3" CRLF /*14*/
  +"Content-Type: image/png" CRLF
  +"Content-Transfer-Encoding: binary" CRLF
  +"Content-ID: <980119.X25MNC@example.com>" CRLF CRLF /*103*/
  +"...Binary data here..."  /*22*/ CRLF
  +"--f93dcbA3" CRLF /*14*/
  +"Content-Type: image/png" CRLF
  +"Content-Transfer-Encoding: binary" CRLF
  +"Content-ID: <980119.X17AXM@example.com>" CRLF CRLF
  +"...Binary data here..." CRLF
  +"--f93dcbA3--" CRLF;
  +
  +
   
   extern apr_bucket_brigade *bb;
   extern apr_table_t *table;
  @@ -201,13 +230,12 @@
       CuAssertPtrEquals(tc, NULL, val);
   }
   
  -static void parse_xml(CuTest *tc)
  +static void parse_generic(CuTest *tc)
   {
       const char *val;
       apr_size_t vlen;
       apr_status_t rv;
  -    int ns_map = 0;
  -    apr_xml_doc *doc;
  +    apreq_param_t *dummy;
       apreq_request_t *req = apreq_request(APREQ_XML_ENCTYPE, "");
       apr_bucket_brigade *bb = apr_brigade_create(p, 
                                      apr_bucket_alloc_create(p));
  @@ -221,25 +249,91 @@
   
       req->body = NULL;
       req->parser = apreq_make_parser(p, APREQ_XML_ENCTYPE, 
  -                                    apreq_parse_xml, NULL, NULL);
  +                                    apreq_parse_generic, NULL, NULL);
  +    rv = apreq_parse_request(req,bb);
  +    CuAssertIntEquals(tc, APR_SUCCESS, rv);
  +    dummy = *(apreq_param_t **)req->parser->ctx;
  +    CuAssertPtrNotNull(tc, dummy);
  +    apr_brigade_pflatten(dummy->bb, (char **)&val, &vlen, p);
  +
  +    CuAssertIntEquals(tc, strlen(xml_data), vlen);
  +    CuAssertStrNEquals(tc, xml_data, val, vlen);
  +}
  +
  +
  +static void parse_related(CuTest *tc)
  +{
  +    char ct[] = "multipart/related; boundary=f93dcbA3; "
  +        "type=application/xml; start=\"<980119.X53GGT@example.com>\"";
  +    char data[] = "...Binary data here...";
  +    int dlen = strlen(data);
  +    const char *val;
  +    apr_size_t vlen;
  +    apr_status_t rv;
  +    int ns_map = 0;
  +    apr_xml_doc *doc;
  +    apreq_hook_t *xml_hook;
  +    apreq_param_t *param;
  +    apreq_request_t *req = apreq_request(ct, "");
  +    apr_bucket_brigade *bb = apr_brigade_create(p, 
  +                                   apr_bucket_alloc_create(p));
  +    apr_bucket *e = apr_bucket_immortal_create(rel_data,
  +                                                   strlen(rel_data),
  +                                                   bb->bucket_alloc);
  +
  +    CuAssertPtrNotNull(tc, req);
  +    APR_BRIGADE_INSERT_HEAD(bb, e);
  +    APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc));
  +    xml_hook = apreq_make_hook(p, apreq_hook_apr_xml_parser, NULL, NULL);
  +
  +    req->body = NULL;
  +    req->parser = apreq_make_parser(p, ct, 
  +                                    apreq_parse_multipart, xml_hook, NULL);
       rv = apreq_parse_request(req,bb);
       CuAssertIntEquals(tc, APR_SUCCESS, rv);
  -    doc = *(apr_xml_doc **)req->parser->ctx;
  -    CuAssertPtrNotNull(tc, doc);
  -    apr_xml_to_text(p, doc->root, APR_XML_X2T_FULL, 
  +    CuAssertPtrNotNull(tc, req->body);
  +
  +    param = apreq_param(req, "<980119.X53GGT@example.com>");
  +    CuAssertPtrNotNull(tc, param);
  +    CuAssertPtrNotNull(tc, param->info);
  +    val = apr_table_get(param->info, "Content-Length");
  +    CuAssertStrEquals(tc, "400", val);
  +    CuAssertPtrNotNull(tc, param->bb);
  +    apr_brigade_pflatten(param->bb, (char **)&val, &vlen, p);
  +    CuAssertIntEquals(tc, 400, vlen);
  +    CuAssertStrNEquals(tc,rel_data + 122, val, 400);
  +
  +    doc = *(apr_xml_doc **)xml_hook->ctx;
  +    apr_xml_to_text(p, doc->root, APR_XML_X2T_FULL,
                       doc->namespaces, &ns_map, &val, &vlen);
  -    CuAssertIntEquals(tc, strlen(xml_data), vlen + 42);
  -    CuAssertStrEquals(tc, xml_data + 43, val);
  +    CuAssertIntEquals(tc, 400 - 22, vlen);
  +    CuAssertStrNEquals(tc, rel_data + 122 + 23, val, 400 - 23);
   
  +    param = apreq_param(req, "<980119.X25MNC@example.com>");
  +    CuAssertPtrNotNull(tc, param);
  +    CuAssertPtrNotNull(tc, param->bb);
  +    apr_brigade_pflatten(param->bb, (char **)&val, &vlen, p);
  +    CuAssertIntEquals(tc, dlen, vlen);
  +    CuAssertStrNEquals(tc, data, val, vlen);
  +
  +    param = apreq_param(req, "<980119.X17AXM@example.com>");
  +    CuAssertPtrNotNull(tc, param);
  +    CuAssertPtrNotNull(tc, param->bb);
  +    apr_brigade_pflatten(param->bb, (char **)&val, &vlen, p);
  +    CuAssertIntEquals(tc, dlen, vlen);
  +    CuAssertStrNEquals(tc, data, val, vlen);
   }
   
  +
  +
   CuSuite *testparser(void)
   {
       CuSuite *suite = CuSuiteNew("Parsers");
       SUITE_ADD_TEST(suite, parse_urlencoded);
       SUITE_ADD_TEST(suite, parse_multipart);
       SUITE_ADD_TEST(suite, parse_disable_uploads);
  -    SUITE_ADD_TEST(suite, parse_xml);
  +    SUITE_ADD_TEST(suite, parse_generic);
  +    SUITE_ADD_TEST(suite, parse_related);
       return suite;
   }
   
  
  
  

Mime
View raw message