1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
# Copyright (C) 2016-2021 all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
use strict; use v5.10.1; use PublicInbox::TestCommon;
use PublicInbox::Hval qw(ascii_html);
use MIME::QuotedPrint 3.05 qw(encode_qp);
use_ok('PublicInbox::MsgIter');
{
my $mime = eml_load 't/msg_iter-order.eml';
my @parts;
msg_iter($mime, sub {
my ($part, $level, @ex) = @{$_[0]};
my $s = $part->body_str;
$s =~ s/\s+//s;
push @parts, [ $s, $level, @ex ];
});
is_deeply(\@parts, [ [ qw(a 1 1) ], [ qw(b 1 2) ] ], 'order is fine');
}
{
my $mime = eml_load 't/msg_iter-nested.eml';
my @parts;
msg_iter($mime, sub {
my ($part, $level, @ex) = @{$_[0]};
my $s = $part->body_str;
$s =~ s/\s+//s;
push @parts, [ $s, $level, @ex ];
});
is_deeply(\@parts, [ [qw(a 2 1.1)], [qw(b 2 1.2)], [qw(sig 1 2)] ],
'nested part shows up properly');
}
{
my $mime = eml_load 't/iso-2202-jp.eml';
my $raw = '';
msg_iter($mime, sub {
my ($part, $level, @ex) = @{$_[0]};
my ($s, $err) = msg_part_text($part, 'text/plain');
ok(!$err, 'no error');
$raw .= $s;
});
ok(length($raw) > 0, 'got non-empty message');
is(index($raw, '$$$'), -1, 'no unescaped $$$');
}
{
my $mime = eml_load 't/x-unknown-alpine.eml';
my $raw = '';
msg_iter($mime, sub {
my ($part, $level, @ex) = @{$_[0]};
my ($s, $err) = msg_part_text($part, 'text/plain');
$raw .= $s;
});
like($raw, qr!^\thttps://!ms, 'tab expanded with X-UNKNOWN');
like(ascii_html($raw), qr/• bullet point/s,
'got bullet point when X-UNKNOWN assumes UTF-8');
}
{ # API not finalized
my @warn;
local $SIG{__WARN__} = sub { push @warn, [ @_ ] };
my $attr = "So and so wrote:\n";
my $q = "> hello world\n" x 10;
my $nq = "hello world\n" x 10;
my @sections = PublicInbox::MsgIter::split_quotes($attr . $q . $nq);
is($sections[0], $attr, 'attribution matches');
is($sections[1], $q, 'quoted section matches');
is($sections[2], $nq, 'non-quoted section matches');
is(scalar(@sections), 3, 'only three sections for short message');
is_deeply(\@warn, [], 'no warnings');
$q x= 3300;
$nq x= 3300;
@sections = PublicInbox::MsgIter::split_quotes($attr . $q . $nq);
is_deeply(\@warn, [], 'no warnings on giant message');
is(join('', @sections), $attr . $q . $nq, 'result matches expected');
is(shift(@sections), $attr, 'attribution is first section');
my @check = ('', '');
while (defined(my $l = shift @sections)) {
next if $l eq '';
like($l, qr/\n\z/s, 'section ends with newline');
my $idx = ($l =~ /\A>/) ? 0 : 1;
$check[$idx] .= $l;
}
is($check[0], $q, 'long quoted section matches');
is($check[1], $nq, 'long quoted section matches');
}
{
open my $fh, '<', 't/utf8.eml' or BAIL_OUT $!;
my $expect = do { local $/; <$fh> };
my $qp_patch = encode_qp($expect, "\r\n");
my $common = <<EOM;
Content-Type: multipart/mixed; boundary="DEADBEEF"
MIME-Version: 1.0
--DEADBEEF
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=utf-8
blah
--DEADBEEF
Content-Disposition: attachment;
filename=foo.patch
Content-Type: application/octet-stream;
x-unix-mode=0644;
name="foo.patch"
Content-Transfer-Encoding: quoted-printable
EOM
my $eml = PublicInbox::Eml->new(<<EOM);
$common
$qp_patch
--DEADBEEF--
EOM
my @parts;
$eml->each_part(sub {
my ($part, $level, @ex) = @{$_[0]};
my ($s, $err) = msg_part_text($part, $part->content_type);
push @parts, $s;
});
$expect =~ s/\n/\r\n/sg;
utf8::decode($expect); # aka "bytes2str"
is_deeply(\@parts, [ "blah\r\n", $expect ],
'fallback to application/octet-stream as UTF-8 text');
my $qp_binary = encode_qp("Binary\0crap", "\r\n");
$eml = PublicInbox::Eml->new(<<EOM);
$common
$qp_binary
--DEADBEEF--
EOM
@parts = ();
my @err;
$eml->each_part(sub {
my ($part, $level, @ex) = @{$_[0]};
my ($s, $err) = msg_part_text($part, $part->content_type);
push @parts, $s;
push @err, $err;
});
is_deeply(\@parts, [ "blah\r\n", undef ],
'non-text ignored in octet-stream');
ok($err[1], 'got error for second element');
}
done_testing();
|