blib/lib/AppConfig/CGI.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 40 | 52 | 76.9 |
branch | 10 | 20 | 50.0 |
condition | n/a | ||
subroutine | 7 | 8 | 87.5 |
pod | 0 | 2 | 0.0 |
total | 57 | 82 | 69.5 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | #============================================================================ | ||||||
2 | # | ||||||
3 | # AppConfig::CGI.pm | ||||||
4 | # | ||||||
5 | # Perl5 module to provide a CGI interface to AppConfig. Internal variables | ||||||
6 | # may be set through the CGI "arguments" appended to a URL. | ||||||
7 | # | ||||||
8 | # Written by Andy Wardley |
||||||
9 | # | ||||||
10 | # Copyright (C) 1997-2003 Andy Wardley. All Rights Reserved. | ||||||
11 | # Copyright (C) 1997,1998 Canon Research Centre Europe Ltd. | ||||||
12 | # | ||||||
13 | #============================================================================ | ||||||
14 | |||||||
15 | package AppConfig::CGI; | ||||||
16 | 1 | 1 | 433 | use 5.006; | |||
1 | 2 | ||||||
1 | 33 | ||||||
17 | 1 | 1 | 4 | use strict; | |||
1 | 1 | ||||||
1 | 22 | ||||||
18 | 1 | 1 | 3 | use warnings; | |||
1 | 2 | ||||||
1 | 19 | ||||||
19 | 1 | 1 | 4 | use AppConfig::State; | |||
1 | 1 | ||||||
1 | 373 | ||||||
20 | our $VERSION = '1.71'; | ||||||
21 | |||||||
22 | |||||||
23 | #------------------------------------------------------------------------ | ||||||
24 | # new($state, $query) | ||||||
25 | # | ||||||
26 | # Module constructor. The first, mandatory parameter should be a | ||||||
27 | # reference to an AppConfig::State object to which all actions should | ||||||
28 | # be applied. The second parameter may be a string containing a CGI | ||||||
29 | # QUERY_STRING which is then passed to parse() to process. If no second | ||||||
30 | # parameter is specifiied then the parse() process is skipped. | ||||||
31 | # | ||||||
32 | # Returns a reference to a newly created AppConfig::CGI object. | ||||||
33 | #------------------------------------------------------------------------ | ||||||
34 | |||||||
35 | sub new { | ||||||
36 | 1 | 1 | 0 | 9 | my $class = shift; | ||
37 | 1 | 2 | my $state = shift; | ||||
38 | 1 | 4 | my $self = { | ||||
39 | STATE => $state, # AppConfig::State ref | ||||||
40 | DEBUG => $state->_debug(), # store local copy of debug | ||||||
41 | PEDANTIC => $state->_pedantic, # and pedantic flags | ||||||
42 | }; | ||||||
43 | 1 | 3 | bless $self, $class; | ||||
44 | |||||||
45 | # call parse(@_) to parse any arg list passed | ||||||
46 | 1 | 50 | 2 | $self->parse(@_) | |||
47 | if @_; | ||||||
48 | |||||||
49 | 1 | 2 | return $self; | ||||
50 | } | ||||||
51 | |||||||
52 | |||||||
53 | #------------------------------------------------------------------------ | ||||||
54 | # parse($query) | ||||||
55 | # | ||||||
56 | # Method used to parse a CGI QUERY_STRING and set internal variable | ||||||
57 | # values accordingly. If a query is not passed as the first parameter, | ||||||
58 | # then _get_cgi_query() is called to try to determine the query by | ||||||
59 | # examing the environment as per CGI protocol. | ||||||
60 | # | ||||||
61 | # Returns 0 if one or more errors or warnings were raised or 1 if the | ||||||
62 | # string parsed successfully. | ||||||
63 | #------------------------------------------------------------------------ | ||||||
64 | |||||||
65 | sub parse { | ||||||
66 | 2 | 2 | 0 | 254 | my $self = shift; | ||
67 | 2 | 2 | my $query = shift; | ||||
68 | 2 | 2 | my $warnings = 0; | ||||
69 | 2 | 2 | my ($variable, $value, $nargs); | ||||
70 | |||||||
71 | |||||||
72 | # take a local copy of the state to avoid much hash dereferencing | ||||||
73 | 2 | 9 | my ($state, $debug, $pedantic) = @$self{ qw( STATE DEBUG PEDANTIC ) }; | ||||
74 | |||||||
75 | # get the cgi query if not defined | ||||||
76 | $query = $ENV{ QUERY_STRING } | ||||||
77 | 2 | 100 | 5 | unless defined $query; | |||
78 | |||||||
79 | # no query to process | ||||||
80 | 2 | 50 | 5 | return 1 unless defined $query; | |||
81 | |||||||
82 | # we want to install a custom error handler into the AppConfig::State | ||||||
83 | # which appends filename and line info to error messages and then | ||||||
84 | # calls the previous handler; we start by taking a copy of the | ||||||
85 | # current handler.. | ||||||
86 | 2 | 7 | my $errhandler = $state->_ehandler(); | ||||
87 | |||||||
88 | # install a closure as a new error handler | ||||||
89 | $state->_ehandler( | ||||||
90 | sub { | ||||||
91 | # modify the error message | ||||||
92 | 0 | 0 | 0 | my $format = shift; | |||
93 | 0 | 0 | $format =~ s/</g; | ||||
94 | 0 | 0 | $format =~ s/>/>/g; | ||||
95 | 0 | 0 | $format = " \n[ AppConfig::CGI error: $format ] \n \n"; |
||||
96 | # send error to stdout for delivery to web client | ||||||
97 | 0 | 0 | printf($format, @_); | ||||
98 | } | ||||||
99 | 2 | 13 | ); | ||||
100 | |||||||
101 | |||||||
102 | 2 | 29 | PARAM: foreach (split('&', $query)) { | ||||
103 | |||||||
104 | # extract parameter and value from query token | ||||||
105 | 6 | 10 | ($variable, $value) = map { _unescape($_) } split('='); | ||||
11 | 13 | ||||||
106 | |||||||
107 | # check an argument was provided if one was expected | ||||||
108 | 6 | 100 | 27 | if ($nargs = $state->_argcount($variable)) { | |||
109 | 4 | 50 | 5 | unless (defined $value) { | |||
110 | 0 | 0 | $state->_error("$variable expects an argument"); | ||||
111 | 0 | 0 | $warnings++; | ||||
112 | 0 | 0 | 0 | last PARAM if $pedantic; | |||
113 | 0 | 0 | next; | ||||
114 | } | ||||||
115 | } | ||||||
116 | # default an undefined value to 1 if ARGCOUNT_NONE | ||||||
117 | else { | ||||||
118 | 2 | 50 | 5 | $value = 1 unless defined $value; | |||
119 | } | ||||||
120 | |||||||
121 | # set the variable, noting any error | ||||||
122 | 6 | 50 | 13 | unless ($state->set($variable, $value)) { | |||
123 | 0 | 0 | $warnings++; | ||||
124 | 0 | 0 | 0 | last PARAM if $pedantic; | |||
125 | } | ||||||
126 | } | ||||||
127 | |||||||
128 | # restore original error handler | ||||||
129 | 2 | 5 | $state->_ehandler($errhandler); | ||||
130 | |||||||
131 | # return $warnings => 0, $success => 1 | ||||||
132 | 2 | 50 | 8 | return $warnings ? 0 : 1; | |||
133 | } | ||||||
134 | |||||||
135 | |||||||
136 | |||||||
137 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||||
138 | # The following sub-routine was lifted from Lincoln Stein's CGI.pm | ||||||
139 | # module, version 2.36. Name has been prefixed by a '_'. | ||||||
140 | |||||||
141 | # unescape URL-encoded data | ||||||
142 | sub _unescape { | ||||||
143 | 11 | 11 | 9 | my($todecode) = @_; | |||
144 | 11 | 9 | $todecode =~ tr/+/ /; # pluses become spaces | ||||
145 | 11 | 15 | $todecode =~ s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge; | ||||
0 | 0 | ||||||
146 | 11 | 16 | return $todecode; | ||||
147 | } | ||||||
148 | |||||||
149 | # | ||||||
150 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||||
151 | |||||||
152 | |||||||
153 | |||||||
154 | |||||||
155 | 1; | ||||||
156 | |||||||
157 | __END__ |