| 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 | 485 | use strict; | |||
| 1 | 1 | ||||||
| 1 | 33 | ||||||
| 17 | 1 | 1 | 3 | use warnings; | |||
| 1 | 2 | ||||||
| 1 | 23 | ||||||
| 18 | 1 | 1 | 3 | use AppConfig::State; | |||
| 1 | 1 | ||||||
| 1 | 406 | ||||||
| 19 | our $VERSION = '1.70'; | ||||||
| 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 | 4 | 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 | 414 | $self->parse(@_) | |||
| 46 | if @_; | ||||||
| 47 | |||||||
| 48 | 1 | 3 | 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 | 251 | my $self = shift; | ||
| 66 | 2 | 3 | my $query = shift; | ||||
| 67 | 2 | 3 | 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 | 7 | 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 | 31 | unless defined $query; | |||
| 77 | |||||||
| 78 | # no query to process | ||||||
| 79 | 2 | 50 | 5 | 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 | 5 | 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 | 12 | ); | ||||
| 99 | |||||||
| 100 | |||||||
| 101 | 2 | 7 | PARAM: foreach (split('&', $query)) { | ||||
| 102 | |||||||
| 103 | # extract parameter and value from query token | ||||||
| 104 | 6 | 9 | ($variable, $value) = map { _unescape($_) } split('='); | ||||
| 11 | 14 | ||||||
| 105 | |||||||
| 106 | # check an argument was provided if one was expected | ||||||
| 107 | 6 | 100 | 22 | if ($nargs = $state->_argcount($variable)) { | |||
| 108 | 4 | 50 | 6 | 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 | 16 | 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 | 6 | $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 | 11 | my($todecode) = @_; | |||
| 143 | 11 | 10 | $todecode =~ tr/+/ /; # pluses become spaces | ||||
| 144 | 11 | 10 | $todecode =~ s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge; | ||||
| 0 | 0 | ||||||
| 145 | 11 | 18 | return $todecode; | ||||
| 146 | } | ||||||
| 147 | |||||||
| 148 | # | ||||||
| 149 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||||
| 150 | |||||||
| 151 | |||||||
| 152 | |||||||
| 153 | |||||||
| 154 | 1; | ||||||
| 155 | |||||||
| 156 | __END__ |