#!/usr/bin/perl use CGI::Fast qw/:cgi/; use Blerg::Database; use URI::Escape; use POSIX qw/strftime/; use MIME::Base64; use strict; my $baseurl = Blerg::Database::constant('BASEURL'); sub xml_escape { local $_ = shift; s/&/&/g; s//>/g; return $_; } sub decode_basic_auth { my ($q) = @_; my ($method, $base64) = split(/\s+/, $q->http('Authorization')); if (!defined $method) { return; } elsif ($method ne 'Basic') { return; } my ($username, $password) = split(':', decode_base64($base64), 2); if (!defined $username) { return; } return ($username, $password); } sub print_401 { print header(-type => 'text/html', -status => '401 Unauthorized', -WWW_Authenticate => 'Basic realm="blerg"'); print <

401 Unauthorized

Please log in. DOC } sub print_404 { print header(-type => 'text/html', -status => '404 Not Found'); print <

404 Not Found

Not Found DOC } sub fetch_records { my @out; local $_; foreach (@_) { my $b = Blerg::Database->open_existing($_->{author}); my $data = $b->fetch($_->{record}); if (!defined $data) { $b->close; next; } my $timestamp = $b->timestamp($_->{record}); $b->close; push @out, { author => $_->{author}, record => $_->{record}, data => $data, timestamp => $timestamp, }; } return @out; } sub print_rss { my ($type, $name, @items) = @_; my ($title, $link); if ($type eq 'user') { $title = "${name}'s blërg"; $link = "${baseurl}#$name"; } elsif ($type eq 'feed') { $title = "${name}'s stalking feed"; $link = "${baseurl}#/feed"; } elsif ($type eq 'tag' || $type eq 'ref') { $title = $name; my $basename = $name; $basename =~ s/^.//; $link = "${baseurl}#/$type/$basename"; } print < $title $link Textual vomit HEADER for my $i (@items) { my $author = defined $i->{author} ? $i->{author} : $name; my $data = xml_escape(qq{\@$author
$i->{data}}); my $post_time = strftime("%a, %d %b %Y %H:%M:%S %Z", localtime($i->{timestamp})); print < $post_time ${baseurl}get/$author/$i->{record} ${baseurl}#$author/$i->{record} $data ITEM } print <<'FOOTER'
FOOTER } REQUEST: while (my $q = new CGI::Fast) { $q->charset('utf8'); my @path = split('/', $ENV{PATH_INFO}); shift @path; if ($path[0] eq 'feed') { my ($username, $password) = decode_basic_auth($q); if (!defined $username) { print_401; next REQUEST; } if (!Blerg::Database::auth_check_password($username, $password)) { print_401; next REQUEST; } my $b = Blerg::Database->open_existing($username); my @list = fetch_records($b->subscription_list()); $b->close; print header(-type => 'application/rss+xml'); print_rss(feed => $username, @list); } elsif (@path == 1) { # Assume this is a username; redirect to /user/ my $username = $path[0]; my $b = Blerg::Database->open_existing($username); if (!defined $b) { print_404; next REQUEST; } print header(-type => 'application/rss+xml', -charset => 'utf8', -status => '301 Moved Permanently', -location => "${baseurl}rss/user/$username"); # And present the content in case their client is broken my $i = { record => '?failed_redirect', timestamp => time, data => qq{Your RSS aggregator is dumb and isn't following 301 redirects. Please manually redirect it here: ${baseurl}rss/user/$username} }; print_rss(user => $username, $i); } elsif ($path[0] eq 'user') { my $username = $path[1]; my $b = Blerg::Database->open_existing($username); if (!defined $b) { print_404; next REQUEST; } print header(-type => 'application/rss+xml'); my $n = $b->record_count - 1; my @list = reverse map { { record => $_, data => $b->fetch($_), timestamp => $b->timestamp($_), } } ($n > 50 ? $n - 50 : 0)..$n; $b->close; print_rss(user => $username, @list); } elsif ($path[0] eq 'tag' || $path[0] eq 'ref') { my $tag = $path[1]; my $atag; if ($path[0] eq 'tag') { $atag = '#' . $tag; } else { $atag = '@' . $tag; } my @list = fetch_records(Blerg::Database::tag_list($atag, 0, -1)); print header(-type => 'application/rss+xml'); print_rss($path[0] => $atag, @list); } }