]> Sergey Matveev's repositories - public-inbox.git/blob - t/eml_content_type.t
www: drop --subject from "git send-email" instructions
[public-inbox.git] / t / eml_content_type.t
1 #!perl -w
2 # Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
3 # Copyright (C) 2004- Simon Cozens, Casey West, Ricardo SIGNES
4 # This library is free software; you can redistribute it and/or modify
5 # it under the same terms as Perl itself.
6 #
7 # License: GPL-1.0+ or Artistic-1.0-Perl
8 #  <https://www.gnu.org/licenses/gpl-1.0.txt>
9 #  <https://dev.perl.org/licenses/artistic.html>
10 use strict;
11 use Test::More;
12 use PublicInbox::EmlContentFoo qw(parse_content_type);
13
14 my %ct_tests = (
15         '' => {
16                 type       => "text",
17                 subtype    => "plain",
18                 attributes => { charset => "us-ascii" }
19         },
20
21         "text/plain" => {
22                 type => "text",
23                 subtype => "plain",
24                 attributes => {}
25         },
26         'text/plain; charset=us-ascii' => {
27                 type       => "text",
28                 subtype    => "plain",
29                 attributes => { charset => "us-ascii" }
30         },
31         'text/plain; charset="us-ascii"' => {
32                 type       => "text",
33                 subtype    => "plain",
34                 attributes => { charset => "us-ascii" }
35         },
36         "text/plain; charset=us-ascii (Plain text)" => {
37                 type       => "text",
38                 subtype    => "plain",
39                 attributes => { charset => "us-ascii" }
40         },
41
42         'text/plain; charset=ISO-8859-1' => {
43                 type       => "text",
44                 subtype    => "plain",
45                 attributes => { charset => "ISO-8859-1" }
46         },
47         'text/plain; charset="ISO-8859-1"' => {
48                 type       => "text",
49                 subtype    => "plain",
50                 attributes => { charset => "ISO-8859-1" }
51         },
52         'text/plain; charset="ISO-8859-1" (comment)' => {
53                 type       => "text",
54                 subtype    => "plain",
55                 attributes => { charset => "ISO-8859-1" }
56         },
57
58         '(c) text/plain (c); (c) charset=ISO-8859-1 (c)' => {
59                 type       => "text",
60                 subtype    => "plain",
61                 attributes => { charset => "ISO-8859-1" }
62         },
63         '(c \( \\\\) (c) text/plain (c) (c) ; (c) (c) charset=utf-8 (c)' => {
64                 type       => "text",
65                 subtype    => "plain",
66                 attributes => { charset => "utf-8" }
67         },
68         'text/plain; (c (nested ()c)another c)() charset=ISO-8859-1' => {
69                 type       => "text",
70                 subtype    => "plain",
71                 attributes => { charset => "ISO-8859-1" }
72         },
73         'text/plain (c \(!nested ()c\)\)(nested\(c())); charset=utf-8' => {
74                 type       => "text",
75                 subtype    => "plain",
76                 attributes => { charset => "utf-8" }
77         },
78
79         "application/foo" => {
80                 type       => "application",
81                 subtype    => "foo",
82                 attributes => {}
83         },
84         "multipart/mixed; boundary=unique-boundary-1" => {
85                 type       => "multipart",
86                 subtype    => "mixed",
87                 attributes => { boundary => "unique-boundary-1" }
88         },
89         'message/external-body; access-type=local-file; name="/u/n/m.jpg"' => {
90                 type       => "message",
91                 subtype    => "external-body",
92                 attributes => {
93                         "access-type" => "local-file",
94                         "name"        => "/u/n/m.jpg"
95                 }
96         },
97         'multipart/mixed; boundary="----------=_1026452699-10321-0" ' => {
98                 'type'       => 'multipart',
99                 'subtype'    => 'mixed',
100                 'attributes' => {
101                         'boundary' => '----------=_1026452699-10321-0'
102                 }
103         },
104         'multipart/report; boundary= "=_0=73e476c3-cd5a-5ba3-b910-2="' => {
105                 'type'       => 'multipart',
106                 'subtype'    => 'report',
107                 'attributes' => {
108                         'boundary' => '=_0=73e476c3-cd5a-5ba3-b910-2='
109                 }
110         },
111         'multipart/report; boundary=' . " \t" . '"=_0=7-c-5-b-2="' => {
112                 'type'       => 'multipart',
113                 'subtype'    => 'report',
114                 'attributes' => {
115                         'boundary' => '=_0=7-c-5-b-2='
116                 }
117         },
118
119         'message/external-body; access-type=URL;' .
120         ' URL*0="ftp://";' .
121         ' URL*1="example.com/"' => {
122                 'type'       => 'message',
123                 'subtype'    => 'external-body',
124                 'attributes' => {
125                         'access-type' => 'URL',
126                         'url' => 'ftp://example.com/'
127                 }
128         },
129         'message/external-body; access-type=URL; URL="ftp://example.com/"' => {
130                 'type'       => 'message',
131                 'subtype'    => 'external-body',
132                 'attributes' => {
133                         'access-type' => 'URL',
134                         'url' => 'ftp://example.com/',
135                 }
136         },
137
138         "application/x-stuff; title*=us-ascii'en-us'This%20is%20f%2Ad" => {
139                 'type'       => 'application',
140                 'subtype'    => 'x-stuff',
141                 'attributes' => {
142                         'title' => 'This is f*d'
143                 }
144         },
145         "application/x-stuff; title*=us-ascii''This%20is%20f%2Ad" => {
146                 'type'       => 'application',
147                 'subtype'    => 'x-stuff',
148                 'attributes' => {
149                         'title' => 'This is f*d'
150                 }
151         },
152         "application/x-stuff; title*=''This%20is%20f%2Ad" => {
153                 'type'       => 'application',
154                 'subtype'    => 'x-stuff',
155                 'attributes' => {
156                         'title' => 'This is f*d'
157                 }
158         },
159         "application/x-stuff; title*='en-us'This%20is%20f%2Ad" => {
160                 'type'       => 'application',
161                 'subtype'    => 'x-stuff',
162                 'attributes' => {
163                         'title' => 'This is f*d'
164                 }
165         },
166         q(application/x-stuff;) .
167         q( title*0*=us-ascii'en'This%20is%20even%20more%20;) .
168         q(title*1*=%2A%2A%2Afun%2A%2A%2A%20; title*2="isn't it!") => {
169                 'type'       => 'application',
170                 'subtype'    => 'x-stuff',
171                 'attributes' => {
172                         'title' => "This is even more ***fun*** isn't it!"
173                 }
174         },
175         q(application/x-stuff;) .
176         q( title*0*='en'This%20is%20even%20more%20;) .
177         q( title*1*=%2A%2A%2Afun%2A%2A%2A%20; title*2="isn't it!") => {
178                 'type'       => 'application',
179                 'subtype'    => 'x-stuff',
180                 'attributes' => {
181                         'title' => "This is even more ***fun*** isn't it!"
182                 }
183         },
184         q(application/x-stuff;) .
185         q( title*0*=''This%20is%20even%20more%20;) .
186         q( title*1*=%2A%2A%2Afun%2A%2A%2A%20; title*2="isn't it!") => {
187                 'type'       => 'application',
188                 'subtype'    => 'x-stuff',
189                 'attributes' => {
190                         'title' => "This is even more ***fun*** isn't it!"
191                 }
192         },
193         q(application/x-stuff;).
194         q( title*0*=us-ascii''This%20is%20even%20more%20;).
195         q( title*1*=%2A%2A%2Afun%2A%2A%2A%20; title*2="isn't it!")
196           => {
197                 'type'       => 'application',
198                 'subtype'    => 'x-stuff',
199                 'attributes' => {
200                         'title' => "This is even more ***fun*** isn't it!"
201                 }
202         },
203
204         'text/plain; attribute="v\"v\\\\v\(v\>\<\)\@\,\;\:\/\]\[\?\=v v";' .
205         ' charset=us-ascii' => {
206                 'type'       => 'text',
207                 'subtype'    => 'plain',
208                 'attributes' => {
209                         'attribute' => 'v"v\\v(v><)@,;:/][?=v v',
210                         'charset' => 'us-ascii',
211                 },
212         },
213
214         qq(text/plain;\r
215          charset=us-ascii;\r
216          attribute="\r value1 \r value2\r\n value3\r\n value4\r\n "\r\n ) => {
217                 'type'       => 'text',
218                 'subtype'    => 'plain',
219                 'attributes' => {
220                         'attribute' => ' value1  value2 value3 value4 ',
221                         'charset'   => 'us-ascii',
222                 },
223         },
224 );
225
226 my %non_strict_ct_tests = (
227         "text/plain;" => { type => "text", subtype => "plain", attributes => {} },
228         "text/plain; " =>
229           { type => "text", subtype => "plain", attributes => {} },
230         'image/jpeg;' .
231         ' x-mac-type="3F3F3F3F";'.
232         ' x-mac-creator="3F3F3F3F" name="file name.jpg";' => {
233                 type       => "image",
234                 subtype    => "jpeg",
235                 attributes => {
236                         'x-mac-type'    => "3F3F3F3F",
237                         'x-mac-creator' => "3F3F3F3F",
238                         'name'          => "file name.jpg"
239                 }
240         },
241         "text/plain; key=very long value" => {
242                 type       => "text",
243                 subtype    => "plain",
244                 attributes => { key => "very long value" }
245         },
246         "text/plain; key=very long value key2=value2" => {
247                 type    => "text",
248                 subtype => "plain",
249                 attributes => { key => "very long value", key2 => "value2" }
250         },
251         'multipart/mixed; boundary = "--=_Next_Part_24_Nov_2016_08.09.21"' => {
252                 type    => "multipart",
253                 subtype => "mixed",
254                 attributes => {
255                         boundary => "--=_Next_Part_24_Nov_2016_08.09.21"
256                 }
257         },
258 );
259
260 sub test {
261         my ($string, $expect, $info) = @_;
262
263         local $_;
264         $info =~ s/\r/\\r/g;
265         $info =~ s/\n/\\n/g;
266         is_deeply(parse_content_type($string), $expect, $info);
267 }
268
269 for (sort keys %ct_tests) {
270         test($_, $ct_tests{$_}, "Can parse C-T <$_>");
271 }
272
273 local $PublicInbox::EmlContentFoo::STRICT_PARAMS = 0;
274 for (sort keys %ct_tests) {
275         test($_, $ct_tests{$_}, "Can parse non-strict C-T <$_>");
276 }
277 for (sort keys %non_strict_ct_tests) {
278         test(
279                 $_,
280                 $non_strict_ct_tests{$_},
281                 "Can parse non-strict C-T <$_>"
282         );
283 }
284
285 done_testing;