1<?php
2
3namespace Sabre;
4
5use Sabre\HTTP\Request;
6use Sabre\HTTP\Response;
7use Sabre\HTTP\Sapi;
8
9/**
10 * This class may be used as a basis for other webdav-related unittests.
11 *
12 * This class is supposed to provide a reasonably big framework to quickly get
13 * a testing environment running.
14 *
15 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
16 * @author Evert Pot (http://evertpot.com/)
17 * @license http://sabre.io/license/ Modified BSD License
18 */
19abstract class DAVServerTest extends \PHPUnit_Framework_TestCase {
20
21    protected $setupCalDAV = false;
22    protected $setupCardDAV = false;
23    protected $setupACL = false;
24    protected $setupCalDAVSharing = false;
25    protected $setupCalDAVScheduling = false;
26    protected $setupCalDAVSubscriptions = false;
27    protected $setupCalDAVICSExport = false;
28    protected $setupLocks = false;
29    protected $setupFiles = false;
30    protected $setupSharing = false;
31    protected $setupPropertyStorage = false;
32
33    /**
34     * An array with calendars. Every calendar should have
35     *   - principaluri
36     *   - uri
37     */
38    protected $caldavCalendars = [];
39    protected $caldavCalendarObjects = [];
40
41    protected $carddavAddressBooks = [];
42    protected $carddavCards = [];
43
44    /**
45     * @var Sabre\DAV\Server
46     */
47    protected $server;
48    protected $tree = [];
49
50    protected $caldavBackend;
51    protected $carddavBackend;
52    protected $principalBackend;
53    protected $locksBackend;
54    protected $propertyStorageBackend;
55
56    /**
57     * @var Sabre\CalDAV\Plugin
58     */
59    protected $caldavPlugin;
60
61    /**
62     * @var Sabre\CardDAV\Plugin
63     */
64    protected $carddavPlugin;
65
66    /**
67     * @var Sabre\DAVACL\Plugin
68     */
69    protected $aclPlugin;
70
71    /**
72     * @var Sabre\CalDAV\SharingPlugin
73     */
74    protected $caldavSharingPlugin;
75
76    /**
77     * CalDAV scheduling plugin
78     *
79     * @var CalDAV\Schedule\Plugin
80     */
81    protected $caldavSchedulePlugin;
82
83    /**
84     * @var Sabre\DAV\Auth\Plugin
85     */
86    protected $authPlugin;
87
88    /**
89     * @var Sabre\DAV\Locks\Plugin
90     */
91    protected $locksPlugin;
92
93    /**
94     * Sharing plugin.
95     *
96     * @var \Sabre\DAV\Sharing\Plugin
97     */
98    protected $sharingPlugin;
99
100    /*
101     * @var Sabre\DAV\PropertyStorage\Plugin
102     */
103    protected $propertyStoragePlugin;
104
105    /**
106     * If this string is set, we will automatically log in the user with this
107     * name.
108     */
109    protected $autoLogin = null;
110
111    function setUp() {
112
113        $this->initializeEverything();
114
115    }
116
117    function initializeEverything() {
118
119        $this->setUpBackends();
120        $this->setUpTree();
121
122        $this->server = new DAV\Server($this->tree);
123        $this->server->sapi = new HTTP\SapiMock();
124        $this->server->debugExceptions = true;
125
126        if ($this->setupCalDAV) {
127            $this->caldavPlugin = new CalDAV\Plugin();
128            $this->server->addPlugin($this->caldavPlugin);
129        }
130        if ($this->setupCalDAVSharing || $this->setupSharing) {
131            $this->sharingPlugin = new DAV\Sharing\Plugin();
132            $this->server->addPlugin($this->sharingPlugin);
133        }
134        if ($this->setupCalDAVSharing) {
135            $this->caldavSharingPlugin = new CalDAV\SharingPlugin();
136            $this->server->addPlugin($this->caldavSharingPlugin);
137        }
138        if ($this->setupCalDAVScheduling) {
139            $this->caldavSchedulePlugin = new CalDAV\Schedule\Plugin();
140            $this->server->addPlugin($this->caldavSchedulePlugin);
141        }
142        if ($this->setupCalDAVSubscriptions) {
143            $this->server->addPlugin(new CalDAV\Subscriptions\Plugin());
144        }
145        if ($this->setupCalDAVICSExport) {
146            $this->caldavICSExportPlugin = new CalDAV\ICSExportPlugin();
147            $this->server->addPlugin($this->caldavICSExportPlugin);
148        }
149        if ($this->setupCardDAV) {
150            $this->carddavPlugin = new CardDAV\Plugin();
151            $this->server->addPlugin($this->carddavPlugin);
152        }
153        if ($this->setupLocks) {
154            $this->locksPlugin = new DAV\Locks\Plugin(
155                $this->locksBackend
156            );
157            $this->server->addPlugin($this->locksPlugin);
158        }
159        if ($this->setupPropertyStorage) {
160            $this->propertyStoragePlugin = new DAV\PropertyStorage\Plugin(
161                $this->propertyStorageBackend
162            );
163            $this->server->addPlugin($this->propertyStoragePlugin);
164        }
165        if ($this->autoLogin) {
166            $this->autoLogin($this->autoLogin);
167        }
168        if ($this->setupACL) {
169            $this->aclPlugin = new DAVACL\Plugin();
170            if (!$this->autoLogin) {
171                $this->aclPlugin->allowUnauthenticatedAccess = false;
172            }
173            $this->aclPlugin->adminPrincipals = ['principals/admin'];
174            $this->server->addPlugin($this->aclPlugin);
175        }
176
177    }
178
179    /**
180     * Makes a request, and returns a response object.
181     *
182     * You can either pass an instance of Sabre\HTTP\Request, or an array,
183     * which will then be used as the _SERVER array.
184     *
185     * If $expectedStatus is set, we'll compare it with the HTTP status of
186     * the returned response. If it doesn't match, we'll immediately fail
187     * the test.
188     *
189     * @param array|\Sabre\HTTP\Request $request
190     * @param int $expectedStatus
191     * @return \Sabre\HTTP\Response
192     */
193    function request($request, $expectedStatus = null) {
194
195        if (is_array($request)) {
196            $request = HTTP\Request::createFromServerArray($request);
197        }
198        $response = new HTTP\ResponseMock();
199
200        $this->server->httpRequest = $request;
201        $this->server->httpResponse = $response;
202        $this->server->exec();
203
204        if ($expectedStatus) {
205            $responseBody = $expectedStatus !== $response->getStatus() ? $response->getBodyAsString() : '';
206            $this->assertEquals($expectedStatus, $response->getStatus(), 'Incorrect HTTP status received for request. Response body: ' . $responseBody);
207        }
208        return $this->server->httpResponse;
209
210    }
211
212    /**
213     * This function takes a username and sets the server in a state where
214     * this user is logged in, and no longer requires an authentication check.
215     *
216     * @param string $userName
217     */
218    function autoLogin($userName) {
219        $authBackend = new DAV\Auth\Backend\Mock();
220        $authBackend->setPrincipal('principals/' . $userName);
221        $this->authPlugin = new DAV\Auth\Plugin($authBackend);
222
223        // If the auth plugin already exists, we're removing its hooks:
224        if ($oldAuth = $this->server->getPlugin('auth')) {
225            $this->server->removeListener('beforeMethod', [$oldAuth, 'beforeMethod']);
226        }
227        $this->server->addPlugin($this->authPlugin);
228
229        // This will trigger the actual login procedure
230        $this->authPlugin->beforeMethod(new Request(), new Response());
231    }
232
233    /**
234     * Override this to provide your own Tree for your test-case.
235     */
236    function setUpTree() {
237
238        if ($this->setupCalDAV) {
239            $this->tree[] = new CalDAV\CalendarRoot(
240                $this->principalBackend,
241                $this->caldavBackend
242            );
243        }
244        if ($this->setupCardDAV) {
245            $this->tree[] = new CardDAV\AddressBookRoot(
246                $this->principalBackend,
247                $this->carddavBackend
248            );
249        }
250
251        if ($this->setupCalDAV) {
252            $this->tree[] = new CalDAV\Principal\Collection(
253                $this->principalBackend
254            );
255        } elseif ($this->setupCardDAV || $this->setupACL) {
256            $this->tree[] = new DAVACL\PrincipalCollection(
257                $this->principalBackend
258            );
259        }
260        if ($this->setupFiles) {
261
262            $this->tree[] = new DAV\Mock\Collection('files');
263
264        }
265
266    }
267
268    function setUpBackends() {
269
270        if ($this->setupCalDAVSharing && is_null($this->caldavBackend)) {
271            $this->caldavBackend = new CalDAV\Backend\MockSharing($this->caldavCalendars, $this->caldavCalendarObjects);
272        }
273        if ($this->setupCalDAVSubscriptions && is_null($this->caldavBackend)) {
274            $this->caldavBackend = new CalDAV\Backend\MockSubscriptionSupport($this->caldavCalendars, $this->caldavCalendarObjects);
275        }
276        if ($this->setupCalDAV && is_null($this->caldavBackend)) {
277            if ($this->setupCalDAVScheduling) {
278                $this->caldavBackend = new CalDAV\Backend\MockScheduling($this->caldavCalendars, $this->caldavCalendarObjects);
279            } else {
280                $this->caldavBackend = new CalDAV\Backend\Mock($this->caldavCalendars, $this->caldavCalendarObjects);
281            }
282        }
283        if ($this->setupCardDAV && is_null($this->carddavBackend)) {
284            $this->carddavBackend = new CardDAV\Backend\Mock($this->carddavAddressBooks, $this->carddavCards);
285        }
286        if ($this->setupCardDAV || $this->setupCalDAV || $this->setupACL) {
287            $this->principalBackend = new DAVACL\PrincipalBackend\Mock();
288        }
289        if ($this->setupLocks) {
290            $this->locksBackend = new DAV\Locks\Backend\Mock();
291        }
292        if ($this->setupPropertyStorage)  {
293            $this->propertyStorageBackend = new DAV\PropertyStorage\Backend\Mock();
294        }
295
296    }
297
298
299    function assertHttpStatus($expectedStatus, HTTP\Request $req) {
300
301        $resp = $this->request($req);
302        $this->assertEquals((int)$expectedStatus, (int)$resp->status, 'Incorrect HTTP status received: ' . $resp->body);
303
304    }
305
306}
307