1<?php
2
3namespace Sabre\VObject;
4
5class ReaderTest extends \PHPUnit_Framework_TestCase {
6
7    function testReadComponent() {
8
9        $data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR";
10
11        $result = Reader::read($data);
12
13        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
14        $this->assertEquals('VCALENDAR', $result->name);
15        $this->assertEquals(0, count($result->children));
16
17    }
18    function testReadStream() {
19
20        $data = "BEGIN:VCALENDAR\r\nEND:VCALENDAR";
21
22        $stream = fopen('php://memory', 'r+');
23        fwrite($stream, $data);
24        rewind($stream);
25
26        $result = Reader::read($stream);
27
28        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
29        $this->assertEquals('VCALENDAR', $result->name);
30        $this->assertEquals(0, count($result->children));
31
32    }
33
34    function testReadComponentUnixNewLine() {
35
36        $data = "BEGIN:VCALENDAR\nEND:VCALENDAR";
37
38        $result = Reader::read($data);
39
40        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
41        $this->assertEquals('VCALENDAR', $result->name);
42        $this->assertEquals(0, count($result->children));
43
44    }
45
46    function testReadComponentLineFold() {
47
48        $data = "BEGIN:\r\n\tVCALENDAR\r\nE\r\n ND:VCALENDAR";
49
50        $result = Reader::read($data);
51
52        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
53        $this->assertEquals('VCALENDAR', $result->name);
54        $this->assertEquals(0, count($result->children));
55
56    }
57
58    /**
59     * @expectedException Sabre\VObject\ParseException
60     */
61    function testReadCorruptComponent() {
62
63        $data = "BEGIN:VCALENDAR\r\nEND:FOO";
64
65        $result = Reader::read($data);
66
67    }
68
69    /**
70     * @expectedException Sabre\VObject\ParseException
71     */
72    function testReadCorruptSubComponent() {
73
74        $data = "BEGIN:VCALENDAR\r\nBEGIN:VEVENT\r\nEND:FOO\r\nEND:VCALENDAR";
75
76        $result = Reader::read($data);
77
78    }
79
80    function testReadProperty() {
81
82        $data = "BEGIN:VCALENDAR\r\nSUMMARY:propValue\r\nEND:VCALENDAR";
83        $result = Reader::read($data);
84
85        $result = $result->SUMMARY;
86        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
87        $this->assertEquals('SUMMARY', $result->name);
88        $this->assertEquals('propValue', $result->getValue());
89
90    }
91
92    function testReadPropertyWithNewLine() {
93
94        $data = "BEGIN:VCALENDAR\r\nSUMMARY:Line1\\nLine2\\NLine3\\\\Not the 4th line!\r\nEND:VCALENDAR";
95        $result = Reader::read($data);
96
97        $result = $result->SUMMARY;
98        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
99        $this->assertEquals('SUMMARY', $result->name);
100        $this->assertEquals("Line1\nLine2\nLine3\\Not the 4th line!", $result->getValue());
101
102    }
103
104    function testReadMappedProperty() {
105
106        $data = "BEGIN:VCALENDAR\r\nDTSTART:20110529\r\nEND:VCALENDAR";
107        $result = Reader::read($data);
108
109        $result = $result->DTSTART;
110        $this->assertInstanceOf('Sabre\\VObject\\Property\\ICalendar\\DateTime', $result);
111        $this->assertEquals('DTSTART', $result->name);
112        $this->assertEquals('20110529', $result->getValue());
113
114    }
115
116    function testReadMappedPropertyGrouped() {
117
118        $data = "BEGIN:VCALENDAR\r\nfoo.DTSTART:20110529\r\nEND:VCALENDAR";
119        $result = Reader::read($data);
120
121        $result = $result->DTSTART;
122        $this->assertInstanceOf('Sabre\\VObject\\Property\\ICalendar\\DateTime', $result);
123        $this->assertEquals('DTSTART', $result->name);
124        $this->assertEquals('20110529', $result->getValue());
125
126    }
127
128    /**
129     * @expectedException Sabre\VObject\ParseException
130     */
131    function testReadBrokenLine() {
132
133        $data = "BEGIN:VCALENDAR\r\nPROPNAME;propValue";
134        $result = Reader::read($data);
135
136    }
137
138    function testReadPropertyInComponent() {
139
140        $data = array(
141            "BEGIN:VCALENDAR",
142            "PROPNAME:propValue",
143            "END:VCALENDAR"
144        );
145
146        $result = Reader::read(implode("\r\n",$data));
147
148        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
149        $this->assertEquals('VCALENDAR', $result->name);
150        $this->assertEquals(1, count($result->children()));
151        $this->assertInstanceOf('Sabre\\VObject\\Property', $result->children[0]);
152        $this->assertEquals('PROPNAME', $result->children[0]->name);
153        $this->assertEquals('propValue', $result->children[0]->getValue());
154
155    }
156
157    function testReadNestedComponent() {
158
159        $data = array(
160            "BEGIN:VCALENDAR",
161            "BEGIN:VTIMEZONE",
162            "BEGIN:DAYLIGHT",
163            "END:DAYLIGHT",
164            "END:VTIMEZONE",
165            "END:VCALENDAR"
166        );
167
168        $result = Reader::read(implode("\r\n",$data));
169
170        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
171        $this->assertEquals('VCALENDAR', $result->name);
172        $this->assertEquals(1, count($result->children()));
173        $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children[0]);
174        $this->assertEquals('VTIMEZONE', $result->children[0]->name);
175        $this->assertEquals(1, count($result->children[0]->children()));
176        $this->assertInstanceOf('Sabre\\VObject\\Component', $result->children[0]->children[0]);
177        $this->assertEquals('DAYLIGHT', $result->children[0]->children[0]->name);
178
179
180    }
181
182    function testReadPropertyParameter() {
183
184        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue\r\nEND:VCALENDAR";
185        $result = Reader::read($data);
186
187        $result = $result->PROPNAME;
188
189        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
190        $this->assertEquals('PROPNAME', $result->name);
191        $this->assertEquals('propValue', $result->getValue());
192        $this->assertEquals(1, count($result->parameters()));
193        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
194        $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue());
195
196    }
197
198    function testReadPropertyRepeatingParameter() {
199
200        $data = "BEGIN:VCALENDAR\r\nPROPNAME;N=1;N=2;N=3,4;N=\"5\",6;N=\"7,8\";N=9,10;N=^'11^':propValue\r\nEND:VCALENDAR";
201        $result = Reader::read($data);
202
203        $result = $result->PROPNAME;
204
205        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
206        $this->assertEquals('PROPNAME', $result->name);
207        $this->assertEquals('propValue', $result->getValue());
208        $this->assertEquals(1, count($result->parameters()));
209        $this->assertEquals('N', $result->parameters['N']->name);
210        $this->assertEquals('1,2,3,4,5,6,7,8,9,10,"11"', $result->parameters['N']->getValue());
211        $this->assertEquals(array(1,2,3,4,5,6,"7,8",9,10,'"11"'), $result->parameters['N']->getParts());
212
213    }
214
215    function testReadPropertyRepeatingNamelessGuessedParameter() {
216        $data = "BEGIN:VCALENDAR\r\nPROPNAME;WORK;VOICE;PREF:propValue\r\nEND:VCALENDAR";
217        $result = Reader::read($data);
218
219        $result = $result->PROPNAME;
220
221        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
222        $this->assertEquals('PROPNAME', $result->name);
223        $this->assertEquals('propValue', $result->getValue());
224        $this->assertEquals(1, count($result->parameters()));
225        $this->assertEquals('TYPE', $result->parameters['TYPE']->name);
226        $this->assertEquals('WORK,VOICE,PREF', $result->parameters['TYPE']->getValue());
227        $this->assertEquals(array('WORK', 'VOICE', 'PREF'), $result->parameters['TYPE']->getParts());
228
229    }
230
231    function testReadPropertyNoName() {
232
233        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PRODIGY:propValue\r\nEND:VCALENDAR";
234        $result = Reader::read($data);
235
236        $result = $result->PROPNAME;
237
238        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
239        $this->assertEquals('PROPNAME', $result->name);
240        $this->assertEquals('propValue', $result->getValue());
241        $this->assertEquals(1, count($result->parameters()));
242        $this->assertEquals('TYPE', $result->parameters['TYPE']->name);
243        $this->assertTrue($result->parameters['TYPE']->noName);
244        $this->assertEquals('PRODIGY', $result->parameters['TYPE']);
245
246    }
247
248    function testReadPropertyParameterExtraColon() {
249
250        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue:propValue:anotherrandomstring\r\nEND:VCALENDAR";
251        $result = Reader::read($data);
252
253        $result = $result->PROPNAME;
254
255        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
256        $this->assertEquals('PROPNAME', $result->name);
257        $this->assertEquals('propValue:anotherrandomstring', $result->getValue());
258        $this->assertEquals(1, count($result->parameters()));
259        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
260        $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue());
261
262    }
263
264    function testReadProperty2Parameters() {
265
266        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue;PARAMNAME2=paramvalue2:propValue\r\nEND:VCALENDAR";
267        $result = Reader::read($data);
268
269        $result = $result->PROPNAME;
270
271        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
272        $this->assertEquals('PROPNAME', $result->name);
273        $this->assertEquals('propValue', $result->getValue());
274        $this->assertEquals(2, count($result->parameters()));
275        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
276        $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue());
277        $this->assertEquals('PARAMNAME2', $result->parameters['PARAMNAME2']->name);
278        $this->assertEquals('paramvalue2', $result->parameters['PARAMNAME2']->getValue());
279
280    }
281
282    function testReadPropertyParameterQuoted() {
283
284        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"paramvalue\":propValue\r\nEND:VCALENDAR";
285        $result = Reader::read($data);
286
287        $result = $result->PROPNAME;
288
289        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
290        $this->assertEquals('PROPNAME', $result->name);
291        $this->assertEquals('propValue', $result->getValue());
292        $this->assertEquals(1, count($result->parameters()));
293        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
294        $this->assertEquals('paramvalue', $result->parameters['PARAMNAME']->getValue());
295
296    }
297
298    function testReadPropertyParameterNewLines() {
299
300        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=paramvalue1^nvalue2^^nvalue3:propValue\r\nEND:VCALENDAR";
301        $result = Reader::read($data);
302
303        $result = $result->propname;
304
305        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
306        $this->assertEquals('PROPNAME', $result->name);
307        $this->assertEquals('propValue', $result->getValue());
308
309        $this->assertEquals(1, count($result->parameters()));
310        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
311        $this->assertEquals("paramvalue1\nvalue2^nvalue3", $result->parameters['PARAMNAME']->getValue());
312
313    }
314
315    function testReadPropertyParameterQuotedColon() {
316
317        $data = "BEGIN:VCALENDAR\r\nPROPNAME;PARAMNAME=\"param:value\":propValue\r\nEND:VCALENDAR";
318        $result = Reader::read($data);
319        $result = $result->propname;
320
321        $this->assertInstanceOf('Sabre\\VObject\\Property', $result);
322        $this->assertEquals('PROPNAME', $result->name);
323        $this->assertEquals('propValue', $result->getValue());
324        $this->assertEquals(1, count($result->parameters()));
325        $this->assertEquals('PARAMNAME', $result->parameters['PARAMNAME']->name);
326        $this->assertEquals('param:value', $result->parameters['PARAMNAME']->getValue());
327
328    }
329
330    function testReadForgiving() {
331
332        $data = array(
333            "BEGIN:VCALENDAR",
334            "X_PROP:propValue",
335            "END:VCALENDAR"
336        );
337
338        $caught = false;
339        try {
340            $result = Reader::read(implode("\r\n",$data));
341        } catch (ParseException $e) {
342            $caught = true;
343        }
344
345        $this->assertEquals(true, $caught);
346
347        $result = Reader::read(implode("\r\n",$data), Reader::OPTION_FORGIVING);
348
349        $expected = implode("\r\n", array(
350            "BEGIN:VCALENDAR",
351            "X_PROP:propValue",
352            "END:VCALENDAR",
353            ""
354        ));
355
356        $this->assertEquals($expected, $result->serialize());
357
358    }
359
360    function testReadWithInvalidLine() {
361
362        $data = array(
363            "BEGIN:VCALENDAR",
364            "DESCRIPTION:propValue",
365            "Yes, we've actually seen a file with non-idented property values on multiple lines",
366            "END:VCALENDAR"
367        );
368
369        $caught = false;
370        try {
371            $result = Reader::read(implode("\r\n",$data));
372        } catch (ParseException $e) {
373            $caught = true;
374        }
375
376        $this->assertEquals(true, $caught);
377
378        $result = Reader::read(implode("\r\n",$data), Reader::OPTION_IGNORE_INVALID_LINES);
379
380        $expected = implode("\r\n", array(
381            "BEGIN:VCALENDAR",
382            "DESCRIPTION:propValue",
383            "END:VCALENDAR",
384            ""
385        ));
386
387        $this->assertEquals($expected, $result->serialize());
388
389    }
390
391    /**
392     * Reported as Issue 32.
393     *
394     * @expectedException \Sabre\VObject\ParseException
395     */
396    public function testReadIncompleteFile() {
397
398        $input = <<<ICS
399BEGIN:VCALENDAR
400VERSION:1.0
401BEGIN:VEVENT
402X-FUNAMBOL-FOLDER:DEFAULT_FOLDER
403X-FUNAMBOL-ALLDAY:0
404DTSTART:20111017T110000Z
405DTEND:20111017T123000Z
406X-MICROSOFT-CDO-BUSYSTATUS:BUSY
407CATEGORIES:
408LOCATION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Netviewer Meeting
409PRIORITY:1
410STATUS:3
411X-MICROSOFT-CDO-REPLYTIME:20111017T064200Z
412SUMMARY;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:Kopieren: test
413CLASS:PUBLIC
414AALARM:
415RRULE:
416X-FUNAMBOL-BILLINGINFO:
417X-FUNAMBOL-COMPANIES:
418X-FUNAMBOL-MILEAGE:
419X-FUNAMBOL-NOAGING:0
420ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Heino' heino@test.com
421ATTENDEE;STATUS=NEEDS ACTION;ENCODING=QUOTED-PRINTABLE;CHARSET=UTF-8:'Markus' test@test.com
422ATTENDEE;STATUS=NEEDS AC
423ICS;
424
425        Reader::read($input);
426
427    }
428
429    /**
430     * @expectedException \InvalidArgumentException
431     */
432    public function testReadBrokenInput() {
433
434        Reader::read(false);
435
436    }
437
438    public function testReadBOM() {
439
440        $data = chr(0xef) . chr(0xbb) . chr(0xbf) . "BEGIN:VCALENDAR\r\nEND:VCALENDAR";
441        $result = Reader::read($data);
442
443        $this->assertInstanceOf('Sabre\\VObject\\Component', $result);
444        $this->assertEquals('VCALENDAR', $result->name);
445        $this->assertEquals(0, count($result->children));
446
447    }
448
449}
450