X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;f=rss.cgi;h=3eed7e26bd90408dc44cb10c240e29d0164b8820;hb=948ce5be6ef6bba36edfb544565ca22e316afb0a;hp=b207874991f20277666554cfd4deecb26b286ee3;hpb=681f470b41ea3674089425b5227a5b0b76291118;p=blerg.git diff --git a/rss.cgi b/rss.cgi index b207874..3eed7e2 100755 --- a/rss.cgi +++ b/rss.cgi @@ -3,6 +3,7 @@ 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'); @@ -15,6 +16,35 @@ sub xml_escape { 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'); @@ -25,25 +55,67 @@ 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 ($name, @items) = @_; + 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 < - ${name}'s blërg - ${baseurl}#$name + $title + $link Textual vomit HEADER for my $i (@items) { - my $data = xml_escape($i->{data}); - my $post_time = strftime("%a, %d %b %Y %H:%M:%S %Z", gmtime($i->{timestamp})); + my $author = defined $i->{author} ? $i->{author} : $name; + my $data = xml_escape(qq{\@$author
$i->{data}}); + my $title = xml_escape(substr($i->{data}, 0, 27)) . "..."; + my $post_time = strftime("%a, %d %b %Y %H:%M:%S %Z", localtime($i->{timestamp})); print < + $title $post_time - ${baseurl}get/$name/$i->{record} + ${baseurl}get/$author/$i->{record} + ${baseurl}#$author/$i->{record} $data ITEM @@ -57,10 +129,28 @@ FOOTER REQUEST: while (my $q = new CGI::Fast) { + $q->charset('utf8'); my @path = split('/', $ENV{PATH_INFO}); shift @path; - if (@path == 1) { + 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); @@ -73,16 +163,12 @@ while (my $q = new CGI::Fast) { -status => '301 Moved Permanently', -location => "${baseurl}rss/user/$username"); # And present the content in case their client is broken - 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($username, @list); + 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); @@ -100,9 +186,19 @@ while (my $q = new CGI::Fast) { } } ($n > 50 ? $n - 50 : 0)..$n; $b->close; - print_rss($username, @list); - } elsif ($path[0] eq 'tag') { - } elsif ($path[0] eq 'ref') { - } elsif ($path[0] eq 'feed') { + 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); } }