1###############################################################################
2# ErrorLog.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###############################################################################
15use CGI::Carp qw(fatalsToBrowser);
16our $VERSION = '2.6.11';
17
18$errorlogpmver = 'YaBB 2.6.11 $Revision: 1611 $';
19if ( $action eq 'detailedversion' ) { return 1; }
20
21sub ErrorLog {
22    is_admin_or_gmod();
23    $yytitle    = "$errorlog{'1'}";
24    $errorcount = 0;
25    fopen( ERRORFILE, "$vardir/errorlog.txt" );
26    @errors = <ERRORFILE>;
27    fclose(ERRORFILE);
28    $errorcount = @errors;
29    $date2      = $date;
30    $mytest = 0;
31    for my $i ( 0 .. ( $#errors ) ) {
32        my @tmpArray = split /\|/xsm, $errors[$i];
33        if ( $tmpArray[0] eq q{} || $tmpArray[0] =~ /[a-z]/igsm || $tmpArray[1] eq q{} || $tmpArray[1] =~ /[a-z]/igsm ) { next; }
34        else {
35            $date1 = $tmpArray[1];
36            calcdifference();
37            $date_ref = $result;
38            $tmplist[$mytest] = qq~$date_ref|$errors[$i]~;
39            $mytest++;
40        }
41    }
42
43    $sortmode  = $INFO{'sort'};
44    $sortorder = $INFO{'order'};
45    if ( $sortmode eq q{} ) {
46        $sortmode = 'time';
47    }
48    if ( $sortorder eq q{} ) {
49        $sortorder = 'reverse';
50    }
51    my @sortlist = ();
52    my $field    = '0';    # 0-based field defaults to the datecmp value
53    my $type     = '0';    # 0=numeric; 1=text
54    my $case     = '1';    # 0=case sensitive; 1=ignore case
55    my $dir      = '0';    # 0=increasing; 1=decreasing
56
57    if ( $sortmode eq 'time' ) {
58        $field = '1';
59        $type  = '0';
60        $case  = '1';
61        $dir   = '0';
62    }
63    elsif ( $sortmode eq 'users' ) {
64        $field = '8';
65        $type  = '1';
66        $case  = '1';
67        $dir   = '0';
68    }
69    elsif ( $sortmode eq 'ip' ) {
70        $field = '3';
71        $type  = '0';
72        $case  = '0';
73        $dir   = '0';
74    }
75    @sortlist =
76      map { $_->[0] }
77      sort { YaBBsort( $field, $type, $case, $dir ) }
78      map { [ $_, split /\|/xsm ] } @tmplist;
79
80    if ( $INFO{'order'} eq 'reverse' ) {
81        @sortlist = reverse @sortlist;
82    }
83    else {
84        if ( $sortmode eq 'time' ) {
85            $order_time = ';order=reverse';
86        }
87        elsif ( $sortmode eq 'users' ) {
88            $order_users = ';order=reverse';
89        }
90        elsif ( $sortmode eq 'ip' ) {
91            $order_ip = ';order=reverse';
92        }
93    }
94
95    if ( $sortmode ne q{} ) {
96        $sortmode = ';sort=' . $INFO{'sort'};
97    }
98    if ( $sortorder ne q{} ) {
99        $sortorder = ';order=' . $INFO{'order'};
100    }
101
102    $errorlog_error = q{};
103    if ( $#errors > $#tmplist ) {
104        $err = $#errors - $#tmplist;
105        $errorlog_error = qq~<br /><span class="important"><b>$errorlog{'27a'} $err $errorlog{'27b'}</b></span>~;
106        if ( $err == 1 ) {
107            $errorlog_error = qq~<br /><span class="important"><b>$errorlog{'27c'} $err $errorlog{'27d'}</b></span>~;
108        }
109    }
110    $yymain .= qq~\
111<script src="$yyhtml_root/ubbc.js" type="text/javascript"></script>
112<script type="text/javascript">
113function changeBox(cbox) {
114  box = eval(cbox);
115  box.checked = !box.checked;
116}
117function checkAll() {
118  for (var i = 0; i < document.errorlog_form.elements.length; i++) {
119    if(document.errorlog_form.elements[i].name != "subfield" && document.errorlog_form.elements[i].name != "msgfield") {
120            document.errorlog_form.elements[i].checked = true;
121        }
122    }
123}
124function uncheckAll() {
125  for (var i = 0; i < document.errorlog_form.elements.length; i++) {
126    if(document.errorlog_form.elements[i].name != "subfield" && document.errorlog_form.elements[i].name != "msgfield") {
127            document.errorlog_form.elements[i].checked = false;
128        }
129  }
130}
131</script>
132<form name="errorlog_form" action="$adminurl?action=deleteerror;$sortmode$sortorder" method="post" onsubmit="return submitproc()">
133<input type="hidden" name="button" value="4" />
134    <div class="bordercolor rightboxdiv">
135        <table class="border-space pad-cell" style="margin-bottom:.5em">
136            <colgroup>
137                <col style="width:5%" />
138                <col style="width:10%" />
139                <col style="width:15%" />
140                <col style="width:65%" />
141                <col style="width:5%" />
142            </colgroup>
143            <tr>
144                <td class="titlebg" colspan="5">$admin_img{'xx'} <b>$yytitle</b></td>
145            </tr><tr>
146                <td class="windowbg2" colspan="5"><div class="pad-more">$errorlog{'18'} $errorlog_error</div></td>
147            </tr><tr>
148                <td class="catbg center"><b>$errorlog{'21'}</b></td>
149                <td class="catbg center">
150                    <a href="$adminurl?action=errorlog$startmode;sort=time$order_time"><b>$errorlog{'5'}</b></a>
151                </td>
152                <td class="catbg center">
153                    <a href="$adminurl?action=errorlog$startmode;sort=users$order_users"><b>$errorlog{'11'}</b></a> ( <a href="$adminurl?action=errorlog$startmode;sort=ip$order_ip"><b>$errorlog{'6'}</b></a> )
154                </td>
155                <td class="catbg center"><b>$errorlog{'7'} / $errorlog{'8'}</b></td>
156                <td class="catbg center"><b>$errorlog{'13'}</b></td>
157            </tr>~;
158    $numshown  = 0;
159    $actualnum = 0;
160    $bb = 0;
161    while ( $numshown <= $errorcount ) {
162        my ( $tmp_user, $username, $numb, $ids, $all ) = q{};
163        $numshown++;
164        $sortlist[$bb] =~ s/<br \/>/\[br \/\]/gsm;
165        $sortlist[$bb] =~ s/<b>/\[b\]/gxsm;
166        $sortlist[$bb] =~ s/<\/b>/\[\/b\]/gxsm;
167        $sortlist[$bb] =~ s/</&lt;/gxsm;
168        $sortlist[$bb] =~ s/>/&gt;/gxsm;
169        $sortlist[$bb] =~ s/\[b\]/<b>/gxsm;
170        $sortlist[$bb] =~ s/\[\/b\]/<\/b>/gxsm;
171        $sortlist[$bb] =~ s/\[br \/\]/<br \/>/gsm;
172        my (
173            $tmp_datecmp,      $tmp_id,    $tmp_date,
174            $tmp_userip,       $tmp_error, $tmp_action,
175            $tmp_topic_number, $tmp_board, $tmp_username,
176            $tmp_password
177        ) = split /\|/xsm, $sortlist[$bb];
178        if ( !$tmp_id ) { next; }
179        FormatUserName($tmp_username);
180        if ( !$tmp_username ) {
181            $tmp_user = 'Guest';
182        }
183        else {
184            $tmp_user = $tmp_username;
185        }
186        $userlist{$tmp_user} = $userlist{$tmp_user} + 1;
187        $tmp_date = timeformat($tmp_date);
188        LoadUser($tmp_user);
189        my $ipBlock = q{};
190        my $lookupIP = qq{$tmp_userip};
191        my $ipBan = q{};
192        if ( $tmp_userip ne '127.0.0.1' ) {
193            $ipBlock = ( $use_guardian && $use_htaccess ) ? qq~<br /><a href="$adminurl?action=guardian_block;ip=$tmp_userip;return=errorlog" onclick="return confirm('$admin_txt{'ipblock_confirm'}$tmp_userip');">$admin_txt{'ipblock'}</a>~ : qq~<br /><a href="$adminurl?action=blockip;ip=$tmp_userip;return=errorlog" onclick="return confirm('$admin_txt{'ipblock_confirm'}$tmp_userip');">$admin_txt{'ipblock2'}</a>~;
194
195            $lookupIP =
196            ($ipLookup)
197            ? qq~<a href="$scripturl?action=iplookup;ip=$tmp_userip">$tmp_userip</a>~
198            : qq~$tmp_userip~;
199            $ipBan = qq~ - <a href="$adminurl?action=ipban_err;ban=$tmp_userip;lev=p;return=errorlog" onclick="return confirm('$admin_txt{'ipban_confirm'}$tmp_userip');">$admin_txt{'725f'}</a>~;
200            }
201            if ( $tmp_user eq "$useraccount{$tmp_user}" ) {
202                if ( $userprofile{$tmp_user}->[1] ) {
203                $username =
204qq~<a href="$scripturl?action=viewprofile;username=$useraccount{$tmp_user}" target="_blank">$userprofile{$tmp_user}->[1]</a>~;
205                }
206                else {
207                    $username .= qq~$useraccount{$tmp_user}~;
208                }
209                $username .=
210qq~<br />$lookupIP$ipBan$ipBlock~;
211            }
212            else {
213                $username = qq~$tmp_user<br />$lookupIP$ipBan$ipBlock~;
214            }
215        if ( $tmp_topic_number eq q{} ) {
216            $numb = "&amp;action=$tmp_action";
217        }
218        else {
219            $numb = "&amp;action=$tmp_action&amp;num=$tmp_topic_number";
220        }
221        if ( $tmp_board eq q{} ) {
222            $ids = '?board=';
223        }
224        else {
225            $ids = "?board=$tmp_board";
226        }
227        if ( $tmp_action eq q{} && $tmp_board eq q{} ) {
228            $all = "$boardurl/$yyexec.$yyext";
229        }
230        else {
231            $all = "$boardurl/$yyexec.$yyext$ids$numb";
232        }
233        if ( $tmp_error eq $admin_txt{'39'} || $tmp_error eq $admin_txt{'40'} )
234        {
235            $tmp_error =
236              $tmp_error . qq~ - (<span class="important">$tmp_password</span>)~;
237        }
238
239        $bb++;
240        $addel =
241qq~                <td class="windowbg center"><input type="checkbox" name="error$tmp_id" value="$tmp_id" class="windowbg" style="border: 0;" /></td>~;
242        $actualnum++;
243        $print_errorlog .= qq~<tr>
244                <td class="windowbg center">$actualnum</td>
245                <td class="windowbg">$tmp_date</td>
246                <td class="windowbg2 center">$username</td>
247                <td class="windowbg center">
248                    <div class="small" style="height:5em; overflow:auto">$tmp_error<br /><a href="$all">$all</a></div>
249                </td>
250                $addel
251            </tr>~;
252    }
253    if ( !($actualnum) ) {
254        $print_errorlog = qq~<tr>
255                <td class="windowbg2 center" colspan="5">$errorlog{'19'}</td>
256            </tr>~;
257    }
258    $yymain .= qq~
259$print_errorlog
260    ~;
261
262    @userlist = reverse sort { $userlist{$a} <=> $userlist{$b} } keys %userlist;
263    foreach my $member (@userlist) {
264        $errmember .= qq~$member ($userlist{$member}), ~;
265    }
266    $errmember =~ s/, \Z//sm;
267
268    $yymain .= qq~          <tr>
269                <td class="windowbg2" colspan="5"><div class="pad-more"><b>$errorlog{'26'}</b> $errmember</div></td>
270            </tr><tr>
271                <td class="windowbg right" colspan="4">&nbsp;~;
272    if ( $errorcount > 0 ) {
273        $yymain .=
274          qq~<label for="checkall"><b>$admin_txt{'737'}</b></label>&nbsp;~;
275    }
276    $yymain .= q~
277                </td>
278                <td class="windowbg center">&nbsp;~;
279    if ( $errorcount > 0 ) {
280        $yymain .=
281q~<input type="checkbox" name="checkall" id="checkall" class="windowbg" style="border: 0;" onclick="if (this.checked) checkAll(); else uncheckAll();" />~;
282    }
283    $yymain .= q~
284            </td>
285        </tr>
286    </table>
287</div>~;
288
289    if ( $errorcount > 0 ) {
290
291        $yymain .= qq~
292<div class="bordercolor rightboxdiv">
293    <table class="border-space pad-cell">
294        <tr>
295            <th class="titlebg">$admin_img{'prefimg'} $errorlog{'14'}</th>
296        </tr><tr>
297            <td class="catbg center">
298                <input type="submit" value="$errorlog{'14'}" onclick="return confirm('$errorlog{'15'}')" class="button" />
299                <br /><a href="$boardurl/AdminIndex.$yyaext?action=cleanerrorlog" onclick="return confirm('$errorlog{'15a'}')">$errorlog{'14a'}</a>
300            </td>
301        </tr>
302    </table>
303</div>~;
304    }
305
306    $yymain .= q~
307</form>
308~;
309    $action_area = 'errorlog';
310    AdminTemplate();
311    return;
312}
313
314sub CleanErrorLog {
315    is_admin_or_gmod();
316    if ( -e ("$vardir/errorlog.txt") ) {
317        unlink "$vardir/errorlog.txt" or croak qq~$!~;
318    }
319    $yySetLocation = qq~$adminurl?action=errorlog~;
320    redirectexit();
321    return;
322}
323
324sub DeleteError {
325    is_admin_or_gmod();
326    my ( $sortmode, $sortorder );
327    chomp $FORM{'button'};
328    if ( $FORM{'button'} ne '4' ) { fatal_error('no_access'); }
329    fopen( FILE, "$vardir/errorlog.txt" );
330    @errors = <FILE>;
331    fclose(FILE);
332    unlink "$vardir/errorlog.txt";
333    fopen( FILE, ">>$vardir/errorlog.txt" );
334
335    foreach my $line (@errors) {
336        chomp $line;
337        my (
338            $tmp_id,    $tmp_date,  $tmp_username,
339            $tmp_error, $tmp_board, $tmp_action
340        ) = split /\|/xsm, $line;
341        if ( !exists $FORM{"error$tmp_id"} ) {
342            print {FILE} $line . "\n" or croak "$croak{'print'} FILE";
343        }
344    }
345    fclose(FILE);
346    $yySetLocation = qq~$adminurl?action=errorlog~;
347    redirectexit();
348    return;
349}
350
351# Moved here from Subs.pm since it was only used here
352sub YaBBsort {
353    my $field = ( shift || 0 ) + 1;    # 0-based field
354    my $type = shift || 0;             # 0=numeric; 1=text
355    my $case = shift || 0;             # 0=case sensitive; 1=ignore case
356    my $dir  = shift || 0;             # 0=increasing; 1=decreasing
357
358    if ( $type == 0 ) {
359        if ( $dir == 0 ) {
360            $a->[$field] <=> $b->[$field];
361        }
362        else {
363            $b->[$field] <=> $a->[$field];
364        }
365    }
366    else {
367        if ( $case == 0 ) {
368            if ( $dir == 0 ) {
369                $a->[$field] cmp $b->[$field];
370            }
371            else {
372                $b->[$field] cmp $a->[$field];
373            }
374        }
375        else {
376            if ( $dir == 0 ) {
377                uc $a->[$field] cmp uc $b->[$field];
378            }
379            else {
380                uc $b->[$field] cmp uc $a->[$field];
381            }
382        }
383    }
384    return 1;
385}
386
387sub update_htaccess {
388    my ( $action, @values ) = @_;
389    my ( $htheader, $htfooter, @denies, @htout );
390    if ( !$action ) { return 0; }
391    fopen( HTA, '.htaccess' );
392    @htlines = <HTA>;
393    fclose(HTA);
394
395# header to determine only who has access to the main script, not the admin script
396    $htheader = q~<Files YaBB*>~;
397    $htfooter = q~</Files>~;
398    $start    = 0;
399    foreach (@htlines) {
400        chomp $_;
401        if ( $_ eq $htheader ) { $start = 1; }
402        if ( $start == 0 && $_ !~ m{#}sm && $_ ne q{} ) { push @htout, "$_\n"; }
403        if ( $_ eq $htfooter ) { $start = 0; }
404        if ( $start == 1 && $_ =~ s/Deny from //gsm ) {
405            push @denies, $_;
406        }
407    }
408    if ( $action eq 'load' ) {
409        return @denies;
410    }
411    elsif ( $action eq 'save' ) {
412        fopen( HTA, '>.htaccess' );
413        print {HTA} '# Last modified by YaBB: '
414          . timeformat( $date, 1 )
415          . " #\n\n"
416          or croak "$croak{'print'} HTA";
417        print {HTA} @htout or croak "$croak{'print'} HTA";
418        if (@values) {
419            print {HTA} "\n$htheader\n" or croak "$croak{'print'} HTA";
420            foreach (@values) {
421                chomp $_;
422                if ( $_ ne q{} ) {
423                    print {HTA} "Deny from $_\n" or croak "$croak{'print'} HTA";
424                }
425            }
426            print {HTA} "$htfooter\n" or croak "$croak{'print'} HTA";
427        }
428        fclose(HTA);
429    }
430    elsif ( $action eq 'add' ) {
431        push @denies, @values;
432    update_htaccess( 'save', @denies );
433    }
434    return;
435}
436
437sub blockip {
438    is_admin_or_gmod();
439    my $blockIP = $INFO{'ip'};
440    update_htaccess( 'add', $blockIP );
441    $yySetLocation = qq~$adminurl?action=errorlog~;
442    redirectexit();
443    return;
444}
445
4461;
447