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