]> source.dussan.org Git - nextcloud-server.git/commitdiff
Merge branch 'master' into fixing-4011-master
authorThomas Müller <thomas.mueller@tmit.eu>
Fri, 4 Oct 2013 12:06:42 +0000 (14:06 +0200)
committerThomas Müller <thomas.mueller@tmit.eu>
Fri, 4 Oct 2013 12:06:42 +0000 (14:06 +0200)
1  2 
lib/private/connector/sabre/directory.php
lib/private/connector/sabre/file.php
lib/private/connector/sabre/node.php

index 0000000000000000000000000000000000000000,382bdf06df1f272e311e5fd2e0fca8f30f539860..af0dfd70f08e32670285c5e5ba5544de5091beda
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,256 +1,218 @@@
 -              if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
 -                      $info = OC_FileChunking::decodeName($name);
 -                      if (empty($info)) {
 -                              throw new Sabre_DAV_Exception_NotImplemented();
 -                      }
 -                      $chunk_handler = new OC_FileChunking($info);
 -                      $chunk_handler->store($info['index'], $data);
 -                      if ($chunk_handler->isComplete()) {
 -                              $newPath = $this->path . '/' . $info['name'];
 -                              $chunk_handler->file_assemble($newPath);
 -                              return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
 -                      }
 -              } else {
 -                      $newPath = $this->path . '/' . $name;
 -
 -                      // mark file as partial while uploading (ignored by the scanner)
 -                      $partpath = $newPath . '.part';
 -
 -                      \OC\Files\Filesystem::file_put_contents($partpath, $data);
 -
 -                      // rename to correct path
 -                      $renameOkay = \OC\Files\Filesystem::rename($partpath, $newPath);
 -                      $fileExists = \OC\Files\Filesystem::file_exists($newPath);
 -                      if ($renameOkay === false || $fileExists === false) {
 -                              \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
 -                              \OC\Files\Filesystem::unlink($partpath);
 -                              throw new Sabre_DAV_Exception();
 -                      }
 -
 -                      // allow sync clients to send the mtime along in a header
 -                      $mtime = OC_Request::hasModificationTime();
 -                      if ($mtime !== false) {
 -                              if(\OC\Files\Filesystem::touch($newPath, $mtime)) {
 -                                      header('X-OC-MTime: accepted');
 -                              }
 -                      }
 -
 -                      return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
 -              }
+ <?php
+ /**
+  * ownCloud
+  *
+  * @author Jakob Sack
+  * @copyright 2011 Jakob Sack kde@jakobsack.de
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  * License as published by the Free Software Foundation; either
+  * version 3 of the License, or any later version.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public
+  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
+ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sabre_DAV_ICollection, Sabre_DAV_IQuota {
+       /**
+        * Creates a new file in the directory
+        *
+        * Data will either be supplied as a stream resource, or in certain cases
+        * as a string. Keep in mind that you may have to support either.
+        *
+        * After succesful creation of the file, you may choose to return the ETag
+        * of the new file here.
+        *
+        * The returned ETag must be surrounded by double-quotes (The quotes should
+        * be part of the actual string).
+        *
+        * If you cannot accurately determine the ETag, you should not return it.
+        * If you don't store the file exactly as-is (you're transforming it
+        * somehow) you should also not return an ETag.
+        *
+        * This means that if a subsequent GET to this new file does not exactly
+        * return the same contents of what was submitted here, you are strongly
+        * recommended to omit the ETag.
+        *
+        * @param string $name Name of the file
+        * @param resource|string $data Initial payload
+        * @throws Sabre_DAV_Exception_Forbidden
+        * @return null|string
+        */
+       public function createFile($name, $data = null) {
+               if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
 -              return null;
++              $path = $this->path . '/' . $name;
++              $node = new OC_Connector_Sabre_File($path);
++              return $node->put($data);
 -       * @return void
+       }
+       /**
+        * Creates a new subdirectory
+        *
+        * @param string $name
+        * @throws Sabre_DAV_Exception_Forbidden
+        * @return void
+        */
+       public function createDirectory($name) {
+               if (!\OC\Files\Filesystem::isCreatable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               $newPath = $this->path . '/' . $name;
+               if(!\OC\Files\Filesystem::mkdir($newPath)) {
+                       throw new Sabre_DAV_Exception_Forbidden('Could not create directory '.$newPath);
+               }
+       }
+       /**
+        * Returns a specific child node, referenced by its name
+        *
+        * @param string $name
+        * @throws Sabre_DAV_Exception_FileNotFound
+        * @return Sabre_DAV_INode
+        */
+       public function getChild($name, $info = null) {
+               $path = $this->path . '/' . $name;
+               if (is_null($info)) {
+                       $info = \OC\Files\Filesystem::getFileInfo($path);
+               }
+               if (!$info) {
+                       throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
+               }
+               if ($info['mimetype'] == 'httpd/unix-directory') {
+                       $node = new OC_Connector_Sabre_Directory($path);
+               } else {
+                       $node = new OC_Connector_Sabre_File($path);
+               }
+               $node->setFileinfoCache($info);
+               return $node;
+       }
+       /**
+        * Returns an array with all the child nodes
+        *
+        * @return Sabre_DAV_INode[]
+        */
+       public function getChildren() {
+               $folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path);
+               $paths = array();
+               foreach($folder_content as $info) {
+                       $paths[] = $this->path.'/'.$info['name'];
+                       $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = '"' . $info['etag'] . '"';
+               }
+               if(count($paths)>0) {
+                       //
+                       // the number of arguments within IN conditions are limited in most databases
+                       // we chunk $paths into arrays of 200 items each to meet this criteria
+                       //
+                       $chunks = array_chunk($paths, 200, false);
+                       foreach ($chunks as $pack) {
+                               $placeholders = join(',', array_fill(0, count($pack), '?'));
+                               $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`'
+                                       .' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
+                               array_unshift($pack, OC_User::getUser()); // prepend userid
+                               $result = $query->execute( $pack );
+                               while($row = $result->fetchRow()) {
+                                       $propertypath = $row['propertypath'];
+                                       $propertyname = $row['propertyname'];
+                                       $propertyvalue = $row['propertyvalue'];
+                                       if($propertyname !== self::GETETAG_PROPERTYNAME) {
+                                               $properties[$propertypath][$propertyname] = $propertyvalue;
+                                       }
+                               }
+                       }
+               }
+               $nodes = array();
+               foreach($folder_content as $info) {
+                       $node = $this->getChild($info['name'], $info);
+                       $node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
+                       $nodes[] = $node;
+               }
+               return $nodes;
+       }
+       /**
+        * Checks if a child exists.
+        *
+        * @param string $name
+        * @return bool
+        */
+       public function childExists($name) {
+               $path = $this->path . '/' . $name;
+               return \OC\Files\Filesystem::file_exists($path);
+       }
+       /**
+        * Deletes all files in this directory, and then itself
+        *
+        * @return void
+        * @throws Sabre_DAV_Exception_Forbidden
+        */
+       public function delete() {
+               if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               if ($this->path != "/Shared") {
+                       \OC\Files\Filesystem::rmdir($this->path);
+               }
+       }
+       /**
+        * Returns available diskspace information
+        *
+        * @return array
+        */
+       public function getQuotaInfo() {
+               $storageInfo = OC_Helper::getStorageInfo($this->path);
+               return array(
+                       $storageInfo['used'],
+                       $storageInfo['free']
+               );
+       }
+       /**
+        * Returns a list of properties for this nodes.;
+        *
+        * The properties list is a list of propertynames the client requested,
+        * encoded as xmlnamespace#tagName, for example:
+        * http://www.example.org/namespace#author
+        * If the array is empty, all properties should be returned
+        *
+        * @param array $properties
 -                      $props[self::GETETAG_PROPERTYNAME]
 -                              = OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
++       * @return array
+        */
+       public function getProperties($properties) {
+               $props = parent::getProperties($properties);
+               if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
++                      $props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path);
+               }
+               return $props;
+       }
+ }
index 0000000000000000000000000000000000000000,433b11485523f786851d20a9c8e9292f94379af3..8ffec371e3f4e94a2589fc300a3e88105129c7bb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,176 +1,192 @@@
 -       * After a succesful put operation, you may choose to return an ETag. The
+ <?php
+ /**
+  * ownCloud
+  *
+  * @author Jakob Sack
+  * @copyright 2011 Jakob Sack kde@jakobsack.de
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  * License as published by the Free Software Foundation; either
+  * version 3 of the License, or any later version.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public
+  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
+ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_DAV_IFile {
+       /**
+        * Updates the data
+        *
+        * The data argument is a readable stream resource.
+        *
 -
 -              if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
++       * After a successful put operation, you may choose to return an ETag. The
+        * etag must always be surrounded by double-quotes. These quotes must
+        * appear in the actual string you're returning.
+        *
+        * Clients may use the ETag from a PUT request to later on make sure that
+        * when they update the file, the contents haven't changed in the mean
+        * time.
+        *
+        * If you don't plan to store the file byte-by-byte, and you return a
+        * different object on a subsequent GET you are strongly recommended to not
+        * return an ETag, and just return null.
+        *
+        * @param resource $data
+        * @throws Sabre_DAV_Exception_Forbidden
+        * @return string|null
+        */
+       public function put($data) {
 -              
++              $fs = $this->getFS();
++              if ($fs->file_exists($this->path) &&
++                      !$fs->isUpdatable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               // throw an exception if encryption was disabled but the files are still encrypted
+               if (\OC_Util::encryptedFiles()) {
+                       throw new \Sabre_DAV_Exception_ServiceUnavailable();
+               }
 -              \OC\Files\Filesystem::file_put_contents($partpath, $data);
 -
 -              //detect aborted upload
 -              if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') {
 -                      if (isset($_SERVER['CONTENT_LENGTH'])) {
 -                              $expected = $_SERVER['CONTENT_LENGTH'];
 -                              $actual = \OC\Files\Filesystem::filesize($partpath);
 -                              if ($actual != $expected) {
 -                                      \OC\Files\Filesystem::unlink($partpath);
 -                                      throw new Sabre_DAV_Exception_BadRequest(
 -                                              'expected filesize ' . $expected . ' got ' . $actual);
 -                              }
++
++              // chunked handling
++              if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
++                      list(, $name) = \Sabre_DAV_URLUtil::splitPath($this->path);
++
++                      $info = OC_FileChunking::decodeName($name);
++                      if (empty($info)) {
++                              throw new Sabre_DAV_Exception_NotImplemented();
++                      }
++                      $chunk_handler = new OC_FileChunking($info);
++                      $chunk_handler->store($info['index'], $data);
++                      if ($chunk_handler->isComplete()) {
++                              $newPath = $this->path . '/' . $info['name'];
++                              $chunk_handler->file_assemble($newPath);
++                              return $this->getETagPropertyForPath($newPath);
++                      }
++
++                      return null;
++              }
++
+               // mark file as partial while uploading (ignored by the scanner)
+               $partpath = $this->path . '.part';
 -              $renameOkay = \OC\Files\Filesystem::rename($partpath, $this->path);
 -              $fileExists = \OC\Files\Filesystem::file_exists($this->path);
++              try {
++                      $putOkay = $fs->file_put_contents($partpath, $data);
++                      if ($putOkay === false) {
++                              \OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
++                              $fs->unlink($partpath);
++                              // because we have no clue about the cause we can only throw back a 500/Internal Server Error
++                              throw new Sabre_DAV_Exception();
+                       }
++              } catch (\OCP\Files\NotPermittedException $e) {
++                      throw new Sabre_DAV_Exception_Forbidden();
+               }
+               // rename to correct path
 -                      \OC\Files\Filesystem::unlink($partpath);
++              $renameOkay = $fs->rename($partpath, $this->path);
++              $fileExists = $fs->file_exists($this->path);
+               if ($renameOkay === false || $fileExists === false) {
+                       \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
 -
 -              //allow sync clients to send the mtime along in a header
++                      $fs->unlink($partpath);
+                       throw new Sabre_DAV_Exception();
+               }
 -                      if (\OC\Files\Filesystem::touch($this->path, $mtime)) {
++              // allow sync clients to send the mtime along in a header
+               $mtime = OC_Request::hasModificationTime();
+               if ($mtime !== false) {
 -              return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
++                      if($fs->touch($this->path, $mtime)) {
+                               header('X-OC-MTime: accepted');
+                       }
+               }
 -              //throw execption if encryption is disabled but files are still encrypted
++              return $this->getETagPropertyForPath($this->path);
+       }
+       /**
+        * Returns the data
+        *
+        * @return string
+        */
+       public function get() {
 -       * arbritrary string, but MUST be surrounded by double-quotes.
++              //throw exception if encryption is disabled but files are still encrypted
+               if (\OC_Util::encryptedFiles()) {
+                       throw new \Sabre_DAV_Exception_ServiceUnavailable();
+               } else {
+                       return \OC\Files\Filesystem::fopen($this->path, 'rb');
+               }
+       }
+       /**
+        * Delete the current file
+        *
+        * @return void
+        * @throws Sabre_DAV_Exception_Forbidden
+        */
+       public function delete() {
+               if (!\OC\Files\Filesystem::isDeletable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               \OC\Files\Filesystem::unlink($this->path);
+       }
+       /**
+        * Returns the size of the node, in bytes
+        *
+        * @return int
+        */
+       public function getSize() {
+               $this->getFileinfoCache();
+               if ($this->fileinfo_cache['size'] > -1) {
+                       return $this->fileinfo_cache['size'];
+               } else {
+                       return null;
+               }
+       }
+       /**
+        * Returns the ETag for a file
+        *
+        * An ETag is a unique identifier representing the current version of the
+        * file. If the file changes, the ETag MUST change.  The ETag is an
++       * arbitrary string, but MUST be surrounded by double-quotes.
+        *
+        * Return null if the ETag can not effectively be determined
+        *
+        * @return mixed
+        */
+       public function getETag() {
+               $properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
+               if (isset($properties[self::GETETAG_PROPERTYNAME])) {
+                       return $properties[self::GETETAG_PROPERTYNAME];
+               }
+               return null;
+       }
+       /**
+        * Returns the mime-type for a file
+        *
+        * If null is returned, we'll assume application/octet-stream
+        *
+        * @return mixed
+        */
+       public function getContentType() {
+               if (isset($this->fileinfo_cache['mimetype'])) {
+                       return $this->fileinfo_cache['mimetype'];
+               }
+               return \OC\Files\Filesystem::getMimeType($this->path);
+       }
+ }
index 0000000000000000000000000000000000000000,e65ad7b8bef6d643f5c17bacbd814260203b784f..fa27abb381ab48297b65dcaae36a33537afdad14
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,245 +1,258 @@@
 -      static public function getETagPropertyForPath($path) {
 -              $data = \OC\Files\Filesystem::getFileInfo($path);
+ <?php
+ /**
+  * ownCloud
+  *
+  * @author Jakob Sack
+  * @copyright 2011 Jakob Sack kde@jakobsack.de
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+  * License as published by the Free Software Foundation; either
+  * version 3 of the License, or any later version.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+  *
+  * You should have received a copy of the GNU Affero General Public
+  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
+ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties {
+       const GETETAG_PROPERTYNAME = '{DAV:}getetag';
+       const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
+       /**
+        * Allow configuring the method used to generate Etags
+        *
+        * @var array(class_name, function_name)
+       */
+       public static $ETagFunction = null;
++      /**
++       * is kept public to allow overwrite for unit testing
++       *
++       * @var \OC\Files\View
++       */
++      public $fileView;
++
+       /**
+        * The path to the current node
+        *
+        * @var string
+        */
+       protected $path;
+       /**
+        * node fileinfo cache
+        * @var array
+        */
+       protected $fileinfo_cache;
+       /**
+        * node properties cache
+        * @var array
+        */
+       protected $property_cache = null;
+       /**
+        * @brief Sets up the node, expects a full path name
+        * @param string $path
+        * @return void
+        */
+       public function __construct($path) {
+               $this->path = $path;
+       }
+       /**
+        * @brief  Returns the name of the node
+        * @return string
+        */
+       public function getName() {
+               list(, $name)  = Sabre_DAV_URLUtil::splitPath($this->path);
+               return $name;
+       }
+       /**
+        * @brief Renames the node
+        * @param string $name The new name
+        * @return void
+        */
+       public function setName($name) {
+               // rename is only allowed if the update privilege is granted
+               if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
+               list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
+               $newPath = $parentPath . '/' . $newName;
+               $oldPath = $this->path;
+               \OC\Files\Filesystem::rename($this->path, $newPath);
+               $this->path = $newPath;
+               $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?'
+                       .' WHERE `userid` = ? AND `propertypath` = ?' );
+               $query->execute( array( $newPath, OC_User::getUser(), $oldPath ));
+       }
+       public function setFileinfoCache($fileinfo_cache)
+       {
+               $this->fileinfo_cache = $fileinfo_cache;
+       }
+       /**
+        * @brief Ensure that the fileinfo cache is filled
+        * @note Uses OC_FileCache or a direct stat
+        */
+       protected function getFileinfoCache() {
+               if (!isset($this->fileinfo_cache)) {
+                       if ($fileinfo_cache = \OC\Files\Filesystem::getFileInfo($this->path)) {
+                       } else {
+                               $fileinfo_cache = \OC\Files\Filesystem::stat($this->path);
+                       }
+                       $this->fileinfo_cache = $fileinfo_cache;
+               }
+       }
+       public function setPropertyCache($property_cache)
+       {
+               $this->property_cache = $property_cache;
+       }
+       /**
+        * @brief Returns the last modification time, as a unix timestamp
+        * @return int
+        */
+       public function getLastModified() {
+               $this->getFileinfoCache();
+               return $this->fileinfo_cache['mtime'];
+       }
+       /**
+        *  sets the last modification time of the file (mtime) to the value given
+        *  in the second parameter or to now if the second param is empty.
+        *  Even if the modification time is set to a custom value the access time is set to now.
+        */
+       public function touch($mtime) {
+               // touch is only allowed if the update privilege is granted
+               if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
+                       throw new \Sabre_DAV_Exception_Forbidden();
+               }
+               \OC\Files\Filesystem::touch($this->path, $mtime);
+       }
+       /**
+        * @brief Updates properties on this node,
+        * @param array $mutations
+        * @see Sabre_DAV_IProperties::updateProperties
+        * @return bool|array
+        */
+       public function updateProperties($properties) {
+               $existing = $this->getProperties(array());
+               foreach($properties as $propertyName => $propertyValue) {
+                       // If it was null, we need to delete the property
+                       if (is_null($propertyValue)) {
+                               if(array_key_exists( $propertyName, $existing )) {
+                                       $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
+                                               .' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
+                                       $query->execute( array( OC_User::getUser(), $this->path, $propertyName ));
+                               }
+                       }
+                       else {
+                               if( strcmp( $propertyName, self::GETETAG_PROPERTYNAME) === 0 ) {
+                                       \OC\Files\Filesystem::putFileInfo($this->path, array('etag'=> $propertyValue));
+                               } elseif( strcmp( $propertyName, self::LASTMODIFIED_PROPERTYNAME) === 0 ) {
+                                       $this->touch($propertyValue);
+                               } else {
+                                       if(!array_key_exists( $propertyName, $existing )) {
+                                               $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties`'
+                                                       .' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
+                                               $query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue ));
+                                       } else {
+                                               $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?'
+                                                       .' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
+                                               $query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName ));
+                                       }
+                               }
+                       }
+               }
+               $this->setPropertyCache(null);
+               return true;
+       }
+       /**
+        * @brief Returns a list of properties for this nodes.;
+        * @param array $properties
+        * @return array
+        * @note The properties list is a list of propertynames the client
+        * requested, encoded as xmlnamespace#tagName, for example:
+        * http://www.example.org/namespace#author If the array is empty, all
+        * properties should be returned
+        */
+       public function getProperties($properties) {
+               if (is_null($this->property_cache)) {
+                       $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
+                       $result = OC_DB::executeAudited( $sql, array( OC_User::getUser(), $this->path ) );
+                       $this->property_cache = array();
+                       while( $row = $result->fetchRow()) {
+                               $this->property_cache[$row['propertyname']] = $row['propertyvalue'];
+                       }
+                       // Don't call the static getETagPropertyForPath, its result is not cached
+                       $this->getFileinfoCache();
+                       if ($this->fileinfo_cache['etag']) {
+                               $this->property_cache[self::GETETAG_PROPERTYNAME] = '"'.$this->fileinfo_cache['etag'].'"';
+                       } else {
+                               $this->property_cache[self::GETETAG_PROPERTYNAME] = null;
+                       }
+               }
+               // if the array was empty, we need to return everything
+               if(count($properties) == 0) {
+                       return $this->property_cache;
+               }
+               $props = array();
+               foreach($properties as $property) {
+                       if (isset($this->property_cache[$property])) $props[$property] = $this->property_cache[$property];
+               }
+               return $props;
+       }
+       /**
+        * Returns the ETag surrounded by double-quotes for this path.
+        * @param string $path Path of the file
+        * @return string|null Returns null if the ETag can not effectively be determined
+        */
++      protected function getETagPropertyForPath($path) {
++              $data = $this->getFS()->getFileInfo($path);
+               if (isset($data['etag'])) {
+                       return '"'.$data['etag'].'"';
+               }
+               return null;
+       }
++      protected function getFS() {
++              if (is_null($this->fileView)) {
++                      $this->fileView = \OC\Files\Filesystem::getView();
++              }
++              return $this->fileView;
++      }
+ }