You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Carl Brewer <ca...@bl.echidna.id.au> on 2004/08/26 00:25:05 UTC

[mp2] code broken by 1.99_15 or _16 or _17-dev


Stas et all,

Here's the code that I was using to grab POSTed values and
put them into a hash 0 sorry for the verbosity of this post,
I won't pretend to fully understand this code, Stas wrote
the majority of it way back when libapreq wouldn't compile
on NetBSD, and I've been using it ever since.

If there's a better way to do this with libapreq, I'd
preobably like to move my code over to using it!

Code attached, which no longer works :

I call this to fill a simple hash, eg :

my %posted_data = CB::hash_post($r);



sub read_post {
     use Apache::Filter ();
     use APR::Bucket ();
     use APR::Brigade ();
     use constant IOBUFSIZE => 8192;
     use Apache::Const -compile => qw(MODE_READBYTES);
     use APR::Const    -compile => qw(SUCCESS BLOCK_READ);

     use CGI::Util;

     my $r = shift;
     my $debug = shift || 0;

     my @data = ();
     my $seen_eos = 0;
     my $filters = $r->input_filters();
     my $ba = $r->connection->bucket_alloc;
     my $bb = APR::Brigade->new($r->pool, $ba);

     do {
         my $rv = $filters->get_brigade($bb,
             Apache::MODE_READBYTES, APR::BLOCK_READ, IOBUFSIZE);
         if ($rv != APR::SUCCESS) {
             return $rv;
         }

         while (!$bb->is_empty) {
             my $buf;
             my $b = $bb->first;

             $b->remove;

             if ($b->is_eos) {
                 warn "EOS bucket:\n" if $debug;
                 $seen_eos++;
                 last;
             }

             my $status = $b->read($buf);
             warn "DATA bucket: [$buf]\n" if $debug;
             if ($status != APR::SUCCESS) {
                 return $status;
             }
             push @data, $buf;
         }

         $bb->destroy;

     } while (!$seen_eos);
     my $string = join '', @data;
     return $string;
}


sub hash_post {
     # this has to get called instead of read_post, as read_post()
     # gobbles up the POST arguments and they're no longer available...
     # and this calls read_post() :)

     # returns a hash of all the POST values

     my ($r) = shift;

     my $post_string = CB::read_post($r);
     my %rethash = {};

     my @bits = split(/&/, $post_string);
     foreach my $bit (@bits) {
         $bit =~ /^(.*)=(.*)$/;
         my $key = CGI::Util::unescape($1);
         my $value = CGI::Util::unescape($2);
         $rethash{$key} = $value;
     }
     return %rethash;
}





-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html


Re: [mp2] code broken by 1.99_15 or _16 or _17-dev

Posted by Stas Bekman <st...@stason.org>.
Carl Brewer wrote:
> Stas Bekman wrote:
> 
> 
>> I'm thinking that it might be beneficial to implement it in C.
> 
> 
> Would I be better served by switching to using libapreq?  Isn't this
> what it's for?  I recall you sent me that code a long time ago
> as the libapreq stuff wouldn't compile cleanly on NetBSD.
> 
> I'd prefer not to have to maintain code that goes this deeply
> into mod_perl :)  I won't pretend to be anything like a solid
> enough perl hacker to do anything but make an awful mess!

Once mp2.0 is released, there will be no API changes that will break your 
existing code. Hence it's not released yet, as we polish it.

Yes, you absolutely want to use libapreq2[1], though I don't know whether 
it works fine under NetBSD, download it, test it and chances are that it 
works just fine, then switch to it.

I just think that sometimes it's useful to be able to grab the whole 
request body w/o depending on any external library.

[1] http://httpd.apache.org/apreq/

p.s. if you know that the client provides a correct Content-Length header 
you could get the content in one line:

my $len = $r->read(my $data, $r->headers_in->{'Content-Length'});

but I won't trust all the clients to do it right.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html


Re: [mp2] code broken by 1.99_15 or _16 or _17-dev

Posted by Carl Brewer <ca...@bl.echidna.id.au>.
Stas Bekman wrote:


> I'm thinking that it might be beneficial to implement it in C.

Would I be better served by switching to using libapreq?  Isn't this
what it's for?  I recall you sent me that code a long time ago
as the libapreq stuff wouldn't compile cleanly on NetBSD.

I'd prefer not to have to maintain code that goes this deeply
into mod_perl :)  I won't pretend to be anything like a solid
enough perl hacker to do anything but make an awful mess!








-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html


Re: [mp2] code broken by 1.99_15 or _16 or _17-dev

Posted by Stas Bekman <st...@stason.org>.
Carl Brewer wrote:
> 
> 
> Stas et all,
> 
> Here's the code that I was using to grab POSTed values and
> put them into a hash 0 sorry for the verbosity of this post,
> I won't pretend to fully understand this code, Stas wrote
> the majority of it way back when libapreq wouldn't compile
> on NetBSD, and I've been using it ever since.

>             my $status = $b->read($buf);
>             warn "DATA bucket: [$buf]\n" if $debug;
>             if ($status != APR::SUCCESS) {
>                 return $status;

That's your problem. Please see:
http://perl.apache.org/docs/2.0/api/APR/Bucket.html#C_read_
The API of read has changed.

The new way to implement $r->content is:

use APR::Brigade ();
use APR::Bucket ();
use Apache::Filter ();

use Apache::Const -compile => qw(MODE_READBYTES);
use APR::Const    -compile => qw(SUCCESS BLOCK_READ);

use constant IOBUFSIZE => 8192;

sub content {
     my $r = shift;

     my $bb = APR::Brigade->new($r->pool,
                                $r->connection->bucket_alloc);

     my $data = '';
     my $seen_eos = 0;
     do {
         $r->input_filters->get_brigade($bb, Apache::MODE_READBYTES,
                                        APR::BLOCK_READ, IOBUFSIZE);
         while (!$bb->is_empty) {
             my $b = $bb->first;

             if ($b->is_eos) {
                 $seen_eos++;
                 last;
             }

             if ($b->read(my $buf)) {
                 $data .= $buf;
             }

             $b->delete;
         }
     } while (!$seen_eos);

     $bb->destroy;

     return $data;
}

I'm thinking that it might be beneficial to implement it in C.


-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html


Re: [mp2] code broken by 1.99_15 or _16 or _17-dev

Posted by Glenn Strauss <gs...@gluelogic.com>.
On Thu, Aug 26, 2004 at 08:25:05AM +1000, Carl Brewer wrote:
> sub hash_post {
>     # this has to get called instead of read_post, as read_post()
>     # gobbles up the POST arguments and they're no longer available...
>     # and this calls read_post() :)
> 
>     # returns a hash of all the POST values
> 
>     my ($r) = shift;
> 
>     my $post_string = CB::read_post($r);
>     my %rethash = {};
> 
>     my @bits = split(/&/, $post_string);
>     foreach my $bit (@bits) {
>         $bit =~ /^(.*)=(.*)$/;
>         my $key = CGI::Util::unescape($1);
>         my $value = CGI::Util::unescape($2);
>         $rethash{$key} = $value;
>     }
>     return %rethash;
> }


A really quick look and I see that 
>         $bit =~ /^(.*)=(.*)$/;
should be
          $bit =~ /^(.*?)=(.*)$/ || next;
or else the greedy match in the key will grab up to an "=" sign
in the value, if one exists.  Also, you do double work on a
sequence without any '=' sign, because $1 and $2 will still be
the same from the previous match if there was one, or else might
be a previous match from elsewhere in the program (!) if there
was not a previous key/value in the $post_string.

The line should really be
          $bit =~ /^(.+?)=(.*)$/;
if you want to handle those and additionally wish to disallow
empty keys, either.

If you do want to allow key/value pairs without "=", then a
slight variation in code should be used.


However, these probably have nothing to do with the question you
are asking; I'm just pointing out a bug in the code you posted.

Cheers,
Glenn

-- 
Report problems: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
List etiquette: http://perl.apache.org/maillist/email-etiquette.html