+# called by PSGI server as body response
+# this gets called twice for every message, once to return the header,
+# once to retrieve the body
+sub getline {
+ my ($ctx) = @_; # ctx
+ my $smsg = $ctx->{smsg} or return;
+ my $ibx = $ctx->{ibx};
+ my $eml = $ibx->smsg_eml($smsg) or return;
+ my $n = $ctx->{smsg} = $ibx->over->next_by_mid(@{$ctx->{next_arg}});
+ $ctx->zmore(msg_hdr($ctx, $eml));
+ if ($n) {
+ $ctx->translate(msg_body($eml));
+ } else { # last message
+ $ctx->zmore(msg_body($eml));
+ $ctx->zflush;
+ }
+}
+
+# called by PublicInbox::DS::write after http->next_step
+sub async_next {
+ my ($http) = @_; # PublicInbox::HTTP
+ my $ctx = $http->{forward} or return; # client aborted
+ eval {
+ my $smsg = $ctx->{smsg} or return $ctx->close;
+ $ctx->smsg_blob($smsg);
+ };
+ warn "E: $@" if $@;
+}
+
+sub async_eml { # for async_blob_cb
+ my ($ctx, $eml) = @_;
+ my $smsg = delete $ctx->{smsg};
+ # next message
+ $ctx->{smsg} = $ctx->{ibx}->over->next_by_mid(@{$ctx->{next_arg}});
+
+ $ctx->zmore(msg_hdr($ctx, $eml));
+ $ctx->{http_out}->write($ctx->translate(msg_body($eml)));
+}
+
+sub res_hdr ($$) {
+ my ($ctx, $subject) = @_;
+ my $fn = $subject // '';
+ $fn =~ s/^re:\s+//i;
+ $fn = to_filename($fn) // 'no-subject';
+ my @hdr = ('Content-Type');
+ if ($ctx->{ibx}->{obfuscate}) {
+ # obfuscation is stupid, but maybe scrapers are, too...
+ push @hdr, 'application/mbox';
+ $fn .= '.mbox';
+ } else {
+ push @hdr, 'text/plain';
+ $fn .= '.txt';
+ }
+ push @hdr, 'Content-Disposition', "inline; filename=$fn";
+ \@hdr;
+}
+
+# for rare cases where v1 inboxes aren't indexed w/ ->over at all
+sub no_over_raw ($) {
+ my ($ctx) = @_;
+ my $mref = $ctx->{ibx}->msg_by_mid($ctx->{mid}) or return;
+ my $eml = PublicInbox::Eml->new($mref);
+ [ 200, res_hdr($ctx, $eml->header_str('Subject')),
+ [ msg_hdr($ctx, $eml) . msg_body($eml) ] ]
+}