| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Apache2::Controller::Methods; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Apache2::Controller::Methods - methods shared by Apache2::Controller modules |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 VERSION |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Version 1.001.001 |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
|
12
|
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
10
|
use version; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
7
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = version->new('1.001.001'); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
package Apache2::Controller::SomeNewBrilliantPlugin; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use base qw( Apache2::Controller::Methods ); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# ... |
|
23
|
|
|
|
|
|
|
my $directives = $self->get_directives(); |
|
24
|
|
|
|
|
|
|
my $directive = $self->get_directive('A2CSomethingSomething'); |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Methods shared in common by various Apache2::Controller modules, |
|
29
|
|
|
|
|
|
|
like L, L, etc. |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Note: In this module we always dereference C<$self->{r}>, |
|
32
|
|
|
|
|
|
|
because we don't know if $self is blessed as an Apache2::Request |
|
33
|
|
|
|
|
|
|
yet or not. (This package is used as a base by multiple handler stages.) |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 METHODS |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=cut |
|
38
|
|
|
|
|
|
|
|
|
39
|
1
|
|
|
1
|
|
137
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
56
|
|
|
40
|
1
|
|
|
1
|
|
13
|
use warnings FATAL => 'all'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
51
|
|
|
41
|
1
|
|
|
1
|
|
7
|
use English '-no_match_vars'; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
8
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
1
|
|
|
1
|
|
4239
|
use Apache2::Module (); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
use Apache2::Controller::X; |
|
45
|
|
|
|
|
|
|
use Apache2::Cookie; |
|
46
|
|
|
|
|
|
|
use APR::Error (); |
|
47
|
|
|
|
|
|
|
use APR::Request::Error (); |
|
48
|
|
|
|
|
|
|
use YAML::Syck; |
|
49
|
|
|
|
|
|
|
use Log::Log4perl qw( :easy ); |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head2 get_directives |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
my $directives_hashref = $self->get_directives(); |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Returns the L config hash for this request, |
|
56
|
|
|
|
|
|
|
with per-directory settings. |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
NOTE: real directives don't work because of problems with Apache::Test. |
|
59
|
|
|
|
|
|
|
For now use C. |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
When directives work, if you mix A2C Directives with PerlSetVar |
|
62
|
|
|
|
|
|
|
statements in Apache config, the directives take precedence |
|
63
|
|
|
|
|
|
|
and the PerlSetVar values are not merged. Hrmm. |
|
64
|
|
|
|
|
|
|
Well, I think there's a method, but I've got better |
|
65
|
|
|
|
|
|
|
things to work on right now. |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=cut |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub get_directives { |
|
70
|
|
|
|
|
|
|
my ($self) = @_; |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
my $r = $self->{r}; |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
my $directives = $r->pnotes->{a2c}{directives}; |
|
75
|
|
|
|
|
|
|
return $directives if $directives; |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
$directives = Apache2::Module::get_config( |
|
78
|
|
|
|
|
|
|
'Apache2::Controller::Directives', |
|
79
|
|
|
|
|
|
|
$r->server(), |
|
80
|
|
|
|
|
|
|
$r->per_dir_config(), |
|
81
|
|
|
|
|
|
|
); |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
DEBUG sub{"directives found:\n".Dump($directives)}; |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
$r->pnotes->{a2c}{directives} = $directives; |
|
86
|
|
|
|
|
|
|
return $directives; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head2 get_directive |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
my $value = $self->get_directive( $A2CDirectiveNameString ) |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Returns the value of the given directive name. Does not die if |
|
94
|
|
|
|
|
|
|
get_directives() returns an empty hash. |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
NOTE: directives don't work because of problems with Apache::Test. |
|
97
|
|
|
|
|
|
|
For now use C. |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=cut |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub get_directive { |
|
102
|
|
|
|
|
|
|
my ($self, $directive) = @_; |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
a2cx 'usage: $self->get_directive($directive)' if !$directive; |
|
105
|
|
|
|
|
|
|
my $directives = $self->get_directives(); |
|
106
|
|
|
|
|
|
|
my $directive_value = $directives->{$directive}; |
|
107
|
|
|
|
|
|
|
DEBUG sub { |
|
108
|
|
|
|
|
|
|
"directive $directive = " |
|
109
|
|
|
|
|
|
|
.(defined $directive_value ? "'$directive_value'" : '[undef]') |
|
110
|
|
|
|
|
|
|
}; |
|
111
|
|
|
|
|
|
|
return $directive_value; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 get_cookie_jar |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
my $jar = $self->get_cookie_jar(); |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Gets the L object. |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Does NOT cache the jar in any way, as this is the business |
|
121
|
|
|
|
|
|
|
of C, and input headers could possibly change |
|
122
|
|
|
|
|
|
|
via filters, and it would create a circular reference to C<< $r >> |
|
123
|
|
|
|
|
|
|
if you stuck it in pnotes. It always creates a new Jar object, |
|
124
|
|
|
|
|
|
|
which acts as a utility object to parse the source information |
|
125
|
|
|
|
|
|
|
that remains in C<< $r >>, if I understand this correctly. |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
If the directive << A2C_Skip_Bogus_Cookies >> is set, fetches |
|
128
|
|
|
|
|
|
|
jar in eval and returns C<< $EVAL_ERROR->jar >> if the error |
|
129
|
|
|
|
|
|
|
is an L and the code is C<< APR::Request::Error::NOTOKEN >>, |
|
130
|
|
|
|
|
|
|
indicating a cookie with a value like '1' sent by a defective client. |
|
131
|
|
|
|
|
|
|
Any other L will be re-thrown as per that doc, |
|
132
|
|
|
|
|
|
|
otherwise A2C will throw an L with the error. |
|
133
|
|
|
|
|
|
|
(See L - |
|
134
|
|
|
|
|
|
|
closes RT #61744, thanks Arkadius Litwinczuk.) Skipping these |
|
135
|
|
|
|
|
|
|
errors is optional since they might be important for debugging |
|
136
|
|
|
|
|
|
|
clients that send invalid headers. |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
See L, L. |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=cut |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub get_cookie_jar { |
|
143
|
|
|
|
|
|
|
my $self = shift; |
|
144
|
|
|
|
|
|
|
return $self->get_directive('A2C_Skip_Bogus_Cookies') |
|
145
|
|
|
|
|
|
|
? $self->_get_cookie_jar_eval(@_) |
|
146
|
|
|
|
|
|
|
: $self->_get_cookie_jar_normal(@_) |
|
147
|
|
|
|
|
|
|
; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub _get_cookie_jar_normal { |
|
151
|
|
|
|
|
|
|
my ($self) = @_; |
|
152
|
|
|
|
|
|
|
my $r = $self->{r}; |
|
153
|
|
|
|
|
|
|
my $jar; |
|
154
|
|
|
|
|
|
|
eval { $jar = Apache2::Cookie::Jar->new($r) }; |
|
155
|
|
|
|
|
|
|
if (my $err = $EVAL_ERROR) { |
|
156
|
|
|
|
|
|
|
my $ref = ref $err; |
|
157
|
|
|
|
|
|
|
DEBUG "error creating cookie jar (reftype '$ref'): '$err'"; |
|
158
|
|
|
|
|
|
|
die $err if $ref; # rethrow blessed APR::Error errors |
|
159
|
|
|
|
|
|
|
a2cx "unknown error creating cookie jar: '$err'"; |
|
160
|
|
|
|
|
|
|
} |
|
161
|
|
|
|
|
|
|
DEBUG sub { |
|
162
|
|
|
|
|
|
|
my $cookie = $r->headers_in->{Cookie}; |
|
163
|
|
|
|
|
|
|
$cookie = $cookie ? qq{$cookie} : '[no raw cookie string]'; |
|
164
|
|
|
|
|
|
|
eval { my @cookies = $jar->cookies() }; |
|
165
|
|
|
|
|
|
|
a2cx "error getting cookie from jar that worked: '$EVAL_ERROR'" |
|
166
|
|
|
|
|
|
|
if $EVAL_ERROR; |
|
167
|
|
|
|
|
|
|
return |
|
168
|
|
|
|
|
|
|
"raw cookie header: $cookie\n" |
|
169
|
|
|
|
|
|
|
."cookie names in jar:\n" |
|
170
|
|
|
|
|
|
|
.join('', map qq{ - $_\n}, $jar->cookies() ) |
|
171
|
|
|
|
|
|
|
; |
|
172
|
|
|
|
|
|
|
}; |
|
173
|
|
|
|
|
|
|
return $jar; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _get_cookie_jar_eval { |
|
177
|
|
|
|
|
|
|
my ($self) = @_; |
|
178
|
|
|
|
|
|
|
my $r = $self->{r}; |
|
179
|
|
|
|
|
|
|
my $jar; |
|
180
|
|
|
|
|
|
|
eval { $jar = Apache2::Cookie::Jar->new($r) }; |
|
181
|
|
|
|
|
|
|
if (my $err = $EVAL_ERROR) { |
|
182
|
|
|
|
|
|
|
my $ref = ref $err; |
|
183
|
|
|
|
|
|
|
my $is_apr_error = length($ref) >= 5 && substr($ref,0,5) eq 'APR::'; |
|
184
|
|
|
|
|
|
|
DEBUG "caught error from jar of ref '$ref'"; |
|
185
|
|
|
|
|
|
|
if ($is_apr_error) { |
|
186
|
|
|
|
|
|
|
if ($err == APR::Request::Error::NOTOKEN) { |
|
187
|
|
|
|
|
|
|
my $code = int($err); |
|
188
|
|
|
|
|
|
|
my $errstr = APR::Error::strerror($code); |
|
189
|
|
|
|
|
|
|
DEBUG sub { |
|
190
|
|
|
|
|
|
|
my $ip = $r->connection->remote_ip |
|
191
|
|
|
|
|
|
|
|| '[ could not detect remote ip?? ]'; |
|
192
|
|
|
|
|
|
|
return "bad cookies from ip $ip, skipping error: '$err'" |
|
193
|
|
|
|
|
|
|
." ($code/$errstr)"; |
|
194
|
|
|
|
|
|
|
}; |
|
195
|
|
|
|
|
|
|
$jar = $err->jar; |
|
196
|
|
|
|
|
|
|
} |
|
197
|
|
|
|
|
|
|
else { |
|
198
|
|
|
|
|
|
|
DEBUG "rethrowing other APR::Error: '$err'"; |
|
199
|
|
|
|
|
|
|
die $err; |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
else { |
|
203
|
|
|
|
|
|
|
a2cx "unknown error (reftype '$ref') getting cookie jar: '$err'"; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
} |
|
206
|
|
|
|
|
|
|
DEBUG sub { |
|
207
|
|
|
|
|
|
|
my $cookie = $r->headers_in->{Cookie}; |
|
208
|
|
|
|
|
|
|
$cookie = $cookie ? qq{$cookie} : '[no raw cookie string]'; |
|
209
|
|
|
|
|
|
|
my @cookie_names; |
|
210
|
|
|
|
|
|
|
eval { @cookie_names = map qq{$_}, $jar->cookies }; |
|
211
|
|
|
|
|
|
|
return "eval error reading cookie names: $EVAL_ERROR" if $EVAL_ERROR; |
|
212
|
|
|
|
|
|
|
return |
|
213
|
|
|
|
|
|
|
"raw cookie header: $cookie\n" |
|
214
|
|
|
|
|
|
|
."cookie names in jar:\n" |
|
215
|
|
|
|
|
|
|
.join('', map " - $_\n", @cookie_names) |
|
216
|
|
|
|
|
|
|
; |
|
217
|
|
|
|
|
|
|
}; |
|
218
|
|
|
|
|
|
|
return $jar; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
L |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
L |
|
226
|
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
L |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
L |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
L |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
L |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=head1 AUTHOR |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Mark Hedges, C |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Copyright 2008-2010 Mark Hedges. CPAN: markle |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
|
244
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
This software is provided as-is, with no warranty |
|
247
|
|
|
|
|
|
|
and no guarantee of fitness |
|
248
|
|
|
|
|
|
|
for any particular purpose. |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=cut |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
1; |
|
253
|
|
|
|
|
|
|
|