

sub FixSubjectEncoding {
	my $item = shift;
	$item =~ s/&/&amp\;/gi;                #no ampersand codes
	$item =~ s/"/&quot\;/gi;               #no quotes
	$item =~ s/\|/&#0124\;/gi;             #no pipes
	$item =~ s/&amp\;(#\d+)\;/&$1\;/gi;    #fix b0rked &# codes
	return $item;
}


sub CheckCoding {

	# required parameters
	# $_[0] : html is/is not permitted
	# $_[1] : ubb code is/is not permitted
	# $_[2] : ubb code images ON/OFF

	if ($_[0] eq 'is') {
		$is_html      = "$vars_wordlets{html_is_on}";
		$html_allowed = 'yes';
	} else {
		$is_html      = "$vars_wordlets{html_is_off}";
		$html_allowed = 'no';
	}

	if ($_[1] eq 'is') {
		$is_ubb      = "$vars_wordlets{ubbcode_is_on}";
		$ubb_allowed = 'yes';
	} else {
		$is_ubb      = "$vars_wordlets{ubbcode_is_off}";
		$ubb_allowed = 'no';
	}

	if (($_[2] eq 'OFF') && ($_[1] eq 'is')) {
		$ubb_images_wording = "$vars_wordlets{ubbcode_images_banned}";
	} else {
		$ubb_images_wording = '';
	}

}    # end checkcoding

sub floodcheck {    # blocks multiple posting in a short period
	    # floodcheck written by Michael Farris!
	local (*FILE);
	local ($j, @last_post_list, $last_post_time);

	#$wait_between_posts = "1.0"; #  edit in the default number of minutes to wait
	$lastpost_list_length = 80;    # edit in the number of records to keep

	my $IPNumber       = $ENV{'REMOTE_ADDR'};    # the IP address
	my $this_post_time = time();                 # secs since 1970

	# don't bother with error code if it doesn't exist
	@last_post_list = &OpenFileAsArray("$vars_config{NonCGIPath}/BanLists/Floodcheck.cgi");

	foreach (@last_post_list) {                  # check if this user has posted already
		if (/^$IPNumber/) {
			($j, $last_post_time) = split (/\|!!\|/, $_);
			chomp($last_post_time);
			last;
		}
	}    # end foreach

	# $FloodCheckSpan (in seconds) is set in General Settings

	if (int(($this_post_time - $last_post_time) < $vars_misc{FloodCheckSpan})) {

		if ($in{ubb} eq 'submit_registration') {

			#print qq%Content-type: text/html\n\n%;
			print header(
				-charset => "$masterCharset",
				-type    => "text/html",
			);

		}

		&StandardHTML("$vars_wordlets_err{flood_control} $vars_misc{FloodCheckSpan}");
	} else {    # add the IP and posting time to the list
		if (unshift (@last_post_list, "$IPNumber|!!|$this_post_time\n") > $lastpost_list_length) {
			$#last_post_list = $lastpost_list_length;    # limit length of list
		}
		chmod(0666, "$vars_config{NonCGIPath}/BanLists/Floodcheck.cgi");

		&WriteFileAsArray("$vars_config{NonCGIPath}/BanLists/Floodcheck.cgi", @last_post_list);

	}    #  end else

}    # end SR


sub update_forum_summary {
	local ($number, $j, $thread_num, $month, $day, $year, $get_hour, $get_minute, $am_pm, $mil_time, $post_j, %forum_topics, $lc_subject, $subject, @forum_info);
	local (*FILE);

	# two parameters must be passed:
	$number     = $_[0];
	$thread_num = $_[1];
	$subject    = $_[2];

	undef(%forum_topics);

	# grab current threads file
	if ($number ne '') {

		my $this_forum_topics = &GetForumTopics($number);
		%forum_topics = %$this_forum_topics;

	}

	# now we have the current %forum_topics hash

	@forum_info = &GetForumRecord($number);

	if ($forum_info[15] eq 'abc') {

		$lc_subject = lc($subject);
		$lc_subject =~ s/"/\&quot\;/g;
		$lc_subject =~ s/\|/&#0124;/sg;
		$lc_subject = &EliminateReturns($lc_subject);
		if ($lc_subject =~ /\\$/) { $lc_subject .= ' '; }
		$forum_topics{$thread_num} = "$lc_subject";

	} else {

		# parse topic date
		($month, $day, $year) = split (/-/, $GotTime{HyphenDate});

		($get_hour,   $get_minute) = split (/:/, $GotTime{Time});
		($get_minute, $am_pm)      = split (/ /, $get_minute);
		chomp($am_pm);

		$mil_time = &ConvertTo24HourRunon("$get_hour", "$get_minute", "$am_pm");
		$post_j = &jday($month, $day, $year);
		$post_j = ($post_j + ($mil_time * 0.0001));
		$post_j = sprintf("%6.4f", $post_j);
		$post_j =~ tr/ /0/;

		$forum_topics{$thread_num} = "$post_j";

	}    # if/else alphabetical storage

	&UpdateForumTopics($number, \%forum_topics);

}    # end update_forum_summary


sub unlink_topic_from_forum_summary {
	local ($number, %forum_topics);
	local (*FILE);

	# two parameters must be passed:
	$number     = $_[0];
	$thread_num = $_[1];

	undef(%forum_topics);

	my $this_forum_topics = &GetForumTopics($number);
	%forum_topics = %$this_forum_topics;

	delete $forum_topics{$thread_num};

	my @array = &GetThreadData($number, $thread_num);    #make sure it's loaded
	$thread_num =~ m/^(\d{4})(\d{2})$/;
	my ($lefty, $righty) = ($1, $2);

	delete $forum_thread_data{$number}->{$lefty}->{$righty};

	&UpdateForumTopics($number,   \%forum_topics);
	&WriteForumThreadData($number, $lefty);

}    # end unlink_topic_from_forum_summary



sub nice_unlink_topic_from_forum_summary {

	# like its big brother, only doesn't write the changes out
	local ($number, *FILE);

	# two parameters must be passed:
	$number     = $_[0];
	$thread_num = $_[1];

	delete $forum_topics{$thread_num};

	&SafeGetThreadData($number, $thread_num);    #make sure it's loaded
	$thread_num =~ m/^(\d{4})(\d{2})$/;
	my ($lefty, $righty) = ($1, $2);
	delete $forum_thread_data{$number}->{$lefty}->{$righty};

	&SetExactPath($number);

	&UpdateForumTopics($number, \%forum_topics, 1);    # ,1 == don't write the file, just update the hash
	#&WriteForumThreadData($lefty, "$vars_config{NonCGIPath}/$exact_path");

}    # end unlink_topic_from_forum_summary



sub create_icon_field {
	local ($icon_list, $item, $icon_num, $inumber, $j);
	local (*FILE);

	# one parameter
	# $_[0] : $icon_selection

	if ($_[0] eq '') { $_[0] = '1'; }

	opendir(FILE, "$vars_config{NonCGIPath}/icons");
	my @icons = sort(readdir(FILE));
	closedir(FILE);

	my @the_icons = grep(/icon\d/, @icons);
	my $count = 0;
	my $check_this = '';

	foreach $item (@the_icons) {
		($j,       $icon_num) = split (/con/, $item);
		($inumber, $j)        = split (/\./,  $icon_num);
		$count++;
		if ($inumber == $_[0]) {
			$check_this = 'checked="checked"';
		} else {
			$check_this = '';
		}

		$icon_list .= qq(<input type="radio" name="msg_icon" value="$inumber" $check_this>&nbsp;&nbsp;
<img src="$vars_config{NonCGIURL}/icons/$item" align="ABSCENTER">&nbsp;&nbsp;&nbsp;&nbsp;);
		if ($count == 7) { $icon_list .= '<br />'; $count = 0; }
	}

	return ($icon_list);
}


sub prep_for_edit {

	# requires three parameters:
	# $_[0] : the text to prep
	# $_[1] : ubbcode setting for forum (is/is not)
	# $_[2] : ubbcode IMG permission setting for forum (ON/OFF)

	$_[0] =~ s/<p>/\n\r\n/isg;
	$_[0] =~ s/<br>/\n/isg;
	$_[0] =~ s/<br \/>/\n/isg;
	$_[0] =~ s/<\/p>//gi;

	if (!exists $vars_graemlins->{'graems'}) {
		&RequireVars("$vars_config{VariablesPath}/vars_graemlins.cgi");
	}

	foreach my $item (sort keys %{$vars_graemlins->{'graems'}}) {
		my $short = %$vars_graemlins->{'graems'}->{$item};
		$_[0] =~ s/ ?<img src="graemlins\/$short->{'image'}" border="0" alt="\[[^\"\[\]]+\]" \/> ?/ :$short->{'trigger'}: /gi;
	}    #endforeach

	foreach my $item (sort keys %{$vars_graemlins->{'origs'}}) {
		my $short = %$vars_graemlins->{'origs'}->{$item};
		$_[0] =~ s/ ?<img src="$short->{'image'}" border="0"> ?/ $short->{'trigger'} /gi;
	}    #endforeach

	if ($_[1] eq 'is') {

		#convert UBB Code
		$_[0] = &reverse_ubb_code("$_[0]", "$_[2]");
	}
	return ($_[0]);
}


sub reverse_ubb_code {

	# two parameters:
	# $_[0] : the text to convert
	# $_[1] : ubbcode [IMG] enabled? (ON/OFF)

	$_[0] =~ s/(<A HREF=")(http|https|ftp)(:\/\/)(\S+)(" TARGET=_blank>)(.+?)(<\/A>)/\[URL=$2:\/\/$4\]$6\[\/URL\]/isg;
	$_[0] =~ s/(<A HREF=")(http|https|ftp)(:\/\/)(\S+)(" TARGET="_blank">)(.+?)(<\/A>)/\[URL=$2:\/\/$4\]$6\[\/URL\]/isg;
	$_[0] =~ s/(<A HREF="mailto:)(\S+)(">)(\S+)(<\/A>)/\[EMAIL\]$2\[\/EMAIL\]/isg;
	$_[0] =~ s/(<i>)(.+?)(<\/i>)/\[i\]$2\[\/i\]/isg;
	$_[0] =~ s/(<b>)(.+?)(<\/b>)/\[b\]$2\[\/b\]/isg;
	$_[0] =~ s/(<strong>)(.+?)(<\/strong>)/\[qb\]$2\[\/qb\]/isg;
	$_[0] =~ s/(<BLOCKQUOTE><font size="1" face=".*?">$vars_wordlets{ubbcode_code}:<\/font><HR><pre>?)(.+?)(<\/pre><HR><\/BLOCKQUOTE>)/\[CODE\]$2\[\/CODE\]/isg;
	$_[0] =~ s/(<BLOCKQUOTE><font size="1" face=".*?">$vars_wordlets{ubbcode_quote}:<\/font><HR>?)(.+?)(<HR><\/BLOCKQUOTE>)/\[QUOTE\]$2\[\/QUOTE\]/isg;

	if ($_[1] ne "OFF") {
		$_[0] =~ s/(<IMG SRC=")(\S+)(">)/\[IMG\]$2\[\/IMG\]/isg;
	}

	$_[0] =~ s/(<UL TYPE=SQUARE>)(.+?)(<\/UL>)/\[list\]$2\[\/list\]/isg;
	$_[0] =~ s/(<UL TYPE="SQUARE">)(.+?)(<\/UL>)/\[list\]$2\[\/list\]/isg;
	$_[0] =~ s/(<OL TYPE=")(A|1)(">)(.+?)(<\/OL>)/\[list=$2\]$4\[\/list\]/isg;
	$_[0] =~ s/<LI>/\[\*\]/isg;

	return ($_[0]);
}    #end EditUBBConvert


sub build_topic_review {
	local (@sort_topic, $total_posts, $summary, $row, $alt_color2, @posted, @user_profile, $listed_name, $this_user_number);
	@sort_topic  = sort(@this_topic);
	$total_posts = @sort_topic;

	if (($total_posts > 26) || ($post_permiss eq "private")) {
		$summary = qq(<font size="$vars_style{TextSize}" color="$vars_style{TableStripTextColor}" face="$vars_style{FontFace}"><a href="$go_to" target="_blank"> $vars_wordlets{topic_review_link}</a></font>);
	} else {
		$summary = qq~
$TBT
<tr bgcolor="$vars_style{TableColorStrip}">
<td colspan="2" align="left">
<font size="$vars_style{TextSize}" color="$vars_style{TableStripTextColor}" face="$vars_style{FontFace}">
<b>$vars_wordlets{topic_review}</b>
</font></td></tr>
~;

		$alt_color2 = "$vars_style{AltColumnColor2}";

		foreach $row (@sort_topic) {
			if ($alt_color2 eq "$vars_style{AltColumnColor1}") {
				$alt_color2 = "$vars_style{AltColumnColor2}";
			} else {
				$alt_color2 = "$vars_style{AltColumnColor1}";
			}

			if ($row !~ /^A/) {
				@posted = split (/\|\|/, $row);

				if (($posted[8] eq 'unreg') or ($posted[8] eq '')) {
					$listed_name = $posted[2];
				} else {

					if ($posted[11] eq '') {

						# old post- we need to find user number
						$this_user_number = &GetUserNumber($posted[2]);
						if ((-e "$vars_config{MembersPath}/$this_user_number.cgi") && ($this_user_number ne '')) {
							@user_profile = &OpenProfile("$this_user_number");
						} else {
							$user_profile[15] = $posted[2];
						}

					} else {

						# already have user number
						if (-e "$vars_config{MembersPath}/$posted[11].cgi") {
							@user_profile = &OpenProfile("$posted[11]");
						} else {
							$user_profile[15] = "$posted[10]";
							chomp($posted[10]);
						}

					}

					chomp($user_profile[15]);
					if ($user_profile[15] ne '') {
						$listed_name = $user_profile[15];
					} else {
						$listed_name = $posted[2];
					}
					chomp($listed_name);

				}
				$summary .= qq~
<tr bgcolor="$alt_color2">
<td valign="top">
<font size="$vars_style{TextSize}" face="$vars_style{FontFace}">
$listed_name
</font></td>
<td><font size="$vars_style{TextSize}" face="$vars_style{FontFace}">$posted[6]</font>
</td></tr>
~;
			}

		}
		$summary .= "$TBB <p> </p>";
	}
	return ($summary);

}

sub create_topic {

	# you are entering the most complicated (and important) subroutine in the UBB... beware!

	local ($forum_number, $topic_number, $array_start, $page_number, @topic_file, @stat_line, @ordered_topic, $j, $ThisPage, $TopicPageTotal, $PostTotal, $PageName, $whole, @postinfo, $MaxPoint, $ContinueAt, $NextPage, $TotalPages, $close_transfer_wording, $ubb_friend_on, $close_option, $reply_button, $move_option, $delete_option, $reply_restrict, $topic_restrict, $reply_wording, $topic_wording, $category, $cat_name, $line, @thisline, $un_coded, $public_name, $this_user_name, $hyphen_date, $ip_number, $ip_wording, $is_reg, @datearray, @timearray, $year_check, $year, $ThisDate, $get_hour, $get_minute, $FormatTime, $post_body, $edit_link, @user_profile, $this_user_number, $user_status, @themonths, $RegDate, $RegMon, $RegDay, $RegYear, $AuthorExtra, $profile_link, $email_link, $icon_number, $this_icon, $direct_reply, $alt_color, $hop_to_options, $page_name, $show_public_name, $ip_divider, $cat_line1, $cat_line2, $user_rating, $user_type, %Rater, %User, %votes, %total, %avg, %weighted_avg, $homepage_link, @author_extra, $location_line, $regdate_line, $post_total_line, @blank, $u, $member_number, $allow_images, $overall_rating, $stars, $rating_line, $total_votes, $pm_link, %rate_list);
	local (*FILE);

	# args:
	$forum_number = $_[0];
	$topic_number = $_[1];
	$array_start  = $_[2];
	$page_number  = $_[3];

	# for registration date...
	@themonths = ('', "$vars_wordlets_date{month_1_abbrev}", "$vars_wordlets_date{month_2_abbrev}", "$vars_wordlets_date{month_3_abbrev}", "$vars_wordlets_date{month_4_abbrev}", "$vars_wordlets_date{month_5_abbrev}", "$vars_wordlets_date{month_6_abbrev}", "$vars_wordlets_date{month_7_abbrev}", "$vars_wordlets_date{month_8_abbrev}", "$vars_wordlets_date{month_9_abbrev}", "$vars_wordlets_date{month_10_abbrev}", "$vars_wordlets_date{month_11_abbrev}", "$vars_wordlets_date{month_12_abbrev}");

	# used for mod check later:
	my $Moderator = ("Forum" . "$forum_number" . "Moderator");
	$Moderator = $$Moderator;

	# create hop-to list
	if (!$hop_to_options) {
		$in{f} = $forum_number;    # need this for hop to sr
		$hop_to_options = &hop_to_list;
	}

	#get topic file
	@topic_file = &OpenTopic("$topic_number", "$forum_number");
	my $topic_file_end = $#topic_file;

	# get forum stat line
	@stat_line = split (/\|\|/, $topic_file[0]);

	# remove statline from topic_file array
	@topic_file = @topic_file[1 .. $topic_file_end];

	#reverse topics?
	if ($vars_display{ReverseThreads} eq 'TRUE') {
		@ordered_topic = reverse(@topic_file);
	} else {
		@ordered_topic = @topic_file;
	}    # end if/else reverse threads option

	undef($ThisPage);
	undef($TopicPageTotal);
	undef($PostTotal);
	undef($PageName);

	#adjust for max post per page, if necessary
	if (($vars_display{HTMLDisplayMax} ne '') && ($vars_display{HTMLDisplayMax} ne 'NONE')) {

		$PostTotal = @ordered_topic;

		if ($PostTotal > $vars_display{HTMLDisplayMax}) {

			$TotalPages = int($PostTotal / $vars_display{HTMLDisplayMax});
			if ($PostTotal % $vars_display{HTMLDisplayMax}) { $TotalPages++; }

			$TopicPageTotal = "$vars_wordlets{topic_total_pages}";

			foreach (1 .. $TotalPages) {
				if ($_ == 1) {
					$PageName = '';
				} else {
					$PageName = "$_";
				}

				if ($page_number == $_) {
					$TopicPageTotal .= qq(&nbsp;$_&nbsp;);
				} else {
					$TopicPageTotal .= qq(&nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_topic&f=$in{f}&t=$topic_number&p=$PageName">$_</A>&nbsp;)

				}
			}    # foreach page...

			$ThisPage = "($vars_wordlets{page} $page_number)";

			# limit ordered_topic based on page limitations
			$MaxPoint = ($array_start + $vars_display{HTMLDisplayMax}) - 1;
			if ($MaxPoint >= $#ordered_topic) {
				$MaxPoint   = $#ordered_topic;
				@postinfo   = @ordered_topic[$array_start ... $MaxPoint];
				$ContinueAt = '';
			} else {
				@postinfo   = @ordered_topic[$array_start ... $MaxPoint];
				$ContinueAt = $MaxPoint + 1;
				$NextPage   = $page_number + 1;
			}

		} else {
			@postinfo   = @ordered_topic[0 ... $#ordered_topic];
			$ContinueAt = '';
			$TotalPages = 1;
		}

	} else {
		@postinfo   = @ordered_topic[0 ... $#ordered_topic];
		$ContinueAt = '';
		$TotalPages = 1;
	}    #end if HTML max display

	if ($TotalPages == 1) { $ThisPage = ""; $TopicPageTotal = ""; }

	# UBB Friend?
	if (($vars_email{UseEmail} eq 'ON') && ($this_forum[6] ne 'private') && ($vars_email{UBBFriendUSE} ne 'OFF')) {

		$ubb_friend_on = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=send_topic&t=$topic_number&f=$forum_number"><img src="$vars_config{NonCGIURL}/$vars_style{ubb_friend_mini}" border="0"></a> <a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=send_topic&t=$topic_number&f=$forum_number">$vars_wordlets{ubb_friend}</a>);

	} else {

		$ubb_friend_on = '';

	}

	# set topic title
	$title_wording = $stat_line[4];
	&set_page_elements;

	# is topic closed?
	if ($stat_line[1] =~ m/X/) {

		$topic_closed = qq(<br clear=all><font size=1><img src="$vars_config{NonCGIURL}/lock.gif" border="0" alt="$vars_wordlets{topic_closed}">&nbsp;&nbsp;$vars_wordlets{topic_closed}</font>);

		if (($stat_line[7]) && ($stat_line[1] =~ m/X/)) {
			$close_transfer_wording = qq(<br /><b>$stat_line[7]</b>);
			$ubb_friend_on          = '';
		} else {
			$close_transfer_wording = "";
		}

		$close_option = qq(<a  href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=open_topic&t=$topic_number&f=$forum_number"><img src="$vars_config{NonCGIURL}/$vars_style{open_topic}" border="0" alt="$vars_wordlets{open_topic}"></a>);

		$reply_button = $topic_closed;

	} else {

		$topic_closed           = '';
		$close_transfer_wording = '';

		$close_option = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=close_topic&t=$topic_number&f=$forum_number"><img src="$vars_config{NonCGIURL}/$vars_style{close_topic}" border="0" alt="$vars_wordlets{close_topic}"></a>);

		$reply_button = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=reply&f=$forum_number&t=$topic_number"><img src="$vars_config{NonCGIURL}/$vars_style{BBReply}" BORDER="0" alt="$vars_wordlets{post_reply}"></a>);

	}

	$move_option = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=transfer&t=$topic_number&f=$forum_number"><img src="$vars_config{NonCGIURL}/$vars_style{move_topic}" border="0" alt="$vars_wordlets{move_topic}"></a>);

	$delete_option = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=delete_topic&f=$forum_number&t=$topic_number"><img src="$vars_config{NonCGIURL}/$vars_style{delete_topic}" border="0" alt="$vars_wordlets{delete_topic}"></a>);

	# recreate directory, if necessary
	unless (-d "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path") {
		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path", 0777);
		chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path");
	}

	# get posting permissions
	if (!$reply_restrict) {

		if ($this_forum[6] eq 'private') {
			$reply_restrict = 'ok';
			$topic_restrict = 'ok';
		} else {
			($topic_restrict, $reply_restrict) = split (/&/, $this_forum[6]);
		}

		unless ($reply_restrict eq 'none') { $reply_wording = $reply_button; }

		unless ($topic_restrict eq 'none') {
			$topic_wording = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=newtopic&f=$forum_number"><img src="$vars_config{NonCGIURL}/$vars_style{BBTopic}" alt="$vars_wordlets{post_new_topic}" border="0"></a>);
		}

	}    # end check for posting perms


	if ($vars_display{CategoryView} eq 'yes') {

		if (!$category) {
			$category = $this_forum[0];
			$cat_name = &GetCatName($category);
		}

		$cat_line1 = qq!
&nbsp;
&#187;  <a href="$vars_config{CGIURL}/ultimatebb.cgi?category=$category">
<b>$cat_name</b></a>
!;
	} else {
		$cat_line1 = '';
	}

	# now we have $cat_line1 for breadcrumb

	&LoadTemplate("public_topic_page");

	$ThisHTML = $Header;

	$ThisHTML .= &topic_top;

	$alt_color = $vars_style{AltColumnColor2};

	THISPARTICULARLINE: foreach $line (@postinfo) {
		chomp($line);
		undef($this_user_number);
		undef($un_coded);
		undef($public_name);
		undef($show_public_name);
		undef($user_status);
		undef($email_link);
		undef($AuthorExtra);
		undef($pm_link);
		undef($member_number);
		undef(@user_profile);
		undef($profile_link);
		undef($overall_rating);
		undef($total_votes);
		undef($stars);
		undef(@thisline);

		#chomp($line);

		if ($line !~ m/^Z/) { next THISPARTICULARLINE; }    #not a Z line -> corrupt thread
		chomp $line;

		# get post values
		@thisline = split (/\|\|/, $line);

		#use Data::Dumper;
		#print Dumper(\@thisline);

		# username
		$un_coded = $thisline[2];

		#print "\n$un_coded -> $thisline[2]!\n";

		# public name
		#chomp($thisline[10]);
		if ($thisline[10]) {
			$public_name = $thisline[10];
		} else {
			$public_name = $thisline[2];
		}

		# set user number (make sure it exists, too!)
		# very old format reg/unreg check
		#unless ($thisline[8]) { $thisline[8] = "" }

		$this_user_number = &GetUserNumber($thisline[2]);
		if (($this_user_number) && ($this_user_number =~ m/^\d{8}$/)) {
			unless (-s "$vars_config{MembersPath}/$this_user_number.cgi") {
				$this_user_number = '';
				$thisline[8] = 'unreg';
			}
		} else {

			$this_user_number = '';
			$thisline[8] = 'unreg';
		}    #no user number

		#chomp($thisline[11]);
		if ($thisline[11]) {
			$this_user_number = $thisline[11];
			unless (-e "$vars_config{MembersPath}/$this_user_number.cgi") {
				$this_user_number = '';
				$thisline[8] = 'unreg';
			}
		}


		# hyphen date
		$hyphen_date = $thisline[3];

		# IP
		$ip_number = $thisline[7];


		if ((($vars_display{author_location} ne "yes") && ($vars_display{author_reg_date} ne "yes") && ($vars_display{author_post_total} ne "yes")) || (($thisline[8]) && ($thisline[8] eq 'unreg'))) {
			$ip_divider = '';
		} else {
			$ip_divider = '&nbsp;|&nbsp;';
		}

		if (($ip_number) && ($vars_misc{IP} eq 'ON')) {
			$ip_wording = "$ip_divider $vars_wordlets{ip_logged}: $ip_number";
		} elsif (($ip_number) && ($vars_misc{IP} eq 'LOGONLY')) {
$ip_wording = qq($ip_divider <sub><A HREF="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_ip&f=$forum_number&t=$topic_number&reply_num=$thisline[1]"><img src="$vars_config{NonCGIURL}/ip.gif" border="0"></A></sub>);
			
		} else {
			$ip_wording = '';
		}

		# registered?
		$is_reg = $thisline[8];
		$is_reg = "" unless $is_reg;
		chomp($is_reg) if $is_reg;

		#format date
		@datearray = split (/-/, $hyphen_date);
		chomp($datearray[2]);

		# just in case we have some really old posts that weren't Y2K-ready
		$year        = &Y2K($datearray[2]);
		$hyphen_date = "$datearray[0]-$datearray[1]-$year";
		$ThisDate    = &DateFormat($hyphen_date);

		#format time
		$FormatTime = &TimeFormat($thisline[4]);

		# grab post message
		$post_body = $thisline[6];

		# allow editing?
		$edit_link = qq(<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=edit_post&f=$forum_number&t=$topic_number&reply_num=$thisline[1]&u=$this_user_number"><img src="$vars_config{NonCGIURL}/$vars_style{edit_icon}" border="0" alt="$vars_wordlets{edit_delete_post}"></a>);


		# get user profile info- if registered
		if ($is_reg eq 'unreg') {

			if ($public_name) {
				$show_public_name = $thisline[2];
			} else {
				$show_public_name = $public_name;
			}

			$user_status   = $vars_wordlets{unregistered};
			$member_number = $rating_line = $this_icon = $profile_link = $homepage_link = $email_link = $pm_link = $direct_reply = $AuthorExtra = ""



		} else {    #it's not unreg...

			if (!$this_user_number) {

				# old post- we need to find user number
				$this_user_number = &GetUserNumber($thisline[2]);

				if ((-e "$vars_config{MembersPath}/$this_user_number.cgi") && ($this_user_number ne '')) {
					@user_profile = &OpenProfile("$this_user_number");
				} else {
					$thisline[8] = 'unreg';

					if (!$public_name) {
						$show_public_name = $thisline[2];
					} else {
						$show_public_name = $public_name;
					}

					$user_status = $vars_wordlets{unregistered};
				}

			} else {

				# already have user number
				@user_profile = &OpenProfile("$this_user_number");

				# one day, Dave will get a haircut...
			}

			foreach (@user_profile) {chomp}

			if (!$show_public_name) {
				if (!$user_profile[15]) {
					$show_public_name = $user_profile[0];
				} else {
					$show_public_name = $user_profile[15];
				}
			}

			# get custom title
			if (!$user_profile[31]) {
				$user_status = &CustomTitle($user_profile[8]);
			} else {
				$user_status = $user_profile[31];
			}

			$u             = $this_user_number + 0;                     # rid extra zeros from member no.
			$member_number = "$vars_wordlets{user_number_abbrev} $u";


			unless (exists($rate_list{$u})) {
				($overall_rating, $total_votes) = &get_rating($u);
				$rate_list{$u} = $overall_rating;
			}

			# if moderator- only list as mod if actually a mod in this forum
			if (($user_status eq "$vars_misc{ModeratorTitle}") && $Moderator) {
				if ($Moderator =~ /$this_user_number/) {
					$user_status = "$vars_misc{ModeratorTitle}";
				} else {
					$user_status = "$vars_misc{MemberTitle}";
				}
			} elsif(($user_status eq "$vars_misc{ModeratorTitle}") && !$Moderator) {
				$user_status = "$vars_misc{MemberTitle}";
			}    # end mod check

			# do some cleaning---
			$user_profile[6] =~ s/<.+?>//g;
			$user_profile[6] =~ s/<.*//g;     # delete unclosed HTML tags

			# registration date for user
			$RegDate = $user_profile[10];
			chomp($RegDate);

			if ($RegDate eq '') {
				$RegDate = "$vars_wordlets{pre_reg_date_wording}";
			} else {
				($RegMon, $RegDay, $RegYear) = split (/-/, $RegDate);
				$RegMonth = $themonths[$RegMon];
				$RegDate  = "$RegMonth $RegYear";
			}

			# author info options
			undef($post_total_line);
			undef($location_line);
			undef($regdate_line);
			@author_extra = @blank;

			if ($vars_display{author_post_total} eq 'yes') {
				$post_total_line = qq( $vars_wordlets{author_posts} <b>$user_profile[7]</b> );
				push (@author_extra, $post_total_line);
			}

			if ($vars_display{author_location} eq 'yes') {
				my $thislocation = &strip_lead_trail_space($user_profile[6]);
				if($thislocation) {
					$location_line = qq( $vars_wordlets{author_from} <b>$user_profile[6]</b> );
					push (@author_extra, $location_line);
				}
			}

			if ($vars_display{author_reg_date} eq 'yes') {
				$regdate_line = qq( $vars_wordlets{author_registered} <b>$RegDate</b> );
				push (@author_extra, $regdate_line);
			}

			if ($author_extra[0]) {
				$AuthorExtra = join ("|", @author_extra);
			} else {
				$AuthorExtra = '';
			}


			$profile_link = qq( &nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_profile&u=$this_user_number" target=_blank><img src="$vars_config{NonCGIURL}/$vars_style{profilegif}" border="0" alt="$vars_wordlets{view_profile_for} $show_public_name"></a>&nbsp;);


			if (($vars_display{EmailBlock} eq 'ON') || ($user_profile[11] eq 'no')) {
				$email_link = '&nbsp;';
			} else {

				$email_link = qq( &nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=email&ToWhom=$this_user_number" target="_blank"><img src="$vars_config{NonCGIURL}/$vars_style{mailgif}" border="0" alt="$vars_wordlets{send_email_to} $show_public_name"></a>&nbsp;);
			}

			# add signature, if necessary
			if ($thisline[12]) {

				# new format! - signature is not included in message
				if (($vars_display{AllowSignature} eq 'YES') && ($user_profile[12] ne '') && ($thisline[12] eq 'yes')) {

					if ($vars_display{AllowSignatureImage} eq 'YES') {
						$allow_images = 'ON';
					} else {
						$allow_images = 'OFF';
					}

					$user_profile[12] = &UBBCode($user_profile[12], $allow_images);
					$user_profile[12] = &Smilies($user_profile[12]) if $allow_images eq "ON";

					$post_body .= ("<p>$vars_wordlets{signature_break}</p><p>$user_profile[12]</p>");
				}


			}


		}    # if/else registered


		# message icons?
		if ($vars_display{AllowIcons} eq 'TRUE') {
			$icon_number = $thisline[9];
			if (!$icon_number) {
				$icon_number = '1';
			}
			unless (-e "$vars_config{NonCGIPath}/icons/icon$icon_number.gif") {
				$icon_number = '1';
			}
			$this_icon = qq(<img src="$vars_config{NonCGIURL}/icons/icon$icon_number.gif" border="0">);
		} else {
			$this_icon = qq(<img src="$vars_config{NonCGIURL}/posticon.gif" border="0">);
		}

		# reply with quote?
		if (($vars_misc{ReplyQuote} eq 'YES') && ($reply_restrict ne 'none') && ($this_forum[5] eq 'is') && ($stat_line[1] !~ m/X/)) {
			$direct_reply = qq( &nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=reply&f=$forum_number&t=$topic_number&replyto=$thisline[1]"><img src="$vars_config{NonCGIURL}/$vars_style{reply_with_quote_icon}" border="0" alt="$vars_wordlets{reply_with_quote}"></a>&nbsp;);
		} else {
			$direct_reply = '';
		}

		# homepage link?
		if (($user_profile[3]) && ($user_profile[3] ne "http://") && ($vars_display{homepage_icon_link} eq 'yes')) {

			# format URL if necessary
			if ($user_profile[3] !~ /^http/) { $user_profile[3] = ('http://' . $user_profile[3]); }

			$homepage_link = qq( &nbsp;<a href="$user_profile[3]" target=_new><img src="$vars_config{NonCGIURL}/$vars_style{homepage_icon}" border="0" alt="$vars_wordlets{homepage}"></a>&nbsp;);
		} else {
			$homepage_link = '';
		}

		# private message?
		unless ($vars_pm{feature} eq "off") {
			if ($user_profile[27]) {
				if (($user_profile[27] ne 'no') && ($user_status ne $vars_wordlets{unregistered})) {
					$pm_link = qq( &nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=private_message&u=$this_user_number"><img src="$vars_config{NonCGIURL}/$vars_style{priv_message}" border='0' alt="$vars_wordlets{send_private_message}"></a>&nbsp;);
				}
			} elsif ($user_status ne $vars_wordlets{unregistered}) {
				$pm_link = qq( &nbsp;<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=private_message&u=$this_user_number"><img src="$vars_config{NonCGIURL}/$vars_style{priv_message}" border='0' alt="$vars_wordlets{send_private_message}"></a>&nbsp;);
			} else {
				$pm_link = "&nbsp;";
			}    #if
		}
		else {
			$pm_link = '&nbsp;';
		}    #unless


		# user rating?
		chomp($user_profile[25]) if $user_profile[25];
		$user_profile[25] = "" unless $user_profile[25];
		$rating_line = '';
		if (($vars_display{user_ratings} ne 'off') && ($user_profile[25] ne 'no') && ($user_status ne $vars_wordlets{unregistered})) {
			if ($rate_list{$u} ne '') {

				unless (($vars_display{user_ratings} eq 'feature_top') && ($rate_list{$u} < 4)) {
					if($rate_list{$u} > 5){ $rate_list{$u} = 5; }
					if($rate_list{$u} < 1){ $rate_list{$u} = 1; }
					if($rate_list{$u} < 1){ $rate_list{$u} = 1 unless $rate_list{$u} == 0 }
					$stars       = ("user_ratings_" . "$rate_list{$u}");
					$rating_line = qq!<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_profile&u=$this_user_number">$vars_wordlets{member_rated}</a>:<br /><a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_profile&u=$this_user_number"><img src="$vars_style{$stars}" border="0"></a>!;
				} else {
					$rating_line = qq!<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_profile&u=$this_user_number">$vars_wordlets{rate_member}</a>!;
				}
			} else {
				$rating_line = qq!<a href="$vars_config{CGIURL}/ultimatebb.cgi?ubb=get_profile&u=$this_user_number">$vars_wordlets{rate_member}</a>!;
			}

		} else {

			# ratings off!
			$rating_line = '';
		}

		$ThisHTML .= &topic_row;

	}    # end post loop

	$ThisHTML .= &topic_bottom;
	$ThisHTML .= $Footer;


	# do file name
	if ($page_number eq '1') {
		$page_name = "$topic_number";
	} else {
		$page_name = "$topic_number-$page_number";
	}


	# is directory created?
	unless (-d "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path") {

		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files", 0777);
		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums", 0777);
		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/Forum$in{f}", 0777);
		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path", 0777);
		chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files");
		chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums}");
		chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/Forum$in{f}");
		chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path");
	}


	unless (-w "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path/$page_name.cgi") {
		unlink "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path/$page_name.cgi";
	}

	&WriteFileAsString("$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/forums/$exact_path/$page_name.cgi", $ThisHTML);

	# more pages in topic to create?
	#if ($ContinueAt ne '') {
	#	&create_topic("$in{f}", "$topic_number", "$ContinueAt", "$NextPage");
	#}

}    # end create_topic

sub grab_last_numbers {
	local (@info);
	if (-e "$vars_config{NonCGIPath}/$exact_path/lastnumber.file") {
		@info = &OpenFileAsArray("$vars_config{NonCGIPath}/$exact_path/lastnumber.file");
	} else {
		@info = ("0", "0", "0");
	}

	return (@info);
}    # end grab_last_numbers sr

sub append_index {
	local ($getkey, $index_file, $shrunk, $index_line, %daily_date_time);
	local (*FILE);

	# sr parameters
	# $_[0] : forum number
	# $_[1] : topic number
	# $_[2] : forum permissions (check to see if private)
	# $_[3] : post number

	# only index if search is ON
	unless ($vars_search{AllowSearch} eq 'FALSE') {

		# index file to update will depend on index method...
		if ($vars_search{IndexMethod} eq 'ONEFILE') {
			$index_file = "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/forumindex.cgi";
		} else {
			$index_file = "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/forumindex$_[0].cgi";
		}

		# clean fields
		$shrunk = &indexify("$message");
		$in{topic_subject} =~ s/\|/&#0124;/sg;
		$pubname =~ s/\|/&#0124;/sg;


		# assemble index line
		$index_line = ("$_[0]" . "|" . "$_[1]" . "|" . "$_[3]" . "|" . "$GotTime{HyphenDate}" . "|" . "$in{topic_subject}" . "|" . "$shrunk");

		# append index file
		mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/search_index", 0777); #jic
		&AppendFileAsString($index_file, "$index_line\n");
	}    # if search is activated


	# update daily index
	unless ($_[2] eq 'private') {

		# delete old daily indices
		&clean_dailies;

		undef(%daily_date_time);

		if (-s "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/daily_index-$GotTime{LastLoginJulianDATE}-main.cgi") {

			# whoops, there's another!
			eval { require "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/daily_index-$GotTime{LastLoginJulianDATE}-main.cgi"; };

			if ($@) {
				unlink("$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/daily_index-$GotTime{LastLoginJulianDATE}-main.cgi");
				undef(%daily_date_time);
			}

		}

		# print to daily file
		my $f = sprintf("%4d", $_[0]);
		$f =~ tr/ /0/;
		my $daily_key = ("$f" . "a" . "$_[1]");

		# set hash values
		$daily_date_time{$daily_key} = "$GotTime{LastLoginJulian}";

		unless (-d "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index") {
			mkdir("$vars_config{NonCGIPath}/cache-$cache_cookie/search_index", 0777);
			chmod(0777, "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index");
		}

		&WriteHashToFile("$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/daily_index-$GotTime{LastLoginJulianDATE}-main.cgi", "daily_date_time", \%daily_date_time);

		# unlink file from cache
		if (($vars_misc{use_cache} ne 'no') && (-e "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/misc/ubb_daily_topics.cgi")) {
			unlink "$vars_config{NonCGIPath}/cache-$cache_cookie/ubb_files/misc/ubb_daily_topics.cgi";
		}

	}    # end update daily index

}    # end append_index

sub indexify {
	$_[0] =~ s/\[.+?\]//isg;
	$_[0] =~ s/------------------(.*)//isg;                                                                                             # old format sig break
	$_[0] =~ s/<.+?>//sg;
	$_[0] =~ s/\|/&#0124;/sg;
	$_[0] =~ s/\b(that|this|it|the|as|a|an|will|for|of|but|in|there|could|should|would|can|be|is|are|to|was|with|because|how)\b//isg;
	$_[0] =~ s/\s//sg;
	$_[0] =~ s/(\||\?|\!|\^|\"|--)//sg;
	$_[0] = substr($_[0], 0, 210);
	return ($_[0]);
}    #end Indexify


sub clean_dailies {    # Thanks Graeme for this cleanup code
	local (*FILE);
	local ($j, $dfile, $dfiledate, @dailies);
	opendir(FILE, "$vars_config{NonCGIPath}/cache-$cache_cookie/search_index");
	@dailies = grep(/^daily_index\-.*/, readdir(FILE));
	closedir(FILE);

	foreach $dfile (@dailies) {
		($j,         $dfiledate) = split (/\-/, $dfile);
		($dfiledate, $j)         = split (/\-/, $dfiledate);
		if ($dfiledate < $GotTime{LastLoginJulianDATE}) {
			unlink("$vars_config{NonCGIPath}/cache-$cache_cookie/search_index/$dfile");
		}
	}
}    # END SR

sub promo {
	local ($length, $revised, $this_length, $total_length);
	$_[0] =~ s/<.+?>//sg;
	$length = length($_[0]);
	if ($length > 200) {
		$total_length = 0;
		@words = split (/\s/, $_[0]);
		$_[0] = '';

		for (@words) {
			$this_length  = length($_);
			$total_length = $this_length + $total_length;

			if ($total_length < 200) {
				$_[0] .= " $_";
			} else {
				last;
			}

		}

		$_[0] .= '&nbsp;...';
	}

	#remove whitespace at begin and end of string
	$_[0] = &strip_lead_trail_space($_[0]);
	return ($_[0]);

}    # end promo

sub excess_smilies_check {
	my $max_smilies  = 8;
	my $smilie_count = 0;
	while ($_[0] =~ m/\<IMG.+?SRC/gi) { $smilie_count++; }
	if ($smilie_count > $max_smilies) { &StandardHTML("$vars_wordlets_err{excess_images}"); }
}    # end smilie check

1;
