1<?php
2/**
3 * Copyright 2010-2017 Horde LLC (http://www.horde.org/)
4 *
5 * @category   Horde
6 * @copyright  2010-2016 Horde LLC
7 * @license    http://www.horde.org/licenses/lgpl21 LGPL 2.1
8 * @package    Mime
9 * @subpackage UnitTests
10 */
11
12/**
13 * Tests for the Horde_Mime_Headers_ContentParam class.
14 *
15 * @author     Michael Slusarz <slusarz@horde.org>
16 * @category   Horde
17 * @copyright  2010-2016 Horde LLC
18 * @internal
19 * @license    http://www.horde.org/licenses/lgpl21 LGPL 2.1
20 * @package    Mime
21 * @subpackage UnitTests
22 */
23class Horde_Mime_ContentParamTest extends PHPUnit_Framework_TestCase
24{
25    /**
26     * @dataProvider encodeProvider
27     */
28    public function testEncode($params, $opts, $expected)
29    {
30        $cp = new Horde_Mime_Headers_ContentParam('NOT_USED', $params);
31
32        ksort($expected);
33        $params = $cp->encode($opts);
34        ksort($params);
35
36        $this->assertEquals(
37            $expected,
38            $params
39        );
40    }
41
42    public function encodeProvider()
43    {
44        return array(
45            array(
46                array(
47                    'bar' => 'foo',
48                    'test' => str_repeat('a', 100) . '.txt'
49                ),
50                array(
51                    'broken_rfc2231' => true
52                ),
53                array(
54                    'bar' => 'foo',
55                    'test' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt',
56                    'test*0' =>'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
57                    'test*1' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt'
58                )
59            ),
60            array(
61                array(
62                    'bar' => 'foo',
63                    'test' => str_repeat('a', 100) . '.txt'
64                ),
65                array(
66                    'broken_rfc2231' => false
67                ),
68                array(
69                    'bar' => 'foo',
70                    'test*0' =>'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
71                    'test*1' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.txt'
72                )
73            ),
74            array(
75                array(
76                    'foo' => "\x01"
77                ),
78                array(),
79                array(
80                    'foo' => "\"\x01\""
81                )
82            ),
83            // Bug #12127 (part 1)
84            array(
85                array(
86                    'foo' => 'test'
87                ),
88                array(
89                    'broken_rfc2231' => true,
90                    'charset' => 'UTF-16LE'
91                ),
92                array(
93                    'foo' => 'test'
94                )
95            ),
96            // Bug #12127 (part 2)
97            array(
98                array(
99                    'foo' => 'ā'
100                ),
101                array(
102                    'broken_rfc2231' => true,
103                    'charset' => 'UTF-16LE'
104                ),
105                array(
106                    'foo*' => "utf-16le''%01%01",
107                    'foo' => '"=?utf-16le?b?AQE=?="'
108                )
109            )
110        );
111    }
112
113    /**
114     * @dataProvider decodeProvider
115     */
116    public function testDecode($in, $val_expected, $params_expected)
117    {
118        $cp = new Horde_Mime_Headers_ContentParam('NOT_USED', $in);
119
120        $this->assertEquals(
121            $val_expected,
122            $cp->value
123        );
124
125
126        ksort($params_expected);
127        $params = $cp->params;
128        ksort($params);
129
130        $this->assertEquals(
131            $params_expected,
132            $params
133        );
134    }
135
136    public function decodeProvider()
137    {
138        return array(
139            array(
140                'foo',
141                'foo',
142                array()
143            ),
144            array(
145                'foo=bar',
146                null,
147                array(
148                    'foo' => 'bar'
149                )
150            ),
151            array(
152                'test ; foo = bar ; baz = "goo"',
153                'test',
154                array(
155                    'baz' => 'goo',
156                    'foo' => 'bar'
157                )
158            ),
159            array(
160                'test ; foo*1=B; foo*0="A"; foo*3=D; foo*2="C";foo*5=F;' .
161                'foo*4="E"; foo*7=H; foo*6="G"; foo*9=J; foo*8=I; foo*11=L; ' .
162                'bar  =  Z  ;  foo*10=K;',
163                'test',
164                array(
165                    'bar' => 'Z',
166                    'foo' => 'ABCDEFGHIJKL'
167                )
168            ),
169            array(
170                "attachment; size=147502;\n filename*=utf-8''Factura%20n%C2%BA%2010.pdf",
171                'attachment',
172                array(
173                    'size' => '147502',
174                    'filename' => 'Factura nº 10.pdf'
175                )
176            ),
177            // Bug #13587
178            array(
179                "multipart/mixed; boundary=\"EPOC32-8'4Lqb7RwmJkJ+8bx'NRLMC2SXt1Ls'Gfpd0RMtxgP6JQFKj\"",
180                'multipart/mixed',
181                array(
182                    'boundary' => "EPOC32-8'4Lqb7RwmJkJ+8bx'NRLMC2SXt1Ls'Gfpd0RMtxgP6JQFKj"
183                )
184            ),
185            // Gmail
186            array(
187                // Content-Disposition
188                "attachment;\n filename=\"=?UTF-8?Q?Vantagens_da_Caixa_para_Empresas_e_alterac=CC=A7a=CC=83o_do_prec=CC=A7?=\n =?UTF-8?Q?a=CC=81rio=2Epdf?=\"",
189                'attachment',
190                array(
191                    'filename' => 'Vantagens da Caixa para Empresas e alteração do preçário.pdf'
192                )
193            ),
194            array(
195                // Content-Type
196                "application/pdf;\nname=\"=?UTF-8?Q?Vantagens_da_Caixa_para_Empresas_e_alterac=CC=A7a=CC=83o_do_prec=CC=A7?=\n =?UTF-8?Q?a=CC=81rio=2Epdf?=\"",
197                'application/pdf',
198                array(
199                    'name' => 'Vantagens da Caixa para Empresas e alteração do preçário.pdf'
200                )
201            ),
202            // mail.app
203            // Note: filename/name parameter value is NOT the same UTF-8
204            // string as the Gmail examples above; character length is the
205            // same, but Gmail byte-length is 4 bytes longer (they are using
206            // different Unicode points to display the 4 non-ASCII chars)
207            array(
208                // Content-Disposition
209                "inline;\n filename*=iso-8859-1''Vantagens%20da%20Caixa%20para%20Empresas%20e%20altera%E7%E3o%20do%20pre%E7%E1rio.pdf",
210                'inline',
211                array(
212                    'filename' => 'Vantagens da Caixa para Empresas e alteração do preçário.pdf'
213                )
214            ),
215            array(
216                // Content-Type
217                "application/pdf;\n name=\"=?iso-8859-1?Q?Vantagens_da_Caixa_para_Empresas_e_altera=E7=E3o_?=\n =?iso-8859-1?Q?do_pre=E7=E1rio=2Epdf?=\"",
218                'application/pdf',
219                array(
220                    'name' => 'Vantagens da Caixa para Empresas e alteração do preçário.pdf'
221                )
222            ),
223            // Params with different cases (params are case-insensitive)
224            array(
225                "kEy*1=b; KEY*0=a; key*2=c",
226                null,
227                array(
228                    'key' => 'abc'
229                )
230            ),
231            // Adapted from Dovecot's src/lib-mail/test-rfc2231-parser.c
232            array(
233                "key4*=us-ascii''foo" .
234                "; key*2=ba%" .
235                "; key2*0=a" .
236                "; key3*0*=us-ascii'en'xyz" .
237                "; key*0=\"foo\"" .
238                "; key2*1*=b%25" .
239                "; key3*1=plop%" .
240                "; key*1=baz",
241                null,
242                array(
243                    'key' => 'foobazba%',
244                    'key2' => 'ab%',
245                    'key3' => 'xyzplop%',
246                    'key4' => 'foo'
247                )
248            )
249        );
250    }
251
252}
253