# FILE: src-board-subs-14
# Data Recovery functions
#-------------------------------------------------------------------------------
# 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.
#-------------------------------------------------------------------------------

#---SEPARATOR---#
#REQ:show_gauge
#REQ:data_recovery_special

sub clean_tree {
	my ($tempfile, $ts, $topic1) = @_;
	$tempfile =~ s/\D//g;
	$topic1 =~ s/\D//g; $topic = $topic1; $topic_number = $topic;
	($dirdata) = grep(/^$topic_number-/, @pairs);
	$files = (split(/-/, $dirdata))[1];
	$cpos = $FORM{'cpos'};
	$topic_string = $FORM{'ts'};
	@pairs = split(/,/, $topic_string);
	undef @dir;
	if (-e "$message_dir/$topic_number") {
		opendir(DIR, "$message_dir/$topic_number");
	} elsif (-e "$secdir/$topic_number") {
		opendir(DIR, "$secdir/$topic_number");
	}
	$ctr = 0; $hitend = 0;
	$factor = 15;
	$factor = $GLOBAL_OPTIONS{'reindex_factor'} if $GLOBAL_OPTIONS{'reindex_factor'} > 0;
	$factor = $factor * 3;
	while ($dir = readdir(DIR)) {
		next if $dir !~ m|^(\d+)\.$ext$|;
		$ctr += 1;
		if ($ctr > ($cpos*$factor) && $ctr <= ((1+$cpos)*$factor)) {
			push (@dir, $dir);
		} elsif ($ctr > ((1+$cpos)*$factor)) {
			$hitend = 1; last;
		}
	}
	closedir(DIR);
	undef %TREE_SEEN;
	&lock("clean_tree", "$admin_dir/msg_index/$topic_number-tree.txt");
	open (TREE, "$admin_dir/msg_index/$topic_number-tree.txt");
	while (<TREE>) {
		chomp;
		@c = split(/\t/, $_);
		$TS{$c[2]} = 1;
	}
	close (TREE);
	&unlock("clean_tree", "$admin_dir/msg_index/$topic_number-tree.txt");
	open (TEMPFILE, ">>$admin_dir/msg_index/$tempfile.TMP");
O:	foreach $file (@dir) {
		$FORM{'done'} += 1;
		$file =~ m|^(\d+)\.$ext|; $page = $1; $topic = $topic_number;
		next if $TS{$page} == 1;
		my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
		@head = split(/\n/, $head);
		$lt_seen = $topic;
I:		foreach $line (@head) {
			if ($line =~ m|<!--Level (\d+): (\d+)/(.*)-->|) {
				($ln, $lpn, $lnm) = ($1, $2, $3);
				$lt_seen = $lpn if $TS{$lpn} == 1;
				$me_name = $3 if $TS{$lpn} == 1;
				if ($TS{$lpn} == 0) {
					print TEMPFILE "$topic/$lt_seen ($topic/$page) [$me_name]\n";
					last I;
				}
			}
		}
	}
	close (TEMPFILE);
	$flag = 0; $files = 0; $nexttopic = 0; $done = 0;
	foreach $line (@pairs) {
		$line =~ m|^(\d+)-(\d+)|;
		$files += $2;
		if ($1 == $topic_number) {
			$flag = 1;
		} elsif ($flag == 1) {
			$nexttopic = $1; $flag = 2;
		}
	}
	if ($hitend == 0) {
		$cpos = 0; $topic1 = $nexttopic;
	} else {
		$cpos += 1; $topic1 = $topic;
	}
	$pct = ($FORM{'done'} / $files);
	&extract("//$topic/$topic.$ext");
	$actionurl="$cgiurl?action=clean_tree&username=$superuser";
	&show_gauge("Clean Up Tree", "Cleaning up tree -- &quot;$topic_name&quot;", $pct, "$actionurl&ctopic=$topic1&cpos=$cpos&ts=$topic_string&done=$FORM{'done'}&tempfile=$tempfile") if $topic1 != 0;
	open (TEMPFILE, "$admin_dir/msg_index/$tempfile.TMP") || &error_message("File Error", "Could not open temporary file!");
	@tempfile = <TEMPFILE>;
	close (TEMPFILE);
	$removed = 0;
	$fixed = 0; undef %done; undef @removed; undef @fixed; undef @errors;
	my ($topic, $page, $topic2, $page2, $line, $me_name, $dir);
	foreach $line (sort(@tempfile)) {
		if ($line =~ m|^(\d+)/(\d+) \((\d+)/(\d+)\) \[(.*)\]|) {
			$topic = $1; $page = $2; $topic2 = $3; $page2 = $4; $me_name = $5;
		} else {
			push (@errors, $line);
		}
		$dir = "$message_dir/$topic" if -e "$message_dir/$topic";
		$dir = "$secdir/$topic" if -e "$secdir/$topic";
		if ($page == 0) {
			unlink("$dir/$page2.$ext");
			$removed += 1;
			push (@removed, $page2);
		} else {
			next if $done{$page};
			$done{$page} = 1;
			$code = &data_recovery_special($topic, $page, 1);
			push (@fixed, $me_name) if $code;
			$fixed += $code;
		}
	}
	unlink "$admin_dir/msg_index/$tempfile.TMP";
	&header;
	print "<HTML><HEAD><TITLE>Tree Cleanup</TITLE></HEAD>\n";
	print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>\n";
	print "$fs<FONT SIZE=4><CENTER>Tree Cleanup</CENTER></FONT><HR><P>\n";
	print "The tree cleanup reported the following:<P>\n";
	print "<LI>Orphan pages removed: <B>$removed</B>\n";
	print "<LI>Subtopic lists repaired: <B>$fixed</B>\n";
	print "<P>\n";
	if ($removed == 0 && $fixed == 0) {
		print "Discus Data Recovery could not locate any problems with your tree file or your file structure.\n";
		print "There is no need to proceed further.\n";
	} elsif ($removed > 0 && $fixed == 0) {
		print "Discus Data Recovery removed some orphaned files that were unnecessarily taking up disk space\n";
		print "on your board.  These files were not causing any problems with your tree file, so there is no\n";
		print "need to proceed further.\n";
	} elsif ($fixed > 0) {
		print "Discus Data Recovery fixed <B>$fixed</B> subtopic list";
		print "s" if $fixed != 1;
		print "!  This will add back lost subtopics to your discussion board.\n";
		print "The next step is to regenerate your board's index file.  You can do this by clicking the button\n";
		print "below.  Please note that after you have run the regeneration procedure of the tree file by clicking\n";
		print "this button, if you are still having trouble, repeat this procedure.\n";
		print "<FORM ACTION=\"$cgiurl2\" METHOD=POST NAME=tands>\n";
		print "<INPUT TYPE=SUBMIT NAME=submit VALUE=\"Index Board\" onClick=\"return confirm('Are you sure you want to re-index your board?')\">\n";
		print "<INPUT TYPE=HIDDEN NAME=index_topics VALUE='all'>\n";
		print "<INPUT NAME=action TYPE=hidden value=\"templates\">\n";
		print "<INPUT NAME=username TYPE=hidden value=\"$FORM{'username'}\">\n";
		print "</FORM>\n";
	}
	print "<P><HR><B>DETAILS:</B><P>\n";
	print "Removed file(s):<P><UL>\n";
	print "<LI>" if scalar(@removed);
	print join("<LI>", @removed);
	print "</UL>\n<P>Repaired file(s):<P><UL>\n";
	print "<LI>" if scalar(@fixed);
	print join("<LI>", @fixed);
	print "</UL><P>\n";
	if (scalar(@errors)) {
		print "<FONT COLOR=#ffffff>", join("<BR>", @errors), "</FONT><P>\n";
	}
	print "<HR><CENTER><A HREF=$cgiurlm?cmd=data_recovery&username=$superuser>Return to Data Recovery</A></CENTER><P>\n";
	print "</BODY></HTML>\n";
	exit(0);
}

#---SEPARATOR---#
#REQ:show_gauge

sub clean_posting_logs {
	my ($tempfile, $ts, $topic1) = @_;
	$tempfile =~ s/\D//g;
	$topic1 =~ s/\D//g; $topic = $topic1; $topic_number = $topic;
	($dirdata) = grep(/^$topic_number-/, @pairs);
	$files = (split(/-/, $dirdata))[1];
	$cpos = $FORM{'cpos'};
	$topic_string = $FORM{'ts'};
	@pairs = split(/,/, $topic_string);
	$fixed = 0 + $FORM{'fixed'};
	$added = 0 + $FORM{'added'};
	if ($FORM{'cleanup'} == 0) {
		undef @dir;
		if (-e "$message_dir/$topic_number") {
			opendir(DIR, "$message_dir/$topic_number");
		} elsif (-e "$secdir/$topic_number") {
			opendir(DIR, "$secdir/$topic_number");
		}
		$ctr = 0; $hitend = 0;
		$factor = 15;
		$factor = $GLOBAL_OPTIONS{'reindex_factor'} if $GLOBAL_OPTIONS{'reindex_factor'} > 0;
		$factor = $factor * 2;
		while ($dir = readdir(DIR)) {
			next if $dir !~ m|^(\d+)\.$ext$|;
			$ctr += 1;
			if ($ctr > ($cpos*$factor) && $ctr <= ((1+$cpos)*$factor)) {
				push (@dir, $dir);
			} elsif ($ctr > ((1+$cpos)*$factor)) {
				$hitend = 1; last;
			}
		}
		closedir(DIR);
		undef %found; undef %named; undef %firstfew;
		open (LOG, "$admin_dir/msg_index/$topic-log.txt");
		while (<LOG>) {
			chomp;
			@x = split(/;/, $_);
			$found{$x[0]} = 1;
			$named{$x[0]} = $x[7];
			$firstfew{$x[0]} = $x[6];
		}
		close (LOG);
		undef %fixed;
		open (TEMPFILE, ">>$admin_dir/msg_index/$tempfile.TMP");
		open (LOG, ">>$admin_dir/msg_index/$topic-log.txt");
O:		foreach $file (@dir) {
			$FORM{'done'} += 1;
			$file =~ m|^(\d+)\.$ext|; $page = $1; $topic = $topic_number;
			my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
			@msg = split(/\n/, $message); undef %dolog;
			@mg = grep(/^<!-Post: (\d+)-!>/, @msg);
			foreach $line (@mg) {
				$line =~ m|<!-Post: (\d+)-!>|;
				$o = $1;
				$dolog{$o} = 1 if !$found{$o};
				$dolog{$o} = 2 if $named{$o} eq $L{BPANONYMOUS};
				$dolog{$o} = 2 if $named{$o} eq "";
				$dolog{$o} = 2 if $firstfew{$o} eq "";
			}
			$flag = 0;
			$profile_identity = "unknown";
			$email_address = "";
			foreach $line (@msg) {
				if ($line =~ m|<!-Post: (\d+)-!>|) {
					$num = $1;
					print TEMPFILE "$topic $num\n";
					next if !$dolog{$num};
					$flag = $dolog{$num};
					$time = 0;
					if ($line =~ m|<!-Time: (\d+)-!>|) {
						$time = $1;
					}
				} elsif ($line =~ m|<!-/Post|) {
					if ($flag == 1) {
						$added += 1;
						print LOG "$num;$profile_identity;$time;$topic/$page;unknown;unknown;$firstfew;$poster;$email_address\n";
					} elsif ($flag == 2) {
						$fixed += 1;
						$fixed{$num} = "$num;$profile_identity;$time;$topic/$page;unknown;unknown;$firstfew;$poster;$email_address\n";
					}
					$flag = 0;
				} elsif ($flag >= 1) {
					if ($line =~ m|<!-Name-!>(.*)<!-/Name-!>|) {
						$nm = $1; $nm =~ s/^\s+//; $nm =~ s/\s+$//; $poster = &escape($nm);
						if ($dolog{$num} == 2 && $nm eq $L{BPANONYMOUS}) {
							$dolog{$num} = 0;
							$flag = 0;
							next;
						}
					}
					if ($line =~ m|<!-Text-!>(.*)<!-/Text-!>|) {
						$txt = $1; $firstfew = &escape(substr($txt, 0, 40));
					}
					if ($line =~ m|<!-Email-!>(.*)<!-/Email-!>|) {
						$eml = $1;
						if ($eml =~ m|&profile=([^\&\"]+)|) {
							$emx = $1; $emx =~ s/-/:/;
							$profile_identity = $emx; $email_address = "";
						} elsif ($eml =~ m|mailto:([\w\-\.\+]+)\@([\w\-\.\+]+)|) {
							$profile_identity = "unknown";
							$email_address = "$1\@$2";
						}
					} else {
						$profile_identity = "unknown";
						$email_address = "";
					}
				}
			}
		}
		close (TEMPFILE);
		close (LOG);
		if (scalar(keys(%fixed))) {
			$kfixed = scalar(keys(%fixed));
			$x = join("/", keys(%fixed));
			open (LOG, "$admin_dir/msg_index/$topic-log.txt");
			$size = 0;
			open (LOGNEW, ">$admin_dir/msg_index/$topic-log.txt.NEW");
			while (<LOG>) {
				if (m|^(\d+);|) {
					if ($fixed{$1}) {
						print LOGNEW $fixed{$1};
						delete $fixed{$1};
						$size += length($fixed{$1});
					} else {
						print LOGNEW $_;
						$size += length($_);
					}
				}
			}
			close (LOG);
			foreach $key (keys(%fixed)) {
				print LOGNEW $fixed{$key};
				$size += length($fixed{$key});
			}
			close (LOGNEW);
			&rename_file("$admin_dir/msg_index/$topic-log.txt", $size);
		}
		$flag = 0; $files = 0; $nexttopic = 0; $done = 0;
		foreach $line (@pairs) {
			$line =~ m|^(\d+)-(\d+)|;
			$files += $2;
			if ($1 == $topic_number) {
				$flag = 1;
			} elsif ($flag == 1) {
				$nexttopic = $1; $flag = 2;
			}
		}
		if ($hitend == 0) {
			$cpos = 0; $topic1 = $nexttopic;
		} else {
			$cpos += 1; $topic1 = $topic;
		}
		$pct = ($FORM{'done'} / $files);
		&extract("//$topic/$topic.$ext");
		$actionurl="$cgiurl?action=clean_logs&username=$superuser";
		&show_gauge("Clean Posting Logs", "Verifying all posting logs -- &quot;$topic_name&quot;", $pct, "$actionurl&ctopic=$topic1&cpos=$cpos&ts=$topic_string&done=$FORM{'done'}&tempfile=$tempfile&added=$added&fixed=$fixed") if $topic1 != 0;
		&seturl("$actionurl&cpos=1&ts=$topic_string&tempfile=$tempfile&cleanup=1&added=$added&fixed=$fixed");
	}
	$paird = $pairs[$cpos-1];
	$paird =~ m|^(\d+)|; $topic = $1;
	if ($topic > 0) {
		undef %found;
		$size = 0;
		$removed = $FORM{'removed'};
		open (TEMPFILE, "$admin_dir/msg_index/$tempfile.TMP");
		while (<TEMPFILE>) {
			m|^(\d+)\s+(\d+)|;
			$found{$2} = 1 if $1 == $topic;
		}
		close (TEMPFILE);
		open (LOG, "$admin_dir/msg_index/$topic-log.txt");
		open (LOGOPT, ">$admin_dir/msg_index/$topic-log.txt.NEW");
		while (<LOG>) {
			if (m|^(\d+)|) {
				if ($found{$1} == 0) {
					$removed += 1;
					next;
				}
				print LOGOPT $_; $size += length($_);
			} else {
				$removed += 1;
			}
		}
		close (LOG);
		close (LOGOPT);
		&rename_file("$admin_dir/msg_index/$topic-log.txt", $size);
		$cpos += 1;
		$paird = $pairs[$cpos-1];
		$paird =~ m|^(\d+)|; $topic = $1;
		$pct = $cpos / scalar(@pairs);
		$actionurl="$cgiurl?action=clean_logs&username=$superuser";
		&show_gauge("Clean Posting Logs", "Cleaning up posting logs ($topic)", $pct, "$actionurl&cpos=$cpos&ts=$topic_string&tempfile=$tempfile&added=$FORM{'added'}&removed=$removed&fixed=$fixed&cleanup=1") if $topic != 0;
	}
	unlink "$admin_dir/msg_index/$tempfile.TMP";
	&header;
	print "<HTML><HEAD><TITLE>Posting Log Cleanup</TITLE></HEAD>\n";
	print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>\n";
	print "$fs<FONT SIZE=4><CENTER>Posting Log Cleanup</CENTER></FONT><HR><P>\n";
	print "RESULTS:<P>\n";
	$added = 0 + $FORM{'added'};
	print "<LI>$added post record(s) recreated.\n";
	$removed = 0 + $FORM{'removed'};
	print "<LI>$removed post record(s) removed.\n";
	$fixed = 0 + $FORM{'fixed'};
	print "<LI>$fixed post record(s) repaired.\n";
	print "<HR><CENTER><A HREF=$cgiurlm?cmd=data_recovery&username=$superuser>Return to Data Recovery</A></CENTER><P>\n";
	print "</BODY></HTML>\n";
	exit(0);
}

#---SEPARATOR---#
#REQ:show_gauge
#REQ:regenerate_message

sub repair_names {
	my ($tempfile, $ts, $topic1) = @_;
	$tempfile =~ s/\D//g;
	$topic1 =~ s/\D//g; $topic = $topic1; $topic_number = $topic;
	($dirdata) = grep(/^$topic_number-/, @pairs);
	$files = (split(/-/, $dirdata))[1];
	$cpos = $FORM{'cpos'};
	$topic_string = $FORM{'ts'};
	@pairs = split(/,/, $topic_string);
	undef @dir;
	if (-e "$message_dir/$topic_number") {
		opendir(DIR, "$message_dir/$topic_number");
	} elsif (-e "$secdir/$topic_number") {
		opendir(DIR, "$secdir/$topic_number");
	}
	$ctr = 0; $hitend = 0;
	$factor = 15;
	$factor = $GLOBAL_OPTIONS{'reindex_factor'} if $GLOBAL_OPTIONS{'reindex_factor'} > 0;
	while ($dir = readdir(DIR)) {
		next if $dir !~ m|^(\d+)\.$ext$|;
		$ctr += 1;
		if ($ctr > ($cpos*$factor) && $ctr <= ((1+$cpos)*$factor)) {
			push (@dir, $dir);
		} elsif ($ctr > ((1+$cpos)*$factor)) {
			$hitend = 1; last;
		}
	}
	closedir(DIR);
	undef %repair;
	foreach $file (@dir) {
		$FORM{'done'} += 1;
		$file =~ m|^(\d+)\.$ext|; $page = $1; $topic = $topic_number;
		my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
		@msg = split(/\n/, $message); undef %dolog;
		@mg = grep(/^<!-Post: (\d+)-!>/, @msg);
		foreach $line (@mg) {
			$line =~ m|<!-Post: (\d+)-!>|;
		}
		$flag = 0;
		foreach $line (@msg) {
			if ($line =~ m|<!-Post: (\d+)-!>|) {
				$num = $1; $flag = $num;
			} elsif ($line =~ m|<!-/Post:|) {
				$flag = 0;
			} elsif ($flag) {
				if ($line =~ m|<!-Name-!><!-/Name-!>|) {
					$repair{$flag} = $page;
				} elsif ($line =~ m|<!-Name-!>(.*?)<!-/Name-!>|) {
					$mtch = $1;
					$repair{$flag} = $page if $1 !~ m|\(|;
				}
			}
		}
	}
	undef %done;
	if (keys(%repair)) {
		my ($key, $line, $flag, %LOGDATA, @message);
		$done{$pg} = 1;
		undef %LOGDATA; $looked_in_old_log = 0;
		open (LOG, "$admin_dir/msg_index/$topic-log.txt");
		while (<LOG>) {
			@c = split(/;/, $_);
			chomp $c[7]; chomp $c[8];
			$LOG{$c[0]}	= join("/", $c[1], &unescape($c[7]), $c[8]);
		}
		close (LOG);
		$unrec = $L{BPANONYMOUS}; $unrec = "Anonymous" if $unrec eq "";
		chomp $unrec;
		foreach $key (keys(%repair)) {
			$pg = $repair{$key};
			next if $done{$pg};
			$done{$pg} = 1; undef %usr;
			&log_error("src-board-subs-11", "repair_names", "Fixing page $topic/$repair{$key} for post $key, et. al.");
			($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $repair{$key});
			@message = split(/\n/, $message);
			$flag = 0;
			foreach $line (@message) {
				if ($line =~ m|<!-Post: (\d+)-!>|) {
					$flag = $1;
				} elsif ($line =~ m|<!-/Post:|) {
					$flag = 0;
				} elsif ($flag) {
					if ($line =~ m|<!-Name-!><!-/Name-!>|) {
						$bef = $`; $num = $flag; $aft = $';
						if ($LOG{$num} ne "" && !$looked_in_old_log) {
							if (-e "$admin_dir/backups/old-log.txt") {
								open (OLDLOG, "$admin_dir/backups/old-log.txt");
								while (<OLDLOG>) {
									@c = split(/;/, $_);
									next if $c[3] !~ m|^$topic/|;
									chomp $c[7]; chomp $c[8];
									$LOG{$c[0]}	= join("/", $c[1], &unescape($c[7]), $c[8]);
								}
							}
							$looked_in_old_log = 1;
						}
						if ($LOG{$num} ne "") {
							($info, $name, $mailto) = split(/\//, $LOG{$num}, 3); chomp $info; chomp $name;
							$name = $unrec if $name eq "";
							$line = join("", $bef, "<!-Name-!>$name<!-/Name-!>", $aft) if $name;
							$line = join("", $bef, "<!-Name-!>$unrec<!-/Name-!>", $aft) if !$name;
							if ($info !~ m|^PUBLIC:| && $info =~ m|(\w+):(\w+)|) {
								$pn = "$1-$2";
								$fn = "$admin_dir/profiles/$pn.txt";
								if ($usr{$pn} == -1) {
									next;
								} elsif ($usr{$pn} == 1 || -e "$admin_dir/profiles/$pn.txt") {
									if ($line =~ m|<!-Email-!>(.*)<!-/Email-!>| ) {
										$bef = $`; $aft = $';
										$line = join("", $bef, "<!-Email-!><A HREF=\"$script_url/board-profile.$cgi_extension?action=display_profile&profile=$pn\"><!-/Email-!>", $aft);
									}
									$usr{$pn} = 1;
								} else {
									$usr{$pn} = -1;
								}
							} elsif ($mailto ne "") {
								if ($line =~ m|<!-Email-!>(.*)<!-/Email-!>| ) {
									$bef = $`; $aft = $';
									$line = join("", $bef, "<!-Email-!><A HREF=\"mailto:$mailto\"><!-/Email-!>", $aft);
								}
							}
						} else {
							$line = join("", $bef, "<!-Name-!>$unrec<!-/Name-!>", $aft);
						}
						if ($line =~ m|<!-Email-!><!-/Email-!>|) {
							$bef = $`; $aft = $';
							$line = join("", $bef, "<!-Email-!><A HREF=\"javascript:alert('$L{NOT_AVAILABLE}');\" onMouseOver=\"window.status = '$L{NOT_AVAILABLE}'; return true;\"><!-/Email-!>", $aft);
						}
					} elsif ($line =~ m|<!-Name-!>(.*?)<!-/Name-!>|) {
						$bef = $`; $num = $flag; $aft = $'; $match = $1;
						if ($LOG{$num} ne "") {
							($info, $name, $mailto) = split(/\//, $LOG{$num}, 3); chomp $info; chomp $name;
							if ($name =~ m|\(([^\)]+)\)\s*$| && $match !~ m|\(([^\)]+)\)\s*$|) {
								$line = join("", $bef, "<!-Name-!>$name<!-/Name-!>", $aft);
							}
						}
					}
				}
			}
			$message = join("\n", @message);
			&set_page($topic, $repair{$key}, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src, "", "", "", 1);
			&log_error("src-board-subs-11", "repair_names", "Fixing page $topic/$repair{$key} COMPLETE");
		}
	}
	$flag = 0; $files = 0; $nexttopic = 0; $done = 0;
	foreach $line (@pairs) {
		$line =~ m|^(\d+)-(\d+)|;
		$files += $2;
		if ($1 == $topic_number) {
			$flag = 1;
		} elsif ($flag == 1) {
			$nexttopic = $1; $flag = 2;
		}
	}
	if ($hitend == 0) {
		$cpos = 0; $topic1 = $nexttopic;
	} else {
		$cpos += 1; $topic1 = $topic;
	}
	$pct = ($FORM{'done'} / $files);
	&extract("//$topic/$topic.$ext");
	$actionurl="$cgiurl?action=repair_names&username=$superuser";
	&show_gauge("Rebuild names", "Working -- &quot;$topic_name&quot;", $pct, "$actionurl&ctopic=$topic1&cpos=$cpos&ts=$topic_string&done=$FORM{'done'}&tempfile=$tempfile&added=$added") if $topic1 != 0;
	&seturl("$cgiurlm?cmd=data_recovery&username=$superuser");
}

#---SEPARATOR---#

sub data_recovery {
	&header;
	print "<HTML><HEAD><TITLE>Data Recovery</TITLE></HEAD>\n";
	print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
	print "onLoad=\"window.defaultStatus = 'Data Recovery'\">$fs\n";
	print "<FONT SIZE=3><CENTER><B>Data Recovery</B></CENTER></FONT>\n";
	print "<HR>\n";
	if (open (TOPFILE, "$message_dir/$board_topics_file")) {
		@top = <TOPFILE>;
		close (TOPFILE);
	} else {
		if (open (TOP, ">$message_dir/$board_topics_file")) {
			print TOP "\n";
			close (TOP);
		} else {
			print "The problem is that the script cannot read the $board_topics_file file,\n";
			print "probably because your specification of the HTML directory is not correct.\n";
			print "The reason the system cannot read the file is: <B>$!</B>.<P>";
			print "If this is something to the effect of &quot;No such file or directory&quot;\n";
			print "then you need to correct your setting of the HTML directory by editing your\n";
			print "discus.conf file.<P>\n";
			print "</TD></TR></TABLE></BODY></HTML>";
			exit(0);
		}
	}
	if (!grep(m|^<!-Top: (\d+)-!>|, @top)) {
		print "<B>TOPICS PAGE CORRUPTED</B><P>The data recovery utility has detected that the topics page has been\n";
		print "corrupted, probably due to editing the file with an HTML editor.\n";
		print "<P>This message could also occur if you have not ever created any topics\n";
		print "on your board.<P>\n";
		print "<FORM ACTION=$cgiurl METHOD=POST>\n";
		print "<TABLE BORDER=1 BGCOLOR=#ffffcc WIDTH=100%><TR><TD>$fs";
		print "You have two options for recovery:<P>\n";
		print "<INPUT TYPE=RADIO NAME=rectype VALUE=1 CHECKED><B>Salvage Page</B>\n";
		print "<UL>This will attempt to save as much information as possible from your\n";
		print "page (such as topic names, descriptions, last modified times, and so\n";
		print "on).  Depending on the extent of corruption, this may or may not find\n";
		print "any topics.  We recommend that you use this option first, and if it does\n";
		print "not work, use the regeneration option below.</UL><P>\n";
		print "<INPUT TYPE=RADIO NAME=rectype VALUE=2><B>Regenerate Page</B>\n";
		print "<UL>This will regenerate all of the topics on the topics page, but you\n";
		print "will lose all topic descriptions, the main message, and anything else\n";
		print "that ordinarily is displayed on the top page.  We recommend this option\n";
		print "only in those cases where &quot;Salvage Page&quot; fails.</UL><P>\n";
		print "<INPUT TYPE=SUBMIT VALUE='Run Data Recovery'>\n";
		print "</TD></TR></TABLE>\n";
		print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
		print "<INPUT TYPE=HIDDEN NAME=action VALUE=data_recovery_top>\n";
		print "</FORM>\n";
		print "</BODY></HTML>\n";
		print "<!--\n";
		foreach $line (@top) {
			$line =~ s/</[/g;
			$line =~ s/>/]/g;
			print $line;
		}
		print "-->\n";
		exit(0);
	}
	print "<B>TOPICS PAGE NOT CORRUPTED</B><P>The data recovery utility has concluded that your topics page is not corrupted, as it has";
	print " detected the presence of ";
	@top = grep(/\S/, @top); $x = scalar(@top);
	@ct = grep(/^<!-Top:/, @top); $xc = scalar(@ct);
	print "$xc topic";
	print "s" if $x != 1;
	print " on the topics page.  If you believe that the topics page is corrupt, or if you have received ";
	print "instructions from DiscusWare, LLC to regenerate your topics page, you can click the following ";
	print "button to do so.  <B>Please read the appropriate section in the <A HREF=\"$html_url/board-admin-instr-17.html#regenanyway\">Discus Administration Instructions</A>\n";
	print "before choosing this option.</B>\n";
	print "<FORM ACTION=$cgiurl METHOD=POST>\n";
	print "<INPUT TYPE=HIDDEN NAME=rectype VALUE=2>\n";
	print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
	print "<INPUT TYPE=HIDDEN NAME=action VALUE=data_recovery_top>\n";
	print "<INPUT TYPE=BUTTON VALUE=\"Regenerate Topics Page\" onClick=\"if (confirm('Are you sure you want to regenerate your topics page?  You will lose your title message and any customizations thereto!')) { document.forms[0].submit(); }\">\n";
	print "</FORM>\n";
	print "<HR>\n";
	if ($top[$x-1] =~ m|<!--/Topics--!>\s*$|) {
		&lock("data_recovery", "$message_dir/$board_topics_file");
		open (TOP, "$message_dir/$board_topics_file");
		@top = <TOP>;
		close (TOP);
		foreach $line (@top) {
			if ($line =~ m|<!--/Topics--!>\s*$|) {
				$line = "<!--/Topics-->\n";
			}
		}
		push (@top, "<!--Message-->\n<HR>\n<!--Source: -->\n<!--/Message-->\n");
		push (@top, "<!--Description Source:\n");
		@top2 = @top;
		foreach $line (@top2) {
			if ($line =~ m|<!-Top: (\d+)-!>|) {
				push (@top, "<!-Source: $1-!>\n");
			}
		}
		push (@top, "<!-End Description Source-!>-->\n</FONT>\n</BODY>\n</HTML>\n");
		open (TOP, ">$message_dir/$board_topics_file");
		print TOP @top;
		close (TOP);
		print "<FONT COLOR=#00aa00>Data Recovery noticed that your topics page was missing certain elements\n";
		print "that would make the Main Message and topic descriptions function improperly.\n";
		print "Data Recovery has fixed those elements on your topic page.  You may specify\n";
		print "a main message and topic descriptions using the Board Manager.</FONT><P>\n";
	}
	print "<B>FIX SUBTOPIC PAGES</B><P>The data recovery utility allows you to fix pages which have been corrupted\n";
	print "or inadvertantly deleted from your board.  In most cases, subtopic data can\n";
	print "be re-created by analyzing the other files in the topic directory.  However,\n";
	print "the text of any messages is permanently lost unless you restore from a backup.<P>\n";
	print "<FORM ACTION=$cgiurl METHOD=POST>\n";
	print "<TABLE BORDER=1 BGCOLOR=#ffffcc WIDTH=100%><TR><TD>$fs";
	print "Select the name of the topic that contains the corrupted page from the list\n";
	print "below.  If you want the Data Recovery procedure to automatically fix the\n";
	print "corrupted file for you, make sure &quot;Automically Fix Errors&quot; is checked.\n";
	print "<P>Topic name: <SELECT NAME=topic SIZE=1>\n";
	@topics = grep(/<!-Top:/, @top);
	foreach $line (@topics) {
		if ($line =~ m|<!-Top: (\d+)-!>.*?<a[^>]+>(.*?)</A>|i) {
			$topic_number = $1; $topic_name = &remove_html($2);
			print "<OPTION VALUE=$topic_number>$topic_name [$topic_number]\n";
		} elsif ($line =~ m|<!-Top: (\d+)-!>|) {
			$topic_number = $1;
			if (($head) = &get_page($topic_number, $topic_number)) {
				print "<OPTION VALUE=$topic_number>";
				if ($head =~ m|<!--Topic: $topic_number/(.*)-->|) {
					print "$1 [$topic_number]\n";
				} else {
					print "Unknown topic [$topic_number]\n";
				}
			}
		}
	}
	print "</SELECT>\n";
	print "<P><INPUT TYPE=CHECKBOX NAME=fixem VALUE=1 CHECKED> Automatically Fix Errors\n";
	print "<P><INPUT TYPE=SUBMIT VALUE=\"Run Data Recovery\">\n";
	print "</TD></TR></TABLE>\n";
	print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
	print "<INPUT TYPE=HIDDEN NAME=action VALUE=data_recovery>\n";
	print "</FORM>\n";
	print "<HR>\n";
	print "<B>MANUALLY REGENERATE PAGE</B><P>If a specific page is missing subtopics, the data recovery utility can add any missing\n";
	print "subtopics back to that page.  Misplaced subtopics from that page will also be removed.  <B>Please read the appropriate section in the\n";
	print "<A HREF=$html_url/board-admin-instr-17.html#specpage>Discus Administration Instructions</A>\n";
	print "before attempting this procedure.</B><P>\n";
	print "<FORM ACTION=$cgiurl METHOD=POST>\n";
	print "<TABLE BORDER=1 BGCOLOR=#ffffcc WIDTH=100%><TR><TD>$fs";
	print "Enter the topic number and page number of the page to regenerate:<P>\n";
	print "<UL><TABLE><TR><TD>$fs", "Topic Number:</FONT></TD><TD><INPUT TYPE=TEXT NAME=topic_r SIZE=5></TD></TR>\n";
	print "<TR><TD>$fs", "Page Number:</FONT></TD><TD><INPUT TYPE=TEXT NAME=page_r SIZE=5></TD></TR>\n";
	print "</TABLE></UL><P>\n";
	print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
	print "<INPUT TYPE=HIDDEN NAME=action VALUE=data_recovery_special>\n";
	print "<INPUT TYPE=SUBMIT VALUE=\"Fix Indicated Page\">\n";
	print "</FONT></TD></TR></TABLE><P></FORM>\n";
	print "<HR>\n";
	print "<B>OTHER RECOVERY OPTIONS</B><P>\n";
	print "These options are designed to clean up specific problems that can occur on a Discus board,\n";
	print "normally due to file corruption as a result of a system crash.  You should not perform these\n";
	print "options unless you are instructed to by DiscusWare support staff or documents or the instructions\n";
	print "provided by the administration program.<P>\n";
	print "<FORM ACTION=$cgiurl METHOD=POST NAME=oth>\n";
	print "<UL>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=1 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Rebuild Attachment Index<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=2 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Unlinked Attachment Cleanup<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=3 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "<I>UNDO</I> an Unlinked Attachment Cleanup<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=5 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Clean and repair posting logs<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=7 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Clean data structure (read instructions to see what this does!)<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=8 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Check and clean tree file<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=9 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Rebuild names on posts from logs<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=10 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Clean blank lines from password files<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=11 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Clean up any data files written in binary mode<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=12 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Search for and collect misplaced files<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=13 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Remove blank descriptions from topics page<BR>\n";
	print "<INPUT TYPE=RADIO NAME=opt VALUE=14 onClick=\"document.oth.CONFIRM.checked = false;\">\n";
	print "Fix &quot;Unrecorded Date&quot; messages on posts<BR>\n";
	print "</UL>\n";
	print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
	print "<INPUT TYPE=HIDDEN NAME=action VALUE=data_recovery_other>\n";
	print "<UL><TABLE WIDTH=440 BGCOLOR=#ff00000><TR><TD>$fs<FONT COLOR=#ffffff><INPUT TYPE=CHECKBOX NAME=CONFIRM VALUE=1><B>Confirm</B><P>To prevent accidental disaster, please\n";
	print "confirm that you indeed wish to perform the selected action by checking this box.</FONT></FONT></TD></TR></TABLE></UL>\n";
	print "<INPUT TYPE=SUBMIT VALUE=\"Perform Selected Procedure\">\n";
	print "</FONT></TD></TR></TABLE><P>\n";
	print "</FORM>\n";
	print "</BODY></HTML>\n";
	exit(0);
}

#---SEPARATOR---#

sub data_recovery_action {
	my ($topic, $autofix) = @_;
	$topic =~ s/\D//g;
	$page =~ s/\D//g;
	if (!-e "$message_dir/$topic" && !-e "$secdir/$topic") {
		&error_message("Topic Specification Error", "The requested topic does not have its own subdirectory.");
	}
	undef %head_content; undef %parent; undef %sub_content;
	if (-e "$message_dir/$topic") {
		opendir(MESSAGEDIR, "$message_dir/$topic");
	} else {
		opendir(MESSAGEDIR, "$secdir/$topic");
	}
	undef @filelist;
	while ($file = readdir(MESSAGEDIR)) {
		push (@filelist, $file);
	}
	@filelist = grep(/^(\d+)\.$ext$/, @filelist);
	undef @corrupt;
	foreach $file (@filelist) {
		$file =~ s/\D//g;
		($head, $color, $lm, $announce, $announce_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $file);
		$head{$file} = $head;
		$wf = $file if $head ne "";
		$color_works = $color if $head ne "";
		$sublist{$file} = $sublist;
		push (@corrupt, $file) if $head eq "";
	}
	foreach $file (keys(%head)) {
		$head = $head{$file};
		if ($head =~ m|<!--Parent: (\d+)-->|) {
			$p = $1;
			$parent{$file} = $p;
			if ($head{$p} eq "") {
				push (@corrupt, $p) if !grep(/^$p$/, @corrupt);
			} else {
				$wf = $file;
			}
		}
		$st = $sublist{$file}; @st = split(/\n/, $st); @st = grep(/<!-Top:/, @st);
		foreach $s (@st) {
			$s =~ m|<!-Top: (\d+)-!>|; $sl = $1;
			if ($head{$sl} eq "") {
				push (@corrupt, $sl) if !grep(/^$sl$/, @corrupt);
			}
			$parent{$sl} = $file;
		}
	}
	$fixed = 0; undef @fixedpage; $sls = "";
	if (scalar(@corrupt)) {
		foreach $f (@corrupt) {
			if ($f == $topic) {
				if ($wf != 0) {
					($head, $color, $lm, $announce, $announce_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($f, $wf);
					@h = split(/\n/, $head{$wf});
					@h = grep(!/^<!--Me:/, @h);
					@h = grep(!/^<!--Parent:/, @h);
					@h = grep(!/^<!--Param:/, @h);
					@h = grep(!/^<!--Level /, @h);
					($t) = grep(/<!--Topic:/, @h);
					$t =~ m|<!--Topic: (\d+)/(.*)-->|;
					push (@h, "<!--Me: $f/$2-->"); $fixedname{$f} = $2;
					push (@h, "<!--Param: Sublist-->");
					$fixed += 1; push (@fixed, $f);
				}
			} else {
				foreach $key (keys(%parent)) {
					$fixedit = 0;
					if ($parent{$key} == $f) {
						@h = split(/\n/, $head{$key});
						@h = grep(!/^<!--Me:/, @h);
						@h = grep(!/^<!--Parent:/, @h);
						@h = grep(!/^<!--Param:/, @h);
						$ml = 0;
						foreach $l (@h) {
							if ($l =~ m|<!--Level (\d+):|) {
								$ml = $1 if $1 > $ml;
							}
						}
						$mlm1 = $ml - 1;
						($t) = grep(/<!--Level $mlm1:/, @h);
						$t =~ m|<!--Level (\d+): (\d+)/(.*)-->|;
						push (@h, "<!--Me: $2/$3-->"); $fixedname{$f} = $3;
						@h = grep(!/^<!--Level $ml:/, @h);
						$mlm2 = $ml - 2;
						if (($t) = grep(/<!--Level $mlm1:/, @h)) {
							$t =~ m|<!--Level (\d+): (\d+)/|;
							push (@h, "<!--Parent: $2-->");
						} else {
							push (@h, "<!--Parent: $topic-->");
						}
						$fixed += 1; push (@fixed, $f); $fixedit = 1;
						push (@h, "<!--Param: Sublist-->");
						last;
					}
				}
				if ($fixedit == 0) {
					$mlp1 = $ml + 1;
					$p = $parent{$f};
					@h = split(/\n/, $head{$p});
					@h = grep(!/^<!--Me:/, @h);
					@h = grep(!/^<!--Parent:/, @h);
					@h = grep(!/^<!--Param:/, @h);
					$ml = 0;
					foreach $l (@h) {
						if ($l =~ m|<!--Level (\d+):|) {
							$ml = $1 if $1 > $ml;
						}
					}
					$mlp1 = $ml + 1;
					$st = $sublist{$p}; @st = split(/\n/, $st); @st = grep(/<!-Top:/, @st);
					$this_name = "(Untitled)";
					foreach $s (@st) {
						if ($s =~ m|^<!-Top: $f-!>|) {
							$s =~ m|<A[^>]+>(.*)</A>|i; $this_name = $1;
						}
					}
					push (@h, "<!--Level $mlp1: $f/$this_name-->");
					push (@h, "<!--Me: $f/$this_name-->");
					push (@h, "<!--Param: MessagesAdd-->");
					push (@h, "<!--Parent: $parent{$f}-->");
					$fixed += 1; push (@fixed, $f); $fixedit = 1;
					$fixedname{$f} = "$this_name";
				}
			}
			$h = join("\n", @h);
			foreach $key (keys(%parent)) {
				if ($parent{$key} == $f) {
					$head{$key} =~ m|<!--Me: (\d+)/(.*)-->|;
					$me_number = $1; $me_name = $2;
					$ts = &get_date_time('short');
					$sls .= "<!-Top: $me_number-!><LI><A HREF=\"$message_url/$topic/$me_number.$ext\"";
					$sls .= " onMouseOver=\"return setStatus('" . &JavaScript_prepare($me_name) . "')\">";
					$sls .= "$me_name</A> <FONT SIZE=\"-1\">$ts</FONT></LI><P>\n";
				}
			}
			&set_page($topic, $f, $h, $color_works, "", "", "", $sls, "", "", "", "", "", "", "", "", 1) if $autofix;
		}
	}
	&header;
	print "<HTML><HEAD><TITLE>Data Recovery Report</TITLE></HEAD>\n";
	print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
	print "onLoad=\"window.defaultStatus = 'Data Recovery Report'\">$fs\n";
	print "<FONT SIZE=3><CENTER><B>Data Recovery Report</B></CENTER></FONT>\n";
	print "<HR>\n";
	if (scalar(@corrupt) == 0) {
		print "The data recovery utility was not able to find any corrupted pages in\n";
		print "this topic.  If any page has become corrupted, you should either delete\n";
		print "that page or regenerate it by making a change to it using one of the\n";
		print "administrative tools.\n";
	} else {
		print "The data recovery utility detected <B>", scalar(@corrupt), "</B> corrupted page";
		print "s" if scalar(@corrupted) > 1;
		print " in this topic.\n";
		print "Of these errors, <B>$fixed</B> ";
		print "were" if ($fixed != 1 && $autofix);
		print "was" if ($fixed == 1 && $autofix);
		print "can be" if !$autofix;
		print " fixed.<P>\n";
		if ($fixed > 0 && $autofix) {
			print "Note that the subtopics on the pages that were fixed will likely be in\n";
			print "a different order than they were before the page was lost.  Thus, you\n";
			print "should access the Page Manager to reorder the subtopics if necessary.\n";
			print "<P>\n";
		}
		if ($autofix) {
			print "The following pages were fixed:<P><UL>\n";
			foreach $l (@fixed) {
				print "<LI><A HREF=\"$cgiurlm?action=page_editor&username=$superuser&HTTP_REFERER=//$topic/$l.$ext\" onMouseOver=\"window.status = 'Edit this subtopic'; return true\">";
				print "$fixedname{$l}</A>\n";
			}
			print "</UL>\n";
		} else {
			print "The following pages can be fixed:<P><UL>\n";
			foreach $l (@fixed) {
				print "<LI>$fixedname{$l}<P>\n";
			}
			print "</UL><P>\n";
			print "<FORM ACTION=\"$cgiurl\" METHOD=POST>\n";
			print "<INPUT NAME=action VALUE=data_recovery TYPE=HIDDEN>\n";
			print "<INPUT TYPE=HIDDEN NAME=username VALUE=$username>\n";
			print "<INPUT TYPE=HIDDEN NAME=topic VALUE=$topic>\n";
			print "<INPUT TYPE=HIDDEN NAME=fixem VALUE=1>\n";
			print "<INPUT TYPE=SUBMIT VALUE='Fix Errors'>\n";
			print "</FORM>\n";
		}
	}
	print "</BODY></HTML>\n";
	exit(0);
}

#---SEPARATOR---#
#REQ:change_board_colors
#REQ:board_manager

sub data_recovery_top {
	my ($option) = @_;
	if ($FORM{'rectype'} == 2) {
		opendir(DIR, "$message_dir");
		undef %data;
		while ($dir = readdir(DIR)) {
			$data{$1} = 1 if $dir =~ m|^(\d+)$|;
		}
		closedir(DIR);
		opendir(DIR, "$secdir");
		while ($dir = readdir(DIR)) {
			$data{$1} = 1 if $dir =~ m|^(\d+)$|;
		}
		closedir(DIR);
		open (FILE, ">$message_dir/$board_topics_file") || &error_message("Top File Write Error", "Could not write the topics page");
		if (open(TREE, "$admin_dir/tree.txt")) {
			@tree = <TREE>;
			close (TREE);
			foreach $line (@tree) {
				@c = split(/\t/, $line);
				if ($data{$c[1]} == 1) {
					print FILE "<!-Top: $c[1]-!>\n";
					delete $data{$c[1]};
				}
			}
		}
		foreach $key (sort {$a <=> $b} keys(%data)) {
			print FILE "<!-Top: $key-!>\n";
		}
		close (FILE);
	}
	&change_board_colors("*", "", "", "", "", "", "", "", 1, 1);
	&board_manager($FORM{"username"});
	exit(0);
}

#---SEPARATOR---#
#REQ:regenerate_subtopic_list

sub data_recovery_special {
	my ($topic, $page, $returner) = @_;
	$topic =~ s/\D//g; $page =~ s/\D//g;
	if ($topic eq "") {
		&error_message("Data Recovery Error", "Specified topic is invalid!  Consult administration instructions.");
	}
	if ($page eq "") {
		&error_message("Data Recovery Error", "Specified page is invalid!  Consult administration instructions.");
	}
	if (!-e "$secdir/$topic/$page.$ext" && !-e "$message_dir/$topic/$page.$ext") {
		return 0 if $returner;
		&error_message("Data Recovery Error", "File not found!  The topic number/page number combination you entered does not correspond to a file that was found on this board.  Consult administration instructions.");
	}
	$dir = "$secdir/$topic" if -e "$secdir/$topic";
	$dir = "$message_dir/$topic" if -e "$message_dir/$topic";
	open (PAGE, "$dir/$page.$ext");
	undef @subt_found; undef %F;
	while (<PAGE>) {
		if (m|^<!-Top: (\d+)-!>|) {
			push (@subt_found, $_);
			$F{$1} = 1;
		} elsif (m|^<!-URL: (\d+)-!>|) {
			push (@subt_found, $_);
		} elsif (m|^<!-EndSub-!>|) {
			last;
		}
	}
	close (PAGE);
	undef %G;
F:	foreach $found (keys(%F)) {
		($head) = &get_page($topic,$found);
		@head = grep((/^<!--Level (\d+):/ || /^<!--Topic:/), split(/\n/, $head));
		$mypnt = -1; $mylev = 0; $flag = 0;
L:		foreach $line (sort levelrank @head) {
			if ($line =~ m|<!--Level (\d+): $page/|) {
				$mypnt = $1;
				next L;
			} elsif ($line =~ m|<!--Topic: $page/|) {
				$mypnt = 0;
				next L;
			} elsif ($line =~ m|<!--Level (\d+): $found/|) {
				$mylev = $1;
				next L;
			} elsif ($mypnt != -1) {
				$flag = 1;
				$G{$found} = 1;
				delete $F{$found};
				next F;
			}
		}
	}
	undef @repair;
	opendir(DIR, $dir);
O:	while ($file = readdir(DIR)) {
		if ($file =~ m|^(\d+)\.$ext$|) {
			$fn = $1;
			next O if $F{$fn};
			next O if $page == $fn;
			open (FILE, "$dir/$file");
I:			while (<FILE>) {
				if (m|^<!--Parent: (\d+)-->|) {
					push (@repair, $fn) if $1 == $page;
					last I;
				} elsif (m|^</HEAD>i|) {
					last I;
				}
			}
			close (FILE);
		}
	}
	closedir(DIR);
	if (scalar(@repair) == 0 && scalar(keys(%G)) == 0) {
		return 0 if $returner == 1;
		&header;
		print "<HTML><HEAD><TITLE>Nothing to do</TITLE></HEAD>\n";
		print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>\n";
		print "$fs<FONT SIZE=4><CENTER>Data Recovery</CENTER></FONT><HR><P>\n";
		print "<B>Nothing to do:</B> All subtopics for topic <B>$topic</B>, page <B>$page</B>\n";
		print "were found to be contained on the subtopic list for that page.  This page did\n";
		print "not contain any misplaced subtopics.<P>\n";
		print "<A HREF=$cgiurlm?username=$superuser&cmd=data_recovery>Click here to continue</A><P>\n";
		print "</FONT></BODY></HTML>\n";
		exit(0);
	}
	if (scalar(@repair)) {
		foreach $x (@repair) {
			push (@subt_found, "<!-Top: $x-!>\n");
		}
		$TN = $topic;
	}
	&lock("data_recovery_special", "$message_dir/$topic/$page.$ext");
	my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
	@subt_found = sort tree_order @subt_found;
	if (scalar(keys(%G))) {
		foreach $line (@subt_found) {
			if ($line =~ m|<!-Top: (\d+)-!>|) {
				$line = "" if $G{$1};
			}
		}
	}
	$x_str = join("", @subt_found);
	$new_ststr = &regenerate_subtopic_list($topic, $page, $x_str);
	&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $new_ststr, $about, $about_src, $message, $message_src, $description_src, "", "", "", 1);
	&unlock("data_recovery_special", "$message_dir/$topic/$page.$ext");
	return 1 if $returner;
	&header;
	print "<HTML><HEAD><TITLE>Page repaired</TITLE></HEAD>\n";
	print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>\n";
	print "$fs<FONT SIZE=4><CENTER>Data Recovery</CENTER></FONT><HR><P>\n";
	print "<B>Missing subtopic(s) restored:</B> ", scalar(@repair), "<BR>\n";
	print "<B>Misplaced subtopic(s) removed:</B> ", scalar(keys(%G)), "<BR>\n";
	print "<P><A HREF=$script_url/show.$cgi_extension?$topic/$page TARGET=_blank>Click here</A> to\n";
	print "view the restored page (link will open in a new browser window)<P>\n";
	print "<A HREF=$cgiurlm?username=$superuser&cmd=data_recovery>Click here</A> if you need to run\n";
	print "Data Recovery on additional pages.<P>\n";
	print "When you have finished all restoration actions, you should go to the\n";
	print "<A HREF=$cgiurlm?username=$superuser&cmd=board_mgr#TEMPL>Board Manager</A> and click the\n";
	print "\"Reindex Board\" button in order to make your changes take hold.<P>\n";
	print "</FONT></BODY></HTML>\n";
	exit(0);
}

sub tree_order {
	$a =~ m|<!-Top: (\d+)-!>|; $anum = $1;
	$b =~ m|<!-Top: (\d+)-!>|; $bnum = $1;
	if (scalar(@TREE_TN) == 0) {
		if (open (TREE, "$admin_dir/msg_index/$TN-tree.txt")) {
			@TREE_TN = <TREE>;
			close (TREE);
		} else {
			@TREE_TN = ("no data");
		}
	}
	foreach $line (@TREE_TN) {
		@c = split(/\t/, $line);
		return 1 if $c[2] == $bnum;
		return -1 if $c[2] == $anum;
	}
	return 0;
}

sub levelrank {
	return -1 if $a =~ m|^<!--Topic|;
	return 1 if $b =~ m|^<!--Topic|;
	$a =~ m|<!--Level (\d+):|; $anum = $1;
	$b =~ m|<!--Level (\d+):|; $bnum = $1;
	return $a <=> $b;
}

#---SEPARATOR---#
#REQ:incremental
#REQ:show_gauge
#REQ:regenerate_subtopic_list
#REQ:page_fixer

sub misplaced_cleaner {
	my ($tempfile, $destdir) = @_;
	$factor = $GLOBAL_OPTIONS{'reindex_factor'} if $factor == 0;
	$factor = 15 if $factor == 0; $destdir =~ s/\D//g;
	if ($tempfile eq "") {
		($fileref, $counter, $tempfile) = &incremental("MPC", 1, "", "");
		$destdir = join("", time, $$); $destdir =~ s/\D//g;
		mkdir ("$admin_dir/backups/misplaced-$destdir", 0777);
		&show_gauge("Performing misplaced file cleanup", 'Estimating time', 0, "$cgiurl?username=$superuser&action=misplaced&counter=$counter&tempfile=$tempfile&destdir=$destdir");
	} else {
		($fileref) = &incremental($tempfile, 2, "", "");
		$destdir =~ s/\D//g;
		@TEMPFILER = @{$fileref};
		$starttime = time;
		$returned = "";
		$sec_due_to_factor = int($GLOBAL_OPTIONS{'reindex_factor'} / 30);
		$was_using_topic = 0;
RX:		while (time <= ($starttime + 2 + $sec_due_to_factor)) {
			$file = shift(@TEMPFILER);
			last if $file eq "";
			$FORM{'done'} += 1;
			$file =~ m|(\d+)/(\d+)\.$ext|; $page = $2; $topic = $1; $pageh = $page;
			next if $page == $topic;
			($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
			@head = split(/\n/, $head);
			$flagged = 0;
			($tline) = grep(/<!--Topic: (\d+)/, @head);
			if ($tline =~ m|<!--Topic: (\d+)/|) {
				$tb = $1;
			} else {
				&log_error("src-board-subs-14", "misplaced_cleaner", "File $topic/$page does not have valid topic header information.");
				$flagged = 1;
			}
			($pline) = grep(/<!--Parent: (\d+)/, @head);
			if ($pline =~ m|<!--Parent: (\d+)-->|) {
				$pn = $1;
			} else {
				$maxlev = 0;
				$pn = 0;
				foreach $line (@head) {
					if ($line =~ m|<!--Level (\d+): (\d+)|) {
						$pn = $2 if $1 > $maxlev && $2 != $page;
						$maxlev = $1 if $1 > $maxlev;
					}
				}
				if ($maxlev == 0 && $head =~ m|<!--Topic: (\d+)/|) {
					$pn = $1;
				}
				if ($pn != 0) {
					&log_error("src-board-subs-14", "misplaced_cleaner", "File $topic/$page does not know what its parent page is (I'm guessing it's $pn)");
					&lock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
					if ($head =~ m|<!--Parent: (\d+)-->|) {
						$head = join("", $`, "<!--Parent: $pn-->", $');
					} else {
						$head .= "\n<!--Parent: $pn-->\n";
					}
					&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
				} else {
					&log_error("src-board-subs-14", "misplaced_cleaner", "File $topic/$page has no available parent information; page must be corrupted; removing");
					&move_out($topic, $page);
					next RX;
				}
			}
			if ($tb != $topic) {
				if ($pn != 0) {
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
					@subl = split(/\n/, $sublist);
					if (grep(/^<!-Top: $page-!>/, @subl)) {
						&log_error("src-board-subs-14", "misplaced_cleaner", "[$topic/$page] WRONG TOPIC: $tb // Parent page found and claims child; fixing page header");
						&lock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
						$head =~ m|<!--Topic: (\d+)/(.*)-->|; $tnm = $1;
						($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
						$head =~ s%<!--Topic: (\d+)/(.*)-->%<!--Topic: $topic/$tnm-->%g;
						&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
						&unlock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
						next RX;
					} elsif ($head ne "") {
						&log_error("src-board-subs-14", "misplaced_cleaner", "[$topic/$page] WRONG TOPIC: $tb // Parent page found but does not claim child; fixing parent page & child page");
						&lock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
						($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
						@sublist = split(/\n/, $sublist);
						push (@sublist, "<!-Top: $page-!>");
						@sublist = grep(/\S/, @sublist);
						$sublist = join("\n", @sublist);
						$sublist = &regenerate_subtopic_list($topic, $pn, $sublist);
						if ($head =~ m|<!--Param: (.*)-->|) {
							$af = $'; $bf = $`; $pr = $1;
							if ($1 !~ m|Sublist|) {
								$head = join("", $bf, "<!--Param: Sublist$pr-->", $af);
							}
						}
						&set_page($topic, $pn, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
						&unlock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
						&lock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
						$head =~ m|<!--Topic: (\d+)/(.*)-->|; $tnm = $1;
						($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
						$head =~ s%<!--Topic: (\d+)/(.*)-->%<!--Topic: $topic/$tnm-->%g;
						&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
						&unlock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
						next RX;
					} else {
						&log_error("src-board-subs-14", "misplaced_cleaner", "[$topic/$page] WRONG TOPIC: $tb // Parent page does not exist or is corrupt; relocating page out of directory");
						&move_out($topic, $page);
						next RX;
					}
				} else {
					&log_error("src-board-subs-14", "misplaced_cleaner", "[$topic/$page] WRONG TOPIC: $tb // Does not claim parent page; relocating page");
					&move_out($topic, $page);
					next RX;
				}
			}
			($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
			if ($head eq "") {
				&log_error("src-board-subs-14", "misplaced_cleaner", "File $topic/$page belongs to a bad parent ($pn)");
				$result = &page_fixer($topic, $pn);
				if ($result == 0) {
					&log_error("src-board-subs-14", "misplaced_cleaner", "Parent page $topic/$pn could not be repaired.  Moving $topic/$page out.");
					&move_out($topic, $page);
					next RX;
				} else {
					&log_error("src-board-subs-14", "misplaced_cleaner", "Parent page $topic/$pn repaired!");
					&lock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
					@sublist = split(/\n/, $sublist);
					next RX if grep(/^<!-Top: $page-!>/, @sublist);
					push (@sublist, "<!-Top: $page-!>");
					@sublist = grep(/\S/, @sublist);
					$sublist = join("\n", @sublist);
					$sublist = &regenerate_subtopic_list($topic, $pn, $sublist);
					&set_page($topic, $pn, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
					&unlock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
					&lock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
					$head =~ m|<!--Topic: (\d+)/(.*)-->|; $tnm = $1;
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
					$head =~ s%<!--Topic: (\d+)/(.*)-->%<!--Topic: $topic/$tnm-->%g;
					&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
					&unlock("misplaced_cleaner", "$message_dir/$topic/$page.$ext");
					next RX;
				}
			} else {
				if ($sublist =~ m|<!-Top: $pageh-!>|) {
					next RX;
				} else {
					&log_error("src-board-subs-14", "misplaced_cleaner", "Parent file $topic/$pn does not claim child file $page!  Repairing...");
					&lock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
					@sublist = split(/\n/, $sublist);
					push (@sublist, "<!-Top: $page-!>");
					@sublist = grep(/\S/, @sublist);
					$sublist = join("\n", @sublist);
					$sublist = &regenerate_subtopic_list($topic, $pn, $sublist);
					&set_page($topic, $pn, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
					&unlock("misplaced_cleaner", "$message_dir/$topic/$pn.$ext");
					next RX;
				}
			}
		}
		$fileref = \@TEMPFILER;
		($status, $foo, $tempfiler) = &incremental($tempfile, 3, $fileref);
		if ($status) {
			if ($FORM{'counter'} > 0) {
				$pct = $FORM{'done'} / $FORM{'counter'};
			} else {
				$pct = 0;
			}
			&show_gauge("Performing misplaced file cleanup", "Cleaning misplaced files - $FORM{'done'} of $FORM{'counter'} processed", $pct, "$cgiurl?action=misplaced&tempfile=$tempfile&destdir=$destdir&username=$superuser&done=$FORM{'done'}&counter=$FORM{'counter'}");
		}
		&header;
		print "<HTML><HEAD><TITLE>Misplaced File Cleanup</TITLE></HEAD>\n";
		print "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#0000ff>$fs";
		print "<CENTER><FONT SIZE=3><B>Misplaced File Cleanup Finished</B></FONT></CENTER>\n";
		print "<HR>\n";

		print "<P>Please reindex your board by going to\n";
		print "<A HREF=$cgiurlm?username=$superuser&cmd=board_mgr#TEMPL>Board Manager</A>\n";
		print "and clicking the &quot;Reindex Board&quot; button,\n";
		print "choosing to reindex all topics.\n";
		print "</FONT></BODY></HTML>\n";
		exit(0);
	}
}

sub move_out {
	my ($topic, $page) = @_;
	if (-e "$message_dir/$topic/$page.$ext") {
		open (FILE, "$message_dir/$topic/$page.$ext");
		@file = <FILE>;
		close (FILE);
	} elsif (-e "$secdir/$topic/$page.$ext") {
		open (FILE, "$secdir/$topic/$page.$ext");
		@file = <FILE>;
		close (FILE);
	}
	open (DEST, ">$admin_dir/backups/misplaced-$destdir/$page.$ext");
	print DEST @file;
	close (DEST);
	open (FILE, "$admin_dir/msg_index/$topic/$page-src.txt");
	@file = <FILE>;
	close (FILE);
	open (DEST, ">$admin_dir/backups/misplaced-$destdir/$page-src.txt");
	print DEST @file;
	close (DEST);
	unlink("$admin_dir/msg_index/$topic/$page-src.txt");
	if (-e "$message_dir/$topic/$page.$ext") {
		unlink("$message_dir/$topic/$page.$ext");
	} elsif (-e "$secdir/$topic/$page.$ext") {
		unlink("$secdir/$topic/$page.$ext");
	}
}

#---SEPARATOR---#

sub take_to_maintenance {
	my ($function, $script, $fields, $flag) = @_;
	if ($function eq "1" || $function eq "0") {
		&lock("$admin_dir/options.txt");
		open (FILE, "$admin_dir/options.txt");
		@file = <FILE>;
		close (FILE);
		$flag = 0;
		open (FILE, ">$admin_dir/options.txt");
		foreach $line (@file) {
			if ($line =~ m|^maintenance=|) {
				print FILE "maintenance=$function\n"; $flag = 1;
			} else {
				print FILE $line;
			}
		}
		print FILE "maintenance=$function\n" if $flag == 0;
		close (FILE);
		&unlock("$admin_dir/options.txt");
		return -1;
	}
	&header;
	print "<HTML><HEAD><TITLE>Maintenance Mode Inquiry</TITLE></HEAD>\n";
	print "<BODY BGCOLOR=#ffffff TEXT=#000000>$fs";
	print "<CENTER><FONT SIZE=3><B>Maintenance Mode Inquiry</B></FONT></CENTER><HR>\n";
	print "It is recommended that you place your board in Maintenance Mode when running the function\n";
	print "&quot;$function.&quot;  Maintenance mode insures that user activity on your board will not\n";
	print "interfere with this operation.  Do you want to take your board do Maintenance Mode as\n";
	print "recommended?  If you are not sure, answer Yes!<P>\n";
	print "<FORM ACTION=$script METHOD=POST>\n";
	@fields = split(/,/, $fields);
	foreach $x (@fields) {
		($key, $val) = split(/=/, $x);
		print "<INPUT TYPE=HIDDEN NAME=$key VALUE=\"$val\">\n";
	}
	foreach $key (keys(%FORM)) {
		print "<INPUT TYPE=HIDDEN NAME=$key VALUE=\"$FORM{$key}\">\n" if $key ne "submit";
	}
	print "<CENTER><TABLE WIDTH=300 BORDER=1><TR><TD ALIGN=CENTER><INPUT TYPE=SUBMIT NAME=maintainflag VALUE=\"Yes\">\n";
	print "<INPUT TYPE=SUBMIT NAME=none VALUE=\"No\"></TD></TR></TABLE></CENTER>\n";
	print "</FORM><P>\n";
	print "HINT: You can read more about Maintenance Mode in the administration instructions documentation\n";
	print "for the &quot;Options Manager&quot; page.</FONT></BODY></HTML>\n";
	exit(0);
}

#---SEPARATOR---#

sub page_fixer {
	my ($topic, $page) = @_;
	my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
	my ($new_head, @file, $line, $navbar, $flag, @junk, $junkline, $url, $name);
	$new_head = "";
	if (-e "$message_dir/$topic") {
		open (FILE, "$message_dir/$topic/$page.$ext");
	} else {
		open (FILE, "$secdir/$topic/$page.$ext");
	}
	@file = <FILE>;
	close ($FILE);
	foreach $line (@file) {
		if ($line =~ m|<!--Navbar-->|) {
			$flag = 1;
		} elsif ($line =~ m|<!--/Navbar-->|) {
			$flag = 0;
		} elsif ($flag == 1) {
			$navbar .= $line;
		}
	}
	@file = split(/\n/, $navbar);
	$l_ctr = 0; $p_number = 0;
	foreach $line (@file) {
		next if $line =~ m|^<B>\s*$|;
		next if $line =~ m|^</B>\s*$|;
		next if $line !~ m|\S|;
		if ($line =~ m|<A HREF=|) {
			@junk = split(/<\/A>: <A HREF/, $line);
			foreach $junkline (@junk) {
				$junkline =~ s/<\/A>:\s*$//;
				$junkline =~ m|="([^"]+)"([^>]*)>(.*)|;
				($url, $name) = ($1, $3);
				next if $url =~ m|$board_topics_file|;
				$url =~ m|/(\d+)/(\d+).$ext|;
				($topic, $mpage) = ($1, $2);
				if ($topic == $mpage) {
					$newhead .= "<!--Topic: $topic/$name-->\n";
				} else {
					$l_ctr += 1;
					$newhead .= "<!--Level $l_ctr: $mpage/$name-->\n";
					$p_number = $mpage if $mpage ne $page;
				}
			}
		} else {
			chomp $line;
			$l_ctr += 1;
			$newhead .= "<!--Level $l_ctr: $page/$line-->\n" if $topic != $page;
			$newhead .= "<!--Me: $page/$line-->\n";
		}
	}
	if ($newhead ne "") {
		$newhead .= "<!--Param: ";
		$newhead .= "Announce" if $ann ne "";
		$newhead .= "SublistCreate" if $sublist ne "";
		$newhead .= "About" if $about ne "";
		$newhead .= "MessagesAdd" if $message ne "";
		$newhead .= "-->\n";
		&extract("$message_dir/$topic/$topic.$ext") if (-e "$message_dir/$topic");
		&extract("$secdir/$topic/$topic.$ext") if (-e "$secdir/$topic");
		$newhead .= "<!--Owner: $owner-->\n";
		$newhead .= "<!--Parent: $p_number-->\n";
		$newhead .= "<!--Properties: -->\n";
	}
	if ($newhead ne "") {
		&set_page($topic, $page, $newhead, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src, "", "", "", 1);
		return 1;
	} else {
		return 0;
	}
}

#---SEPARATOR---#
#REQ:misplaced_cleaner
#REQ:change_board_colors

sub data_recovery_other {
	my ($action) = @_;
	if ($action == 1) {
		$time = time;
		open (ATTACH, "$admin_dir/msg_index/attach-mgr.txt");
		open (NEW, ">$admin_dir/backups/attach-mgr-$time.txt");
		while (<ATTACH>) {
			print NEW;
		}
		close (NEW);
		close (ATTACH);
		open (ATTACH, ">$admin_dir/msg_index/attach-mgr.txt");
		close (ATTACH);
		&seturl("$cgiurl?username=$superuser&action=rebuild_attach");
		exit(0);
	}
	if ($action == 2) {
		$backup_dir = "$admin_dir/backups/attachclean-";
		$backup_dir .= time;
		undef %MADE;
		$made = 0; $count = 0;
		open (ATTACH, "$admin_dir/msg_index/attach-mgr.txt") || &error_message("Attachment Cleanup", "Could not open attachment manager file (msg_index/attach-mgr.txt).  Please run the 'Rebuild attachment index' option to generate this file!");
		undef %ATT;
		while (<ATTACH>) {
			($msg, $file) = split(/\s+/, $_);
			$ATT{$file} = 1;
		}
		close (ATTACH);
		open (TOPICS, "$message_dir/$board_topics_file") || &error_message("Attachment Cleanup", "Could not open main topics file ($board_topics_file)!");
		undef @topics;
		while (<TOPICS>) {
			push (@topics, $1) if m|<!-Top: (\d+)-!>|;
		}
		close (TOPICS);
		if (scalar(@topics) == 0) {
			&error_message("Attachment Cleanup", "Nothing to do: There are not any topics on your board!", 0, 1);
		}
		undef @results;
O:		foreach $file (@topics) {
			$dirname = "";
			$dirname = "$message_dir/$file" if -e "$message_dir/$file";
			$dirname = "$secdir/$file" if -e "$secdir/$file";
			next O if $dirname eq "";
			opendir(DIR, $dirname);
I:			while ($filename = readdir(DIR)) {
				next I if $filename =~ m|^(\d+)\.$ext$|;
				next I if $filename =~ m|^\.+$|;
				next I if $filename =~ m|\.conf$|;
				next I if $filename eq "passwd.txt";
				next I if $ATT{$filename} == 1;
				next I if $filename =~ m|\.skin$|;
				if ($made == 0) {
					mkdir("$backup_dir", oct($perms0777)) || &error_message("Attachment Cleanup", "Could not make backup directory ($backup_dir)!");
					$made = 1;
				}
				if ($MADE{$file} == 0) {
					mkdir("$backup_dir/$file", oct($perms0777)) || &error_message("Attachment Cleanup", "Could not make backup subdirectory ($backup_dir/$file)!");
					$MADE{$file} = 1;
				}
				open (SRC, "$dirname/$filename");
				binmode(SRC);
				open (DEST, ">$backup_dir/$file/$filename");
				binmode(DEST);
				while (<SRC>) {
					print DEST;
				}
				close (DEST);
				close (SRC);
				unlink("$dirname/$filename");
				push (@results, "$file/$filename");
				$count += 1;
			}
			closedir(DIR);
		}
		&header;
		print "<HTML><HEAD><TITLE>Attachment Cleanup</TITLE></HEAD>\n";
		print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
		print "onLoad=\"window.defaultStatus = 'Attachment Cleanup'\">$fs\n";
		print "<FONT SIZE=3><CENTER><B>Attachment Cleanup</B></CENTER></FONT>\n";
		print "<HR>\n";
		print "Attachment cleanup located <B>$count</B> stray attachment";
		print "s" if $count != 1;
		print ".\n";
		if ($count > 0) {
			print "<P>Stray attachments were moved into $backup_dir for backup purposes.\n";
			print "When you have confirmed that no needed attachments were removed, you can\n";
			print "remove this directory and its subdirectories.<P>\n";
			print "<UL>\n";
			foreach $line (@results) {
				print "<LI>$line\n";
			}
			print "</UL>\n";
		}
	} elsif ($action == 3) {
		&header;
		print "<HTML><HEAD><TITLE>Undo an Attachment Cleanup</TITLE></HEAD>\n";
		print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
		print "onLoad=\"window.defaultStatus = 'Undo an Attachment Cleanup'\">$fs\n";
		print "<FONT SIZE=3><CENTER><B>Undo an Attachment Cleanup</B></CENTER></FONT>\n";
		print "<HR>\n";
		print "<FORM ACTION=$cgiurl METHOD=POST>\n";
		print "<INPUT TYPE=hidden NAME=username VALUE=$superuser>\n";
		print "<INPUT TYPE=hidden NAME=action VALUE=data_recovery_other>\n";
		print "<INPUT TYPE=hidden NAME=opt VALUE=4>\n";
		print "<INPUT TYPE=hidden NAME=CONFIRM VALUE=1>\n";
		print "The following is a list of your attachment cleanups, along with the date and time that\n";
		print "you performed the cleanup.  Please select the attachment cleanup you wish to restore.\n";
		print "<P><TABLE BORDER=1><TR><TD>$fs", "Choose</FONT></TD><TD>$fs", "File Name</FONT></TD><TD>$fs", "Date/Time</FONT></TD></TR>\n";
		opendir(DIR, "$admin_dir/backups");
		while ($dir = readdir(DIR)) {
			if ($dir =~ m|^attachclean-(\d+)|) {
				$num = $1;
				print "<TR><TD ALIGN=CENTER><INPUT TYPE=RADIO NAME=sel VALUE=$num></TD><TD>$fs";
				print "attachclean-$num</FONT></TD><TD>";
				$dt = &get_date_time("long", $num);
				print $fs, "$dt</FONT></TD></TR>\n";
			}
		}
		closedir(DIR);
		print "</TABLE><P><INPUT TYPE=SUBMIT VALUE=\"Undo attachment cleanup\"></FORM>\n";
	} elsif ($action == 4) {
		&header;
		print "<HTML><HEAD><TITLE>Undo an Attachment Cleanup - Result</TITLE></HEAD>\n";
		print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
		print "onLoad=\"window.defaultStatus = 'Undo an Attachment Cleanup - Result'\">$fs\n";
		print "<FONT SIZE=3><CENTER><B>Undo an Attachment Cleanup - Result</B></CENTER></FONT>\n";
		print "<HR>\n";
		$number = $FORM{'sel'}; $number =~ s/\D//g;
		if (!-e "$admin_dir/backups/attachclean-$number") {
			&error_message("Undo Attachment Cleanup", "Requested directory (attachclean-$number) does not exist!", 0, 1);
		}
		opendir(DIR, "$admin_dir/backups/attachclean-$number");
		while ($dirnum = readdir(DIR)) {
			next if $dirnum !~ m|^\d+$|;
			if (!-e "$message_dir/$dirnum" && !-e "$admin_dir/$dirnum") {
				print "<B><FONT COLOR=#ff0000>Error restoring attachments</FONT>:</B> Source directory ($dirnum) has no destination<BR>\n";
			} else {
				print "<B><FONT COLOR=#00aa00>Restoring attachments</FONT>: Source directory ($dirnum)</B><BR><UL>\n";
				opendir(DIR2, "$admin_dir/backups/attachclean-$number/$dirnum");
				$destdir = "$message_dir/$dirnum" if -e "$message_dir/$dirnum";
				$destdir = "$secdir/$dirnum" if -e "$secdir/$dirnum";
				while ($file = readdir(DIR2)) {
					if ($file !~ m|^\.+$|) {
						$code1 = open (SRC, "$admin_dir/backups/attachclean-$number/$dirnum/$file");
						binmode(SRC);
						$code2 = open (DEST, ">$destdir/$file");
						binmode(DEST);
						while (<SRC>) {
							print DEST;
						}
						close (DEST);
						close (SRC);
						print "<LI>Restored $file\n" if ($code1 && $code2);
						print "<LI>Could not read $file\n" if !$code1;
						print "<LI>Could not write $file\n" if !$code2;
						unlink("$admin_dir/backups/attachclean-$number/$dirnum/$file") if ($code1 && $code2);
					}
				}
				rmdir("$admin_dir/backups/attachclean-$number/$dirnum");
				print "</UL>\n";
				closedir(DIR2);
			}
		}
		closedir(DIR);
		rmdir("$admin_dir/backups/attachclean-$number");
		print "<P>\n";
	} elsif ($action == 5) {
		($tempfile, $ts, $topic1) = &build_topic_list;
		&seturl("$cgiurl?username=$superuser&action=clean_logs&tempfile=$tempfile&ts=$ts&ctopic=$topic1");
		exit(0);
	} elsif ($action == 7) {
		&seturl("$cgiurl?username=$superuser&action=clean_board");
		exit(0);
	} elsif ($action == 8) {
		($tempfile, $ts, $topic1) = &build_topic_list;
		&seturl("$cgiurl?username=$superuser&action=clean_tree&tempfile=$tempfile&ts=$ts&ctopic=$topic1");
		exit(0);
	} elsif ($action == 9) {
		($tempfile, $ts, $topic1) = &build_topic_list;
		&seturl("$cgiurl?username=$superuser&action=repair_names&tempfile=$tempfile&ts=$ts&ctopic=$topic1");
		exit(0);
	} elsif ($action == 10) {
		undef @passwd; $uclean = 0; $pclean = 0;
		&lock("data_recovery_other", "$admin_dir/passwd.txt");
		open (PASSWD, "$admin_dir/passwd.txt");
		while (<PASSWD>) {
			$pclean += 1;
			next if m|^::|;
			push (@passwd, $_) if m|\S|;
		}
		close (PASSWD);
		$pwrite = scalar(@passwd);
		$passwd = \@passwd;
		&safe_write("$admin_dir/passwd.txt", $passwd) || &error_message("File write failure", "Could not write passwd.txt.  Call to safe_write failed.");
		undef @passwd;
		&unlock("data_recovery_other", "$admin_dir/passwd.txt");
		&lock("data_recovery_other", "$admin_dir/users.txt");
		open (PASSWD, "$admin_dir/users.txt");
		while (<PASSWD>) {
			$uclean += 1;
			next if m|^::|;
			push (@passwd, $_) if m|\S|;
		}
		close (PASSWD);
		$passwd = \@passwd;
		$uwrite = scalar(@passwd);
		&safe_write("$admin_dir/users.txt", $passwd) || &error_message("File write failure", "Could not write users.txt.  Call to safe_write failed.");
		undef @passwd;
		&unlock("data_recovery_other", "$admin_dir/users.txt");
		&header;
		print "<HTML><HEAD><TITLE>Data Recovery Results</TITLE></HEAD>\n";
		print "<BODY BGCOLOR=#ffffff TEXT=#000000 VLINK=#0000ff LINK=#0000ff>$fs\n";
		print "<FONT SIZE=3><CENTER><B>Clean Password Files</B></CENTER></FONT><HR>\n";
		print "<P>Password files were successfully cleaned.<P>\n";
		print ($pclean-$pwrite); print " blank line(s) removed from passwd.txt.<BR>\n";
		print ($uclean-$uwrite); print " blank line(s) removed from users.txt.<BR>\n";
	} elsif ($action == 11) {
		$repaired = 0; $failed = 0; $processed = 0;
		opendir(DIR, "$admin_dir");
		while ($dir = readdir(DIR)) {
			next if $dir !~ m|\.txt$|;
			&processor("$admin_dir/$dir");
		}
		closedir(DIR);
		opendir(DIR, "$admin_dir/profiles");
		while ($dir = readdir(DIR)) {
			next if $dir !~ m|\.txt$|;
			&processor("$admin_dir/profiles/$dir");
		}
		closedir(DIR);
		opendir(DIR, "$admin_dir/msg_index");
		while ($dir = readdir(DIR)) {
			next if $dir !~ m|\.txt$|;
			&processor("$admin_dir/msg_index/$dir");
		}
		closedir(DIR);
		&header;
		print "<HTML><HEAD><TITLE>Data Recovery Results</TITLE></HEAD>\n";
		print "<BODY BGCOLOR=#ffffff TEXT=#000000 VLINK=#0000ff LINK=#0000ff>$fs\n";
		print "<FONT SIZE=3><CENTER><B>Fix Binary Mode Files</B></CENTER></FONT><HR>\n";
		print "<P>Data files were cleaned.<P>\n";
		print "$processed file(s) processed.<BR>\n";
		print "$repaired file(s) repaired.<BR>\n";
		print "$failed file(s) could not be repaired (see error log for details).<BR>\n";
	} elsif ($action == 12) {
		&misplaced_cleaner("", "");
		exit(0);
	} elsif ($action == 13) {
		&change_board_colors("*", "", "", "", "", "", "", "", 1, "", 1);
		&header;
		print "<HTML><HEAD><TITLE>Data Recovery Results</TITLE></HEAD>\n";
		print "<BODY BGCOLOR=#ffffff TEXT=#000000 VLINK=#0000ff LINK=#0000ff>$fs\n";
		print "<FONT SIZE=3><CENTER><B>Topics page fixed</B></CENTER></FONT><HR>\n";
		print "<P>Blank or space-only descriptions were removed.<P>\n";
	} elsif ($action == 14) {
		&header;
		print "<HTML><HEAD><TITLE>Fix Dates on Posts</TITLE></HEAD>\n";
		print '<BODY BGCOLOR="ffffff" TEXT="000000" LINK="0000FF" VLINK="0000FF" ';
		print "onLoad=\"window.defaultStatus = 'Fix Dates on Posts'\">$fs\n";
		print "<FONT SIZE=3><CENTER><B>Fix Dates on Posts</B></CENTER></FONT>\n";
		print "<HR>\n";
		print "<B><A HREF=$cgiurlm?username=$superuser&cmd=data_recovery>Data Recovery</A>: Fix Dates on Posts</B><HR><P>\n";
		print "If in a previous upgrade from version 3.01 or before to version 3.10 you had an incomplete log file,\n";
		print "the dates may not have been properly imported.  Now these may show up as &quot;unrecorded date.&quot;\n";
		print "If you saved a backup as advised before upgrading, you can recover this date information.  Otherwise,\n";
		print "you can enter a date and all messages currently noted as &quot;Unrecorded date&quot; will be displayed\n";
		print "as the date/time you enter.\n";
		print "<P><FORM ACTION=\"$cgiurl\" METHOD=POST>\n";
		print "<INPUT TYPE=HIDDEN NAME=username VALUE=$superuser>\n";
		print "<INPUT TYPE=HIDDEN NAME=action VALUE=datefixer>\n";
		print "<TABLE BORDER=1><TR><TD>$fs", "Choose</FONT></TD><TD>$fs", "Recovery Option</FONT></TD></TR>\n";
		print "<TR><TD VALIGN=CENTER ALIGN=CENTER>";
		if (-r "$admin_dir/backups/datefix.tar") {
			print "<INPUT TYPE=RADIO NAME=method VALUE=1>";
		} else {
			print "&nbsp;";
		}
		print "</TD>\n";
		print "<TD VALIGN=TOP>$fs", "Use <B>datefix.tar</B> in &quot;backups&quot; directory.<BR>\n";
		if (!-r "$admin_dir/backups/datefix.tar") {
			print "<FONT SIZE=1 COLOR=#ff0000>This option is not available, as a file called\n";
			print "&quot;datefix.tar&quot; is not found in your &quot;backups&quot; directory.</FONT>\n";
		}
		print "</FONT></TD></TR>\n";
		print "<TR><TD VALIGN=CENTER ALIGN=CENTER>";
		if (-r "$admin_dir/backups/datefix") {
			print "<INPUT TYPE=RADIO NAME=method VALUE=2>";
		} else {
			print "&nbsp;";
		}
		print "<TD VALIGN=TOP>$fs", "Use files in <B>backups/datefix</B> directory.<BR>\n";
		if (!-r "$admin_dir/backups/datefix") {
			print "<FONT SIZE=1 COLOR=#ff0000>This option is not available, as a directory called\n";
			print "&quot;datefix&quot; is not found in your &quot;backups&quot; directory.</FONT>\n";
		}
		print "</FONT></TD></TR>\n";
		print "<TR><TD ALIGN=CENTER VALIGN=CENTER>";
		if (-r "$admin_dir/backups/old-log.txt") {
			print "<INPUT TYPE=RADIO NAME=method VALUE=7>";
		} else {
			print "&nbsp;";
		}
		print "</TD><TD VALIGN=TOP>$fs", "Use <B>old-log.txt</B> file in &quot;backups&quot; directory.</FONT>\n";
		if (!-r "$admin_dir/backups/old-log.txt") {
			print "<FONT SIZE=1 COLOR=#ff0000>This option is not available, as a file called\n";
			print "&quot;old-log.txt&quot; is not found in your &quot;backups&quot; directory.</FONT>\n";
		}
		print "</FONT></TD></TR>\n";
		print "<TR><TD ALIGN=CENTER VALIGN=CENTER>";
		print "<INPUT TYPE=RADIO NAME=method VALUE=3>";
		print "</TD><TD>$fs", "Reset all unrecorded times to this time:<P></FONT>\n";
		print "<SELECT NAME=month>\n";
		for ($i = 0; $i <= 11; $i++) {
			print "<OPTION VALUE=$i>$MONTH[$i]\n";
		}
		print "</SELECT>\n";
		print " <INPUT TYPE=TEXT NAME=day VALUE=1 SIZE=2>\n";
		print "<SELECT NAME=year>\n";
		$myyear = (localtime(time))[5] + 1900;
		for ($i = 1997; $i <= $myyear; $i++) {
			print "<OPTION VALUE=$i>$i\n";
		}
		print "</SELECT>\n";
		print "<INPUT TYPE=TEXT NAME=hour VALUE=12 SIZE=2>:<INPUT TYPE=TEXT NAME=min VALUE=00 SIZE=2>\n";
		print "</TD></TR></TABLE><P>\n";

		print "<INPUT TYPE=SUBMIT VALUE=\"Fix Dates\"></FORM>\n";
		print "</FONT></BODY></HTML>\n";
		exit(0);
	} else {
		&error_message("Error", "You should never see this message.  Invalid parameter option ($FORM{'opt'})!", 0, 1);
	}
	print "<P><A HREF=\"$cgiurlm?username=$superuser&cmd=data_recovery\">Return to Data Recovery</A><P>\n";
	print "</BODY></HTML>\n";
}

sub processor {
	my ($file) = @_;
	my (@file, $line);
	&lock("$file");
	open (FILE, "$file");
	@file = <FILE>;
	close (FILE);
	if (grep(/\r/, @file)) {
		foreach $line (@file) {
			$line =~ s/\r//g;
		}
		if (open (FILE, ">$file")) {
			print FILE @file;
			close (FILE);
			&unlock($file);
			$processed += 1; $repaired += 1;
		} else {
			&unlock($file);
			$processed += 1; $fixed += 1;
			&log_error("src-board-subs-12", "processor", "Could not write $file [$!]");
		}
	} else {
		$processed += 1;
	}
}

sub build_topic_list {
	$procnum = $$; $procnum =~ s/\D//g;
	$tempfile = join("", time, $procnum);
	open (FILE, ">$admin_dir/msg_index/$tempfile.TMP") || &error_message("Recovery Error", "Could not create temporary file ($admin_dir/msg_index/$procnum.TMP)!");
	close (FILE);
	open (TOPICS, "$message_dir/$board_topics_file"); @top = <TOPICS>; close (TOPICS);
	@top = grep(/^<!-Top: (\d+)-!>/, @top);
	if (scalar(@top) == 0) {
		&seturl("$cgiurlm?cmd=data_recovery&username=$superuser");
	}
	undef @topic_line;
	$count = 0;
	$top[0] =~ m|<!-Top: (\d+)-!>|; $topic1 = $1;
	foreach $line (@top) {
		$line =~ m|^<!-Top: (\d+)-!>|; $topic = $1;
		undef @dir;
		if (-e "$message_dir/$topic") {
			opendir(DIR, "$message_dir/$topic");
			while ($dir = readdir(DIR)) {
				push (@dir, $dir) if $dir =~ m|^(\d+)\.$ext$|;
			}
			closedir(DIR);
			if (scalar(@dir) > 0) {
				push (@topic_line, "$topic-" . scalar(@dir));
				$count += scalar(@dir);
			}
		} elsif (-e "$secdir/$topic") {
			opendir(DIR, "$secdir/$topic");
			while ($dir = readdir(DIR)) {
				push (@dir, $dir) if $dir =~ m|^(\d+)\.$ext$|;
			}
			closedir(DIR);
			if (scalar(@dir) > 0) {
				push (@topic_line, "$topic-" . scalar(@dir));
				$count += scalar(@dir);
			}
		}
	}
	$ts = join(",", @topic_line);
	return ($tempfile, $ts, $topic1);
}

#---SEPARATOR---#
#REQ:show_gauge
#REQ:get_number

sub duplicate_clean {
	my ($header, $actionurl) = @_;
	my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src);
	if ($FORM{'cltemp'} eq "") {
		undef %pglog; undef $mymax;
		open (TOPICS, "$message_dir/$board_topics_file"); @top = <TOPICS>; close (TOPICS);
		@top = grep(/^<!-Top: (\d+)-!>/, @top);
		foreach $line (@top) {
			if ($line =~ m|^<!-Top: (\d+)-!>|) {
				$topic = $1;
				undef @dir;
				if (-e "$message_dir/$topic") {
					opendir(DIR, "$message_dir/$topic");
					while ($dir = readdir(DIR)) {
						if ($dir =~ m|^(\d+)\.$ext$|) {
							push (@dir, $dir); $p = $1;
							$mymax = $p if $p > $mymax;
							if ($pagename{$p} ne "") {
								$pglog{$p} .= "$topic/$dir\n";
							}
							$pagename{$p} = "$topic/$p.$ext" if $pagename{$p} eq "";
						}
					}
					closedir(DIR);
					if (scalar(@dir) > 0) {
						push (@topic_line, "$topic-" . scalar(@dir));
						$count += scalar(@dir);
					}
				} elsif (-e "$secdir/$topic") {
					opendir(DIR, "$secdir/$topic");
					while ($dir = readdir(DIR)) {
						if ($dir =~ m|^(\d+)\.$ext$|) {
							push (@dir, $dir); $p = $1;
							$mymax = $p if $p > $mymax;
							if ($pagename{$p} ne "") {
								$pglog{$p} .= "$topic/$dir\n";
							}
							$pagename{$p} = "$topic/$p.$ext" if $pagename{$p} eq "";
						}
					}
					closedir(DIR);
					if (scalar(@dir) > 0) {
						push (@topic_line, "$topic-" . scalar(@dir));
						$count += scalar(@dir);
					}
				}
			}
		}
		open (DATA, "$admin_dir/data.txt"); $data = <DATA>; close (DATA);
		if ($data < $mymax) {
			&lock("duplicate_clean", "$admin_dir/data.txt");
			open (DATA, ">$admin_dir/data.txt");
			print DATA (1000+$mymax);
			close (DATA);
			&unlock("duplicate_clean", "$admin_dir/data.txt");
			&log_error("src-board-subs-1", "duplicate_clean", "Data file had invalid number with respect to found pages.  Data file reset to higher index.");
		}
		if (scalar(keys(%pglog)) == 0) {
			&log_error("src-board-subs-1", "duplicate_clean", "Received request to clean duplicates but found no duplicate pages to be removed.");
			&seturl($actionurl);
		}
		$cleanertemp = join("", time, $$, 1); $cleanertemp =~ s/\D//g;
		open (TEMP, ">$admin_dir/msg_index/$cleanertemp.TMP");
		foreach $key (keys(%pglog)) {
			$string = "$pagename{$key}\t";
			$pglog{$key} =~ s/\n/\t/g;
			$pglog{$key} =~ s/\s+$//;
			$string .= $pglog{$key};
			$string .= "\n";
			print TEMP $string;
		}
		close (TEMP);
		$actionurl .= "&cltemp=$cleanertemp";
		&show_gauge($header, 'Reindexing -- Fixing duplicate pages', 0, "$actionurl&ctopic=$topic1&cpos=0&ts=" . join(",", @topic_line) . "&tempfile=$tempfile");
	}
	$tempfile = $FORM{'cltemp'}; $tempfile =~ s/\D//g;
	if ($tempfile eq "" || !-e "$admin_dir/msg_index/$tempfile.TMP") {
		&log_error("src-board-subs-1", "duplicate_clean", "Illegal temp file $FORM{'cltemp'}.TMP does not exist!");
		&error_message("Reindexing duplicate cleaning error", "Illegal temp file $FORM{'cltemp'}.TMP does not exist!");
	}
	open (TEMP, "$admin_dir/msg_index/$tempfile.TMP");
	@temp = <TEMP>;
	close (TEMP);
	if (scalar(@temp) == 0) {
		$actionurl =~ s/\&ts=([^\&]+)//;
		unlink("$admin_dir/msg_index/$tempfile.TMP");
		&seturl($actionurl);
	}
	$actionurl .= "&cltemp=$tempfile";
	$FORM{'mycount'} += 1;
	&error_message("Invalid count") if $FORM{'mycount'} < 1;
	$actionurl .= "&mycount=$FORM{'mycount'}";
	$pct = $FORM{'mycount'} / ($FORM{'mycount'} + scalar(@temp));
	$x = pop(@temp);
	open (TEMP, ">$admin_dir/msg_index/$tempfile.TMP");
	print TEMP @temp;
	close (TEMP);
	@files = split(/\t/, $x);
	foreach $line (@files) {
		$line =~ m|(\d+)/(\d+)|;
		$topic = $1; $page = $2;
		($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
		if ($head !~ m|<!--Topic: (\d+)/|) {
			&rename_file("$message_dir/$topic/$page.$ext", 0, "$message_dir/$topic/$page.$ext.BAD") if -e "$message_dir/$topic";
			&rename_file("$secdir/$topic/$page.$ext", 0, "$secdir/$topic/$page.$ext.BAD") if -e "$secdir/$topic";
			$line = "";
			&log_error("src-board-subs-1", "duplicate_clean", "File $topic/$page does not have valid topic header info. Presumed bad file; renamed to $topic/$page.$ext.BAD");
			next;
		}
		$head =~ m|<!--Topic: (\d+)/|;
		if ($1 != $topic) {
			&rename_file("$message_dir/$topic/$page.$ext", 0, "$message_dir/$topic/$page.$ext.BAD") if -e "$message_dir/$topic";
			&rename_file("$secdir/$topic/$page.$ext", 0, "$secdir/$topic/$page.$ext.BAD") if -e "$secdir/$topic";
			$line = "";
			&log_error("src-board-subs-1", "duplicate_clean", "File $topic/$page is in the wrong topic. Presumed bad file; renamed to $topic/$page.$ext.BAD");
			next;
		}
	}
	@files = grep(/\S/, @files);
	if (scalar(@files) > 1) {
		foreach $x (@files) {
			$x =~ m|(\d+)/(\d+)|;
			($topic, $page) = ($1, $2);
			next if $topic == $page;
			$hold_my_bad_page = $page;
			$newnum = &get_number;
			$size = -s "$message_dir/$topic/$page.$ext" if -e "$message_dir/$topic";
			$size = -s "$secdir/$topic/$page.$ext" if -e "$secdir/$topic";
			&rename_file("$message_dir/$topic/$page.$ext", $size, "$message_dir/$topic/$newnum.$ext") if -e "$message_dir/$topic";
			&rename_file("$secdir/$topic/$page.$ext", $size, "$secdir/$topic/$newnum.$ext") if -e "$secdir/$topic";
			($newpage, $addfile) = &determine_templates($topic);
			&recursive_fixer($topic, $newnum, $hold_my_bad_page, $newnum, $newpage, $addfile);
			($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $newnum);
			if ($head =~ m|<!--Parent: (\d+)-->|) {
				$pn = $1;
				if ($pn ne $page && (-e "$message_dir/$topic/$pn.$ext" ||  -e "$secdir/$topic/$pn.$ext")) {
					&lock("duplicate_clean", "$message_dir/$topic/$pn.$ext");
					($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $pn);
					$sublist =~ s%<!-Top: $hold_my_bad_page-!>%<!-Top: $newnum-!>%g;
					$sublist =~ s%$message_url/$topic/$hold_my_bad_page.$ext%$message_url/$topic/$newnum.$ext%g;
					&set_page($topic, $pn, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src, $newpage, $addfile, "", 1);
					&unlock("duplicate_clean", "$message_dir/$topic/$pn.$ext");
				}
			}
			&log_error("src-board-subs-1", "duplicate_clean", "File $topic/$hold_my_bad_page renamed to $topic/$newnum.$ext (parent is $pn)!");
		}
	}
	&show_gauge($header, 'Reindexing -- Fixing duplicate pages', $pct, "$actionurl&ctopic=$topic1&cpos=0&ts=" . join(",", @topic_line) . "&tempfile=$tempfile");
}

sub recursive_fixer {
	my ($topic, $page, $oldpage, $newpage, $pagefile, $addfile) = @_;
	my ($line, @subl);
	&lock("recursive_fixer", "$message_dir/$topic/$page.$ext");
	my ($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
	$head =~ s%<!--Level (\d+): $oldpage/(.*)-->%<!--Level $1: $newpage/$2-->%;
	$head =~ s%<!--Me: $oldpage/(.*)-->%<!--Me: $newpage/$1-->%;
	$head =~ s%<!--Parent: $hold_my_bad_page-->%<!--Parent: $newnum-->%;
	&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src, $pagefile, $addfile, "", 1);
	@subl = grep(/^<!-Top:/, split(/\n/, $sublist));
	foreach $line (@subl) {
		$line =~ m|^<!-Top: (\d+)-!>|;
		&recursive_fixer($topic, $1, $oldpage, $newpage, $pagefile, $addfile);
	}
	&unlock("recursive_fixer", "$message_dir/$topic/$page.$ext");
}

#---SEPARATOR---#
#REQ:show_gauge
#REQ:inverse_get_date_time

sub time_grabber {
	if ($FORM{'method'} <= 2 || $FORM{'method'} == 7) {
		$tempfile = join("", $$, time, "DF"); $tempfile =~ s/\W//g;
		open (TEMPFILE, ">$admin_dir/backups/$tempfile.TMP");
	}
	if ($FORM{'method'} == 1) {
		if (!open(FILE,"$admin_dir/backups/datefix.tar")) {
			&error_message("Date Fixer Error", "The required archive file, backups/datefix.tar, does not exist");
		}
		binmode(FILE);
		read(FILE, $header, 512);
		while (length($header) == 512) {
			($file, $mode, $f, $f, $size, $f, $chksum, $type, $f, $f, $f, $f, $f, $f, $f, $prefix) = unpack("A100 A8 A8 A8 A12 A12 A8 A1 A100 A6 A2 A32 A32 A8 A8 A155",$header);
			($mode, $size, $chksum) = (oct($mode), oct($size), oct($chksum));
			$type = 5 if ($name =~ /\/$/ && $type == 0);
			last if $header eq "\0" x 512;
			substr($header, 148, 8) = "        ";
			$d = $size % 512;
			read(FILE,$foo,512-$d) if $d != 0;
			if (read(FILE, $content, $size) != $size) {
				close (FILE);
				&error_message("Error reading backup file", "Critical error.  Archive is probably corrupted.");
			}
			if ($file =~ m|(\d+)\.$ext$|) {
				@content = split(/\n/, $content);
				&handle_file;
			}
			read (FILE, $header, 512);
		}
		close (FILE);
		close (TEMPFILE);
		&show_gauge("Repair times on posts", "Estimating time necessary", 0, "$cgiurl?action=datefixer&method=4&tempfile=$tempfile&username=$superuser");
	} elsif ($FORM{'method'} == 2) {
		if (opendir(DIR, "$admin_dir/backups/datefix")) {
			while ($dir = readdir(DIR)) {
				if ($dir =~ m|^(\d+)$| && -d $dir) {
					opendir(DIR2, "$admin_dir/backups/datefix/$dir2");
					while ($dir2 = readdir(DIR2)) {
						if ($dir2 =~ m|^(\d+)\.$ext|) {
							open (FILE, "$admin_dir/backups/datefix/$dir2");
							@content = <FILE>;
							close (FILE);
							&handle_file;
						}
					}
					closedir(DIR2);
				}
			}
			closedir(DIR);
		} else {
			&error_message("Date Fixer Error", "The required directory, backups/datefix, does not exist");
		}
		&show_gauge("Repair times on posts", "Estimating time necessary", 0, "$cgiurl?action=datefixer&method=4&tempfile=$tempfile&username=$superuser");
	} elsif ($FORM{'method'} == 7) {
		if (open(FILE, "$admin_dir/backups/old-log.txt")) {
			while (<FILE>) {
				chomp;
				($postnum, $who, $time, $where, $addr, $host, $text, $postby) = split(/;/, $_);
				print TEMPFILE "$postnum\t$time\t", &unescape($postby), "\t\n";
			}
			close (FILE);
			close (TEMPFILE);
		} else {
			&error_message("Date Fixer Error", "The required directory, backups/old-log.txt, does not exist");
		}
		&show_gauge("Repair times on posts", "Estimating time necessary", 0, "$cgiurl?action=datefixer&method=4&tempfile=$tempfile&username=$superuser");
	} elsif ($FORM{'method'} == 3) {
		eval 'use Time::Local;';
		$x = timelocal(0,$FORM{'min'},$FORM{'hour'},$FORM{'day'},$FORM{'month'},$FORM{'year'});
		$x = time if $x <= 0;
		&show_gauge("Repair times on posts", "Estimating time necessary", 0, "$cgiurl?action=datefixer&method=4&timesetter=$x&username=$superuser");
	} elsif ($FORM{'method'} == 4) {
		$tempfile2 = join("", $$, time, "DF2"); $tempfile2 =~ s/\W//g;
		open (TEMPFILE, ">$admin_dir/backups/$tempfile2.TMP");
		opendir(DIR, "$admin_dir/msg_index");
		while ($dir = readdir(DIR)) {
			next if $dir !~ m|(\d+)-tree\.txt$|;
			open (TREE, "$admin_dir/msg_index/$1-tree.txt");
			while (<TREE>) {
				@c = split(/\t/, $_);
				print TEMPFILE "$c[1]\t$c[2]\n"; $counter += 1;
			}
			close (TREE);
		}
		closedir(DIR);
		close (TEMPFILE);
		&show_gauge("Repair times on posts", "Starting Process", 0, "$cgiurl?total=$counter&action=datefixer&method=5&timesetter=$FORM{'timesetter'}&tempfile=$FORM{'tempfile'}&tempfile2=$tempfile2&username=$superuser");
	} elsif ($FORM{'method'} == 5) {
		$tempfile = $FORM{'tempfile'}; $tempfile2 = $FORM{'tempfile2'};
		$tempfile =~ s/\W//g; $tempfile2 =~ s/\W//g;
		if ($tempfile) {
			if (open(TEMPFILE, "$admin_dir/backups/$tempfile.TMP")) {
				while (<TEMPFILE>) {
					chomp;
					($msg, $time, $name, $email) = split(/\t/, $_);
					$time{$msg} = $time;
					$name{$msg} = $name;
					$email{$msg} = $email;
				}
				close (TEMPFILE);
			} else {
				&error_message("Temporary file error", "The file $tempfile.TMP could not be opened!");
			}
		} else {
			$timesetter = $FORM{'timesetter'}; $timesetter += 0;
			$timesetter = time if $timesetter == 0;
		}
		if (open(TEMPFILE, "$admin_dir/backups/$tempfile2.TMP")) {
			@tempfile2 = <TEMPFILE>;
			close (TEMPFILE);
		} else {
			&error_message("Temporary file error", "The file $tempfile2.TMP could not be opened!");
		}
		$timenow = time;
		foreach $line (@tempfile2) {
			chomp $line;
			($topic, $page) = split(/\t/, $line);
			next if $topic == 0;
			next if $page == 0;
			$line = "";
			($head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src) = &get_page($topic, $page);
			@msg = split(/\n/, $message);
			$flag = ""; $num = 0;
			foreach $m (@msg) {
				if ($m =~ m|<!-Post: (\d+)-!>|) {
					$num = $1;
					if ($m =~ m|<!-Time: 0-!>|) {
						$m = join("", $`, "<!-Time: $time{$num}-!>", $') if $time{$num} > 0;
						$m = join("", $`, "<!-Time: $timesetter-!>", $') if $timesetter > 0;
						$flag = 1 if ($time{$num} > 0 || $timesetter > 0);
					}
				} elsif ($m =~ m|<!-Name-!>(.*?)<!-/Name-!>|) {
					if ($1 ne $name{$num} && $name{$num} ne "" && $name{$num} ne $L{BPANONYMOUS}) {
						$flag = 1;
						$m = join("", $`, "<!-Name-!>$name{$num}<!-/Name-!>", $');
					} elsif ($1 eq "" && $name{$num} eq $L{BPANONYMOUS}) {
						$flag = 1;
						$m = join("", $`, "<!-Name-!>$name{$num}<!-/Name-!>", $');
					}
					if ($m =~ m|<!-Email-!><A HREF="?javascript:([^>]+)>|) {
						if ($email{$num} ne "") {
							$aa = $`; $ab = $'; chomp $email{$num};
							$m = join("", $aa, "<!-Email-!><A HREF=\"$email{$num}\">", $ab) if $email{$num} =~ m|^mailto:|;
							$m = join("", $aa, "<!-Email-!><A HREF=\"$email{$num}\">", $ab) if $email{$num} =~ m|display_profile|;
							$flag = 1;
						}
					} elsif ($m =~ m|<!-Email-!>\s*<!-/Email-!>|) {
						$aa = $`; $ab = $';
						if ($email{$num} ne "") {
							chomp $email{$num};
							$m = join("", $aa, "<!-Email-!><A HREF=\"$email{$num}\"><!-/Email-!>", $ab) if $email{$num} =~ m|^mailto:|;
							$m = join("", $aa, "<!-Email-!><A HREF=\"$email{$num}\"><!-/Email-!>", $ab) if $email{$num} =~ m|display_profile|;
							$flag = 1;
						}
						$m = join("", $aa, "<!-Email-!><A HREF=\"javascript:alert('$L{NOT_AVAILABLE}')\"><!-/Email-!>", $ab) if $m =~ m|<!-Email-!>\s*<!-/Email-!>|;
					}
				}
			}
			if ($flag) {
				$message = join("\n", @msg);
				&set_page($topic, $page, $head, $color, $lm, $ann, $ann_src, $sublist, $about, $about_src, $message, $message_src, $description_src, "", "", "", 1);
				$FORM{'sofar'} += 1;
			}
			if (time >= ($timenow+3)) {
				open (NEWTEMP, ">$admin_dir/backups/$tempfile2.TMP");
				print NEWTEMP @tempfile2;
				close (NEWTEMP);
				$FORM{'total'} = 1 if $FORM{'total'} <= 0;
				$FORM{'sofar'} = 0 if $FORM{'sofar'} <= 0;
				&show_gauge("Repair times on posts", "Running -- $FORM{'sofar'} fixed so far", ($FORM{'total'}-scalar(@tempfile2))/$FORM{'total'}, "$cgiurl?action=datefixer&method=5&timesetter=$FORM{'timesetter'}&tempfile=$tempfile&tempfile2=$tempfile2&username=$superuser&total=$FORM{'total'}&sofar=$FORM{'sofar'}");
			}
		}
	}
	unlink("$admin_dir/backups/$tempfile.TMP");
	unlink("$admin_dir/backups/$tempfile2.TMP");
}

sub handle_file {
	foreach $line (@content) {
		if ($line =~ m|<!-Post: (\d+)-!>|) {
			$num = $1; $flag = 1; $foundflag = 0;
			$name = ""; $email = ""; $time = "";
			if ($line =~ m|<!-Time: (\d+)-!>|) {
				$time = $1 if $1 != 0;
				$badtime = 1 if $time == 0;
				$line = join("", $`, $');
			} else {
				$badtime = 1;
			}
		} elsif ($line =~ m|<!-Name-!>|) {
			$name = ""; $email = "";
			$line =~ m|<!-Name-!>(.*?)<!-/Name-!>|; $name = $1 if $1 ne "";
			$line =~ m|<!-Email-!>(.*?)<!-/Email-!>|; $email = $1 if $1 ne "";
			if ($email =~ m|<A HREF="mailto:([^"]+)">|i) {
				$email = "mailto:$1";
			} elsif ($email =~ m|<A HREF="(.*?)&profile=(\w+)-(\w+)|i) {
				$email = "$script_url/board-profile.$cgi_extension?action=display_profile&profile=$2-$3";
			} else {
				$email = "";
			}
		} elsif (($line =~ m|^<FONT SIZE="?-1"?>| || $line =~ m|^<!-Icons-!>|) && $flag && !$foundflag) {
			$x = "";
			if ($line =~ m|<B><A HREF=(['"]*)([^>]+)(['"]*)>(.*?)</A>|) {
				$x = $'; $foundflag = 1; $email = $2;
				$line = join("", $`, "<B><A HREF=\"$2\"><!-Name-!>$4<!-/Name-!></A>", $');
				$name = $4;
			} elsif ($line =~ m|<B><A HREF=([^>]+)>(.*?)</A>|) {
				$x = $'; $foundflag = 1; $email = $1;
				$line = join("", $`, "<B><A HREF=\"$1\"><!-Name-!>$2<!-/Name-!></A>", $');
				$name = $2;
			} elsif ($line =~ m|<B>(.*?)</B>|) {
				$x = $'; $foundflag = 1;
				$line = join("", $`, "<B><!-Name-!>$1<!-/Name-!></B>", $');
				$name = $1;
			}
			if ($badtime == 1) {
				$badtime = 0;
				if ($x =~ m|<B>(.*?)</B>|) {
					$o = $1;
					$tv = &inverse_get_date_time("long", $o);
					if ($tv > 0) {
						$time = $tv;
					} else {
						$time = "0";
					}
				}
			}
		} elsif ($line =~ m|<!-/Post: (\d+)-!>|) {
			$flag = 0;
			print TEMPFILE "$num\t$time\t$name\t$email\n";
		}
		$ctrline += 1;
	}
}

# END - FILE IS CORRECTLY UPLOADED #
