D:\WEBSITES\testbed\zipped\yabb252_09_08\cgi-bin\yabb2\Sources\RSS.pl D:\WEBSITES\testbed\cgi-bin\yabb252\Sources\RSS.pl
#!/usr/bin/perl -- #!/usr/bin/perl --
# Change the shebang only if you plan to use RSS in a program of your own. # Change the shebang only if you plan to use RSS in a program of your own.
############################################################################### ###############################################################################
# RSS.pl                                                                      # # RSS.pl                                                                      #
############################################################################### ###############################################################################
# YaBB: Yet another Bulletin Board                                            # # YaBB: Yet another Bulletin Board                                            #
# Open-Source Community Software for Webmasters                               # # Open-Source Community Software for Webmasters                               #
# Version:        YaBB 2.5.2                                                  # # Version:        YaBB 2.5.2                                                  #
# Packaged:       September 30, 2012                                          # # Packaged:       September 30, 2012                                          #
# Distributed by: http://www.yabbforum.com                                    # # Distributed by: http://www.yabbforum.com                                    #
# =========================================================================== # # =========================================================================== #
# Copyright (c) 2000-2012 YaBB (www.yabbforum.com) - All Rights Reserved.     # # Copyright (c) 2000-2012 YaBB (www.yabbforum.com) - All Rights Reserved.     #
# Software by:  The YaBB Development Team                                     # # Software by:  The YaBB Development Team                                     #
#               with assistance from the YaBB community.                      # #               with assistance from the YaBB community.                      #
############################################################################### ###############################################################################
   
$rssplver = 'YaBB 2.5.2 $Revision: 1.0 $'; $rssplver = 'YaBB 2.5.2 $Revision: 1.0 $';
if ($action eq 'detailedversion') { return 1; } if ($action eq 'detailedversion') { return 1; }
   
# Change the error routine for here. # Change the error routine for here.
$SIG{__WARN__} = sub { &RSS_error(@_) }; $SIG{__WARN__} = sub { &RSS_error(@_) };
   
# Allow us to be called by a system()-like call # Allow us to be called by a system()-like call
# This lets us send data to any language that supports capturing STDOUT. # This lets us send data to any language that supports capturing STDOUT.
# Usage is detailed in POD at the bottom. # Usage is detailed in POD at the bottom.
if (scalar @ARGV) {&shellaccess();} if (scalar @ARGV) {&shellaccess();}
   
# Is RSS disabled? # Is RSS disabled?
&RSS_error('not_allowed') if $rss_disabled; &RSS_error('not_allowed') if $rss_disabled;
   
&LoadCensorList; &LoadCensorList;
   
# Load YaBBC if it is enabled # Load YaBBC if it is enabled
require "$sourcedir/YaBBC.pl" if $enable_ubbc; require "$sourcedir/YaBBC.pl" if $enable_ubbc;
   
# Read from a single board # Read from a single board
sub RSS_board { sub RSS_board {
   ### Arguments:    ### Arguments:
   # board: the board to load from. Defaults to all boards.    # board: the board to load from. Defaults to all boards.
   # showauthor: show the author or not? Defaults to false.    # showauthor: show the author or not? Defaults to false.
   # topics: Number of topics to show. Defaults to 5.    # topics: Number of topics to show. Defaults to 5.
   ###    ###
   
   # Local variables    # Local variables
   my ($board, $topics); # Variables for settings    my ($board, $topics); # Variables for settings
   
   # Settings    # Settings
   $board = $INFO{'board'};    $board = $INFO{'board'};
   $topics = $INFO{'topics'} || $rss_limit || 10;    $topics = $INFO{'topics'} || $rss_limit || 10;
   if ($rss_limit && $topics > $rss_limit) { $topics = $rss_limit; }    if ($rss_limit && $topics > $rss_limit) { $topics = $rss_limit; }
   
   ### Security check ###    ### Security check ###
   if (&AccessCheck($currentboard, '', $boardperms) ne 'granted') { &RSS_error('no_access'); }    if (&AccessCheck($currentboard, '', $boardperms) ne 'granted') { &RSS_error('no_access'); }
   if ($annboard eq $board && !$iamadmin && !$iamgmod) { &RSS_error('no_access'); }    if ($annboard eq $board && !$iamadmin && !$iamgmod) { &RSS_error('no_access'); }
   
   # Now, go into the board and look for the last X topics    # Now, go into the board and look for the last X topics
   fopen(BRDTXT, "$boardsdir/$board.txt") || &RSS_error('cannot_open', "$boardsdir/$board.txt", 1);    fopen(BRDTXT, "$boardsdir/$board.txt") || &RSS_error('cannot_open', "$boardsdir/$board.txt", 1);
   my @threadlist = <BRDTXT>;    my @threadlist = <BRDTXT>;
   fclose(BRDTXT);    fclose(BRDTXT);
   my $threadcount = @threadlist;    my $threadcount = @threadlist;
   if ($threadcount < $topics) { $topics = $threadcount; }    if ($threadcount < $topics) { $topics = $threadcount; }
   
   @threadlist = splice(@threadlist, 0, $topics);    @threadlist = splice(@threadlist, 0, $topics);
   # Sorting mode    # Sorting mode
   if ($rss_message == 2) {    if ($rss_message == 2) {
       # Sort by original post        # Sort by original post
       @threadlist = sort @threadlist;        @threadlist = sort @threadlist;
   }    }
   # Otherwise, it's good enough as-is    # Otherwise, it's good enough as-is
   chomp @threadlist;    chomp @threadlist;
   
   my $i = 0;    my $i = 0;
   foreach (@threadlist) {    foreach (@threadlist) {
       ($mnum, $msub, $mname, $memail, $mdate, $mreplies, $musername, $micon, $mstate, $ns) = split(/\|/, $_);        ($mnum, $msub, $mname, $memail, $mdate, $mreplies, $musername, $micon, $mstate, $ns) = split(/\|/, $_);
       $curnum = $mnum;        $curnum = $mnum;
       # See if this is a topic that we don't want displayed.        # See if this is a topic that we don't want displayed.
       if ($mstate =~ /h/ && !$iamadmin && !$iamgmod) { next; }        if ($mstate =~ /h/ && !$iamadmin && !$iamgmod) { next; }
   
       # Does it need to be returned as a 304?        # Does it need to be returned as a 304?
       if ($i == 0) { # Do this for the first request only        if ($i == 0) { # Do this for the first request only
           $cachedate = &RFC822Date($mdate);            $cachedate = &RFC822Date($mdate);
           if ($ENV{'HTTP_IF_NONE_MATCH'} eq qq~"$cachedate"~ || $ENV{'HTTP_IF_MODIFIED_SINCE'} eq $cachedate) {            if ($ENV{'HTTP_IF_NONE_MATCH'} eq qq~"$cachedate"~ || $ENV{'HTTP_IF_MODIFIED_SINCE'} eq $cachedate) {
               &Send304NotModified(); # Comment this out to test with caching disabled                &Send304NotModified(); # Comment this out to test with caching disabled
           }            }
       }        }
   
       ($msub, undef) = &Split_Splice_Move($msub,0);        ($msub, undef) = &Split_Splice_Move($msub,0);
       &FromHTML($msub);        &FromHTML($msub);
       &ToChars($msub);        &ToChars($msub);
       # Censor the subject of the thread.        # Censor the subject of the thread.
       $msub = &Censor($msub);        $msub = &Censor($msub);
   
       my $postid = "$mreplies#$mreplies";        my $postid = "$mreplies#$mreplies";
       $postid = '0#0' if $rss_message == 2;        $postid = '0#0' if $rss_message == 2;
   
       my $category = "$mbname/$boardname";        my $category = "$mbname/$boardname";
       &FromHTML($category);        &FromHTML($category);
       # Show the minimum stuff (topic title, link to it)        # Show the minimum stuff (topic title, link to it)
       if ($accept_permalink){        if ($accept_permalink){
           $permdate = &permtimer($curnum);            $permdate = &permtimer($curnum);
           $yymain .= qq~        <item>            $yymain .= qq~        <item>
               <title>~ . &RSSDescriptionTrim($msub) . qq~</title>                <title>~ . &RSSDescriptionTrim($msub) . qq~</title>
               <link>~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$currentboard/$curnum") . qq~</link>                <link>~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$currentboard/$curnum") . qq~</link>
               <category>~ . &RSSDescriptionTrim($category) . qq~</category>                <category>~ . &RSSDescriptionTrim($category) . qq~</category>
               <guid isPermaLink="true">~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$currentboard/$curnum") . qq~</guid>                <guid isPermaLink="true">~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$currentboard/$curnum") . qq~</guid>
~; ~;
       } else {        } else {
           $yymain .= qq~        <item>            $yymain .= qq~        <item>
               <title>~ . &RSSDescriptionTrim($msub) . qq~</title>                <title>~ . &RSSDescriptionTrim($msub) . qq~</title>
               <link>~ . &RSSDescriptionTrim("$scripturl?num=$curnum") . qq~</link>                <link>~ . &RSSDescriptionTrim("$scripturl?num=$curnum") . qq~</link>
               <category>~ . &RSSDescriptionTrim($category) . qq~</category>                <category>~ . &RSSDescriptionTrim($category) . qq~</category>
               <guid>~ . &RSSDescriptionTrim("$scripturl?num=$curnum") . qq~</guid>                <guid>~ . &RSSDescriptionTrim("$scripturl?num=$curnum") . qq~</guid>
~; ~;
       }        }
   
       my $post;        my $post;
       fopen(TOPIC, "$datadir/$curnum.txt") || &RSS_error('cannot_open', "$datadir/$curnum.txt", 1);        fopen(TOPIC, "$datadir/$curnum.txt") || &RSS_error('cannot_open', "$datadir/$curnum.txt", 1);
       if ($rss_message == 1) {        if ($rss_message == 1) {
           # Open up the thread and read the last post.            # Open up the thread and read the last post.
           while (<TOPIC>) {            while (<TOPIC>) {
               chomp $_;                chomp $_;
               $post = $_ if $_;                $post = $_ if $_;
           }            }
       } elsif ($rss_message == 2) {        } elsif ($rss_message == 2) {
           # Open up the thread and read the first post.            # Open up the thread and read the first post.
           $post = <TOPIC>;            $post = <TOPIC>;
       }        }
       fclose(TOPIC);        fclose(TOPIC);
       if ($post ne '') {        if ($post ne '') {
           (undef, undef, undef, undef, $musername, undef, undef, undef, $message, $ns) = split(/\|/, $post);            (undef, undef, undef, undef, $musername, undef, undef, undef, $message, $ns) = split(/\|/, $post);
       }        }
       if ($showauthor) {        if ($showauthor) {
           # The spec really wants us to include their email.    
           # That's not adviseable for us (spambots anyone?). So we skip author if the email hidden flag is on for that user.    
           if (-e "$memberdir/$musername.vars") {            if (-e "$memberdir/$musername.vars") {
               &LoadUser($musername);                &LoadUser($musername);
               if (!${$uid.$musername}{'hidemail'}){                if (!${$uid.$musername}{'hidemail'}){
                   $yymain .= qq~<author>~ . &RSSDescriptionTrim("${$uid.$musername}{'email'} (${$uid.$musername}{'realname'})") . qq~</author>~;                    $yymain .= qq~<author>~ . &RSSDescriptionTrim("${$uid.$musername}{'email'} (${$uid.$musername}{'realname'})") . qq~</author>~;
               }                }
                 else {  
                     $yymain .= qq~            <author><name>~ . &RSSDescriptionTrim("(${$uid.$musername}{'realname'})") . qq~</name></author>\n~;  
                 }  
           }            }
       }        }
       if ($showdate) {        if ($showdate) {
               $mdate = $curnum if $rss_message == 2; # Sort by topic creation if requested.                $mdate = $curnum if $rss_message == 2; # Sort by topic creation if requested.
               # Get the date how the user wants it.                # Get the date how the user wants it.
               my $realdate = &RFC822Date($mdate);                my $realdate = &RFC822Date($mdate);
               $yymain .= qq~        <pubDate>$realdate</pubDate>                $yymain .= qq~        <pubDate>$realdate</pubDate>
~; ~;
       }        }
       if ($message ne '') {        if ($message ne '') {
           ($message, undef) = &Split_Splice_Move($message,$curnum);            ($message, undef) = &Split_Splice_Move($message,$curnum);
           if ($enable_ubbc) {            if ($enable_ubbc) {
                   &LoadUser($musername);                    &LoadUser($musername);
                   $displayname = ${$uid.$musername}{'realname'};                    $displayname = ${$uid.$musername}{'realname'};
                   &DoUBBC;                    &DoUBBC;
           }            }
           &FromHTML($message);            &FromHTML($message);
           &ToChars($message);            &ToChars($message);
           $message = &Censor($message);            $message = &Censor($message);
           $yymain .= qq~        <description>~ . &RSSDescriptionTrim($message) . qq~</description>            $yymain .= qq~        <description>~ . &RSSDescriptionTrim($message) . qq~</description>
~; ~;
       }        }
       # Finish up the item        # Finish up the item
       $yymain .= qq~        </item>        $yymain .= qq~        </item>
~; ~;
       $i++; # Increment        $i++; # Increment
   }    }
   
   &ToChars($boardname);    &ToChars($boardname);
   $yytitle = $boardname;    $yytitle = $boardname;
   $yydesc = ${$uid.$curboard}{'description'};    $yydesc = ${$uid.$curboard}{'description'};
   
   &RSS_template();    &RSS_template();
} }
   
# Similar to Recent.pl&RecentList but uses original code # Similar to Recent.pl&RecentList but uses original code
# RSS feed from multiple boards (a category or the whole forum) # RSS feed from multiple boards (a category or the whole forum)
sub RSS_recent { sub RSS_recent {
   ### Arguments:    ### Arguments:
   # catselect: use a specific category instead of the whole forum (optional)    # catselect: use a specific category instead of the whole forum (optional)
   # topics: Number of topics to show. Defaults to 5.    # topics: Number of topics to show. Defaults to 5.
   ###    ###
   
   
   # Local variables    # Local variables
   my ($topics); # Variables for settings    my ($topics); # Variables for settings
   my (@threadlist, $i, $cutofftime); # Variables for the messages    my (@threadlist, $i, $cutofftime); # Variables for the messages
   
   # Settings    # Settings
   $topics = $INFO{'topics'} || $rss_limit;    $topics = $INFO{'topics'} || $rss_limit;
   if ($rss_limit && $topics > $rss_limit) { $topics = $rss_limit; }    if ($rss_limit && $topics > $rss_limit) { $topics = $rss_limit; }
   
   # If this is just a single category, handle it.    # If this is just a single category, handle it.
   if ($catinfo{$INFO{'catselect'}}) { @categoryorder = ($INFO{'catselect'}); }    if ($catinfo{$INFO{'catselect'}}) { @categoryorder = ($INFO{'catselect'}); }
   
   # Find the latest $topics post times in all boards that we have access to    # Find the latest $topics post times in all boards that we have access to
   # and add them to a giant array    # and add them to a giant array
   foreach $catid (@categoryorder) {    foreach $catid (@categoryorder) {
       my $boardlist = $cat{$catid};        my $boardlist = $cat{$catid};
   
       my @bdlist = split(/\,/, $boardlist);        my @bdlist = split(/\,/, $boardlist);
       my ($catname, $catperms) = split(/\|/, $catinfo{$catid});        my ($catname, $catperms) = split(/\|/, $catinfo{$catid});
       my $cataccess = &CatAccess($catperms);        my $cataccess = &CatAccess($catperms);
       if (!$cataccess) { next; }        if (!$cataccess) { next; }
   
       foreach $curboard (@bdlist) {        foreach $curboard (@bdlist) {
           ($boardname{$curboard}, $boardperms, $boardview) = split(/\|/, $board{$curboard});            ($boardname{$curboard}, $boardperms, $boardview) = split(/\|/, $board{$curboard});
   
           my $access = &AccessCheck($curboard, '', $boardperms);            my $access = &AccessCheck($curboard, '', $boardperms);
           if (!$iamadmin && $access ne 'granted') { next; }            if (!$iamadmin && $access ne 'granted') { next; }
   
           fopen(BOARD, "$boardsdir/$curboard.txt") || &RSS_error('cannot_open', "$boardsdir/$curboard.txt", 1);            fopen(BOARD, "$boardsdir/$curboard.txt") || &RSS_error('cannot_open', "$boardsdir/$curboard.txt", 1);
           for($i = 0; $i < $topics; $i++) {            for($i = 0; $i < $topics; $i++) {
               my($buffer, $mnum, $mdate, $mstate);                my($buffer, $mnum, $mdate, $mstate);
   
               $buffer = <BOARD>;                $buffer = <BOARD>;
               last unless $buffer;                last unless $buffer;
               chomp $buffer;                chomp $buffer;
   
               ($mnum, undef, undef, undef, $mdate, undef, undef, undef, $mstate) = split(/\|/, $buffer);                ($mnum, undef, undef, undef, $mdate, undef, undef, undef, $mstate) = split(/\|/, $buffer);
               $mdate = sprintf("%010d", $mdate);                $mdate = sprintf("%010d", $mdate);
               $mdate = $mnum if $rss_message == 2; # Sort by topic creation if requested.                $mdate = $mnum if $rss_message == 2; # Sort by topic creation if requested.
   
               # Check if it's hidden. If so, don't show it                # Check if it's hidden. If so, don't show it
               if ($mstate =~ /h/ && !$iamadmin && !$iamgmod) { next; }                if ($mstate =~ /h/ && !$iamadmin && !$iamgmod) { next; }
   
               # Add it to an array, using $mdate as the first value so we can easily sort                # Add it to an array, using $mdate as the first value so we can easily sort
               push(@threadlist, "$mdate|$curboard|$buffer");                push(@threadlist, "$mdate|$curboard|$buffer");
           }            }
           fclose(BOARD);            fclose(BOARD);
   
           # Clean out the extra entries in the threadlist            # Clean out the extra entries in the threadlist
           @threadlist = reverse sort @threadlist;            @threadlist = reverse sort @threadlist;
           @threadlist = @threadlist[0 .. $topics - 1];            @threadlist = @threadlist[0 .. $topics - 1];
       }        }
   }    }
   
   for($i = 0; $threadlist[$i]; $i++) {    for($i = 0; $threadlist[$i]; $i++) {
       # Opening item stuff        # Opening item stuff
       ($mdate, $board, $mnum, $msub, $mname, $memail, $modate, $mreplies, $musername, $micon, $mstate) = split(/\|/, $threadlist[$i]);        ($mdate, $board, $mnum, $msub, $mname, $memail, $modate, $mreplies, $musername, $micon, $mstate) = split(/\|/, $threadlist[$i]);
       $curnum = $mnum;        $curnum = $mnum;
   
       ($msub, undef) = &Split_Splice_Move($msub,0);        ($msub, undef) = &Split_Splice_Move($msub,0);
       &FromHTML($msub);        &FromHTML($msub);
       &ToChars($msub);        &ToChars($msub);
       # Censor the subject of the thread.        # Censor the subject of the thread.
       $msub = &Censor($msub);        $msub = &Censor($msub);
   
       # Does it need to be returned as a 304?        # Does it need to be returned as a 304?
       if($i == 0) { # Do this for the first request only        if($i == 0) { # Do this for the first request only
           $cachedate = &RFC822Date($mdate);            $cachedate = &RFC822Date($mdate);
           if($ENV{'HTTP_IF_NONE_MATCH'} eq qq~"$cachedate"~ || $ENV{'HTTP_IF_MODIFIED_SINCE'} eq $cachedate) {            if($ENV{'HTTP_IF_NONE_MATCH'} eq qq~"$cachedate"~ || $ENV{'HTTP_IF_MODIFIED_SINCE'} eq $cachedate) {
               &Send304NotModified(); # Comment this out to test with caching disabled                &Send304NotModified(); # Comment this out to test with caching disabled
           }            }
       }        }
   
       my $postid = "$mreplies#$mreplies";        my $postid = "$mreplies#$mreplies";
       $postid = '0#0' if $rss_message == 2;        $postid = '0#0' if $rss_message == 2;
   
       my $category = "$mbname/$boardname{$board}";        my $category = "$mbname/$boardname{$board}";
       &FromHTML($category);        &FromHTML($category);
       my $bn = $boardname{$board};        my $bn = $boardname{$board};
       &FromHTML($bn);        &FromHTML($bn);
       if ($accept_permalink){        if ($accept_permalink){
           my $permsub = $msub;            my $permsub = $msub;
           $permdate = &permtimer($curnum);            $permdate = &permtimer($curnum);
           $permsub =~ s~ ~$perm_spacer~g;            $permsub =~ s~ ~$perm_spacer~g;
           $yymain .= qq~            <item>            $yymain .= qq~            <item>
           <title>~ . &RSSDescriptionTrim("$bn - $msub") . qq~</title>            <title>~ . &RSSDescriptionTrim("$bn - $msub") . qq~</title>
           <link>~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$board/$curnum") . qq~</link>            <link>~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$board/$curnum") . qq~</link>
           <category>~ . &RSSDescriptionTrim($category) . qq~</category>            <category>~ . &RSSDescriptionTrim($category) . qq~</category>
           <guid isPermaLink="true">~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$board/$curnum") . qq~</guid>\n~;            <guid isPermaLink="true">~ . &RSSDescriptionTrim("http://$perm_domain/$symlink$permdate/$board/$curnum") . qq~</guid>\n~;
       } else {        } else {
           $yymain .= qq~        <item>            $yymain .= qq~        <item>
           <title>~ . &RSSDescriptionTrim("$bn - $msub") . qq~</title>            <title>~ . &RSSDescriptionTrim("$bn - $msub") . qq~</title>
           <link>~ . &RSSDescriptionTrim("$scripturl?num=$curnum/$postid") . qq~</link>            <link>~ . &RSSDescriptionTrim("$scripturl?num=$curnum/$postid") . qq~</link>
           <category>~ . &RSSDescriptionTrim($category) . qq~</category>            <category>~ . &RSSDescriptionTrim($category) . qq~</category>
           <guid>~ . &RSSDescriptionTrim("$scripturl?num=$curnum/$postid") . qq~</guid>\n~;            <guid>~ . &RSSDescriptionTrim("$scripturl?num=$curnum/$postid") . qq~</guid>\n~;
       }        }
   
       my $post;        my $post;
       fopen(TOPIC, "$datadir/$curnum.txt") || &RSS_error('cannot_open', "$datadir/$curnum.txt", 1);        fopen(TOPIC, "$datadir/$curnum.txt") || &RSS_error('cannot_open', "$datadir/$curnum.txt", 1);
       if ($rss_message == 1) {        if ($rss_message == 1) {
           # Open up the thread and read the last post.            # Open up the thread and read the last post.
           while(<TOPIC>) {            while(<TOPIC>) {
               chomp $_;                chomp $_;
               $post = $_ if $_;                $post = $_ if $_;
           }            }
       } elsif ($rss_message == 2) {        } elsif ($rss_message == 2) {
           # Open up the thread and read the first post.            # Open up the thread and read the first post.
           $post = <TOPIC>;            $post = <TOPIC>;
       }        }
       fclose(TOPIC);        fclose(TOPIC);
   
       if ($post ne ''){        if ($post ne ''){
           (undef, undef, undef, undef, $musername, undef, undef, undef, $message, $ns) = split(/\|/, $post);            (undef, undef, undef, undef, $musername, undef, undef, undef, $message, $ns) = split(/\|/, $post);
       }        }
   
       if ($showauthor) {        if ($showauthor) {
           # The spec really wants us to include their email.            # The spec really wants us to include their email.
           # That's not adviseable for us (spambots anyone?). So we skip author if the email hidden flag is on for that user.            # That's not adviseable for us (spambots anyone?). So we skip author if the email hidden flag is on for that user.
           if (-e "$memberdir/$musername.vars") {            if (-e "$memberdir/$musername.vars") {
               &LoadUser($musername);                &LoadUser($musername);
               if (!${$uid.$musername}{'hidemail'}){                if (!${$uid.$musername}{'hidemail'}){
                   $yymain .= qq~            <author>~ . &RSSDescriptionTrim("${$uid.$musername}{'email'} (${$uid.$musername}{'realname'})") . qq~</author>\n~;                    $yymain .= qq~            <author>~ . &RSSDescriptionTrim("${$uid.$musername}{'email'} (${$uid.$musername}{'realname'})") . qq~</author>\n~;
                 }  
                 else {  
                     $yymain .= qq~            <author><name>~ . &RSSDescriptionTrim("${$uid.$musername}{'realname'}") . qq~</name></author>\n~;  
               }                }
           }            }
       }        }
   
       if ($showdate) {        if ($showdate) {
           $mdate = $curnum if $rss_message == 2; # Sort by topic creation if requested.            $mdate = $curnum if $rss_message == 2; # Sort by topic creation if requested.
           # Get the date how the user wants it.            # Get the date how the user wants it.
           my $realdate = &RFC822Date($mdate);            my $realdate = &RFC822Date($mdate);
           $yymain .= qq~            <pubDate>$realdate</pubDate>\n~;            $yymain .= qq~            <pubDate>$realdate</pubDate>\n~;
       }        }
   
       if ($message ne '') {        if ($message ne '') {
           ($message, undef) = &Split_Splice_Move($message,$curnum);            ($message, undef) = &Split_Splice_Move($message,$curnum);
           if ($enable_ubbc) {            if ($enable_ubbc) {
                   &LoadUser($musername);                    &LoadUser($musername);
                   $displayname = ${$uid.$musername}{'realname'};                    $displayname = ${$uid.$musername}{'realname'};
                   &DoUBBC;                    &DoUBBC;
           }            }
           &FromHTML($message);            &FromHTML($message);
           &ToChars($message);            &ToChars($message);
           $message = &Censor($message);            $message = &Censor($message);
           $yymain .= qq~            <description>~ . &RSSDescriptionTrim($message) . qq~</description>\n~;            $yymain .= qq~            <description>~ . &RSSDescriptionTrim($message) . qq~</description>\n~;
       }        }
   
       $yymain .= qq~        </item>\n~;        $yymain .= qq~        </item>\n~;
   }    }
   
   &ToChars($boardname);    &ToChars($boardname);
   $yytitle = "$topics $maintxt{'214b'}";    $yytitle = "$topics $maintxt{'214b'}";
   $yydesc = ${$uid.$curboard}{'description'};    $yydesc = ${$uid.$curboard}{'description'};
   
   &RSS_template();    &RSS_template();
} }
   
sub RSS_template { # print RSS output sub RSS_template { # print RSS output
   # Generate the lastBuildDate    # Generate the lastBuildDate
   my $rssdate = &RFC822Date($date);    my $rssdate = &RFC822Date($date);
   
   # Send out the "Last-Modified" and "ETag" headers so nice readers will ask before downloading.    # Send out the "Last-Modified" and "ETag" headers so nice readers will ask before downloading.
   $LastModified = $ETag = $cachedate || $rssdate;    $LastModified = $ETag = $cachedate || $rssdate;
   $contenttype = 'text/xml';    $contenttype = 'text/xml';
   &print_output_header;    &print_output_header;
   
   # Make the generator look better    # Make the generator look better
   my $RSSplver = $rssplver;    my $RSSplver = $rssplver;
   $RSSplver =~ s/\$//g;    $RSSplver =~ s/\$//g;
   
   # Removed per Corey's suggestion: http://www.yabbforum.com/community/YaBB.pl?num=1142571424/20#20    # Removed per Corey's suggestion: http://www.yabbforum.com/community/YaBB.pl?num=1142571424/20#20
   #my $docs = "       <docs>http://$perm_domain</docs>\n" if $perm_domain;    #my $docs = "       <docs>http://$perm_domain</docs>\n" if $perm_domain;
   
   my $mainlink = $scripturl;    my $mainlink = $scripturl;
   $mainlink .= "?board=$INFO{'board'}" if $INFO{'board'};    $mainlink .= "?board=$INFO{'board'}" if $INFO{'board'};
   $mainlink .= "?catselect=$INFO{'catselect'}" if $INFO{'catselect'};    $mainlink .= "?catselect=$INFO{'catselect'}" if $INFO{'catselect'};
   
   my $tit = "$yytitle - $mbname";    my $tit = "$yytitle - $mbname";
   &FromHTML($tit);    &FromHTML($tit);
   my $descr = ($boardname ? "$boardname - " : "") . $mbname;    my $descr = ($boardname ? "$boardname - " : "") . $mbname;
   &FromHTML($descr);    &FromHTML($descr);
   my $mn = $mbname;    my $mn = $mbname;
   &FromHTML($mn);    &FromHTML($mn);
   $output = qq~<?xml version="1.0" encoding="$yycharset" ?>    $output = qq~<?xml version="1.0" encoding="$yycharset" ?>
<!-- Generated by YaBB on $rssdate --> <!-- Generated by YaBB on $rssdate -->
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>    <channel>
       <atom:link href="$scripturl?action=$INFO{'action'}~ . ($INFO{'board'} ? ";board=$INFO{'board'}" : "") . qq~" rel="self" type="application/rss+xml" />        <atom:link href="$scripturl?action=$INFO{'action'}~ . ($INFO{'board'} ? ";board=$INFO{'board'}" : "") . qq~" rel="self" type="application/rss+xml" />
       <title>~ . &RSSDescriptionTrim($tit) . qq~</title>        <title>~ . &RSSDescriptionTrim($tit) . qq~</title>
       <link>~ . &RSSDescriptionTrim($mainlink) . qq~</link>        <link>~ . &RSSDescriptionTrim($mainlink) . qq~</link>
       <description>~ . &RSSDescriptionTrim($descr) . qq~</description>        <description>~ . &RSSDescriptionTrim($descr) . qq~</description>
       <language>~ . &RSSDescriptionTrim("$maintxt{'w3c_lngcode'}") . qq~</language>        <language>~ . &RSSDescriptionTrim("$maintxt{'w3c_lngcode'}") . qq~</language>
   
       <copyright>~ . &RSSDescriptionTrim($mn) . qq~</copyright>        <copyright>~ . &RSSDescriptionTrim($mn) . qq~</copyright>
       <lastBuildDate>$rssdate</lastBuildDate>        <lastBuildDate>$rssdate</lastBuildDate>
       <docs>http://blogs.law.harvard.edu/tech/rss</docs>        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
       <generator>$RSSplver</generator>        <generator>$RSSplver</generator>
       <ttl>30</ttl>        <ttl>30</ttl>
$yymain $yymain
   </channel>    </channel>
</rss>~; </rss>~;
   
   &print_HTML_output_and_finish;    &print_HTML_output_and_finish;
} }
   
sub RSS_error { sub RSS_error {
   # This routine is mostly a copy of fatal_error except it uses RSS templating    # This routine is mostly a copy of fatal_error except it uses RSS templating
   &LoadLanguage('Error');    &LoadLanguage('Error');
   my($e_filename, $e_line, $e_subroutine, $l, $ot);    my($e_filename, $e_line, $e_subroutine, $l, $ot);
   # Gets filename and line where fatal_error was called.    # Gets filename and line where fatal_error was called.
   # Need to go further back to get correct subroutine name,    # Need to go further back to get correct subroutine name,
   # otherwise will print fatal_error as current subroutine!    # otherwise will print fatal_error as current subroutine!
   (undef, $e_filename, $e_line) = caller(0);    (undef, $e_filename, $e_line) = caller(0);
   (undef, undef, undef, $e_subroutine) = caller(1);    (undef, undef, undef, $e_subroutine) = caller(1);
   (undef, $e_subroutine) = split(/::/, $e_subroutine);    (undef, $e_subroutine) = split(/::/, $e_subroutine);
   my($e,$t,$v) = @_;    my($e,$t,$v) = @_;
   if ($t || $e) { $ot = "<b>$maintxt{'error_description'}</b>: $error_txt{$e} $t"; }    if ($t || $e) { $ot = "<b>$maintxt{'error_description'}</b>: $error_txt{$e} $t"; }
   if (($debug == 1 or ($debug == 2 && $iamadmin)) && ($e_filename || $e_line || $e_subroutine)) { $l = "<br />$maintxt{'error_location'}: $e_filename<br />$maintxt{'error_line'}: $e_line<br />$maintxt{'error_subroutine'}: $e_subroutine"; }    if (($debug == 1 or ($debug == 2 && $iamadmin)) && ($e_filename || $e_line || $e_subroutine)) { $l = "<br />$maintxt{'error_location'}: $e_filename<br />$maintxt{'error_line'}: $e_line<br />$maintxt{'error_subroutine'}: $e_subroutine"; }
   if ($v) { $v = "<br />$maintxt{'error_verbose'}: $!"; }    if ($v) { $v = "<br />$maintxt{'error_verbose'}: $!"; }
   
   if ($elenable) {    if ($elenable) {
       &fatal_error_logging("$ot$l$v");        &fatal_error_logging("$ot$l$v");
   }    }
   
   my $tit = $error_txt{'error_occurred'};    my $tit = $error_txt{'error_occurred'};
   &FromHTML($tit);    &FromHTML($tit);
   my $ed = "$ot$l$v";    my $ed = "$ot$l$v";
   &FromHTML($ed);    &FromHTML($ed);
   my $mn = $mbname;    my $mn = $mbname;
   &FromHTML($mn);    &FromHTML($mn);
   $yymain = qq~    $yymain = qq~
   <item>    <item>
       <title>~ . &RSSDescriptionTrim($tit) . qq~</title>        <title>~ . &RSSDescriptionTrim($tit) . qq~</title>
       <description>~ . &RSSDescriptionTrim($ed) . qq~</description>        <description>~ . &RSSDescriptionTrim($ed) . qq~</description>
       <category>~ . &RSSDescriptionTrim($mn) . qq~</category>        <category>~ . &RSSDescriptionTrim($mn) . qq~</category>
   </item>~;    </item>~;
   
   &RSS_template();    &RSS_template();
} }
   
sub Send304NotModified { sub Send304NotModified {
   print "Status: 304 Not Modified\n\n";    print "Status: 304 Not Modified\n\n";
   exit;    exit;
} }
   
sub RFC822Date { sub RFC822Date {
   # Takes a Unix timestamp and returns the RFC-822 date format    # Takes a Unix timestamp and returns the RFC-822 date format
   # of it: Sat, 07 Sep 2002 9:42:31 GMT    # of it: Sat, 07 Sep 2002 9:42:31 GMT
   my @GMTime = split(/ +/, gmtime(shift));    my @GMTime = split(/ +/, gmtime(shift));
   "$GMTime[0], $GMTime[2] $GMTime[1] $GMTime[4] $GMTime[3] GMT";    "$GMTime[0], $GMTime[2] $GMTime[1] $GMTime[4] $GMTime[3] GMT";
} }
   
sub RSSDescriptionTrim { # This formats the RSS sub RSSDescriptionTrim { # This formats the RSS
   my $x = $_[0];    my $x = $_[0];
   
   $x =~ s/ (class|style)\s*=\s*["'].+?['"]//g;    $x =~ s/ (class|style)\s*=\s*["'].+?['"]//g;
   
   $x =~ s/&/&#38;/g;    $x =~ s/&/&#38;/g;
   $x =~ s/"/&#34;/g;    $x =~ s/"/&#34;/g;
   $x =~ s~'~&#39;~g;    $x =~ s~'~&#39;~g;
   $x =~ s/  / &#160;/g;    $x =~ s/  / &#160;/g;
   $x =~ s/</&#60;/g;    $x =~ s/</&#60;/g;
   $x =~ s/>/&#62;/g;    $x =~ s/>/&#62;/g;
   $x =~ s/\|/&#124;/g;    $x =~ s/\|/&#124;/g;
   $x =~ s/\{/&#123;/g;    $x =~ s/\{/&#123;/g;
   $x =~ s/\}/&#125;/g;    $x =~ s/\}/&#125;/g;
   
   $x;    $x;
} }
   
sub shellaccess { sub shellaccess {
   # Parse the arguments    # Parse the arguments
   my($data, $i, %arguments);    my($data, $i, %arguments);
   
   for($i = 0; $i < @ARGV; $i++) {    for($i = 0; $i < @ARGV; $i++) {
       if($ARGV[$i] =~ /\A\-/) {        if($ARGV[$i] =~ /\A\-/) {
           my($option, $value);            my($option, $value);
           $option = $ARGV[$i];            $option = $ARGV[$i];
           $option =~ s/\A\-\-?//;            $option =~ s/\A\-\-?//;
           ($option, $value) = split(/\=/, $option);            ($option, $value) = split(/\=/, $option);
           $arguments{$option} = $value || '';            $arguments{$option} = $value || '';
           unless(defined $arguments{$option}) {$arguments{$option} = 1;}            unless(defined $arguments{$option}) {$arguments{$option} = 1;}
       }        }
   }    }
   
   ### Requirements and Errors ###    ### Requirements and Errors ###
   $script_root = $arguments{'script-root'};    $script_root = $arguments{'script-root'};
   
   if (-e "Paths.pl") { require "Paths.pl"; }    if (-e "Paths.pl") { require "Paths.pl"; }
   elsif (-e "$script_root/Paths.pl") { require "$script_root/Paths.pl"; }    elsif (-e "$script_root/Paths.pl") { require "$script_root/Paths.pl"; }
   
   require "$vardir/Settings.pl";    require "$vardir/Settings.pl";
   require "$sourcedir/Subs.pl";    require "$sourcedir/Subs.pl";
   require "$sourcedir/DateTime.pl";    require "$sourcedir/DateTime.pl";
   require "$sourcedir/Load.pl";    require "$sourcedir/Load.pl";
   
   &LoadCookie;          # Load the user's cookie (or set to guest)    &LoadCookie;          # Load the user's cookie (or set to guest)
   &LoadUserSettings;    # Load user settings    &LoadUserSettings;    # Load user settings
   &WhatLanguage;        # Figure out which language file we should be using! :D    &WhatLanguage;        # Figure out which language file we should be using! :D
   
   require "$boardsdir/forum.master";    require "$boardsdir/forum.master";
   require "$sourcedir/Security.pl";    require "$sourcedir/Security.pl";
   
   # Is RSS disabled?    # Is RSS disabled?
   &RSS_error('rss_disabled') if $rss_disabled;    &RSS_error('rss_disabled') if $rss_disabled;
   
   $gzcomp = 0; # Disable gzip so we can talk clearly    $gzcomp = 0; # Disable gzip so we can talk clearly
   
   # Map %arguments to %INFO    # Map %arguments to %INFO
   foreach my $var (qw(action board catselect topics)) {    foreach my $var (qw(action board catselect topics)) {
       $INFO{$var} = $arguments{$var};        $INFO{$var} = $arguments{$var};
   }    }
   
   # Run the subroutine    # Run the subroutine
   require "$sourcedir/SubList.pl";    require "$sourcedir/SubList.pl";
   my $action = $INFO{'action'};    my $action = $INFO{'action'};
   my ($file,$sub) = split(/&/, $director{$action});    my ($file,$sub) = split(/&/, $director{$action});
   if ($file eq 'RSS.pl') { &{$sub}(); }    if ($file eq 'RSS.pl') { &{$sub}(); }
   exit;    exit;
} }
   
1; 1;
   
__END__ __END__
   
# Sample subroutine to show how to use URL encoding # Sample subroutine to show how to use URL encoding
# If $_[1] is true, it fully encodes the text. If not, it just encodes non-word characters (\W). # If $_[1] is true, it fully encodes the text. If not, it just encodes non-word characters (\W).
sub urlencode { sub urlencode {
   my($text, $mode) = ($_[0], $_[1]);    my($text, $mode) = ($_[0], $_[1]);
   #$text =~ s/(\W)/sprintf("%%%lx", ord($1));/eg; # Not good enough; doesn't make it 2 digits all the time    #$text =~ s/(\W)/sprintf("%%%lx", ord($1));/eg; # Not good enough; doesn't make it 2 digits all the time
   
   ### "Real Perl Hackers Use 'pack'" (tm) - jbert on Perlmonks    ### "Real Perl Hackers Use 'pack'" (tm) - jbert on Perlmonks
   if(!$mode) {$text =~ s/(\W)/'%' . unpack("H*", pack("C", ord($1)))/eg;}    if(!$mode) {$text =~ s/(\W)/'%' . unpack("H*", pack("C", ord($1)))/eg;}
   elsif($mode) {$text =~ s/(.)/'%' . unpack("H*", pack("C", ord($1)))/eg;}    elsif($mode) {$text =~ s/(.)/'%' . unpack("H*", pack("C", ord($1)))/eg;}
   return $text;    return $text;
} }
   
=pod =pod
   
=head1 Command line usage =head1 Command line usage
   
To make it possible for most programming languages to easily get output from this script, we have a command line mode. To make it possible for most programming languages to easily get output from this script, we have a command line mode.
To do this, simply run "$sourcedir/RSS.pl (ARGUMENTS)". The RSS feed will be sent to STDOUT. To do this, simply run "$sourcedir/RSS.pl (ARGUMENTS)". The RSS feed will be sent to STDOUT.
   
=head1 Command line arguments =head1 Command line arguments
   
You must give at least one argument so we know we're running as a commandline script. You must give at least one argument so we know we're running as a commandline script.
   
All options are given delimited by equal signs, for instance: All options are given delimited by equal signs, for instance:
   
Sources/RSS.pl --action=RSS_board Sources/RSS.pl --action=RSS_board
   
If you need to insert a character with a special meaning such as a space, equals sign, or percent sign: use the URL encoding format. The subroutine &urlencode found in this file should show how to encode properly. If you need to insert a character with a special meaning such as a space, equals sign, or percent sign: use the URL encoding format. The subroutine &urlencode found in this file should show how to encode properly.
   
For true/false values, 0 is false and anything else is true (even without an option). For true/false values, 0 is false and anything else is true (even without an option).
   
=head2 Required argument =head2 Required argument
   
=over 12 =over 12
   
=item C<--action> =item C<--action>
   
Action to run. This is the exact same as the actions found in SubList.pl that belong to this file. Action to run. This is the exact same as the actions found in SubList.pl that belong to this file.
   
=back =back
   
=head3 Optional argument =head3 Optional argument
   
=over 12 =over 12
   
=item C<--script-root> =item C<--script-root>
   
Changes the script root used to load Paths.pl from. Changes the script root used to load Paths.pl from.
   
=back =back
   
=head2 Optional arguments for action=RSSrecent =head2 Optional arguments for action=RSSrecent
   
=over 12 =over 12
   
=item C<--catselect> =item C<--catselect>
   
Category to use for recent posts. Category to use for recent posts.
   
=item C<--showauthor> =item C<--showauthor>
   
Show the author's email address and name? Defaults to false. Working only if allowed by forum Admin Show the author's email address and name? Defaults to false. Working only if allowed by forum Admin
   
=item C<--topics> =item C<--topics>
   
Number of topics to show. Can be anywhere from 1 to 10, and it defaults to 5. Number of topics to show. Can be anywhere from 1 to 10, and it defaults to 5.
   
=back =back
   
=head2 Required arguments for action=RSSboard =head2 Required arguments for action=RSSboard
   
=over 12 =over 12
   
=item C<--board> =item C<--board>
   
Board ID to use. Board ID to use.
   
=back =back
   
=head3 Optional arguments for action=RSSboard =head3 Optional arguments for action=RSSboard
   
=over 12 =over 12
   
=item C<--showauthor> =item C<--showauthor>
   
Show the author's name? Defaults to false. Show the author's name? Defaults to false.
   
=item C<--topics> =item C<--topics>
   
Number of topics to show. Can be anywhere from 1 to 10, and it defaults to 5. Number of topics to show. Can be anywhere from 1 to 10, and it defaults to 5.
   
=back =back
   
=cut =cut