)
{
chomp $l;
if ($l =~ /^si:\s*(.*?)=(.*)$/)
{
$sourceinfo->{$id}->{$1} = $2;
}
elsif (my @a = split(/<ó>/, $l, 5))
{
push @articles, [ $a[0], $id, xmldecode($a[2]), xmldecode($a[3]), xmldecode($a[4]) ];
}
elsif (my @a = split(/;;/, $l, 4))
{
push @articles, [ $a[0], $id, xmldecode($a[2]), xmldecode($a[3]), "" ];
}
}
close(CF);
my $cs = stat($cachefile);
return (time() - $cs->mtime ,@articles);
}
sub save_cached_data
{
my ($id, $path, @articles) = @_;
my $cachefile = cache_file($path);
open(CF, ">$cachefile") || return undef;
foreach my $key (keys(%{ $sourceinfo->{$id} }))
{
print CF "si: $key=", $sourceinfo->{$id}->{$key}, "\n";
}
foreach my $a (@articles)
{
print CF join('<ó>', map { xmlencode($_) } @{ $a }), "\n";
}
close(CF);
return 1;
}
sub show_help_page
{
if ($config->{help} =~ /^redirect:\s*(.*)$/i)
{
print "Location: $1\n\n";
return;
}
print "Content-type: text/html\n\n";
print "rssticker $version \@ ", $ENV{"SERVER_NAME"};
print "\n";
print "This is rssticker $version \@ ", $ENV{"SERVER_NAME"}, "
\n";
if ($config->{help} !~ /^quiet$/)
{
my $rss = undef;
print "
Available URL aliases (RSS):
\n";
foreach my $key (sort grep(!/css$/i, keys(%{ $urlalias })))
{
$rss = $key unless ($rss);
my $u = $urlalias->{$key};
print "- $key, $u\n";
}
print "
";
print "Available URL aliases (CSS):
\n";
foreach my $key (sort grep(/css$/i, keys(%{ $urlalias })))
{
my $u = $urlalias->{$key};
print "- $key, $u\n";
}
print "
";
if ($config->{policy} =~ /^open$/i)
{
print "This ticker is open, you may specify your own resources.
\n";
}
else
{
print "This ticker is closed, you may only use the above aliases.
\n";
}
print "Default cache TTL is $cache_ttl seconds.
\n";
print "Default page refresh time is $refresh seconds.
\n";
print "View configuration file.
\n";
}
else
{
print "This ticker's configuration is a secret. Please visit\n";
print "the rssticker home page for more info.
\n";
}
print "\n";
exit 0;
}
sub panic
{
my $msg = shift;
print "Content-type: text/html\n\n";
print "rssticker $version: ", i18n("Error"), ", $msg\n";
print "", i18n("Error"), ":
";
if ($config->{"footer"})
{
print $config->{"footer"};
}
else
{
print "rssticker $version\n";
}
exit 0;
}
sub urldecode
{
my $text = shift;
$text =~ tr/+/ /;
$text =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
return $text;
}
sub urlencode
{
my $text = shift;
$text =~ s/([^A-Za-z0-9\s])/ $_=sprintf("%%%2.2X", ord($1))/ge;
return $text;
}
sub unsort
{
return sort { rand() <=> rand() } @_;
}
sub forkget
{
my $url = shift;
my $timeout = shift;
my $sleeps = 1;
my $pid = undef;
do
{
$pid = open(GET, "-|");
unless (defined $pid)
{
warn "cannot fork: $!";
die "bailing out" if ($sleeps++ > 6);
sleep 2;
}
}
until(defined $pid);
if ($pid)
{
my $ret = undef;
eval {
local $SIG{ALRM} = sub { die "timed out\n" };
alarm $timeout;
$ret = join('', );
alarm 0;
close(GET) || return undef;
};
if ($@) {
kill 'KILL' => $pid;
close(GET);
return undef;
alarm 0;
}
return $ret;
}
else
{
# KID - here we should use something smarter than get and
# abort if someone tries to feed us Too Much Data(tm).
print get($url);
exit(0);
}
}
# This implements a two-stage cookie counter, which only counts people who
# have cookies enabled and haven't been counted within the last counting
# interval.
#
sub user_counter
{
return "" if ($ENV{HTTP_COOKIE} =~ /rssticker=COUNTED/i);
return "" unless ($config->{cnt_every} && $config->{cnt_file});
if (open (CNT, ">>".$config->{cnt_file}))
{
if ($ENV{HTTP_COOKIE} =~ /rssticker=COUNTING/i)
{
if (my $r = $ENV{HTTP_REFERER})
{
print CNT scalar localtime(), " New from: $r\n";
}
else
{
print CNT scalar localtime(), " New user!\n";
}
close(CNT);
return "Set-Cookie: rssticker=COUNTED; path=/; expires=".
http_time(time() + $config->{cnt_every})."\n";
}
return "Set-Cookie: rssticker=COUNTING; path=/; expires=".
http_time(time() + $config->{cnt_every})."\n";
}
return "";
}
sub http_time
{
my $time = shift;
my $ht = gmtime($time);
$ht =~ s/^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$/$1, $3-$2-$5 $4 GMT/;
return $ht;
}