diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/PublicInbox/Mbox.pm | 64 | ||||
-rw-r--r-- | lib/PublicInbox/WWW.pm | 8 |
2 files changed, 67 insertions, 5 deletions
diff --git a/lib/PublicInbox/Mbox.pm b/lib/PublicInbox/Mbox.pm index fc9df1ad..cb9d65d1 100644 --- a/lib/PublicInbox/Mbox.pm +++ b/lib/PublicInbox/Mbox.pm @@ -11,8 +11,7 @@ sub thread_mbox { my ($ctx, $srch) = @_; sub { my ($response) = @_; # Plack callback - my $w = $response->([200, ['Content-Type' => 'text/plain']]); - emit_mbox($w, $ctx, $srch); + emit_mbox($response, $ctx, $srch); } } @@ -40,7 +39,14 @@ sub emit_msg { } sub emit_mbox { - my ($fh, $ctx, $srch) = @_; + my ($response, $ctx, $srch) = @_; + eval { require IO::Compress::Gzip }; + return need_gzip($response) if $@; + + # http://www.iana.org/assignments/media-types/application/gzip + # http://www.iana.org/assignments/media-types/application/mbox + my $fh = $response->([200, ['Content-Type' => 'application/gzip']]); + $fh = PublicInbox::MboxGz->new($fh); require PublicInbox::GitCatFile; require Email::Simple; @@ -62,6 +68,58 @@ sub emit_mbox { $opts{offset} += $nr; } while ($nr > 0); + + $fh->close; +} + +sub need_gzip { + my $fh = $_[0]->([501, ['Content-Type' => 'text/html']]); + my $title = 'gzipped mbox not available'; + $fh->write(<<EOF); +<html><head><title>$title</title><body><pre>$title +The administrator needs to install the IO::Compress::Gzip Perl module +to support gzipped mboxes. +<a href="../">Return to index</a></pre></body></html> +EOF +} + +1; + +# fh may not be a proper IO, so we wrap the write and close methods +# to prevent IO::Compress::Gzip from complaining +package PublicInbox::MboxGz; +use strict; +use warnings; +use fields qw(gz fh buf); + +sub new { + my ($class, $fh) = @_; + my $self = fields::new($class); + my $buf; + $self->{buf} = \$buf; + $self->{gz} = IO::Compress::Gzip->new(\$buf); + $self->{fh} = $fh; + $self; +} + +sub _flush_buf { + my ($self) = @_; + if (defined ${$self->{buf}}) { + $self->{fh}->write(${$self->{buf}}); + ${$self->{buf}} = undef; + } +} + +sub write { + $_[0]->{gz}->write($_[1]); + _flush_buf($_[0]); +} + +sub close { + my ($self) = @_; + $self->{gz}->close; + _flush_buf($self); + # do not actually close $fh } 1; diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm index cd8a5705..68839d7c 100644 --- a/lib/PublicInbox/WWW.pm +++ b/lib/PublicInbox/WWW.pm @@ -53,7 +53,8 @@ sub run { } elsif ($path_info =~ m!$LISTNAME_RE/t/(\S+)\.html\z!o) { invalid_list_mid(\%ctx, $1, $2) || get_thread(\%ctx, $cgi); - } elsif ($path_info =~ m!$LISTNAME_RE/t/(\S+)\.mbox\z!o) { + } elsif ($path_info =~ m!$LISTNAME_RE/t/(\S+)\.mbox\.gz!o) { + my $sfx = $3; invalid_list_mid(\%ctx, $1, $2) || get_thread_mbox(\%ctx, $cgi); } elsif ($path_info =~ m!$LISTNAME_RE/f/\S+\.txt\z!o) { @@ -329,7 +330,10 @@ sub msg_pfx { "../f/$href.html"; } -# /$LISTNAME/t/$MESSAGE_ID.mbox -> search results as mbox +# /$LISTNAME/t/$MESSAGE_ID.mbox.gz -> search results as gzipped mbox +# note: I'm not a big fan of other compression formats since they're +# significantly more expensive on CPU than gzip and less-widely available, +# especially on older systems. Stick to zlib since that's what git uses. sub get_thread_mbox { my ($ctx, $cgi) = @_; my $srch = searcher($ctx) or return need_search($ctx); |