joes        2004/07/07 16:53:01

  Modified:    .        CHANGES STATUS
               glue/perl/t/apreq request.t
               glue/perl/t/response/TestApReq request.pm
               glue/perl/xsbuilder/Apache/Request Apache__Request.h
               src      apreq_env.c apreq_params.h apreq_parsers.c
  Log:
  Implement HOOK_DATA and UPLOAD_HOOK
  
  Revision  Changes    Path
  1.54      +3 -0      httpd-apreq-2/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- CHANGES   6 Jul 2004 18:26:48 -0000       1.53
  +++ CHANGES   7 Jul 2004 23:53:01 -0000       1.54
  @@ -6,6 +6,9 @@
   
   
   - Perl API [joes]
  +  Implement HOOK_DATA and UPLOAD_HOOK.
  +
  +- Perl API [joes]
     Add safe XS wrappers for $table->add, $table->set, $table->STORE,
     and $table_class->new.
   
  
  
  
  1.63      +1 -3      httpd-apreq-2/STATUS
  
  Index: STATUS
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/STATUS,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- STATUS    7 Jul 2004 13:31:59 -0000       1.62
  +++ STATUS    7 Jul 2004 23:53:01 -0000       1.63
  @@ -81,8 +81,6 @@
       - Install the html dox during "make install".  Should we do this 
         for the doxy manpages also?
   
  -    - Implement HOOK_DATA and UPLOAD_HOOK.
  -
       - Rework glue/perl build system to use apreq2-config instead of
         relying on paths like "../../src".
   
  
  
  
  1.16      +6 -1      httpd-apreq-2/glue/perl/t/apreq/request.t
  
  Index: request.t
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/glue/perl/t/apreq/request.t,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- request.t 5 Jul 2004 14:18:26 -0000       1.15
  +++ request.t 7 Jul 2004 23:53:01 -0000       1.16
  @@ -6,7 +6,7 @@
   use Apache::TestUtil;
   use Apache::TestRequest qw(GET_BODY UPLOAD_BODY);
   
  -plan tests => 17, have_lwp;
  +plan tests => 18, have_lwp;
   
   my $location = "/TestApReq__request";
   #print GET_BODY $location;
  @@ -37,6 +37,11 @@
       my $value = 'DataUpload' x 100;
       my $result = UPLOAD_BODY("$location?test=type", content => $value); 
       ok t_cmp("text/plain", $result, "type");
  +}
  +{
  +    my $value = 'DataUpload' x 100;
  +    my $result = UPLOAD_BODY("$location?test=hook", content => $value); 
  +    ok t_cmp($value, $result, "type");
   }
   {
       my $value = 'DataUpload' x 100;
  
  
  
  1.24      +17 -0     httpd-apreq-2/glue/perl/t/response/TestApReq/request.pm
  
  Index: request.pm
  ===================================================================
  RCS file: /home/cvs/httpd-apreq-2/glue/perl/t/response/TestApReq/request.pm,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- request.pm        7 Jul 2004 06:41:16 -0000       1.23
  +++ request.pm        7 Jul 2004 23:53:01 -0000       1.24
  @@ -13,6 +13,17 @@
   use Apache::ServerUtil;
   use File::Spec;
   
  +my $data;
  +
  +sub hook {
  +    my ($upload, $buffer, $len, $hook_data) = @_;
  +    warn "$upload saw EOS" and return unless defined $buffer;
  +
  +    die "BAD UPLOAD ARGS" unless length $buffer == $len;
  +    warn "$upload saw $buffer";
  +    $data .= $buffer;
  +}
  +
   sub handler {
       my $r = shift;
       my $temp_dir = $r->server->server_root_relative('logs');
  @@ -110,6 +121,12 @@
               $req->upload("HTTPUPLOAD")->slurp(my $data);
               $req->print($data);
           }
  +    }
  +    elsif ($test eq 'hook') {
  +        $data = "";
  +        $req->config(UPLOAD_HOOK => \&hook);
  +        $req->parse;
  +        $r->print($data);
       }
       elsif ($test eq 'type') {
           my $upload = $req->upload("HTTPUPLOAD");
  
  
  
  1.42      +184 -12   
httpd-apreq-2/glue/perl/xsbuilder/Apache/Request/Apache__Request.h
  
  Index: Apache__Request.h
  ===================================================================
  RCS file: 
/home/cvs/httpd-apreq-2/glue/perl/xsbuilder/Apache/Request/Apache__Request.h,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- Apache__Request.h 7 Jul 2004 06:41:17 -0000       1.41
  +++ Apache__Request.h 7 Jul 2004 23:53:01 -0000       1.42
  @@ -143,53 +143,225 @@
   APREQ_XS_DEFINE_TABLE_METHOD_N(param,set);
   APREQ_XS_DEFINE_TABLE_METHOD_N(param,add);
   
  +
  +struct hook_ctx {
  +    SV                  *hook_data;
  +    SV                  *hook;
  +    SV                  *bucket_data;
  +    SV                  *parent;
  +    PerlInterpreter     *perl;
  +};
  +
  +
  +#define DEREF(slot) if (ctx->slot) SvREFCNT_dec(ctx->slot)
  +
  +static apr_status_t upload_hook_cleanup(void *ctx_)
  +{
  +    struct hook_ctx *ctx = ctx_;
  +
  +#ifdef USE_ITHREADS
  +    dTHXa(ctx->perl);
  +#endif
  +
  +    DEREF(hook_data);
  +    DEREF(hook);
  +    DEREF(bucket_data);
  +    DEREF(parent);
  +    return APR_SUCCESS;
  +}
  +
  +APR_INLINE
  +static apr_status_t eval_upload_hook(pTHX_ apreq_param_t *upload, 
  +                                     void *env, struct hook_ctx *ctx)
  +{
  +    dSP;
  +    SV *sv = ctx->bucket_data;
  +    STRLEN len = SvPOK(sv) ? SvCUR(sv) : 0;
  +
  +    PUSHMARK(SP);
  +    EXTEND(SP, 4);
  +    ENTER;
  +    SAVETMPS;
  +
  +    PUSHs(sv_2mortal(apreq_xs_2sv(upload, "Apache::Upload", ctx->parent)));
  +    PUSHs(sv);
  +    PUSHs(sv_2mortal(newSViv(len)));
  +    if (ctx->hook_data)
  +        PUSHs(ctx->hook_data);
  +
  +    PUTBACK;
  +    perl_call_sv(ctx->hook, G_EVAL|G_DISCARD);
  +    FREETMPS;
  +    LEAVE;
  +
  +    if (SvTRUE(ERRSV)) {
  +        Perl_warn(aTHX_ "Upload hook failed: %s", SvPV_nolen(ERRSV));
  +        return APR_EGENERAL;
  +    }
  +    return APR_SUCCESS;
  +}
  +
  +
  +static apr_status_t apreq_xs_upload_hook(APREQ_HOOK_ARGS)
  +{
  +    struct hook_ctx *ctx = hook->ctx; /* ctx set during $req->config */
  +    apr_bucket *e;
  +    apr_status_t s = APR_SUCCESS;
  +#ifdef USE_ITHREADS
  +    dTHXa(ctx->perl);
  +#endif
  +
  +    for (e = APR_BRIGADE_FIRST(bb); e!= APR_BRIGADE_SENTINEL(bb);
  +         e = APR_BUCKET_NEXT(e))
  +    {
  +        apr_off_t len;
  +        const char *data;
  +        apreq_log(APREQ_DEBUG 0, env, "looping through buckets");
  +
  +        if (APR_BUCKET_IS_EOS(e)) {  /*last call on this upload */           
  +            SV *sv = ctx->bucket_data;
  +            ctx->bucket_data = &PL_sv_undef;
  +            s = eval_upload_hook(aTHX_ param, env, ctx);
  +            ctx->bucket_data = sv;
  +            if (s != APR_SUCCESS)
  +                return s;
  +            apreq_log(APREQ_DEBUG 0, env, "upload hook saw eos bucket");
  +
  +            break;
  +        }
  +
  +        s = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
  +        if (s != APR_SUCCESS)
  +            return s;
  +
  +        sv_setpvn(ctx->bucket_data, data, (STRLEN)len);
  +
  +        s = eval_upload_hook(aTHX_ param, env, ctx);
  +
  +        apreq_log(APREQ_DEBUG 0, env, "ran upload hook");
  +
  +        if (s != APR_SUCCESS)
  +            return s;
  +
  +    }
  +
  +    if (hook->next)
  +        s = APREQ_RUN_HOOK(hook->next, env, param, bb);
  +
  +    return s;
  +}
  +
  +
  +
   static XS(apreq_xs_request_config)
   {
       dXSARGS;
  +    apr_pool_t *pool;
       apreq_request_t *req;
  +    apreq_hook_t *upload_hook = NULL;
  +    SV *sv;
  +    SV *hook_data = NULL;
       int j;
  +
       if (items % 2 != 1 || !SvROK(ST(0)))
           Perl_croak(aTHX_ "usage: $req->config(%settings)");
   
  -    req = apreq_xs_sv2(request,ST(0));
  +    sv = apreq_xs_find_obj(aTHX_ ST(0), "request");
  +    req = (apreq_request_t *)SvIVX(sv);
  +    pool = apreq_env_pool(req->env);
   
       for (j = 1; j + 1 < items; j += 2) {
  -        STRLEN alen, vlen;
  -        const char *attr = SvPVbyte(ST(j),alen), 
  -                    *val = SvPVbyte(ST(j+1),vlen);
  +        STRLEN alen;
  +        const char *attr = SvPVbyte(ST(j),alen);
   
           if (strcasecmp(attr,"POST_MAX")== 0
               || strcasecmp(attr, "MAX_BODY") == 0) 
           {
  +            const char *val = SvPV_nolen(ST(j+1));
               apreq_env_max_body(req->env,
                                  (apr_off_t)apreq_atoi64f(val));
           }
           else if (strcasecmp(attr, "TEMP_DIR") == 0) {
  +            const char *val = SvPV_nolen(ST(j+1));
               apreq_env_temp_dir(req->env, val);
           }
           else if (strcasecmp(attr, "MAX_BRIGADE") == 0) {
  +            const char *val = SvPV_nolen(ST(j+1));
               apreq_env_max_brigade(req->env, (apr_ssize_t)apreq_atoi64f(val));
           }
           else if (strcasecmp(attr, "DISABLE_UPLOADS") == 0) {
  -            if (req->parser == NULL)
  +            if (req->parser == NULL) {
                   req->parser = apreq_parser(req->env, NULL);
  -            if (req->parser != NULL)
  -                apreq_add_hook(req->parser,
  -                               apreq_make_hook(apreq_env_pool(req->env), 
  -                                               apreq_hook_disable_uploads,
  -                                               NULL, NULL));
  +                if (req->parser == NULL) {
  +                    Perl_warn(aTHX_ "Apache::Request::config: "
  +                              "cannot disable/enable uploads (parser not 
found)");
  +                    continue;
  +                }
  +            }
  +            if (SvTRUE(ST(j+1))) {
  +                /* add disable_uploads hook */
  +                if (req->parser == NULL)
  +                    req->parser = apreq_parser(req->env, NULL);
  +                if (req->parser != NULL)
  +                    apreq_add_hook(req->parser,
  +                                   apreq_make_hook(pool, 
  +                                                   
apreq_hook_disable_uploads,
  +                                                   NULL, NULL));
  +            }
  +            else {
  +                /* remove all disable_uploads hooks */
  +                apreq_hook_t *first = req->parser->hook;
  +
  +                while (first != NULL && first->hook == 
apreq_hook_disable_uploads)
  +                    first = first->next;
  +
  +                req->parser->hook = first;
  +
  +                if (first != NULL) {
  +                    apreq_hook_t *cur;
  +
  +                    for (cur = first->next; cur != NULL; cur = cur->next) {
  +                        if (cur->hook == apreq_hook_disable_uploads)
  +                            first->next = cur->next;
  +                        else
  +                            first = cur;
  +                    }
  +                }
  +            }
           }
           else if (strcasecmp(attr, "UPLOAD_HOOK") == 0) {
  -            ;
  +            struct hook_ctx *ctx = apr_palloc(apreq_env_pool(req->env), 
sizeof *ctx);
  +            if (upload_hook)
  +                Perl_croak(aTHX_ "Apache::Request::config: "
  +                           "cannot set UPLOAD_HOOK more than once");
  +
  +            ctx->hook_data = NULL;
  +            ctx->hook = newSVsv(ST(j+1));
  +            ctx->bucket_data = newSV(8000);
  +            ctx->parent = SvREFCNT_inc(sv);
  +#ifdef USE_ITHREADS
  +            ctx->perl = aTHX;
  +#endif
  +            upload_hook = apreq_make_hook(pool, apreq_xs_upload_hook, NULL, 
ctx);
  +            apreq_add_hook(req->parser, upload_hook);
  +            apr_pool_cleanup_register(pool, ctx, upload_hook_cleanup, NULL);
           }
  +
           else if (strcasecmp(attr, "HOOK_DATA") == 0) {
  -            ;
  +            if (hook_data)
  +                Perl_croak(aTHX_ "Apache::Request::config: "
  +                           "cannot set HOOK_DATA more than once");
  +            hook_data = ST(j+1);
           }
           else {
               Perl_warn(aTHX_ "Apache::Request::config: "
                         "Unrecognized attribute %s, skipped", attr);
           }
       }
  +
  +    if (upload_hook && hook_data)
  +        ((struct hook_ctx *)upload_hook->ctx)->hook_data = 
newSVsv(hook_data);
  +
       XSRETURN(0);
   }
   
  
  
  
  1.11      +0 -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.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- apreq_env.c       7 Jul 2004 16:12:15 -0000       1.10
  +++ apreq_env.c       7 Jul 2004 23:53:01 -0000       1.11
  @@ -16,8 +16,6 @@
   
   #include "apreq.h"
   #include "apreq_env.h"
  -#include "apreq_params.h"
  -#include "apreq_cookie.h"
   #include "apr_strings.h"
   #include "apr_lib.h"
   #include "apr_env.h"
  
  
  
  1.36      +13 -13    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.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- apreq_params.h    7 Jul 2004 13:49:53 -0000       1.35
  +++ apreq_params.h    7 Jul 2004 23:53:01 -0000       1.36
  @@ -217,26 +217,26 @@
   #include "apreq.h"
   
   /** Parser arguments. */
  -#define APREQ_PARSER_ARGS (apreq_parser_t *parser,     \
  +#define APREQ_PARSER_ARGS  apreq_parser_t *parser,     \
                              void *env,                  \
                              apr_table_t *t,             \
  -                           apr_bucket_brigade *bb)
  +                           apr_bucket_brigade *bb
   
   /** Hook arguments */
  -#define APREQ_HOOK_ARGS   (apreq_hook_t *hook,         \
  +#define APREQ_HOOK_ARGS    apreq_hook_t *hook,         \
                              void *env,                  \
  -                           const apreq_param_t *param, \
  -                           apr_bucket_brigade *bb)
  +                           apreq_param_t *param,       \
  +                           apr_bucket_brigade *bb
   
   /**
    * Declares a API parser.
    */
   #ifndef WIN32
   #define APREQ_DECLARE_PARSER(f) APREQ_DECLARE(apr_status_t) \
  -                                (f) APREQ_PARSER_ARGS
  +                                (f) (APREQ_PARSER_ARGS)
   #else
   #define APREQ_DECLARE_PARSER(f) APREQ_DECLARE_NONSTD(apr_status_t) \
  -                                (f) APREQ_PARSER_ARGS
  +                                (f) (APREQ_PARSER_ARGS)
   #endif
   
   /**
  @@ -244,10 +244,10 @@
    */
   #ifndef WIN32
   #define APREQ_DECLARE_HOOK(f)   APREQ_DECLARE(apr_status_t) \
  -                                (f) APREQ_HOOK_ARGS
  +                                (f) (APREQ_HOOK_ARGS)
   #else
   #define APREQ_DECLARE_HOOK(f)   APREQ_DECLARE_NONSTD(apr_status_t) \
  -                                (f) APREQ_HOOK_ARGS
  +                                (f) (APREQ_HOOK_ARGS)
   #endif
   
   /**
  @@ -255,7 +255,7 @@
    *
    */
   struct apreq_hook_t {
  -    apr_status_t  (*hook) APREQ_HOOK_ARGS;
  +    apr_status_t  (*hook) (APREQ_HOOK_ARGS);
       apreq_hook_t   *next;
       void           *ctx;
   };
  @@ -265,7 +265,7 @@
    *
    */
   struct apreq_parser_t {
  -    apr_status_t (*parser) APREQ_PARSER_ARGS;
  +    apr_status_t (*parser) (APREQ_PARSER_ARGS);
       const char    *enctype;
       apreq_hook_t  *hook;
       void          *ctx;
  @@ -339,7 +339,7 @@
   APREQ_DECLARE(apreq_parser_t *)
           apreq_make_parser(apr_pool_t *pool,
                             const char *enctype,
  -                          apr_status_t (*parser) APREQ_PARSER_ARGS,
  +                          apr_status_t (*parser) (APREQ_PARSER_ARGS),
                             apreq_hook_t *hook,
                             void *ctx);
   
  @@ -354,7 +354,7 @@
    */
   APREQ_DECLARE(apreq_hook_t *)
           apreq_make_hook(apr_pool_t *pool,
  -                        apr_status_t (*hook) APREQ_HOOK_ARGS,
  +                        apr_status_t (*hook) (APREQ_HOOK_ARGS),
                           apreq_hook_t *next,
                           void *ctx);
   
  
  
  
  1.55      +7 -7      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.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- apreq_parsers.c   1 Jul 2004 18:18:26 -0000       1.54
  +++ apreq_parsers.c   7 Jul 2004 23:53:01 -0000       1.55
  @@ -44,7 +44,7 @@
   APREQ_DECLARE(apreq_parser_t *)
       apreq_make_parser(apr_pool_t *pool,
                         const char *enctype,
  -                      apr_status_t (*parser) APREQ_PARSER_ARGS,
  +                      apr_status_t (*parser) (APREQ_PARSER_ARGS),
                         apreq_hook_t *hook,
                         void *ctx)
   {
  @@ -58,7 +58,7 @@
   
   APREQ_DECLARE(apreq_hook_t *)
       apreq_make_hook(apr_pool_t *pool,
  -                    apr_status_t (*hook) APREQ_HOOK_ARGS,
  +                    apr_status_t (*hook) (APREQ_HOOK_ARGS),
                       apreq_hook_t *next,
                       void *ctx)
   {
  @@ -146,7 +146,7 @@
           decoded_len = apreq_decode((char *)v->name + off, data, dlen);
   
           if (decoded_len < 0) {
  -            return APR_BADARG;
  +            return APR_EGENERAL;
           }
   
           off += decoded_len;
  @@ -179,7 +179,7 @@
           decoded_len = apreq_decode(v->data + off, data, dlen);
   
           if (decoded_len < 0) {
  -            return APR_BADCH;
  +            return APR_EGENERAL;
           }
   
           off += decoded_len;
  @@ -611,7 +611,7 @@
           bytes_to_check = MIN(slen,blen);
   
           if (strncmp(buf,start_string,bytes_to_check) != 0)
  -            return APR_BADCH;
  +            return APR_EGENERAL;
   
           slen -= bytes_to_check;
           start_string += bytes_to_check;
  @@ -961,14 +961,14 @@
   
               if (cd == NULL) {
                   ctx->status = MFD_ERROR;
  -                return APR_BADARG;
  +                return APR_EGENERAL;
               }
   
               s = apreq_header_attribute(cd, "name", 4, &name, &nlen);
   
               if (s != APR_SUCCESS) {
                   ctx->status = MFD_ERROR;
  -                return APR_BADARG;
  +                return APR_EGENERAL;
               }
   
               s = apreq_header_attribute(cd, "filename", 8, &filename, &flen);
  
  
  

Reply via email to