Spent some idle time today watching the rest of my Sapphire and Steel DVD. Okay it's only old 4:3 ratio, and the original video isn't the richest of sources, but it was still rather fun.
On a more productive front I've been working on a Apache::Registry/CGI-BIN based RSS client. I'm trying to make a small and simple client, but is more robust than a simple hack. By using the rather excellent Cache::FileCache module, CGI and my XML::RSS::Tools, I've been able to knock up a simple enough client in less than 200 lines of code.
If you have never used DeWitt Clinton's very useful Cache::Cache then you are missing a very useful set of modules. I first spotted it when reading one of Randal's excellent WebTechniques Perl columns - "Getting One-Click Processing".
Re:Hrmmm
ajt on 2003-05-11T20:21:05
Not that sophisticated. My code is simple Apache::Registry application that takes the URI of a RSS Feed and the name of a XSL stylesheet, and it returns a nicely formatted HTML page. There is no real user interface, short of a HTML form you build yourself—which I have done.
In case anyone is interested here is the Perl code for my ultra-light RSS application. It will go into the next release of XML::RSS::Tools as a new example soon.
#!d:/bin/perl/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp;
use XML::RSS::Tools;
use Cache::FileCache;
$|++;
my $q = CGI->new;
my %config= (
xsl_path => "G:/apache/cgi-bin/",
css1 => "/style/style.css",
css2 => "/style/news-style.css",
title => "i r e d a l e consulting | News Feeds |",
language => "en-GB",
namespace=> "xhtml",
cache_depth => 1,
auto_purge => '+2h',
default_expire => '+1h',
cache_root => 'd:/tmp/FileCache/news');
my $input = process_params($q);
top_html($q, $input, \%config);
tad ("Usage: news2html.pl?site=uri;style=xsl[;cache=off |;debug=on]\n", $q)
unless $input->{uri} && $input->{xsl};
my ($cache, $cache_key, $data) = manage_cache($q, $input, \%config);
$data = process_rss_feed($q, $input, \%config) unless $data;
print $data;
end_fragment($q, $input);
$cache->set($cache_key, $data) if $cache;
%ENV = ();
exit;
#
# Process Input Paramaters
#
sub process_params {
my $q = shift;
my %p;
$p{uri} = $q->param("site") if $q->param("site");
$p{xsl} = $q->param("style") if $q->param("style");
$p{debug}= $q->param("debug") if $q->param("debug");
$p{cache_status} = lc($q->param("cache")) || "on";
return \%p;
}
#
# Output HTTP and HTML headers
#
sub top_html {
my $q = shift;
my $input = shift;
my $config= shift;
$input->{uri} = "No Site URI" unless $input->{uri};
$input->{xsl} = "No XSL stylesheet" unless $input->{xsl};
print $q->header(-type => "text/html",
-expires => $config->{default_expire}),
$q->start_html(-title => $config->{title} . " " . $input->{uri} . " and " . $input->{xsl},
-lang => $config->{language},
-style => {-src => $config->{css1},
-verbatim => '@import url(' . $config->{css2} . ');'}
);
print $q->comment("\nInput Conditions:\nURI: ", $input->{uri},
"\nxsl sheet: ", $input->{xsl},
"\nCache: ", $input->{cache_status}, "\n") if $input->{debug};
};
#
# Deal with adding, removing or retrieving data from cache
#
sub manage_cache {
my $q = shift;
my $input = shift;
my $config = shift;
my $cache_key = $input->{uri} . $input->{xsl};
my $cached_file;
my $c_handle = Cache::FileCache->new({namespace => $config->{namespace},
default_expires_in => $config->{default_expire},
auto_purge_interval => $config->{auto_purge},
cache_depth => $config->{cache_depth},
cache_root => $config->{cache_root},
auto_purge_on_set => 1 } ) || tad ("Unable to create Cache object", $q);
if ($input->{cache_status} eq "off") {
$c_handle->remove($cache_key);
} else {
$cached_file = $c_handle->get($cache_key);
$cached_file.= "\n<!-- Cached Fragment -->\n" if $cached_file && $input->{debug};
}
return $c_handle, $cache_key, $cached_file;
}
#
# Get and process RSS Feed
#
sub process_rss_feed{
my $q = shift;
my $input = shift;
my $config = shift;
my $rss = XML::RSS::Tools->new;
$rss->set_version(0);
$rss->set_http_client("lite");
if (! $rss->xsl_file($config->{xsl_path} . $input->{xsl})) {tad ($rss->as_string('error'), $q)};
print $q->comment("\nHTTP Client: " . $rss->get_http_client . "\n") if $input->{debug};
if (! $rss->rss_uri($input->{uri})) {tad ($rss->as_string('error'), $q)};
if ($rss->transform) {
return $rss->as_string;
} else {
tad ($rss->as_string('error'), $q);
}
}
#
# Handle the end of the page
#
sub end_fragment {
my $q = shift;
my $input = shift;
my $ref = $q->referer() || "";
my $self = $q->self_url;
print $q->hr, $q->start_div({-id => "navigation"});
print $q->a({-href => $ref,
-title => "Click to Go Back"}, "Go Back"), " " if $ref;
print $q->a({-href => "view-source: " . $input->{uri},
-title => "Click to See Source RSS Feed (Opens a New Window)",
-target=> "_blank"}, "View RSS"), " ",
$q->a({-href => "view-source:$self",
-title => "View HTML Page Source"}, "View HTML"), " ";
$self.= ";cache=off" unless $self =~ /cache=off/;
print $q->a({-href => "$self",
-title => "Reload RSS Feed From Source"}, "Refresh Feed"),
$q->end_div, $q->end_html;
}
#
# Gracefully die
#
sub tad {
my $error = shift || "Unkown Error";
my $q = shift;
warn $error;
print $q->hr, $q->h1("News 2 HTML Error:"), $q->h2($error), $q->hr, $q->end_html;
%ENV = ();
exit;
}