File Coverage

blib/lib/CGI/Deurl.pm
Criterion Covered Total %
statement 32 111 28.8
branch 8 54 14.8
condition 2 18 11.1
subroutine 3 9 33.3
pod 7 7 100.0
total 52 199 26.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             CGI::Deurl.pm - a CGI parameter decoding package
4              
5             version 1.08
6              
7             =head1 SYNOPSIS
8              
9             use CGI::Deurl as => 'q';
10             ...
11             print "$q{ParamName}\n";
12              
13             =head1 DESCRIPTION
14              
15             This is a little module made for CGI scripting. It decodes the parameters
16             passed to the CGI. It does nothing more, so it's much smaller and loads
17             more quickly than CGI.pm.
18              
19             Since version 0.04 it also exports the C, C and C
20             functions so that you are able to decode not only the parameters your
21             CGI got, but also an arbitrary string.
22              
23             =head2 Reading CGI query
24              
25             The module can take the arguments from several sources. CGI::Deurl tests the environmental
26             variable 'REQUEST_METHOD' to find the arguments.
27              
28             =over 4
29              
30             =item REQUEST_METHOD=POST
31              
32             CGI::Deurl slurps in it's STDIN and parses it, then it tests
33             $ENV{QUERY_STRING} and if defined parses the data as well.
34              
35             =item REQUEST_METHOD=GET
36              
37             CGI::Deurl reads $ENV{QUERY_STRING} and parses the contents.
38              
39             =item REQUEST_METHOD not defined
40              
41             CGI::Deurl tests ARGV and parses all it's arguments.
42             If it didn't find any args it reads it's STDIN line by line
43             until EOF and parses all the lines. This is handy if you want
44             to test a CGI script from command prompt. You may specify the parameters
45             either on the command line or enter them after the script starts to run.
46              
47             =back
48              
49             If you C the module doesn't look for the parameters
50             and just exports the functions. This is handy if you use CGI::Deurl.pm in a
51             script that is not a CGI.
52              
53             =head2 Using query variables
54              
55             The data are stored in a hash C<%CGI::Deurl::query>, but CGI::Deurl provides
56             two ways to specify otherwise. They may be stored either in a hash
57             you specify or be exported into a package.
58              
59             =head2 "use" statement options
60              
61             =over 4
62              
63             =item lc
64              
65             If you use the option 'lc' all names of the parameters are converted
66             to lowercase. This way you may get case insensitive parameters.
67              
68             =item uc
69              
70             This option is similar to 'lc'. It converts the names to uppercase.
71              
72             =item as variable
73              
74             If you use CGI::Deurl qw(as variablename); CGI::Deurl uses variable
75             %variablename from package main
76             to store the data (%CGI::Deurl::query works as well, this is just
77             a nickname).
78              
79             =item use CGI::Deurl export;
80              
81             All the query variables are exported into package CGI::Deurl.
82             That means that if the query was "?x=5&y=24", you can
83             use $CGI::Deurl::x + $CGI::Deurl::y. Again %CGI::Deurl::query works
84             as usual.
85              
86             =item use CGI::Deurl export Package;
87              
88             All the query values are exported into Package.
89             That means that if the query was "?x=5&y=24", you can
90             use $Package::x + $Package::y. Again %CGI::Deurl::query works
91             as usual.
92              
93             =item use CGI::Deurl NOTCGI;
94              
95             Do not read any query. This option should be first or directly after the
96             &=....
97              
98             =item use CGI::Deurl '&=.'
99              
100             You may change the character used to separate the parameters. Use any
101             character or string you want. This must be the first option if present!
102              
103             The parameter separator is stored in variable $CGI::Deurl::ParamSeparator.
104             You may change it any time you want.
105              
106             =item use CGI::Deurl 'JOIN' => ';';
107              
108             =item use CGI::Deurl 'JOIN' , 'file' => ';', '-all' => ',';
109              
110             This option will cause a call to joinquery(), all folowing arguments
111             will be passed to this function, so this switch has to be the last one!
112              
113             =back
114              
115             =head2 Parsing query
116              
117             If the argument in the query in in the form "name=value".
118             $CGI::Deurl::query{name} is set to value. If it is just "value"
119             (say myscript.pl?one&two), $CGI::Deurl::query{0}='one' and
120             $CGI::Deurl::query{1}='two'. These kinds of parameters can be intermixed.
121              
122             If there is more than one occurence of a variable,
123             $CGI::Deurl::query{name} contains a refference to an array containing
124             all the values.
125              
126             Ex.
127             ?x=one&y=two&x=three
128             =>
129             $CGI::Deurl::query{x}=['one','three'];
130             $CGI::Deurl::query{y}='two';
131              
132             !!! If you 'export' such a variable it's not exported as a refference
133             but as a real array!!!
134              
135             That is if you use CGI::Deurl qw(export CGI::Deurl) you will get :
136             @CGI::Deurl::x = ('one','three');
137             $CGI::Deurl::y = 'two';
138              
139             ! All changes made to $CGI::Deurl::variable are visible in
140             $CGI::Deurl::query{variable} and vice versa.
141              
142             =head2 Functions
143              
144             =over 4
145              
146             =item deurl
147              
148             =item deurl $string, \%hash
149              
150             Decodes the string as if it was an ordinary CGI query.
151             The %hash then contains all CGI parameters specified there.
152              
153             Ex.
154             deurl('a=5&b=13',\%query);
155             leads to :
156             $query{a} = 5;
157             $query{b} = 13;
158              
159             =item deurlstr
160              
161             =item $decodedstring = deurlstr $string
162              
163             Decodes the string as if it was a CGI parameter value.
164             That is ist translates all '+' to ' ' and all
165             %xx to the corresponding character. It doesn't care about
166             '&' nor '='.
167              
168             Ex.
169             $result = deurlstr 'How+are+you%3F';
170             leads to:
171             $result = 'How are you?'
172             !!! but notice that !!!
173             $result = deurlstr('a=5&b=13%25');
174             gives:
175             $result = 'a=5&b=13%'
176             !!!!!!
177              
178             =item deurlarr
179              
180             =item @result = deurlarr $string;
181              
182             Decodes the string as a sequence of unnamed CGI parameters,
183             that is it supposes that the $string looks somehow like this :
184             'param1¶m2&par%61m3'. It doesn't care about '='
185              
186             Ex.
187             @result = deurlarr 'How&are+you%3f';
188             leads to
189             @result = ( 'How', 'are you?');
190              
191             @result = deurlstr('a=5&b=13%25');
192             gives:
193             @result = ( 'a=5', 'b=13%');
194             which may but may not be what you want.
195              
196             =item CGI::Deurl::load
197              
198             Instructs CGI::Deurl to load the CGI data from QUERY_STRING, @ARGV or .
199             The parameters are the same as for the C
200             Usefull only if you C, but later on you find out you want
201             the CGI parameters.
202              
203             =item joinquery %query, $delimiter
204              
205             =item joinquery %query, $key => $delimiter [, ...]
206              
207             If the query contains several values for a singe variable, these values
208             are stored as an array in the hash. This function joins them using the delimiter
209             you specify. You may either join all the keys using the same delimiter, or use different
210             delimiters for each key. You may even leave some values intact.
211              
212             Ex.:
213             joinquery %query, $delimiter
214             it will join all multivalues it finds using the $delimiter.
215              
216             joinquery %query, 'key' => $delimiter
217             it will join only the multivalue for 'key'. All other values will remain
218             the same.
219              
220             joinquery %query, 'key' => ';', '-all' => ' '
221             it will join the multivalue for 'key' by semicolons. All other values will
222             be joined using spaces.
223              
224             You may call this function from the "use" statement.
225              
226             =item $CGI::Deurl::offline
227              
228             If the script was called from the command line instead of as a CGI,
229             this variable contains 1. Otherwise it's undefined.
230              
231             =back
232              
233             =cut
234              
235              
236             package CGI::Deurl;
237             require Exporter;
238             @EXPORT=qw(deurl deurlstr deurlarr joinquery);
239 1     1   1344 use vars qw'$VERSION $query $string';
  1         2  
  1         2138  
240             $VERSION='1.08';
241              
242             $ParamSeparator = '&' unless $ParamSeparator;
243              
244             sub joinquery (\%@);
245              
246             sub export {
247 0     0 1 0 my $pkg=$_[0];
248 0 0       0 $pkg.='::' if $pkg;
249 0         0 my $key;
250 0         0 foreach $key (keys %CGI::Deurl::query) {
251 0 0       0 if (ref ${CGI::Deurl::query{$key}}) {
252 0         0 *{$pkg.$key} = ${CGI::Deurl::query{$key}};
  0         0  
253             } else {
254 0         0 *{$pkg.$key} = \${CGI::Deurl::query{$key}};
  0         0  
255             }
256             }
257             }
258              
259             sub as {
260 0     0 1 0 my $name = $_[0];
261             package main;
262 0         0 *{$name} = *CGI::Deurl::query;
  0         0  
263             package CGI::Deurl;
264             }
265              
266             sub import {
267 1     1   9 my $caller_pack = caller;
268 1         4 my( $pkg )= shift;
269              
270 1         122 Exporter::export( $pkg, $caller_pack, qw(deurl deurlstr deurlarr joinquery));
271              
272 1 50       5 if (defined $_[0]) {
273 1 50       3 if ($_[0] =~ /^&=(.+)$/) {shift; $ParamSeparator="\Q$1"}
  0         0  
  0         0  
274 1 50 33     3111 return if ($_[0] eq 'NOTCGI' or $_[0] eq 'NOCGI');
275 0 0       0 if ($_[0] =~ /^&=(.+)$/) {shift; $ParamSeparator="\Q$1"}
  0         0  
  0         0  
276             }
277              
278 0         0 &CGI::Deurl::load(@_);
279             }
280              
281             sub load {
282 0     0 1 0 my $data;
283 0 0 0     0 if (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq "POST") {
    0 0        
    0          
    0          
284 0         0 read STDIN , $data , $ENV{CONTENT_LENGTH} ,0;
285 0 0       0 if ($ENV{QUERY_STRING}) {
286 0         0 $data .= $ParamSeparator . $ENV{QUERY_STRING};
287             }
288             } elsif (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq "GET") {
289 0         0 $data=$ENV{QUERY_STRING};
290             } elsif (defined $ENV{REQUEST_METHOD}) {
291 0         0 print "Status: 405 Method Not Allowed\r\n\r\n";
292 0         0 exit;
293             } elsif ($#ARGV >= 0) {
294 0         0 $CGI::Deurl::offline = 1;
295 0         0 $data=join $ParamSeparator, @ARGV;
296             } else {
297 0 0       0 print STDERR "\t\n";
298 0         0 $CGI::Deurl::offline = 1;
299              
300 0         0 my @lines=;
301 0         0 chomp @lines;
302 0         0 $data=join $ParamSeparator, @lines;
303             }
304              
305 0 0 0     0 return unless (defined $data and $data ne '');
306              
307 0         0 deurl($data,\%CGI::Deurl::query);
308 0         0 my $i;
309 0         0 for($i=0;$i<=$#_;$i++) {
310 0 0       0 if (lc $_[$i] eq 'lc') {
    0          
    0          
    0          
    0          
311 0         0 my (%hash,$key,$value);
312 0         0 while (($key,$value) = each %CGI::Deurl::query) {
313 0         0 $hash{lc $key} = $value;
314             }
315 0         0 %CGI::Deurl::query = %hash;
316             } elsif (lc $_[$i] eq 'uc') {
317 0         0 my (%hash,$key,$value);
318 0         0 while (($key,$value) = each %CGI::Deurl::query) {
319 0         0 $hash{uc $key} = $value;
320             }
321 0         0 %CGI::Deurl::query = %hash;
322             } elsif (lc $_[$i] eq 'as') {
323 0         0 $i++;
324 0         0 CGI::Deurl::as $_[$i];
325             } elsif (lc $_[$i] eq 'export') {
326 0         0 CGI::Deurl::export($_[++$i]);
327             } elsif ($_[$i] =~ /^join$/i) {
328 0 0       0 if (ref $_[++$i] eq 'ARRAY') {
329 0         0 joinquery(%CGI::Deurl::query, @{$_[$i]});
  0         0  
330             } else {
331 0         0 joinquery(%CGI::Deurl::query, $_[$i]);
332             }
333             } else {
334 0         0 die "Unknown export directive $_[$i] in CGI::Deurl.pm!\n"
335             }
336             }
337             }
338              
339             sub deurl ($$) {
340 3     3 1 155 my ($data,$hash)=@_;
341 3 50 33     19 die "deurl: ussage deurl($string, \%hash)\n" unless ($data and ref $hash eq 'HASH');
342 3         7 $data=~s/\?$//;
343 3         4 my $i=0;
344              
345 3         25 my @items = grep {!/^$/} (split /$ParamSeparator/o, $data);
  13         35  
346 3         6 my $thing;
347              
348 3         5 foreach $thing (@items) {
349              
350 12         41 my @res = $thing=~/^(.*?)=(.*)$/;
351 12         13 my ($name,$value,@value);
352              
353 12 100       24 if ($#res<=0) {
354 6         7 $name = $i++;
355 6         10 $value = $thing;
356             } else {
357 6         10 ($name,$value) = @res;
358             }
359 12 50       25 next unless $value ne '';
360              
361 12         15 $name=~tr/+/ /;
362 12         20 $name =~ s/%(\w\w)/chr(hex $1)/ge;
  0         0  
363              
364 12         15 $value=~tr/+/ /;
365 12         25 $value =~ s/%(\w\w)/chr(hex $1)/ge;
  24         66  
366              
367 12 50       19 if ($hash->{$name}) {
368 0 0       0 if (ref $hash->{$name}) {
369 0         0 push @{$hash->{$name}},$value;
  0         0  
370             } else {
371 0         0 $hash->{$name} = [ $hash->{$name}, $value];
372             }
373             } else {
374 12         41 $hash->{$name} = $value;
375             }
376              
377             }
378 3         10 1;
379             }
380              
381             sub deurlstr ($) {
382 0     0 1   my $value=$_[0];
383 0           $value=~tr/+/ /;
384 0           $value =~ s/%(\w\w)/chr(hex $1)/ge;
  0            
385 0           $value;
386             }
387              
388             sub deurlarr ($) {
389 0     0 1   my @value = split /$ParamSeparator/o, $_[0];
390 0           foreach (@value) {
391 0           tr/+/ /;
392 0           s/%(\w\w)/chr(hex $1)/ge;
  0            
393             }
394 0           return @value;
395             }
396              
397             sub joinquery (\%@) {
398 0     0 1   my $query = shift;
399             #{
400             #local $"=", ";
401             #print "(@_)\n";
402             #}
403              
404 0 0         if (@_ == 1) {
405 0           @_ = ('-all',$_[0]);
406             }
407 0           my %joins = @_;
408 0           while (($key,$value) = each %$query) {
409 0 0         if (ref $value eq 'ARRAY') {
410 0           my $join;
411 0 0 0       if ($join = $joins{$key} or $join = $joins{'-all'}) {
412 0           $query->{$key} = join $join, @$value;
413             }
414             }
415             }
416             }
417              
418             1;
419             __END__