PageRenderTime 64ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/dav/SabreDAV/tests/Sabre/CalDAV/PluginTest.php

https://github.com/chiefdome/friendica-addons
PHP | 1084 lines | 806 code | 230 blank | 48 comment | 12 complexity | 3fd79b17e2d037f6e779cce7e01b4d3e MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0, GPL-2.0
  1. <?php
  2. require_once 'Sabre/HTTP/ResponseMock.php';
  3. require_once 'Sabre/DAV/Auth/MockBackend.php';
  4. require_once 'Sabre/CalDAV/TestUtil.php';
  5. require_once 'Sabre/DAVACL/MockPrincipalBackend.php';
  6. class Sabre_CalDAV_PluginTest extends PHPUnit_Framework_TestCase {
  7. /**
  8. * @var Sabre_DAV_Server
  9. */
  10. protected $server;
  11. /**
  12. * @var Sabre_CalDAV_Plugin
  13. */
  14. protected $plugin;
  15. protected $response;
  16. /**
  17. * @var Sabre_CalDAV_Backend_PDO
  18. */
  19. protected $caldavBackend;
  20. function setup() {
  21. $this->caldavBackend = new Sabre_CalDAV_Backend_Mock(array(
  22. array(
  23. 'id' => 1,
  24. 'uri' => 'UUID-123467',
  25. 'principaluri' => 'principals/user1',
  26. '{DAV:}displayname' => 'user1 calendar',
  27. '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description',
  28. '{http://apple.com/ns/ical/}calendar-order' => '1',
  29. '{http://apple.com/ns/ical/}calendar-color' => '#FF0000',
  30. '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet(array('VEVENT','VTODO')),
  31. ),
  32. array(
  33. 'id' => 2,
  34. 'uri' => 'UUID-123468',
  35. 'principaluri' => 'principals/user1',
  36. '{DAV:}displayname' => 'user1 calendar2',
  37. '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description',
  38. '{http://apple.com/ns/ical/}calendar-order' => '1',
  39. '{http://apple.com/ns/ical/}calendar-color' => '#FF0000',
  40. '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet(array('VEVENT','VTODO')),
  41. )
  42. ), array(
  43. 1 => array(
  44. 'UUID-2345' => array(
  45. 'calendardata' => Sabre_CalDAV_TestUtil::getTestCalendarData(),
  46. )
  47. )
  48. ));
  49. $principalBackend = new Sabre_DAVACL_MockPrincipalBackend();
  50. $principalBackend->setGroupMemberSet('principals/admin/calendar-proxy-read',array('principals/user1'));
  51. $principalBackend->setGroupMemberSet('principals/admin/calendar-proxy-write',array('principals/user1'));
  52. $principalBackend->addPrincipal(array(
  53. 'uri' => 'principals/admin/calendar-proxy-read',
  54. ));
  55. $principalBackend->addPrincipal(array(
  56. 'uri' => 'principals/admin/calendar-proxy-write',
  57. ));
  58. $calendars = new Sabre_CalDAV_CalendarRootNode($principalBackend,$this->caldavBackend);
  59. $principals = new Sabre_CalDAV_Principal_Collection($principalBackend);
  60. $root = new Sabre_DAV_SimpleCollection('root');
  61. $root->addChild($calendars);
  62. $root->addChild($principals);
  63. $objectTree = new Sabre_DAV_ObjectTree($root);
  64. $this->server = new Sabre_DAV_Server($objectTree);
  65. $this->server->debugExceptions = true;
  66. $this->server->setBaseUri('/');
  67. $this->plugin = new Sabre_CalDAV_Plugin();
  68. $this->server->addPlugin($this->plugin);
  69. $this->response = new Sabre_HTTP_ResponseMock();
  70. $this->server->httpResponse = $this->response;
  71. }
  72. function testSimple() {
  73. $this->assertEquals(array('MKCALENDAR'), $this->plugin->getHTTPMethods('calendars/user1/randomnewcalendar'));
  74. $this->assertEquals(array('calendar-access','calendar-proxy'), $this->plugin->getFeatures());
  75. $this->assertArrayHasKey('urn:ietf:params:xml:ns:caldav', $this->server->xmlNamespaces);
  76. }
  77. function testUnknownMethodPassThrough() {
  78. $request = new Sabre_HTTP_Request(array(
  79. 'REQUEST_METHOD' => 'MKBREAKFAST',
  80. 'REQUEST_URI' => '/',
  81. ));
  82. $this->server->httpRequest = $request;
  83. $this->server->exec();
  84. $this->assertEquals('HTTP/1.1 501 Not Implemented', $this->response->status,'Incorrect status returned. Full response body:' . $this->response->body);
  85. }
  86. function testReportPassThrough() {
  87. $request = new Sabre_HTTP_Request(array(
  88. 'REQUEST_METHOD' => 'REPORT',
  89. 'HTTP_CONTENT_TYPE' => 'application/xml',
  90. 'REQUEST_URI' => '/',
  91. ));
  92. $request->setBody('<?xml version="1.0"?><s:somereport xmlns:s="http://www.rooftopsolutions.nl/NS/example" />');
  93. $this->server->httpRequest = $request;
  94. $this->server->exec();
  95. $this->assertEquals('HTTP/1.1 501 Not Implemented', $this->response->status);
  96. }
  97. function testMkCalendarBadLocation() {
  98. $request = new Sabre_HTTP_Request(array(
  99. 'REQUEST_METHOD' => 'MKCALENDAR',
  100. 'REQUEST_URI' => '/blabla',
  101. ));
  102. $body = '<?xml version="1.0" encoding="utf-8" ?>
  103. <C:mkcalendar xmlns:D="DAV:"
  104. xmlns:C="urn:ietf:params:xml:ns:caldav">
  105. <D:set>
  106. <D:prop>
  107. <D:displayname>Lisa\'s Events</D:displayname>
  108. <C:calendar-description xml:lang="en"
  109. >Calendar restricted to events.</C:calendar-description>
  110. <C:supported-calendar-component-set>
  111. <C:comp name="VEVENT"/>
  112. </C:supported-calendar-component-set>
  113. <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
  114. PRODID:-//Example Corp.//CalDAV Client//EN
  115. VERSION:2.0
  116. BEGIN:VTIMEZONE
  117. TZID:US-Eastern
  118. LAST-MODIFIED:19870101T000000Z
  119. BEGIN:STANDARD
  120. DTSTART:19671029T020000
  121. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  122. TZOFFSETFROM:-0400
  123. TZOFFSETTO:-0500
  124. TZNAME:Eastern Standard Time (US & Canada)
  125. END:STANDARD
  126. BEGIN:DAYLIGHT
  127. DTSTART:19870405T020000
  128. RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
  129. TZOFFSETFROM:-0500
  130. TZOFFSETTO:-0400
  131. TZNAME:Eastern Daylight Time (US & Canada)
  132. END:DAYLIGHT
  133. END:VTIMEZONE
  134. END:VCALENDAR
  135. ]]></C:calendar-timezone>
  136. </D:prop>
  137. </D:set>
  138. </C:mkcalendar>';
  139. $request->setBody($body);
  140. $this->server->httpRequest = $request;
  141. $this->server->exec();
  142. $this->assertEquals('HTTP/1.1 403 Forbidden', $this->response->status);
  143. }
  144. function testMkCalendarNoParentNode() {
  145. $request = new Sabre_HTTP_Request(array(
  146. 'REQUEST_METHOD' => 'MKCALENDAR',
  147. 'REQUEST_URI' => '/doesntexist/calendar',
  148. ));
  149. $body = '<?xml version="1.0" encoding="utf-8" ?>
  150. <C:mkcalendar xmlns:D="DAV:"
  151. xmlns:C="urn:ietf:params:xml:ns:caldav">
  152. <D:set>
  153. <D:prop>
  154. <D:displayname>Lisa\'s Events</D:displayname>
  155. <C:calendar-description xml:lang="en"
  156. >Calendar restricted to events.</C:calendar-description>
  157. <C:supported-calendar-component-set>
  158. <C:comp name="VEVENT"/>
  159. </C:supported-calendar-component-set>
  160. <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
  161. PRODID:-//Example Corp.//CalDAV Client//EN
  162. VERSION:2.0
  163. BEGIN:VTIMEZONE
  164. TZID:US-Eastern
  165. LAST-MODIFIED:19870101T000000Z
  166. BEGIN:STANDARD
  167. DTSTART:19671029T020000
  168. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  169. TZOFFSETFROM:-0400
  170. TZOFFSETTO:-0500
  171. TZNAME:Eastern Standard Time (US & Canada)
  172. END:STANDARD
  173. BEGIN:DAYLIGHT
  174. DTSTART:19870405T020000
  175. RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
  176. TZOFFSETFROM:-0500
  177. TZOFFSETTO:-0400
  178. TZNAME:Eastern Daylight Time (US & Canada)
  179. END:DAYLIGHT
  180. END:VTIMEZONE
  181. END:VCALENDAR
  182. ]]></C:calendar-timezone>
  183. </D:prop>
  184. </D:set>
  185. </C:mkcalendar>';
  186. $request->setBody($body);
  187. $this->server->httpRequest = $request;
  188. $this->server->exec();
  189. $this->assertEquals('HTTP/1.1 409 Conflict', $this->response->status);
  190. }
  191. function testMkCalendarExistingCalendar() {
  192. $request = new Sabre_HTTP_Request(array(
  193. 'REQUEST_METHOD' => 'MKCALENDAR',
  194. 'REQUEST_URI' => '/calendars/user1/UUID-123467',
  195. ));
  196. $body = '<?xml version="1.0" encoding="utf-8" ?>
  197. <C:mkcalendar xmlns:D="DAV:"
  198. xmlns:C="urn:ietf:params:xml:ns:caldav">
  199. <D:set>
  200. <D:prop>
  201. <D:displayname>Lisa\'s Events</D:displayname>
  202. <C:calendar-description xml:lang="en"
  203. >Calendar restricted to events.</C:calendar-description>
  204. <C:supported-calendar-component-set>
  205. <C:comp name="VEVENT"/>
  206. </C:supported-calendar-component-set>
  207. <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
  208. PRODID:-//Example Corp.//CalDAV Client//EN
  209. VERSION:2.0
  210. BEGIN:VTIMEZONE
  211. TZID:US-Eastern
  212. LAST-MODIFIED:19870101T000000Z
  213. BEGIN:STANDARD
  214. DTSTART:19671029T020000
  215. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  216. TZOFFSETFROM:-0400
  217. TZOFFSETTO:-0500
  218. TZNAME:Eastern Standard Time (US & Canada)
  219. END:STANDARD
  220. BEGIN:DAYLIGHT
  221. DTSTART:19870405T020000
  222. RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
  223. TZOFFSETFROM:-0500
  224. TZOFFSETTO:-0400
  225. TZNAME:Eastern Daylight Time (US & Canada)
  226. END:DAYLIGHT
  227. END:VTIMEZONE
  228. END:VCALENDAR
  229. ]]></C:calendar-timezone>
  230. </D:prop>
  231. </D:set>
  232. </C:mkcalendar>';
  233. $request->setBody($body);
  234. $this->server->httpRequest = $request;
  235. $this->server->exec();
  236. $this->assertEquals('HTTP/1.1 405 Method Not Allowed', $this->response->status);
  237. }
  238. function testMkCalendarSucceed() {
  239. $request = new Sabre_HTTP_Request(array(
  240. 'REQUEST_METHOD' => 'MKCALENDAR',
  241. 'REQUEST_URI' => '/calendars/user1/NEWCALENDAR',
  242. ));
  243. $timezone = 'BEGIN:VCALENDAR
  244. PRODID:-//Example Corp.//CalDAV Client//EN
  245. VERSION:2.0
  246. BEGIN:VTIMEZONE
  247. TZID:US-Eastern
  248. LAST-MODIFIED:19870101T000000Z
  249. BEGIN:STANDARD
  250. DTSTART:19671029T020000
  251. RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  252. TZOFFSETFROM:-0400
  253. TZOFFSETTO:-0500
  254. TZNAME:Eastern Standard Time (US & Canada)
  255. END:STANDARD
  256. BEGIN:DAYLIGHT
  257. DTSTART:19870405T020000
  258. RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
  259. TZOFFSETFROM:-0500
  260. TZOFFSETTO:-0400
  261. TZNAME:Eastern Daylight Time (US & Canada)
  262. END:DAYLIGHT
  263. END:VTIMEZONE
  264. END:VCALENDAR';
  265. $body = '<?xml version="1.0" encoding="utf-8" ?>
  266. <C:mkcalendar xmlns:D="DAV:"
  267. xmlns:C="urn:ietf:params:xml:ns:caldav">
  268. <D:set>
  269. <D:prop>
  270. <D:displayname>Lisa\'s Events</D:displayname>
  271. <C:calendar-description xml:lang="en"
  272. >Calendar restricted to events.</C:calendar-description>
  273. <C:supported-calendar-component-set>
  274. <C:comp name="VEVENT"/>
  275. </C:supported-calendar-component-set>
  276. <C:calendar-timezone><![CDATA[' . $timezone . ']]></C:calendar-timezone>
  277. </D:prop>
  278. </D:set>
  279. </C:mkcalendar>';
  280. $request->setBody($body);
  281. $this->server->httpRequest = $request;
  282. $this->server->exec();
  283. $this->assertEquals('HTTP/1.1 201 Created', $this->response->status,'Invalid response code received. Full response body: ' .$this->response->body);
  284. $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
  285. $this->assertEquals(3, count($calendars));
  286. $newCalendar = null;
  287. foreach($calendars as $calendar) {
  288. if ($calendar['uri'] === 'NEWCALENDAR') {
  289. $newCalendar = $calendar;
  290. break;
  291. }
  292. }
  293. $this->assertInternalType('array',$newCalendar);
  294. $keys = array(
  295. 'uri' => 'NEWCALENDAR',
  296. 'id' => null,
  297. '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar restricted to events.',
  298. '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => $timezone,
  299. '{DAV:}displayname' => 'Lisa\'s Events',
  300. '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => null,
  301. );
  302. foreach($keys as $key=>$value) {
  303. $this->assertArrayHasKey($key, $newCalendar);
  304. if (is_null($value)) continue;
  305. $this->assertEquals($value, $newCalendar[$key]);
  306. }
  307. $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
  308. $this->assertTrue($newCalendar[$sccs] instanceof Sabre_CalDAV_Property_SupportedCalendarComponentSet);
  309. $this->assertEquals(array('VEVENT'),$newCalendar[$sccs]->getValue());
  310. }
  311. function testMkCalendarEmptyBodySucceed() {
  312. $request = new Sabre_HTTP_Request(array(
  313. 'REQUEST_METHOD' => 'MKCALENDAR',
  314. 'REQUEST_URI' => '/calendars/user1/NEWCALENDAR',
  315. ));
  316. $request->setBody('');
  317. $this->server->httpRequest = $request;
  318. $this->server->exec();
  319. $this->assertEquals('HTTP/1.1 201 Created', $this->response->status,'Invalid response code received. Full response body: ' .$this->response->body);
  320. $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
  321. $this->assertEquals(3, count($calendars));
  322. $newCalendar = null;
  323. foreach($calendars as $calendar) {
  324. if ($calendar['uri'] === 'NEWCALENDAR') {
  325. $newCalendar = $calendar;
  326. break;
  327. }
  328. }
  329. $this->assertInternalType('array',$newCalendar);
  330. $keys = array(
  331. 'uri' => 'NEWCALENDAR',
  332. 'id' => null,
  333. '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => null,
  334. );
  335. foreach($keys as $key=>$value) {
  336. $this->assertArrayHasKey($key, $newCalendar);
  337. if (is_null($value)) continue;
  338. $this->assertEquals($value, $newCalendar[$key]);
  339. }
  340. $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
  341. $this->assertTrue($newCalendar[$sccs] instanceof Sabre_CalDAV_Property_SupportedCalendarComponentSet);
  342. $this->assertEquals(array('VEVENT','VTODO'),$newCalendar[$sccs]->getValue());
  343. }
  344. function testPrincipalProperties() {
  345. $httpRequest = new Sabre_HTTP_Request(array(
  346. 'HTTP_HOST' => 'sabredav.org',
  347. ));
  348. $this->server->httpRequest = $httpRequest;
  349. $props = $this->server->getPropertiesForPath('/principals/user1',array(
  350. '{urn:ietf:params:xml:ns:caldav}calendar-home-set',
  351. '{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL',
  352. '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set',
  353. '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}calendar-proxy-read-for',
  354. '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}calendar-proxy-write-for',
  355. '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}notification-URL',
  356. ));
  357. $this->assertArrayHasKey(0,$props);
  358. $this->assertArrayHasKey(200,$props[0]);
  359. $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}calendar-home-set',$props[0][200]);
  360. $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}calendar-home-set'];
  361. $this->assertTrue($prop instanceof Sabre_DAV_Property_Href);
  362. $this->assertEquals('calendars/user1/',$prop->getHref());
  363. $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL',$props[0][200]);
  364. $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL'];
  365. $this->assertTrue($prop instanceof Sabre_DAV_Property_Href);
  366. $this->assertEquals('calendars/user1/outbox',$prop->getHref());
  367. $this->assertArrayHasKey('{'.Sabre_CalDAV_Plugin::NS_CALENDARSERVER .'}notification-URL',$props[0][200]);
  368. $prop = $props[0][200]['{'.Sabre_CalDAV_Plugin::NS_CALENDARSERVER .'}notification-URL'];
  369. $this->assertTrue($prop instanceof Sabre_DAV_Property_Href);
  370. $this->assertEquals('calendars/user1/notifications/',$prop->getHref());
  371. $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}calendar-user-address-set',$props[0][200]);
  372. $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'];
  373. $this->assertTrue($prop instanceof Sabre_DAV_Property_HrefList);
  374. $this->assertEquals(array('mailto:user1.sabredav@sabredav.org','/principals/user1'),$prop->getHrefs());
  375. $this->assertArrayHasKey('{http://calendarserver.org/ns/}calendar-proxy-read-for', $props[0][200]);
  376. $prop = $props[0][200]['{http://calendarserver.org/ns/}calendar-proxy-read-for'];
  377. $this->assertInstanceOf('Sabre_DAV_Property_HrefList', $prop);
  378. $this->assertEquals(array('principals/admin'), $prop->getHrefs());
  379. $this->assertArrayHasKey('{http://calendarserver.org/ns/}calendar-proxy-write-for', $props[0][200]);
  380. $prop = $props[0][200]['{http://calendarserver.org/ns/}calendar-proxy-write-for'];
  381. $this->assertInstanceOf('Sabre_DAV_Property_HrefList', $prop);
  382. $this->assertEquals(array('principals/admin'), $prop->getHrefs());
  383. }
  384. function testSupportedReportSetPropertyNonCalendar() {
  385. $props = $this->server->getPropertiesForPath('/calendars/user1',array(
  386. '{DAV:}supported-report-set',
  387. ));
  388. $this->assertArrayHasKey(0,$props);
  389. $this->assertArrayHasKey(200,$props[0]);
  390. $this->assertArrayHasKey('{DAV:}supported-report-set',$props[0][200]);
  391. $prop = $props[0][200]['{DAV:}supported-report-set'];
  392. $this->assertTrue($prop instanceof Sabre_DAV_Property_SupportedReportSet);
  393. $value = array(
  394. );
  395. $this->assertEquals($value,$prop->getValue());
  396. }
  397. /**
  398. * @depends testSupportedReportSetPropertyNonCalendar
  399. */
  400. function testSupportedReportSetProperty() {
  401. $props = $this->server->getPropertiesForPath('/calendars/user1/UUID-123467',array(
  402. '{DAV:}supported-report-set',
  403. ));
  404. $this->assertArrayHasKey(0,$props);
  405. $this->assertArrayHasKey(200,$props[0]);
  406. $this->assertArrayHasKey('{DAV:}supported-report-set',$props[0][200]);
  407. $prop = $props[0][200]['{DAV:}supported-report-set'];
  408. $this->assertTrue($prop instanceof Sabre_DAV_Property_SupportedReportSet);
  409. $value = array(
  410. '{urn:ietf:params:xml:ns:caldav}calendar-multiget',
  411. '{urn:ietf:params:xml:ns:caldav}calendar-query',
  412. '{urn:ietf:params:xml:ns:caldav}free-busy-query',
  413. );
  414. $this->assertEquals($value,$prop->getValue());
  415. }
  416. /**
  417. * @depends testSupportedReportSetProperty
  418. */
  419. function testCalendarMultiGetReport() {
  420. $body =
  421. '<?xml version="1.0"?>' .
  422. '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  423. '<d:prop>' .
  424. ' <c:calendar-data />' .
  425. ' <d:getetag />' .
  426. '</d:prop>' .
  427. '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
  428. '</c:calendar-multiget>';
  429. $request = new Sabre_HTTP_Request(array(
  430. 'REQUEST_METHOD' => 'REPORT',
  431. 'REQUEST_URI' => '/calendars/user1',
  432. 'HTTP_DEPTH' => '1',
  433. ));
  434. $request->setBody($body);
  435. $this->server->httpRequest = $request;
  436. $this->server->exec();
  437. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
  438. $xml = simplexml_load_string($this->response->body);
  439. $xml->registerXPathNamespace('d','DAV:');
  440. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  441. $check = array(
  442. '/d:multistatus',
  443. '/d:multistatus/d:response',
  444. '/d:multistatus/d:response/d:href',
  445. '/d:multistatus/d:response/d:propstat',
  446. '/d:multistatus/d:response/d:propstat/d:prop',
  447. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  448. '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
  449. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  450. );
  451. foreach($check as $v1=>$v2) {
  452. $xpath = is_int($v1)?$v2:$v1;
  453. $result = $xml->xpath($xpath);
  454. $this->assertEquals(1,count($result));
  455. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  456. }
  457. // The response object should have a reference to the Asia/Seoul
  458. // timezone.
  459. $this->assertTrue(strpos($this->response->body,'Asia/Seoul')!==false);
  460. }
  461. /**
  462. * @depends testCalendarMultiGetReport
  463. */
  464. function testCalendarMultiGetReportExpand() {
  465. $body =
  466. '<?xml version="1.0"?>' .
  467. '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  468. '<d:prop>' .
  469. ' <c:calendar-data>' .
  470. ' <c:expand start="20110101T000000Z" end="20111231T235959Z" />' .
  471. ' </c:calendar-data>' .
  472. ' <d:getetag />' .
  473. '</d:prop>' .
  474. '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
  475. '</c:calendar-multiget>';
  476. $request = new Sabre_HTTP_Request(array(
  477. 'REQUEST_METHOD' => 'REPORT',
  478. 'REQUEST_URI' => '/calendars/user1',
  479. 'HTTP_DEPTH' => '1',
  480. ));
  481. $request->setBody($body);
  482. $this->server->httpRequest = $request;
  483. $this->server->exec();
  484. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
  485. $xml = simplexml_load_string($this->response->body);
  486. $xml->registerXPathNamespace('d','DAV:');
  487. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  488. $check = array(
  489. '/d:multistatus',
  490. '/d:multistatus/d:response',
  491. '/d:multistatus/d:response/d:href',
  492. '/d:multistatus/d:response/d:propstat',
  493. '/d:multistatus/d:response/d:propstat/d:prop',
  494. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  495. '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
  496. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  497. );
  498. foreach($check as $v1=>$v2) {
  499. $xpath = is_int($v1)?$v2:$v1;
  500. $result = $xml->xpath($xpath);
  501. $this->assertEquals(1,count($result));
  502. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  503. }
  504. // The response object should no longer hold references to timezones.
  505. $this->assertTrue(strpos($this->response->body,'Asia/Seoul')===false);
  506. }
  507. /**
  508. * @depends testSupportedReportSetProperty
  509. * @depends testCalendarMultiGetReport
  510. */
  511. function testCalendarQueryReport() {
  512. $body =
  513. '<?xml version="1.0"?>' .
  514. '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  515. '<d:prop>' .
  516. ' <c:calendar-data>' .
  517. ' <c:expand start="20000101T000000Z" end="20101231T235959Z" />' .
  518. ' </c:calendar-data>' .
  519. ' <d:getetag />' .
  520. '</d:prop>' .
  521. '<c:filter>' .
  522. ' <c:comp-filter name="VCALENDAR">' .
  523. ' <c:comp-filter name="VEVENT" />' .
  524. ' </c:comp-filter>' .
  525. '</c:filter>' .
  526. '</c:calendar-query>';
  527. $request = new Sabre_HTTP_Request(array(
  528. 'REQUEST_METHOD' => 'REPORT',
  529. 'REQUEST_URI' => '/calendars/user1/UUID-123467',
  530. 'HTTP_DEPTH' => '1',
  531. ));
  532. $request->setBody($body);
  533. $this->server->httpRequest = $request;
  534. $this->server->exec();
  535. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
  536. $xml = simplexml_load_string($this->response->body);
  537. $xml->registerXPathNamespace('d','DAV:');
  538. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  539. $check = array(
  540. '/d:multistatus',
  541. '/d:multistatus/d:response',
  542. '/d:multistatus/d:response/d:href',
  543. '/d:multistatus/d:response/d:propstat',
  544. '/d:multistatus/d:response/d:propstat/d:prop',
  545. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  546. '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
  547. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  548. );
  549. foreach($check as $v1=>$v2) {
  550. $xpath = is_int($v1)?$v2:$v1;
  551. $result = $xml->xpath($xpath);
  552. $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
  553. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  554. }
  555. }
  556. /**
  557. * @depends testCalendarQueryReport
  558. */
  559. function testCalendarQueryReportNoCalData() {
  560. $body =
  561. '<?xml version="1.0"?>' .
  562. '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  563. '<d:prop>' .
  564. ' <d:getetag />' .
  565. '</d:prop>' .
  566. '<c:filter>' .
  567. ' <c:comp-filter name="VCALENDAR">' .
  568. ' <c:comp-filter name="VEVENT" />' .
  569. ' </c:comp-filter>' .
  570. '</c:filter>' .
  571. '</c:calendar-query>';
  572. $request = new Sabre_HTTP_Request(array(
  573. 'REQUEST_METHOD' => 'REPORT',
  574. 'REQUEST_URI' => '/calendars/user1//UUID-123467',
  575. 'HTTP_DEPTH' => '1',
  576. ));
  577. $request->setBody($body);
  578. $this->server->httpRequest = $request;
  579. $this->server->exec();
  580. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
  581. $xml = simplexml_load_string($this->response->body);
  582. $xml->registerXPathNamespace('d','DAV:');
  583. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  584. $check = array(
  585. '/d:multistatus',
  586. '/d:multistatus/d:response',
  587. '/d:multistatus/d:response/d:href',
  588. '/d:multistatus/d:response/d:propstat',
  589. '/d:multistatus/d:response/d:propstat/d:prop',
  590. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  591. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  592. );
  593. foreach($check as $v1=>$v2) {
  594. $xpath = is_int($v1)?$v2:$v1;
  595. $result = $xml->xpath($xpath);
  596. $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
  597. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  598. }
  599. }
  600. /**
  601. * @depends testCalendarQueryReport
  602. */
  603. function testCalendarQueryReportNoFilters() {
  604. $body =
  605. '<?xml version="1.0"?>' .
  606. '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  607. '<d:prop>' .
  608. ' <c:calendar-data />' .
  609. ' <d:getetag />' .
  610. '</d:prop>' .
  611. '</c:calendar-query>';
  612. $request = new Sabre_HTTP_Request(array(
  613. 'REQUEST_METHOD' => 'REPORT',
  614. 'REQUEST_URI' => '/calendars/user1//UUID-123467',
  615. ));
  616. $request->setBody($body);
  617. $this->server->httpRequest = $request;
  618. $this->server->exec();
  619. $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
  620. }
  621. /**
  622. * @depends testSupportedReportSetProperty
  623. * @depends testCalendarMultiGetReport
  624. */
  625. function testCalendarQueryReport1Object() {
  626. $body =
  627. '<?xml version="1.0"?>' .
  628. '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  629. '<d:prop>' .
  630. ' <c:calendar-data>' .
  631. ' <c:expand start="20000101T000000Z" end="20101231T235959Z" />' .
  632. ' </c:calendar-data>' .
  633. ' <d:getetag />' .
  634. '</d:prop>' .
  635. '<c:filter>' .
  636. ' <c:comp-filter name="VCALENDAR">' .
  637. ' <c:comp-filter name="VEVENT" />' .
  638. ' </c:comp-filter>' .
  639. '</c:filter>' .
  640. '</c:calendar-query>';
  641. $request = new Sabre_HTTP_Request(array(
  642. 'REQUEST_METHOD' => 'REPORT',
  643. 'REQUEST_URI' => '/calendars/user1/UUID-123467/UUID-2345',
  644. 'HTTP_DEPTH' => '0',
  645. ));
  646. $request->setBody($body);
  647. $this->server->httpRequest = $request;
  648. $this->server->exec();
  649. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
  650. $xml = simplexml_load_string($this->response->body);
  651. $xml->registerXPathNamespace('d','DAV:');
  652. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  653. $check = array(
  654. '/d:multistatus',
  655. '/d:multistatus/d:response',
  656. '/d:multistatus/d:response/d:href',
  657. '/d:multistatus/d:response/d:propstat',
  658. '/d:multistatus/d:response/d:propstat/d:prop',
  659. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  660. '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
  661. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  662. );
  663. foreach($check as $v1=>$v2) {
  664. $xpath = is_int($v1)?$v2:$v1;
  665. $result = $xml->xpath($xpath);
  666. $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
  667. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  668. }
  669. }
  670. /**
  671. * @depends testSupportedReportSetProperty
  672. * @depends testCalendarMultiGetReport
  673. */
  674. function testCalendarQueryReport1ObjectNoCalData() {
  675. $body =
  676. '<?xml version="1.0"?>' .
  677. '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  678. '<d:prop>' .
  679. ' <d:getetag />' .
  680. '</d:prop>' .
  681. '<c:filter>' .
  682. ' <c:comp-filter name="VCALENDAR">' .
  683. ' <c:comp-filter name="VEVENT" />' .
  684. ' </c:comp-filter>' .
  685. '</c:filter>' .
  686. '</c:calendar-query>';
  687. $request = new Sabre_HTTP_Request(array(
  688. 'REQUEST_METHOD' => 'REPORT',
  689. 'REQUEST_URI' => '/calendars/user1/UUID-123467/UUID-2345',
  690. 'HTTP_DEPTH' => '0',
  691. ));
  692. $request->setBody($body);
  693. $this->server->httpRequest = $request;
  694. $this->server->exec();
  695. $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
  696. $xml = simplexml_load_string($this->response->body);
  697. $xml->registerXPathNamespace('d','DAV:');
  698. $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
  699. $check = array(
  700. '/d:multistatus',
  701. '/d:multistatus/d:response',
  702. '/d:multistatus/d:response/d:href',
  703. '/d:multistatus/d:response/d:propstat',
  704. '/d:multistatus/d:response/d:propstat/d:prop',
  705. '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
  706. '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
  707. );
  708. foreach($check as $v1=>$v2) {
  709. $xpath = is_int($v1)?$v2:$v1;
  710. $result = $xml->xpath($xpath);
  711. $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
  712. if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
  713. }
  714. }
  715. function testHTMLActionsPanel() {
  716. $output = '';
  717. $r = $this->server->broadcastEvent('onHTMLActionsPanel', array($this->server->tree->getNodeForPath('calendars/user1'), &$output));
  718. $this->assertFalse($r);
  719. $this->assertTrue(!!strpos($output,'Display name'));
  720. }
  721. function testBrowserPostAction() {
  722. $r = $this->server->broadcastEvent('onBrowserPostAction', array('calendars/user1', 'mkcalendar', array(
  723. 'name' => 'NEWCALENDAR',
  724. '{DAV:}displayname' => 'foo',
  725. )));
  726. $this->assertFalse($r);
  727. $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
  728. $this->assertEquals(3, count($calendars));
  729. $newCalendar = null;
  730. foreach($calendars as $calendar) {
  731. if ($calendar['uri'] === 'NEWCALENDAR') {
  732. $newCalendar = $calendar;
  733. break;
  734. }
  735. }
  736. if (!$newCalendar)
  737. $this->fail('Could not find newly created calendar');
  738. }
  739. /**
  740. * @depends testCalendarMultiGetReport
  741. */
  742. function testCalendarMultiGetReportNoEnd() {
  743. $body =
  744. '<?xml version="1.0"?>' .
  745. '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  746. '<d:prop>' .
  747. ' <c:calendar-data>' .
  748. ' <c:expand start="20110101T000000Z" />' .
  749. ' </c:calendar-data>' .
  750. ' <d:getetag />' .
  751. '</d:prop>' .
  752. '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
  753. '</c:calendar-multiget>';
  754. $request = new Sabre_HTTP_Request(array(
  755. 'REQUEST_METHOD' => 'REPORT',
  756. 'REQUEST_URI' => '/calendars/user1',
  757. 'HTTP_DEPTH' => '1',
  758. ));
  759. $request->setBody($body);
  760. $this->server->httpRequest = $request;
  761. $this->server->exec();
  762. $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
  763. }
  764. /**
  765. * @depends testCalendarMultiGetReport
  766. */
  767. function testCalendarMultiGetReportNoStart() {
  768. $body =
  769. '<?xml version="1.0"?>' .
  770. '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  771. '<d:prop>' .
  772. ' <c:calendar-data>' .
  773. ' <c:expand end="20110101T000000Z" />' .
  774. ' </c:calendar-data>' .
  775. ' <d:getetag />' .
  776. '</d:prop>' .
  777. '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
  778. '</c:calendar-multiget>';
  779. $request = new Sabre_HTTP_Request(array(
  780. 'REQUEST_METHOD' => 'REPORT',
  781. 'REQUEST_URI' => '/calendars/user1',
  782. 'HTTP_DEPTH' => '1',
  783. ));
  784. $request->setBody($body);
  785. $this->server->httpRequest = $request;
  786. $this->server->exec();
  787. $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
  788. }
  789. /**
  790. * @depends testCalendarMultiGetReport
  791. */
  792. function testCalendarMultiGetReportEndBeforeStart() {
  793. $body =
  794. '<?xml version="1.0"?>' .
  795. '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
  796. '<d:prop>' .
  797. ' <c:calendar-data>' .
  798. ' <c:expand start="20200101T000000Z" end="20110101T000000Z" />' .
  799. ' </c:calendar-data>' .
  800. ' <d:getetag />' .
  801. '</d:prop>' .
  802. '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
  803. '</c:calendar-multiget>';
  804. $request = new Sabre_HTTP_Request(array(
  805. 'REQUEST_METHOD' => 'REPORT',
  806. 'REQUEST_URI' => '/calendars/user1',
  807. 'HTTP_DEPTH' => '1',
  808. ));
  809. $request->setBody($body);
  810. $this->server->httpRequest = $request;
  811. $this->server->exec();
  812. $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
  813. }
  814. function testNotificationProperties() {
  815. $request = array(
  816. '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}notificationtype',
  817. );
  818. $result = array();
  819. $notification = new Sabre_CalDAV_Notifications_Node(
  820. $this->caldavBackend,
  821. new Sabre_CalDAV_Notifications_Notification_SystemStatus('foo')
  822. );
  823. $this->plugin->beforeGetProperties('foo', $notification, $request, $result);
  824. $this->assertEquals(
  825. array(
  826. 200 => array(
  827. '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}notificationtype' => $notification->getNotificationType()
  828. )
  829. ), $result);
  830. }
  831. function testNotificationGet() {
  832. $notification = new Sabre_CalDAV_Notifications_Node(
  833. $this->caldavBackend,
  834. new Sabre_CalDAV_Notifications_Notification_SystemStatus('foo')
  835. );
  836. $server = new Sabre_DAV_Server(array($notification));
  837. $caldav = new Sabre_CalDAV_Plugin();
  838. $httpResponse = new Sabre_HTTP_ResponseMock();
  839. $server->httpResponse = $httpResponse;
  840. $server->addPlugin($caldav);
  841. $caldav->beforeMethod('GET','foo');
  842. $this->assertEquals('HTTP/1.1 200 OK', $httpResponse->status);
  843. $this->assertEquals(array(
  844. 'Content-Type' => 'application/xml',
  845. ), $httpResponse->headers);
  846. $expected =
  847. '<?xml version="1.0" encoding="UTF-8"?>
  848. <cs:notification xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
  849. <cs:systemstatus type="high"/>
  850. </cs:notification>
  851. ';
  852. $this->assertEquals($expected, $httpResponse->body);
  853. }
  854. }