1<?php
2
3namespace Sabre\CalDAV\Schedule;
4
5use
6    Sabre\DAV,
7    Sabre\DAVACL,
8    Sabre\HTTP,
9    Sabre\CalDAV,
10    Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp;
11
12class FreeBusyRequestTest extends \PHPUnit_Framework_TestCase {
13
14    protected $plugin;
15    protected $server;
16    protected $aclPlugin;
17    protected $request;
18    protected $authPlugin;
19    protected $caldavBackend;
20
21    function setUp() {
22
23        $calendars = [
24            [
25                'principaluri' => 'principals/user2',
26                'id'           => 1,
27                'uri'          => 'calendar1',
28                '{' . CalDAV\Plugin::NS_CALDAV . '}calendar-timezone' => "BEGIN:VCALENDAR\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nEND:VTIMEZONE\r\nEND:VCALENDAR",
29            ],
30            [
31                'principaluri' => 'principals/user2',
32                'id'           => 2,
33                'uri'          => 'calendar2',
34                '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new ScheduleCalendarTransp(ScheduleCalendarTransp::TRANSPARENT),
35            ],
36        ];
37        $calendarobjects = [
38            1 => [ '1.ics' => [
39                'uri' => '1.ics',
40                'calendardata' => 'BEGIN:VCALENDAR
41BEGIN:VEVENT
42DTSTART:20110101T130000
43DURATION:PT1H
44END:VEVENT
45END:VCALENDAR',
46                'calendarid' => 1,
47            ]],
48            2 => [ '2.ics' => [
49                'uri' => '2.ics',
50                'calendardata' => 'BEGIN:VCALENDAR
51BEGIN:VEVENT
52DTSTART:20110101T080000
53DURATION:PT1H
54END:VEVENT
55END:VCALENDAR',
56                'calendarid' => 2,
57            ]]
58
59        ];
60
61        $principalBackend = new DAVACL\PrincipalBackend\Mock();
62        $this->caldavBackend = new CalDAV\Backend\MockScheduling($calendars, $calendarobjects);
63
64        $tree = [
65            new DAVACL\PrincipalCollection($principalBackend),
66            new CalDAV\CalendarRoot($principalBackend, $this->caldavBackend),
67        ];
68
69        $this->request = HTTP\Sapi::createFromServerArray([
70            'CONTENT_TYPE' => 'text/calendar',
71        ]);
72        $this->response = new HTTP\ResponseMock();
73
74        $this->server = new DAV\Server($tree);
75        $this->server->httpRequest = $this->request;
76        $this->server->httpResponse = $this->response;
77
78        $this->aclPlugin = new DAVACL\Plugin();
79        $this->server->addPlugin($this->aclPlugin);
80
81        $authBackend = new DAV\Auth\Backend\Mock();
82        $authBackend->setPrincipal('principals/user1');
83        $this->authPlugin = new DAV\Auth\Plugin($authBackend,'SabreDAV');
84        // Forcing authentication to work.
85        $this->authPlugin->beforeMethod($this->request, $this->response);
86        $this->server->addPlugin($this->authPlugin);
87
88        // CalDAV plugin
89        $this->plugin = new CalDAV\Plugin();
90        $this->server->addPlugin($this->plugin);
91
92        // Scheduling plugin
93        $this->plugin = new Plugin();
94        $this->server->addPlugin($this->plugin);
95
96    }
97
98    function testWrongContentType() {
99
100        $this->server->httpRequest = new HTTP\Request(
101            'POST',
102            '/calendars/user1/outbox',
103            ['Content-Type' => 'text/plain']
104        );
105
106        $this->assertNull(
107            $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse)
108        );
109
110    }
111
112    function testNotFound() {
113
114        $this->server->httpRequest = new HTTP\Request(
115            'POST',
116            '/calendars/user1/blabla',
117            ['Content-Type' => 'text/calendar']
118        );
119
120        $this->assertNull(
121            $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse)
122        );
123
124    }
125
126    function testNotOutbox() {
127
128        $this->server->httpRequest = new HTTP\Request(
129            'POST',
130            '/calendars/user1/inbox',
131            ['Content-Type' => 'text/calendar']
132        );
133
134        $this->assertNull(
135            $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse)
136        );
137
138    }
139
140    /**
141     * @expectedException Sabre\DAV\Exception\BadRequest
142     */
143    function testNoItipMethod() {
144
145        $this->server->httpRequest = new HTTP\Request(
146            'POST',
147            '/calendars/user1/outbox',
148            ['Content-Type' => 'text/calendar']
149        );
150
151        $body = <<<ICS
152BEGIN:VCALENDAR
153BEGIN:VFREEBUSY
154END:VFREEBUSY
155END:VCALENDAR
156ICS;
157
158        $this->server->httpRequest->setBody($body);
159        $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse);
160
161    }
162
163    /**
164     * @expectedException \Sabre\DAV\Exception\NotImplemented
165     */
166    function testNoVFreeBusy() {
167
168        $this->server->httpRequest = new HTTP\Request(
169            'POST',
170            '/calendars/user1/outbox',
171            ['Content-Type' => 'text/calendar']
172        );
173
174        $body = <<<ICS
175BEGIN:VCALENDAR
176METHOD:REQUEST
177BEGIN:VEVENT
178END:VEVENT
179END:VCALENDAR
180ICS;
181
182        $this->server->httpRequest->setBody($body);
183        $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse);
184
185    }
186
187    /**
188     * @expectedException Sabre\DAV\Exception\Forbidden
189     */
190    function testIncorrectOrganizer() {
191
192        $this->server->httpRequest = new HTTP\Request(
193            'POST',
194            '/calendars/user1/outbox',
195            ['Content-Type' => 'text/calendar']
196        );
197
198
199        $body = <<<ICS
200BEGIN:VCALENDAR
201METHOD:REQUEST
202BEGIN:VFREEBUSY
203ORGANIZER:mailto:john@wayne.org
204END:VFREEBUSY
205END:VCALENDAR
206ICS;
207
208        $this->server->httpRequest->setBody($body);
209        $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse);
210
211    }
212
213    /**
214     * @expectedException Sabre\DAV\Exception\BadRequest
215     */
216    function testNoAttendees() {
217
218        $this->server->httpRequest = new HTTP\Request(
219            'POST',
220            '/calendars/user1/outbox',
221            ['Content-Type' => 'text/calendar']
222        );
223
224        $body = <<<ICS
225BEGIN:VCALENDAR
226METHOD:REQUEST
227BEGIN:VFREEBUSY
228ORGANIZER:mailto:user1.sabredav@sabredav.org
229END:VFREEBUSY
230END:VCALENDAR
231ICS;
232
233        $this->server->httpRequest->setBody($body);
234        $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse);
235
236    }
237
238    /**
239     * @expectedException Sabre\DAV\Exception\BadRequest
240     */
241    function testNoDTStart() {
242
243        $this->server->httpRequest = new HTTP\Request(
244            'POST',
245            '/calendars/user1/outbox',
246            ['Content-Type' => 'text/calendar']
247        );
248
249        $body = <<<ICS
250BEGIN:VCALENDAR
251METHOD:REQUEST
252BEGIN:VFREEBUSY
253ORGANIZER:mailto:user1.sabredav@sabredav.org
254ATTENDEE:mailto:user2.sabredav@sabredav.org
255END:VFREEBUSY
256END:VCALENDAR
257ICS;
258
259        $this->server->httpRequest->setBody($body);
260        $this->plugin->httpPost($this->server->httpRequest, $this->server->httpResponse);
261
262    }
263
264    function testSucceed() {
265
266        $this->server->httpRequest = new HTTP\Request(
267            'POST',
268            '/calendars/user1/outbox',
269            ['Content-Type' => 'text/calendar']
270        );
271
272        $body = <<<ICS
273BEGIN:VCALENDAR
274METHOD:REQUEST
275BEGIN:VFREEBUSY
276ORGANIZER:mailto:user1.sabredav@sabredav.org
277ATTENDEE:mailto:user2.sabredav@sabredav.org
278ATTENDEE:mailto:user3.sabredav@sabredav.org
279DTSTART:20110101T080000Z
280DTEND:20110101T180000Z
281END:VFREEBUSY
282END:VCALENDAR
283ICS;
284
285        $this->server->httpRequest->setBody($body);
286
287        // Lazily making the current principal an admin.
288        $this->aclPlugin->adminPrincipals[] = 'principals/user1';
289
290        $this->assertFalse(
291            $this->plugin->httpPost($this->server->httpRequest, $this->response)
292        );
293
294        $this->assertEquals(200, $this->response->status);
295        $this->assertEquals(array(
296            'Content-Type' => ['application/xml'],
297        ), $this->response->getHeaders());
298
299        $strings = array(
300            '<d:href>mailto:user2.sabredav@sabredav.org</d:href>',
301            '<d:href>mailto:user3.sabredav@sabredav.org</d:href>',
302            '<cal:request-status>2.0;Success</cal:request-status>',
303            '<cal:request-status>3.7;Could not find principal</cal:request-status>',
304            'FREEBUSY;FBTYPE=BUSY:20110101T120000Z/20110101T130000Z',
305        );
306
307        foreach($strings as $string) {
308            $this->assertTrue(
309                strpos($this->response->body, $string)!==false,
310                'The response body did not contain: ' . $string .'Full response: ' . $this->response->body
311            );
312        }
313
314        $this->assertTrue(
315            strpos($this->response->body, 'FREEBUSY;FBTYPE=BUSY:20110101T080000Z/20110101T090000Z')==false,
316            'The response body did contain free busy info from a transparent calendar.'
317        );
318
319    }
320
321    /**
322     * Testing if the freebusy request still works, even if there are no
323     * calendars in the target users' account.
324     */
325    function testSucceedNoCalendars() {
326
327        // Deleting calendars
328        $this->caldavBackend->deleteCalendar(1);
329        $this->caldavBackend->deleteCalendar(2);
330
331        $this->server->httpRequest = new HTTP\Request(
332            'POST',
333            '/calendars/user1/outbox',
334            ['Content-Type' => 'text/calendar']
335        );
336
337        $body = <<<ICS
338BEGIN:VCALENDAR
339METHOD:REQUEST
340BEGIN:VFREEBUSY
341ORGANIZER:mailto:user1.sabredav@sabredav.org
342ATTENDEE:mailto:user2.sabredav@sabredav.org
343DTSTART:20110101T080000Z
344DTEND:20110101T180000Z
345END:VFREEBUSY
346END:VCALENDAR
347ICS;
348
349        $this->server->httpRequest->setBody($body);
350
351        // Lazily making the current principal an admin.
352        $this->aclPlugin->adminPrincipals[] = 'principals/user1';
353
354        $this->assertFalse(
355            $this->plugin->httpPost($this->server->httpRequest, $this->response)
356        );
357
358        $this->assertEquals(200, $this->response->status);
359        $this->assertEquals(array(
360            'Content-Type' => ['application/xml'],
361        ), $this->response->getHeaders());
362
363        $strings = array(
364            '<d:href>mailto:user2.sabredav@sabredav.org</d:href>',
365            '<cal:request-status>2.0;Success</cal:request-status>',
366        );
367
368        foreach($strings as $string) {
369            $this->assertTrue(
370                strpos($this->response->body, $string)!==false,
371                'The response body did not contain: ' . $string .'Full response: ' . $this->response->body
372            );
373        }
374
375    }
376
377    /*
378    function testNoPrivilege() {
379
380        $this->markTestIncomplete('Currently there\'s no "no privilege" situation');
381
382        $this->server->httpRequest = HTTP\Sapi::createFromServerArray(array(
383            'CONTENT_TYPE' => 'text/calendar',
384            'REQUEST_METHOD' => 'POST',
385            'REQUEST_URI' => '/calendars/user1/outbox',
386        ));
387
388        $body = <<<ICS
389BEGIN:VCALENDAR
390METHOD:REQUEST
391BEGIN:VFREEBUSY
392ORGANIZER:mailto:user1.sabredav@sabredav.org
393ATTENDEE:mailto:user2.sabredav@sabredav.org
394DTSTART:20110101T080000Z
395DTEND:20110101T180000Z
396END:VFREEBUSY
397END:VCALENDAR
398ICS;
399
400        $this->server->httpRequest->setBody($body);
401
402        $this->assertFalse(
403            $this->plugin->httpPost($this->server->httpRequest, $this->response)
404        );
405
406        $this->assertEquals(200, $this->response->status);
407        $this->assertEquals([
408            'Content-Type' => 'application/xml',
409        ], $this->response->getHeaders());
410
411        $strings = [
412            '<d:href>mailto:user2.sabredav@sabredav.org</d:href>',
413            '<cal:request-status>3.7;No calendar-home-set property found</cal:request-status>',
414        ];
415
416        foreach($strings as $string) {
417            $this->assertTrue(
418                strpos($this->response->body, $string)!==false,
419                'The response body did not contain: ' . $string .'Full response: ' . $this->response->body
420            );
421        }
422
423
424    }*/
425
426}
427