URI-Query-0.10/0000755000175000017500000000000012023261107012160 5ustar gavingavinURI-Query-0.10/MANIFEST.SKIP0000644000175000017500000000010111516375645014071 0ustar gavingavin.git .gitignore EXCLUDE Makefile Makefile.old MANIFEST.bak TODO URI-Query-0.10/t/0000755000175000017500000000000012023260314012422 5ustar gavingavinURI-Query-0.10/t/06_eq.t0000644000175000017500000000111512023260314013517 0ustar gavingavin# Test 'eq' overloading use Test::More tests => 10; BEGIN { use_ok( URI::Query ) } use strict; my ($qq1, $qq2); ok($qq1 = URI::Query->new('foo=1&foo=2&bar=3'), 'qq1 constructor ok'); ok($qq2 = URI::Query->new('foo=1&bar=3&foo=2'), 'qq2 constructor ok'); is($qq1, $qq2, 'eq ok'); ok($qq2 = URI::Query->new('bar=3&foo=1&foo=2'), 'qq2 constructor ok'); is($qq1, $qq2, 'eq ok'); ok($qq2 = URI::Query->new('bar=3&foo=2&foo=1'), 'qq2 constructor ok'); isnt($qq1, $qq2, 'ne ok (value ordering preserved)'); ok($qq2 = URI::Query->new('bar=3'), 'qq2 constructor ok'); isnt($qq1, $qq2, 'ne ok'); URI-Query-0.10/t/03_hash.t0000644000175000017500000000260511516332275014053 0ustar gavingavin# URI::Query hash methods use strict; use vars q($count); BEGIN { $count = 5 } use Test::More tests => $count; use_ok('URI::Query'); my ($qq, $out); # Load result strings my $test = 't03'; my %result = (); $test = "t/$test" if -d "t/$test"; die "missing data dir $test" unless -d $test; { opendir my $dir, "$test" or die "can't open $test"; for (readdir $dir) { next if m/^\./; open my $file, "<$test/$_" or die "can't read $test/$_"; local $/ = undef; $result{$_} = <$file>; } } my $print = shift @ARGV || 0; my $t = 3; sub report { my ($data, $file, $inc) = @_; $inc ||= 1; if ($print == $t) { print STDERR "--> $file\n"; print $data; exit 0; } $t += $inc; } ok($qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'), "constructor ok"); SKIP: { my $yaml = eval { require YAML }; skip "YAML not found", 2 unless $yaml; # Require YAML 0.39 on Windows (reported by Andy Grundman) if ($^O =~ m/^MSWin/i && ! defined eval { YAML->VERSION(0.39) }) { skip "YAML >= 0.39 required on windows", 2; } $out = YAML::Dump(scalar($qq->hash)); report $out, "hash"; is($out, $result{hash}, 'hash ok'); $out = YAML::Dump(scalar($qq->hash_arrayref)); report $out, "hash_arrayref"; is($out, $result{hash_arrayref}, 'hash_arrayref ok'); } $out = $qq->hidden; report $out, "hidden"; is($out, $result{hidden}, 'hidden ok'); URI-Query-0.10/t/t03/0000755000175000017500000000000011516331243013036 5ustar gavingavinURI-Query-0.10/t/t03/hash_arrayref0000644000175000017500000000010111516331243015567 0ustar gavingavin--- bar: - 3 - 7 bog: - abc fluffy: - 3 foo: - 1 - 2 URI-Query-0.10/t/t03/hidden0000644000175000017500000000042311516331243014213 0ustar gavingavin URI-Query-0.10/t/t03/hash0000644000175000017500000000007111516331243013702 0ustar gavingavin--- bar: - 3 - 7 bog: abc fluffy: 3 foo: - 1 - 2 URI-Query-0.10/t/t05/0000755000175000017500000000000011615626613013050 5ustar gavingavinURI-Query-0.10/t/t05/explicit0000644000175000017500000000005111516331243014600 0ustar gavingavinbar=3;bar=7;bog=abc;fluffy=3;foo=1;foo=2 URI-Query-0.10/t/t05/standard0000644000175000017500000000005111516331243014557 0ustar gavingavinbar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2 URI-Query-0.10/t/t05/default0000644000175000017500000000005111615627063014413 0ustar gavingavinbar=3;bar=7;bog=abc;fluffy=3;foo=1;foo=2 URI-Query-0.10/t/05_sep.t0000644000175000017500000000253611516332300013711 0ustar gavingavin# Test separator handling use strict; use vars q($count); BEGIN { $count = 6 } use Test::More tests => $count; use_ok('URI::Query'); my ($qq, $out); # Load result strings my $test = 't05'; my %result = (); $test = "t/$test" if -d "t/$test"; die "missing data dir $test" unless -d $test; { opendir my $dir, "$test" or die "can't open $test"; for (readdir $dir) { next if m/^\./; open my $file, "<$test/$_" or die "can't read $test/$_"; { local $/ = undef; $result{$_} = <$file>; } chomp $result{$_}; } } my $print = shift @ARGV || 0; my $t = 3; sub report { my ($data, $file, $inc) = @_; $inc ||= 1; if ($print == $t) { print STDERR "--> $file\n"; print $data; exit 0; } $t += $inc; } ok($qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'), "constructor ok"); $out = $qq->stringify; report $out, "standard"; is($out, $result{standard}, "standard stringify ok"); # Stringify with an explicit separator $out = $qq->stringify(';'); report $out, "explicit"; is($out, $result{explicit}, "explicit separator ok"); # Recheck standard in place $out = $qq->stringify; report $out, "standard"; is($out, $result{standard}, "standard stringify ok"); # Set default separator $qq->separator(';'); $out = $qq->stringify; report $out, "default"; is($out, $result{default}, "setting default separator ok"); URI-Query-0.10/t/01_constructor.t0000644000175000017500000000277511516356630015524 0ustar gavingavin# Basic URI::Query tests use Test::More; use_ok(URI::Query); use strict; my $qq; # Constructor - scalar version ok($qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'), "scalar constructor ok"); is($qq->stringify, 'bar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2', sprintf("stringifies ok (%s)", $qq->stringify)); # Constructor - array version ok($qq = URI::Query->new(foo => 1, foo => 2, bar => 3, bog => 'abc', bar => 7, fluffy => 3), "array constructor ok"); is($qq->stringify, 'bar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2', sprintf("stringifies ok (%s)", $qq->stringify)); # Constructor - hashref version ok($qq = URI::Query->new({ foo => [ 1, 2 ], bar => [ 3, 7 ], bog => 'abc', fluffy => 3 }), "hashref constructor ok"); is($qq->stringify, 'bar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2', sprintf("stringifies ok (%s)", $qq->stringify)); # Constructor - CGI.pm-style hashref version, packed values ok($qq = URI::Query->new({ foo => "1\0002", bar => "3\0007", bog => 'abc', fluffy => 3 }), "cgi-style hashref constructor ok"); is($qq->stringify, 'bar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2', sprintf("stringifies ok (%s)", $qq->stringify)); # Bad constructor args { no warnings qw(once); for my $bad ((undef, '', \"foo", [ foo => 1 ], \*bad)) { my $b2 = $bad; $b2 = '[undef]' unless defined $bad; $qq = URI::Query->new($bad); ok(ref $qq eq 'URI::Query', "bad '$b2' constructor ok"); is($qq->stringify, '', sprintf("stringifies ok (%s)", $qq->stringify)); } } done_testing; URI-Query-0.10/t/02_methods.t0000644000175000017500000000312311516332310014554 0ustar gavingavin# URI::Query tests use Test::More tests => 15; BEGIN { use_ok( URI::Query ) } use strict; my $qq; # Basics - scalar version ok($qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'), "constructor ok"); is($qq->stringify, 'bar=3&bar=7&bog=abc&fluffy=3&foo=1&foo=2', sprintf("stringifies ok (%s)", $qq->stringify)); # strip ok($qq->strip(qw(foo bog)), "strip ok"); is($qq->stringify, 'bar=3&bar=7&fluffy=3', sprintf("strip correct (%s)", $qq->stringify)); # Simple replace $qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'); ok($qq->replace(foo => 'xyz', bog => 'magic', extra => 1), "replace ok"); is($qq->stringify, 'bar=3&bar=7&bog=magic&extra=1&fluffy=3&foo=xyz', sprintf("replace correct (%s)", $qq->stringify)); # Composite replace ok($qq->replace(foo => [ 123, 456, 789 ], extra => 2), "replace ok"); is($qq->stringify, 'bar=3&bar=7&bog=magic&extra=2&fluffy=3&foo=123&foo=456&foo=789', sprintf("replace correct (%s)", $qq->stringify)); # Auto-stringification is("$qq", 'bar=3&bar=7&bog=magic&extra=2&fluffy=3&foo=123&foo=456&foo=789', sprintf("auto-stringification ok (%s)", $qq . '')); # strip_except ok($qq->strip_except(qw(bar foo extra)), "strip_except ok"); is($qq->stringify, 'bar=3&bar=7&extra=2&foo=123&foo=456&foo=789', sprintf("strip_except correct (%s)", $qq->stringify)); # strip_null ok($qq = URI::Query->new(foo => 1, foo => 2, bar => '', bog => 'abc', zero => 0, fluffy => undef), "array constructor ok"); ok($qq->strip_null, "strip_null ok"); is($qq->stringify, 'bog=abc&foo=1&foo=2&zero=0', sprintf("strip_null correct (%s)", $qq->stringify)); URI-Query-0.10/t/07_unesc.t0000644000175000017500000000222311516342340014237 0ustar gavingavin# Test input unescaping # # Fixing bug #35170: https://rt.cpan.org/Public/Bug/Display.html?id=35170 # # RFC2396: Within a query component, the characters ";", "/", "?", # ":", "@", "&", "=", "+", ",", and "$" are reserved. # use strict; use Test::More; BEGIN { use_ok( 'URI::Query' ) } my $data_esc = { group => 'prod%2Cinfra%2Ctest', 'op%3Aset' => 'x%3Dy', }; my $data_unesc = { group => 'prod,infra,test', 'op:set' => 'x=y', }; my $qs_esc = 'group=prod%2Cinfra%2Ctest&op%3Aset=x%3Dy'; my ($qq, $qs); ok($qq = URI::Query->new($qs_esc), 'qq string constructor ok'); is_deeply(scalar $qq->hash, $data_unesc, '$qq->hash keys and values are unescaped'); is("$qq", $qs_esc, 'stringified keys/values escaped ok'); ok($qq = URI::Query->new($data_esc), 'qq hashref constructor ok'); is_deeply(scalar $qq->hash, $data_unesc, '$qq->hash keys and values are unescaped'); is("$qq", $qs_esc, 'stringified keys/values escaped ok'); ok($qq = URI::Query->new(%$data_esc), 'qq hash constructor ok'); is_deeply(scalar $qq->hash, $data_unesc, '$qq->hash keys and values are unescaped'); is("$qq", $qs_esc, 'stringified keys/values escaped ok'); done_testing; URI-Query-0.10/t/04_revert.t0000644000175000017500000000074311516332314014433 0ustar gavingavin# Test URI::Query revert() use strict; use vars q($count); BEGIN { $count = 4 } use Test::More tests => $count; use_ok('URI::Query'); my $qq; ok($qq = URI::Query->new('foo=1&foo=2&bar=3;bog=abc;bar=7;fluffy=3'), "constructor ok"); my $str1 = $qq->stringify; # Strip $qq->strip(qw(foo fluffy)); my $str2 = $qq->stringify; isnt($str1, $str2, "strings different after strip"); # Revert $qq->revert; my $str3 = $qq->stringify; is($str1, $str3, "strings identical after revert"); URI-Query-0.10/Makefile.PL0000644000175000017500000000076511516345573014162 0ustar gavingavinuse 5.00503; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'URI::Query', 'VERSION_FROM' => 'Query.pm', # finds $VERSION 'PREREQ_PM' => { URI => 1.31, Test::More => 0.88, }, # e.g., Module::Name => 1.1 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (AUTHOR => 'Gavin Carr ') : ()), ); URI-Query-0.10/MANIFEST0000644000175000017500000000035111516375746013335 0ustar gavingavinMakefile.PL MANIFEST MANIFEST.SKIP Query.pm README t/01_constructor.t t/02_methods.t t/03_hash.t t/04_revert.t t/05_sep.t t/06_eq.t t/07_unesc.t t/t03/hash t/t03/hash_arrayref t/t03/hidden t/t05/default t/t05/explicit t/t05/standard URI-Query-0.10/README0000644000175000017500000000164611516331243013054 0ustar gavingavinURI/Query ========= URI::Query provides simple URI query string manipulation, allowing you to create and manipulate URI query strings from GET and POST requests in web applications. This is primarily useful for creating links where you wish to preserve some subset of the parameters to the current request, and potentially add or replace others. Given a query string this is doable with regexes, of course, but making sure you get the anchoring and escaping right is tedious and error-prone - using this module is much simpler. INSTALLATION Installation is the standard perl install tango: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: URI::Escape COPYRIGHT AND LICENCE Copyright (C) 2004-2005 Gavin Carr. All Rights Reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. URI-Query-0.10/ChangeLog0000644000175000017500000000160512023261051013732 0ustar gavingavinChangeLog --------- [2012-09-10] * Bump $VERSION to 0.10. * Remove value-based reordering in stringification. [2011-08-02] [2011-01-27] * Bump version to 0.09. * Change t/t05/default from symlink to dup, to avoid problems on windows etc. * Add ChangeLog to .gitignore. [2011-01-21] * Fix typo in URI::Query pod. * MANIFEST tweakage. * Add lots of nice pod. * Add support for cgi-packed-scalar-values, update unit tests. * Perldoc updates, and trailing whitespace pruning. * Add .gitignore; bump Test::More requirement to 0.88. * Add _init_from_arrayref method to Query, and unescape keys/values. * Add unescaping of keys and values in parse_qs, and unit test. * Remove all old arch-tags. [2010-01-20] * Upgrade use of uri_escape to uri_escape_utf8; bump version to 0.07. [2007-09-11] * Sort output hash key order for deterministic testing; bump to version 0.06. * Initial import, version 0.05. URI-Query-0.10/Query.pm0000644000175000017500000003037312023260640013632 0ustar gavingavin# # Class providing URI query string manipulation # package URI::Query; use 5.00503; use strict; use URI::Escape qw(uri_escape_utf8 uri_unescape); use overload '""' => \&stringify, 'eq' => sub { $_[0]->stringify eq $_[1]->stringify }, 'ne' => sub { $_[0]->stringify ne $_[1]->stringify }; use vars q($VERSION); $VERSION = '0.10'; # ------------------------------------------------------------------------- # Remove all occurrences of the given parameters sub strip { my $self = shift; delete $self->{qq}->{$_} foreach @_; $self } # Remove all parameters except those given sub strip_except { my $self = shift; my %keep = map { $_ => 1 } @_; foreach (keys %{$self->{qq}}) { delete $self->{qq}->{$_} unless $keep{$_}; } $self } # Remove all empty/undefined parameters sub strip_null { my $self = shift; foreach (keys %{$self->{qq}}) { delete $self->{qq}->{$_} unless @{$self->{qq}->{$_}}; } $self } # Replace all occurrences of the given parameters sub replace { my $self = shift; my %arg = @_; for my $key (keys %arg) { $self->{qq}->{$key} = []; if (ref $arg{$key} eq 'ARRAY') { push @{$self->{qq}->{$key}}, $_ foreach @{$arg{$key}}; } else { push @{$self->{qq}->{$key}}, $arg{$key}; } } $self } # Return the stringified qq hash sub stringify { my $self = shift; my $sep = shift || $self->{sep} || '&'; my @out = (); for my $key (sort keys %{$self->{qq}}) { for my $value (@{$self->{qq}->{$key}}) { push @out, sprintf("%s=%s", uri_escape_utf8($key), uri_escape_utf8($value)); } } join $sep, @out; } sub revert { my $self = shift; # Revert qq to the qq_orig hashref $self->{qq} = $self->_deepcopy($self->{qq_orig}); $self } # ------------------------------------------------------------------------- # Convenience methods # Return the current qq hash(ref) with one-elt arrays flattened sub hash { my $self = shift; my %qq = %{$self->{qq}}; # Flatten one element arrays for (sort keys %qq) { $qq{$_} = $qq{$_}->[0] if @{$qq{$_}} == 1; } return wantarray ? %qq : \%qq; } # Return the current qq hash(ref) with all elements as arrayrefs sub hash_arrayref { my $self = shift; my %qq = %{$self->{qq}}; # (Don't flatten one element arrays) return wantarray ? %qq : \%qq; } # Return the current query as a string of html hidden input tags sub hidden { my $self = shift; my $str = ''; for my $key (sort keys %{$self->{qq}}) { for my $value (@{$self->{qq}->{$key}}) { $str .= qq(\n); } } return $str; } # ------------------------------------------------------------------------- # Set the output separator to use by default sub separator { my $self = shift; $self->{sep} = shift; } # Deep copy routine, originally swiped from a Randal Schwartz column sub _deepcopy { my ($self, $this) = @_; if (! ref $this) { return $this; } elsif (ref $this eq "ARRAY") { return [map $self->_deepcopy($_), @$this]; } elsif (ref $this eq "HASH") { return {map { $_ => $self->_deepcopy($this->{$_}) } keys %$this}; } elsif (ref $this eq "CODE") { return $this; } elsif (sprintf $this) { # Object! As a last resort, try copying the stringification value return sprintf $this; } else { die "what type is $_? (" . ref($this) . ")"; } } # Parse query string, storing as hash (qq) of key => arrayref pairs sub _parse_qs { my $self = shift; my $qs = shift; for (split /[&;]/, $qs) { my ($key, $value) = map { uri_unescape($_) } split /=/, $_, 2; $self->{qq}->{$key} ||= []; push @{$self->{qq}->{$key}}, $value if defined $value && $value ne ''; } $self } # Process arrayref arguments into hash (qq) of key => arrayref pairs sub _init_from_arrayref { my ($self, $arrayref) = @_; while (@$arrayref) { my $key = shift @$arrayref; my $value = shift @$arrayref; my $key_unesc = uri_unescape($key); $self->{qq}->{$key_unesc} ||= []; if (defined $value && $value ne '') { my @values; if (! ref $value) { @values = split "\0", $value; } elsif (ref $value eq 'ARRAY') { @values = @$value; } else { die "Invalid value found: $value. Not string or arrayref!"; } push @{$self->{qq}->{$key_unesc}}, map { uri_unescape($_) } @values; } } } # Constructor - either new($qs) where $qs is a scalar query string or a # a hashref of key => value pairs, or new(key => val, key => val); # In the array form, keys can repeat, and/or values can be arrayrefs. sub new { my $class = shift; my $self = bless { qq => {} }, $class; if (@_ == 1 && ! ref $_[0] && $_[0]) { $self->_parse_qs($_[0]); } elsif (@_ == 1 && ref $_[0] eq 'HASH') { $self->_init_from_arrayref([ %{$_[0]} ]); } elsif (scalar(@_) % 2 == 0) { $self->_init_from_arrayref(\@_); } # Clone the qq hashref to allow reversion $self->{qq_orig} = $self->_deepcopy($self->{qq}); return $self; } # ------------------------------------------------------------------------- 1; =head1 NAME URI::Query - class providing URI query string manipulation =head1 SYNOPSIS # Constructor - using a GET query string $qq = URI::Query->new($query_string); # OR Constructor - using a hashref of key => value parameters $qq = URI::Query->new($cgi->Vars); # OR Constructor - using an array of successive keys and values $qq = URI::Query->new(@params); # Revert back to the initial constructor state (to do it all again) $qq->revert; # Remove all occurrences of the given parameters $qq->strip('page', 'next'); # Remove all parameters except the given ones $qq->strip_except('pagesize', 'order'); # Remove all empty/undefined parameters $qq->strip_null; # Replace all occurrences of the given parameters $qq->replace(page => $page, foo => 'bar'); # Set the argument separator to use for output (default: unescaped '&') $qq->separator(';'); # Output the current query string print "$qq"; # OR $qq->stringify; # Stringify with explicit argument separator $qq->stringify(';'); # Get a flattened hash/hashref of the current parameters # (single item parameters as scalars, multiples as an arrayref) my %qq = $qq->hash; # Get a non-flattened hash/hashref of the current parameters # (parameter => arrayref of values) my %qq = $qq->hash_arrayref; # Get the current query string as a set of hidden input tags print $qq->hidden; =head1 DESCRIPTION URI::Query provides simple URI query string manipulation, allowing you to create and manipulate URI query strings from GET and POST requests in web applications. This is primarily useful for creating links where you wish to preserve some subset of the parameters to the current request, and potentially add or replace others. Given a query string this is doable with regexes, of course, but making sure you get the anchoring and escaping right is tedious and error-prone - this module is simpler. =head2 CONSTRUCTOR URI::Query objects can be constructed from scalar query strings ('foo=1&bar=2&bar=3'), from a hashref which has parameters as keys, and values either as scalars or arrayrefs of scalars (to handle the case of parameters with multiple values e.g. { foo => '1', bar => [ '2', '3' ] }), or arrays composed of successive parameters-value pairs e.g. ('foo', '1', 'bar', '2', 'bar', '3'). For instance: # Constructor - using a GET query string $qq = URI::Query->new($query_string); # Constructor - using an array of successive keys and values $qq = URI::Query->new(@params); # Constructor - using a hashref of key => value parameters, # where values are either scalars or arrayrefs of scalars $qq = URI::Query->new($cgi->Vars); URI::Query also handles L-style hashrefs, where multiple values are packed into a single string, separated by the "\0" (null) character. All keys and values are URI unescaped at construction time, and are stored and referenced unescaped. So a query string like: group=prod%2Cinfra%2Ctest&op%3Aset=x%3Dy is stored as: 'group' => 'prod,infra,test' 'op:set' => 'x=y' You should always use the unescaped/normal variants in methods i.e. $qq->replace('op:set' => 'x=z'); NOT: $qq->replace('op%3Aset' => 'x%3Dz'); =head2 MODIFIER METHODS All modifier methods change the state of the URI::Query object in some way, and return $self, so they can be used in chained style e.g. $qq->revert->strip('foo')->replace(bar => 123); Note that URI::Query stashes a copy of the parameter set that existed at construction time, so that any changes made by these methods can be rolled back using 'revert()'. So you don't (usually) need to keep multiple copies around to handle incompatible changes. =over 4 =item revert() Revert the current parameter set back to that originally given at construction time i.e. discard all changes made since construction. =item strip($param1, $param2, ...) Remove all occurrences of the given parameters and their values from the current parameter set. =item strip_except($param1, $param2, ...) Remove all parameters EXCEPT those given from the current parameter set. =item strip_null() Remove all parameters that have a value of undef from the current parameter set. =item replace($param1 => $value1, $param2, $value2, ...) Replace the values of the given parameters in the current parameter set with these new ones. Parameter names must be scalars, but values can be either scalars or arrayrefs of scalars, when multiple values are desired. Note that 'replace' can also be used to add or append, since there's no requirement that the parameters already exist in the current parameter set. =item separator($separator) Set the argument separator to use for output. Default: '&'. =back =head2 OUTPUT METHODS =over 4 =item "$qq", stringify(), stringify($separator) Return the current parameter set as a conventional param=value query string, using $separator as the separator if given. e.g. foo=1&bar=2&bar=3 Note that all parameters and values are URI escaped by stringify(), so that query-string reserved characters do not occur within elements. For instance, a parameter set of: 'group' => 'prod,infra,test' 'op:set' => 'x=y' will be stringified as: group=prod%2Cinfra%2Ctest&op%3Aset=x%3Dy =item hash() Return a hash (in list context) or hashref (in scalar context) of the current parameter set. Single-item parameters have scalar values, while while multiple-item parameters have arrayref values e.g. { foo => 1, bar => [ 2, 3 ], } =item hash_arrayref() Return a hash (in list context) or hashref (in scalar context) of the current parameter set. All values are returned as arrayrefs, including those with single values e.g. { foo => [ 1 ], bar => [ 2, 3 ], } =item hidden() Returns the current parameter set as a concatenated string of hidden input tags, one per parameter-value e.g. =back =head1 BUGS AND CAVEATS Please report bugs and/or feature requests to C, or through the web interface at L. Should allow unescaping of input to be turned off, for situations in which it's already been done. Please let me know if you find you actually need this. I don't think it makes sense on the output side though, since you need to understand the structure of the query to escape elements correctly. =head1 PATCHES URI::Query code lives at L. Patches / pull requests welcome! =head1 AUTHOR Gavin Carr =head1 COPYRIGHT Copyright 2004-2011, Gavin Carr. All Rights Reserved. This program is free software. You may copy or redistribute it under the same terms as perl itself. =cut # vim:sw=4:et