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