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.
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>
12 use PublicInbox::EmlContentFoo qw(parse_content_type);
18 attributes => { charset => "us-ascii" }
26 'text/plain; charset=us-ascii' => {
29 attributes => { charset => "us-ascii" }
31 'text/plain; charset="us-ascii"' => {
34 attributes => { charset => "us-ascii" }
36 "text/plain; charset=us-ascii (Plain text)" => {
39 attributes => { charset => "us-ascii" }
42 'text/plain; charset=ISO-8859-1' => {
45 attributes => { charset => "ISO-8859-1" }
47 'text/plain; charset="ISO-8859-1"' => {
50 attributes => { charset => "ISO-8859-1" }
52 'text/plain; charset="ISO-8859-1" (comment)' => {
55 attributes => { charset => "ISO-8859-1" }
58 '(c) text/plain (c); (c) charset=ISO-8859-1 (c)' => {
61 attributes => { charset => "ISO-8859-1" }
63 '(c \( \\\\) (c) text/plain (c) (c) ; (c) (c) charset=utf-8 (c)' => {
66 attributes => { charset => "utf-8" }
68 'text/plain; (c (nested ()c)another c)() charset=ISO-8859-1' => {
71 attributes => { charset => "ISO-8859-1" }
73 'text/plain (c \(!nested ()c\)\)(nested\(c())); charset=utf-8' => {
76 attributes => { charset => "utf-8" }
79 "application/foo" => {
80 type => "application",
84 "multipart/mixed; boundary=unique-boundary-1" => {
87 attributes => { boundary => "unique-boundary-1" }
89 'message/external-body; access-type=local-file; name="/u/n/m.jpg"' => {
91 subtype => "external-body",
93 "access-type" => "local-file",
94 "name" => "/u/n/m.jpg"
97 'multipart/mixed; boundary="----------=_1026452699-10321-0" ' => {
98 'type' => 'multipart',
101 'boundary' => '----------=_1026452699-10321-0'
104 'multipart/report; boundary= "=_0=73e476c3-cd5a-5ba3-b910-2="' => {
105 'type' => 'multipart',
106 'subtype' => 'report',
108 'boundary' => '=_0=73e476c3-cd5a-5ba3-b910-2='
111 'multipart/report; boundary=' . " \t" . '"=_0=7-c-5-b-2="' => {
112 'type' => 'multipart',
113 'subtype' => 'report',
115 'boundary' => '=_0=7-c-5-b-2='
119 'message/external-body; access-type=URL;' .
121 ' URL*1="example.com/"' => {
123 'subtype' => 'external-body',
125 'access-type' => 'URL',
126 'url' => 'ftp://example.com/'
129 'message/external-body; access-type=URL; URL="ftp://example.com/"' => {
131 'subtype' => 'external-body',
133 'access-type' => 'URL',
134 'url' => 'ftp://example.com/',
138 "application/x-stuff; title*=us-ascii'en-us'This%20is%20f%2Ad" => {
139 'type' => 'application',
140 'subtype' => 'x-stuff',
142 'title' => 'This is f*d'
145 "application/x-stuff; title*=us-ascii''This%20is%20f%2Ad" => {
146 'type' => 'application',
147 'subtype' => 'x-stuff',
149 'title' => 'This is f*d'
152 "application/x-stuff; title*=''This%20is%20f%2Ad" => {
153 'type' => 'application',
154 'subtype' => 'x-stuff',
156 'title' => 'This is f*d'
159 "application/x-stuff; title*='en-us'This%20is%20f%2Ad" => {
160 'type' => 'application',
161 'subtype' => 'x-stuff',
163 'title' => 'This is f*d'
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',
172 'title' => "This is even more ***fun*** isn't it!"
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',
181 'title' => "This is even more ***fun*** isn't it!"
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',
190 'title' => "This is even more ***fun*** isn't it!"
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!")
197 'type' => 'application',
198 'subtype' => 'x-stuff',
200 'title' => "This is even more ***fun*** isn't it!"
204 'text/plain; attribute="v\"v\\\\v\(v\>\<\)\@\,\;\:\/\]\[\?\=v v";' .
205 ' charset=us-ascii' => {
207 'subtype' => 'plain',
209 'attribute' => 'v"v\\v(v><)@,;:/][?=v v',
210 'charset' => 'us-ascii',
216 attribute="\r value1 \r value2\r\n value3\r\n value4\r\n "\r\n ) => {
218 'subtype' => 'plain',
220 'attribute' => ' value1 value2 value3 value4 ',
221 'charset' => 'us-ascii',
226 my %non_strict_ct_tests = (
227 "text/plain;" => { type => "text", subtype => "plain", attributes => {} },
229 { type => "text", subtype => "plain", attributes => {} },
231 ' x-mac-type="3F3F3F3F";'.
232 ' x-mac-creator="3F3F3F3F" name="file name.jpg";' => {
236 'x-mac-type' => "3F3F3F3F",
237 'x-mac-creator' => "3F3F3F3F",
238 'name' => "file name.jpg"
241 "text/plain; key=very long value" => {
244 attributes => { key => "very long value" }
246 "text/plain; key=very long value key2=value2" => {
249 attributes => { key => "very long value", key2 => "value2" }
251 'multipart/mixed; boundary = "--=_Next_Part_24_Nov_2016_08.09.21"' => {
255 boundary => "--=_Next_Part_24_Nov_2016_08.09.21"
261 my ($string, $expect, $info) = @_;
266 is_deeply(parse_content_type($string), $expect, $info);
269 for (sort keys %ct_tests) {
270 test($_, $ct_tests{$_}, "Can parse C-T <$_>");
273 local $PublicInbox::EmlContentFoo::STRICT_PARAMS = 0;
274 for (sort keys %ct_tests) {
275 test($_, $ct_tests{$_}, "Can parse non-strict C-T <$_>");
277 for (sort keys %non_strict_ct_tests) {
280 $non_strict_ct_tests{$_},
281 "Can parse non-strict C-T <$_>"