###############################################################################
# Admin.pl                                                                    #
###############################################################################
# YaBB: Yet another Bulletin Board                                            #
# Open-Source Community Software for Webmasters                               #
# Version:        YaBB 2.2.3                                                  #
# Packaged:       July 12, 2008                                               #
# Distributed by: http://www.yabbforum.com                                    #
# =========================================================================== #
# Copyright (c) 2000-2008 YaBB (www.yabbforum.com) - All Rights Reserved.     #
# Software by:  The YaBB Development Team                                     #
#               with assistance from the YaBB community.                      #
# Sponsored by: Xnull Internet Media, Inc. - http://www.ximinc.com            #
#               Your source for web hosting, web design, and domains.         #
###############################################################################

$YaBBversion = 'YaBB 2.2.3';
$adminplver  = 'YaBB 2.2.3 $Revision: 1.80.2.22 $';

sub Admin {
	&is_admin_or_gmod;

	$yymain .= qq~
 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
       <td align="left" class="titlebg" colspan="2">
        <b>$admintxt{'1'}</b>
      </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2">
        <img alt="Admin Centre Logo" src="$defaultimagesdir/aarea.jpg" />
       </td>
       <td align="left" class="windowbg2">
        $admintxt{'2'}
      </td>
     </tr>
   </table>
 </div>

<br />

<div style="float: left; width: 49%; text-align: left;">

 <div class="bordercolor" style="padding: 0px; width: 95%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
       <td align="left" class="titlebg">
        <b>$admintxt{'6'}</b>
      </td>
     </tr>
     <tr align="center" valign="middle">
       <td align="left" class="catbg">
        <span class="small">YaBB 2</span>
       </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2"><br />
Ron Hartendorp, Andrew Aitken, Carsten Dalgaard, Ryan Farrington, Zoltan Kovacs, Tim Ceuppens, Shoeb Omar, Torsten Mrotz, Brian Schaefer, Juvenall Wilson, Corey Chapman, Christer Jenson, Adrian Kreher, Steve Brereton, Jeffrey Man, Boris Tjuvanov, Detlef Pilzecker, $yabbBeta<br /><br />
      </td>
     </tr>
     <tr align="center" valign="middle">
       <td align="left" class="catbg">
        <span class="small">$yabbThanks</span>
       </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2"><br />
Dave Baughman, Bjoern Berg, Corey Chapman, Peter Crouch, ejdmoo, Dave G, Christian Land, Jeff Lewis, Gunther Meyer, Darya Misse, Parham Mofidi, AstroPilot, Torsten Mrotz, Carey P, Popeye, Michael Prager, Matt Siegman, Jay Silverman, StarSaber, Marco van Veelen, Myhailo Danylenko, $yabb2Credits<br /><br />
$noBytesHarmed<br /><br />
      </td>
     </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 95%; margin-left: 0px; margin-right: auto;">
  <script language="JavaScript" type="text/javascript">
  <!-- //hide from dinosaurs
	var STABLE;
  // -->
  </script>
  <script language="javascript" src="http://www.yabbforum.com/update/versioncheck.js" type="text/javascript"></script>
  <script language="JavaScript" type="text/javascript">
  <!-- //hide from dinosaurs
	document.write('<table width="100%" cellspacing="1" cellpadding="4">');		
	document.write('<tr><td colspan="2" class="titlebg"><b>$admintxt{'3'}</b></td></tr>');
	document.write('<tr><td class="windowbg2">$versiontxt{'4'}</td><td class="windowbg2"><b>$YaBBversion</b></td></tr>');
	if (!STABLE) {
		document.write('<tr><td colspan="2" class="titlebg">$rna</b></td></tr>');
	} else {
		document.write('<tr><td class="windowbg2">$versiontxt{'5'}</td><td class="windowbg2"><b>'+STABLE+'</b></td></tr>');
		document.write('<tr><td class="windowbg2">$versiontxt{'7'}</td><td class="windowbg2"><b>'+BETA+'</b></td></tr>');
		document.write('<tr><td class="windowbg2">$versiontxt{'8'}</td><td class="windowbg2"><b>'+ALPHA+'</b></td></tr>');
		if (STABLE == "$YaBBversion") {
			document.write('<tr><td colspan="2" valign="middle" class="windowbg2"><br />$versiontxt{'6'}<br /><br /></td></tr>');
		} else {
			document.write('<tr><td colspan="2" valign="middle" class="windowbg2"><br />$versiontxt{'2'}'+STABLE+'$versiontxt{'3'}<br /><br /></td></tr>');
		}
	}
	document.write('</table>');
  // -->
  </script>
  <noscript>$versiontxt{'1'}</noscript>
 </div>

</div>
<div style="float: left; width: 50%; text-align: right;">

 <div class="bordercolor" style="padding: 0px; width: 100%; margin-left: auto; margin-right: 0px;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
       <td align="left" class="titlebg">
        <b>$admintxt{'4'}</b>
      </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2">
        <iframe src="http://www.yabbforum.com/update/" frameborder="0" width="100%" height="293">$iFrameSupport</iframe>
      </td>
     </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 100%; margin-left: auto; margin-right: 0px;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
       <td align="left" class="titlebg">
        <b>$admintxt{'5'}</b>
      </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2">~;

	&GetLastLogins;

	$yymain .= qq~
      </td>
     </tr>
   </table>
 </div>~;

	if (-d "./Convert") {
		$yymain .= qq~
<br />
<div class="bordercolor" style="padding: 0px; width: 100%; margin-left: auto; margin-right: 0px;">
<form name="backdelete" action="$adminurl?action=convdelete" method="post">
<table width="100%" cellspacing="1" cellpadding="4">
	<tr valign="middle">
	<td align="left" class="titlebg">
		<b>$admintxt{'7'}</b>
	</td>
	</tr>
	<tr valign="middle">
	<td align="left" class="windowbg2"><br />
		$admintxt{'8'}<br /><br />
	</td>
	</tr>
	<tr valign="middle">
	<td align="center" class="catbg">
		<input type="submit" value="$admintxt{'9'}" class="button" />
	</td>
	</tr>
</table>
</form>
</div>~;
	}

	$yymain .= qq~
<div style="height: 130px;">&nbsp;</div>
</div>~;
	$yytitle = "$admin_txt{'208'}";
	&AdminTemplate;
}

sub DeleteConverterFiles {
	my @convertdir = qw~Boards Members Messages Variables~;

	foreach $cnvdir (@convertdir) {
		$convdir = "./Convert/$cnvdir";
		if (-d "$convdir") {
			opendir("CNVDIR", $convdir) || &admin_fatal_error("cannot_open_dir","$convdir");
			@convlist = readdir("CNVDIR");
			closedir("CNVDIR");
			foreach $file (@convlist) {
				unlink "$convdir/$file" || &admin_fatal_error("cannot_open_dir","$convdir/$file");
			}
			rmdir("$convdir");
		}
	}
	$convdir = "./Convert";
	if (-d "$convdir") {
		opendir("CNVDIR", $convdir) || &admin_fatal_error("cannot_open_dir","$convdir");
		@convlist = readdir("CNVDIR");
		closedir("CNVDIR");
		foreach $file (@convlist) {
			unlink "$convdir/$file";
		}
		rmdir("$convdir");
	}
	if (-e "./Setup.pl") { unlink("./Setup.pl"); }

	$yymain .= qq~<b>$admintxt{'10'}</b>~;
	$yytitle = "$admintxt{'10'}";
	&AdminTemplate;
	exit;
}

sub GetLastLogins {
	fopen(ADMINLOG, "$vardir/adminlog.txt");
	@adminlog = <ADMINLOG>;
	fclose(ADMINLOG);

	foreach $line (@adminlog) {
		chomp $line;
		@element = split(/\|/, $line);
		if (!${$uid.$element[0]}{'realname'}) { &LoadUser($element[0]); }    # If user is not in memory, s/he must be loaded.
		$element[2] = &timeformat($element[2]);
		$yymain .= qq~
		<a href="$scripturl?action=viewprofile;username=$useraccount{$element[0]}">${$uid.$element[0]}{'realname'}</a> <span class="small">($element[1]) - $element[2]</span><br />
		~;
	}
}

sub FullStats {
	&is_admin_or_gmod;
	my ($numcats, $numboards, $threadcount, $messagecount, $maxdays, $totalt, $totalm, $avgt, $avgm);
	my ($memcount, $latestmember) = &MembershipGet;
	&LoadUser($latestmember);
	$thelatestmember = qq~<a href="$scripturl?action=viewprofile;username=$useraccount{$latestmember}">${$uid.$latestmember}{'realname'}</a>~;
	$memcount ||= 1;

	$numcats = 0;

	unless ($mloaded == 1) { require "$boardsdir/forum.master"; }
	foreach $catid (@categoryorder) {
		$boardlist = $cat{$catid};
		$numcats++;
		(@bdlist) = split(/\,/, $boardlist);
		($catname, $catperms, $catallowcol) = split(/\|/, $catinfo{"$catid"});

		foreach $curboard (@bdlist) {
			chomp $curboard;
			$numboards++;
			push(@loadboards, $curboard);

		}
	}

	&BoardTotals("load", @loadboards);
	foreach $curboard (@loadboards) {

		$totalm += ${$uid.$curboard}{'messagecount'};
		$totalt += ${$uid.$curboard}{'threadcount'};

	}

	$avgm = int($totalm / $memcount);
	&LoadAdmins;

	if ($enableclicklog) {
		my (@log);
		fopen(LOG, "$vardir/clicklog.txt");
		@log = <LOG>;
		fclose(LOG);
		$yyclicks    = @log;
		$yyclicktext = $admin_txt{'692'};
		$yyclicklink = qq~$yyclicks&nbsp;(<a href="$adminurl?action=showclicks">$admin_txt{'693'}</a>)~;

	} else {
		$yyclicktext = $admin_txt{'692a'};
		$yyclicklink = "";
	}
	my (@elog);
	fopen(ELOG, "$vardir/errorlog.txt");
	@elog = <ELOG>;
	fclose(ELOG);
	$errorslog = @elog;

	$yymain .= qq~
 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
      <td align="left" class="titlebg">
        <img src="$imagesdir/info.gif" alt="" border="0" /> <b>$admintxt{'28'}</b>
      </td>
     </tr>
     <tr valign="middle">
      <td align="left" class="catbg">
       <i>$admin_txt{'94'}</i>
      </td>
     </tr>
     <tr valign="middle">
      <td align="left" class="windowbg2"><br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'488'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$memcount</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'490'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$totalt</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'489'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$totalm</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admintxt{'39'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$avgm</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'658'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$numcats</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'665'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$numboards</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$errorlog{'3'}</div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$errorslog</div>
       <br />
       <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'691'}&nbsp;<span class="small">($yyclicktext)</span></div>
       <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$yyclicklink</div>
       <br />&nbsp;<br />
      </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="catbg">
        <i>$admin_txt{'657'}</i>
      </td>
     </tr>
     <tr valign="middle">
       <td align="left" class="windowbg2"><br />
        <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'656'}</div>
        <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$thelatestmember</div>
        <br />
        <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'659'}</div>
        <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">
        ~;

	# Sorts the threads to find the most recent post
	# No need to check for board access here because only admins have access to this page
	unless ($mloaded == 1) { require "$boardsdir/forum.master"; }
	foreach $catid (@categoryorder) {
		$boardlist = $cat{$catid};
		(@bdlist) = split(/\,/, $boardlist);
		foreach $curboard (@bdlist) {
			push(@goodboards, $curboard);
		}
	}

	&BoardTotals("load", @goodboards);
	&getlog(@goodboards);
	foreach $curboard (@goodboards) {
		chomp $curboard;
		$lastposttime = ${$uid.$curboard}{'lastposttime'};
		$lastposttime{$curboard} = &timeformat(${$uid.$curboard}{'lastposttime'});
		${$uid.$curboard}{'lastposttime'} = ${$uid.$curboard}{'lastposttime'} eq 'N/A' || !${$uid.$curboard}{'lastposttime'} ? $boardindex_txt{'470'} : ${$uid.$curboard}{'lastposttime'};
		$lastpostrealtime{$curboard} = ${$uid.$curboard}{'lastposttime'} eq 'N/A' || !${$uid.$curboard}{'lastposttime'} ? '' : ${$uid.$curboard}{'lastposttime'};
		if (${$uid.$curboard}{'lastposter'} =~ m~\AGuest-(.*)~) {
			${$uid.$curboard}{'lastposter'} = $1;
			$lastposterguest{$curboard} = 1;
		}
		${$uid.$curboard}{'lastposter'} = ${$uid.$curboard}{'lastposter'} eq 'N/A' || !${$uid.$curboard}{'lastposter'} ? $boardindex_txt{'470'} : ${$uid.$curboard}{'lastposter'};
		${$uid.$curboard}{'messagecount'} = ${$uid.$curboard}{'messagecount'} || 0;
		${$uid.$curboard}{'threadcount'} = ${$uid.$curboard}{'threadcount'} || 0;
		$totalm += ${$uid.$curboard}{'messagecount'};
		$totalt += ${$uid.$curboard}{'threadcount'};

		# determine the true last post on all the boards a user has access to
		if ($lastposttime > $lastthreadtime) {
			$lsdatetime = &timeformat($lastposttime);
			$lsposter = ${$uid.$curboard}{'lastposter'};
			$lssub = ${$uid.$curboard}{'lastsubject'};
			$lspostid = ${$uid.$curboard}{'lastpostid'};
			$lsreply = ${$uid.$curboard}{'lastreply'};
			$lastthreadtime = $lastposttime;
		}
	}
	$lssub =~ s/\A\[m.*?\]/$maintxt{'758'}/;
	&ToChars($lssub);
	$yymain .= qq~<a href="$scripturl?num=$lspostid/$lsreply#$lsreply">$lssub</a> ($lsdatetime)</div>
        <br />
        <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'684'}</div>
        <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$administrators</div>
        <br />
        <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'684a'}</div>
        <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$gmods</div>
        <br />
        <div style="float: left; clear: left; width: 35%; text-align: left; padding-top: 2px; padding-bottom: 2px;">$admin_txt{'425'}</div>
        <div style="float: left; width: 65%; text-align: left; padding-top: 2px; padding-bottom: 2px;">
        <script language="javascript" src="http://www.yabbforum.com/update/versioncheck.js" type="text/javascript"></script>
        <script language="JavaScript" type="text/javascript">  
         <!-- //hide from dinosaurs  
          document.write("$versiontxt{'4'} <b>$YaBBversion</b> - $versiontxt{'5'} <b>"+STABLE+"</b> <p>");  
         // -->
        </script>
        <noscript>$versiontxt{'1'} <img src="http://www.yabbforum.com/images/version/versioncheck.gif" alt="" /></noscript> 
        </div>
        <br />&nbsp;<br />
      </td>
     </tr>
   </table>
 </div>~;

	$yytitle = $admintxt{'28'};
	$action_area = "stats";
	&AdminTemplate;
	exit;
}

sub LoadAdmins {
	&is_admin_or_gmod;
	my (@members, $curentry, $memdata);
	$administrators = "";
	$gmods          = "";
	&ManageMemberinfo("load");
	while (($membername, $value) = each(%memberinf)) {
		($memberrealname, undef, $memposition, $memposts) = split(/\|/, $value);
		if($do_scramble_id){$membernameCloaked = &cloak($membername); } else { $membernameCloaked = $membername; }
		if ($memposition eq "Administrator") {
			$administrators .= qq~ <a href="$scripturl?action=viewprofile;username=$membernameCloaked">$memberrealname</a><span class="small">,</span> \n~;
		}
		if ($memposition eq "Global Moderator") {
			$gmods .= qq~ <a href="$scripturl?action=viewprofile;username=$membernameCloaked">$memberrealname</a><span class="small">,</span> \n~;
		}
	}
	$administrators =~ s~<span class="small">,</span> \n\Z~~;
	$gmods          =~ s~<span class="small">,</span> \n\Z~~;
	if ($gmods eq "") { $gmods = qq~&nbsp;~; }
	undef %memberinf;
}

sub ShowClickLog {
	&is_admin_or_gmod;

	if ($enableclicklog) { $logtimetext = $admin_txt{'698'}; }
	else { $logtimetext = $admin_txt{'698a'}; }

	my ($totalip, $totalclick, $totalbrow, $totalos, @log, @iplist, $date, @to, @from, @info, @os, @browser, @newiplist, @newbrowser, @newoslist, @newtolist, @newfromlist, $i, $curentry);
	fopen(LOG, "$vardir/clicklog.txt");
	@log = <LOG>;
	fclose(LOG);

	$i = 0;
	foreach $curentry (@log) {
		($iplist[$i], $date, $to[$i], $from[$i], $info[$i]) = split(/\|/, $curentry);
		$i++;
	}
	$i = 0;
	foreach $curentry (@info) {
		if ($curentry !~ /\s\(Win/i || $curentry !~ /\s\(mac/) { $curentry =~ s/\s\((compatible;\s)*/ - /ig; }
		else { $curentry =~ s/(\S)*\(/; /g; }
		if ($curentry =~ /\s-\sWin/i) { $curentry =~ s/\s-\sWin/; win/ig; }
		if ($curentry =~ /\s-\sMac/i) { $curentry =~ s/\s-\sMac/; mac/ig; }
		($browser[$i], $os[$i]) = split(/\;\s/, $curentry);
		if ($os[$i] =~ /\)\s\S/) { ($os[$i], $browser[$i]) = split(/\)\s/, $os[$i]); }
		$os[$i] =~ s/\)//g;
		$i++;
	}

	for ($i = 0; $i < @iplist; $i++) { $iplist{ $iplist[$i] }++; }
	$i = 0;
	while (($key, $val) = each(%iplist)) {
		$newiplist[$i] = [$key, $val];
		$i++;
	}
	$totalclick = @iplist;
	$totalip    = @newiplist;
	for ($i = 0; $i < @newiplist; $i++) {

		if ($newiplist[$i]->[0] =~ /\S+/ && $newiplist[$i]->[0] =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) {
			$guestiplist .= qq~$newiplist[$i]->[0]&nbsp;<span style="color: #FF0000;">(<i>$newiplist[$i]->[1]</i>)</span><br />~;
		} else {
			&LoadUser($newiplist[$i]->[0]);
			if($do_scramble_id){$cloakedUserName = &cloak($newiplist[$i]->[0]); } else {$cloakedUserName = $newiplist[$i]->[0]; }
			my $displayUserName = $newiplist[$i]->[0];
			if(${$uid.$displayUserName}{'realname'} && (${$uid.$displayUserName}{'realname'} ne $newiplist[$i]->[0])) 	{
				$displayUserName = ${$uid.$displayUserName}{'realname'};}
			$useriplist .= qq~<a href="$scripturl?action=viewprofile;username=$cloakedUserName">$displayUserName</a>&nbsp;<span style="color: #FF0000;">(<i>$newiplist[$i]->[1]</i>)</span><br />~;
		}
	}

	for ($i = 0; $i < @browser; $i++) { $browser{ $browser[$i] }++; }
	$i = 0;
	while (($key, $val) = each(%browser)) {
		$newbrowser[$i] = [$key, $val];
		$i++;
	}
	$totalbrow = @newbrowser;
	for ($i = 0; $i < @newbrowser; $i++) {
		if ($newbrowser[$i]->[0] =~ /\S+/) {
			$browserlist .= qq~$newbrowser[$i]->[0] &nbsp;<span style="color: #FF0000;">(<i>$newbrowser[$i]->[1]</i>)</span><br />~;
		}
	}

	for ($i = 0; $i < @os; $i++) { $os{ $os[$i] }++; }
	$i = 0;
	while (($key, $val) = each(%os)) {
		$newoslist[$i] = [$key, $val];
		$i++;
	}
	$totalos = @newoslist;
	for ($i = 0; $i < @newoslist; $i++) {
		if ($newoslist[$i]->[0] =~ /\S+/) {
			$oslist .= qq~$newoslist[$i]->[0] &nbsp;<span style="color: #FF0000;">(<i>$newoslist[$i]->[1]</i>)</span><br />~;
		}
	}

	for ($i = 0; $i < @to; $i++) { $to{ $to[$i] }++; }
	$i = 0;
	while (($key, $val) = each(%to)) {
		$newtolist[$i] = [$key, $val];
		$i++;
	}
	for ($i = 0; $i < @newtolist; $i++) {
		if ($newtolist[$i]->[0] =~ /\S+/) {
			$scriptcalls .= qq~<a href="$newtolist[$i]->[0]" target="_blank">$newtolist[$i]->[0]</a>&nbsp;<span style="color: #FF0000;">(<i>$newtolist[$i]->[1]</i>)</span><br />~;
		}
	}

	for ($i = 0; $i < @from; $i++) { $from{ $from[$i] }++; }
	$i = 0;
	while (($key, $val) = each(%from)) {
		$newfromlist[$i] = [$key, $val];
		$i++;
	}
	for ($i = 0; $i < @newfromlist; $i++) {
		if ($newfromlist[$i]->[0] =~ /\S+/ && $newfromlist[$i]->[0] !~ m~$boardurl~i) {
		$message = qq~<a href="$newfromlist[$i]->[0]" target="_blank">$newfromlist[$i]->[0]</a>~;
		#	&wrap;
		#	if (!$yyYaBBCloaded) { require "$sourcedir/YaBBC.pl"; }
		#	&DoUBBC;
			&wrap2;
			$referlist .= qq~$message&nbsp;<span style="color: #FF0000;">(<i>$newfromlist[$i]->[1]</i>)</span><br />~;
		}
	}

	$yymain .= qq~

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
     <tr valign="middle">
      <td align="left" class="titlebg">
       <img src="$imagesdir/info.gif" alt="" border="0" /> <b>$admin_txt{'693'}</b>
      </td>
     </tr>
     <tr valign="middle">
      <td align="left" class="windowbg2"><br />
       $admin_txt{'697'}$logtimetext<br /><br />
      </td>
     </tr>
   </table>
 </div>~;
 
	if ($enableclicklog) {
		$yymain .= qq~

<br />

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg" colspan="2">
      <img src="$imagesdir/cat.gif" alt="" border="0" /> <b>$admin_txt{'694'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2" colspan="2"><br />
      $admin_txt{'691'}: $totalclick<br />
      $admin_txt{'743'}: $totalip<br /><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="catbg" width="50%">
      <b>$clicklog_txt{'users'}</b>
     </td>
     <td align="center" class="catbg" width="50%">
      <b>$clicklog_txt{'guests'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2" valign="top" width="50%"><br />
      $useriplist<br />
     </td>
     <td align="left" class="windowbg2" valign="top" width="50%"><br />
      $guestiplist<br />
     </td>
    </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/cat.gif" alt="" border="0" /> <b>$admin_txt{'695'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="catbg">
      <i>$admin_txt{'744'}: $totalbrow</i>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $browserlist<br />
     </td>
    </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/cat.gif" alt="" border="0" /> <b>$admin_txt{'696'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="catbg">
      <i>$admin_txt{'745'}: $totalos</i>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $oslist<br />
     </td>
    </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/cat.gif" alt="" border="0" /> <b>$admin_txt{'696a'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $scriptcalls<br />
     </td>
    </tr>
   </table>
 </div>

<br />

 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/cat.gif" alt="" border="0" /> <b>$admin_txt{'838'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $referlist<br />
     </td>
    </tr>
   </table>
 </div>
~;
	}

	$yytitle     = $admin_txt{'693'};
	$action_area = "showclicks";
	&AdminTemplate;
	exit;
}

sub AdminMembershipRecount {
	&is_admin_or_gmod;

	&automaintenance('on');
	&MembershipCountTotal;
	&automaintenance('off');

	$yymain     .= qq~<b>$admin_txt{'505'}</b>~;
	$yytitle     = $admin_txt{'504'};
	$action_area = "membershiprecount";
	&AdminTemplate;
	exit;
}

sub AdminBoardRecount {
	&is_admin_or_gmod();
	&automaintenance('on');

	$action_area = 'boardrecount';
	$yytitle = $admin_txt{'502'};

	# Set up the multi-step action
	$begin_time = time();
	$topicnum = $INFO{'topicnum'} || 0;

	if (!$INFO{'tnext'}) {
		# Get the thread list
		opendir(TXT, $datadir);
		@topiclist = sort( grep { /^\d+\.txt$/ } readdir(TXT) );
		closedir(TXT);

		for ($i = $topicnum; $i < @topiclist; $i++) {
			($filename, undef) = split(/\./, $topiclist[$i]);

			fopen(MSG, "$datadir/$filename.txt");
			@messages = <MSG>;
			fclose(MSG);

			@lastmessage = split(/\|/, $messages[$#messages]);
			&MessageTotals('load', $filename);
			${$filename}{'replies'} = $#messages;
			if ($lastmessage[0] =~ /^\[m\]:/) { ${$filename}{'lastposter'} = $lastmessage[11]; }
			else { ${$filename}{'lastposter'} = $lastmessage[4] eq 'Guest' ? qq~Guest-$lastmessage[1]~ : $lastmessage[4]; }
			&MessageTotals('update', $filename);

			$topicnum++;
			last if time() > ($begin_time + $max_process_time);
		}

		# Prepare to continue...
		$numleft = @topiclist - $topicnum;
		if ($numleft == 0) { # go to finish
			$yySetLocation = qq~$adminurl?action=boardrecount;tnext=1~;
			&redirectexit;
		}

		# Continue
		$sumtopic = @topiclist;
		$resttopic = $sumtopic - $topicnum;

		$yymain .= qq~
		<br />
		$rebuild_txt{'1'}
		<br />
		$rebuild_txt{'5'} $max_process_time $rebuild_txt{'6'}
		<br /><br />
		$rebuild_txt{'13'} $sumtopic
		<br />
		$rebuild_txt{'14'} $resttopic
		<br />
		<br />
		<br />
		<div id="boardrecountcontinued">
		<br />
		$rebuild_txt{'1'}<br />
		$rebuild_txt{'2'} <a href="$adminurl?action=boardrecount;topicnum=$topicnum" onclick="rebRecount();">$rebuild_txt{'3'}</a>
		</div>
		<script type="text/javascript" language="JavaScript">
		<!--
		function rebRecount() {
			document.getElementById("boardrecountcontinued").innerHTML = '$rebuild_txt{'4'}';
		}

		function recounttick() {
			rebRecount();
			location.href="$adminurl?action=boardrecount;topicnum=$topicnum";
		}

		setTimeout("recounttick()",2000)
		// -->
		</script>
		~;
		&AdminTemplate();
	}

	# Get the board list from the forum.master file
	require "$boardsdir/forum.master";
	foreach (keys %board) {
		&BoardCountTotals($_);
	}

	$yymain .= qq~<b>$admin_txt{'503'}</b>~;
	&automaintenance('off');
	&AdminTemplate;
	exit;
}


sub RebuildMessageIndex {
	&is_admin_or_gmod();

	# Set up the multi-step action
	$time_to_jump = time() + $max_process_time;

	require "$boardsdir/forum.master";

	my %rebuildboards;
	if (!$INFO{'rebuild'}) {
		$yymain .= qq~<b>$admin_txt{'530'}</b>
		<a href="$adminurl?action=rebuildmesindex;rebuild=1"><b>$admin_txt{'531'}</b></a><br />
		($admin_txt{'532'} $max_process_time $admin_txt{'533'}.)~;
		$yytitle = $admin_txt{'506'};
		$action_area = 'rebuildmesindex';
		&AdminTemplate;
		exit;

	# delete old rebuldings when starting or if maintenance mode was 'off'
	} elsif (!-e "$vardir/maintenance.lock" || (!$INFO{'next'} && $INFO{'rebuild'} == 1)) {
		opendir(BOARDSDIR, $boardsdir) || &admin_fatal_error('cannot_open', "$boardsdir", 1);
		my @blist = grep { /\.tmp$/ } readdir(BOARDSDIR);
		closedir(BOARDSDIR);

		foreach (@blist) { unlink "$boardsdir/$_"; }

		foreach (keys %board) { push(@{$rebuildboards{$_}}, ''); }

		&automaintenance('on');
	}

	if ($INFO{'rebuild'} == 1) {
		require "$admindir/Attachments.pl";
		my %attachfile;

		# storing the 'board' and the 'status' of all threads
		foreach $oldboard (keys %board) {
			my @temparray;
			fopen(OLDBOARD, "$boardsdir/$oldboard.txt") || &admin_fatal_error('cannot_open', "$boardsdir/$oldboard.txt", 1);
			my @temparray = <OLDBOARD>;
			fclose(OLDBOARD);
			chomp(@temparray);

			foreach (@temparray) {
				($mnum, undef, undef, undef, undef, undef, undef, undef, $mstate) = split(/\|/, $_);
				$thread_status{$mnum} = $mstate if $mstate;
				$thread_boards{$mnum} = $oldboard;
			}
		}

		opendir(TXT, $datadir) || &admin_fatal_error('cannot_open', "$datadir", 1);
		my @threadlist = sort( grep { /\d+\.txt$/ } readdir(TXT) );
		closedir(TXT);

		$totalthreads = @threadlist;
		for (my $j = ($INFO{'next'} || 0); $j < $totalthreads; $j++) {
			$thread = $threadlist[$j];
			$thread =~ s/\.txt$//;

			if ($thread eq '' || !-e "$datadir/$thread.txt" || -s "$datadir/$thread.txt" < 35) {
				unlink("$datadir/$thread.txt");
				unlink("$datadir/$thread.ctb");
				unlink("$datadir/$thread.mail");
				unlink("$datadir/$thread.poll");
				unlink("$datadir/$thread.polled");
				$attachfile{$thread} = undef;
				$INFO{'count_del_threads'}++;
				next;
			}
		
			if (!-e "$datadir/$thread.ctb") {
				${$thread}{'board'} = '';
			} else {
				&MessageTotals('load', $thread);
			}

			# set correct board
			$theboard = exists $thread_boards{$thread} ? $thread_boards{$thread} : ${$thread}{'board'};
			# if boardname is wrong - > put to recycle
			if (!exists $board{$theboard}) {
				if ($binboard) {
					$theboard = $binboard;
				} else {
					unlink("$datadir/$thread.txt");
					unlink("$datadir/$thread.ctb");
					unlink("$datadir/$thread.mail");
					unlink("$datadir/$thread.poll");
					unlink("$datadir/$thread.polled");
					$attachfile{$thread} = undef;
					$INFO{'count_del_threads'}++;
					next;
				}
			}

			fopen(FILETXT, "$datadir/$thread.txt") || &admin_fatal_error('cannot_open', "$datadir/$thread.txt", 1);
			my @threaddata = <FILETXT>;
			fclose(FILETXT);

			@firstinfo = split(/\|/, $threaddata[0]);
			@lastinfo = split(/\|/, $threaddata[$#threaddata]);
			$lastpostdate = sprintf("%010d", $lastinfo[3]);

			# rewrite/create a correct threadnumber.ctb
			${$thread}{'board'} = $theboard;
			${$thread}{'replies'} = $#threaddata;
			${$thread}{'views'} = ${$thread}{'views'} || 1; # is never = 0 !
			${$thread}{'lastposter'} = $lastinfo[4] eq 'Guest' ? qq~Guest-$lastinfo[1]~ : $lastinfo[4];
			${$thread}{'lastpostdate'} = $lastpostdate;
			${$thread}{'threadstatus'} = $thread_status{$thread};
			&MessageTotals('update', $thread);

			push(@{$rebuildboards{$theboard}}, qq~$lastpostdate|$thread|$firstinfo[0]|$firstinfo[1]|$firstinfo[2]|$lastinfo[3]|$#threaddata|$firstinfo[4]|$firstinfo[5]|$thread_status{$thread}\n~);

			if (time() > $time_to_jump && ($j + 1) < $totalthreads) {
				foreach (keys %rebuildboards) {
					fopen(REBBOARD, ">>$boardsdir/$_.tmp") || &admin_fatal_error('cannot_open', "$boardsdir/$_.tmp", 1);
					print REBBOARD @{$rebuildboards{$_}};
					fclose(REBBOARD);
				}

				&RemoveAttachments(\%attachfile);

				&RebuildMessageIndexText($INFO{'rebuild'},$j,$totalthreads);
			}
		}
	
		foreach (keys %rebuildboards) {
			fopen(REBBOARD, ">>$boardsdir/$_.tmp") || &admin_fatal_error('cannot_open', "$boardsdir/$_.tmp", 1);
			print REBBOARD @{$rebuildboards{$_}};
			fclose(REBBOARD);
		}

		&RemoveAttachments(\%attachfile);

		$INFO{'next'} = 0;
		$INFO{'rebuild'} = 2;
	}

	if ($INFO{'rebuild'} == 2) {
		opendir(REBUILDS, $boardsdir);
		my @rebuilds = sort( grep(/\.tmp$/, readdir(REBUILDS)) );
		closedir(REBUILDS);

		$totalrebuilds = @rebuilds;
		for(my $j = 0; $j < $totalrebuilds; $j++) {
			my $boardname = $rebuilds[$j];
			$boardname =~ s/\.tmp$//;

			fopen(FILETXT, "$boardsdir/$boardname.tmp") || &admin_fatal_error('cannot_open', "$boardsdir/$boardname.tmp", 1);
			my @tempboard = <FILETXT>;
			fclose(FILETXT);

			fopen(NEWBOARD, ">$boardsdir/$boardname.txt") || &admin_fatal_error('cannot_open', "$boardsdir/$boardname.txt", 1);
			print NEWBOARD map({ s/^.*?\|//; $_; } sort({ lc($b) cmp lc($a) } @tempboard) );
			fclose(NEWBOARD);

			unlink "$boardsdir/$boardname.tmp";

			if (time() > $time_to_jump && ($j + 1) < $totalrebuilds) {
				&RebuildMessageIndexText($INFO{'rebuild'},-1,$totalrebuilds);
			}
		}
	}

	&RebuildMessageIndexText(3,0,0) if $INFO{'rebuild'} < 3;

	foreach (keys %board) { &BoardCountTotals($_); }

	&automaintenance('off');
	$yymain .= qq~<b>$admin_txt{'507'}</b>~;
	$yytitle = $admin_txt{'506'};
	$action_area = 'rebuildmesindex';
	&AdminTemplate;
	exit;
}

sub RebuildMessageIndexText {
	my ($part,$j,$total) = @_;

	$j++;
	$INFO{'st'} = int($INFO{'st'} + time() - $time_to_jump + $max_process_time);

	$yymain .= qq~<b>$admin_txt{'534'} <i>$max_process_time $admin_txt{'533'}</i>.<br />
	$admin_txt{'535'} <i>~ . (time() - $time_to_jump + $max_process_time) . qq~ $admin_txt{'533'}</i>.<br />
	$admin_txt{'536'} <i>~ . int(($INFO{'st'} + 60)/60) . qq~ $admin_txt{'537'}</i>.<br />
	<br />~;
	$yymain .= qq~$INFO{'count_del_threads'} $admin_txt{'538'}.<br />
	<br />~ if $INFO{'count_del_threads'};


	if ($part == 1) {
		$yymain .= qq~$j/$total $admin_txt{'539'}~;
	} elsif ($part == 2) {
		$yymain .= qq~$j/$total $admin_txt{'540'}~;
	} else {
		$yymain .= $admin_txt{'541'};
	}

	$yymain .= qq~</b>
	<p id="memcontinued">$admin_txt{'542'} <a href="$adminurl?action=rebuildmesindex;rebuild=$part;st=$INFO{'st'};next=$j;count_del_threads=$INFO{'count_del_threads'}" onclick="PleaseWait();">$admin_txt{'543'}</a>...<br />$admin_txt{'544'}
	</p>

	<script type="text/javascript">
	 <!--
		function PleaseWait() {
			document.getElementById("memcontinued").innerHTML = '<font color="red"><b>$admin_txt{'545'}</b></font><br />&nbsp;<br />&nbsp;';
		}

		function stoptick() { stop = 1; }

		stop = 0;
		function membtick() {
			if (stop != 1) {
				PleaseWait();
				location.href="$adminurl?action=rebuildmesindex;rebuild=$part;st=$INFO{'st'};next=$j;count_del_threads=$INFO{'count_del_threads'}";
			}
		}

		setTimeout("membtick()",2000);
	 // -->
	</script>~;

			$yytitle = $admin_txt{'506'};
			$action_area = 'rebuildmesindex';
			&AdminTemplate;
			exit;
}

sub DeleteOldMessages {
	&is_admin_or_gmod;

	fopen(DELETEOLDMESSAGE, "$vardir/oldestmes.txt");
	$maxdays = <DELETEOLDMESSAGE>;
	fclose(DELETEOLDMESSAGE);

	$yytitle = "$aduptxt{'04'}";
	$yymain .= qq~
<form action="$adminurl?action=removeoldthreads" method="post">
 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/ban.gif" alt="" border="0" /> <b>$aduptxt{'04'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $aduptxt{'05'}<br /><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2"><br />
      $admin_txt{'4'}: <input type="checkbox" name="keep_them" value="1" /><br />
      $admin_txt{'124'} <input type=text name="maxdays" size="4" value="$maxdays" /> $admin_txt{'579'} $admin_txt{'2'}:<br /><br />
      <div align="left" style="margin-left: 25px; margin-right: auto;">~;

	unless ($mloaded == 1) { require "$boardsdir/forum.master"; }

	foreach $catid (@categoryorder) {
		$boardlist = $cat{$catid};
		(@bdlist) = split(/\,/, $boardlist);
		($catname, $catperms) = split(/\|/, $catinfo{"$catid"});

		foreach $curboard (@bdlist) {
			($boardname, $boardperms, $boardview) = split(/\|/, $board{"$curboard"});

			$selectname = $curboard . 'check';
			$yymain .= qq~
		<input type="checkbox" name="$selectname" value="1" />&nbsp;$boardname<br />~;
		}
	}
	$yymain .= qq~
      </div><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="catbg">
      <input type="submit" value="$admin_txt{'31'}" class="button" />
     </td>
    </tr>
   </table>
 </div>
</form>~;

	$action_area = "deleteoldthreads";
	&AdminTemplate;
	exit;
}

# June 2008: looks like this is a not used subroutine!
# If you use it again, be carefull not to run out of time with xx-large forums!!!!
# refresh the IM system, or update it, or rebuld it . Whichever!
#sub RebuildIMs {
#	&is_admin_or_gmod;
#	&automaintenance("on");
#
#	# grep a list of members from vars file
#	opendir("MEMBSDIR", $memberdir);
#	my @imslist = grep { /\.vars$/ } readdir(MEMBSDIR);
#	closedir("MEMBSDIR");
#	#new ims
#	#0	$mnum = 3;
#	#1	$imnewcount = 0;
#	#2	$moutnum = 17;
#	#3	$storenum = 0;
#	#4	@incurrent = qw/ /;  # list of messages in .msg
#	#5	@inunread = qw/ /; # unread in msg
#	#6	@inreplied = qw/ /; # replied to
#	#7	@inforward = qw/ /; # forwarded
#	#8	@outcurrent = qw/ /; # list of messages in .outbox
#	#9	@outunread = qw/ /; # outbox, not opened by receiver
#	#10	@storecurrentin = qw/ /; # list of messages in .imstore msg
#	#11	@storecurrentout = qw/ /; # list of messages in .imstore outbox
#
#	chomp(@imslist);
#	foreach my $member (@imslist) {
#		my $memlen = length($member);
#		my($member,$undef) = substr($member,0, $memlen-5); 
#		&buildIMS($member);
#	}
#
#	&automaintenance("off");
#
#	$yytitle = "$admin_txt{'600'}";
#	$yymain .= "<b>$admin_txt{'601'}</b>";
#	$action_area = "updateinstantmessages";
#	&AdminTemplate;
#	exit;
#}

sub RebuildMemHistory {
	my (@contents,$begin_time,$start_time,$timeleft,$hour,$min,$sec,$sumtopic,$resttopic);

	# Security
	&is_admin_or_gmod;
	&automaintenance("on");

	# Set up the multi-step action
	$begin_time = time();

	if (-e "$datadir/topicrest.txt.rebuild"  && -M "$datadir/topicrest.txt.rebuild" < 1) {
		fopen(TOPICREST, "$datadir/topicrest.txt.rebuild") || &fatal_error('cannot_open', "$datadir/topicrest.txt.rebuild", 1);
		@contents = <TOPICREST>;
		fclose(TOPICREST);

		fopen(TOPICCALC, "$datadir/topiccalc.txt.rebuild") || &fatal_error('cannot_open', "$datadir/topiccalc.txt.rebuild", 1);
		$start_time = <TOPICCALC>;
		$sumtopic = <TOPICCALC>;
		fclose(TOPICCALC);
		chomp ($begin_time,$sumtopic);
	}

	if (!@contents) {
		# Delete all rlog
		opendir(MEMBERS, $memberdir) || die "$txt{'230'} ($memberdir) :: $!";
		@contents = grep { /\.rlog$/ } readdir(MEMBERS);
		closedir(MEMBERS);
		foreach (@contents) {
			unlink "$memberdir/$_";
		}

		# Get and store the thread list
		opendir(TXT, $datadir);
		@contents = map { $_ =~ s/\.txt$//; "$_\n"; } grep { /^\d+\.txt$/ } readdir(TXT);
		closedir(TXT);

		$start_time = $begin_time;
		$sumtopic = @contents;
		fopen(TOPICCALC, ">$datadir/topiccalc.txt.rebuild") || &fatal_error('cannot_open', "$datadir/topiccalc.txt.rebuild", 1);
		print TOPICCALC "$start_time\n$sumtopic\n";
		fclose(TOPICCALC);
	}

	# Loop through each -rest- topic
	while (@contents) {
		$topic = pop @contents;
		chomp $topic;

		my %curtopic=();

		fopen(TOPIC, "$datadir/$topic.txt");
		my @topic = <TOPIC>;
		fclose(TOPIC);

		foreach my $line (@topic) {
			my $user;
			(undef, undef, undef, undef, $user, undef) = split(/\|/, $line, 6);
			if($user ne 'Guest') {
				$curtopic{$user}++;
			}
		}

		foreach my $user (keys %curtopic) {
			if (-e "$memberdir/$user.vars") { 
				fopen(HIST, ">>$memberdir/$user.rlog");
				print HIST "$topic\t$curtopic{$user}\n";
				fclose(HIST);
			}
		}

		last if time() > ($begin_time + $max_process_time);
	}

	# See if we're completely done
	if(!@contents) {
		&automaintenance("off");

		unlink("$datadir/topicrest.txt.rebuild");
		unlink("$datadir/topiccalc.txt.rebuild");

		$yymain .= qq~<b>$admin_txt{'598'}</b>~;

	# Or prepare to continue looping
	} else {
		fopen(TOPICREST, ">$datadir/topicrest.txt.rebuild") || &fatal_error('cannot_open', "$datadir/topicrest.txt.rebuild", 1);
		print TOPICREST @contents;
		fclose(TOPICREST);

		$resttopic = @contents;

		$run_time = int(time() - $start_time);
		$run_time = 1 if !$run_time;
		$time_left = int($resttopic / (($sumtopic - $resttopic) / $run_time));

		$hour= int($run_time/3600);
		$min = int(($run_time - $hour * 3600) / 60);
		$sec = $run_time - $hour * 3600 - $min * 60;
		$hour = "0$hour" if $hour < 10; $min = "0$min" if $min < 10; $sec = "0$sec" if $sec < 10;

		$run_time = "$hour:$min:$sec";

		$hour= int($time_left / 3600);
		$min = int(($time_left - $hour * 3600) / 60);
		$sec = $time_left - $hour * 3600 - $min * 60;
		$hour = "0$hour" if $hour < 10; $min = "0$min" if $min < 10; $sec = "0$sec" if $sec < 10;

		$time_left = "$hour:$min:$sec";

		$yymain .= qq~
<br />
$rebuild_txt{'1'}
<br />
$rebuild_txt{'5'} $max_process_time $rebuild_txt{'6'}
<br /><br />
$rebuild_txt{'13'} $sumtopic
<br />
$rebuild_txt{'14'} $resttopic
<br />
<br />
$rebuild_txt{'7'} $run_time
<br />
$rebuild_txt{'8'} $time_left
<br />
<br />
<div id="memcontinued">
$rebuild_txt{'2'} <a href="$adminurl?action=rebuildmemhist" onclick="clearMeminfo();">$rebuild_txt{'3'}</a>
</div>
<script type="text/javascript" language="JavaScript">
 <!--
	function clearMeminfo() {
		document.getElementById("memcontinued").innerHTML = '$rebuild_txt{'4'}';
	}

	function membtick() {
		clearMeminfo();
		location.href="$adminurl?action=rebuildmemhist";
	}

	setTimeout("membtick()", 2000)
 // -->
</script>~;
	}

	$yytitle = $admin_txt{'597'};
	$action_area = "rebuildmemhist";
	&AdminTemplate();
}

sub RebuildMemList {
	my (@contents, $begin_time, $start_time, $timeleft, $hour, $min, $sec, $sumuser, $grpdel, @grpexist, $regtime);

	# Security
	&automaintenance("on");
	&is_admin_or_gmod;

	# Set up the multi-step action
	$begin_time = time();

	if (-e "$memberdir/memberrest.txt.rebuild" && -M "$memberdir/memberrest.txt.rebuild" < 1) {
		fopen(MEMBERREST, "$memberdir/memberrest.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberrest.txt.rebuild", 1);
		@contents = <MEMBERREST>;
		fclose(MEMBERREST);

		fopen(MEMBERCALC, "$memberdir/membercalc.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/membercalc.txt.rebuild", 1);
		$start_time = <MEMBERCALC>;
		$sumuser = <MEMBERCALC>;
		fclose(MEMBERCALC);
		chomp ($start_time, $sumuser);

	} else {
		unlink("$memberdir/memberlist.txt.rebuild");
		unlink("$memberdir/memberinfo.txt.rebuild");
	}

	if (!@contents) {
		# Get the list
		opendir(MEMBERS, $memberdir) || die "$txt{'230'} ($memberdir) :: $!";
		@contents = map { $_ =~ s/\.vars$//; "$_\n"; } grep { /.\.vars$/ } readdir(MEMBERS);
		closedir(MEMBERS);

		$start_time = $begin_time;
		$sumuser = @contents;
		fopen(MEMBERCALC, ">$memberdir/membercalc.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/membercalc.txt.rebuild", 1);
		print MEMBERCALC "$start_time\n$sumuser\n";
		fclose(MEMBERCALC);
	}

	# Loop through each -rest- member
	while (@contents) {
		$member = pop @contents;
		chomp $member;
		$grpdel   = 0;
		@grpexist = ();

		# Load the user's info
		&UserCheck($member, "realname+email+regdate+position+addgroups+postcount");
		(@addigroups) = split(/,/, $usercheck{'addgroups'});
		foreach $addigrp (@addigroups) {
			if (!exists $NoPost{$addigrp}) { $grpdel = 1; }
			else { push(@grpexist, $addigrp); }
		}
		$actposition = $usercheck{'position'};
		if (!exists $Group{$actposition} && !exists $NoPost{$actposition}) {
			$usercheck{'position'} = "";
			$grpdel = 1;
		}
		if ($grpdel) {
			if (!${$uid.$member}{'password'}) { &LoadUser($member); }
			${$uid.$member}{'addgroups'} = join(',', @grpexist);
			${$uid.$member}{'position'}  = $usercheck{'position'};
			&UserAccount($member, "update");
		}
		if (!$usercheck{'position'}) { $usercheck{'position'} = &MemberPostGroup($usercheck{'postcount'}); }
		$regtime = &stringtotime($usercheck{'regdate'}) || &stringtotime($forumstart);
		$memberlist{$member} = sprintf("%010d", $regtime);
		$memberinf{$member}  = qq~$usercheck{'realname'}|$usercheck{'email'}|$usercheck{'position'}|$usercheck{'postcount'}|${$uid.$member}{'addgroups'}~;

		undef %{$uid.$member} if $member ne $username;
		last if time() > ($begin_time + $max_process_time);
	}

	# Save what we have rebuilt so far
	fopen(MEMBERLIST, ">>$memberdir/memberlist.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberlist.txt.rebuild", 1);
	foreach (keys %memberlist) { print MEMBERLIST "$_\t$memberlist{$_}\n" };
	fclose(MEMBERLIST);

	fopen(MEMBERINFO, ">>$memberdir/memberinfo.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberinfo.txt.rebuild", 1);
	foreach (keys %memberinf) { print MEMBERINFO "$_\t$memberinf{$_}\n" };
	fclose(MEMBERINFO);

	# If it is completely done ...
	if(!@contents) {
		%memberlist = ();
		# Sort memberlist.txt
		fopen(MEMBERLIST, "$memberdir/memberlist.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberlist.txt.rebuild", 1);
		my %memberlist = map {split(/\t/, $_)} <MEMBERLIST>;
		fclose(MEMBERLIST);

		fopen(MEMBERLIST, ">$memberdir/memberlist.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberlist.txt.rebuild", 1);
		foreach (sort {$memberlist{$a} <=> $memberlist{$b}} keys %memberlist) {
			print MEMBERLIST "$_\t$memberlist{$_}";
		}
		fclose(MEMBERLIST);

		# Move the updated copy back
		rename("$memberdir/memberlist.txt.rebuild", "$memberdir/memberlist.txt");
		rename("$memberdir/memberinfo.txt.rebuild", "$memberdir/memberinfo.txt");
		unlink("$memberdir/memberrest.txt.rebuild");
		unlink("$memberdir/membercalc.txt.rebuild");

		$regcounter = &MembershipCountTotal();

		&automaintenance("off");

		if ($INFO{'actiononfinish'}) {
			$yySetLocation = qq~$adminurl?action=$INFO{'actiononfinish'}~;
			&redirectexit;
		}
		$yymain     .= qq~<b>$admin_txt{'594'} $regcounter $admin_txt{'594a'}</b>~;
		$yytitle     = "$admin_txt{'593'}";
		$action_area = "rebuildmemlist";

	# ... or continue looping
	} else {
		fopen(MEMBERREST, ">$memberdir/memberrest.txt.rebuild") || &fatal_error('cannot_open', "$memberdir/memberrest.txt.rebuild", 1);
		print MEMBERREST @contents;
		fclose(MEMBERREST);

		$restuser = @contents;
		$run_time = int(time() - $start_time);
		$run_time ||= 1;
		$time_left = int($restuser / (($sumuser - $restuser + 1) / $run_time));

		$hour= int($run_time/3600);
		$min = int(($run_time-$hour*3600)/60);
		$sec = $run_time - $hour*3600 - $min*60;
		$hour = "0$hour" if $hour<10; $min = "0$min" if $min<10; $sec = "0$sec" if $sec<10;

		$run_time = "$hour:$min:$sec";

		$hour= int($time_left/3600);
		$min = int(($time_left-$hour*3600)/60);
		$sec = $time_left - $hour*3600 - $min*60;
		$hour = "0$hour" if $hour<10; $min = "0$min" if $min<10; $sec = "0$sec" if $sec<10;

		$time_left = "$hour:$min:$sec";

		if ($INFO{'actiononfinish'} eq 'modmemgr') {
			$yymain     .= $rebuild_txt{'20'} ;
			$yytitle     = $admin_txt{'8'};
			$action_area = "modmemgr";
		} else {
			$yytitle     = $admin_txt{'593'};
			$action_area = "rebuildmemlist";
		}

		$yymain .= qq~
<br />
$rebuild_txt{'1'}
<br />
$rebuild_txt{'5'} = $max_process_time $rebuild_txt{'6'}
<br /><br />
$rebuild_txt{'10'} $sumuser
<br />
$rebuild_txt{'10a'} $restuser
<br />
<br />
$rebuild_txt{'7'} $run_time
<br />
$rebuild_txt{'8'} $time_left
<br />
<br />
<div id="memcontinued">
$rebuild_txt{'2'} <a href="$adminurl?action=rebuildmemlist;actiononfinish=$INFO{'actiononfinish'}" onclick="clearMeminfo();">$rebuild_txt{'3'}</a>
</div>
<script type="text/javascript" language="JavaScript">
 <!--
	function clearMeminfo() {
		document.getElementById("memcontinued").innerHTML = '$rebuild_txt{'4'}';
	}

	function membtick() {
		clearMeminfo();
		location.href="$adminurl?action=rebuildmemlist;actiononfinish=$INFO{'actiononfinish'}";
	}

	setTimeout("membtick()", 2000)
 // -->
</script>~;
	}

	&AdminTemplate();
}

sub DeleteMultiMembers {
	&is_admin_or_gmod;

	&automaintenance("on");

	my ($count, $currentmem, $start, $sortmode, $sortorder, $deadusers, @userslist);
	chomp $FORM{'button'};
	chomp $FORM{'emailsubject'};
	chomp $FORM{'emailtext'};
	$tmpemailsubject = $FORM{'emailsubject'};
	$tmpemailtext = $FORM{'emailtext'};
	if ($FORM{'button'} != 1 && $FORM{'button'} != 2) { &admin_fatal_error('no_access'); }

	if ($FORM{'del_mail'} || $FORM{'emailtext'} ne '') { require "$sourcedir/Mailer.pl"; }

	fopen(FILE, "$memberdir/memberlist.txt");
	@memnum = <FILE>;
	fclose(FILE);
	$count = 0;

	if ($FORM{'button'} == 1 && $FORM{'emailtext'} ne "") {
		$FORM{'emailsubject'} =~ s~\|~&#124~g;
		$FORM{'emailtext'}    =~ s~\|~&#124~g;
		$FORM{'emailtext'} =~ s/\r(?=\n*)//g;
		$mailline = qq~$date|$FORM{'emailsubject'}|$FORM{'emailtext'}|$username~;
		&MailList($mailline);
	}

	my $templanguage = $language;
	&getMailFiles;

	while (@memnum >= $count) {
		$currentmem = $FORM{"member$count"};
		if (exists $FORM{"member$count"}) {
			if (-e "$memberdir/$currentmem.vars") { # Bypass dead entries.
				&UserCheck($currentmem, "realname+email+language");
				if ($FORM{'emailtext'} ne '') {
					$emailsubject = $FORM{'emailsubject'};
					$emailtext = $FORM{'emailtext'};
					$emailsubject =~ s~\[name\]~$usercheck{'realname'}~ig;
					$emailsubject =~ s~\[username\]~$currentmem~ig;
					$emailtext =~ s~\[name\]~$usercheck{'realname'}~ig;
					$emailtext =~ s~\[username\]~$currentmem~ig;
					&sendmail($usercheck{'email'}, $emailsubject, $emailtext);
				} elsif ($FORM{'del_mail'}) {
					$language = $usercheck{'language'};
					&LoadLanguage('Email');
					my $message = &template_email($deleteduseremail, {'displayname' => $usercheck{'realname'}});
					&sendmail($usercheck{'email'}, "$deletedusersybject $mbname", $message, '', $emailcharset);
				}
			}
			if ($FORM{'button'} == 2) {
				unlink("$memberdir/$currentmem.dat");
				unlink("$memberdir/$currentmem.vars");
				unlink("$memberdir/$currentmem.ims");
				unlink("$memberdir/$currentmem.msg");
				unlink("$memberdir/$currentmem.log");
				unlink("$memberdir/$currentmem.rlog");
				unlink("$memberdir/$currentmem.outbox");
				unlink("$memberdir/$currentmem.imstore");
				unlink("$memberdir/$currentmem.imdraft");
				# save name up
				push (@userslist, $currentmem);
				#&MemberIndex("remove", $currentmem);
				# For security, remove username from mod position
				&KillModerator($currentmem);
			}
		}
		$count++;
	}
	if(@userslist) {
		$deadusers = join(',', @userslist);
		&MemberIndex("remove", $deadusers);
	}

	&automaintenance("off");

	$language = $templanguage;
	if ($INFO{'start'} ne '') { $startmode = $INFO{'start'}; }
	if ($INFO{'sort'}  ne '') { $sortmode  = ";sort=" . $INFO{'sort'}; }
	if ($INFO{'order'}) { $sortorder = ";reversed=" . $INFO{'order'}; }

	if ($FORM{'button'} == 1) {
		$yySetLocation = qq~$adminurl?action=mailing;$sortmode~;
	} else {
		$yySetLocation = qq~$adminurl?action=viewmembers;start=$startmode$sortmode$sortorder~;
	}
	&redirectexit;
}

#sub ml { June 2008: looks like this is a not used subroutine!
#	&is_admin_or_gmod;
#	require "$sourcedir/Mailer.pl";
#	$FORM{'emails'} = "; " . $FORM{'emails'};
#	$FORM{'emails'} =~ s/[\n\r]//g;
#	@emails = split(/;\s*/, $FORM{'emails'});
#	foreach $curmem (@emails) {
#		&sendmail($curmem, "$mbname: $FORM{'subject'}", "$FORM{'message'}\n\n$admin_txt{'130'}\n\n$scripturl");
#	}
#	$yySetLocation = qq~$adminurl~;
#	&redirectexit;
#}

sub clean_log {
	&is_admin_or_gmod;

	# Overwrite with a blank file
	fopen(FILE, ">$vardir/log.txt");
	print FILE '';
	fclose(FILE);

	$yymain .= qq~<b>$admin_txt{'596'}</b>~;
	$yytitle     = "$admin_txt{'595'}";
	$action_area = "clean_log";
	&AdminTemplate;
	exit;
}

sub ipban {
	&is_admin_or_gmod;
	my (@banlist, $line, $tmp, @ipban, @emailban, @userban, $bantype, $eban, $iban, $uban);

	if (!-e "$vardir/ban.txt") {
		fopen(BANFILE, ">$vardir/ban.txt") || &admin_fatal_error('cannot_open', "$vardir/ban.txt", 1);
		print BANFILE "E|\n";
		print BANFILE "I|\n";
		print BANFILE "U|\n";
		fclose(BANFILE);
	}

	fopen(FILE, "$vardir/ban.txt") || &admin_fatal_error('cannot_open', "$vardir/ban.txt", 1);
	@banlist = <FILE>;
	fclose(FILE);
	foreach $line (@banlist) {
		chomp $line;
		($bantype, $tmp) = split(/\|/, $line);
		if ($bantype eq 'I') { $iban = $tmp; }
		if ($bantype eq 'E') { $eban = $tmp; }
		if ($bantype eq 'U') { $uban = $tmp; }
	}
	$iban =~ s/\,/\n/g;
	$eban =~ s/\,/\n/g;
	$uban =~ s/\,/\n/g;
	$yymain .= qq~
<form action="$adminurl?action=ipban2" method="post">
 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg">
      <img src="$imagesdir/ban.gif" alt="" border="0" /><b>$admin_txt{'340'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="catbg">
      <span class="small">$admin_txt{'724'}</span>
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="windowbg2"><br />
      <textarea cols="60" rows="10" name="ban" style="width: 95%">$iban</textarea><br /><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="catbg">
      <span class="small">$admin_txt{'725'}</span>
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="windowbg2"><br />
      <textarea cols="60" rows="10" name="ban_email" style="width: 95%">$eban</textarea><br /><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="catbg">
      <span class="small">$admin_txt{'725a'}</span>
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="windowbg2"><br />
      <textarea cols="60" rows="10" name="ban_memname" style="width: 95%">$uban</textarea><br /><br />
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="catbg">
      <input type="submit" value="$admin_txt{'10'}" class="button" />
     </td>
    </tr>
   </table>
 </div>
</form>~;

	$yytitle     = "$admin_txt{'340'}";
	$action_area = "ipban";
	&AdminTemplate;
	exit;
}

sub ipban2 {
	&is_admin_or_gmod;
	$FORM{'ban'} =~ tr/\r//d;
	$FORM{'ban'} =~ s/ //g;
	$FORM{'ban'} =~ s~\A[\s\n]+~~;
	$FORM{'ban'} =~ s~[\s\n]+\Z~~;
	$FORM{'ban'} =~ s~\n\s*\n~\n~g;
	$FORM{'ban'} =~ s/\n/\,/g;
	$FORM{'ban_email'} =~ s/ //g;
	$FORM{'ban_email'} =~ tr/\r//d;
	$FORM{'ban_email'} =~ s~\A[\s\n]+~~;
	$FORM{'ban_email'} =~ s~[\s\n]+\Z~~;
	$FORM{'ban_email'} =~ s~\n\s*\n~\n~g;
	$FORM{'ban_email'} =~ s/\n/\,/g;
	$FORM{'ban_memname'} =~ s/ //g;
	$FORM{'ban_memname'} =~ tr/\r//d;
	$FORM{'ban_memname'} =~ s~\A[\s\n]+~~;
	$FORM{'ban_memname'} =~ s~[\s\n]+\Z~~;
	$FORM{'ban_memname'} =~ s~\n\s*\n~\n~g;
	$FORM{'ban_memname'} =~ s/\n/\,/g;

	fopen(BANFILE, ">$vardir/ban.txt", 1);
	print BANFILE "E|$FORM{'ban_email'}\n";
	print BANFILE "I|$FORM{'ban'}\n";
	print BANFILE "U|$FORM{'ban_memname'}\n";
	fclose(BANFILE);

	$yySetLocation = qq~$adminurl~;
	&redirectexit;
}

sub ipban_update {
	# This is for quick updating for banning + unbanning
	&is_admin_or_gmod;

	if (!-e "$vardir/ban.txt") {
		fopen(BANFILE, ">$vardir/ban.txt") || &admin_fatal_error('cannot_open', "$vardir/ban.txt", 1);
		print BANFILE "E|\n";
		print BANFILE "I|\n";
		print BANFILE "U|\n";
		fclose(BANFILE);
	}

	if ($INFO{'ban'}) { $ban_details = $INFO{'ban'}; $ban_t = 'I'; }
	if ($INFO{'ban_email'}) { $ban_details = $INFO{'ban_email'}; $ban_t = 'E'; }
	if ($INFO{'ban_memname'}) {
		if ($do_scramble_id){ $name = &decloak($INFO{'ban_memname'}); } else { $name = $INFO{'ban_memname'}; }
		$ban_details = $name; $ban_t = 'U';
	}

	if ($INFO{'unban'} eq 1) {
		# Make sure there are no dupes before writing, sort for neatness too
		fopen(BANFILE, "+<$vardir/ban.txt", 1) || &admin_fatal_error('cannot_open', "$vardir/ban.txt", 1);
		@allbans = <BANFILE>;
		foreach $line (@allbans) {
			my @banned = ();
			chomp $line;
			my ($bantype, $bannedlst) = split(/\|/, $line);
			my $newlinne = qq~$bantype|~;
			@banned = split(/\,/, $bannedlst);
			foreach my $banned (@banned) {
				chomp $banned;
				if ($banned ne $ban_details) { $newlinne .= qq~$banned,~; }
			}
			$newlinne =~ s/,\Z//;
			push (@newallbans, "$newlinne\n");
		}
		seek BANFILE, 0, 0;
		truncate BANFILE, 0;
		print BANFILE @newallbans;
		fclose(BANFILE);
	} else {
		# Make sure there are no dupes before writing, sort for neatness too
		fopen(BANFILE, "+<$vardir/ban.txt", 1) || &admin_fatal_error('cannot_open', "$vardir/ban.txt", 1);
		@allbans = <BANFILE>;
		foreach $line (@allbans) {
			my @banned = ();
			chomp $line;
			my ($bantype, $bannedlst) = split(/\|/, $line);
			my (@bannedlst) = split(/\,/, $bannedlst);
			$newlinne = qq~$bantype|~;
			if ($bantype eq $ban_t) {
				push (@bannedlst, $ban_details);
				$newbannedlst = join (',', @bannedlst);
				$newlinne .= $newbannedlst;
				push (@newallbans, "$newlinne\n");
			} else {
				push (@newallbans, "$line\n");
			}
		}
		seek BANFILE, 0, 0;
		truncate BANFILE, 0;
		print BANFILE @newallbans;
		fclose(BANFILE);
	}
	$yySetLocation = qq~$scripturl?action=viewprofile;username=$INFO{'username'}~;
	&redirectexit;
}

sub ver_detail {
	&is_admin_or_gmod;

	require "$boarddir/YaBB.$yyext";
	$YaBBplver =~ s/\$Revision\: (.*?) \$/Build $1/ig;

	$yymain .= qq~
	<div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
	<table width="100%" cellspacing="1" cellpadding="4">
	<tr valign="middle">
			<td align="left" class="titlebg" colspan="3"><img src="$imagesdir/info.gif" alt="" border="0" /><b>$admin_txt{'429'}</b></td>
     </tr>
	<tr valign="middle">
		<td align="left" class="windowbg2" colspan="3">
		<script language="javascript" src="http://www.yabbforum.com/update/versioncheck.js" type="text/javascript"></script>
		$versiontxt{'4'} <b>$YaBBversion</b><br />
		<script language="JavaScript" type="text/javascript">  
		<!-- //hide from dinosaurs  
			document.write("$versiontxt{'5'} <b>"+STABLE+"</b><br />$versiontxt{'7'} <b>"+BETA+"</b>");  
		// -->
		</script>
		<noscript>$versiontxt{'1'} <img src="http://www.yabbforum.com/images/version/versioncheck.gif" alt="" /></noscript> 
	</td>
	</tr>
	<tr valign="middle">
		<td align="center" class="catbg" width="40%"><b>$admin_txt{'495'}</b><br /></td>
		<td align="center" class="catbg" width="60%"><b>$admin_txt{'494'}</b><br /></td>
	</tr>
	<tr>
		<td class="windowbg2" align="left">$admin_txt{'496'}</td>
		<td class="windowbg2" align="left"><i>$YaBBversion</i></td>
	</tr><tr>
		<td class="windowbg2" align="left">YaBB.$yyext</td>
		<td class="windowbg2" align="left"><i>$YaBBplver</i></td>
	</tr><tr>
		<td class="windowbg2" align="left">AdminIndex.pl</td>
		<td class="windowbg2" align="left"><i>$adminindexplver</i></td>
	</tr>~;

	opendir(LNGDIR, $langdir);
	my @lfilesanddirs = readdir(LNGDIR);
	close(LNGDIR);
	foreach $fld (@lfilesanddirs) {
		if (-d "$langdir/$fld" && $fld =~ m^\A[0-9a-zA-Z_\#\%\-\:\+\?\$\&\~\,\@/]+\Z^ && -e "$langdir/$fld/Main.lng") {
			fopen(FILE, "$langdir/$fld/version.txt");
			my @ver = <FILE>;
			fclose(FILE);
			$yymain .= qq~
	<tr>
		<td width="30%" class="windowbg2" align="left">$fld Language Pack</td>
		<td width="35%" class="windowbg2" align="left"><i>$ver[0]</i></td>
	</tr>~;
		}
	}
	$yymain .= qq~
	<tr valign="middle">
		<td align="left" class="titlebg" colspan="3"><b>$admin_txt{'430'}</b></td>
	</tr>~;

	opendir(DIR, $admindir);
	my @adminDIR = readdir(DIR);
	close(DIR);
	@adminDIR = sort (@adminDIR);
	foreach my $fileinDIR (@adminDIR) {
		chomp $fileinDIR;
		if ($fileinDIR =~ m/\.pl\Z/) {
			require "$admindir/$fileinDIR";
			my $txtrevision = lc $fileinDIR;
			$txtrevision =~ s/\.pl/plver/ig;
			$$txtrevision =~ s/\$Revision\: (.*?) \$/Build $1/ig;
			$yymain .= qq~
	<tr>
		<td class="windowbg2" align="left">$fileinDIR</td>
		<td class="windowbg2" align="left"><i>$$txtrevision</i></td>
	</tr>~;
		}
	}
	$yymain .= qq~
	<tr valign="middle">
		<td align="left" class="titlebg" colspan="3"><b>$admin_txt{'431'}</b></td>
	</tr>~;

	opendir(DIR, $sourcedir);
	my @sourceDIR = readdir(DIR);
	close(DIR);
	@sourceDIR = sort (@sourceDIR);
	foreach my $fileinDIR (@sourceDIR) {
		chomp $fileinDIR;
		if ($fileinDIR =~ m/\.pl\Z/) {
			require "$sourcedir/$fileinDIR";
			my $txtrevision = lc $fileinDIR;
			$txtrevision =~ s/\.pl/plver/ig;
			$$txtrevision =~ s/\$Revision\: (.*?) \$/Build $1/ig;
			$yymain .= qq~
			<tr>
				<td class="windowbg2" align="left">$fileinDIR</td>
				<td class="windowbg2" align="left"><i>$$txtrevision</i></td>
			</tr>~;
		}
	}

	$yymain .= qq~
	</table>
	</div>~;

	$yytitle = $admin_txt{'429'};
	$action_area = "detailedversion";
	&AdminTemplate;
	exit;
}

sub Refcontrol {
	&is_admin_or_gmod;
	&LoadLanguage('RefControl');

	fopen(FILE, "$sourcedir/SubList.pl");
	@scriptlines = <FILE>;
	fclose(FILE);

	fopen(FILE, "$vardir/allowed.txt");
	@allowed = <FILE>;
	fclose(FILE);

	$startread = 0;
	$counter   = 0;

	foreach $scriptline (@scriptlines) {
		chomp $scriptline;
		if (substr($scriptline, 0, 1) eq "'") {
			$scriptline =~ /\'(.*?)\'/;
			$actionfound = $1;
			push(@actfound, $actionfound);
			$counter++;
		}
	}
	$column  = int($counter / 3);
	$counter = 0;
	foreach $actfound (@actfound) {
		$selected = "";
		foreach $allow (@allowed) {
			chomp $allow;
			if ($actfound eq $allow) { $selected = ' checked="checked"'; last; }
		}
		$refexpl_txt{$actfound} =~ s/"/'/g; # XHTML Validation
		$dismenu .= qq~<input type="checkbox" name="$actfound"$selected />&nbsp;<img src="$imagesdir/question.gif" align="middle" alt="$reftxt{'1a'} $refexpl_txt{$actfound}" title="$reftxt{'1a'} $refexpl_txt{$actfound}" border="0" /> $actfound<br />\n~;
		$counter++;
		if ($counter > $column + 1) {
			$dismenu .= qq~</td><td align="left" class="windowbg2" valign="top" width="33%">~;
			$counter = 0;
		}
	}
	$yymain .= qq~
<form action="$adminurl?action=referer_control2" method="post">
 <div class="bordercolor" style="padding: 0px; width: 99%; margin-left: 0px; margin-right: auto;">
   <table width="100%" cellspacing="1" cellpadding="4">
    <tr valign="middle">
     <td align="left" class="titlebg" colspan="3">
      <img src="$imagesdir/preferences.gif" alt="" border="0" /><b>$reftxt{'1'}</b>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2" colspan="3"><br />
      $reftxt{'2'}<br />
      <span class="small">
      <i>$reftxt{'3'}</i><br /><br />
      </span>
     </td>
    </tr>
    <tr valign="middle">
     <td align="left" class="windowbg2" valign="top" width="33%">
      $dismenu
     </td>
    </tr>
    <tr valign="middle">
     <td align="center" class="catbg" colspan="3">
      <input type="submit" value="$reftxt{'4'}" class="button" />
     </td>
     </tr>
   </table>
 </div>
</form>~;

	$yytitle     = "$reftxt{'1'}";
	$action_area = "referer_control";
	&AdminTemplate;
	exit;
}

sub Refcontrol2 {
	&is_admin_or_gmod;

	fopen(FILE, "$sourcedir/SubList.pl");
	@scriptlines = <FILE>;
	fclose(FILE);

	$startread = 0;
	$counter   = 0;
	foreach $scriptline (@scriptlines) {
		chomp $scriptline;
		if (substr($scriptline, 0, 1) eq "'") {
			$scriptline =~ /\'(.*?)\'/;
			$actionfound = $1;
			push(@actfound, $actionfound);
			$counter++;
		}
	}

	foreach $actfound (@actfound) {
		if ($FORM{$actfound}) { push(@outfile, "$actfound\n"); }
	}

	fopen(FILE, ">$vardir/allowed.txt");
	print FILE @outfile;
	fclose(FILE);

	$yySetLocation = qq~$adminurl~;
	&redirectexit;
}

sub AddMember {
	&is_admin_or_gmod;
	&LoadLanguage('Register');
	if ($regcheck) {
		require "$sourcedir/Decoder.pl";
		&validation_code;
	}
	$yymain .= qq~
<form action="$adminurl?action=addmember2" method="post" name="creator"> 
   <table align="center" border="0" cellspacing="1" cellpadding="3" class="bordercolor">
    <tr>
     <td colspan="2" width="100%" valign="middle" class="titlebg">
      <img src="$imagesdir/register.gif" alt="" border="0" style="vertical-align: middle;" /><b> $admintxt{'17a'}</b>
     </td>
    </tr>
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'98'}:</b></td>
     <td width="70%" class="windowbg"><input type="text" name="regusername" size="30" maxlength="18" /><input type="hidden" name="_session_id_" id="_session_id_" value="$sessionid" /><input type="hidden" name="regdate" id="regdate" value="$regdate" /></td>
    </tr>
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'98a'}:</b></td>
     <td width="70%" class="windowbg"><input type="text" name="regrealname" size="30" maxlength="18" /></td>
    </tr>
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'69'}:</b></td>
     <td width="70%" class="windowbg"><input type="text" maxlength="40" name="email" size="50" /></td>
    </tr>~;
	if ($allow_hide_email == 1) {
		$yymain .= qq~
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'721'}</b></td>
     <td width="70%" class="windowbg"><input type="checkbox" name="hideemail" value="checked" /></td>
    </tr>~;
	}

	unless ($emailpassword) {
		$yymain .= qq~
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'81'}:</b></td>
     <td width="70%" class="windowbg"><input type="password" maxlength="30" name="passwrd1" size="30" /></td>
    </tr>
    <tr>
     <td width="30%" class="windowbg"><b>$register_txt{'82'}:</b></td>
     <td width="70%" class="windowbg"><input type="password" maxlength="30" name="passwrd2" size="30" /></td>
    </tr>~;
	}

	if ($regcheck) {
		$yymain .= qq~
    <tr>
     <td width="30%" class="windowbg"><b>$floodtxt{'1'}:</b></td>
     <td width="70%" class="windowbg">$showcheck<br /><span class="small">$floodtxt{'casewarning'}</span></td>
    </tr>
    <tr>
     <td width="30%" class="windowbg"><b>$floodtxt{'3'}:</b></td>
     <td width="70%" class="windowbg"><input type="text" maxlength="30" name="verification" id="verification" size="30" /></td>
    </tr>~;
	}

	$yymain .= qq~
    <tr>
     <td colspan="2" align="center" class="catbg">
      <input type="submit" value="$register_txt{'97'}" class="button" />
     </td>
    </tr>
   </table>
</form>~;

	$yymain .= qq~
<script type="text/javascript" language="JavaScript">
 <!--
	document.creator.regusername.focus();
	//function 
 //-->
</script>~;

	$yytitle     = "$register_txt{'97'}";
	$action_area = "addmember";
	&AdminTemplate;
	exit;
}

sub AddMember2 {
	&is_admin_or_gmod;
	&LoadLanguage('Register');
	&LoadLanguage('Main');
	my %member;
	while (($key, $value) = each(%FORM)) {
		$value =~ s~\A\s+~~;
		$value =~ s~\s+\Z~~;
		$value =~ s~[\n\r]~~g;
		$member{$key} = $value;
	}
	$member{'username'} =~ s/\s/_/g;

	# check if there is a system hash named like this by checking existence through size
	my $hsize = keys(%{ $member{'regusername'} });
	if ($hsize > 0) { &admin_fatal_error("system_prohibited_id"); }
	if (length($member{'regusername'}) > 25) { $member{'regusername'} = substr($member{'regusername'}, 0, 25); }
	&admin_fatal_error("no_username","($member{'regusername'})")  if ($member{'regusername'} eq '');
	&admin_fatal_error("id_alfa_only","($member{'regusername'})") if ($member{'regusername'} eq '_' || $member{'regusername'} eq '|');
	&admin_fatal_error("id_reserved","($member{'regusername'})")  if ($member{'regusername'} =~ /guest/i);
	&admin_fatal_error("invalid_character","$register_txt{'35'} $register_txt{'241re'}") if ($member{'regusername'} =~ /[^\w\+\-\.\@]/);
	&admin_fatal_error("no_email","($member{'regusername'})") if ($member{'email'} eq "");
	&admin_fatal_error("id_taken","($member{'regusername'})") if (-e ("$memberdir/$member{'regusername'}.vars"));
	&admin_fatal_error("password_is_userid")                  if ($member{'regusername'} eq $member{'passwrd1'});

	if ($regcheck) {
		require "$sourcedir/Decoder.pl";
		&validation_check($FORM{'verification'});
	}

	if ($emailpassword) {
		srand();
		$member{'passwrd1'} = int(rand(100));
		$member{'passwrd1'} =~ tr/0123456789/ymifxupbck/;
		$_ = int(rand(77));
		$_ =~ tr/0123456789/q8dv7w4jm3/;
		$member{'passwrd1'} .= $_;
		$_ = int(rand(89));
		$_ =~ tr/0123456789/y6uivpkcxw/;
		$member{'passwrd1'} .= $_;
		$_ = int(rand(188));
		$_ =~ tr/0123456789/poiuytrewq/;
		$member{'passwrd1'} .= $_;
		$_ = int(rand(65));
		$_ =~ tr/0123456789/lkjhgfdaut/;
		$member{'passwrd1'} .= $_;

	} else {
		&admin_fatal_error("password_mismatch","($member{'regusername'})") if ($member{'passwrd1'} ne $member{'passwrd2'});
		&admin_fatal_error("no_password","($member{'regusername'})") if ($member{'passwrd1'} eq '');
		&admin_fatal_error("invalid_character","$register_txt{'36'} $register_txt{'241'}") if ($member{'passwrd1'}  =~ /[^\s\w!\@#\$\%\^&\*\(\)\+\|`~\-=\\:;'",\.\/\?\[\]\{\}]/);
	}

	&admin_fatal_error("invalid_character","$register_txt{'69'} $register_txt{'241e'}") if ($member{'email'} !~ /^[\w\-\.\+]+\@[\w\-\.\+]+\.\w{2,4}$/);
	&admin_fatal_error("invalid_email") if (($member{'email'} =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)|(\.$)/) || ($member{'email'} !~ /\A.+@\[?(\w|[-.])+\.[a-zA-Z]{2,4}|[0-9]{1,4}\]?\Z/));

	fopen(FILE, "$vardir/ban_email.txt");
	@banned = <FILE>;
	fclose(FILE);

	foreach $curban (@banned) {
		if ($member{'email'} eq "$curban") { &admin_fatal_error("banned","$register_txt{'678'}$register_txt{'430'}!"); }
	}

	if (lc $member{'regusername'} eq lc &MemberIndex("check_exist", $member{'regusername'})) { &admin_fatal_error("id_taken","($member{'regusername'})"); }
	if (lc $member{'email'} eq lc &MemberIndex("check_exist", $member{'email'})) { &admin_fatal_error("email_taken","($member{'email'})"); }
	if (lc $member{'regrealname'} eq lc &MemberIndex("check_exist", $member{'regrealname'})) { &admin_fatal_error("name_taken","($member{'regrealname'})"); }

	if ($name_cannot_be_userid && lc $member{'regusername'} eq lc $member{'regrealname'}) { &admin_fatal_error("name_is_userid"); }

	&ToHTML($member{'email'});

	fopen(RESERVE, "$vardir/reserve.txt") || &admin_fatal_error("cannot_open","$vardir/reserve.txt", 1);
	@reserve = <RESERVE>;
	fclose(RESERVE);
	fopen(RESERVECFG, "$vardir/reservecfg.txt") || &admin_fatal_error("cannot_open","$vardir/reservecfg.txt", 1);
	@reservecfg = <RESERVECFG>;
	fclose(RESERVECFG);
	for ($a = 0; $a < @reservecfg; $a++) {
		chomp $reservecfg[$a];
	}
	$matchword = $reservecfg[0] eq 'checked';
	$matchcase = $reservecfg[1] eq 'checked';
	$matchuser = $reservecfg[2] eq 'checked';
	$matchname = $reservecfg[3] eq 'checked';
	$namecheck = $matchcase eq 'checked' ? $member{'regusername'} : lc $member{'regusername'};
	$realnamecheck = $matchcase eq 'checked' ? $member{'regrealname'} : lc $member{'regrealname'};

	foreach $reserved (@reserve) {
		chomp $reserved;
		$reservecheck = $matchcase ? $reserved : lc $reserved;
		if ($matchuser) {
			if ($matchword) {
				if ($namecheck eq $reservecheck) { &admin_fatal_error('id_reserved',"$reserved"); }
			} else {
				if ($namecheck =~ $reservecheck) { &admin_fatal_error('id_reserved',"$reserved"); }
			}
		}
		if ($matchname) {
			if ($matchword) {
				if ($realnamecheck eq $reservecheck) { &admin_fatal_error('name_reserved',"$reserved"); }
			} else {
				if ($realnamecheck =~ $reservecheck) { &admin_fatal_error('name_reserved',"$reserved"); }
			}
		}
	}

	&admin_fatal_error("id_taken") if (-e ("$memberdir/$member{'username'}.vars"));

	if ($send_welcomeim == 1) {
		# new format msg file:
		# messageid|(from)user|(touser(s))|(ccuser(s))|(bccuser(s))|subject|date|message|(parentmid)|reply#|ip|messagestatus|flags|storefolder|attachment
		$messageid = $^T . $$;
		fopen(IM, ">$memberdir/$member{'regusername'}.msg", 1);
		print IM "$messageid|$sendname|$member{'regusername'}|||$imsubject|$date|$imtext|$messageid|0|$ENV{'REMOTE_ADDR'}|s|u||\n";
		fclose(IM);
	}
	$encryptopass = &encode_password($member{'passwrd1'});
	$reguser      = $member{'regusername'};
	$registerdate = timetostring($date);

	if ($default_template) { $new_template = $default_template; }
	else { $new_template = "default"; }

	${$uid.$reguser}{'password'}      = $encryptopass;
	${$uid.$reguser}{'realname'}      = $member{'regrealname'};
	${$uid.$reguser}{'email'}         = lc($member{'email'});
	${$uid.$reguser}{'postcount'}     = 0;
	${$uid.$reguser}{'usertext'}      = $defaultusertxt;
	${$uid.$reguser}{'userpic'}       = "blank.gif";
	${$uid.$reguser}{'regdate'}       = $registerdate;
	${$uid.$reguser}{'regtime'}       = $date;
	${$uid.$reguser}{'timeselect'}    = $timeselected;
	${$uid.$reguser}{'timeoffset'}    = $timeoffset;
	${$uid.$reguser}{'dsttimeoffset'} = $dstoffset;
	${$uid.$reguser}{'hidemail'}      = $FORM{'hideemail'};
	${$uid.$reguser}{'timeformat'}    = qq~MM D+ YYYY @ HH:mm:ss*~;
	${$uid.$reguser}{'template'}      = $new_template;
	${$uid.$reguser}{'language'}      = $language;
	${$uid.$reguser}{'pageindex'}     = qq~1|1|1~;

	&UserAccount($reguser, "register") & MemberIndex("add", $reguser) & FormatUserName($reguser);

	if ($emailpassword) {
		require "$sourcedir/Mailer.pl";
		&sendmail($member{'email'}, "$register_txt{'700'} $mbname", "$register_txt{'248'} $member{'regusername'}!\n\n$register_txt{'719'} $member{'regusername'}, $register_txt{'492'} $member{'passwrd1'}\n\n$register_txt{'701'}\n$scripturl?action=profile;username=$useraccount{$member{'regusername'}}\n\n$register_txt{'130'}");

		} else {
		if ($emailwelcome) {
			require "$sourcedir/Mailer.pl";
			&sendmail($member{'email'}, "$register_txt{'700'} $mbname", "$register_txt{'248'} $member{'regusername'}!\n\n$register_txt{'719'} $member{'regusername'}, $register_txt{'492'} $member{'passwrd1'}\n\n$register_txt{'701'}\n$scripturl?action=profile;username=$useraccount{$member{'regusername'}}\n\n$register_txt{'130'}");
		}
	}

	$yytitle       = "$register_txt{'245'}";
	$yymain        = "$register_txt{'245'}";
	$yySetLocation = qq~$adminurl?action=viewmembers;sort=regdate;reversed=on;start=0~;
	&redirectexit;
	$action_area = "addmember";
	&AdminTemplate;
}

#sub startTraceFile { June 2008: looks like this is a not used subroutine!
#	&is_admin_or_gmod;
#
#	fopen("TRACEFILE", "+>$vardir/tracefile.txt");	
#	print TRACEFILE "###############################################################################";
#	print TRACEFILE "Tracefile for $mbname, started ";
#	print TRACEFILE "###############################################################################";
#	fclose("TRACEFILE");
#}

1;