blib/lib/Lemonldap/NG/Common/CGI.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 77 | 187 | 41.1 |
branch | 16 | 76 | 21.0 |
condition | 7 | 43 | 16.2 |
subroutine | 16 | 31 | 51.6 |
pod | 2 | 19 | 10.5 |
total | 118 | 356 | 33.1 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | ## @file | ||||||
2 | # Base package for all Lemonldap::NG CGI | ||||||
3 | |||||||
4 | ## @class | ||||||
5 | # Base class for all Lemonldap::NG CGI | ||||||
6 | package Lemonldap::NG::Common::CGI; | ||||||
7 | |||||||
8 | 1 | 1 | 17938 | use strict; | |||
1 | 2 | ||||||
1 | 46 | ||||||
9 | |||||||
10 | 1 | 1 | 5 | use File::Basename; | |||
1 | 3 | ||||||
1 | 113 | ||||||
11 | 1 | 1 | 669 | use MIME::Base64; | |||
1 | 813 | ||||||
1 | 70 | ||||||
12 | 1 | 1 | 499 | use Time::Local; | |||
1 | 1851 | ||||||
1 | 92 | ||||||
13 | 1 | 1 | 314376 | use CGI; | |||
1 | 16836 | ||||||
1 | 6 | ||||||
14 | 1 | 1 | 612 | use utf8; | |||
1 | 9 | ||||||
1 | 4 | ||||||
15 | 1 | 1 | 539 | use Encode; | |||
1 | 8075 | ||||||
1 | 83 | ||||||
16 | 1 | 1 | 487 | use Net::CIDR::Lite; | |||
1 | 3015 | ||||||
1 | 111 | ||||||
17 | |||||||
18 | #parameter syslog Indicates syslog facility for logging user actions | ||||||
19 | |||||||
20 | our $VERSION = '1.4.0'; | ||||||
21 | our $_SUPER; | ||||||
22 | our @ISA; | ||||||
23 | |||||||
24 | BEGIN { | ||||||
25 | 1 | 50 | 1 | 5 | if ( exists $ENV{MOD_PERL} ) { | ||
26 | 0 | 0 | 0 | 0 | if ( $ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION} >= 2 ) { | ||
27 | 0 | 0 | eval 'use constant MP => 2;'; | ||||
28 | } | ||||||
29 | else { | ||||||
30 | 0 | 0 | eval 'use constant MP => 1;'; | ||||
31 | } | ||||||
32 | } | ||||||
33 | else { | ||||||
34 | 1 | 1 | 58 | eval 'use constant MP => 0;'; | |||
1 | 5 | ||||||
1 | 9 | ||||||
1 | 45 | ||||||
35 | } | ||||||
36 | 1 | 2 | $_SUPER = 'CGI'; | ||||
37 | 1 | 2177 | @ISA = ('CGI'); | ||||
38 | } | ||||||
39 | |||||||
40 | sub import { | ||||||
41 | 1 | 1 | 135 | my $pkg = shift; | |||
42 | 1 | 50 | 33 | 18 | if ( $pkg eq __PACKAGE__ and @_ and $_[0] eq "fastcgi" ) { | ||
33 | |||||||
43 | 0 | 0 | eval 'use CGI::Fast'; | ||||
44 | 0 | 0 | 0 | die($@) if ($@); | |||
45 | 0 | 0 | unshift @ISA, 'CGI::Fast'; | ||||
46 | 0 | 0 | $_SUPER = 'CGI::Fast'; | ||||
47 | } | ||||||
48 | } | ||||||
49 | |||||||
50 | ## @cmethod Lemonldap::NG::Common::CGI new(@p) | ||||||
51 | # Constructor: launch CGI::new() then secure parameters since CGI store them at | ||||||
52 | # the root of the object. | ||||||
53 | # @param p arguments for CGI::new() | ||||||
54 | # @return new Lemonldap::NG::Common::CGI object | ||||||
55 | sub new { | ||||||
56 | 3 | 3 | 1 | 6595 | my $class = shift; | ||
57 | 3 | 50 | 20 | my $self = $_SUPER->new(@_) or return undef; | |||
58 | 3 | 4121 | $self->{_prm} = {}; | ||||
59 | 3 | 12 | my @tmp = $self->param(); | ||||
60 | 3 | 39 | foreach (@tmp) { | ||||
61 | 0 | 0 | $self->{_prm}->{$_} = $self->param($_); | ||||
62 | 0 | 0 | $self->delete($_); | ||||
63 | } | ||||||
64 | 3 | 8 | $self->{lang} = extract_lang(); | ||||
65 | 3 | 12 | bless $self, $class; | ||||
66 | 3 | 17 | return $self; | ||||
67 | } | ||||||
68 | |||||||
69 | ## @method scalar param(string s, scalar newValue) | ||||||
70 | # Return the wanted parameter issued of GET or POST request. If $s is not set, | ||||||
71 | # return the list of parameters names | ||||||
72 | # @param $s name of the parameter | ||||||
73 | # @param $newValue if set, the parameter will be set to his value | ||||||
74 | # @return datas passed by GET or POST method | ||||||
75 | sub param { | ||||||
76 | 0 | 0 | 0 | 0 | my ( $self, $p, $v ) = @_; | ||
77 | 0 | 0 | 0 | $self->{_prm}->{$p} = $v if ($v); | |||
78 | 0 | 0 | 0 | unless ( defined $p ) { | |||
79 | 0 | 0 | return keys %{ $self->{_prm} }; | ||||
0 | 0 | ||||||
80 | } | ||||||
81 | 0 | 0 | return $self->{_prm}->{$p}; | ||||
82 | } | ||||||
83 | |||||||
84 | ## @method scalar rparam(string s) | ||||||
85 | # Return a reference to a parameter | ||||||
86 | # @param $s name of the parameter | ||||||
87 | # @return ref to parameter data | ||||||
88 | sub rparam { | ||||||
89 | 0 | 0 | 0 | 0 | my ( $self, $p ) = @_; | ||
90 | 0 | 0 | 0 | return $self->{_prm}->{$p} ? \$self->{_prm}->{$p} : undef; | |||
91 | } | ||||||
92 | |||||||
93 | ## @method void lmLog(string mess, string level) | ||||||
94 | # Log subroutine. Use Apache::Log in ModPerl::Registry context else simply | ||||||
95 | # print on STDERR non debug messages. | ||||||
96 | # @param $mess Text to log | ||||||
97 | # @param $level Level (debug|info|notice|error) | ||||||
98 | sub lmLog { | ||||||
99 | 2 | 2 | 0 | 3 | my ( $self, $mess, $level ) = @_; | ||
100 | 2 | 3 | my $call; | ||||
101 | 2 | 50 | 4 | if ( $level eq 'debug' ) { | |||
102 | 2 | 50 | 7 | $mess = ( ref($self) ? ref($self) : $self ) . ": $mess"; | |||
103 | } | ||||||
104 | else { | ||||||
105 | 0 | 0 | my @tmp = caller(); | ||||
106 | 0 | 0 | $call = "$tmp[1] $tmp[2]:"; | ||||
107 | } | ||||||
108 | 2 | 50 | 50 | 9 | if ( $self->r and MP() ) { | ||
109 | 0 | 0 | 0 | $self->abort( "Level is required", | |||
110 | 'the parameter "level" is required when lmLog() is used' ) | ||||||
111 | unless ($level); | ||||||
112 | 0 | 0 | if ( MP() == 2 ) { | ||||
113 | require Apache2::Log; | ||||||
114 | Apache2::ServerRec->log->debug($call) if ($call); | ||||||
115 | Apache2::ServerRec->log->$level($mess); | ||||||
116 | } | ||||||
117 | else { | ||||||
118 | 0 | 0 | 0 | Apache->server->log->debug($call) if ($call); | |||
119 | 0 | 0 | Apache->server->log->$level($mess); | ||||
120 | } | ||||||
121 | } | ||||||
122 | else { | ||||||
123 | 2 | 100 | 19 | $self->{hideLogLevels} = 'debug|info' | |||
124 | unless defined( $self->{hideLogLevels} ); | ||||||
125 | 2 | 30 | my $re = qr/^(?:$self->{hideLogLevels})$/; | ||||
126 | 2 | 50 | 33 | 6 | print STDERR "$call\n" if ( $call and 'debug' !~ $re ); | ||
127 | 2 | 50 | 15 | print STDERR "[$level] $mess\n" unless ( $level =~ $re ); | |||
128 | } | ||||||
129 | } | ||||||
130 | |||||||
131 | ## @method void setApacheUser(string user) | ||||||
132 | # Set user for Apache logs in ModPerl::Registry context. Does nothing else. | ||||||
133 | # @param $user data to set as user in Apache logs | ||||||
134 | sub setApacheUser { | ||||||
135 | 0 | 0 | 0 | 0 | my ( $self, $user ) = @_; | ||
136 | 0 | 0 | 0 | 0 | if ( $self->r and MP() ) { | ||
137 | 0 | 0 | $self->lmLog( "Inform Apache about the user connected", 'debug' ); | ||||
138 | 0 | 0 | if ( MP() == 2 ) { | ||||
139 | require Apache2::Connection; | ||||||
140 | $self->r->user($user); | ||||||
141 | } | ||||||
142 | else { | ||||||
143 | 0 | 0 | $self->r->connection->user($user); | ||||
144 | } | ||||||
145 | } | ||||||
146 | 0 | 0 | $ENV{REMOTE_USER} = $user; | ||||
147 | } | ||||||
148 | |||||||
149 | ##@method string getApacheHtdocsPath() | ||||||
150 | # Return absolute path to the htdocs directory where the current script is | ||||||
151 | # @return path string | ||||||
152 | sub getApacheHtdocsPath { | ||||||
153 | 0 | 0 | 0 | 0 | 0 | return dirname( $ENV{SCRIPT_FILENAME} || $0 ); | |
154 | } | ||||||
155 | |||||||
156 | ## @method void soapTest(string soapFunctions, object obj) | ||||||
157 | # Check if request is a SOAP request. If it is, launch | ||||||
158 | # Lemonldap::NG::Common::CGI::SOAPServer and exit. Else simply return. | ||||||
159 | # @param $soapFunctions list of authorized functions. | ||||||
160 | # @param $obj optional object that will receive SOAP requests | ||||||
161 | sub soapTest { | ||||||
162 | 0 | 0 | 0 | 0 | my ( $self, $soapFunctions, $obj ) = @_; | ||
163 | |||||||
164 | # If non form encoded datas are posted, we call SOAP Services | ||||||
165 | 0 | 0 | 0 | if ( $ENV{HTTP_SOAPACTION} ) { | |||
166 | require | ||||||
167 | 0 | 0 | Lemonldap::NG::Common::CGI::SOAPServer; #link protected dispatcher | ||||
168 | require | ||||||
169 | 0 | 0 | Lemonldap::NG::Common::CGI::SOAPService; #link protected soapService | ||||
170 | 0 | 0 | 0 | my @func = ( | |||
171 | ref($soapFunctions) ? @$soapFunctions : split /\s+/, | ||||||
172 | $soapFunctions | ||||||
173 | ); | ||||||
174 | 0 | 0 | 0 | my $dispatcher = | |||
175 | Lemonldap::NG::Common::CGI::SOAPService->new( $obj || $self, @func ); | ||||||
176 | 0 | 0 | Lemonldap::NG::Common::CGI::SOAPServer->dispatch_to($dispatcher) | ||||
177 | ->handle($self); | ||||||
178 | 0 | 0 | $self->quit(); | ||||
179 | } | ||||||
180 | } | ||||||
181 | |||||||
182 | ## @method string header_public(string filename) | ||||||
183 | # Implements the "304 Not Modified" HTTP mechanism. | ||||||
184 | # If HTTP request contains an "If-Modified-Since" header and if | ||||||
185 | # $filename was not modified since, prints the "304 Not Modified" response and | ||||||
186 | # exit. Else, launch CGI::header() with "Cache-Control" and "Last-Modified" | ||||||
187 | # headers. | ||||||
188 | # @param $filename Optional name of the reference file. Default | ||||||
189 | # $ENV{SCRIPT_FILENAME}. | ||||||
190 | # @return Common Gateway Interface standard response header | ||||||
191 | sub header_public { | ||||||
192 | 1 | 1 | 1 | 1 | my $self = shift; | ||
193 | 1 | 2 | my $filename = shift; | ||||
194 | 1 | 33 | 4 | $filename ||= $ENV{SCRIPT_FILENAME}; | |||
195 | 1 | 28 | my @tmp = stat($filename); | ||||
196 | 1 | 2 | my $date = $tmp[9]; | ||||
197 | 1 | 9 | my $hd = gmtime($date); | ||||
198 | 1 | 35 | $hd =~ s/^(\w+)\s+(\w+)\s+(\d+)\s+([\d:]+)\s+(\d+)$/$1, $3 $2 $5 $4 GMT/; | ||||
199 | 1 | 2 | my $year = $5; | ||||
200 | 1 | 2 | my $cm = $2; | ||||
201 | |||||||
202 | # TODO: Remove TODO_ for stable releases | ||||||
203 | 1 | 50 | 5 | if ( my $ref = $ENV{HTTP_IF_MODIFIED_SINCE} ) { | |||
204 | 0 | 0 | my %month = ( | ||||
205 | jan => 0, | ||||||
206 | feb => 1, | ||||||
207 | mar => 2, | ||||||
208 | apr => 3, | ||||||
209 | may => 4, | ||||||
210 | jun => 5, | ||||||
211 | jul => 6, | ||||||
212 | aug => 7, | ||||||
213 | sep => 8, | ||||||
214 | oct => 9, | ||||||
215 | nov => 10, | ||||||
216 | dec => 11 | ||||||
217 | ); | ||||||
218 | 0 | 0 | 0 | if ( $ref =~ /^\w+,\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/ ) { | |||
219 | 0 | 0 | my $m = $month{ lc($2) }; | ||||
220 | 0 | 0 | 0 | $year-- if ( $m > $month{ lc($cm) } ); | |||
221 | 0 | 0 | $ref = timegm( $6, $5, $4, $1, $m, $3 ); | ||||
222 | 0 | 0 | 0 | if ( $ref == $date ) { | |||
223 | 0 | 0 | print $self->SUPER::header( -status => '304 Not Modified', @_ ); | ||||
224 | 0 | 0 | $self->quit(); | ||||
225 | } | ||||||
226 | } | ||||||
227 | } | ||||||
228 | 1 | 12 | return $self->SUPER::header( | ||||
229 | '-Last-Modified' => $hd, | ||||||
230 | '-Cache-Control' => 'public; must-revalidate; max-age=1800', | ||||||
231 | @_ | ||||||
232 | ); | ||||||
233 | } | ||||||
234 | |||||||
235 | ## @method void abort(string title, string text) | ||||||
236 | # Display an error message and exit. | ||||||
237 | # Used instead of die() in Lemonldap::NG CGIs. | ||||||
238 | # @param title Title of the error message | ||||||
239 | # @param text Optional text. Default: "See Apache's logs" | ||||||
240 | sub abort { | ||||||
241 | 0 | 0 | 0 | 0 | my $self = shift; | ||
242 | 0 | 0 | my $cgi = CGI->new(); | ||||
243 | 0 | 0 | my ( $t1, $t2 ) = @_; | ||||
244 | |||||||
245 | # Default message | ||||||
246 | 0 | 0 | 0 | $t2 ||= "See Apache's logs"; | |||
247 | |||||||
248 | # Change \n into for HTML |
||||||
249 | 0 | 0 | my $t2html = $t2; | ||||
250 | 0 | 0 | $t2html =~ s#\n# #g; |
||||
251 | |||||||
252 | 0 | 0 | print $cgi->header( -type => 'text/html; charset=utf-8', ); | ||||
253 | 0 | 0 | print $cgi->start_html( | ||||
254 | -title => $t1, | ||||||
255 | -encoding => 'utf8', | ||||||
256 | -style => { | ||||||
257 | -code => ' | ||||||
258 | body{ | ||||||
259 | background:#000; | ||||||
260 | color:#fff; | ||||||
261 | padding:10px 50px; | ||||||
262 | font-family:sans-serif; | ||||||
263 | } | ||||||
264 | a { | ||||||
265 | text-decoration:none; | ||||||
266 | color:#fff; | ||||||
267 | } | ||||||
268 | ' | ||||||
269 | }, | ||||||
270 | ); | ||||||
271 | 0 | 0 | print "$t1$t2html "; |
||||
272 | 0 | 0 | |||||
273 | ' |
||||||
274 | 0 | 0 | 0 | print STDERR ( ref($self) || $self ) . " error: $t1, $t2\n"; | |||
275 | 0 | 0 | print $cgi->end_html(); | ||||
276 | 0 | 0 | $self->quit(); | ||||
277 | } | ||||||
278 | |||||||
279 | ##@method private void startSyslog() | ||||||
280 | # Open syslog connection. | ||||||
281 | sub startSyslog { | ||||||
282 | 0 | 0 | 0 | 0 | my $self = shift; | ||
283 | 0 | 0 | 0 | return if ( $self->{_syslog} ); | |||
284 | 0 | 0 | eval { | ||||
285 | 0 | 0 | require Sys::Syslog; | ||||
286 | 0 | 0 | Sys::Syslog->import(':standard'); | ||||
287 | 0 | 0 | openlog( 'lemonldap-ng', 'ndelay,pid', $self->{syslog} ); | ||||
288 | }; | ||||||
289 | 0 | 0 | 0 | $self->abort( "Unable to use syslog", $@ ) if ($@); | |||
290 | 0 | 0 | $self->{_syslog} = 1; | ||||
291 | } | ||||||
292 | |||||||
293 | ##@method void userLog(string mess, string level) | ||||||
294 | # Log user actions on Apache logs or syslog. | ||||||
295 | # @param $mess string to log | ||||||
296 | # @param $level level of log message | ||||||
297 | sub userLog { | ||||||
298 | 0 | 0 | 0 | 0 | my ( $self, $mess, $level ) = @_; | ||
299 | 0 | 0 | 0 | if ( $self->{syslog} ) { | |||
300 | 0 | 0 | $self->startSyslog(); | ||||
301 | 0 | 0 | $level =~ s/^warn$/warning/; | ||||
302 | 0 | 0 | 0 | syslog( $level || 'notice', $mess ); | |||
303 | } | ||||||
304 | else { | ||||||
305 | 0 | 0 | $self->lmLog( $mess, $level ); | ||||
306 | } | ||||||
307 | } | ||||||
308 | |||||||
309 | ##@method void userInfo(string mess) | ||||||
310 | # Log non important user actions. Alias for userLog() with facility "info". | ||||||
311 | # @param $mess string to log | ||||||
312 | sub userInfo { | ||||||
313 | 0 | 0 | 0 | 0 | my ( $self, $mess ) = @_; | ||
314 | 0 | 0 | $mess = "Lemonldap::NG : $mess (" . $self->ipAddr . ")"; | ||||
315 | 0 | 0 | $self->userLog( $mess, 'info' ); | ||||
316 | } | ||||||
317 | |||||||
318 | ##@method void userNotice(string mess) | ||||||
319 | # Log user actions like access and logout. Alias for userLog() with facility | ||||||
320 | # "notice". | ||||||
321 | # @param $mess string to log | ||||||
322 | sub userNotice { | ||||||
323 | 0 | 0 | 0 | 0 | my ( $self, $mess ) = @_; | ||
324 | 0 | 0 | $mess = "Lemonldap::NG : $mess (" . $self->ipAddr . ")"; | ||||
325 | 0 | 0 | $self->userLog( $mess, 'notice' ); | ||||
326 | } | ||||||
327 | |||||||
328 | ##@method void userError(string mess) | ||||||
329 | # Log user errors like "bad password". Alias for userLog() with facility | ||||||
330 | # "warn". | ||||||
331 | # @param $mess string to log | ||||||
332 | sub userError { | ||||||
333 | 0 | 0 | 0 | 0 | my ( $self, $mess ) = @_; | ||
334 | 0 | 0 | $mess = "Lemonldap::NG : $mess (" . $self->ipAddr . ")"; | ||||
335 | 0 | 0 | $self->userLog( $mess, 'warn' ); | ||||
336 | } | ||||||
337 | |||||||
338 | ## @method protected scalar _sub(string sub, array p) | ||||||
339 | # Launch $self->{$sub} if defined, else launch $self->$sub. | ||||||
340 | # @param $sub name of the sub to launch | ||||||
341 | # @param @p parameters for the sub | ||||||
342 | sub _sub { | ||||||
343 | 2 | 2 | 3374 | my ( $self, $sub, @p ) = @_; | |||
344 | 2 | 100 | 6 | if ( $self->{$sub} ) { | |||
345 | 1 | 7 | $self->lmLog( "processing to custom sub $sub", 'debug' ); | ||||
346 | 1 | 1 | return &{ $self->{$sub} }( $self, @p ); | ||||
1 | 3 | ||||||
347 | } | ||||||
348 | else { | ||||||
349 | 1 | 8 | $self->lmLog( "processing to sub $sub", 'debug' ); | ||||
350 | 1 | 4 | return $self->$sub(@p); | ||||
351 | } | ||||||
352 | } | ||||||
353 | |||||||
354 | ##@method string extract_lang | ||||||
355 | #@return array of user's preferred languages (two letters) | ||||||
356 | sub extract_lang { | ||||||
357 | 6 | 6 | 0 | 357 | my $self = shift; | ||
358 | |||||||
359 | 6 | 100 | 63 | my @langs = split /,\s*/, ( shift || $ENV{HTTP_ACCEPT_LANGUAGE} || "" ); | |||
360 | 6 | 9 | my @res = (); | ||||
361 | |||||||
362 | 6 | 10 | foreach (@langs) { | ||||
363 | |||||||
364 | # Languages are supposed to be sorted by preference | ||||||
365 | 12 | 25 | my $lang = ( split /;/ )[0]; | ||||
366 | |||||||
367 | # Take first part of lang code (part before -) | ||||||
368 | 12 | 17 | $lang = ( split /-/, $lang )[0]; | ||||
369 | |||||||
370 | # Go to next if lang was already added | ||||||
371 | 12 | 100 | 72 | next if grep( /$lang/, @res ); | |||
372 | |||||||
373 | # Store lang only if size is 2 characters | ||||||
374 | 8 | 50 | 21 | push @res, $lang if ( length($lang) == 2 ); | |||
375 | } | ||||||
376 | |||||||
377 | 6 | 27 | return \@res; | ||||
378 | } | ||||||
379 | |||||||
380 | ##@method void translate_template(string text_ref, string lang) | ||||||
381 | # translate_template is used as an HTML::Template filter to tranlate strings in | ||||||
382 | # the wanted language | ||||||
383 | #@param text_ref reference to the string to translate | ||||||
384 | #@param lang optionnal language wanted. Falls to browser language instead. | ||||||
385 | #@return | ||||||
386 | sub translate_template { | ||||||
387 | 0 | 0 | 0 | my $self = shift; | |||
388 | 0 | my $text_ref = shift; | |||||
389 | |||||||
390 | # Decode UTF-8 | ||||||
391 | 0 | 0 | utf8::decode($$text_ref) unless ( $ENV{FCGI_ROLE} ); | ||||
392 | |||||||
393 | # Test if a translation is available for the selected language | ||||||
394 | # If not available, return the first translated string | ||||||
395 | # |
||||||
396 | 0 | foreach ( @{ $self->{lang} } ) { | |||||
0 | |||||||
397 | 0 | 0 | if ( $$text_ref =~ m/$_=\"(.*?)\"/ ) { | ||||
398 | 0 | $$text_ref =~ s/ |
|||||
399 | 0 | return; | |||||
400 | } | ||||||
401 | } | ||||||
402 | 0 | $$text_ref =~ s/ |
|||||
403 | } | ||||||
404 | |||||||
405 | ##@method void session_template(string text_ref) | ||||||
406 | # session_template is used as an HTML::Template filter to replace session info | ||||||
407 | # by their value | ||||||
408 | #@param text_ref reference to the string to translate | ||||||
409 | #@return | ||||||
410 | sub session_template { | ||||||
411 | 0 | 0 | 0 | my $self = shift; | |||
412 | 0 | my $text_ref = shift; | |||||
413 | |||||||
414 | # Replace session information | ||||||
415 | 0 | $$text_ref =~ s/\$(\w+)/decode("utf8",$self->{sessionInfo}->{$1})/ge; | |||||
0 | |||||||
416 | } | ||||||
417 | |||||||
418 | ## @method private void quit() | ||||||
419 | # Simply exit. | ||||||
420 | sub quit { | ||||||
421 | 0 | 0 | 0 | my $self = shift; | |||
422 | 0 | 0 | if ( $_SUPER eq 'CGI::Fast' ) { | ||||
423 | 0 | next LMAUTH; | |||||
424 | } | ||||||
425 | else { | ||||||
426 | 0 | exit; | |||||
427 | } | ||||||
428 | } | ||||||
429 | |||||||
430 | ##@method string ipAddr() | ||||||
431 | # Retrieve client IP address from remote address or X-FORWARDED-FOR header | ||||||
432 | #@return client IP | ||||||
433 | sub ipAddr { | ||||||
434 | 0 | 0 | 0 | my $self = shift; | |||
435 | |||||||
436 | 0 | 0 | unless ( $self->{ipAddr} ) { | ||||
437 | 0 | $self->{ipAddr} = $ENV{REMOTE_ADDR}; | |||||
438 | 0 | 0 | if ( my $xheader = $ENV{HTTP_X_FORWARDED_FOR} ) { | ||||
439 | 0 | 0 | 0 | if ( $self->{trustedProxies} =~ /\*/ | |||
0 | |||||||
440 | or $self->{useXForwardedForIP} ) | ||||||
441 | { | ||||||
442 | 0 | 0 | $self->{ipAddr} = $1 if ( $xheader =~ /^([^,]*)/ ); | ||||
443 | } | ||||||
444 | elsif ( $self->{trustedProxies} ) { | ||||||
445 | 0 | my $localIP = | |||||
446 | Net::CIDR::Lite->new("127.0.0.0/8"); # TODO: add IPv6 local IP | ||||||
447 | 0 | my $trustedIP = | |||||
448 | Net::CIDR::Lite->new( split /\s+/, $self->{trustedProxies} ); | ||||||
449 | 0 | 0 | while ( | ||||
0 | |||||||
450 | ( | ||||||
451 | $localIP->find( $self->{ipAddr} ) | ||||||
452 | or $trustedIP->find( $self->{ipAddr} ) | ||||||
453 | ) | ||||||
454 | and $xheader =~ s/[,\s]*([^,\s]+)$// | ||||||
455 | ) | ||||||
456 | { | ||||||
457 | |||||||
458 | # because it is of no use to store a local IP as client IP | ||||||
459 | 0 | 0 | $self->{ipAddr} = $1 unless ( $localIP->find($1) ); | ||||
460 | } | ||||||
461 | } | ||||||
462 | } | ||||||
463 | } | ||||||
464 | 0 | return $self->{ipAddr}; | |||||
465 | } | ||||||
466 | |||||||
467 | 1; | ||||||
468 | |||||||
469 | __END__ |