]> Sergey Matveev's repositories - public-inbox.git/commitdiff
atom: implement message threading per RFC 4685
authorEric Wong <e@80x24.org>
Tue, 13 Dec 2016 02:33:30 +0000 (02:33 +0000)
committerEric Wong <e@80x24.org>
Sat, 17 Dec 2016 05:42:04 +0000 (05:42 +0000)
This will allows certain feed readers to render a message thread
as described in <https://www.jwz.org/doc/threading.html>.

Feed readers with knowledge of of RFC 4685 are unknown to us at
this time, but perhaps this will encourage future implementations.

Existing feed readers I've tested (newsbeuter, feed2imap) seem
to ignore these tags gracefully without degradation.

TODO
lib/PublicInbox/WwwAtomStream.pm

diff --git a/TODO b/TODO
index 55720a2cb505df7c8c69cf88218761a1f49d4196..b85887ad80c3e1ebdfdc64615fde6d62c273c7ae 100644 (file)
--- a/TODO
+++ b/TODO
@@ -34,8 +34,6 @@ all need to be considered for everything we introduce)
   the links should point to an anchor tag within the same page,
   instead; giving the user options.
 
-* implement RFC 4685 (Atom message threading)
-
 * configurable constants (index limits, search results)
 
 * handle messages with multiple Message-IDs
index 5720384cf648f4f50c93f661f2ab467bf2392d77..a6817b31475c4e2df23c9d2ab141d56f64a09b1f 100644 (file)
@@ -9,10 +9,10 @@ use warnings;
 # FIXME: locale-independence:
 use POSIX qw(strftime);
 use Date::Parse qw(strptime);
-
+use Digest::SHA qw(sha1_hex);
 use PublicInbox::Address;
 use PublicInbox::Hval qw(ascii_html);
-use PublicInbox::MID qw/mid_clean mid2path mid_escape/;
+use PublicInbox::MID qw/mid_clean mid_escape/;
 
 # called by PSGI server after getline:
 sub close {}
@@ -72,7 +72,8 @@ sub atom_header {
        my $mtime = (stat($ibx->{mainrepo}))[9] || time;
 
        qq(<?xml version="1.0" encoding="us-ascii"?>\n) .
-       qq{<feed\nxmlns="http://www.w3.org/2005/Atom">} .
+       qq(<feed\nxmlns="http://www.w3.org/2005/Atom"\n) .
+       qq(xmlns:thr="http://purl.org/syndication/thread/1.0">) .
        qq{$title} .
        qq(<link\nrel="alternate"\ntype="text/html") .
                qq(\nhref="$base_url"/>) .
@@ -81,22 +82,33 @@ sub atom_header {
        feed_updated(gmtime($mtime));
 }
 
+sub mid2uuid ($) {
+       my ($mid) = @_;
+       utf8::encode($mid); # really screwed up In-Reply-To fields exist
+       $mid = sha1_hex($mid);
+       my $h = '[a-f0-9]';
+       my (@uuid5) = ($mid =~ m!\A($h{8})($h{4})($h{4})($h{4})($h{12})!o);
+       'urn:uuid:' . join('-', @uuid5);
+}
+
 # returns undef or string
 sub feed_entry {
        my ($self, $mime) = @_;
        my $ctx = $self->{ctx};
        my $hdr = $mime->header_obj;
        my $mid = mid_clean($hdr->header_raw('Message-ID'));
-
-       my $uuid = mid2path($mid);
-       $uuid =~ tr!/!!d;
-       my $h = '[a-f0-9]';
-       my (@uuid5) = ($uuid =~ m!\A($h{8})($h{4})($h{4})($h{4})($h{12})!o);
-       $uuid = 'urn:uuid:' . join('-', @uuid5);
-
-       $mid = PublicInbox::Hval->new_msgid($mid);
-       my $href = $ctx->{feed_base_url} . $mid->{href}. '/';
-
+       my $irt = PublicInbox::View::in_reply_to($hdr);
+       my $uuid = mid2uuid($mid);
+       my $base = $ctx->{feed_base_url};
+       if (defined $irt) {
+               my $irt_uuid = mid2uuid($irt);
+               $irt = mid_escape($irt);
+               $irt = qq(<thr:in-reply-to\nref="$irt_uuid"\n).
+                       qq(href="$base$irt/"/>);
+       } else {
+               $irt = '';
+       }
+       my $href = $base . mid_escape($mid) . '/';
        my $date = $hdr->header('Date');
        my @t = eval { strptime($date) } if defined $date;
        @t = gmtime(time) unless scalar @t;
@@ -124,7 +136,7 @@ sub feed_entry {
                PublicInbox::View::multipart_text_as_html($mime, $href) .
                '</pre>' .
                qq!</div></content><link\nhref="$href"/>!.
-               "<id>$uuid</id></entry>";
+               "<id>$uuid</id>$irt</entry>";
 }
 
 sub feed_updated {