use Blerg::Database;
use URI::Escape;
use POSIX qw/strftime/;
+use MIME::Base64;
use strict;
my $baseurl = Blerg::Database::constant('BASEURL');
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 <<DOC;
+<!DOCTYPE html>
+<h1>401 Unauthorized</h1>
+Please log in.
+DOC
+}
+
sub print_404 {
print header(-type => 'text/html',
-status => '404 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) = @_;
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;
HEADER
for my $i (@items) {
- my $data = xml_escape($i->{data});
- my $post_time = strftime("%a, %d %b %Y %H:%M:%S %Z", localtime($i->{timestamp}));
my $author = defined $i->{author} ? $i->{author} : $name;
+ my $data = xml_escape(qq{<a href="${baseurl}#$author"><strong>\@$author</strong></a><br> $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 <<ITEM;
<item>
+ <title>$title</title>
<pubDate>$post_time</pubDate>
<guid>${baseurl}get/$author/$i->{record}</guid>
+ <link>${baseurl}#$author/$i->{record}</link>
<description>$data</description>
</item>
ITEM
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/<username>
my $username = $path[0];
my $b = Blerg::Database->open_existing($username);
# And present the content in case their client is broken
my $i = {
record => '?failed_redirect',
- timestamp => time,
+ 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);
} ($n > 50 ? $n - 50 : 0)..$n;
$b->close;
print_rss(user => $username, @list);
- } elsif ($path[0] eq 'tag') {
+ } elsif ($path[0] eq 'tag' || $path[0] eq 'ref') {
my $tag = $path[1];
- $tag =~ s/^H/#/;
- my @list = Blerg::Database::tag_list($tag, 0, -1);
- @list = map {
- my $b = Blerg::Database->open_existing($_->{author});
- my $data = $b->fetch($_->{record});
- my $timestamp = $b->timestamp($_->{record});
- $b->close;
- {
- author => $_->{author},
- record => $_->{record},
- data => $data,
- timestamp => $timestamp,
- };
- } @list;
- print header(-type => 'application/rss+xml');
- if (substr($tag, 0, 1) eq '#') {
- print_rss(tag => $tag, @list);
+ my $atag;
+ if ($path[0] eq 'tag') {
+ $atag = '#' . $tag;
} else {
- print_rss(ref => $tag, @list);
+ $atag = '@' . $tag;
}
- } elsif ($path[0] eq 'ref') {
- } elsif ($path[0] eq 'feed') {
+
+ my @list = fetch_records(Blerg::Database::tag_list($atag, 0, -1));
+
+ print header(-type => 'application/rss+xml');
+ print_rss($path[0] => $atag, @list);
}
}