1 # Copyright (C) 2014, Eric Wong <normalperson@yhbt.net> and all contributors
2 # License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
3 package PublicInbox::View;
6 use CGI qw/escapeHTML escape/;
7 use Encode qw/decode encode/;
8 use Encode::MIME::Header;
10 # only one public function:
12 my ($class, $mime) = @_;
14 headers_to_html_header($mime) .
15 multipart_text_as_html($mime) .
19 # only private functions below.
21 sub multipart_text_as_html {
26 # scan through all parts, looking for displayable text
27 $mime->walk_parts(sub {
29 return if $part->subparts; # walk_parts already recurses
31 my $part_type = $part->content_type;
32 if ($part_type =~ m!\btext/[a-z0-9\+\._-]+\b!i) {
33 my $fn = $part->filename;
36 defined($fn) or $fn = "part #$part_nr";
37 $rv .= add_filename_line($fn);
40 # n.b. $part->body should already be decoded if text
41 $rv .= escapeHTML($part->body);
42 $rv .= "\n" unless $rv =~ /\n\z/s;
44 $rv .= "-- part #$part_nr ";
45 $rv .= escapeHTML($part_type);
53 sub add_filename_line {
59 $pad x= ($len/2) if ($len > 0);
60 "$pad " . escapeHTML($fn) . " $pad\n";
66 my $html = escapeHTML($mid);
67 my $href = escapeHTML(escape($mid));
72 sub headers_to_html_header {
77 foreach my $h (qw(From To Cc Subject Date)) {
78 my $v = $simple->header($h);
80 $v = decode("MIME-Header", $v);
81 $v = encode("utf8", $v);
86 if ($h eq "From" || $h eq "Subject") {
91 my $mid = $simple->header('Message-ID');
93 my ($html, $href) = trim_message_id($mid);
94 $rv .= "Message-ID: <a href=$href.html>$html</a> ";
95 $rv .= "(<a href=$href.txt>raw message</a>)\n";
98 my $irp = $simple->header('In-Reply-To');
100 my ($html, $href) = trim_message_id($irp);
101 $rv .= "In-Reply-To: <a href=$href.html>$html</a>\n";
105 return ("<html><head><title>".
106 join(' - ', @title) .
107 '</title></head><body><pre style="white-space:pre-wrap">' .