| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# $Id: Utils.pm,v 1.6 2008-02-15 09:49:17 mike Exp $ |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Keystone::Resolver::Utils; |
|
4
|
|
|
|
|
|
|
|
|
5
|
5
|
|
|
5
|
|
25578
|
use strict; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
150
|
|
|
6
|
5
|
|
|
5
|
|
26
|
use warnings; |
|
|
5
|
|
|
|
|
16
|
|
|
|
5
|
|
|
|
|
190
|
|
|
7
|
5
|
|
|
5
|
|
4131
|
use URI::Escape qw(uri_unescape uri_escape_utf8); |
|
|
5
|
|
|
|
|
7054
|
|
|
|
5
|
|
|
|
|
352
|
|
|
8
|
5
|
|
|
5
|
|
6944
|
use Encode; |
|
|
5
|
|
|
|
|
69840
|
|
|
|
5
|
|
|
|
|
507
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
5
|
|
|
5
|
|
44
|
use Exporter 'import'; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
3984
|
|
|
11
|
|
|
|
|
|
|
our @EXPORT_OK = qw(encode_hash decode_hash utf8param |
|
12
|
|
|
|
|
|
|
apache_request mod_perl_version |
|
13
|
|
|
|
|
|
|
apache_non_moronic_logging); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 NAME |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Keystone::Resolver::Utils - Simple utility functions for Keystone Resolver |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
use Keystone::Resolver::Utils qw(encode_hash decode_hash); |
|
22
|
|
|
|
|
|
|
$string = encode_hash(%foo); |
|
23
|
|
|
|
|
|
|
%bar = decode_hash($string); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
This module consists of standalone functions -- yes, that's right, |
|
28
|
|
|
|
|
|
|
functions: not classes, not methods, functions. These are provided |
|
29
|
|
|
|
|
|
|
for the use of Keystone Resolver. |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head2 encode_hash(), decode_hash() |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$string = encode_hash(%foo); |
|
36
|
|
|
|
|
|
|
%bar = decode_hash($string); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
C encodes a hash into a single scalar string, which may |
|
39
|
|
|
|
|
|
|
then be stored in a database, specified as a URL parameters, etc. |
|
40
|
|
|
|
|
|
|
C decodes a string created by C back |
|
41
|
|
|
|
|
|
|
into a hash identical to the original. |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
These two functions constitute a tiny subset of the functionality of |
|
44
|
|
|
|
|
|
|
the C module, but have the pleasant property that the |
|
45
|
|
|
|
|
|
|
encoded form is human-readable and therefore useful in logging. In |
|
46
|
|
|
|
|
|
|
theory, the encoding is secret, but I may as well admit that the hash |
|
47
|
|
|
|
|
|
|
is encoded as a URL query. |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
sub encode_hash { |
|
52
|
26
|
|
|
26
|
1
|
7783
|
my(%hash) = @_; |
|
53
|
|
|
|
|
|
|
|
|
54
|
80
|
|
|
|
|
1220
|
return join("&", map { |
|
55
|
26
|
|
|
|
|
96
|
uri_escape_utf8($_) . "=" . uri_escape_utf8($hash{$_}) |
|
56
|
|
|
|
|
|
|
} sort keys %hash); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub decode_hash { |
|
60
|
13
|
|
|
13
|
1
|
495
|
my($string) = @_; |
|
61
|
|
|
|
|
|
|
|
|
62
|
80
|
|
|
|
|
1373
|
return (map { decode_utf8(uri_unescape($_)) } |
|
|
40
|
|
|
|
|
76
|
|
|
63
|
13
|
|
|
|
|
40
|
map { (split /=/, $_, -1) } split(/&/, $string, -1)); |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head2 utf8param() |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
$unicodeString = utf8param($r, $key); |
|
70
|
|
|
|
|
|
|
@unicodeKeys = utf8param($r); |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
Returns the value associated with the parameter named C<$key> in the |
|
73
|
|
|
|
|
|
|
Apache Request (or similar object) C<$r>, on the assumption that the |
|
74
|
|
|
|
|
|
|
encoded value was a sequence of UTF-8 octets. These octets are |
|
75
|
|
|
|
|
|
|
decoded into Unicode characters, and it is a string of these that is |
|
76
|
|
|
|
|
|
|
returned. |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
If called with no C<$key> parameter, returns a list of the names of |
|
79
|
|
|
|
|
|
|
all parameters available in C<$r>, each such key returned as a string |
|
80
|
|
|
|
|
|
|
of Unicode characters. |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=cut |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Under Apache 2/mod_perl 2, the ubiquitous $r is no longer and |
|
85
|
|
|
|
|
|
|
# Apache::Request object, nor even an Apache2::Request, but an |
|
86
|
|
|
|
|
|
|
# Apache2::RequestReq ... which, astonishingly, doesn't have the |
|
87
|
|
|
|
|
|
|
# param() method. So if we're given one of these things, we need to |
|
88
|
|
|
|
|
|
|
# make an Apache::Request out of, which at least isn't too hard. |
|
89
|
|
|
|
|
|
|
# However *sigh* this may not be a cheap operation, so we keep a cache |
|
90
|
|
|
|
|
|
|
# of already-made Request objects. |
|
91
|
|
|
|
|
|
|
# |
|
92
|
|
|
|
|
|
|
my %_apache2request; |
|
93
|
|
|
|
|
|
|
my %_paramsbyrequest; # Used for Apache2 only |
|
94
|
|
|
|
|
|
|
sub utf8param { |
|
95
|
0
|
|
|
0
|
1
|
|
my($r, $key, $value) = @_; |
|
96
|
|
|
|
|
|
|
|
|
97
|
0
|
0
|
|
|
|
|
if ($r->isa('Apache2::RequestRec')) { |
|
98
|
|
|
|
|
|
|
# Running under Apache2 |
|
99
|
0
|
0
|
|
|
|
|
if (defined $_apache2request{$r}) { |
|
100
|
|
|
|
|
|
|
#warn "using existing Apache2::RequestReq for '$r'"; |
|
101
|
0
|
|
|
|
|
|
$r = $_apache2request{$r}; |
|
102
|
|
|
|
|
|
|
} else { |
|
103
|
0
|
|
|
|
|
|
require Apache2::Request; |
|
104
|
|
|
|
|
|
|
#warn "making new Apache2::RequestReq for '$r'"; |
|
105
|
0
|
|
|
|
|
|
$r = $_apache2request{$r} = new Apache2::Request($r); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
|
|
109
|
0
|
0
|
|
|
|
|
if (!defined $key) { |
|
110
|
0
|
|
|
|
|
|
return map { decode_utf8($_) } $r->param(); |
|
|
0
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
0
|
|
|
|
|
|
my $raw = undef; |
|
114
|
0
|
0
|
|
|
|
|
$raw = $_paramsbyrequest{$r}->{$key} if $r->isa('Apache2::Request'); |
|
115
|
0
|
0
|
|
|
|
|
$raw = $r->param($key) if !defined $raw; |
|
116
|
|
|
|
|
|
|
|
|
117
|
0
|
0
|
|
|
|
|
if (defined $value) { |
|
118
|
|
|
|
|
|
|
# Argh! Simply writing through to the underlying method |
|
119
|
|
|
|
|
|
|
# param() won't work in Apache2, where param() is readonly. |
|
120
|
|
|
|
|
|
|
# So we have to keep a hash of additional values, which we |
|
121
|
|
|
|
|
|
|
# consult (above) before the actual parameters. Ouch ouch. |
|
122
|
0
|
0
|
|
|
|
|
if ($r->isa('Apache2::Request')) { |
|
123
|
0
|
|
|
|
|
|
$_paramsbyrequest{$r}->{$key} = encode_utf8($value); |
|
124
|
|
|
|
|
|
|
} else { |
|
125
|
0
|
|
|
|
|
|
$r->param($key, encode_utf8($value)); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
0
|
0
|
|
|
|
|
return undef if !defined $raw; |
|
130
|
0
|
|
|
|
|
|
my $cooked = decode_utf8($raw); |
|
131
|
0
|
0
|
|
|
|
|
warn "converted '$raw' to '", $cooked, "'\n" if $cooked ne $raw; |
|
132
|
0
|
|
|
|
|
|
return $cooked; |
|
133
|
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 apache_request() |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my $r = apache_request($cgi); |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Because the Apache/Perl project people saw fit to totally change the |
|
141
|
|
|
|
|
|
|
API between C versions 1 and 2, and because the environment |
|
142
|
|
|
|
|
|
|
variables that might tell you what version is in use are undocumented |
|
143
|
|
|
|
|
|
|
and obscure, it is pretty painful getting hold of the Apache request |
|
144
|
|
|
|
|
|
|
object in a portable way -- which you need for things like setting the |
|
145
|
|
|
|
|
|
|
content-type. C does this, returning the Apache 1 |
|
146
|
|
|
|
|
|
|
or 2 request object if running under Apache, and otherwise returning |
|
147
|
|
|
|
|
|
|
the fallback object which is passed in, if any. |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub apache_request { |
|
152
|
0
|
|
|
0
|
1
|
|
my($fallback) = @_; |
|
153
|
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
my $ver = mod_perl_version(); |
|
155
|
|
|
|
|
|
|
#warn "ver=", (defined $ver ? "'$ver'" : "UNDEFINED"), "\n"; |
|
156
|
0
|
0
|
|
|
|
|
if (!defined $ver) { |
|
157
|
|
|
|
|
|
|
#warn "Fallback: r='$fallback'\n"; |
|
158
|
0
|
|
|
|
|
|
return $fallback; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
0
|
0
|
|
|
|
|
if ($ver == 2) { |
|
162
|
0
|
|
|
|
|
|
require Apache2::RequestUtil; |
|
163
|
0
|
|
|
|
|
|
my $r = Apache2::RequestUtil->request(); |
|
164
|
|
|
|
|
|
|
#warn "Apache2: r='$r'\n"; |
|
165
|
0
|
|
|
|
|
|
return $r; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
|
|
168
|
0
|
0
|
|
|
|
|
if ($ver == 1) { |
|
169
|
0
|
|
|
|
|
|
require Apache; |
|
170
|
0
|
|
|
|
|
|
my $r = Apache->request(); |
|
171
|
|
|
|
|
|
|
#warn "Apache: r='$r'\n"; |
|
172
|
0
|
|
|
|
|
|
return $r; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
0
|
|
|
|
|
|
die "unknown mod_perl version '$ver'"; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head2 mod_perl_version() |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
$ver = mod_perl_version(); |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Returns the major API version number of the version C in |
|
184
|
|
|
|
|
|
|
effect, or an undefined value if not running under mod_perl (e.g. as |
|
185
|
|
|
|
|
|
|
an external CGI script or from the command-line). |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=cut |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# By inspection, it seems that mod_perl version 2 sets the |
|
190
|
|
|
|
|
|
|
# MOD_PERL_API_VERSION environment variable, but mod_perl version 1 |
|
191
|
|
|
|
|
|
|
# does not; but that both set MOD_PERL. |
|
192
|
|
|
|
|
|
|
# |
|
193
|
|
|
|
|
|
|
sub mod_perl_version { |
|
194
|
0
|
|
|
0
|
1
|
|
my $api = $ENV{MOD_PERL_API_VERSION}; |
|
195
|
0
|
0
|
|
|
|
|
return $api if defined $api; |
|
196
|
0
|
|
|
|
|
|
my $mp = $ENV{MOD_PERL}; |
|
197
|
0
|
0
|
|
|
|
|
return undef if !defined $mp; |
|
198
|
|
|
|
|
|
|
# $mp is of the form "mod_perl/1.29" |
|
199
|
0
|
|
|
|
|
|
$mp =~ s/mod_perl\/([0-9]+)\..*/$1/; |
|
200
|
0
|
|
|
|
|
|
return $mp; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head2 |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
apache_non_moronic_logging() |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
I hate the world. |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
For reasons which no rational being could ever fathom, one of the |
|
211
|
|
|
|
|
|
|
differences between Apache 1.x/mod_perl and Apache 2.x/mod_perl2 is |
|
212
|
|
|
|
|
|
|
that in the latter, calls to C result in the output going to |
|
213
|
|
|
|
|
|
|
the I error-log of the server rather than the the error-log of |
|
214
|
|
|
|
|
|
|
the virtual site. I know, I know, it is truly astonishing. I will |
|
215
|
|
|
|
|
|
|
not meditate on this further. See the section entitled C
|
|
216
|
|
|
|
|
|
|
Hosts> in the C manual for details, or see the online |
|
217
|
|
|
|
|
|
|
version at |
|
218
|
|
|
|
|
|
|
http://perl.apache.org/docs/2.0/api/Apache2/Log.html#Virtual_Hosts |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Anyway, call C to globally fix this by |
|
221
|
|
|
|
|
|
|
aliasing C to the non-braindead Apache2 logging function |
|
222
|
|
|
|
|
|
|
of the same name. Calling under mod_perl 1, or not under mod_perl at |
|
223
|
|
|
|
|
|
|
all, will no-op. |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
I<### except -- it turns out -- this doesn't actually work, even |
|
226
|
|
|
|
|
|
|
though it is the very code from the Apache2::Log manual. Or rather, |
|
227
|
|
|
|
|
|
|
it works intermittently. So I think you will just have to read the |
|
228
|
|
|
|
|
|
|
global log as well as the resolver log. Nice.> |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=cut |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub apache_non_moronic_logging { |
|
233
|
0
|
|
|
0
|
0
|
|
my $ver = mod_perl_version(); |
|
234
|
0
|
0
|
0
|
|
|
|
if (defined $ver && $ver == 2) { |
|
235
|
0
|
|
|
|
|
|
require "Apache2/Log.pm"; |
|
236
|
0
|
|
|
|
|
|
*CORE::GLOBAL::warn = \&Apache2::ServerRec::warn; |
|
237
|
|
|
|
|
|
|
#warn "calling CORE::warn() as warn()"; |
|
238
|
|
|
|
|
|
|
#CORE::warn "calling CORE::warn() as CORE::warn()"; |
|
239
|
|
|
|
|
|
|
#Apache2::ServerRec::warn "calling Apache2::ServerRec::warn()"; |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
1; |