0012000: WebDAV fails overwriting file silently, possible data loss
[tine20] / tests / tine20 / Filemanager / Frontend / WebDAVTest.php
1 <?php
2 /**
3  * Tine 2.0 - http://www.tine20.org
4  * 
5  * @package     Filemanager
6  * @license     http://www.gnu.org/licenses/agpl.html
7  * @copyright   Copyright (c) 2010-2014 Metaways Infosystems GmbH (http://www.metaways.de)
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  */
10
11 /**
12  * Test class for Filemanager_Frontend_Tree
13  * 
14  * @package     Filemanager
15  */
16 class Filemanager_Frontend_WebDAVTest extends TestCase
17 {
18     /**
19      * Tree
20      *
21      * @var Sabre\DAV\ObjectTree
22      */
23     protected $_webdavTree;
24     
25     /**
26      * testgetNodeForPath
27      */
28     public function testgetNodeForPath()
29     {
30         $node = $this->_getWebDAVTree()->getNodeForPath(null);
31         
32         $this->assertInstanceOf('Tinebase_WebDav_Root', $node, 'wrong node class');
33         
34         $children = $node->getChildren();
35         
36         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
37         
38         $this->_getWebDAVTree()->delete('/');
39     }
40     
41     public function testgetNodeForPath_webdav()
42     {
43         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav');
44         
45         $this->assertInstanceOf('\Sabre\DAV\SimpleCollection', $node, 'wrong node class');
46         $this->assertEquals('webdav', $node->getName());
47         
48         $children = $node->getChildren();
49         
50         $this->assertInstanceOf('Tinebase_WebDav_Collection_AbstractContainerTree', $children[0], 'wrong child class');
51         
52         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
53         
54         $this->_getWebDAVTree()->delete('/webdav');
55     }
56     
57     public function testgetNodeForPath_webdav_filemanager()
58     {
59         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager');
60         
61         $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
62         $this->assertEquals('Filemanager', $node->getName());
63         
64         $children = $node->getChildren();
65         
66         $this->assertGreaterThanOrEqual(2, count($children));
67         $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $children[0], 'wrong node class');
68         
69         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
70         
71         $this->_getWebDAVTree()->delete('/webdav/Filemanager');
72     }
73     
74     /**
75      * test currently fails:
76      * 
77      * 1) Filemanager_Frontend_WebDAVTest::testgetNodeForPath_webdav_filemanager_personal
78      * Sabre\DAV\Exception\NotFound: Directory Filemanager/personal not found
79      * 
80      * /var/lib/jenkins-tine20.com/jobs/tine20com-gerrit/workspace/tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php:128
81      * /var/lib/jenkins-tine20.com/jobs/tine20com-gerrit/workspace/tine20/vendor/sabre/dav/lib/Sabre/DAV/ObjectTree.php:72
82      * /var/lib/jenkins-tine20.com/jobs/tine20com-gerrit/workspace/tests/tine20/Filemanager/Frontend/WebDAVTest.php:76
83      */
84     public function testgetNodeForPath_webdav_filemanager_personal()
85     {
86         $this->markTestSkipped('FIXME');
87         
88         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/personal');
89         
90         $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
91         $this->assertEquals('personal', $node->getName());
92         
93         $children = $node->getChildren();
94         
95         $this->assertEquals(1, count($children));
96         $this->assertEquals('Filemanager_Frontend_WebDAV', get_class($children[0]), 'wrong child class');
97         
98         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
99         
100         $this->_getWebDAVTree()->delete('/webdav/Filemanager/personal');
101     }
102     
103     public function testgetNodeForPath_webdav_filemanager_currentuser()
104     {
105         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
106         
107         $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
108         $this->assertEquals(Tinebase_Core::getUser()->accountDisplayName, $node->getName());
109         
110         $children = $node->getChildren();
111         
112         $this->assertGreaterThanOrEqual(1, count($children));
113         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $children[0], 'wrong node class');
114         
115         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
116         
117         $this->_getWebDAVTree()->delete('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
118     }
119     
120     /**
121      * @return Filemanager_Frontend_WebDAV_Directory
122      */
123     public function testgetNodeForPath_webdav_filemanager_currentuser_unittestdirectory()
124     {
125         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
126         
127         $node->createDirectory('unittestdirectory');
128         
129         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
130         
131         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $node, 'wrong node class');
132         $this->assertEquals('unittestdirectory', $node->getName());
133         
134         $children = $this->_getWebDAVTree()->getChildren('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
135         foreach ($children as $node) {
136             $names[] = $node->getName();
137         }
138         $this->assertContains('unittestdirectory', $names);
139         
140         $this->_getWebDAVTree()->delete('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
141         
142         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
143         
144         $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
145     }
146     
147     public function testgetNodeForPath_webdav_filemanager_shared()
148     {
149         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared');
150         
151         $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
152         $this->assertEquals('shared', $node->getName());
153         
154         $children = $node->getChildren();
155         
156         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
157         
158         $this->_getWebDAVTree()->delete('/webdav/Filemanager/shared');
159     }
160     
161     /**
162      * testgetNodeForPath_webdav_filemanager_shared_unittestdirectory
163      * 
164      * @return Filemanager_Frontend_WebDAV_Container
165      */
166     public function testgetNodeForPath_webdav_filemanager_shared_unittestdirectory()
167     {
168         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared');
169         
170         $node->createDirectory('unittestdirectory');
171         
172         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory');
173         
174         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $node, 'wrong node class');
175         $this->assertEquals('unittestdirectory', $node->getName());
176         
177         $children = $node->getChildren();
178         
179         $properties = $node->getProperties(array());
180         
181         return $node;
182     }
183     
184     /**
185      * @return Filemanager_Frontend_WebDAV_File
186      */
187     public function testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file()
188     {
189         $parent = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory();
190         $filename = dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png';
191         
192         $etag = $parent->createFile('tine_logo.png', fopen($filename, 'r'));
193         
194         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
195
196         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
197         $this->assertTrue(is_resource($node->get()));
198         $this->assertEquals('tine_logo.png', $node->getName());
199         $this->assertEquals(7246, $node->getSize());
200         $this->assertEquals('image/png', $node->getContentType());
201         $this->assertEquals('"7424e2c16388bf388af1c4fe44c1dd67d31f468b"', $node->getETag());
202         $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
203         $this->assertTrue(fread($node->get(), 10000) == file_get_contents($filename), 'content not saved');
204         
205         return $node;
206     }
207     
208     public function testUpdateFile()
209     {
210         $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
211         $eTag = $node->getETag();
212
213         $updateFile = dirname(__FILE__) . '/../../Tinebase/files/tine_logo_setup.png';
214
215         $updatedEtag = $node->put(fopen($updateFile, 'r'));
216
217         $this->assertEquals('Filemanager_Frontend_WebDAV_File', get_class($node), 'wrong type');
218         $this->assertNotEquals($eTag, $updatedEtag, 'eTag did not changed');
219         $this->assertTrue(preg_match('/"\w+"/', $updatedEtag) === 1);
220
221         $this->assertTrue(fread($node->get(), 10000) == file_get_contents($updateFile), 'content not updated');
222     }
223
224     public function testUpdateFileWithOCMTime()
225     {
226         $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
227         $filename = dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png';
228         $updateFile = dirname(__FILE__) . '/../../Tinebase/files/tine_logo_setup.png';
229
230         $mtime = Tinebase_DateTime::now()->subDay(1);
231         $_SERVER['HTTP_X_OC_MTIME'] = $mtime->getTimestamp();
232
233         $node->put(fopen($updateFile, 'r'));
234
235         unset($_SERVER['HTTP_X_OC_MTIME']);
236
237         $savedMTime = new Tinebase_DateTime($node->getLastModified());
238         $this->assertEquals($mtime, $savedMTime, 'X_OC_MTIME not saved');
239     }
240
241     /**
242      * test chunked upload from OwnCloud clients
243      * 
244      * @backupGlobals enabled
245      * @return Filemanager_Frontend_WebDAV_File
246      */
247 //    public function testOwnCloudChunkedUpload()
248 //    {
249 //        // this currently fails on http://ci.tine20.org/job/tine20-gerrit-cloud
250 //        // -> Exception: DateTimeZone::__construct(): Unknown or bad timezone (+00:00)
251 //        $this->markTestSkipped('FIXME repair this test');
252 //
253 //        $_SERVER['HTTP_OC_CHUNKED'] = 1;
254 //
255 //        $fileStream = fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png', 'r');
256 //
257 //        $parent = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory();
258 //
259 //        // upload first chunk
260 //        $tempStream = fopen('php://temp', 'w');
261 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream, 1000);
262 //        rewind($tempStream);
263 //        $etag = $parent->createFile('tine_logo.png-chunking-1000-3-0', $tempStream);
264 //        fclose($tempStream);
265 //
266 //        // upload second chunk
267 //        $tempStream = fopen('php://temp', 'w');
268 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream, 1000);
269 //        rewind($tempStream);
270 //        $etag = $parent->createFile('tine_logo.png-chunking-1000-3-1', $tempStream);
271 //        fclose($tempStream);
272 //
273 //        // upload last chunk
274 //        $tempStream = fopen('php://temp', 'w');
275 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream);
276 //        rewind($tempStream);
277 //        $etag = $parent->createFile('tine_logo.png-chunking-1000-3-2', $tempStream);
278 //        fclose($tempStream);
279 //        fclose($fileStream);
280 //
281 //        // retrieve final node
282 //        $this->_getWebDAVTree()->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
283 //        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
284 //
285 //        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
286 //        $this->assertTrue(is_resource($node->get()));
287 //        $this->assertEquals('tine_logo.png', $node->getName());
288 //        $this->assertEquals(7246, $node->getSize());
289 //        $this->assertEquals('image/png', $node->getContentType());
290 //        $this->assertEquals('"7424e2c16388bf388af1c4fe44c1dd67d31f468b"', $node->getETag());
291 //        $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
292 //
293 //        $fileStream = fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo_setup.png', 'r');
294 //
295 //        // upload first chunk
296 //        $tempStream = fopen('php://temp', 'w');
297 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream, 1000);
298 //        rewind($tempStream);
299 //        $etag = $parent->createFile('tine_logo.png-chunking-1001-3-0', $tempStream);
300 //        fclose($tempStream);
301 //
302 //        // upload second chunk
303 //        $tempStream = fopen('php://temp', 'w');
304 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream, 1000);
305 //        rewind($tempStream);
306 //        $etag = $parent->createFile('tine_logo.png-chunking-1001-3-1', $tempStream);
307 //        fclose($tempStream);
308 //
309 //        // upload last chunk
310 //        $tempStream = fopen('php://temp', 'w');
311 //        $_SERVER['CONTENT_LENGTH'] = stream_copy_to_stream($fileStream, $tempStream);
312 //        rewind($tempStream);
313 //        $etag = $parent->createFile('tine_logo.png-chunking-1001-3-2', $tempStream);
314 //        fclose($tempStream);
315 //
316 //        // retrieve final node
317 //        $this->_getWebDAVTree()->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
318 //        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
319 //
320 //        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
321 //        $this->assertTrue(is_resource($node->get()));
322 //        $this->assertEquals('tine_logo.png', $node->getName());
323 //        $this->assertEquals(7258, $node->getSize());
324 //        $this->assertEquals('image/png', $node->getContentType());
325 //        $this->assertEquals('"434f1e3474a04ce3a10febad78a64e65d7b4f531"', $node->getETag());
326 //        $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
327 //
328 //        return $node;
329 //    }
330     
331     public function testDeleteFile()
332     {
333         $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
334     
335         $this->_getWebDAVTree()->delete('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
336     
337         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
338         
339         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
340     }
341     
342     /**
343      * @return Filemanager_Frontend_WebDAV_Directory
344      */
345     public function testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_directory()
346     {
347         $parent = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory();
348     
349         $file = $parent->createDirectory('directory');
350     
351         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/directory');
352     
353         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Directory', $node, 'wrong node class');
354         $this->assertEquals('directory', $node->getName());
355             
356         return $node;
357     }
358     
359     public function testgetNodeForPath_invalidApplication()
360     {
361         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
362         
363         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/invalidApplication');
364     }
365     
366     public function testgetNodeForPath_invalidContainerType()
367     {
368         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
369         
370         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/invalidContainerType');
371     }
372     
373     public function testgetNodeForPath_invalidFolder()
374     {
375         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
376         
377         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/invalidContainer');
378     }
379     
380     /**
381      * 
382      * @return \Sabre\DAV\ObjectTree
383      */
384     protected function _getWebDAVTree()
385     {
386         if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
387             $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
388         }
389         
390         return $this->_webdavTree;
391     }
392 }