1###############################################################################
2# Guardian.pm                                                                 #
3# $Date: 12.02.14 $                                                           #
4###############################################################################
5# YaBB: Yet another Bulletin Board                                            #
6# Open-Source Community Software for Webmasters                               #
7# Version:        YaBB 2.6.11                                                 #
8# Packaged:       December 2, 2014                                            #
9# Distributed by: http://www.yabbforum.com                                    #
10# =========================================================================== #
11# Copyright (c) 2000-2014 YaBB (www.yabbforum.com) - All Rights Reserved.     #
12# Software by:  The YaBB Development Team                                     #
13#               with assistance from the YaBB community.                      #
14###############################################################################
15# use strict;
16# use warnings;
17no warnings qw(uninitialized once redefine);
18use CGI::Carp qw(fatalsToBrowser);
19our $VERSION = '2.6.11';
20
21$guardianpmver = 'YaBB 2.6.11 $Revision: 1611 $';
22
23$not_from   = qq~$webmaster_email~;
24$not_to     = qq~$webmaster_email~;
25
26sub guard {
27    if ( !$use_guardian ) { return; }
28
29    # Proxy Blocker
30    $proxy0 = get_remote_addr();
31    $proxy1 = get_x_ip_client();
32    $proxy2 = get_x_forwarded();
33    $proxy3 = get_http_via();
34
35    @white_list = split /\|/xsm, $whitelist;
36    foreach (@white_list) {
37        chomp $_;
38        if (
39            (
40                   $proxy0 =~ m/$_/xsm
41                || $proxy1 =~ m/$_/xsm
42                || $proxy2 =~ m/$_/xsm
43                || $proxy3 =~ m/$_/xsm
44                || $username eq $_
45            )
46            && $_ ne q{}
47          )
48        {
49            $whitelisted = 1;
50            last;
51        }
52    }
53    if (   $disallow_proxy_on
54        && !$whitelisted
55        && !$iamadmin
56        && ( $proxy1 ne 'empty' || $proxy2 ne 'empty' || $proxy3 ne 'empty' ) )
57    {
58        if ($disallow_proxy_notify) {
59            LoadLanguage('Guardian');
60			$abuse_time = timeformat($date, 1, 'rfc', 1);
61            $not_subject =
62qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'proxy_abuse'} $guardian_txt{'abuse'}~;
63            $not_body =
64qq~$guardian_txt{'proxy_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
65            $not_body .=
66qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
67            $not_body .=
68qq~$guardian_txt{'abuse_ip'}: (REMOTE_ADDR)->$proxy0, (X_IP_CLIENT)->$proxy1, (HTTP_X_FORWARDED_FOR)->$proxy2, (HTTP_VIA)->$proxy3\n~;
69            if (   $use_htaccess
70                && $disallow_proxy_htaccess
71                && !$iamadmin
72                && !$iamgmod )
73            {
74                $not_body .= qq~$guardian_txt{'htaccess_added'}: $user_ip,\n\n~;
75            }
76            $not_body .= qq~$mbname, $guardian_txt{'main'}~;
77            $not_subject =~ s/\&trade\;//gxsm;
78            $not_body    =~ s/\&trade\;//gxsm;
79            $not_body = qq~<pre>$not_body</pre>~;
80            guardian_notify( $not_to, $not_subject, $not_body, $not_from );
81        }
82        if (   $use_htaccess
83            && $disallow_proxy_htaccess
84            && !$iamadmin
85            && !$iamgmod )
86        {
87            update_htaccess( 'add', $user_ip );
88        }
89        fatal_error('proxy_reason');
90    }
91
92    # Basic Value Setup
93    $remote = get_ip();
94    if ( index $remote, q{, } ) {
95        @remotes = split /\, /sm, $remote;
96        if (   $remotes[0] ne 'unknown'
97            && $remotes[0] ne 'empty'
98            && $remotes[0] ne '127.0.0.1'
99            && $remotes[0] ne q{} )
100        {
101            $remote = $remotes[0];
102        }
103        else {
104            $remote = $remotes[1];
105        }
106    }
107    $querystring = get_query_string();
108
109    # Check for Referer
110    if ($referer_on) {
111        @refererlist = split /\|/xsm, lc $banned_referers;
112        $streferer = lc get_referer();
113        foreach (@refererlist) {
114            chomp $_;
115            if ( $streferer =~ m/$_/xsm && $_ ne q{} ) {
116                LoadLanguage('Guardian');
117				$abuse_time = timeformat($date, 1, 'rfc', 1);
118                if ($referer_notify) {
119                    $not_subject =
120qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'referer_abuse'} $guardian_txt{'abuse'}~;
121                    $not_body =
122qq~$guardian_txt{'referer_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
123                    $not_body .=
124qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
125                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
126                    if (   $use_htaccess
127                        && $referer_htaccess
128                        && !$iamadmin
129                        && !$iamgmod )
130                    {
131                        $not_body .=
132                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
133                    }
134                    $not_body .=
135                      qq~$guardian_txt{'abuse_referer'}: $streferer\n\n~;
136                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
137                    $not_subject =~ s/\&trade\;//gxsm;
138                    $not_body    =~ s/\&trade\;//gxsm;
139                    guardian_notify( $not_to, $not_subject, $not_body,
140                        $not_from );
141                }
142                if (   $use_htaccess
143                    && $referer_htaccess
144                    && !$iamadmin
145                    && !$iamgmod )
146                {
147                    update_htaccess( 'add', $user_ip );
148                }
149                fatal_error('referer_reason');
150            }
151        }
152    }
153
154    # Check for Harvester
155    if ($harvester_on) {
156        @harvesterlist = split /\|/xsm, lc $banned_harvesters;
157        $agent = lc get_user_agent();
158        foreach (@harvesterlist) {
159            chomp $_;
160            if ( $agent =~ m/$_/xsm && $_ ne q{} ) {
161                if ($harvester_notify) {
162                    LoadLanguage('Guardian');
163					$abuse_time = timeformat($date, 1, 'rfc', 1);
164                    $not_subject =
165qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'harvester_abuse'} $guardian_txt{'abuse'}~;
166                    $not_body =
167qq~$guardian_txt{'harvester_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
168                    $not_body .=
169qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
170                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
171                    if (   $use_htaccess
172                        && $harvester_htaccess
173                        && !$iamadmin
174                        && !$iamgmod )
175                    {
176                        $not_body .=
177                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
178                    }
179                    $not_body .=
180                      qq~$guardian_txt{'abuse_harvester'}: $agent\n\n~;
181                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
182                    $not_subject =~ s/\&trade\;//gxsm;
183                    $not_body    =~ s/\&trade\;//gxsm;
184                    guardian_notify( $not_to, $not_subject, $not_body,
185                        $not_from );
186                }
187                if (   $use_htaccess
188                    && $harvester_htaccess
189                    && !$iamadmin
190                    && !$iamgmod )
191                {
192                    update_htaccess( 'add', $user_ip );
193                }
194                fatal_error('harvester_reason');
195            }
196        }
197    }
198
199    # Check for Request
200    if ($request_on) {
201        @requestlist = split /\|/xsm, lc $banned_requests;
202        $method = lc get_request_method();
203        foreach (@requestlist) {
204            chomp $_;
205            if ( $method =~ m/$_/xsm && $_ ne q{} ) {
206                if ($request_notify) {
207                    LoadLanguage('Guardian');
208					$abuse_time = timeformat($date, 1, 'rfc', 1);
209                    $not_subject =
210qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'request_abuse'} $guardian_txt{'abuse'}~;
211                    $not_body =
212qq~$guardian_txt{'request_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
213                    $not_body .=
214qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
215                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
216                    if (   $use_htaccess
217                        && $request_htaccess
218                        && !$iamadmin
219                        && !$iamgmod )
220                    {
221                        $not_body .=
222                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
223                    }
224                    $not_body .=
225                      qq~$guardian_txt{'abuse_request'}: $method\n\n~;
226                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
227                    $not_subject =~ s/\&trade\;//gxsm;
228                    $not_body    =~ s/\&trade\;//gxsm;
229                    guardian_notify( $not_to, $not_subject, $not_body,
230                        $not_from );
231                }
232                if (   $use_htaccess
233                    && $request_htaccess
234                    && !$iamadmin
235                    && !$iamgmod )
236                {
237                    update_htaccess( 'add', $user_ip );
238                }
239                fatal_error('request_reason');
240            }
241        }
242    }
243
244    # Check for Strings
245    if ($string_on) {
246        require Sources::SubList;
247        my ( $temp_query, $testkey );
248        $temp_query = lc $querystring;
249        @stringlist = split /\|/xsm, lc $banned_strings;
250        foreach (@stringlist) {
251            chomp $_;
252            foreach my $testkey ( keys %director )
253            { ## strip off all existing command strings from the temporary query ##
254                chomp $testkey;
255                $temp_query =~ s/$testkey//gxsm;
256            }
257            if ( $temp_query =~ m/$_/xsm && $_ ne q{} ) {
258                if ($string_notify) {
259                    LoadLanguage('Guardian');
260					$abuse_time = timeformat($date, 1, 'rfc', 1);
261                    $not_subject =
262qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'string_abuse'} $guardian_txt{'abuse'}~;
263                    $not_body =
264qq~$guardian_txt{'string_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
265                    $not_body .=
266qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
267                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
268                    if (   $use_htaccess
269                        && $string_htaccess
270                        && !$iamadmin
271                        && !$iamgmod
272                        && $action ne 'downloadfile' )
273                    {
274                        $not_body .=
275                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
276                    }
277                    $not_body .= qq~$guardian_txt{'abuse_string'}: $_\n~;
278                    $not_body .=
279                      qq~$guardian_txt{'abuse_environment'}: $querystring\n\n~;
280                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
281                    $not_subject =~ s/\&trade\;//gxsm;
282                    $not_body    =~ s/\&trade\;//gxsm;
283                    guardian_notify( $not_to, $not_subject, $not_body,
284                        $not_from );
285                }
286                if (   $use_htaccess
287                    && $string_htaccess
288                    && !$iamadmin
289                    && !$iamgmod )
290                {
291                    update_htaccess( 'add', $user_ip );
292                }
293                fatal_error( 'string_reason', "($_)" );
294            }
295        }
296    }
297
298    # Check for UNION attack (for MySQL database protection only)
299    if ($union_on) {
300        if (   $querystring =~ m/%20union%20/xsm
301            || $querystring =~ m/\*\/union\/\*/xsm )
302        {
303            if ($union_notify) {
304                LoadLanguage('Guardian');
305				$abuse_time = timeformat($date, 1, 'rfc', 1);
306                $not_subject =
307qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'union_abuse'} $guardian_txt{'abuse'}~;
308                $not_body =
309qq~$guardian_txt{'union_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
310                $not_body .=
311qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
312                $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
313                if (   $use_htaccess
314                    && $union_htaccess
315                    && !$iamadmin
316                    && !$iamgmod )
317                {
318                    $not_body .=
319                      qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
320                }
321                $not_body .=
322                  qq~$guardian_txt{'abuse_environment'}: $querystring\n\n~;
323                $not_body .= qq~$mbname, $guardian_txt{'main'}~;
324                $not_subject =~ s/\&trade\;//gxsm;
325                $not_body    =~ s/\&trade\;//gxsm;
326                guardian_notify( $not_to, $not_subject, $not_body, $not_from );
327            }
328            if ( $use_htaccess && $union_htaccess && !$iamadmin && !$iamgmod ) {
329                update_htaccess( 'add', $user_ip );
330            }
331            fatal_error('union_reason');
332        }
333    }
334
335    # Check for CLIKE attack (for MySQL database protection only)
336    if ($clike_on) {
337        if ( $querystring =~ m/\/\*/xsm ) {
338            if ($clike_notify) {
339                LoadLanguage('Guardian');
340				$abuse_time = timeformat($date, 1, 'rfc', 1);
341                $not_subject =
342qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'clike_abuse'} $guardian_txt{'abuse'}~;
343                $not_body =
344qq~$guardian_txt{'clike_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
345                $not_body .=
346qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
347                $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
348                if (   $use_htaccess
349                    && $clike_htaccess
350                    && !$iamadmin
351                    && !$iamgmod )
352                {
353                    $not_body .=
354                      qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
355                }
356                $not_body .=
357                  qq~$guardian_txt{'abuse_environment'}: $querystring\n\n~;
358                $not_body .= qq~$mbname, $guardian_txt{'main'}~;
359                $not_subject =~ s/\&trade\;//gxsm;
360                $not_body    =~ s/\&trade\;//gxsm;
361                guardian_notify( $not_to, $not_subject, $not_body, $not_from );
362            }
363            if ( $use_htaccess && $clike_htaccess && !$iamadmin && !$iamgmod ) {
364                update_htaccess( 'add', $user_ip );
365            }
366            fatal_error('clike_reason');
367        }
368    }
369
370    # Check for SCRIPTING attack
371    if ($script_on) {
372        while ( ( $key, $secvalue ) = each %INFO ) {
373            $secvalue = lc $secvalue;
374            str_replace( '%3c', '<', $secvalue );
375            str_replace( '%3e', '>', $secvalue );
376            if (   ( $secvalue =~ m/<[^>]script*\"?[^>]*>/xsm )
377                || ( $secvalue =~ m/<[^>]*object*\"?[^>]*>/xsm )
378                || ( $secvalue =~ m/<[^>]*iframe*\"?[^>]*>/xsm )
379                || ( $secvalue =~ m/<[^>]*applet*\"?[^>]*>/xsm )
380                || ( $secvalue =~ m/<[^>]*meta*\"?[^>]*>/xsm )
381                || ( $secvalue =~ m/<[^>]*style*\"?[^>]*>/xsm )
382                || ( $secvalue =~ m/<[^>]*form*\"?[^>]*>/xsm )
383                || ( $secvalue =~ m/\([^>]*\"?[^)]*\)/xsm )
384                || ( $secvalue =~ m/\"/xsm ) )
385            {    #";
386                if ($script_notify) {
387                    LoadLanguage('Guardian');
388					$abuse_time = timeformat($date, 1, 'rfc', 1);
389                    $not_subject =
390qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'script_abuse'} $guardian_txt{'abuse'}~;
391                    $not_body =
392qq~$guardian_txt{'script_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
393                    $not_body .=
394qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
395                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
396                    if (   $use_htaccess
397                        && $script_htaccess
398                        && !$iamadmin
399                        && !$iamgmod )
400                    {
401                        $not_body .=
402                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
403                    }
404                    $not_body .=
405                      qq~$guardian_txt{'abuse_url_environment'}: $secvalue\n\n~;
406                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
407                    $not_subject =~ s/\&trade\;//gxsm;
408                    $not_body    =~ s/\&trade\;//gxsm;
409                    guardian_notify( $not_to, $not_subject, $not_body,
410                        $not_from );
411                }
412                if (   $use_htaccess
413                    && $script_htaccess
414                    && !$iamadmin
415                    && !$iamgmod )
416                {
417                    update_htaccess( 'add', $user_ip );
418                }
419                fatal_error('script_reason');
420            }
421        }
422        while ( ( $key, $secvalue ) = each %FORM ) {
423            $secvalue = lc $secvalue;
424            if (    $key eq 'message'
425                and $action =~ /^(post|modify|imsend|eventcal)2$/xsm )
426            {
427                $secvalue =~ s/\[code.*?\/code\]//gsxm;
428            }
429            if (    $key eq 'message'
430                and $action =~ /^(ajxmessage|ajximmessage|ajxcal)$/xsm )
431            {
432                $secvalue =~ s/\[code.*?\/code\]//gsxm;
433            }
434            str_replace( '%3c', '<', $secvalue );
435            str_replace( '%3e', '>', $secvalue );
436            if (   ( $secvalue =~ m/<[^>]script*\"?[^>]*>/xsm )
437                || ( $secvalue =~ m/<[^>]style*\"?[^>]*>/xsm ) )
438            {
439                if ($script_notify) {
440                    LoadLanguage('Guardian');
441					$abuse_time = timeformat($date, 1, 'rfc', 1);
442                    $not_subject =
443qq~$guardian_txt{'main'}-($mbname): $guardian_txt{'script_abuse'} $guardian_txt{'abuse'}~;
444                    $not_body =
445qq~$guardian_txt{'script_abuse'} $guardian_txt{'abuse'} $maintxt{'30'} $abuse_time\n\n~;
446                    $not_body .=
447qq~$guardian_txt{'abuse_user'}: $username -> (${$uid.$username}{'realname'})\n~;
448                    $not_body .= qq~$guardian_txt{'abuse_ip'}: $user_ip\n~;
449                    if (   $use_htaccess
450                        && $script_htaccess
451                        && !$iamadmin
452                        && !$iamgmod )
453                    {
454                        $not_body .=
455                          qq~$guardian_txt{'htaccess_added'}: $user_ip,\n~;
456                    }
457                    $not_body .=
458qq~$guardian_txt{'abuse_form_environment'}: $secvalue\n\n~;
459                    $not_body .= qq~$mbname, $guardian_txt{'main'}~;
460                    $not_subject =~ s/\&trade\;//gxsm;
461                    $not_body    =~ s/\&trade\;//gxsm;
462                    guardian_notify( $not_to, $not_subject, $not_body,
463                        $not_from );
464                }
465                if (   $use_htaccess
466                    && $script_htaccess
467                    && !$iamadmin
468                    && !$iamgmod )
469                {
470                    update_htaccess( 'add', $user_ip );
471                }
472                fatal_error('script_reason');
473            }
474        }
475    }
476    return;
477}
478
479sub guardian_notify {
480    my ( $to, $subject, $body, $from ) = @_;
481    require Sources::Mailer;
482    my $result = sendmail( $to, $subject, $body, $from );
483    return;
484}
485
486sub get_remote_port {
487    if ( $ENV{'REMOTE_PORT'} ) {
488        return $ENV{'REMOTE_PORT'};
489    }
490    else {
491        return 'empty';
492    }
493}
494
495sub get_request_method {
496    if ( $ENV{'REQUEST_METHOD'} ) {
497        return $ENV{'REQUEST_METHOD'};
498    }
499    else {
500        return 'empty';
501    }
502}
503
504sub get_script_name {
505    if ( $ENV{'SCRIPT_NAME'} ) {
506        return $ENV{'SCRIPT_NAME'};
507    }
508    else {
509        return 'empty';
510    }
511}
512
513sub get_http_host {
514    if ( $ENV{'HTTP_HOST'} ) {
515        return $ENV{'HTTP_HOST'};
516    }
517    else {
518        return 'empty';
519    }
520}
521
522sub get_query_string {
523    if ( $ENV{'QUERY_STRING'} ) {
524        my $tempstring = str_replace( '%09', '%20', $ENV{'QUERY_STRING'} );
525        return str_replace( '%09', '%20', $ENV{'QUERY_STRING'} );
526    }
527    else {
528        return 'empty';
529    }
530}
531
532sub get_user_agent {
533    if ( $ENV{'HTTP_USER_AGENT'} ) {
534        return $ENV{'HTTP_USER_AGENT'};
535    }
536    else {
537        return 'empty';
538    }
539}
540
541sub get_referer {
542    if ( $ENV{'HTTP_REFERER'} ) {
543        return $ENV{'HTTP_REFERER'};
544    }
545    else {
546        return 'empty';
547    }
548}
549
550sub get_ip {
551    $client_ip   = get_client_ip();      ## HTTP_CLIENT_IP
552    $x_forwarded = get_x_forwarded();    ## HTTP_X_FORWARDED_FOR
553    $x_ip_client = get_x_ip_client();    ## X_IP_CLIENT
554    $http_via    = get_http_via();       ## HTTP_VIA
555    $remote_addr = get_remote_addr();    ## REMOTE_ADDR
556    if (   $client_ip
557        && $client_ip !~ m/empty/sm
558        && $client_ip !~ m/unknown/sm )
559    {
560        return $client_ip;
561    }
562    elsif ($x_forwarded
563        && $x_forwarded !~ m/empty/sm
564        && $x_forwarded !~ m/unknown/sm )
565    {
566        return $x_forwarded;
567    }
568    elsif ($x_ip_client
569        && $x_ip_client !~ m/empty/sm
570        && $x_ip_client !~ m/unknown/sm )
571    {
572        return $x_ip_client;
573    }
574    elsif ($http_via
575        && $http_via !~ m/empty/sm
576        && $http_via !~ m/unknown/sm )
577    {
578        return $http_via;
579    }
580    elsif ($remote_addr
581        && $remote_addr !~ m/empty/sm
582        && $remote_addr !~ m/unknown/sm )
583    {
584        return $remote_addr;
585    }
586    else {
587        return 'empty';
588    }
589}
590
591sub get_client_ip {
592    if ( $ENV{'HTTP_CLIENT_IP'} && $ENV{'HTTP_CLIENT_IP'} ne '127.0.0.1' ) {
593        return $ENV{'HTTP_CLIENT_IP'};
594    }
595    else {
596        return 'empty';
597    }
598}
599
600sub get_x_ip_client {
601    if ( $ENV{'X_CLIENT_IP'} && $ENV{'X_CLIENT_IP'} ne '127.0.0.1' ) {
602        return $ENV{'X_CLIENT_IP'};
603    }
604    else {
605        return 'empty';
606    }
607}
608
609sub get_http_via {
610    if ( $ENV{'HTTP_VIA'} && $ENV{'HTTP_VIA'} ne '127.0.0.1' ) {
611        return $ENV{'HTTP_VIA'};
612    }
613    else {
614        return 'empty';
615    }
616}
617
618sub get_x_forwarded {
619    if (   $ENV{'HTTP_X_FORWARDED_FOR'}
620        && $ENV{'HTTP_X_FORWARDED_FOR'} ne '127.0.0.1' )
621    {
622        return $ENV{'HTTP_X_FORWARDED_FOR'};
623    }
624    else {
625        return 'empty';
626    }
627}
628
629sub get_remote_addr {
630    if ( $ENV{'REMOTE_ADDR'} ) {
631        return $ENV{'REMOTE_ADDR'};
632    }
633    else {
634        return 'empty';
635    }
636}
637
638sub str_replace {
639    my ( $org, $repl, $target ) = @_;
640    $target =~ s/$org/$repl/igxsm;
641    return $target;
642}
643
644sub update_htaccess {
645    my ( $action, $value ) = @_;
646    my ( $htheader, $htfooter, @denies, @htout );
647    if ( !$action ) { return 0; }
648    fopen( HTA, '.htaccess' );
649    my @htlines = <HTA>;
650    fclose(HTA);
651
652# header to determine only who has access to the main script, not the admin script
653    $htheader = q~<Files YaBB*>~;
654    $htfooter = q~</Files>~;
655    $start    = 0;
656    foreach (@htlines) {
657        chomp $_;
658        if ( $_ eq $htheader ) { $start = 1; }
659        if ( $start == 0 && $_ !~ m/#/xsm && $_ ne q{} ) {
660            push @htout, "$_\n";
661        }
662        if ( $_ eq $htfooter ) { $start = 0; }
663        if ( $start == 1 && $_ =~ s/Deny from //gsm ) {
664            push @denies, $_;
665        }
666    }
667    if ( $use_htaccess && $action eq 'add' ) {
668        fopen( HTA, '>.htaccess' );
669        print {HTA} '# Last modified by The Guardian: '
670          . timeformat( $date, 1 )
671          . " #\n\n"
672          or croak "$croak{'print'} HTA";
673        print {HTA} @htout or croak "$croak{'print'} HTA";
674        if ($value) {
675            print {HTA} "\n$htheader\n" or croak "$croak{'print'} HTA";
676            push @denies, $value;
677            foreach (@denies) {
678                print {HTA} "Deny from $_\n"
679                      or croak "$croak{'print'} HTA";
680            }
681            print {HTA} "$htfooter\n" or croak "$croak{'print'} HTA";
682        }
683        fclose(HTA);
684    }
685    return;
686}
687
6881;
689