Revision: 31 Author: matt Date: 2006-08-02 20:41:47 +0000 (Wed, 02 Aug 2006)
Log Message: ----------- Querystring parsing Modified Paths: -------------- trunk/demo/xsp/test.xsp trunk/lib/AxKit2/HTTPHeaders.pm trunk/lib/AxKit2/Transformer/XSP.pm trunk/lib/AxKit2/Utils.pm Modified: trunk/demo/xsp/test.xsp =================================================================== --- trunk/demo/xsp/test.xsp 2006-08-02 19:50:37 UTC (rev 30) +++ trunk/demo/xsp/test.xsp 2006-08-02 20:41:47 UTC (rev 31) @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<xsp:page xmlns:xsp="http://apache.org/xsp/core/v1"> +<xsp:page xmlns:xsp="http://apache.org/xsp/core/v1" indent-result="yes"> <output> Hello World. The time of request is: <xsp:expr>scalar localtime</xsp:expr> @@ -8,5 +8,13 @@ { abc => 42, xyz => { goofy => "yes", ugly => "no" } }; </xsp:expr> </structure> + <querystring> + <xsp:expr> + [ + map { {key => $_, value => [ $cgi->headers_in->param($_) ] } } + $cgi->headers_in->param + ] + </xsp:expr> + </querystring> </output> </xsp:page> Modified: trunk/lib/AxKit2/HTTPHeaders.pm =================================================================== --- trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-02 19:50:37 UTC (rev 30) +++ trunk/lib/AxKit2/HTTPHeaders.pm 2006-08-02 20:41:47 UTC (rev 31) @@ -9,17 +9,20 @@ use AxKit2::Utils qw(uri_decode); use fields ( - 'headers', # href; lowercase header -> comma-sep list of values - 'origcase', # href; lowercase header -> provided case - 'hdorder', # aref; order headers were received (canonical order) - 'method', # scalar; request method (if GET request) - 'uri', # scalar; request URI (if GET request) - 'file', # scalar; request File - 'type', # 'res' or 'req' - 'code', # HTTP response status code - 'codetext', # status text that for response code - 'ver', # version (string) "1.1" - 'vernum', # version (number: major*1000+minor): "1.1" => 1001 + 'headers', # href; lowercase header -> comma-sep list of values + 'origcase', # href; lowercase header -> provided case + 'hdorder', # aref; order headers were received (canonical order) + 'method', # scalar; request method (if GET request) + 'uri', # scalar; request URI (if GET request) + 'file', # scalar; request File + 'querystring', # scalar: request querystring + 'params', # parsed params + 'paramkeys', # all parsed param keys + 'type', # 'res' or 'req' + 'code', # HTTP response status code + 'codetext', # status text that for response code + 'ver', # version (string) "1.1" + 'vernum', # version (number: major*1000+minor): "1.1" => 1001 'responseLine', # first line of HTTP response (if response) 'requestLine', # first line of HTTP request (if request) ); @@ -49,12 +52,14 @@ my @lines = split(/\r?\n/, $$hstr_ref); - $self->{headers} = {}; - $self->{origcase} = {}; - $self->{hdorder} = []; - $self->{method} = undef; - $self->{uri} = undef; - $self->{type} = ($is_response ? "res" : "req"); + $self->{headers} = {}; + $self->{origcase} = {}; + $self->{hdorder} = []; + $self->{paramkeys} = []; + $self->{params} = {}; + $self->{method} = undef; + $self->{uri} = undef; + $self->{type} = ($is_response ? "res" : "req"); # check request line if ($is_response) { @@ -90,8 +95,8 @@ if ($self->{uri} =~ m!^http://([^/:]+?)(?::\d+)?(/.*)?$!) { $absoluteURIHost = lc($1); $self->{uri} = $2 || "/"; # "http://www.foo.com" yields no path, so default to "/" - $self->parse_uri; } + $self->parse_uri; # default to HTTP/0.9 unless (defined $ver_ma) { @@ -170,8 +175,37 @@ sub parse_uri { my AxKit2::HTTPHeaders $self = shift; + my ($path, $qs) = split(/\?/, $self->{uri}); + $qs = "" if !defined $qs; + my (@item) = split(/[&;]/, $qs); + foreach (@item) { + my ($key, $value) = split('=',$_,2); + next unless defined $key; + $value = '' unless defined $value; # what I wouldn't give for //= + $key = uri_decode($key); + $value = uri_decode($value); + push @{$self->{paramkeys}}, $key unless exists $self->{params}{$key}; + push @{$self->{params}{$key}}, $value; + } } +sub add_param { + my AxKit2::HTTPHeaders $self = shift; + my ($key, $value) = @_; + $value = '' unless defined $value; + push @{$self->{paramkeys}}, $key unless exists $self->{params}{$key}; + push @{ $self->{params}{$key} }, $value; +} + +# returns all params for a key in LIST context, or the last param for a key in SCALAR +sub param { + my AxKit2::HTTPHeaders $self = shift; + my $key = shift; + return @{$self->{paramkeys}} unless defined $key; + return unless exists $self->{params}{$key}; + return wantarray ? @{ $self->{params}{$key} } : $self->{params}{$key}[-1]; +} + sub http_code_english { my AxKit2::HTTPHeaders $self = shift; if (@_) { Modified: trunk/lib/AxKit2/Transformer/XSP.pm =================================================================== --- trunk/lib/AxKit2/Transformer/XSP.pm 2006-08-02 19:50:37 UTC (rev 30) +++ trunk/lib/AxKit2/Transformer/XSP.pm 2006-08-02 20:41:47 UTC (rev 31) @@ -2,6 +2,7 @@ use strict; use warnings; +no warnings 'uninitialized'; use base qw(AxKit2::Transformer); Modified: trunk/lib/AxKit2/Utils.pm =================================================================== --- trunk/lib/AxKit2/Utils.pm 2006-08-02 19:50:37 UTC (rev 30) +++ trunk/lib/AxKit2/Utils.pm 2006-08-02 20:41:47 UTC (rev 31) @@ -11,10 +11,59 @@ my $uri = shift; return '' unless defined $uri; $uri =~ s/\+/ /g; - $uri =~ s/%([A-F0-9][A-F0-9])/pack("C", hex($1))/eig; + $uri =~ s/ + % # encoded data marker + (?: # followed by either + ([0-9a-fA-F]{2}) # 2 hex chars + | # or + u([0-9a-fA-F]{4}) # 'u' then 4 hex chars + ) + / + defined($1) ? chr hex($1) : utf8_chr(hex($2)) + /gex; return $uri; } +# borrowed from CGI::Util which I think borrowed it from XML::DOM... +sub utf8_chr ($) { + my $c = shift(@_); + + if ($c < 0x80) { + return sprintf("%c", $c); + } elsif ($c < 0x800) { + return sprintf("%c%c", 0xc0 | ($c >> 6), 0x80 | ($c & 0x3f)); + } elsif ($c < 0x10000) { + return sprintf("%c%c%c", + 0xe0 | ($c >> 12), + 0x80 | (($c >> 6) & 0x3f), + 0x80 | ( $c & 0x3f)); + } elsif ($c < 0x200000) { + return sprintf("%c%c%c%c", + 0xf0 | ($c >> 18), + 0x80 | (($c >> 12) & 0x3f), + 0x80 | (($c >> 6) & 0x3f), + 0x80 | ( $c & 0x3f)); + } elsif ($c < 0x4000000) { + return sprintf("%c%c%c%c%c", + 0xf8 | ($c >> 24), + 0x80 | (($c >> 18) & 0x3f), + 0x80 | (($c >> 12) & 0x3f), + 0x80 | (($c >> 6) & 0x3f), + 0x80 | ( $c & 0x3f)); + + } elsif ($c < 0x80000000) { + return sprintf("%c%c%c%c%c%c", + 0xfe | ($c >> 30), + 0x80 | (($c >> 24) & 0x3f), + 0x80 | (($c >> 18) & 0x3f), + 0x80 | (($c >> 12) & 0x3f), + 0x80 | (($c >> 6) & 0x3f), + 0x80 | ( $c & 0x3f)); + } else { + return utf8(0xfffd); + } +} + sub http_date { my $time = shift; $time = time unless defined $time;