# FILE: src-board-subs-common
# Common subroutines and procedures to start with every occurrence of script
#-------------------------------------------------------------------------------
# DISCUS VERSION 3.10 COPYRIGHT NOTICE
#
# Discus 3.10 is copyright (c) 2000 by DiscusWare, LLC, all rights reserved.
# The use of Discus is governed by the Discus License Agreement which is
# available from the Discus WWW site at:
#    http://www.discusware.com/discus/license
#
# Pursuant to the Discus License Agreement, this copyright notice may not be
# removed or altered in any way.
#-------------------------------------------------------------------------------
#
# The following indicates the version information for this distribution.
# This is available to you through the Version Manager.

$release_version = "3.10";
$free_revision = "4";
$pro_revision = "4";
$DISCUS_release_date = "12/Apr/2001";
$board_topics_file = "board-topics.html" if $board_topics_file eq "";

#-------------------------------------------------------------------------------
# Permissions definitions
# See http://www.discusware.com/support/resources/tips/permissions.html
# Do NOT modify these.  Create discus.conf entries instead.  Otherwise you
# will lose all changes when you upgrade.

$perms0777 = "0777" if $perms0777 eq "";
$perms0666 = "0666" if $perms0666 eq "";
$perms0644 = "0644" if $perms0644 eq "";

#-------------------------------------------------------------------------------

$url_to_default_image = "$html_url/clipart/your_image.gif";
$titlej = &JavaScript_prepare($title);
$message_dir = "$html_dir/messages" if $message_dir eq "";
$message_url = "$html_url/messages" if $message_url eq "";
$cgiurl = "$script_url/board-admin.$cgi_extension";
$cgiurl1 = "$script_url/board-admin-1.$cgi_extension";
$cgiurl2 = "$script_url/board-admin-2.$cgi_extension";
$cgiurl3 = "$script_url/board-admin-3.$cgi_extension";
$cgiurlm = "$script_url/board-admin-menuonly.$cgi_extension";
$secdir = "$admin_dir/secure";
$COOKIE_STRING = "";
$ERROR_STRINGS = "";
$spellchecker_net_feature_on = 0;

if (-e "$admin_dir/backups/QUOTA.txt") {
	$DO_NOT_WRITE_FILES_FLAG = 1;
}

sub quota_message {
	&header;
	print "<HTML><BODY BGCOLOR=#ffffff TEXT=#000000>\n";
	if ($L{DISK_QUOTA_ERROR} eq "") {
		print "This discussion forum has been automatically disabled due to server difficulties to preserve the ";
		print "integrity of files on the board.  The board administrator should resolve this problem and will ";
		print "enable the board when the problem has been resolved.  The board administrator should log in to ";
		print "administration for more details.  We apologize for the inconvenience.";
		exit(0);
	} else {
		print $L{DISK_QUOTA_ERROR};
	}
	print "</BODY></HTML>\n";
	exit(0);
}

sub header {
	return 0 if $DISCUS_PRINTED_HEADER;
	$DISCUS_PRINTED_HEADER = 1;
	print "Content-type: text/html\n";
	if ($COOKIE_STRING ne "") {
		print $COOKIE_STRING;
	}
	print "\n";
	$FORM{'charset_disp'} = $FORM{'lang'} if $FORM{'charset_disp'} eq "";
	if ($FORM{'charset_disp'}) {
		$FORM{'charset_disp'} =~ s/[^\w\-]//g;
		$GLOBAL_OPTIONS{'charset_disp'} = $FORM{'charset_disp'};
	}
}

$DISCUS_PRINTED_HEADER = 0;
$fs = "<FONT FACE=\"Verdana,Arial,Helvetica\" SIZE=2>";
undef %GLOBAL_OPTIONS;
undef %FORM;
undef %COOKIE;
open (OPT, "$admin_dir/options.txt"); @opt = <OPT>; close (OPT);
foreach $line (@opt) {
	if ($line =~ m|^(\w+)=(.*)|) {
		$GLOBAL_OPTIONS{$1} = $2;
	}
}

&read_declarations;
undef %ev; undef @subs; $evalctr = 1;
sub ex {
	my ($function_name) = shift (@_);
	$FUNCTION_NAME_EXECUTING = $function_name if $function_name ne "printuntil";
	my (@params, @deps, $fn, $dep, %files, $line, $file, $subnum, $codestr, $tmp, @file, $lx, @m);
	$fn = $function_id{$function_name};
	@params = @_;
	if (!$ev{$fn}) {
		$ev{$fn} = 2;
		push (@subs, $fn);
		@deps = split(/\s+/, $dependency{$fn});
		foreach $dep (@deps) {
			&ex_r($dep);
		}
	}
	undef %files;
	foreach $line (@subs) {
		if ($ev{$line} == 1) {
			$line = ""; next;
		}
		$ev{$line} = 1;
		($file, $subnum) = split(/-/, $line);
		$files{$file} .= ",$subnum";
	}
	$tmp = $/;
	$/ = "#---SEPARATOR---#";
	$codestr = "";
	foreach $line (keys(%files)) {
		next if $line == 0;
		@deps = split(/,/, $files{$line}); $lx = $line;
		if ($line >= 100 && $pro == 0) {
			next;
		}
		$line .= "_$pro_fileid" if $line >= 100;
		open (FILE, "$admin_dir/source/src-board-subs-$line") || &error_message("Execution Error", "Could not open subroutine file src-board-subs-$lx", 1);
		@file = <FILE>;
		close (FILE);
		foreach $subnum (@deps) {
			next if $subnum == 0;
			@m = split(/\n/, $file[$subnum]);
			@m = grep(!/^\s*#/, @m);
			$codestr .= join("\n", @m);
			$codestr .= "\n";
		}
	}
	$/ = $tmp; $codestr .= "\n1;\n\n";
	eval $codestr;
	if ($@) {
		$ERROR_STRINGS .= "$function_name|$@\n";
	}
	if (scalar(@params) > 0) {
		$tempvar = "\@result = &$function_name(\@params);"; eval $tempvar;
		return @result;
	} else {
		return 0;
	}
}
sub ex_r {
	my ($function_name) = shift (@_);
	my (@params, @deps, $fn, $dep);
	$fn = $function_id{$function_name};
	@params = @_;
	if (!$ev{$fn}) {
		$ev{$fn} = 2;
		push (@subs, $fn);
		@deps = split(/\s+/, $dependency{$fn});
		foreach $dep (@deps) {
			&ex_r($dep);
		}
	}
}

sub lock {
	my (@files, $file, @global, $time, $es, $t, $xr, $fxtime, %lockfiles, $filename, $filenm, $ctr, $ilocker, $flag, $subr_locker, $timeline, $previous, $ps, $lock_flag, %files);
	@files = @_;
 	$begun_time = time;
 	if ($files[0] !~ m|/| && $files[0] ne "*") {
		$subr_locker = shift(@files);
	} else {
		$subr_locker = "?";
	}
	if ($GLOBAL_OPTIONS{'lock_with_file'}) {
		if (!-e "$admin_dir/locks.txt") {
			&error_message("File Locking Error", "The locks.txt file in administration directory does not exist.");
		}
		if (!-w "$admin_dir/locks.txt") {
			$msg = "The locks.txt file in your administration directory is not writable by the server.\n";
			$msg .= "On unix, make sure the permissions on the locks.txt\n";
			$msg .= "file are set to 0777 (rwxrwxrwx).  On NT, have the system\n";
			$msg .= "administrator make the administration directory writable by\n";
			$msg .= "the WWW server.  This is a permissions problem and is between\n";
			$msg .= "you and your web host to work out.  DiscusWare, LLC cannot help you\n";
			$msg .= "resolve this problem.  <A HREF=\"http://www.discusware.com/support/resources/errors/fle.html\" TARGET=_top>Click here</A> for assistance.\n";
			&error_message("File Locking Error", $msg . "<P><B>\$!: <FONT COLOR=#ff0000>Permission Denied</FONT></B>", 0, 1);
		}
		undef %files;
		foreach $file (@files) {
			$files{$file} = 1;
		}
		while (scalar(keys(%files))) {
			$flag = 1; $ctr = time;
			open (LOCKS, "$admin_dir/locks.txt");
			@global = <LOCKS>;
			close (LOCKS);
			foreach $file (@global) {
				($filenm, $time, $ps) = split(/\t/, $file);
				$lockfiles{$filenm} = $time;
			}
I:			foreach $file (keys(%files)) {
				if ($file =~ m|.*/(.*)|) {
					$filenm = $1;
				} else {
					$filenm = $file;
				}
				if ($lockfiles{$filenm} == 0 && $files{"*"} == 0) {
					push (@global, "$filenm\t$ctr\t$$\n");
					delete $files{$file};
					next I;
				}
				if ($ctr - $lockfiles{$filenm} >= 10 && $filenm ne "*") {
					push (@global, "$filenm\t$ctr\t$$\n");
					delete $files{$file};
					next I;
				}
				if ($ctr - $lockfiles{$filenm} >= 15 && $filenm eq "*") {
					push (@global, "$filenm\t$ctr\t$$\n");
					delete $files{$file};
					next I;
				}
			}
			if (time - $begun_time >= 5) {
				if (time > ($begun_time + 5)) {
					$filenm = (keys(%files))[0];
					&log_error("src-board-subs-common", "lock", "Request for lock on $filenm failed... [$subr_locker,$$]");
					&error_message("$L{'FILELOCKERROR'}", "$L{FILEISLOCKED}<BR>[$filenm]", 0, 1);
				}
			}
			return 0 if ($subr_locker eq "src-board-subs-common");
		}
		@global = grep(/\S/, @global);
		open (LOCKS, ">$admin_dir/locks.txt") || &error_message("File Locking Error", "Could not write locks.txt file!");
		print LOCKS @global;
		close (LOCKS);
		return 1;
	}
	if (-e "$admin_dir/locks") {
		if (!-w "$admin_dir/locks") {
			$msg = "The locks directory is not writable by this UID.\n";
			$msg .= "On unix, make sure the permissions on the &quot;locks&quot;\n";
			$msg .= "directory are set to 0777 (rwxrwxrwx).  On NT, have the system\n";
			$msg .= "administrator make the &quot;locks&quot; directory writable by\n";
			$msg .= "the WWW server.  This is a permissions problem and is between\n";
			$msg .= "you and your ISP to work out.  DiscusWare, LLC cannot help you\n";
			$msg .= "resolve this problem.  <A HREF=\"http://www.discusware.com/support/resources/errors/fle.html\" TARGET=_top>Click here</A> for assistance.\n";
			&error_message("File Locking Error", $msg . "<P><B>\$!: <FONT COLOR=#ff0000>Permission Denied</FONT></B>", 0, 1);
		}
	} else {
		&error_message("File Locking Error", "The locks directory does not exist.  Could not gain lock on file.", 0, 1);
	}
O:	foreach $file (@files) {
		$done = 0;
		if ($file eq "*") {
			while ($done == 0) {
				if (open (GLOBAL, "$admin_dir/locks/GLOBAL")) {
					@global = <GLOBAL>;
					close (GLOBAL);
					$timeline = $global[0]; chomp $timeline;
					($time, $ps, $previous) = split(/\s+/, $timeline);
					if ((time - $time) <= 15) {
						$es = $L{'FILELOCKREGEN'};
						$t = (15 - (time - $time));
						$es =~ s/\%sec/$t/g;
						&log_error("src-board-subs-common", "lock", "Attempt to re-lock GLOBAL by process $$ [$subr_locker; $previous]") if $ps == $$;
						&error_message("$L{'FILELOCKERROR'}", "$es [*]");
					}
				}
				unlink("$admin_dir/locks/GLOBAL");
				open (GLOBAL, ">$admin_dir/locks/GLOBAL");
				print GLOBAL time, " ", $$;
				close (GLOBAL);
				open (GLOBAL, "<$admin_dir/locks/GLOBAL");
				$xr = <GLOBAL>; chomp $xr;
				close (GLOBAL);
				($fxtime, $xr) = split(/\s+/, $xr);
				if ($xr == $$) {
					$done = 1;
				}
			}
		} else {
			$file =~ m|(.*)/(.*)|; $dir = $1; $filenm = $2;
			while ($done == 0) {
				$fxtime = 0;
				if (open (GLOBAL, "$admin_dir/locks/GLOBAL")) {
					@global = <GLOBAL>;
					close (GLOBAL);
					$timeline = $global[0]; chomp $timeline;
					($time, $ps, $previous) = split(/\s+/, $timeline);
					if (time - $time <= 15) {
						$es = $L{'FILELOCKREGEN'};
						$t = (15 - (time - $time));
						$es =~ s/\%sec/$t/g;
						&log_error("src-board-subs-common", "lock", "Request for lock on $filenm failed... [$subr_locker,$$] (GLOBAL LOCK exists)");
						&error_message("$L{'FILELOCKERROR'}", "$es [$filenm]", 0, 1);
					}
					&log_error("src-board-subs-common", "lock", "Stale lock canceled (GLOBAL): " . (time-$time) . " seconds old [$subr_locker,$previous,$$]");
					unlink("$admin_dir/locks/GLOBAL") if $ps != $$;
				}
				$lock_flag = 0;
MLF:			while ($lock_flag == 0) {
					if (open (LOCK, "$admin_dir/locks/$filenm")) {
						@lock = <LOCK>;
						close (LOCK);
						$fxtime = $lock[0]; chomp $fxtime;
						($fxtime, $ps, $previous) = split(/\s+/, $fxtime);
						&log_error("src-board-subs-common", "lock", "Attempt to re-lock $filenm by process $$ [$subr_locker]; previous file lock by [$previous]") if $ps == $$;
						if (time - $fxtime >= 10) {
							&log_error("src-board-subs-common", "lock", "Stale lock canceled ($filenm): " . (time-$fxtime) . " seconds old [$subr_locker,$previous,$$]");
							unlink("$admin_dir/locks/$filenm");
						}
					} else {
						next if -e "$admin_dir/locks/$filenm";
						if (open (LOCK, ">$admin_dir/locks/$filenm")) {
							print LOCK time, " ", $$;
							close (LOCK);
							open(LOCK, "<$admin_dir/locks/$filenm");
							$xr = <LOCK>; chomp $xr;
							close (LOCK);
							($fxtime, $xr) = split(/\s+/, $xr);
							if ($xr == $$) {
								$done = 1;
								last MLF;
							}
						}
					}
					if (time > ($begun_time + 7)) {
						&log_error("src-board-subs-common", "lock", "Request for lock on $filenm failed... [$subr_locker,$$]");
						&error_message("$L{'FILELOCKERROR'}", "$L{FILEISLOCKED}<BR>[$filenm]", 0, 1);
					}
					if ($subr_locker eq "change_board_colors") {
						return 0;
					}
					for ($delay_counter = 1; $delay_counter <= 250000; $delay_counter++) {

					}
				}
			}
		}
	}
	return 1;
}

sub unlock {
	my (@files, @locks, %files, $line, $x, $y, $tcache);
	@files = @_; $tcache = time;
	if ($files[0] !~ m|/| && $files[0] ne "*") {
		$subr_locker = shift(@files);
	} else {
		$subr_locker = "?";
	}
	if ($GLOBAL_OPTIONS{'lock_with_file'}) {
		foreach $line (@files) {
			$line = (split(/\t/, $line))[0];
			if ($line =~ m|.*/(.*)|) {
				$line = $1;
			}
			$files{$line} = 1;
		}
		open (LOCKS, "$admin_dir/locks.txt");
		@locks = <LOCKS>;
		close (LOCKS);
		foreach $line (@locks) {
			$line =~ s/\s+$//;
			($x, $y) = split(/\t/, $line);
			$line = "" if $files{$x};
			$line = "" if $tcache > ($y + 15);
			$line .= "\n";
		}
		@locks = grep(/\S/, @locks);
		open (LOCKS, ">$admin_dir/locks.txt");
		print LOCKS "#\n";
		print LOCKS @locks;
		close (LOCKS);
		return 1;
	}
	foreach $file (@files) {
		if ($file eq "*") {
			unlink("$admin_dir/locks/GLOBAL") || &log_error("src-board-subs-common", "Could not remove file 'GLOBAL' from locks directory: $!");
		} else {
			$file =~ m|(.*)/(.*)|; $dir = $1; $filenm = $2;
			if (!unlink("$admin_dir/locks/$filenm")) {
				if (-e "$admin_dir/locks/$filenm") {
					&log_error("src-board-subs-common", "unlock", "Could not remove file '$filenm' from locks directory: [$!]");
					if ($GLOBAL_OPTIONS{'lockerror_disable'} == 1 || $GLOBAL_OPTIONS{'lockerror_disable'} eq "") {
						open (BACKUPS, ">$admin_dir/backups/QUOTA.txt");
						print BACKUPS time, "\n";
						print BACKUPS &escape("Unlocking file $filenm -- could not remove file from $admin_dir/locks because of system error [$!].  If this says 'Permission Denied' you need to fix your permissions as directed at <A HREF=http://www.discusware.com/support/resources/windows/nt_permissions.html>this page</A>.  If allowed to continue this way, your disk quota will fill up quickly, and your users will get 'File Locking Errors' more often than they should"), "\n";
						close (BACKUPS);
						&ex('mail_administrator_quota',2);
					}
				}
			}
		}
	}
}

sub parse_form {
	undef %FORM; $null = pack("c", 0);
	if ($ENV{'CONTENT_LENGTH'} != 0) {
		read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
		@pairs = split(/&/, $buffer);
		foreach $pair (@pairs) {
			($name, $value) = split(/=/, $pair);
			$value =~ tr/+/ /;
			$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
			$value =~ s/<!--#(\w*)(\s*)(\w*)(\s*)=(\s*)"([^"]*)"(.*)-->//g;
			$value =~ s/\r//g;
			$value =~ s/$null//g;
			if ($FORM{$name} eq "") {
				$FORM{$name} = $value;
			} else {
				$FORM{$name} .= ",$value";
			}
		}
	}
	$ENV{'QUERY_STRING'} =~ s/#(.*)$//;
	if ($ENV{'QUERY_STRING'} ne "") {
		$command = $ENV{'QUERY_STRING'};
		@pairs = split(/&/, $command);
		foreach $pair (@pairs) {
			($name, $value) = split(/=/, $pair);
			$value = &unescape($value);
			$value =~ s/$null//g;
			$FORM{$name} = $value if $FORM{$name} eq "";
		}
	}
}

sub error_message {
	my ($reason, $explanation, $flag, $noerr, $nobug) = @_;
	$excl_pt = $!;
	&header;
	print "<HTML><HEAD><TITLE>$reason</TITLE></HEAD>\n";
	print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>\n";
	print "<!-Discus Program Error Message-!>\n";
	print "$fs<FONT SIZE=4 COLOR=#ff0000><CENTER><B>$reason</B></CENTER></FONT>\n";
	print "<HR><P>\n";
	print "<!-Begin Error Message-!>\n";
	print "<FONT FACE='Courier New' SIZE=2>$explanation<P>\n";
	if ($excl_pt && !$noerr) {
		print "\$!: <FONT COLOR=#ff0000><B>$excl_pt</B></FONT><P>";
	}
	if ($@) {
		print "\$\@: <FONT COLOR=#ff0000><B>$@</B></FONT><P>";
	}
	print "</FONT>\n";
	print "<!-End Error Message-!>\n";
	if ($GLOBAL_OPTIONS{'admin_contact_name'}) {
		$contact = "<A HREF=\"mailto:$GLOBAL_OPTIONS{'admin_contact_email'}\">$GLOBAL_OPTIONS{'admin_contact_name'}</A>" if $GLOBAL_OPTIONS{'admin_contact_email'} ne "";
		$contact = "$GLOBAL_OPTIONS{'admin_contact_name'}" if $GLOBAL_OPTIONS{'admin_contact_email'} eq "";
	}
	print "<P>Please contact <B>$contact</B> if this problem persists.\n";
	$URL_F = "javascript:history.back()";
	if ($FORM{'HTTP_REFERER'} =~ m|/(\d+)/(\d+)\.$ext|) {
		$topic = $1; $page = $2;
		$URL_F = "$message_url/$topic/$page.$ext" if -e "$message_dir/$topic";
		$URL_F = "$script_url/board-auth.$cgi_extension?file=/$topic/$page.$ext" if !-e "$message_dir/$topic";
	}
	print "<P><A HREF=\"$URL_F\">$L{ILBACK}</A>\n";
	print "<P><HR><P><FONT FACE=\"Courier New\" SIZE=1><B>Discus ";
	print "Pro " if $pro;
	print " $release_version";
	print ".$free_revision" if !$pro;
	print ".$pro_revision" if $pro;
	print "<BR>Copyright 2000, DiscusWare, LLC, all rights reserved</B>\n";
	if ($ENV{'SCRIPT_URI'} ne "") {
		$ENV{'SCRIPT_URI'} =~ m|(.*)/|; $suri = $';
		if ($suri eq "") {
			$suri = $ENV{'SCRIPT_URI'};
		}
		print "<BR>$suri\n";
	}
	print "<BR>Perl $]";
	print "<BR>[$FUNCTION_NAME_EXECUTING]" if $FUNCTION_NAME_EXECUTING;
	print "<BR><PRE>$ERROR_STRINGS</PRE>" if $ERROR_STRINGS;
	print "</FONT><P>\n";
	if (!$nobug) {
		print "<FORM ACTION=$cgiurl METHOD=POST TARGET=_top><INPUT TYPE=SUBMIT VALUE=\"Additional Information\">\n";
		print "<INPUT TYPE=HIDDEN NAME=action VALUE=bugreport>\n";
		print "<INPUT TYPE=HIDDEN NAME=script VALUE=$suri>\n";
		print "<INPUT TYPE=HIDDEN NAME=sub VALUE=$FUNCTION_NAME_EXECUTING>\n";
		print "<INPUT TYPE=HIDDEN NAME=message VALUE=\"", &escape($reason), "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=explanation VALUE=\"", &escape($explanation), "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=dollarexcl VALUE=\"", &escape($!), "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=dollaratsign VALUE=\"", &escape($@), "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=referer VALUE=\"", &escape($ENV{'HTTP_REFERER'}), "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=FORM VALUE=\"";
		foreach $key (keys(%FORM)) {
			if ($key !~ m|^pass|) {
				print &escape($key), "=", &escape($FORM{$key}), "&";
			}
		}
		print "\">\n";
		print "<INPUT TYPE=HIDDEN NAME=ENV VALUE=\"";
		foreach $key (keys(%ENV)) {
			print &escape($key), "=", &escape($ENV{$key}), "&";
		}
		print "\">\n";
		print "</FORM>\n";
	}
	print "<P>\n";
	print "</FONT></BODY></HTML>\n";
	exit(0);
}

sub extract {
	my ($strin, $error_trapping, $subr_caller) = @_;
	my ($line, $filename, @file, $key);
	undef %level_number;
	$secure = 0;
	$strin .= ".$ext" if $strin !~ m|\.$ext$|;
	$strin = "/$strin" if $strin !~ m|^/|;
	if ($strin =~ m|.*/(\d+)/(\d+)\.$ext|) {
		$f1 = $1; $f2 = $2;
	} else {
		&log_error("src-board-subs-common", "extract", "Input file $strin is not valid (called from '$subr_caller')");
		&error_message('Undefined Error',"Undefined Error extracting file!  Input file $strin is not a valid file!!!", 0, 1);
	}
	$filename = "$message_dir/$f1/$f2.$ext"; $filename2 = "";
	if (!-e "$message_dir/$f1") {
		$filename2 = "$secdir/$f1/$f2.$ext";
		$secure = 1;
	}
	$filename = $filename2 if $filename2 ne "";
	if (!-e $filename) {
		if (-e "$filename.NEW") {
			&lock("extract", $filename);
			if (!-e $filename && -e "$filename.NEW") {
				if ($platform eq "NT" || $NT || $platform =~ m|NT|i) {
					$code = 0;
				} else {
					$code = rename("$filename.NEW", "$filename");
				}
				if ($code != 1 || !-e $filename) {
					open (FILE, "$filename.NEW");
					@file = <FILE>;
					close (FILE);
					open (FILE, ">$filename");
					print FILE @file;
					close (FILE);
					unlink ("$filename.NEW");
				}
				chmod (oct($perms0666), "$filename");
			}
			&unlock("extract", $filename);
		}
	}
	if (open (FILE_EXTRACT, $filename)) {
		@file = <FILE_EXTRACT>;
		close (FILE_EXTRACT);
		foreach $line (@file) {
			$_ = $line;
			$topic_name = $2 if /<!--Topic: (\d+)\/(.*)-->/;
			$topic_number = $1 if /<!--Topic: (\d+)\/(.*)-->/;
			$owner = $1 if /<!--Owner: (\w+)-->/;
			if (/<!--Level (\d+): (\d+)\/(.*)-->/) {
				$key = $1;
				$level_name{$key} = $3;
				$level_number{$key} = $2;
			}
			$me_name = $2 if /<!--Me: (\d+)\/(.*)-->/;
			$me_number = $1 if /<!--Me: (\d+)\/(.*)-->/;
			$parent_number = $1 if /<!--Parent: (\d+)/;
			if (/<!--Param: (\w+)-->/) {
				$param = $1;
			}
			$lm_stamped = $1 if m|^<A NAME="([^P].*)">|;
		}
		return 1;
	} else {
		&error_message('Undefined Error',"Undefined Error extracting file!  <I>$filename</I> could not be opened!") if $error_trapping == 0;
		$topic_name = "<B>Corrupted Topic File</B>";
		$topic_number = $f1;
		$owner = "unknown";
		return 0;
	}
}

sub char_convert {
	my ($stringin, $context, $JSP, $extra_param) = @_;
	my (@char, $line, $tag, $conv);
	if (scalar(@CHARCONVERT) == 0) {
		if (open(CHAR, "$admin_dir/charconvert.conf")) {
			@char = <CHAR>;
			close (CHAR);
			@char = grep(!/^\s*#/, @char);
			@char = grep(/\S/, @char);
			foreach $line (@char) {
				if ($line =~ m|^\s*(\S+)\s*(.+)|) {
					$tag = $1; $conv = $2;
					$conv =~ s/\s+$//;
					if ($conv =~ m%\<\|$%) {
						$conv = $`;
						$conv =~ s/\s+$//;
						$conv =~ s/\$html_url/$html_url/g;
						$conv =~ s/\$ext/$ext/g;
						$conv =~ s/\$script_url/$script_url/g;
						$conv =~ s/\$cgi_extension/$cgi_extension/g;
						$conv =~ s/\$message_url/$message_url/g;
						$conv =~ s/\$title/$title/g;
						$conv =~ s/\$titlej/$titlej/g;
						$conv =~ s/\$topic/$topic_number/g;
						$conv =~ s/\$page/$me_number/g;
					}
					push (@CHARCONVERT, "$tag\t$conv");
				}
			}
		} else {
			$_ = $stringin;
			if ($context == 0) {
				s/&/&amp;/g; s/</\&#60;/g; s/>/\&#62;/g; s/"/&#34;/g; s/\\\\/&#92;/g;
				s/\\\{/&#123;/g; s/\\\}/&#125;/g; s/\\,/&#44;/g; s/\(/&#40;/g;
				s/\)/&#41;/g; s/\[/&#91;/g; s/\]/&#93;/g; s/\*/&#42;/g; s/\+/&#43;/g;
				s/\|/&#124;/g; s/'/&#39;/g;
				return $_;
			} else {
				s/&#39;/'/g; s/&#124;/\|/g; s/&#43;/\+/g; s/&#42;/\*/g;
				s/&#93;/\]/g; s/&#91;/\[/g; s/&#41;/\)/g; s/&#40;/\(/g;
				s/&#44;/,/g; s/&#125;/\}/g; s/&#123;/\{/g; s/&#92;/\\/g;
				s/&#34;/"/g; s/&#62;/>/g; s/&#60;/</g; s/&#amp;/&/g;
				$_ = &JavaScript_prepare($_) if $JSP;
				return $_;
			}
		}
	}
	if ($context == 0) {
		foreach $tag (@CHARCONVERT) {
			$tag =~ m|(\S+)\t(.*)|; $conv = $2; $line = quotemeta($1);
			$stringin =~ s/$line/$conv/g;
		}
		$stringin =~ s/\r\n/\n/g;
		$stringin =~ s/\r/\n/g;
		$stringin =~ s/\n/ <BR>/g;
	} else {
		$stringin =~ s/ <BR>/\n/g;
		foreach $tag (reverse(@CHARCONVERT)) {
			$tag =~ m|(\S+)\t(.*)|; $line = $1; $conv = quotemeta($2);
			$stringin =~ s/$conv/$line/g;
		}
		$stringin =~ s/\r\n/\n/g;
		$stringin =~ s/\r/\n/g;
	}
	$stringin = &JavaScript_prepare($stringin, $extra_param) if $JSP;
	return $stringin;
}

sub JavaScript_prepare {
	my ($str, $param) = @_;
	$str =~ s/<IMG SRC="[^"]*" ALT="([^"]*)">/\[$1\]/g;
	$str =~ s/<([^>]*)>//g if $param ne "nostrip";
	$str =~ s/\n//g;
	if ($param == 1) {
		$str =~ s/([^\w&#; ])/&makeord($1)/ge;
	} else {
		$str =~ s/&#(\d+);//g;
		$str =~ s/'//g;
		$str =~ s/"//g;
		$str =~ s/&quot;//g;
		$str =~ s/&amp;//g;
	}
	return $str;
}

sub makeord {
	my ($o, $num) = @_;
	if (ord($o) <= 126 || ord($o) == 255) {
		$num = ord($o);
		return "&#$num;";
	} else {
		return $o;
	}
}

sub remove_links {
	my ($string) = @_;
	my ($str);
	$str = $string;
	$str =~ s/<A\s([^>]*)>//g;
	$str =~ s/<\/A>//g;
	return $str;
}

sub read_cookie {
	$buffer = $ENV{'HTTP_COOKIE'};
	if ($ENV{'HTTP_COOKIE'} eq "" && $ENV{'COOKIE'} ne "") {
		$buffer = $ENV{'COOKIE'};
	}
	@pairs = split(/; /, $buffer);
	foreach $pair (@pairs) {
		($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$COOKIE{$name} = $value;
	}
}

sub escape {
	my ($input) = @_;
	my ($string);
	$string = $input;
	$string =~ s/([^\w ])/sprintf("%%%02lx", ord($1))/eg;
	$string =~ tr/ /+/;
	return $string;
}

sub unescape {
	my ($input) = @_;
	my ($string);
	$string = $input;
	$string =~ tr/+/ /;
	$string =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	return $string;
}

sub remove_html {
	my ($string, $flag) = @_;
	my ($str);
	$str = $string;
	$str =~ s/<IMG SRC="[^"]*" ALT="([^"]*)">/\[$1\]/g;
	$str =~ s/<[^>]*>//g;
	$str =~ s/&#(\d+);//g if $flag == 0;
	return $str;
}

sub seturl {
	my ($targeturl) = @_;
	if (!($nph_server)) {
		print "Location: $targeturl\n\n";
		exit(0);
	} else {
		&header;
		print "<HTML><HEAD><TITLE>Document Moved</TITLE>\n";
		print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=$targeturl\">\n";
		print "</HEAD>\n";
		print "<BODY>\n";
		print "<NOSCRIPT>\n";
		print "<A HREF=\"$targeturl\">Please click here</A>\n";
		print "</NOSCRIPT>\n";
		print "</BODY></HTML>\n";
		exit(0);
	}
}

sub getfn {
	my ($input) = @_;
	my ($before, $after, $m, $o);
	if ($input =~ m|(.*)/|) {
		$before = "$1/";
		$after = $';
	} else {
		$after = $input;
	}
	while ($after =~ m|(.)|g) {
		$m = $1; $o = ord($m);
		if ($m eq "." || $m =~ /\w/ || $m eq "-") {
			$before .= $m;
		} else {
			$before .= "$o";
		}
	}
	return $before;
}

sub print_cookie_string {
	my ($username_in, $password_in, $password_to_crypt_in) = @_;
	$username_in = "" if $ALREADY_SET_USERNAME;
	$password_in = "" if $ALREADY_SET_PWIN;
	$password_to_crypt_in = "" if $ALREADY_SET_PWCIN;
	$store_cookies = 1 if $GLOBAL_OPTIONS{'cookies'};
	if ($pro) {
		return 0 if $PREF{'cookie'} == 0;
		$expires = "";
		$expires = " expires=Monday, 06-Sep-2010 00:00:00 GMT;" if !$PREF{'cookie_temp'};
		if (!$ALREADY_SET_USERNAME) {
			$COOKIE_STRING .= "Set-cookie: user$COOKIE_ID=$username_in;$expires path=/\n" if $username_in;
			$ALREADY_SET_USERNAME = 1 if $username_in;
		}
		if (!$ALREADY_SET_PWIN) {
			$COOKIE_STRING .= "Set-cookie: rpwd$COOKIE_ID=" if $password_in;
			$COOKIE_STRING .= "x" x $password_in if $password_in;
			$COOKIE_STRING .= ";$expires path=/\n" if $password_in;
			$ALREADY_SET_PWIN = 1 if $password_in;
		}
		if (!$ALREADY_SET_PWCIN) {
			$COOKIE_STRING .= "Set-cookie: cpwd$COOKIE_ID=" if $password_to_crypt_in;
			$COOKIE_STRING .= crypt($password_to_crypt_in, "cookie") if $password_to_crypt_in;
			$COOKIE_STRING .= ";$expires path=/\n" if $password_to_crypt_in;
			$ALREADY_SET_PWCIN = 1 if $password_to_crypt_in;
		}
	} else {
		return 0 if !$store_cookies;
		$COOKIE_STRING .= "Set-cookie: user$COOKIE_ID=$username_in; path=/\n" if $username_in;
		$ALREADY_SET_USERNAME = 1 if $username_in;
		$COOKIE_STRING .= "Set-cookie: rpwd$COOKIE_ID=" if $password_in;
		$COOKIE_STRING .= "x" x $password_in if $password_in;
		$COOKIE_STRING .= "; path=/\n" if $password_in;
		$ALREADY_SET_PWIN = 1 if $password_in;
		$COOKIE_STRING .= "Set-cookie: cpwd$COOKIE_ID=" if $password_to_crypt_in;
		$COOKIE_STRING .= crypt($password_to_crypt_in, "cookie") if $password_to_crypt_in;
		$COOKIE_STRING .= "; path=/\n" if $password_to_crypt_in;
		$ALREADY_SET_PWCIN = 1 if $password_to_crypt_in;
		return 1;
	}
}

sub log_error {
	my ($place, $sub, $message) = @_;
	my ($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst);
	if ($GLOBAL_OPTIONS{'usegmtime'} == 1) {
		($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst) = gmtime(time);
	} else {
		($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst) = localtime(time);
	}
	my (@error, $line, $key, $x);
	open(ERROR_LOG, "$admin_dir/errors.txt");
	@error = <ERROR_LOG>;
	close (ERROR_LOG);
	foreach $line (@error) {
		$line = "" if $line !~ m|\[\*\]|;
	}
	@error = grep(/\S/, @error);
	if (scalar(@error) > 100) {
		$num = scalar(@error);
		@error = splice(@error, 0, $num-100);
	}
	open (ERROR_LOG, ">$admin_dir/errors.txt");
	print ERROR_LOG @error;
	print ERROR_LOG "-" x 60, "\n";
	$hour = "0$hour" if $hour < 10;
	$min = "0$min" if $min < 10;
	$sec = "0$sec" if $sec < 10;
	$nmonth += 1; $year += 1900;
	print ERROR_LOG "[*] $nmonth/$day/$year $hour:$min:$sec $place/$sub $message\n";
	foreach $key (keys(%FORM)) {
		$x = $FORM{$key};
		$x = "*" x length($FORM{$key}) if ($key eq "password" || $key eq "passwd" || $key eq "number");
		print ERROR_LOG "  FORM{$key} = '$x'\n";
	}
	foreach $key (keys(%ENV)) {
		print ERROR_LOG "  ENV{$key} = '$ENV{$key}'\n";
	}
	print ERROR_LOG "-" x 60, "\n";
	close (ERROR_LOG);
}

sub get_page {
	my ($topic, $page, $meta_override) = @_;
	&flush_language($topic);
	my ($head, $announce, $announce_src, $sublist, $about, $about_src, $message, $message_src, $flag, $color, $lm, $description_source);
	my ($save, @file, $pr, @pr, $pr1, $pr2, $seenend, $x, $muflag);
	$seenend = 0;
	if (-e "$message_dir/$topic/$page.$ext") {
		open (FILE, "$message_dir/$topic/$page.$ext");
		$secure = 0;
	} elsif (-e "$secdir/$topic/$page.$ext") {
		open (FILE, "$secdir/$topic/$page.$ext");
		$secure = 1;
	} else {
		&log_error("src-board-subs-common", "get_page", "Requested page [$topic/$page] could not be opened (file does not exist)");
		$MESSED_UP_FILES{"$topic/$page"} = 1;
		return "";
	}
	@file = <FILE>;
	close (FILE);
	@file_last_got = @file;
	undef %DP;
	foreach $_ (@file) {
		$x = $_ if m|\S|;
		$seenend = 1 if m|</HTML>|i;
		if (/^<!--Topic/ || /^<!--Level/ || /^<!--Me:/ || /^<!--Param/ || /^<!--Parent/ || /^<!--Owner/) {
			$head .= $_;
		} elsif (/^<!--Properties: (.*)-->/) {
			$pr = $1; @pr = split(/;/, $pr); undef %DP;
			foreach $pr (@pr) {
				($pr1, $pr2) = split(/=/, $pr);
				$DP{$pr1} = &unescape($pr2);
			}
		} elsif (/^\s*$/) {
			next;
		} elsif (/^<BODY BGCOLOR="([^"]*)" TEXT="([^"]*)" LINK="([^"]*)" VLINK="([^"]*)" ALINK="([^"]*)" BACKGROUND="([^"]*)"/i) {
			$color = join("\t", $1, $2, $3, $4, $5, $6);
		} elsif (/^<BODY BGCOLOR="([^"]*)" TEXT="([^"]*)" LINK="([^"]*)" VLINK="([^"]*)" ALINK="([^"]*)"/i) {
			$color = join("\t", $1, $2, $3, $4, $5, "");
		} elsif (/^<BASEFONT SIZE="([^"]*)"><FONT FACE="([^"]*)">/i) {
			$color .= "\t$1\t$2";
		} elsif (/^<A NAME="([^P].*)">/) {
			$lm = $1;
		} elsif (/^<!-Top: (\d+)-!>/) {
			$sublist .= $_;
		} elsif (/^<!-URL: (\d+)-!>/) {
			$sublist .= $_;
		} elsif (/^<!--About-->/) {
			$flag = 1; $muflag += 1;
		} elsif (/^<!--Source:/) {
			$flag = 2;
		} elsif ($flag == 1) {
			$about .= $_ if (!/^<HR>/ && !/^-->/ && !/^<!-Skip-!>/);
		} elsif ($flag == 2 && m|^<!--/About-->|) {
			$flag = 0;
		} elsif ($flag == 2) {
			$about_src .= $_ if !/^-->/;
		} elsif (/^<!--Announcement-->/) {
			$flag = 15;
		} elsif (/^<!--Announcement Source:/) {
			$flag = 16;
		} elsif ($flag == 15) {
			$announce .= $_ if (!/^<HR>/ && !/^-->/ && !/^<!-Skip-!>/);
		} elsif ($flag == 16 && m|^<!--/Announcement-->|) {
			$flag = 0;
		} elsif ($flag == 16) {
			$announce_src .= $_ if !/^-->/;
		} elsif (m|<!-Post: (\d+)-!>|) {
			$save = $1;
			$flag = 3;
			$message .= $_;
		} elsif (m|<!-/Post: $save-!>|) {
			$flag = 0;
			$message .= $_;
		} elsif (/^<!--\/Messages-->/) {
			$flag = 0;
		} elsif ($flag == 3) {
			$message .= $_;
		} elsif (/^<!--Message Source/) {
			$flag = 4; $muflag += 2;
		} elsif ($flag == 4 && /^-->/) {
			$flag = 0;
		} elsif ($flag == 4) {
			$message_src .= $_;
		} elsif (/^<!--Description Source/) {
			$flag = 5;
		} elsif ($flag == 5 && /^-->/) {
			$flag = 0;
		} elsif ($flag == 5) {
			$description_source .= $_;
		} elsif (m|^<META NAME="DESCRIPTION" CONTENT="([^"]*)">|) {
			$meta_description = $1 if !$meta_override;
		} elsif (m|^<META NAME="KEYWORDS" CONTENT="([^"]*)">|) {
			$meta_keywords = $1 if !$meta_override;
		} elsif (m|^<META NAME="ROBOTS" CONTENT="([^"]*)">|) {
			$meta_robots = $1 if !$meta_override;
		} elsif (m|<!--Properties: (.*)-->|) {
			$PROPS = $1;
			@x = split(/;/, $1);
			foreach $x (@x) {
				($par, $val) = split(/=/, $x);
				$DP{$par} = &unescape($val);
			}
		}
	}
	if ($color eq "") {
		$color = "ffffff\t000000\t0000ff\t800080\tff0000\t\t2\tVerdana,Arial,Helvetica";
	}
	if ($seenend == 0) {
		chomp $x;
		$Fleng = length(join("", @file));
		&log_error("src-board-subs-common", "get_page", "Reading page $topic/$page failed: no &lt;/HTML&gt; found... Last line [$x]; file length $Fleng");
		$MESSED_UP_FILES{"$topic/$page"} = $muflag;
	}
	return ($head, $color, $lm, $announce, $announce_src, $sublist, $about, $about_src, $message, $message_src, $description_source);
}

sub set_page {
	local ($topic, $page, $head, $color, $timestr, $announcement_variable, $announcement_source_variable, $subtopic_variable, $about_variable, $about_source_variable, $message_variable, $message_source_variable, $description_source_variable, $templatefile, $addfile, $timesaver, $data_rec) = @_;
	if ($MESSED_UP_FILES{"$topic/$page"} > 0 && !$data_rec) {
		&log_error("src-board-subs-common", "set_page", "Attempt to write to $topic/$page marked as corrupted file...");
		return 0 if $MESSED_UP_FILES{"$topic/$page"} < 3;
	}
	&flush_language($topic);
	return 0 if $page eq "";
	local (@tfile, $key, $line, $param, $owner, $levelj, $navline, $navbar, $str, $file, @file, @head, @dps, $newpage, $addfile);
	@head = split(/\n/, $head);
	@head = grep(!/^<!--Properties: /, @head);
	undef @dps;
	foreach $key (keys(%DP)) {
		push (@dps, "$key=" . &escape($DP{$key}));
	}
	$head = join("\n", @head);
	$head .= "\n" if $head !~ m|\n$|;
	$head .= "<!--Properties: " . join(";", @dps) . "-->\n";
	if ($templatefile) {
		@tfile = split(/\n/, $templatefile);
	} else {
		($newpage) = &determine_templates($topic);
		@tfile = split(/\n/, $newpage);
	}
	foreach $line (@tfile) {
		$line .= "\n";
	}
	@tfile = grep(/\S/, @tfile);
	if (!(grep(/<!--Start-->/, @tfile))) {
		&error_message("Save Error", "The newpage.conf template has been corrupted; unable to save your change", 0, 1);
	}
	if (!(grep(/\$subtopic_variable/, @tfile)) || !(grep(/\$about_variable/, @tfile)) || !(grep(/\$message_variable/, @tfile)) || !(grep(/\$message_source_variable/, @tfile)) || !(grep(/\$about_source_variable/, @tfile)) || !(grep(/\$head/, @tfile))) {
		&error_message("Save Error", "The newpage.conf template has been corrupted; unable to save your change", 0, 1);
	}
	local ($bgcolor, $text, $link, $vlink, $alink, $image, $size, $face) = split(/\t/, $color);
	local (%level_number, %level_name, $topic_number, $topic_name, $me_number, $me_name);
	foreach $line (split(/\n/, $head)) {
		if ($line =~ m|<!--Topic: (\d+)/(.*)-->|) {
			($topic_number, $topic_name) = ($1, $2);
		} elsif ($line =~ m|<!--Level (\d+): (\d+)/(.*)-->|) {
			$level_number{$1} = $2; $level_name{$1} = $3;
		} elsif ($line =~ m|<!--Me: (\d+)/(.*)-->|) {
			$me_number = $1; $me_name = $2;
		} elsif ($line =~ m|<!--Param: (.*)-->|) {
			$param = $1;
		} elsif ($line =~ m|<!--Owner: (.*)-->|) {
			$owner = $1;
		}
	}
	$navline = "<A HREF=\"$message_url/$board_topics_file\" onMouseOver=\"return setStatus('$L{NBRETURN} $titlej $L{NBMAINPAGE}')\">$title</A>: " if $GLOBAL_OPTIONS{'alternate_topic_navbar'} == 0;
	if ($GLOBAL_OPTIONS{'alternate_topic_navbar'} == 1) {
		$navline = "<A HREF=\"$GLOBAL_OPTIONS{'alternate_topic_navbar_url'}\" onMouseOver=\"return setStatus('$L{NBRETURN} $titlej $L{NBMAINPAGE}')\">$title</A>: " if $GLOBAL_OPTIONS{'alternate_topic_navbar_url'} ne "";
	}
	if ($topic_number != $me_number) {
		$levelj = &JavaScript_prepare($topic_name);
		$navline .= "<A HREF=\"$message_url/$topic_number/$topic_number.$ext\"";
		$navline .= " onMouseOver=\"return setStatus('$L{NBRETURN} $levelj')\">";
		$navline .= "$topic_name</A>: ";
	} else {
		$navline .= "$topic_name";
	}
	foreach $line (sort by_number keys(%level_number)) {
		if ($level_number{$line} != $me_number) {
			$levelj = &JavaScript_prepare($level_name{$line});
			$navline .= "<A HREF=\"$message_url/$topic_number/$level_number{$line}.$ext\"";
			$navline .= " onMouseOver=\"return setStatus('$L{NBRETURN} $levelj')\">";
			$navline .= "$level_name{$line}</A>:\n";
		} else {
			$navline .= "$level_name{$line}";
		}
	}
	$str = &JavaScript_prepare($navline);
	$navbar = $navline;
	local (@users, @addfile, $line_2, @valid, $privpub);
	if ($addfile eq "") {
		$addfile = (&determine_templates($topic))[1];
	}
	@addfile = split(/\n/, $addfile);
	foreach $line (@addfile) {
		$line .= "\n";
		$line = &common_discus_variables($line, $topic, $page);
		if ($line =~ m|<!-/Identification Tag - LEAVE THIS HERE-!>|) {
			$line .= "<INPUT TYPE=HIDDEN NAME=HTTP_REFERER VALUE=//$topic/$page.$ext>\n";
		}
	}
	@addfile = grep(/\S/, @addfile);
	undef @file;
	local ($flag, $navflag, $flag2, $pagetitle, @array);
	@array = split(/\n/, $subtopic_variable); @array = grep(/\S/, @array); $subtopic_variable = join("\n", @array);
	@array = split(/\n/, $about_variable); @array = grep(/\S/, @array); $about_variable = join("\n", @array);
	@array = split(/\n/, $about_source_variable); @array = grep(/\S/, @array); $about_source_variable = join("\n", @array);
	@array = split(/\n/, $message_variable); @array = grep(/\S/, @array); $message_variable = join("\n", @array);
	@array = split(/\n/, $message_source_variable); @array = grep(/\S/, @array); $message_source_variable = join("\n", @array);
	@array = split(/\n/, $head); @array = grep(/\S/, @array); @array = sort(@array); $head = join("\n", @array);
	$pagetitle = $me_name;
	$flag = 0; $navflag = 0; $flag2 = 0;
	$head =~ s/\s+$//g; $head .= "\n";
	foreach $line (@tfile) {
		if ($line =~ /<!--Start-->/) {
			$flag = 1;
		} elsif ($flag == 1) {
			if ($line =~ m|<!--Navbar|) {
				$navflag = 1;
				push (@file, "<!--Navbar-->\n<B>\n$navbar\n</B>\n<!--/Navbar-->\n");
			} elsif ($navflag == 1) {
				$navflag = 0 if $line =~ m|<!--/Navbar|;
			} elsif ($line =~ m|</HEAD>|i && $GLOBAL_OPTIONS{'charset'} ne "") {
				$line = "<META http-equiv=\"Content-Type\" content=\"text/html; charset=$GLOBAL_OPTIONS{'charset'}\">\n$`</HEAD>$'";
				chomp $line; $line .= "\n";
				push (@file, $line);
			} elsif ($line !~ m|\S|) {
				next;
			} else {
				$lineorig = $line;
				chomp $lineorig;
				$line = &eval_subst($line);
				if ($line =~ /\[Read addmessage.txt\]/ || $line =~ /\[Read addmessage.conf\]/) {
					push (@file, @addfile);
				} else {
					if ($line =~ m|<!--Sublist-->|) {
						push (@file, "<!--Sublist--><!--Off\n") if $param !~ m|Sublist|;
						push (@file, "<!--Sublist-->\n") if $param =~ m|Sublist|;
					} elsif ($line =~ m|<!--/Sublist-->|) {
						push (@file, "-->\n<!--/Sublist-->\n") if $param !~ m|Sublist|;
						push (@file, "<!--/Sublist-->\n") if $param =~ m|Sublist|;
					} elsif ($line =~ m|<!--Create-->|) {
						push (@file, "<!--Create--><!--Off\n") if $param !~ m|Create|;
						push (@file, "<!--Create-->\n") if $param =~ m|Create|;
					} elsif ($line =~ m|<!--/Create-->|) {
						push (@file, "-->\n<!--/Create-->\n") if $param !~ m|Create|;
						push (@file, "<!--/Create-->\n") if $param =~ m|Create|;
					} elsif ($line =~ m|<!--About-->|) {
						push (@file, "<!--About--><!--Off\n") if $param !~ m|About|;
						push (@file, "<!--About-->\n") if $param =~ m|About|;
					} elsif ($line =~ m|<!--Source:|) {
						push (@file, "-->\n<!--Source:\n") if $param !~ m|About|;
						push (@file, "<!--Source:\n") if $param =~ m|About|;
					} elsif ($line =~ m|<!--Messages-->|) {
						push (@file, "<!--Messages--><!--Off\n") if $param !~ m|Messages|;
						push (@file, "<!--Messages-->\n") if $param =~ m|Messages|;
					} elsif ($line =~ m|<!--/Messages-->|) {
						push (@file, "-->\n<!--/Messages-->\n") if $param !~ m|Messages|;
						push (@file, "<!--/Messages-->\n") if $param =~ m|Messages|;
					} elsif ($line =~ m|<!--Add-->|) {
						push (@file, "<!--Add--><!--Off\n") if $param !~ m|Add|;
						push (@file, "<!--Add-->\n") if $param =~ m|Add|;
					} elsif ($line =~ m|<!--/Add-->|) {
						push (@file, "-->\n<!--/Add-->\n") if $param !~ m|Add|;
						push (@file, "<!--/Add-->\n") if $param =~ m|Add|;
					} elsif ($line =~ m|<!--Announcement-->|) {
						push (@file, "<!--Announcement--><!--Off\n") if $param !~ m|Announcement|;
						push (@file, "<!--Announcement-->\n") if $param =~ m|Announcement|;
					} elsif ($line =~ m|<!--Announcement Source:|) {
						push (@file, "-->\n<!--Announcement Source:\n") if $param !~ m|Announcement|;
						push (@file, "<!--Announcement Source:\n") if $param =~ m|Announcement|;
					} else {
						push (@file, $line);
					}
				}
			}
		}
	}
	@file = grep(/\S/, @file);
	$length_file = length(join("", @file));
	if ($timesaver && join("", @file) eq join("", @file_last_got)) {
		return 0;
	}
	if (-e "$message_dir/$topic") {
		$filename = "$message_dir/$topic/$page.$ext";
	} else {
		$filename = "$secdir/$topic/$page.$ext";
	}
	open (FILE, ">$filename.NEW") || &error_message("File Save - Write Error", "Could not open $filename.NEW for writing.");
	print FILE @file;
	close (FILE);
	&rename_file($filename, $length_file);
	return 1;
}

sub rename_file {
	my ($filename, $fsize_desired, $new_file_name) = @_;
	my ($fsize, $code, @file, $old_file, $new_file);
	if ($new_file_name ne "") {
		$old_file = $filename;
		$new_file = $new_file_name;
	} else {
		$old_file = "$filename.NEW";
		$new_file = $filename;
	}
	if (-e "$old_file") {
		$fsize = -s "$old_file";
		if ($fsize < $fsize_desired) {
			undef $!;
			unlink ("$old_file");
			if ($GLOBAL_OPTIONS{'diskquota_disable'} == 1 || $GLOBAL_OPTIONS{'diskquota_disable'} eq "") {
				open (BACKUPS, ">$admin_dir/backups/QUOTA.txt");
				print BACKUPS time, "\n";
				print BACKUPS &escape("Write to $new_file: wrong size (expected: $fsize_desired; actual: $fsize"), "\n";
				close (BACKUPS);
				&ex('mail_administrator_quota', 1);
			}
			&error_message("File Save - Write Error", "Error trying to write from $old_file to $new_file -- source file has wrong length (Desired: $fsize_desired; actual: $fsize).  Check your disk quota!");
		}
		if ($platform eq "NT" || $NT || $platform =~ m|NT|i || $^O =~ m|Win32|) {
			$code = 0;
		} else {
			$code = rename("$old_file", "$new_file");
		}
		if ($code != 1 || !-e $new_file) {
			open (FILE, "$old_file");
			@file = <FILE>;
			close (FILE);
			open (FILE, ">$new_file");
			print FILE @file;
			close (FILE);
			$fsize = -s "$new_file";
			if ($fsize < $fsize_desired) {
				unlink($new_file);
				if ($GLOBAL_OPTIONS{'diskquota_disable'} == 1 || $GLOBAL_OPTIONS{'diskquota_disable'} eq "") {
					open (BACKUPS, ">$admin_dir/backups/QUOTA.txt");
					print BACKUPS time, "\n";
					print BACKUPS &escape("Write to $new_file: wrong size (expected: $fsize_desired; actual: $fsize"), "\n";
					close (BACKUPS);
					&ex('mail_administrator_quota', 1);
				}
				undef $!;
				&error_message("File Save - Write Error", "Error trying to write from $old_file to $new_file -- destination file has wrong length (Desired: $fsize_desired; actual: $fsize).  Check your disk quota!");
			}
			unlink ("$old_file");
		}
		chmod (oct($perms0666), "$new_file");
	} else {
		&error_message("File Save - Write Error", "Could not open $old_file for reading.") if $fsize_desired != -1;
	}
	return 1;
}

sub eval_subst {
	my ($inline) = @_;
	return $inline if $inline !~ m|\$(\w+)|;
	my ($outline, $x);
	while ($inline =~ m|\$(\w+)|) {
		$x = $1; $outline .= join("", $`, ${$x}); $inline = $';
	}
	$outline .= $inline;
	return $outline;
}

sub by_number {
	$a <=> $b;
}

sub read_declarations {
	undef %function;
	undef %dependency;
	undef %function_id;
	if (open(DEP, "$admin_dir/source/dep.txt")) {
		@dep = <DEP>;
		close (DEP);
		foreach $line (@dep) {
			chomp $line;
			($function, $subroutine, $dependency) = split(/\s/, $line, 3);
			$function{$function} = $subroutine;
			$dependency{$function} = $dependency;
			$function_id{$subroutine} = $function;
		}
	} else {
		&error_message("Dependency File Error", "Could not open dependency file ($admin_dir/source/dep.txt)!");
	}
	undef %evaluated;
}
&read_cookie;
&flush_language("*", 1);
$L{NOTICE_MAINTENANCEMODE} = "The requested function is unavailable, as the forum is in \"Maintenance Mode.\"  Please try again later." if $L{NOTICE_MAINTENANCEMODE} eq "";
&ex('check_ban_ip', 1) if $pro;
1;

sub flush_language {
	my ($topic_num, $flag) = @_;
	return 1 if $flag == 0;
	if ($MRF eq $topic_num) {
		return 1;
	}
	$MRF = $topic_num;
	if ($topic_num eq "*") {
		undef $LANGUAGE_DIR;
		if ($COOKIE{'uilang' . $COOKIE_ID} ne "") {
			$preferred_language = $COOKIE{'uilang' . $COOKIE_ID};
			$preferred_language =~ tr/A-Z/a-z/;
			$preferred_language =~ s/\W//g;
			if (-e "$admin_dir/language/$preferred_language") {
				$LANGUAGE_DIR = "$admin_dir/language/$preferred_language";
			}
		}
		$LANGUAGE_DIR = "$admin_dir" if $LANGUAGE_DIR eq "";
		$language_dir = $LANGUAGE_DIR;
	} elsif ($topic_num eq "") {
		$language_dir = $admin_dir;
	} else {
		if (-e "$message_dir/$topic_num/language.conf") {
			$language_dir = "$message_dir/$topic_num";
		} elsif (-e "$secdir/$topic_num/language.conf") {
			$language_dir = "$secdir/$topic_num";
		} else {
			$language_dir = $admin_dir;
		}
	}
	open (LANG, "$language_dir/language.conf");
	@lang = <LANG>;
	close (LANG);
	if (-e "$language_dir/language_pro.conf") {
		open (LANG, "$language_dir/language_pro.conf");
		@lang2 = <LANG>;
		close (LANG);
		push (@lang, @lang2);
	}
	undef %lang; undef %L;
	@lang = grep(!/^#/, @lang);
	@lang = grep(/\S/, @lang);
	$cur = "";
	foreach $line (@lang) {
		$line =~ s/##(.*)//;
		$line =~ s/^\s+//;
		$line =~ s/\s+$//;
		if ($line =~ m|^\$(\w+)|) {
			$cur = $1; $del = "";
		} elsif ($line =~ m|^\@(\w+)\((.)\)|) {
			$cur = $1; $del = $2;
		} elsif ($del ne "") {
			@arr = split(/$del/, $line);
			foreach $a (@arr) {
				$a =~ s/^\s+//;
				$a =~ s/\s+$//;
			}
			$evst = "\@$cur = (";
			foreach $a (@arr) {
				$evst .= "'$a',";
			}
			chop ($evst); $evst .= ");";
			eval $evst;
		} elsif ($cur ne "") {
			$line =~ s/\\\s*$/\n/;
			$L{$cur} .= $line . " ";
		}
	}
	foreach $key (keys(%L)) {
		$L{$key} =~ s/^ +//;
		$L{$key} =~ s/ +$//;
	}
}

sub determine_templates {
	my ($topic_number, $can_do_alternate_language, $dynamic_screen_request, $fakeurl) = @_;
	my ($topic, @post, $line, $t, $an, @file, @addfile, $addfile, $flag, $skinflag);
	if ($TEMPL_FOUND{"newpage_$topic_number"} && !$fakeurl && !$dynamic_screen_request) {
		return ($TEMPL_FOUND{"newpage_$topic_number"}, $TEMPL_FOUND{"addmessage_$topic_number"}, $TEMPL_FOUND{"messages_$topic_number"}, $TEMPL_FOUND{"subtopics_$topic_number"}, $TEMPL_FOUND{"topics"});
	}
	my ($bgcolor, $text, $link, $vlink, $alink, $face, $size, $image) = &extract_colorsonly;
	undef %FC;
	undef $dir;
	if ($topic_number =~ m|\d|) {
		$dir = "$message_dir/$topic_number" if -e "$message_dir/$topic_number";
		$dir = "$secdir/$topic_number" if -e "$secdir/$topic_number";
	} else {
		$topic_number = "default";
		$dir = "";
	}
	$dir = "" if $fakeurl;
	my ($newpage_templ) = ("");
	if ($dynamic_screen_request) {
		if ($dir ne "" && open(FILE, "$dir/newpage_dynamic.conf")) {
			@file = <FILE>;
			close (FILE);
			$newpage_templ = join("", @file);
		} elsif (open(FILE, "$admin_dir/newpage_dynamic.conf")) {
			@file = <FILE>;
			close (FILE);
			$newpage_templ = join("", @file);
		}
		return ($newpage_templ, "", "", "", "") if $newpage_templ ne "";
	}
	undef @file;
	if ($dir ne "" && open(FILE, "$dir/default.skin")) {
		@file = <FILE>;
		close (FILE);
		$skinflag = 1;
	} elsif ($GLOBAL_OPTIONS{'skinchoice'} ne "" && $GLOBAL_OPTIONS{'skinchoice'} ne "-none-" && -e "$admin_dir/$GLOBAL_OPTIONS{'skinchoice'}.skin") {
		open (FILE, "$admin_dir/$GLOBAL_OPTIONS{'skinchoice'}.skin");
		@file = <FILE>;
		close (FILE);
		$skinflag = 0;
	}
	if (scalar(@file)) {
		foreach $line (@file) {
			if ($line =~ m|<#include ([\w\-]+)\.conf#>|) {
				$flag = $1;
				$flag = "" if ($flag eq "topics" && $skinflag == 1);
			} elsif ($line =~ m|<#end ([\w\-]+)\.conf#>|) {
				$flag = "";
			} elsif ($flag ne "") {
				$line =~ s/\r\n/\n/g;
				$line =~ s/\r/\n/g;
				$FC{$flag} .= $line;
			}
		}
	}
	if ($TEMPL_FOUND{"newpage_$topic_number"} eq "") {
		if ($dir ne "" && open(FILE, "$dir/newpage.conf")) {
			@file = <FILE>;
			close (FILE);
			$TEMPL_FOUND{"newpage_$topic_number"} = join("", @file);
		} elsif ($FC{'newpage'} ne "") {
			$TEMPL_FOUND{"newpage_$topic_number"} = $FC{"newpage"};
		} elsif (open(FILE, "$admin_dir/newpage.conf")) {
			@file = <FILE>;
			close (FILE);
			$TEMPL_FOUND{"newpage_$topic_number"} = join("", @file);
		} else {
			&error_message("Template Configuration Error", "There is no <B>newpage.conf</B> file defined for this board", 0, 1);
		}
		$TEMPL_FOUND{"newpage_$topic_number"} = &common_discus_variables($TEMPL_FOUND{"newpage_$topic_number"}, $topic_number, "", $dynamic_screen_request);
	}
	$anflag = 0;
	if ($TEMPL_FOUND{"addmessage_$topic_number"} eq "") {
		if ($dir ne "" && open(FILE, "$dir/addmessage.conf")) {
			@file = <FILE>;
			close (FILE);
			$TEMPL_FOUND{"addmessage_$topic_number"} = join("", @file);
			$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-FONT-!>%<FONT FACE="$face" SIZE="$size">%g;
			$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-POST TO CGI-!>%$script_url/board-post\.$cgi_extension%g;
			$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-Anon-!>.*%%g if $anflag;
		} else {
			if ($topic_number >= 0) {
				my (@post, $t, $an, $anflag, @addfile, $af, $fi);
				open (POST, "$admin_dir/postoptions.txt"); @post = <POST>; close (POST);
				($line) = grep(/^$topic_number:/, @post);
				($t, $an) = split(/:/, $line);
				$anflag = $an;
				$anflag = 1 if ($GLOBAL_OPTIONS{'anonymous'} == 0 && $GLOBAL_OPTIONS{'options_used'} == 1);
				undef @addfile; undef $af; undef $fi;
				open (FILE, "$admin_dir/posting.txt"); @file = <FILE>; close (FILE);
				@file = grep(/\S/, @file);
				if (grep(/^$topic_number:/, @file)) {
					($line) = grep(/^$topic_number:/, @file);
					$line =~ s/\s+$//;
					($tn, $ip, $usr, $mod, $pas) = split(/:/, $line);
					if ($ip eq "" && $usr eq "" && $mod eq "" && $pas eq "") {
						$ac = $L{BPPOSTINGDISABLEDDESCR};
						$ac =~ s#\%aopen#<A HREF=\"$script_url/board-contact.$cgi_extension\">#g;
						$ac =~ s#\%aclose#</A>#g;
						$L{BPPOSTINGDISABLEDDESCR} = $ac;
						$af = "<HR><CENTER><TABLE BGCOLOR=#ffcccc><TR><TD><FONT FACE=\"$face\" SIZE=\"$size\" COLOR=000000><B>$L{BPPOSTINGDISABLEDDESCR}</B></FONT></TD></TR></TABLE>";
						$public = 2;
					} elsif ($ip eq "") {
						$fi = "private";
					} else {
						@ip = split(/,/, $ip);
						if (grep(/^~$/, @ip)) {
							$fi = "public";
						} else {
							$fi = "private";
						}
					}
				} else {
					$fi = "private";
				}
				if ($af ne "") {
					$TEMPL_FOUND{"addmessage_$topic_number"} = $af;
				} elsif ($FC{"addmessage-$fi"} ne "") {
					$TEMPL_FOUND{"addmessage_$topic_number"} = $FC{"addmessage-$fi"};
				} elsif (open(FILE, "$admin_dir/addmessage-$fi.conf")) {
					@file = <FILE>;
					close (FILE);
					$TEMPL_FOUND{"addmessage_$topic_number"} = join("", @file);
				} else {
					$TEMPL_FOUND{"addmessage_$topic_number"} = "";
				}
				$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-FONT-!>%<FONT FACE="$face" SIZE="$size">%g;
				$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-POST TO CGI-!>%$script_url/board-post\.$cgi_extension%g;
				$TEMPL_FOUND{"addmessage_$topic_number"} =~ s%<!-Anon-!>.*%%g if $anflag;
			}
		}
		$TEMPL_FOUND{"addmessage_$topic_number"} = &common_discus_variables($TEMPL_FOUND{"addmessage_$topic_number"}, $topic_number);
	}
	if ($TEMPL_FOUND{"subtopics_$topic_number"} eq "") {
		if ($dir ne "" && open(FILE, "$dir/subtopics.conf")) {
			@file = <FILE>;
			close (FILE);
		} elsif ($FC{'subtopics'} ne "") {
			@file = split(/\n/, $FC{'subtopics'});
		} elsif (open(FILE, "$admin_dir/subtopics.conf")) {
			@file = <FILE>;
			close (FILE);
		} else {
			&error_message("Template Configuration Error", "There is no <B>subtopics.conf</B> file defined for this board", 0, 1);
		}
		@file = grep(!/^#/, @file);
		@file = grep(/\S/, @file);
		$TEMPL_FOUND{"subtopics_$topic_number"} = join("\n", @file);
		$TEMPL_FOUND{"subtopics_$topic_number"} =~ s/\s+/ /g;
	}
	$LAST_TOPIC_FORMAT_STRING = $topic_number;
	$TEMPL_FOUND{"subtopics_$topic_number"} = &common_discus_variables($TEMPL_FOUND{"subtopics_$topic_number"}, $topic_number);
	$SUBTOPIC_FORMAT_STRING = $TEMPL_FOUND{"subtopics_$topic_number"};
	if ($TEMPL_FOUND{"messages_$topic_number"} eq "") {
		if ($dir ne "" && open(FILE, "$dir/messages.conf")) {
			@file = <FILE>;
			close (FILE);
		} elsif ($FC{'messages'} ne "") {
			@file = split(/\n/, $FC{'messages'});
		} elsif (open(FILE, "$admin_dir/messages.conf")) {
			@file = <FILE>;
			close (FILE);
		} else {
			&error_message("Template Configuration Error", "There is no <B>messages.conf</B> file defined for this board", 0, 1);
		}
		@file = grep(!/^#/, @file);
		@file = grep(/\S/, @file);
		$TEMPL_FOUND{"messages_$topic_number"} = join("\n", @file);
		$TEMPL_FOUND{"messages_$topic_number"} =~ s/\s+/ /g;
	}
	$TEMPL_FOUND{"messages_$topic_number"} = &common_discus_variables($TEMPL_FOUND{"messages_$topic_number"}, $topic_number);
	$MESSAGE_FORMAT_STRING = $TEMPL_FOUND{"messages_$topic_number"};
	if ($TEMPL_FOUND{"topics"} eq "") {
		if ($FC{'topics'} ne "") {
			$TEMPL_FOUND{"topics"} = $FC{'topics'};
		} else {
			if ($GLOBAL_OPTIONS{'skinchoice'} ne "" && $GLOBAL_OPTIONS{'skinchoice'} ne "-none-" && -e "$admin_dir/$GLOBAL_OPTIONS{'skinchoice'}.skin") {
				open (FILE, "$admin_dir/$GLOBAL_OPTIONS{'skinchoice'}.skin");
				@file = <FILE>;
				close (FILE);
				my (@tf);
				$flag = 0; undef @tf;
				foreach $line (@file) {
					if ($line =~ m|<#include topics\.conf#>|) {
						$flag = 1;
					} elsif ($line =~ m|<#end topics\.conf#>|) {
						$flag = 0;
					} elsif ($flag == 1) {
						push (@tf, $line) if ($line =~ m|\S| && $line !~ m|^#|);
					}
				}
				$TEMPL_FOUND{"topics"} = join("", @tf);
			} elsif (open(FILE, "$admin_dir/topics.conf")) {
				@file = <FILE>;
				close (FILE);
				@file = grep(/\S/, @file);
				@file = grep(!/^#/, @file);
				$TEMPL_FOUND{"topics"} = join("", @file);
			} else {
				&error_message("Template Configuration Error", "There is no <B>topics.conf</B> file defined for this board", 0, 1);
			}
		}
		$TEMPL_FOUND{"topics"} = &common_discus_variables($TEMPL_FOUND{"topics"});
	}
	return ($TEMPL_FOUND{"newpage_$topic_number"}, $TEMPL_FOUND{"addmessage_$topic_number"}, $TEMPL_FOUND{"subtopics_$topic_number"}, $TEMPL_FOUND{"messages_$topic_number"}, $TEMPL_FOUND{"topics"});
}

sub common_discus_variables {
	my ($input, $topic_number, $me_number, $notitle) = @_;
	$input =~ s/\$html_url/$html_url/g;
	$input =~ s/\$ext/$ext/g;
	$input =~ s/\$script_url/$script_url/g;
	$input =~ s/\$cgi_extension/$cgi_extension/g;
	$input =~ s/\$message_url/$message_url/g;
	$input =~ s/\$title/$title/g if !$notitle;
	$input =~ s/\$titlej/$titlej/g if !$notitle;
	$input =~ s/\$topic/$topic_number/g if $topic_number;
	$input =~ s/\$page/$me_number/g if $me_number;
	$input =~ s/\r\n/\n/g;
	$input =~ s/\r/\n/g;
	$input =~ s%<#IFPRO#>(.|\n)*?<#/IFPRO#>%%g if !$pro;
	$input =~ s%<#IFPRO#>%%g;
	$input =~ s%<#/IFPRO#>%%g;
	return $input;
}

sub extract_colorsonly {
	my ($line, $filename, @file, $key);
	my (%v,$basefont,$basesize);
	return @CACHED_COLOR_RESULT if scalar(@CACHED_COLOR_RESULT) > 0;
	if ($GLOBAL_OPTIONS{'COLOR_bgcolor'} ne "") {
		foreach $key ('COLOR_bgcolor', 'COLOR_text', 'COLOR_link', 'COLOR_vlink', 'COLOR_alink', 'COLOR_face', 'COLOR_size', 'COLOR_image') {
			$GLOBAL_OPTIONS{$key} = "" if $GLOBAL_OPTIONS{$key} eq "0";
		}
		return ($GLOBAL_OPTIONS{'COLOR_bgcolor'}, $GLOBAL_OPTIONS{'COLOR_text'}, $GLOBAL_OPTIONS{'COLOR_link'}, $GLOBAL_OPTIONS{'COLOR_vlink'}, $GLOBAL_OPTIONS{'COLOR_alink'}, $GLOBAL_OPTIONS{'COLOR_face'}, $GLOBAL_OPTIONS{'COLOR_size'}, $GLOBAL_OPTIONS{'COLOR_image'});
	}
	$filename = "$message_dir/$board_topics_file";
	&lock("extract_colorsonly", $filename);
	open (FILEEXTR, "$filename") || &error_message("Extract Error", "Couldn't open top file ($board_topics_file)", 1);
	@file = <FILEEXTR>;
	close (FILEEXTR);
	&unlock("extract_colorsonly", $filename);
	if (($bl) = grep(/<BODY/, @file)) {
		$_ = $bl;
		if (/<BODY BGCOLOR="([^"]*)" TEXT="([^"]*)" LINK="([^"]*)" VLINK="([^"]*)" ALINK="([^"]*)"/i) {
			$v{'1'} = $1;
			$v{'2'} = $2;
			$v{'3'} = $3;
			$v{'4'} = $4;
			$v{'5'} = $5;
			if (/BACKGROUND="([^"]*)/i) {
				$v{'6'} = $1;
			}
		} else {
			if (m|BGCOLOR="([^"]*)"|i) {
				$v{'1'} = $1;
			} elsif (m|BGCOLOR=(\S+)|i) {
				$v{'1'} = $1;
			} else {
				$v{'1'} = "#ffffff";
			}
			if (m|TEXT="([^"]*)"|i) {
				$v{'2'} = $1;
			} elsif (m|TEXT=(\S+)|i) {
				$v{'2'} = $1;
			} else {
				$v{'2'} = "#000000";
			}
			if (m|LINK="([^"]*)"|i) {
				$v{'3'} = $1;
			} elsif (m|LINK=(\S+)|i) {
				$v{'3'} = $1;
			} else {
				$v{'3'} = "#0000ff";
			}
			if (m|VLINK="([^"]*)"|i) {
				$v{'4'} = $1;
			} elsif (m|VLINK=(\S+)|i) {
				$v{'4'} = $1;
			} else {
				$v{'4'} = "#800080";
			}
			if (m|ALINK="([^"]*)"|i) {
				$v{'5'} = $1;
			} elsif (m|ALINK=(\S+)|i) {
				$v{'5'} = $1;
			} else {
				$v{'5'} = "#ff0000";
			}
			if (m|BACKGROUND="([^"]*)"|i) {
				$v{'6'} = $1;
			} elsif (m|BACKGROUND=(\S+)|i) {
				$v{'6'} = $1;
			} else {
				$v{'6'} = "";
			}
		}
	} else {
		$v{'1'} = "#ffffff"; $v{'2'} = "#000000"; $v{'3'} = "#0000ff", $v{'4'} = "#800080";
		$v{'5'} = "#ff0000"; $v{'6'} = "";
	}
	if (($bl) = grep(/<BASEFONT /i, @file)) {
		$_ = $bl;
		if (m|<BASEFONT SIZE="(\d+)"><FONT FACE="([^"]*)">|) {
			$v{'8'} = $1; $v{'7'} = $2;
		} elsif (m|<SIZE="(\d+)"|i) {
			$v{'8'} = $1;
			if (m|FACE="([^"]+)"|i) {
				$v{'7'} = $1;
			} else {
				$v{'7'} = "Verdana,Arial,Helvetica";
			}
		} else {
			$v{'7'} = "Verdana,Arial,Helvetica";
			$v{'8'} = 2;
		}
	} else {
		$v{'7'} = "Verdana,Arial,Helvetica";
		$v{'8'} = 2;
	}
	@CACHED_COLOR_RESULT = ($v{1}, $v{2}, $v{3}, $v{4}, $v{5}, $v{7}, $v{8}, $v{6});
	&lock("extract_colorsonly", "$admin_dir/options.txt");
	open (OPTIONS, ">>$admin_dir/options.txt");
	print OPTIONS "COLOR_bgcolor=$v{1}\n";
	print OPTIONS "COLOR_text=$v{2}\n";
	print OPTIONS "COLOR_link=$v{3}\n";
	print OPTIONS "COLOR_vlink=$v{4}\n";
	print OPTIONS "COLOR_alink=$v{5}\n";
	print OPTIONS "COLOR_image=$v{6}\n";
	print OPTIONS "COLOR_face=$v{7}\n";
	print OPTIONS "COLOR_size=$v{8}\n";
	close (OPTIONS);
	&unlock("extract_colorsonly", "$admin_dir/options.txt");
	return ($v{'1'},$v{'2'},$v{'3'},$v{'4'},$v{'5'}, $v{'7'}, $v{'8'}, $v{'6'});
}

sub get_date_time {
	my ($format, $timer, $block_tz) = @_;
	my ($months, $weekdays, $ampm, $time_string);
	$TIMECACHE = time if $TIMECACHE == 0;
	$timer = $TIMECACHE if $timer == 0;
	$timer += ($GLOBAL_OPTIONS{'timezone'}*3600) if $block_tz != 591;
	my ($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst);
	if ($GLOBAL_OPTIONS{'usegmtime'} == 1) {
		($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst) = gmtime($timer);
	} else {
		($sec, $min, $hour, $day, $nmonth, $year, $wday, $yday, $isdst) = localtime($timer);
	}
	if ($L{HRCLOCK} == 12) {
		if ($hour > 12) {
			$hour -= 12;
			$ampm = $L{PM};
		} elsif ($hour == 12) {
			$ampm = $L{PM};
		} else {
			$ampm = $L{AM};
		}
		$hour = 12 if $hour == 0;
	}
	$year += 1900;
	$week = $DAY[$wday];
	$month = $MONTH[$nmonth];
	$month_abbr = $MONTH_ABBR[$nmonth];
	$nmonth += 1;
	$nmonth = "0$nmonth" if ($nmonth < 10 && ($GLOBAL_OPTIONS{'dates_zero'} == 1 || $GLOBAL_OPTIONS{'dates_zero'} eq ""));
	$min = "0$min" if $min < 10;
	$hour = "0$hour" if $hour < 10;
	$day = "0$day" if ($day < 10 && ($GLOBAL_OPTIONS{'dates_zero'} == 1 || $GLOBAL_OPTIONS{'dates_zero'} eq ""));
	$ls = $L{LONGDATE} if $format eq "long";
	$ls = $L{SHORTDATE} if $format eq "short";
	if ($format eq "shorter") {
		if ($L{SHORTERDATE} ne "") {
			$ls = $L{SHORTERDATE};
		} else {
			$ls = $L{SHORTDATE};
		}
	}
	if ($format eq "message") {
		if ($L{MESSAGEDATE} ne "") {
			$ls = $L{MESSAGEDATE};
		} else {
			$ls = $L{LONGDATE};
		}
	}
	$ls = $L{REALSHORTDATE} if $format eq "realshort";
	$ls = $L{DATEONLY} if $format eq "dateonly";
	$ls1 = $ls;
	$ls =~ s/\%weekday/$week/g;
	$ls =~ s/\%hour/$hour/g;
	$ls =~ s/\%minute/$min/g;
	$ls =~ s/\%month_abbr/$month_abbr/g;
	$ls =~ s/\%month/$month/g;
	$ls =~ s/\%nmonth/$nmonth/g;
	$ls =~ s/\%year/$year/g;
	$ls =~ s/\%ampm/$ampm/g;
	$ls =~ s/\%day/$day/g;
	$ls =~ s/\s+$//;
	return $ls;
}

sub safe_write {
	my ($file, $crf, $zero_ok, $caller) = @_;
	my ($content, $timefile, $filename, $destfile, $size, $expc, $divider);
	$divider = $/; undef $/;
	$timefile = time; $timefile .= $$; $timefile =~ s/\D//g;
	$file =~ m|.*/(.*)$|; $filename = $1;
	$destfile = "$admin_dir/backups/$timefile-$filename";
	$content = join("", @{$crf}) if !$DIAGNOSTICS;
	if (length($content) == 0 && !$zero_ok) {
		$/ = $divider;
		&error_message("Error writing file $filename", "Received content is zero length.  File write was aborted for safety reasons.  Please click 'Reload Frame' to try again.", 0, 1) if !$DIAGNOSTICS;
		return 0 if $DIAGNOSTICS;
	}
	$content .= "\n" if $content !~ m|\n$|;
	if ($GLOBAL_OPTIONS{'quota_check_off'} == 1) {
		open (FILE, ">$file");
		print FILE $content;
		close (FILE);
		$/ = $divider;
		return 1;
	}
	open (DEST, ">$destfile") || &error_message("Error writing file $filename", "Could not write to output file $filename.  Make sure that your 'backups' directory under your administration directory has the proper permissions (0777 rwxrwxrwx) to permit file creation by your server, <I>especially if you see 'Permission Denied' below</I>!");
	print DEST $content;
	close (DEST);
	$size = -s $destfile;
	$expc = length($content);
	if ($size < $expc) {
		$/ = $divider;
		unlink $destfile;
		if ($GLOBAL_OPTIONS{'diskquota_disable'} == 1 || $GLOBAL_OPTIONS{'diskquota_disable'} eq "") {
			open (BACKUPS, ">$admin_dir/backups/QUOTA.txt");
			print BACKUPS time, "\n";
			print BACKUPS &escape("Write to $destfile: wrong size (expected: $expc; actual: $size) ... no files were corrupted but changes in this operation were not changed!"), "\n";
			close (BACKUPS);
			&ex('mail_administrator_quota', 1);
		}
		&error_message("Error writing file $filename", "Created file name $filename had wrong size (expected: $expc; actual: $size).  Check your disk quota immediately!", 0, 1) if !$DIAGNOSTICS;
		return 0 if $DIAGNOSTICS;
	}
	open (FILE, ">$file") || &error_message("Error writing to $filename", "Could not write to actual file $filename.  Check permissions on your directories.");
	print FILE $content;
	close (FILE);
	$size = -s $file;
	if ($size < $expc) {
		$/ = $divider;
		if ($GLOBAL_OPTIONS{'diskquota_disable'} == 1 || $GLOBAL_OPTIONS{'diskquota_disable'} eq "") {
			open (BACKUPS, ">$admin_dir/backups/QUOTA.txt");
			print BACKUPS time, "\n";
			print BACKUPS &escape("Write to $file: wrong size (expected: $expc; actual: $size) ... this file is probably corrupted now.  The backup file $destfile is probably not corrupted.  You should restore this file manually before enabling the board!"), "\n";
			close (BACKUPS);
			&ex('mail_administrator_quota', 1);
		}
		&error_message("Error writing file $filename", "Created file name $filename had wrong size (expected: $expc; actual: $size).  Check your disk quota immediately!  The original version of this file has been stored and can be restored by the board administrator.", 0, 1) if !$DIAGNOSTICS;
		return 0 if $DIAGNOSTICS;
	}
	$/ = $divider;
	unlink $destfile;
	return 1;
}

# END - FILE IS CORRECTLY UPLOADED #
