#!/usr/bin/perl

# comment out this line when installation is successful:
use CGI::Carp 'fatalsToBrowser';

###### WebBBS 5.xx Addon
my $thismod = "RSS Feed";
my $byTarty = "tarty.webdesignassoc.com";
my $LstModT = "2006-3";
######
# Description:
#  Generate RSS 1.0 (news) feed from your forum(s).
#  Can be used for single or multiple forums.
#  Visitors may choose the numbers of items and the length 
#   of item description to display in their news reader.
#  Display certain poster names as anonymous or skip their posts.
#  Admin & visitors can display the feed on own & visitors' web pages.
######
# Estimated Installation Level/Time: Easy/10 minutes.
# File to Create/Edit: rss.pl (this file)
# Installation:
# 0. Most users have $DBMType = 0 in your webbbs_settings.pl. 
#    If that is not your setting, get instruction from Tarty 
#    and modify this script. 
# 1. Ensure Line 1 -- #!/usr/bin/perl -- of this file is the 
#    same as that in your webbbs_config.pl.
# 2. Define variables of this script. 
# 3. Save changes made and upload the file in ASCII mode to 
#    the same directory as your webbbs_config.pl.
# 4. CHMOD the file to 755 (executable.)
# 5. Point your browser to it, with "?debug" appended to the 
#    URL, and follow the on-screen insturctions to proceed.
######
# Demo: http://tarty.webdesignassoc.com/cgi-bin/rss.pl?build
# History:
#  2004-11 Created script
######
# Specify the location of your webbbs_settings.pl file:

require "/var/www/cgi-bin/webbs512t/webbbs_settings.pl";

######
# Define forum(s). Format:
#  "forum-number" => ["data-directory", "forum-url", "forum-name"] 
#  (ie $dir, $cgiurl, $boardname from the webbbs_config.pl)
# Do this as many times for as many forums as you want, separating 
#  each with a comma. For single forum use, set up one script for each 
#  forum and define one forum -- "a" => [...] only -- in each script.

my %webbbs_dirs = (
#	"a" => [
#"/home/wfcomics/www/comicbookclassifieds.com/bbdata1",
#"http://www.comicbookclassifieds.com/",
#"ComicBookClassifieds.com"]
	"a" => [
$dataDir."/brereton",
$rootUrl."/boards/brereton/",
"Dan Brereton's Message Board"],
);

######
# Basic configuration is done. Leave the following variables as-is 
# until you get the script up & running, and then edit them if you like.
######
# Info about your forum/site *as a whole*. 
# optional siteicon if used, w x h = 88 x 31

my $sitetitle = "World Famous Comics Community: Dan Brereton's Message Board";
my $siteURL = "http://$ENV{'HTTP_HOST'}";
my $sitedesc = "Message board for comic book creator Dan Brereton!";
my $siteicon = "http://$ENV{'HTTP_HOST'}/i/icon88x31.gif";
my $lang = "";			# language used. Eg: $lang = "en-us";

###### Testing. REMOVE these if Tarty forgets to:
#$dataDir = "";
#$forumsUrl = "";
#require "settings.pl";
#my %webbbs_dirs = (
#	"a" => [
#"$dataDir/webbbs",
#"$forumsUrl/index.cgi",
#"Tarty's Message Board"],
#	"b" => [
#"$dataDir/test",
#"$forumsUrl/test.pl",
#"Test Me Board"],
#	"c" => [
#"$dataDir/mods",
#"$forumsUrl/mods.pl",
#"WebBBS Mods/Addons"]
#);
###### END testing

# News feed options, can be left as-is. 

my $ItemsDefault = 50;		# items to display by default
my $UseDescs = 1;		# 1=show item description; 0=show Not;
my $DescLengthDefault = 100;	# suggested 100 (characters)

# Mask these posters' posts. Eg: 
#  @hidePosters = ('fish\'n chips','Admin','Tarty');
#  $skipTheirPosts, 0=display their names as anonymous; 1=skip their posts 

my @hidePosters = ();
my $skipTheirPosts = 0;

# $AllowUserPrefs is a variable from webbbs_settings.pl. If you want the 
# same setting for your forum & your news feed, comment out the one here. 
# Otherwise, redefine it here. 1=allow users to customize feed; 0=allow not

my $AllowUserPrefs = 1;

# if AllowUserPrefs is enabled..
# ..set the maximum item description to display in the feed. 
# This is in case you want people informed of new posts, 
# but want them to come to the forum to read the posts.

my $DescLengthMax = 200;		# 0=no limit (allow full text)

# ..and set the instructions/info to print at the top of Format Feed page

my $BuildFeedMsg = qq~By default, the feed will display <b>$ItemsDefault</b> 
items and the first <b>$DescLengthDefault</b> characters of each item. 
Below is a <a href="#prevu">preview</a> of how the feed will appear. If 
you are happy with the content and format, <a href="#url">copy and paste 
the URL</a> to your RSS (news) reader. Otherwise, use the form below to <a 
href="#format">format the feed</a> with the information you want to appear 
in your news reader. If you like, you may <a href="#jsfeed">include the 
feed on your web page</a>. Instructions are shown below.~;

###### look and feel of the feed when *previewed and js-parsed*. 
###### Can be left as-is. 
# Below is the html that define the look and feel of the news items. 
# Edit them only IF you know what you are doing. (To alter the look of the 
# feed *as a whole*, edit sub template_rss2html, the last sub of this script.) 
######
# Each news item has 7 elements: 
#  %title% %url% %desc% %poster% %date% %newOpenCode% %newCloseCode%
# Use html tags & css classes to have them displayed the way you like.
# Omit those elements you don't want shown. 
# Eg.1 uses css classes:
#  my $item_html = qq~
#  <div class="item">
#  <div class="itemtitle">%newOpenCode%%title%%newCloseCode%</div>
#  <div class="itemdesc">%desc%
#  <span class="itemlink"><a href='%url%'>Read more</a>
#   | <a href='%url%' target='_blank'>Open in browser</a></span>
#  <span class="itemdtls">by %poster% on %date%</span></div>
#  </div>~;
# Eg.2 uses bullet points; links title to url; doesn't show date:
#  my $item_html = qq~
#  <li><div>%newOpenCode%<a href="%url%"><b>%title%</b></a></div>
#  <div>%desc%&nbsp;- <em>%poster%</em>%newCloseCode%</div></li>~;
# Eg.3 same as Eg.2, but shows item description as mouseover preview
#  my $item_html = qq~
#  <li><div>%newOpenCode%<a href="%url%" title="%desc%"><b>%title%</b></a>&nbsp;- 
#  <em>%poster%</em>%newCloseCode%</div></li>~;

my $item_html = qq~
<div style="padding:10px;">
<div style="font:bold 14px Arial; color:black; background:white;
 padding-left:10px; margin-bottom:5px;">%newOpenCode%
%title%%newCloseCode%</div>
<div style="font:normal 13px Arial;color:black; background:white;
 padding-left:10px; margin-bottom:15px; clear:both;">%desc%
<span style="font:normal 13px Arial;color:blue; background:white;
 padding-left:10px; margin-top:3px; clear:both; float:left;">[<a href="%url%">read more</a>]</span>
<span style="font:normal 11px Arial;color:silver; background:white;
 padding-right:5px; margin-top:5px; float:right;">by %poster% on %date%</span>
</div>
</div>~;

# Each summary item has 4 elements:
#  %boardurl% %boardname% %ttlmsgs% %newCount%
# The values defined below show it like this :
# boardname  total-posts (new-post-count) 
# Eg: Test Me Board  1204 (5)

my $newCount = qq~&nbsp;(<span style="color:#cc0000;"><b>%newCount%</b></span>)~;

my $item_summ_html = qq~
<div style="padding-left:20px;">
<div padding-left:10px; margin-bottom:5px;">
<span style="font:bold 14px Arial; color:black; background:white;"><a 
href="%boardurl%" target="_blank">%boardname%</a></span>&nbsp; %ttlmsgs%
%newCount%</div>
</div>~;

######
# NO need to change anything below
######

my $item_rss = qq~
<item rdf:about="%url%">
<title>%title%</title>
<link>%url%</link>
<description>%desc%</description>
<dc:creator>%poster%</dc:creator>
<dc:date>%date%</dc:date></item>\n~;

my $thisURL = "http://$ENV{'HTTP_HOST'}$ENV{'SCRIPT_NAME'}";
my $fetch_posts = $ItemsDefault;
my $DescLength = $DescLengthDefault if ($UseDescs);
my $bbtitle = "$sitetitle :: $thismod"; 
my ($debug,$debuginfo,$bbmeta,$bbmenu,$bbmain) = (0,'','','','');
my $html_page;
my @pairs = ();
my %INPUT = ();
if ($ENV{'QUERY_STRING'}) { @pairs = split(/&/,$ENV{'QUERY_STRING'}); }
elsif ($ENV{'CONTENT_LENGTH'}) {
	read(STDIN, my $buffer, $ENV{'CONTENT_LENGTH'});
	push(@pairs, split(/&/, $buffer));
}
foreach (@pairs) {
	my ($name, $value) = split(/=/, $_);
	$value =~ tr/+/ /;
	$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
	$INPUT{$name} = $INPUT{$name} ? $INPUT{$name}. ",". $value : $value;
}

if (($ENV{'QUERY_STRING'} =~ /debug/i) || $INPUT{'debug'}) { 
	$bbtitle .= " :: Debug"; $debug = 1; 
}
if ( ($ENV{'QUERY_STRING'} =~ /build/i) || $INPUT{'generate'} 
 || ($ENV{'QUERY_STRING'} =~ /js/i) || ($ENV{'QUERY_STRING'} =~ /ssi/i) ) {
	require $webbbs_basic;
	%Cookie_Decode_Chars = ( 
'\+',' ','\%3A\%3A','::','\%26','&','\%3D','=', 
'\%2C',',','\%3B',';','\%2B','+','\%25','%');
	$DateConfig = "%DY%, %dy% %MO% %YR%, at %hr%:%mn% %am%"
	 unless $DateConfig;
	$html_page = 1;
}
if ($NM_Telltale) {
	$Cleaned_NM_Telltale = $NM_Telltale;
	$Cleaned_NM_Telltale =~ s/([\[\]\(\)\\\*\+\?\\\|])/\\$1/g;
}
if ($AllowUserPrefs) {
	if ($INPUT{'num'} > 0) { $fetch_posts = $INPUT{'num'}; }
	elsif ($ENV{'QUERY_STRING'} =~ /^(\d+)$/) { $fetch_posts = $1; }
	$DescLength = $INPUT{'desc'} if (defined($INPUT{'desc'}) && $UseDescs);
	$DescLength = $DescLengthMax if ( ($DescLengthMax > 1)
	 && ($DescLength > $DescLengthMax) );
}

BEGIN { use Benchmark; $t0 = new Benchmark; } 
END { 
	$t1 = new Benchmark;
	print qq~<div style="text-align:center;"><tt>[the code took: ~,
timestr(timediff($t1,$t0))," secs]</tt></div>" if $debug;
}

use Fcntl; 
BEGIN { @AnyDBM_File::ISA = qw (DB_File GDBM_File SDBM_File) } 
# HACK - re-enable other DBs
if (eval "require DB_File") { @ISA = ('DB_File'); } 
else { use AnyDBM_File; }
#use DB_File;

umask (0111);

my ($dir, $boardurl, $boardname);
my (%truval,%mtime,%title,%poster,%newpost,%webbbs);
my ($prevdate,$Seq,$news_items,$feed) = (0,'','','');
foreach (sort keys %webbbs_dirs) {
	$dir = $webbbs_dirs{$_}[0];
	$boardurl = $webbbs_dirs{$_}[1];
	$boardname = $webbbs_dirs{$_}[2];
	&QuickInfoPlus;
}
if (%truval) {
	my $Count = 0;
	foreach $key (sort {$mtime{$b}<=>$mtime{$a}} keys %truval) {
		$Count++;
		last if ($Count > $fetch_posts);
		# strip subject of html tags
	$title{$key} =~ s/<[^>]*\s+ALT\s*=\s*"(([^>"])*)"[^>]*>/*$1*/ig;
		$title{$key} = &html_encode($title{$key});
#		$key =~ s/\&/\&amp;/g;		# escape "&" in url
		my ($description,$item);
		if ($UseDescs && ($DescLength > 0)) {
			if (open (WEBBBS,"$webbbs{$key}")) {
#			 || die "Can't open $webbbs{$key}: $!\n";
				binmode(WEBBBS);
#				my @message = <WEBBBS>;
				my @message;
				while (<WEBBBS>) {
					# strip post of quoted text
					next if /^<([^>])*>$AutoQuoteChar[^ ]*(.*)/;
					push (@message,$_);
				}
				close (WEBBBS);
				$description = join(' ',@message);
				undef @message;
				$description =~ s/\n/ /g;
				$description =~ s/.*LINKURL>[^ ]*(.*)/$1/i;
				$description =~ s/<([^>])*>//g;
				$description =~ s/\s+/ /g;
				$description =~ s/^\s*//;
				$description =~ s/\s*$//;
				$description = substr($description,0,$DescLength) . ".."
				 if (($DescLength > 1) && (length($description) > $DescLength));
				$description = &html_encode($description);
			}
		}
		$poster{$key} = &html_encode($poster{$key});
		unless ($html_page) {
			$Seq .= qq~\n<rdf:li rdf:resource="$key" />~;
			$mtime{$key} = &PrintDate_xml($mtime{$key});
			$item = $item_rss;
		} else {
			$mtime{$key} = &PrintDate($mtime{$key});
			$item = $item_html;
			if ($newpost{$key}) {
				$item =~ s/%newOpenCode%/$NewOpenCode /g;
				$item =~ s/%newCloseCode%/ $NewCloseCode/g;
			} else {
				$item =~ s/%newOpenCode%//g;
				$item =~ s/%newCloseCode%//g;
			}
		}
		$item =~ s/%title%/$title{$key}/g;
		$item =~ s/%url%/$key/g;
		$item =~ s/%desc%/$description/g;
		$item =~ s/%poster%/$poster{$key}/g;
		$item =~ s/%date%/$mtime{$key}/g;
		$news_items .= $item;
	}
}
if ($html_page) {
	&template_rss2html;
	if ( ($ENV{'QUERY_STRING'} =~ /js/i)
	 || ($ENV{'QUERY_STRING'} =~ /ssi/i) ) {
		print "Content-type: text/html\n\n";
		if ($ENV{'QUERY_STRING'} =~ /js/i) {
			$feed =~ s/\n/ /g;
			$feed =~ s!'!\&#39;!g;
			print "document.write('$feed');"; 
		} else { print $feed; }
		exit;
	}
	$bbmenu = qq~<a href="$thisURL?debug">Return to Debug page</a>~ if $debug;
	$bbmeta = qq~
<script type="text/javascript">
<!--
function copyit(theField) {
//	var tempval = eval("document."+theField)
// document.getElementById('remember').
	var tempval = eval("document.getElementById(theField)")
	tempval.focus()
	tempval.select()
	therange = tempval.createTextRange()
	therange.execCommand("Copy")
}
//-->
</script>~;
	if ($INPUT{'generate'}) {
		$bbmain = "You have chosen to have <b>$fetch_posts</b> 
items and the";
		if ( ($DescLengthMax == 0) && ($DescLength == 1) ) {
			$bbmain .= " <b>full text</b>"; 
		} else { 
			$bbmain .= " first <b>$DescLength</b>"; 
			$bbmain .= " (maximum)" if (($DescLengthMax > 1)
			 && ($DescLength == $DescLengthMax)); 
			$bbmain .= " characters";
		}
		$bbmain .= qq~ of each item displayed in 
your RSS (news) reader. [<a href="$thisURL?build">Reset to default</a>]~;
	} else {
		$bbmain = qq~<a id="top"></a>\n~;
		$bbmain .= ($AllowUserPrefs)
		 ? "$BuildFeedMsg" 
		 : qq~Below is a <a href="#prevu">preview</a> of the RSS 
(news) feed. <a href="#url">Copy and paste the URL</a> to your news reader 
to add the feed for this site.~;
	}
	$bbmain .= qq~
<a id="prevu"></a>
<h4>1. Preview the feed</h4>
<blockquote>
$feed
<div style="text-align:right;"><a href="#top">Top</a></div></blockquote>
<a id="url"></a>
<h4>2. Copy and paste this URL to your RSS reader</h4>
<form action="">
<blockquote>
<div>
<input type="button" value="Press to copy this URL"
 onclick="copyit('select1');"/><br/>
<textarea id="select1" rows="2" cols="60">
$thisURL~;
	my $qstring = "";
	if ($AllowUserPrefs) {
		if ($INPUT{'num'} || $INPUT{'desc'}) {
			$qstring .= "num=$INPUT{'num'}&" if (defined($INPUT{'num'}));
			$qstring .= "desc=$INPUT{'desc'}&" if (defined($INPUT{'desc'}));
			chop ($qstring);
			$qstring =~ s/\&/\&amp;/g;
			$bbmain .= "?$qstring</textarea><br/>
and paste it to your RSS reader. [";
			$bbmain .= qq~<a 
 href="http://www.feedvalidator.org/check.cgi?url=$thisURL?$qstring" 
 target="_blank">Validate the feed</a> | ~ if ($debug);
			$bbmain .= qq~<a 
 href="$thisURL?build~;
			$bbmain .= "&amp;debug" if ($debug);
			$bbmain .= qq~">Restore default values</a>]
<div style="text-align:right;"><a href="#top">Top</a></div>
</div>
</blockquote>
</form>
<h4>3. Feed it again?</h4>
<form method="post" action="$thisURL">
<blockquote>~;
		} else { 
			$bbmain .= qq~</textarea><br/>
and paste it to your RSS reader.
<div style="text-align:right;"><a href="#top">Top</a></div>
</div>
</blockquote>
</form>
<a id="format"></a>
<h4>3. Customize the feed?</h4>
<form method="post" action="$thisURL">
<blockquote>
<div>Select the desired options and use the "Generate URL" 
button to get the URL of the feed.</div>~;
		}
		$bbmain .= qq~
<div>
<input type="hidden" name="debug" value="1"/>~ if ($debug);
		my ($chan0,$chan1,$chan2,$summ0,$summ1);
		if ($INPUT{'chan'} eq "n") { $chan0 = " checked='checked'"; }
		elsif ($INPUT{'chan'} eq "y") {	$chan1 = " checked='checked'"; }
		else { $chan2 = " checked='checked'"; }
		if ($INPUT{'summ'} eq "y") { $summ1 = " checked='checked'"; }
		else { $summ0 = " checked='checked'"; }
		$bbmain .= qq~
<p><b>Display information about the publisher of the feed?</b><br/>
<input type="radio" name="chan" value="y"$chan1 />title and description&nbsp; 
<input type="radio" name="chan" value="title"$chan2 />title only&nbsp;
<input type="radio" name="chan" value="n"$chan0 />do not display anything</p>
<p><b>Show summary (total post and new post count?)</b> [for Javascript only. See (4) below.]<br/>
<input type="radio" name="summ" value="y"$summ1 />yes&nbsp; 
<input type="radio" name="summ" value="n"$summ0 />no</p>
<p><b>How many items to display?</b> (default: $ItemsDefault)<br/>
<input type="text" name="num" size="10" value="$fetch_posts"/>~;
		if ($UseDescs) {
			$bbmain .= "</p>
<p><b>Show item description? How many characters?</b> (default: $DescLengthDefault";
			$bbmain .= ", Maximum: $DescLengthMax" if ($DescLengthMax > 1);
			$bbmain .= qq~)<br/>
<input type="text" name="desc" size="10" value="$DescLength"/>
(0=no description~;
		 	$bbmain .= ", 1=full text" unless ($DescLengthMax > 1);
			$bbmain .= ", n&gt;1=first n characters)";
		}
		$bbmain .= qq~</p>
<p>
<input type="submit" name="generate" value="Generate URL" /></p>~;
		$qstring .= "&amp;" if ($qstring);
		$qstring .= "chan=$INPUT{'chan'}&amp;"
		 if (defined($INPUT{'chan'}));
		$qstring .= "summ=$INPUT{'summ'}&amp;"
		 if ($INPUT{'summ'} eq "y");
	}
	my $thisURL = $thisURL;
	$thisURL .= "?$qstring" . "js=1";
	$bbmain .= qq~
<div style="text-align:right;"><a href="#top">Top</a></div>
</blockquote></form>
<a id="jsfeed"></a>
<h4>4. Include the feed on your web page?</h4>
<form action="">
<blockquote>
<div>It is possible to include the feed on a page on your web site. 
The feed can be placed where you desire on a page and is automatically 
updated as $sitetitle is updated.<br/>

<input type="button" value="Press to copy this JavaScript" onclick="copyit('select2');"/><br/>
<textarea id="select2" rows="4" cols="60">
&lt;script type="text/javascript" src="$thisURL"&gt;&lt;/script&gt;
</textarea><br/>
and paste it to your web page. [<a href="$thisURL">Preview result</a>~;
	if ($debug) {
		$thisURL =~ s/js=1/ssi/g;
		$bbmain .= qq~ | <a href="$thisURL">Preview SSI result</a>~;
	}
	$bbmain .= qq~]
<div style="text-align:right;"><a href="#top">Top</a></div>
</div>
</blockquote></form>~;
	&template;
}
&template_rss;
exit;

# get posts
sub QuickInfoPlus {
	my @messages = ();
	undef %MessageList;	# avoid untie problems with prev DBM.
	tie (%MessageList,'AnyDBM_File',"$dir/messagelist",O_RDONLY,0666)
	 || die("Could not open database file $dir/messagelist: $!\n");
	@messages = keys %MessageList;
	my @sortedmessages = (sort {$b<=>$a} @messages); # reverse sort
	@messages = ();
	$debuginfo .= "* $boardname, $dir\n$boardurl\n" if ($debug);
	if ( ($ENV{'QUERY_STRING'} =~ /js/i)
	 || ($ENV{'QUERY_STRING'} =~ /ssi/i) ) {
		my $TotalMessages = scalar @sortedmessages;
		my $lastmessage = $sortedmessages[0];
		%Cookies = ();
		&GetCookieLite($boardname);		# read cookie
		if ($INPUT{'summ'} eq "y") {
			my $nc = "";
			if ($Cookies{'lastmessage'}
			 && ($Cookies{'lastmessage'} < $lastmessage)) {
				my $NewCount = 0;
				my $startcount = $Cookies{'lastmessage'} + 1;
				foreach ($startcount..$lastmessage) {
					$NewCount++ if ($MessageList{$_} > 0);
				}
				if ($NewCount > 0) {
					$nc = $newCount;	# template
					$nc =~ s/%newCount%/$NewCount/g;
				}
			}
			my $item = $item_summ_html;
			$item =~ s/%boardurl%/$boardurl/g;
			$item =~ s/%boardname%/$boardname/g;
			$item =~ s/%ttlmsgs%/$TotalMessages/g;
			$item =~ s/%newCount%/$nc/g;
			$summ_items .= $item;
		}
	}
	if ($boardurl && $fetch_posts) {
		if ($html_page) {
			$DefaultType = $Cookies{'listtype'} || $DefaultType;
			$UseFrames = $Cookies{'UseFrames'} || $UseFrames;
		}
		$boardurl .= (!$UseFrames || ($UseFrames eq "No")) ? "?read="
		 : "?review=";
		my $Count = 0;
		foreach $message (@sortedmessages) {
			last if ($Count == $fetch_posts);
			($date,$sub,$poster,undef) = split(/\|/,$MessageList{$message});
			if ($date < $prevdate) {
$debuginfo .= "\$date < \$prevdate : $date < $prevdate --Abort" if ($debug);
				last;
			}
$debuginfo .= "\$date >= \$prevdate & \$Count+1 <= \$fetch_posts : $date >= $prevdate or $Count+1 <= $fetch_posts? --Yes\n" if ($debug);
			$sub =~ s/&pipe;/\|/g;
			next if ( ($sub eq "(Message Deleted by Poster)")
			 || ($NM_Telltale && ($sub =~ / $Cleaned_NM_Telltale$/)) );
			$poster =~ s/&pipe;/\|/g;
			my $skipthis = 0;
			foreach (@hidePosters) { 
				if ($poster =~ m!$_!) { 
					if ($skipTheirPosts) { $skipthis = 1; }
					else { $poster = "(anon.)"; }
					last; 
				}
			}
			next if ($skipthis);
			$Count++;
			my $FILE = "$boardurl$message";
			$FILE .= "#$message" if ($DefaultType =~ /Guestbook-Style/);
			$truval{$FILE} = 1;
			$mtime{$FILE} = $date;
			$title{$FILE} = $sub;
			$poster{$FILE} = $poster;
			$newpost{$FILE} = 1 if ($Cookies{'lastmessage'}
			 && ($Cookies{'lastmessage'} < $message)); 
			my $subdir = "$dir/bbs" . int($message/1000);
			$webbbs{$FILE} = "$subdir/$message";
$debuginfo .= "$Count (\$message,\$date) = ($message,$date)\n" if ($debug);
		}
		$prevdate = $date;
	}
	untie %MessageList; 
	return 1;
}

sub GetCookieLite {
	local($cookie_name) = @_;
	local($cookie,$value);
	if ($ENV{'HTTP_COOKIE'}) {
		foreach (split(/; /,$ENV{'HTTP_COOKIE'})) {
			($cookie,$value) = split(/=/);
			foreach $char ('\+','\%3A\%3A','\%26','\%3D','\%2C','\%3B','\%2B','\%25') {
		$cookie =~ s/$char/$Cookie_Decode_Chars{$char}/g;
		$value =~ s/$char/$Cookie_Decode_Chars{$char}/g;
			}
			if ($cookie eq $cookie_name) {
				$Cookies{$cookie} = $value; last;
			}
		}
	}
	if ($Cookies{$cookie_name}) {
		foreach (split(/&/,$Cookies{$cookie_name})) {
			($cookie,$value) = split(/::/);
			foreach $char ('\+','\%3A\%3A','\%26','\%3D','\%2C','\%3B','\%2B','\%25') {
				$value =~ s/$char/$Cookie_Decode_Chars{$char}/g;
			}
			$Cookies{$cookie} = $value;
		}
	}
	delete ($Cookies{$cookie_name});
	$Cookies{'lastmessage'} = $Cookies{'m1'} if ($Cookies{'m1'});
	$Cookies{'listtype'} = $Cookies{'tp'} if ($Cookies{'tp'});
	$Cookies{'UseFrames'} = $Cookies{'uf'} if ($Cookies{'uf'});
}

# escape characters illegal in xml
sub html_encode {
	local $_ = $_[0] || '';
#	s!\&!\&amp;!g;
	s!\"!\&quot;!g;
	s!\<!\&lt;!g;
	s!\>!\&gt;!g;
	s!'!\&#39;!g;
	s!\&#147;!\&quot;!g;		# open-quotation mark
	s!\&#148;!\&quot;!g;		# close-quotation mark
	return $_;
}

# convert date to xml format, DO NOT change anything below
sub PrintDate_xml {
	return $_[0] unless ($_[0] =~ /^\d+$/);
#	my (undef,$min,$hour,$mday,$mon,$year,undef) =
#	 localtime($_[0]+($HourOffset*3600));
	my ($min,$hour,$mday,$mon,$year) =
	 (localtime($_[0]+($HourOffset*3600)))[1,2,3,4,5];
	$mon++;
	foreach ($min,$hour,$mday,$mon) { $_ = "0$_" if ($_ < 10); }
	$year += 1900;
	my $datestring = "$year-$mon-$mday" . "T$hour:$min+00:00";
	return $datestring;
}

sub SpawnDebugger {
	$bbmenu .= qq~<a href="#next">What's next</a> | <a
 href="#xml">XML of the feed</a>~;
	$bbmain = qq~<a id="next"></a><pre>Things to do next:
1. <a href="http://www.feedvalidator.org/check.cgi?url=$thisURL"
 target="_blank">Validate your feed</a>
2. Add the feed to your news reader. Copy and paste this URL to it:
   <tt>$thisURL</tt>
3. Advertise your feed. Add to your webpage an XML button linked to this script 
   with "?build" appended to the URL. Example:
   <tt>&lt;a href="$thisURL?build"&gt;&lt;img 
 src="http://$ENV{'HTTP_HOST'}/xml.gif" border="0" width="36" height="14" alt="RSS feed for this site"&gt;&lt;/a&gt;</tt>
4. You can display the feed on your other pages by calling this script from an SSI tag.
   On most systems, a tag such as either of these should work:
   <tt>&lt;!--#exec cgi="$ENV{'SCRIPT_NAME'}<b>?ssi</b>"--&gt;</tt>
   <tt>&lt;!--#include virtual="$ENV{'SCRIPT_NAME'}?<b>ssi</b>&num=10&amp;desc=200"--&gt;</tt>
5. Or, you (and your users) can display the feed on your other pages (and on their web 
   page) by calling this script from a JavaScript tag.
   See <a href="$thisURL?build#jsfeed">"Preview feed" page</a> (<a href="$thisURL?build&debug#jsfeed">Debug mode</a>).<hr />
Feed: <b>$fetch_posts</b> items~;
	$bbmain .= ", description <b>$DescLength</b> characters each" if ($UseDescs);
	$feed =~ s/</\&lt;/g;
	$feed =~ s/>/\&gt;/g;
	$bbmain .= qq~
Debug info:
$debuginfo<hr/>
<a id="xml"></a>
XML of the feed:
$feed</pre>~;
	&template;
}

sub template_rss {
	my $sitedesc = &html_encode($sitedesc);
	my $bbhead = qq~<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns="http://purl.org/rss/1.0/"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel rdf:about="$siteURL/">
    <title>$sitetitle</title>
    <link>$siteURL/</link>
    <description>$sitedesc</description>~;
	$bbhead .= qq~
    <language>$lang</language>~ if $lang;
	$bbhead .= qq~
    <image rdf:resource="$siteicon" />~ if ($siteicon);
	$bbhead .= qq~
    <items>
      <rdf:Seq>$Seq
      </rdf:Seq>
    </items>
  </channel>~;
	$bbhead .= qq~
  <image rdf:about="$siteicon">
    <title>$sitetitle</title>
    <url>$siteicon</url>
    <link>$siteURL/</link>
  </image>~ if ($siteicon);
	my $bbfoot = "
</rdf:RDF>";
	$feed = "$bbhead\n$news_items$bbfoot"; 
	&SpawnDebugger if ($debug);
	print "Content-type: application/rdf+xml\n\n"; 
	print $feed; 
}

sub template {
	my $title = $bbtitle;
	$title =~ s/<([^>]|\n)*(>|$)/ /g;
	my $bbhead = "<html>
<head><title>$title</title>";
	$bbhead .= "\n$bbmeta" if $bbmeta;
	$bbhead .= qq~
<style type="text/css">
body, div, span, p, input	{
	font-family: Verdana, sans-serif;
	font-size: 13px;
}
pre	{
	font-family: "courier new", courier, monospace;
	background-color: white;
	color: #333;
}
img.valid	{
	border: 0;
	width: 80px;
	height: 15px;
}
.copyright	{
	font: normal 11px Arial, sans-serif;
	background-color: white;
	color: #aaa;
	text-align: center;
}
</style></head>
<body>~;
	my $bbfoot = qq~
<a href="http://www.feedvalidator.org/check.cgi?url=$thisURL"><img
 src="/i/rss10.gif" class="valid" alt="Valid RSS" title="Valid RSS"/></a> &nbsp; 
<a href="http://validator.w3.org/check?uri=referer"><img
 src="/i/xhtml11.gif" class="valid" alt="Valid XHTML 1.1" title="Valid XHTML 1.1"/></a> &nbsp; 
<a href="http://jigsaw.w3.org/css-validator/validator?uri=$thisURL?build"><img
 src="/i/css.gif" class="valid" alt="Valid CSS" title="Valid CSS"/></a><br/>~
 if ($ENV{'HTTP_HOST'} =~ /$byTarty/);
	$bbfoot .= qq~
$thismod, by <a href="javascript:void(0);"
 onclick="window.open('http://$byTarty/');">Tarty</a>. (Last modified: $LstModT)~;
	print "Content-type: text/html; charset=utf-8\n\n";
#	print qq~<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
# "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">~;
	print qq~<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">~;
	print "
$bbhead
<div style='text-align:center;'>";
	print "<h1>$bbtitle</h1>" if $bbtitle; 
	print "<font $navbarfontspec>$bbmenu</font>" if $bbmenu;
	print "</div>";
	print "Debug info:<pre>$debuginfo</pre>" if $debuginfo;
	print "<div>$bbmain</div>
<p class='copyright'>$bbfoot</p>
</body></html>";
	exit;
}

# Below is the html that defines the look and feel of 
# the feed *as a whole* when previewed and js-parsed. Edit 
# the html & text and add in style classes if you like.
sub template_rss2html {
		## opening tag for the feed
		$feed = qq~
<div style="background:white;margin-bottom:5px;">
	~; unless ($INPUT{'chan'} eq "n") {
		## site title
		$feed .= qq~
<div style="font:bold 16px Arial;
padding:5px; margin-bottom:5px; color:white; background:#8080ff;">
$sitetitle all headlines
</div>
		~;
		## site description
		$feed .= qq~
<div style="padding:5px;">
$sitedesc
</div>
		~ if ($INPUT{'chan'} eq "y"); }
		## summary: boardname, total posts (new post count) of each board
		$feed .= "
$summ_items
		" if ($summ_items);
		## articles, and closing tag for the feed.
		$feed .= "
$news_items
</div>
		"; 
}

### EOF