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