1 <?php
2 
3 namespace Sabre\CalDAV;
4 
5 use Sabre\DAV;
6 use Sabre\HTTP;
7 use Sabre\VObject;
8 use Sabre\DAVACL;
9 
10 require_once 'Sabre/CalDAV/TestUtil.php';
11 require_once 'Sabre/HTTP/ResponseMock.php';
12 
13 class ICSExportPluginTest extends \PHPUnit_Framework_TestCase {
14 
15     function setUp() {
16 
17         if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available');
18 
19     }
20 
21     function testInit() {
22 
23         $p = new ICSExportPlugin();
24         $s = new DAV\Server();
25         $s->addPlugin($p);
26         $this->assertEquals($p, $s->getPlugin('ics-export'));
27 
28     }
29 
30     function testBeforeMethod() {
31 
32         $cbackend = TestUtil::getBackend();
33 
34         $props = [
35             'uri'=>'UUID-123467',
36             'principaluri' => 'admin',
37             'id' => 1,
38             '{DAV:}displayname' => 'Hello!',
39             '{http://apple.com/ns/ical/}calendar-color' => '#AA0000FF',
40         ];
41         $tree = [
42             new Calendar($cbackend,$props),
43         ];
44 
45         $p = new ICSExportPlugin();
46 
47         $s = new DAV\Server($tree);
48         $s->addPlugin($p);
49         $s->addPlugin(new Plugin());
50 
51         $h = HTTP\Sapi::createFromServerArray([
52             'REQUEST_URI' => '/UUID-123467?export',
53             'REQUEST_METHOD' => 'GET',
54         ]);
55 
56         $s->httpRequest = $h;
57         $s->httpResponse = new HTTP\ResponseMock();
58 
59         $this->assertFalse($p->httpGet($h, $s->httpResponse));
60 
61         $this->assertEquals(200, $s->httpResponse->status);
62         $this->assertEquals([
63             'Content-Type' => ['text/calendar'],
64         ], $s->httpResponse->getHeaders());
65 
66         $obj = VObject\Reader::read($s->httpResponse->body);
67 
68         $this->assertEquals(7,count($obj->children()));
69         $this->assertEquals(1,count($obj->VERSION));
70         $this->assertEquals(1,count($obj->CALSCALE));
71         $this->assertEquals(1,count($obj->PRODID));
72         $this->assertTrue(strpos((string)$obj->PRODID, DAV\Version::VERSION)!==false);
73         $this->assertEquals(1,count($obj->VTIMEZONE));
74         $this->assertEquals(1,count($obj->VEVENT));
75         $this->assertEquals("Hello!", $obj->{"X-WR-CALNAME"});
76         $this->assertEquals("#AA0000FF", $obj->{"X-APPLE-CALENDAR-COLOR"});
77 
78     }
79     function testBeforeMethodNoVersion() {
80 
81         if (!SABRE_HASSQLITE) $this->markTestSkipped('SQLite driver is not available');
82         $cbackend = TestUtil::getBackend();
83 
84         $props = [
85             'uri'=>'UUID-123467',
86             'principaluri' => 'admin',
87             'id' => 1,
88         ];
89         $tree = [
90             new Calendar($cbackend,$props),
91         ];
92 
93         $p = new ICSExportPlugin();
94 
95         $s = new DAV\Server($tree);
96 
97         $s->addPlugin($p);
98         $s->addPlugin(new Plugin());
99 
100         $h = HTTP\Sapi::createFromServerArray([
101             'REQUEST_URI' => '/UUID-123467?export',
102             'REQUEST_METHOD' => 'GET',
103         ]);
104 
105         $s->httpRequest = $h;
106         $s->httpResponse = new HTTP\ResponseMock();
107 
108         DAV\Server::$exposeVersion = false;
109         $this->assertFalse($p->httpGet($h, $s->httpResponse));
110         DAV\Server::$exposeVersion = true;
111 
112         $this->assertEquals(200, $s->httpResponse->status);
113         $this->assertEquals([
114             'Content-Type' => ['text/calendar'],
115         ], $s->httpResponse->getHeaders());
116 
117         $obj = VObject\Reader::read($s->httpResponse->body);
118 
119         $this->assertEquals(5,count($obj->children()));
120         $this->assertEquals(1,count($obj->VERSION));
121         $this->assertEquals(1,count($obj->CALSCALE));
122         $this->assertEquals(1,count($obj->PRODID));
123         $this->assertFalse(strpos((string)$obj->PRODID, DAV\Version::VERSION)!==false);
124         $this->assertEquals(1,count($obj->VTIMEZONE));
125         $this->assertEquals(1,count($obj->VEVENT));
126 
127     }
128 
129     function testBeforeMethodNoExport() {
130 
131         $p = new ICSExportPlugin();
132 
133         $s = new DAV\Server();
134         $s->addPlugin($p);
135 
136         $h = HTTP\Sapi::createFromServerArray([
137             'REQUEST_URI' => '/UUID-123467',
138             'REQUEST_METHOD' => 'GET',
139         ]);
140         $this->assertNull($p->httpGet($h, $s->httpResponse));
141 
142     }
143 
144     function testACLIntegrationBlocked() {
145 
146         $cbackend = TestUtil::getBackend();
147 
148         $props = array(
149             'uri'=>'UUID-123467',
150             'principaluri' => 'admin',
151             'id' => 1,
152         );
153         $tree = array(
154             new Calendar($cbackend,$props),
155         );
156 
157         $p = new ICSExportPlugin();
158 
159         $s = new DAV\Server($tree);
160         $s->addPlugin($p);
161         $s->addPlugin(new Plugin());
162         $s->addPlugin(new DAVACL\Plugin());
163 
164         $h = HTTP\Sapi::createFromServerArray([
165             'REQUEST_URI' => '/UUID-123467?export',
166         ]);
167 
168         $s->httpRequest = $h;
169         $s->httpResponse = new HTTP\ResponseMock();
170 
171         $p->httpGet($h, $s->httpResponse);
172 
173         // If the ACL system blocked this request, the effect will be that
174         // there's no response, because the calendar information could not be
175         // fetched.
176         $this->assertNull($s->httpResponse->getStatus());
177 
178     }
179 
180     function testACLIntegrationNotBlocked() {
181 
182         $cbackend = TestUtil::getBackend();
183         $pbackend = new DAVACL\PrincipalBackend\Mock();
184 
185         $props = array(
186             'uri'=>'UUID-123467',
187             'principaluri' => 'admin',
188             'id' => 1,
189         );
190         $tree = array(
191             new Calendar($cbackend,$props),
192             new DAVACL\PrincipalCollection($pbackend),
193         );
194 
195         $p = new ICSExportPlugin();
196 
197         $s = new DAV\Server($tree);
198         $s->sapi = new HTTP\SapiMock();
199         $s->addPlugin($p);
200         $s->addPlugin(new Plugin());
201         $s->addPlugin(new DAVACL\Plugin());
202         $s->addPlugin(new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock(),'SabreDAV'));
203 
204         // Forcing login
205         $s->getPlugin('acl')->adminPrincipals = array('principals/admin');
206 
207 
208         $h = HTTP\Sapi::createFromServerArray([
209             'REQUEST_URI' => '/UUID-123467?export',
210             'REQUEST_METHOD' => 'GET',
211         ]);
212 
213         $s->httpRequest = $h;
214         $s->httpResponse = new HTTP\ResponseMock();
215 
216         $s->exec();
217 
218         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
219         $this->assertEquals(array(
220             'X-Sabre-Version' => [DAV\Version::VERSION],
221             'Content-Type' => ['text/calendar'],
222         ), $s->httpResponse->getHeaders());
223 
224         $obj = VObject\Reader::read($s->httpResponse->body);
225 
226         $this->assertEquals(5,count($obj->children()));
227         $this->assertEquals(1,count($obj->VERSION));
228         $this->assertEquals(1,count($obj->CALSCALE));
229         $this->assertEquals(1,count($obj->PRODID));
230         $this->assertEquals(1,count($obj->VTIMEZONE));
231         $this->assertEquals(1,count($obj->VEVENT));
232 
233     }
234 
235     function testBadStartParam() {
236 
237         $cbackend = TestUtil::getBackend();
238         $pbackend = new DAVACL\PrincipalBackend\Mock();
239 
240         $props = array(
241             'uri'=>'UUID-123467',
242             'principaluri' => 'admin',
243             'id' => 1,
244         );
245         $tree = array(
246             new Calendar($cbackend,$props),
247             new DAVACL\PrincipalCollection($pbackend),
248         );
249 
250         $p = new ICSExportPlugin();
251 
252         $s = new DAV\Server($tree);
253         $s->sapi = new HTTP\SapiMock();
254         $s->addPlugin($p);
255         $s->addPlugin(new Plugin());
256 
257         $h = HTTP\Sapi::createFromServerArray([
258             'REQUEST_URI' => '/UUID-123467?export&start=foo',
259             'REQUEST_METHOD' => 'GET',
260         ]);
261 
262         $s->httpRequest = $h;
263         $s->httpResponse = new HTTP\ResponseMock();
264 
265         $s->exec();
266 
267         $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
268 
269     }
270 
271     function testBadEndParam() {
272 
273         $cbackend = TestUtil::getBackend();
274         $pbackend = new DAVACL\PrincipalBackend\Mock();
275 
276         $props = array(
277             'uri'=>'UUID-123467',
278             'principaluri' => 'admin',
279             'id' => 1,
280         );
281         $tree = array(
282             new Calendar($cbackend,$props),
283             new DAVACL\PrincipalCollection($pbackend),
284         );
285 
286         $p = new ICSExportPlugin();
287 
288         $s = new DAV\Server($tree);
289         $s->sapi = new HTTP\SapiMock();
290         $s->addPlugin($p);
291         $s->addPlugin(new Plugin());
292 
293         $h = HTTP\Sapi::createFromServerArray([
294             'REQUEST_URI' => '/UUID-123467?export&end=foo',
295             'REQUEST_METHOD' => 'GET',
296         ]);
297 
298         $s->httpRequest = $h;
299         $s->httpResponse = new HTTP\ResponseMock();
300 
301         $s->exec();
302 
303         $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
304 
305     }
306 
307     function testFilterStartEnd() {
308 
309         $cbackend = TestUtil::getBackend();
310         $pbackend = new DAVACL\PrincipalBackend\Mock();
311 
312         $props = array(
313             'uri'=>'UUID-123467',
314             'principaluri' => 'admin',
315             'id' => 1,
316         );
317         $tree = array(
318             new Calendar($cbackend,$props),
319             new DAVACL\PrincipalCollection($pbackend),
320         );
321 
322         $p = new ICSExportPlugin();
323 
324         $s = new DAV\Server($tree);
325         $s->sapi = new HTTP\SapiMock();
326         $s->addPlugin($p);
327         $s->addPlugin(new Plugin());
328 
329         $h = HTTP\Sapi::createFromServerArray([
330             'REQUEST_URI' => '/UUID-123467?export&start=1&end=2',
331             'REQUEST_METHOD' => 'GET',
332         ]);
333 
334         $s->httpRequest = $h;
335         $s->httpResponse = new HTTP\ResponseMock();
336 
337         $s->exec();
338 
339         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
340         $obj = VObject\Reader::read($s->httpResponse->body);
341 
342         $this->assertEquals(0,count($obj->VTIMEZONE));
343         $this->assertEquals(0,count($obj->VEVENT));
344 
345     }
346 
347     function testExpandNoStart() {
348 
349         $cbackend = TestUtil::getBackend();
350         $pbackend = new DAVACL\PrincipalBackend\Mock();
351 
352         $props = array(
353             'uri'=>'UUID-123467',
354             'principaluri' => 'admin',
355             'id' => 1,
356         );
357         $tree = array(
358             new Calendar($cbackend,$props),
359             new DAVACL\PrincipalCollection($pbackend),
360         );
361 
362         $p = new ICSExportPlugin();
363 
364         $s = new DAV\Server($tree);
365         $s->sapi = new HTTP\SapiMock();
366         $s->addPlugin($p);
367         $s->addPlugin(new Plugin());
368 
369         $h = HTTP\Sapi::createFromServerArray([
370             'REQUEST_URI' => '/UUID-123467?export&expand=1&end=1',
371             'REQUEST_METHOD' => 'GET',
372         ]);
373 
374         $s->httpRequest = $h;
375         $s->httpResponse = new HTTP\ResponseMock();
376 
377         $s->exec();
378 
379         $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
380 
381     }
382 
383     function testExpand() {
384 
385         $cbackend = TestUtil::getBackend();
386         $pbackend = new DAVACL\PrincipalBackend\Mock();
387 
388         $props = array(
389             'uri'=>'UUID-123467',
390             'principaluri' => 'admin',
391             'id' => 1,
392         );
393         $tree = array(
394             new Calendar($cbackend,$props),
395             new DAVACL\PrincipalCollection($pbackend),
396         );
397 
398         $p = new ICSExportPlugin();
399 
400         $s = new DAV\Server($tree);
401         $s->sapi = new HTTP\SapiMock();
402         $s->addPlugin($p);
403         $s->addPlugin(new Plugin());
404 
405         $h = HTTP\Sapi::createFromServerArray([
406             'REQUEST_URI' => '/UUID-123467?export&start=1&end=2000000000&expand=1',
407             'REQUEST_METHOD' => 'GET',
408         ]);
409 
410         $s->httpRequest = $h;
411         $s->httpResponse = new HTTP\ResponseMock();
412 
413         $s->exec();
414 
415         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
416         $obj = VObject\Reader::read($s->httpResponse->body);
417 
418         $this->assertEquals(0,count($obj->VTIMEZONE));
419         $this->assertEquals(1,count($obj->VEVENT));
420 
421     }
422 
423     function testJCal() {
424 
425         $cbackend = TestUtil::getBackend();
426         $pbackend = new DAVACL\PrincipalBackend\Mock();
427 
428         $props = array(
429             'uri'=>'UUID-123467',
430             'principaluri' => 'admin',
431             'id' => 1,
432         );
433         $tree = array(
434             new Calendar($cbackend,$props),
435             new DAVACL\PrincipalCollection($pbackend),
436         );
437 
438         $p = new ICSExportPlugin();
439 
440         $s = new DAV\Server($tree);
441         $s->sapi = new HTTP\SapiMock();
442         $s->addPlugin($p);
443         $s->addPlugin(new Plugin());
444 
445         $h = HTTP\Sapi::createFromServerArray([
446             'REQUEST_URI' => '/UUID-123467?export',
447             'REQUEST_METHOD' => 'GET',
448             'HTTP_ACCEPT' => 'application/calendar+json',
449         ]);
450 
451         $s->httpRequest = $h;
452         $s->httpResponse = new HTTP\ResponseMock();
453 
454         $s->exec();
455 
456         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
457         $this->assertEquals('application/calendar+json', $s->httpResponse->getHeader('Content-Type'));
458 
459     }
460 
461     function testJCalInUrl() {
462 
463         $cbackend = TestUtil::getBackend();
464         $pbackend = new DAVACL\PrincipalBackend\Mock();
465 
466         $props = array(
467             'uri'=>'UUID-123467',
468             'principaluri' => 'admin',
469             'id' => 1,
470         );
471         $tree = array(
472             new Calendar($cbackend,$props),
473             new DAVACL\PrincipalCollection($pbackend),
474         );
475 
476         $p = new ICSExportPlugin();
477 
478         $s = new DAV\Server($tree);
479         $s->sapi = new HTTP\SapiMock();
480         $s->addPlugin($p);
481         $s->addPlugin(new Plugin());
482 
483         $h = HTTP\Sapi::createFromServerArray([
484             'REQUEST_URI' => '/UUID-123467?export&accept=jcal',
485             'REQUEST_METHOD' => 'GET',
486         ]);
487 
488         $s->httpRequest = $h;
489         $s->httpResponse = new HTTP\ResponseMock();
490 
491         $s->exec();
492 
493         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
494         $this->assertEquals('application/calendar+json', $s->httpResponse->getHeader('Content-Type'));
495 
496     }
497 
498     function testNegotiateDefault() {
499 
500         $cbackend = TestUtil::getBackend();
501         $pbackend = new DAVACL\PrincipalBackend\Mock();
502 
503         $props = array(
504             'uri'=>'UUID-123467',
505             'principaluri' => 'admin',
506             'id' => 1,
507         );
508         $tree = array(
509             new Calendar($cbackend,$props),
510             new DAVACL\PrincipalCollection($pbackend),
511         );
512 
513         $p = new ICSExportPlugin();
514 
515         $s = new DAV\Server($tree);
516         $s->sapi = new HTTP\SapiMock();
517         $s->addPlugin($p);
518         $s->addPlugin(new Plugin());
519 
520         $h = HTTP\Sapi::createFromServerArray([
521             'REQUEST_URI' => '/UUID-123467?export',
522             'REQUEST_METHOD' => 'GET',
523             'HTTP_ACCEPT' => 'text/plain',
524         ]);
525 
526         $s->httpRequest = $h;
527         $s->httpResponse = new HTTP\ResponseMock();
528 
529         $s->exec();
530 
531         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
532         $this->assertEquals('text/calendar', $s->httpResponse->getHeader('Content-Type'));
533 
534     }
535 
536     function testFilterComponentVEVENT() {
537 
538         $cbackend = TestUtil::getBackend();
539         $pbackend = new DAVACL\PrincipalBackend\Mock();
540 
541         $props = array(
542             'uri'=>'UUID-123467',
543             'principaluri' => 'admin',
544             'id' => 1,
545         );
546         // add a todo to the calendar (see /tests/Sabre/TestUtil)
547         $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO());
548 
549         $tree = array(
550             new Calendar($cbackend,$props),
551             new DAVACL\PrincipalCollection($pbackend),
552         );
553 
554         $p = new ICSExportPlugin();
555 
556         $s = new DAV\Server($tree);
557         $s->sapi = new HTTP\SapiMock();
558         $s->addPlugin($p);
559         $s->addPlugin(new Plugin());
560 
561         $h = HTTP\Sapi::createFromServerArray([
562             'REQUEST_URI' => '/UUID-123467?export&componentType=VEVENT',
563             'REQUEST_METHOD' => 'GET',
564         ]);
565 
566         $s->httpRequest = $h;
567         $s->httpResponse = new HTTP\ResponseMock();
568 
569         $s->exec();
570 
571         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
572         $obj = VObject\Reader::read($s->httpResponse->body);
573 
574         $this->assertEquals(1,count($obj->VTIMEZONE));
575         $this->assertEquals(1,count($obj->VEVENT));
576         $this->assertEquals(0,count($obj->VTODO));
577 
578     }
579 
580     function testFilterComponentVTODO() {
581 
582         $cbackend = TestUtil::getBackend();
583         $pbackend = new DAVACL\PrincipalBackend\Mock();
584 
585         $props = [
586             'uri'=>'UUID-123467',
587             'principaluri' => 'admin',
588             'id' => 1,
589         ];
590         // add a todo to the calendar (see /tests/Sabre/TestUtil)
591         $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO());
592 
593         $tree = [
594             new Calendar($cbackend,$props),
595             new DAVACL\PrincipalCollection($pbackend),
596         ];
597 
598         $p = new ICSExportPlugin();
599 
600         $s = new DAV\Server($tree);
601         $s->sapi = new HTTP\SapiMock();
602         $s->addPlugin($p);
603         $s->addPlugin(new Plugin());
604 
605         $h = HTTP\Sapi::createFromServerArray([
606             'REQUEST_URI' => '/UUID-123467?export&componentType=VTODO',
607             'REQUEST_METHOD' => 'GET',
608         ]);
609 
610         $s->httpRequest = $h;
611         $s->httpResponse = new HTTP\ResponseMock();
612 
613         $s->exec();
614 
615         $this->assertEquals(200, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
616         $obj = VObject\Reader::read($s->httpResponse->body);
617 
618         $this->assertEquals(0,count($obj->VTIMEZONE));
619         $this->assertEquals(0,count($obj->VEVENT));
620         $this->assertEquals(1,count($obj->VTODO));
621 
622     }
623 
624     function testFilterComponentBadComponent() {
625 
626         $cbackend = TestUtil::getBackend();
627         $pbackend = new DAVACL\PrincipalBackend\Mock();
628 
629         $props = [
630             'uri'=>'UUID-123467',
631             'principaluri' => 'admin',
632             'id' => 1,
633         ];
634         // add a todo to the calendar (see /tests/Sabre/TestUtil)
635         $cbackend->createCalendarObject(1, 'UUID-3456', TestUtil::getTestTODO());
636 
637         $tree = [
638             new Calendar($cbackend,$props),
639             new DAVACL\PrincipalCollection($pbackend),
640         ];
641 
642         $p = new ICSExportPlugin();
643 
644         $s = new DAV\Server($tree);
645         $s->sapi = new HTTP\SapiMock();
646         $s->addPlugin($p);
647         $s->addPlugin(new Plugin());
648 
649         $h = HTTP\Sapi::createFromServerArray([
650             'REQUEST_URI' => '/UUID-123467?export&componentType=VVOODOO',
651             'REQUEST_METHOD' => 'GET',
652         ]);
653 
654         $s->httpRequest = $h;
655         $s->httpResponse = new HTTP\ResponseMock();
656 
657         $s->exec();
658 
659         $this->assertEquals(400, $s->httpResponse->status,'Invalid status received. Response body: '. $s->httpResponse->body);
660 
661     }
662 }
663