]> source.dussan.org Git - nextcloud-server.git/commitdiff
Merge branch 'master' of gitorious.org:owncloud/owncloud
authorSam Tuke <samtuke@owncloud.com>
Tue, 3 Jul 2012 17:17:32 +0000 (18:17 +0100)
committerSam Tuke <samtuke@owncloud.com>
Tue, 3 Jul 2012 17:17:32 +0000 (18:17 +0100)
Conflicts:
apps/files_versions/lib/versions.php

1  2 
apps/files_versions/ajax/rollbackVersion.php
apps/files_versions/lib/versions.php

index 127592f3b58095bf55c48b95ae13562c1a049b0c,127592f3b58095bf55c48b95ae13562c1a049b0c..8d1092f8b8e217f03bf59f97ec3896d6cd90beb3
@@@ -2,8 -2,8 +2,6 @@@
  
  OCP\JSON::checkAppEnabled('files_versions');
  
--require_once('apps/files_versions/versions.php');
--
  $userDirectory = "/".OCP\USER::getUser()."/files";
  
  $file = $_GET['file'];
index af7ae11a25889e058b36c4f41046fdae4811ab75,0000000000000000000000000000000000000000..fb78e0a56c046854b226e44dcbd7d5d3ab350c89
mode 100644,000000..100644
--- /dev/null
@@@ -1,353 -1,0 +1,363 @@@
-                       if(is_dir($filesfoldername.'/'.$filename)){\r
 +<?php\r
 +/**\r
 + * Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>\r
 + * This file is licensed under the Affero General Public License version 3 or\r
 + * later.\r
 + * See the COPYING-README file.\r
 + */\r
 +\r
 +/**\r
 + * Versions\r
 + *\r
 + * A class to handle the versioning of files.\r
 + */\r
 +\r
 +namespace OCA_Versions;\r
 +\r
 +class Storage {\r
 +\r
 +\r
 +      // config.php configuration:\r
 +      //   - files_versions\r
 +      //   - files_versionsfolder\r
 +      //   - files_versionsblacklist\r
 +      //   - files_versionsmaxfilesize\r
 +      //   - files_versionsinterval \r
 +      //   - files_versionmaxversions \r
 +      //\r
 +      // todo:\r
 +      //   - finish porting to OC_FilesystemView to enable network transparency\r
 +      //   - add transparent compression. first test if it´s worth it.\r
 +\r
 +      const DEFAULTENABLED=true; \r
 +      const DEFAULTFOLDER='versions'; \r
 +      const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp'; \r
 +      const DEFAULTMAXFILESIZE=1048576; // 10MB \r
 +      const DEFAULTMININTERVAL=1; // 2 min\r
 +      const DEFAULTMAXVERSIONS=50;\r
 +      \r
 +      private $view;\r
 +      \r
 +      function __construct( $view ) {\r
 +      \r
 +              $this->view = $view;\r
 +              \r
 +      }\r
 +\r
 +      /**\r
 +       * init the versioning and create the versions folder.\r
 +       */\r
 +      public static function init() {\r
 +              if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
 +                      // create versions folder\r
 +                      $foldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +                      if(!is_dir($foldername)){\r
 +                              mkdir($foldername);\r
 +                      }\r
 +              }\r
 +      }\r
 +\r
 +\r
 +      /**\r
 +       * listen to write event.\r
 +       */\r
 +      public static function write_hook($params) {\r
 +              if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
 +                      $path = $params[\OC_Filesystem::signal_param_path];\r
 +                      if($path<>'') $this->store($path);\r
 +              }\r
 +      }\r
 +\r
 +\r
 +\r
 +      /**\r
 +       * store a new version of a file.\r
 +       */\r
 +      public function store($filename) {\r
 +              if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
++              \r
++                      $files_view = \OCP\Files::getStorage("files");\r
++                      $users_view = \OCP\Files::getStorage("files_versions");\r
++                      $users_view->chroot(\OCP\User::getUser().'/');\r
++                      \r
 +                      if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {\r
 +                              $pos = strpos($source, '/files', 1);\r
 +                              $uid = substr($source, 1, $pos - 1);\r
 +                              $filename = substr($source, $pos + 6);\r
 +                      } else {\r
 +                              $uid = \OCP\User::getUser();\r
 +                      }\r
 +                      $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +                      $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';\r
 +                      Storage::init();\r
 +\r
++                      //check if source file already exist as version to avoid recursions.\r
++                      if ($users_view->file_exists($filename)) {\r
++                              return false;\r
++                      }\r
++                      \r
 +                      // check if filename is a directory\r
-                       if(filesize($filesfoldername.'/'.$filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)){\r
++                      if($files_view->is_dir($filename)){\r
 +                              return false;\r
 +                      }\r
 +\r
 +                      // check filetype blacklist\r
 +                      $blacklist=explode(' ',\OCP\Config::getSystemValue('files_versionsblacklist', Storage::DEFAULTBLACKLIST));\r
 +                      foreach($blacklist as $bl) {\r
 +                              $parts=explode('.', $filename);\r
 +                              $ext=end($parts);\r
 +                              if(strtolower($ext)==$bl) {\r
 +                                      return false;\r
 +                              }\r
 +                      }\r
 +                      \r
 +                      // check filesize\r
-                       copy($filesfoldername.'/'.$filename,$versionsFolderName.'/'.$filename.'.v'.time());\r
++                      if($files_view->filesize($filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)){\r
 +                              return false;\r
 +                      }\r
 +\r
 +\r
 +                      // check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval)\r
 +                      if ($uid == \OCP\User::getUser()) {\r
 +                              $matches=glob($versionsFolderName.'/'.$filename.'.v*');\r
 +                              sort($matches);\r
 +                              $parts=explode('.v',end($matches));\r
 +                              if((end($parts)+Storage::DEFAULTMININTERVAL)>time()){\r
 +                                      return false;\r
 +                              }\r
 +                      }\r
 +\r
 +\r
 +                      // create all parent folders\r
 +                      $info=pathinfo($filename);      \r
 +                      if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true);   \r
 +\r
 +                      // store a new version of a file\r
-                       $this->expire($filename);\r
++                      @$users_view->copy('files'.$filename, 'versions'.$filename.'.v'.time());\r
 +        \r
 +                      // expire old revisions if necessary\r
-       public function rollback( $filename, $revision ) {\r
++                      Storage::expire($filename);\r
 +              }\r
 +      }\r
 +\r
 +\r
 +      /**\r
 +       * rollback to an old version of a file.\r
 +       */\r
-                       if ( copy( $versionsFolderName.'/'.$filename.'.v'.$revision, $filesfoldername.'/'.$filename ) ) {\r
++      public static function rollback($filename,$revision) {\r
 +      \r
 +              if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
 +                      if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {\r
 +                              $pos = strpos($source, '/files', 1);\r
 +                              $uid = substr($source, 1, $pos - 1);\r
 +                              $filename = substr($source, $pos + 6);\r
 +                      } else {\r
 +                              $uid = \OCP\User::getUser();\r
 +                      }\r
 +                      $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'.$uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +                      \r
 +                      $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files';\r
 +                      \r
 +                      // rollback\r
-                       } else {\r
++                      if ( @copy($versionsFolderName.'/'.$filename.'.v'.$revision,$filesfoldername.'/'.$filename) ) {\r
 +                      \r
 +                              return true;\r
 +                              \r
-         public function expire( $filename ) {\r
++                      }else{\r
 +                      \r
 +                              return false;\r
 +                              \r
 +                      }\r
 +                      \r
 +              }\r
 +              \r
 +      }\r
 +\r
 +      /**\r
 +       * check if old versions of a file exist.\r
 +       */\r
 +      public static function isversioned($filename) {\r
 +              if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
 +                      if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {\r
 +                              $pos = strpos($source, '/files', 1);\r
 +                              $uid = substr($source, 1, $pos - 1);\r
 +                              $filename = substr($source, $pos + 6);\r
 +                      } else {\r
 +                              $uid = \OCP\User::getUser();\r
 +                      }\r
 +                      $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +\r
 +                      // check for old versions\r
 +                      $matches=glob($versionsFolderName.'/'.$filename.'.v*');\r
 +                      if(count($matches)>1){\r
 +                              return true;\r
 +                      }else{\r
 +                              return false;\r
 +                      }\r
 +              }else{\r
 +                      return(false);\r
 +              }\r
 +      }\r
 +\r
 +\r
 +        \r
 +        /**\r
 +         * @brief get a list of all available versions of a file in descending chronological order\r
 +         * @param $filename file to find versions of, relative to the user files dir\r
 +         * @param $count number of versions to return\r
 +         * @returns array\r
 +         */\r
 +        public static function getVersions( $filename, $count = 0 ) {\r
 +        \r
 +                if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {\r
 +                \r
 +                      if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {\r
 +                              $pos = strpos($source, '/files', 1);\r
 +                              $uid = substr($source, 1, $pos - 1);\r
 +                              $filename = substr($source, $pos + 6);\r
 +                      } else {\r
 +                              $uid = \OCP\User::getUser();\r
 +                      }\r
 +                      $versionsFolderName = \OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +                      $versions = array();         \r
 +                      \r
 +                      // fetch for old versions\r
 +                      $matches = glob( $versionsFolderName.'/'.$filename.'.v*' );\r
 +                      \r
 +                      sort( $matches );\r
 +                      \r
 +                      $i = 0;\r
 +                      \r
 +                      foreach( $matches as $ma ) {\r
 +                              \r
 +                              $i++;\r
 +                              $versions[$i]['cur'] = 0;\r
 +                              $parts = explode( '.v', $ma );\r
 +                              $versions[$i]['version'] = ( end( $parts ) );\r
 +                              \r
 +                              // if file with modified date exists, flag it in array as currently enabled version\r
 +                              $curFile['fileName'] = basename( $parts[0] );\r
 +                              $curFile['filePath'] = \OCP\Config::getSystemValue('datadirectory').\OC_Filesystem::getRoot().'/'.$curFile['fileName'];\r
 +                              \r
 +                              ( \md5_file( $ma ) == \md5_file( $curFile['filePath'] ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );\r
 +                              \r
 +                      }\r
 +                      \r
 +                      $versions = array_reverse( $versions );\r
 +                      \r
 +                      foreach( $versions as $key => $value ) {\r
 +                              \r
 +                              // flag the first matched file in array (which will have latest modification date) as current version\r
 +                              if ( $versions[$key]['fileMatch'] ) {\r
 +                              \r
 +                                      $versions[$key]['cur'] = 1;\r
 +                                      break;\r
 +                                      \r
 +                              }\r
 +                      \r
 +                      }\r
 +                      \r
 +                      $versions = array_reverse( $versions );\r
 +                      \r
 +                      // only show the newest commits\r
 +                      if( $count != 0 and ( count( $versions )>$count ) ) {\r
 +                      \r
 +                              $versions = array_slice( $versions, count( $versions ) - $count );\r
 +                              \r
 +                      }\r
 +      \r
 +                      return( $versions );\r
 +\r
 +\r
 +                } else {\r
 +                \r
 +                      // if versioning isn't enabled then return an empty array\r
 +                        return( array() );\r
 +                        \r
 +                }\r
 +                \r
 +        }\r
 +\r
 +        /**\r
 +         * @brief Erase a file's versions which exceed the set quota\r
 +         */\r
-                                       $this->view->unlink( $versionsFolderName.'/'.$filename.'.v'.$de );\r
++        public static function expire($filename) {\r
 +                if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {\r
 +\r
 +                      if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) {\r
 +                              $pos = strpos($source, '/files', 1);\r
 +                              $uid = substr($source, 1, $pos - 1);\r
 +                              $filename = substr($source, $pos + 6);\r
 +                      } else {\r
 +                              $uid = \OCP\User::getUser();\r
 +                      }\r
 +                      $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +\r
 +                      // check for old versions\r
 +                      $matches = glob( $versionsFolderName.'/'.$filename.'.v*' );\r
 +                      \r
 +                      if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) {\r
 +                      \r
 +                              $numberToDelete = count( $matches-\OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) );\r
 +\r
 +                              // delete old versions of a file\r
 +                              $deleteItems = array_slice( $matches, 0, $numberToDelete );\r
 +                              \r
 +                              foreach( $deleteItems as $de ) {\r
 +                              \r
-                               $this->view->unlink( $abs_path . $v['version'] );\r
++                                      unlink( $versionsFolderName.'/'.$filename.'.v'.$de );\r
 +                                      \r
 +                              }\r
 +                      }\r
 +                }\r
 +        }\r
 +\r
 +        /**\r
 +         * @brief Erase all old versions of all user files\r
 +         * @return true/false\r
 +         */\r
 +        public function expireAll() {\r
 +              \r
 +              $dir = \OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER);\r
 +              \r
 +              return $this->view->deleteAll( $dir, true );\r
 +      \r
 +        }\r
 +\r
 +        /**\r
 +         * @brief Erase versions of deleted file\r
 +         * @param array\r
 +         *          \r
 +         * This function is connected to the delete signal of OC_Filesystem\r
 +         * cleanup the versions directory if the actual file gets deleted\r
 +         */\r
 +        public static function removeVersions($params) {\r
 +              $rel_path =  $params['path'];\r
 +              $abs_path = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_path.'.v';\r
 +              if(Storage::isversioned($rel_path)) {\r
 +                      $versions = Storage::getVersions($rel_path);\r
 +                      foreach ($versions as $v){\r
++                              unlink($abs_path . $v['version']);\r
 +                      }\r
 +              }\r
 +        }\r
 +        \r
 +        /**\r
 +         * @brief rename/move versions of renamed/moved files\r
 +         * @param array with oldpath and newpath\r
 +         * \r
 +         * This function is connected to the rename signal of OC_Filesystem and adjust the name and location\r
 +         * of the stored versions along the actual file\r
 +         */\r
 +        public static function renameVersions($params) {\r
 +              $rel_oldpath =  $params['oldpath'];\r
 +              $abs_oldpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_oldpath.'.v';\r
 +              $abs_newpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$params['newpath'].'.v';\r
 +              if(Storage::isversioned($rel_oldpath)) {\r
 +                      $versions = Storage::getVersions($rel_oldpath);\r
 +                      foreach ($versions as $v){\r
 +                              rename($abs_oldpath.$v['version'], $abs_newpath.$v['version']);\r
 +                      }\r
 +              }\r
 +        }\r
 +}\r