0012000: WebDAV fails overwriting file silently, possible data loss
authorCornelius Weiß <c.weiss@metaways.de>
Thu, 7 Jul 2016 16:23:05 +0000 (18:23 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Mon, 11 Jul 2016 08:55:06 +0000 (10:55 +0200)
* fix update etag test
* add update contents test
* fix update from webdav (hash file ref did't update)
* add OC-MTIME test
* improve OC-MTIME header handling

Change-Id: I8ef48b1cfc2fcabe8cb1ec3e2d55bc4b743fe964
Reviewed-on: http://gerrit.tine20.com/customers/3331
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Filemanager/Frontend/WebDAVTest.php
tine20/Tinebase/FileSystem.php
tine20/Tinebase/Frontend/WebDAV/File.php
tine20/Tinebase/Server/WebDAV.php

index 204dde4..27fb478 100644 (file)
@@ -187,11 +187,12 @@ class Filemanager_Frontend_WebDAVTest extends TestCase
     public function testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file()
     {
         $parent = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory();
+        $filename = dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png';
         
-        $etag = $parent->createFile('tine_logo.png', fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png', 'r'));
+        $etag = $parent->createFile('tine_logo.png', fopen($filename, 'r'));
         
         $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
-        
+
         $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
         $this->assertTrue(is_resource($node->get()));
         $this->assertEquals('tine_logo.png', $node->getName());
@@ -199,6 +200,7 @@ class Filemanager_Frontend_WebDAVTest extends TestCase
         $this->assertEquals('image/png', $node->getContentType());
         $this->assertEquals('"7424e2c16388bf388af1c4fe44c1dd67d31f468b"', $node->getETag());
         $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
+        $this->assertTrue(fread($node->get(), 10000) == file_get_contents($filename), 'content not saved');
         
         return $node;
     }
@@ -206,13 +208,36 @@ class Filemanager_Frontend_WebDAVTest extends TestCase
     public function testUpdateFile()
     {
         $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
-        
-        $etag = $node->put(fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png', 'r'));
-        
+        $eTag = $node->getETag();
+
+        $updateFile = dirname(__FILE__) . '/../../Tinebase/files/tine_logo_setup.png';
+
+        $updatedEtag = $node->put(fopen($updateFile, 'r'));
+
         $this->assertEquals('Filemanager_Frontend_WebDAV_File', get_class($node), 'wrong type');
-        $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
+        $this->assertNotEquals($eTag, $updatedEtag, 'eTag did not changed');
+        $this->assertTrue(preg_match('/"\w+"/', $updatedEtag) === 1);
+
+        $this->assertTrue(fread($node->get(), 10000) == file_get_contents($updateFile), 'content not updated');
     }
-    
+
+    public function testUpdateFileWithOCMTime()
+    {
+        $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
+        $filename = dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png';
+        $updateFile = dirname(__FILE__) . '/../../Tinebase/files/tine_logo_setup.png';
+
+        $mtime = Tinebase_DateTime::now()->subDay(1);
+        $_SERVER['HTTP_X_OC_MTIME'] = $mtime->getTimestamp();
+
+        $node->put(fopen($updateFile, 'r'));
+
+        unset($_SERVER['HTTP_X_OC_MTIME']);
+
+        $savedMTime = new Tinebase_DateTime($node->getLastModified());
+        $this->assertEquals($mtime, $savedMTime, 'X_OC_MTIME not saved');
+    }
+
     /**
      * test chunked upload from OwnCloud clients
      * 
index c5acb46..92d8a67 100644 (file)
@@ -375,7 +375,7 @@ class Tinebase_FileSystem implements Tinebase_Controller_Interface
         // quick hack for 2014.11 - will be resolved correctly in 2015.11-develop
         if (isset($_SERVER['HTTP_X_OC_MTIME'])) {
             $updatedFileObject->last_modified_time = new Tinebase_DateTime($_SERVER['HTTP_X_OC_MTIME']);
-            header('X-OC-MTime: accepted');
+            Tinebase_Server_WebDAV::getResponse()->setHeader('X-OC-MTime', 'accepted');
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " using X-OC-MTIME: {$updatedFileObject->last_modified_time->format(Tinebase_Record_Abstract::ISO8601LONG)} for {$updatedFileObject->id}");
 
@@ -856,7 +856,7 @@ class Tinebase_FileSystem implements Tinebase_Controller_Interface
         if (isset($_SERVER['HTTP_X_OC_MTIME'])) {
             $fileObject->creation_time = new Tinebase_DateTime($_SERVER['HTTP_X_OC_MTIME']);
             $fileObject->last_modified_time = new Tinebase_DateTime($_SERVER['HTTP_X_OC_MTIME']);
-            header('X-OC-MTime: accepted');
+            Tinebase_Server_WebDAV::getResponse()->setHeader('X-OC-MTime', 'accepted');
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " using X-OC-MTIME: {$fileObject->last_modified_time->format(Tinebase_Record_Abstract::ISO8601LONG)} for {$name}");
 
@@ -1061,7 +1061,7 @@ class Tinebase_FileSystem implements Tinebase_Controller_Interface
         // quick hack for 2014.11 - will be resolved correctly in 2015.11-develop
         if (isset($_SERVER['HTTP_X_OC_MTIME'])) {
             $fileObject->last_modified_time = new Tinebase_DateTime($_SERVER['HTTP_X_OC_MTIME']);
-            header('X-OC-MTime: accepted');
+            Tinebase_Server_WebDAV::getResponse()->setHeader('X-OC-MTime', 'accepted');
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " using X-OC-MTIME: {$fileObject->last_modified_time->format(Tinebase_Record_Abstract::ISO8601LONG)} for {$_node->name}");
 
index 6b23b9a..92f8130 100644 (file)
@@ -83,8 +83,8 @@ class Tinebase_Frontend_WebDAV_File extends Tinebase_Frontend_WebDAV_Node implem
         // save file object
         Tinebase_FileSystem::getInstance()->fclose($handle);
 
-        // save node
-        Tinebase_FileSystem::getInstance()->update($this->_node);
+        // refetch data
+        $this->_node = Tinebase_FileSystem::getInstance()->stat($this->_path);
 
         return $this->getETag();
     }
index 68b06cc..0bdf670 100644 (file)
@@ -165,7 +165,17 @@ class Tinebase_Server_WebDAV extends Tinebase_Server_Abstract implements Tinebas
     {
         return self::$_server ? self::$_server->httpRequest : new Sabre\HTTP\Request();
     }
-    
+
+    /**
+     * helper to return response
+     *
+     * @return Sabre\HTTP\Response
+     */
+    public static function getResponse()
+    {
+        return self::$_server ? self::$_server->httpResponse : new Sabre\HTTP\Response();
+    }
+
     /**
     * returns request method
     *