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
|
|
|
|
|
|
|
|