diff options
28 files changed, 1061 insertions, 876 deletions
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 8d589ea5e2e..8049e9b0ae3 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -6,7 +6,6 @@ OC::$CLASSPATH['OC_Share'] = "apps/files_sharing/lib_share.php"; OC_Hook::connect("OC_Filesystem", "post_delete", "OC_Share", "deleteItem"); OC_Hook::connect("OC_Filesystem", "post_rename", "OC_Share", "renameItem"); OC_Hook::connect("OC_Filesystem", "post_write", "OC_Share", "updateItem"); -OC_Filesystem::registerStorageType("shared", "OC_Filestorage_Shared", array("datadir" => "string")); OC_Util::addScript("files_sharing", "share"); OC_Util::addScript("3rdparty", "chosen/chosen.jquery.min"); OC_Util::addStyle( 'files_sharing', 'sharing' ); diff --git a/apps/files_sharing/lib_share.php b/apps/files_sharing/lib_share.php index 0eb0e5bf85d..049a74278b3 100644 --- a/apps/files_sharing/lib_share.php +++ b/apps/files_sharing/lib_share.php @@ -89,8 +89,8 @@ class OC_Share { } $query->execute(array($uid_owner, $uid, $source, $target, $permissions)); // Clear the folder size cache for the 'Shared' folder - $clearFolderSize = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?"); - $clearFolderSize->execute(array($sharedFolder)); +// $clearFolderSize = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?"); +// $clearFolderSize->execute(array($sharedFolder)); // Emit post_create and post_write hooks to notify of a new file in the user's filesystem OC_Hook::emit("OC_Filesystem", "post_create", array('path' => $target)); OC_Hook::emit("OC_Filesystem", "post_write", array('path' => $target)); diff --git a/apps/files_sharing/sharedstorage.php b/apps/files_sharing/sharedstorage.php index b0eaeecf723..529a82b830a 100644 --- a/apps/files_sharing/sharedstorage.php +++ b/apps/files_sharing/sharedstorage.php @@ -25,7 +25,7 @@ require_once( 'lib_share.php' ); if (!OC_Filesystem::is_dir('/Shared')) { OC_Filesystem::mkdir('/Shared'); } -OC_Filesystem::mount('shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared'),'/'.OC_User::getUser().'/files/Shared/'); +OC_Filesystem::mount('OC_Filestorage_Shared',array('datadir'=>'/'.OC_User::getUser().'/files/Shared'),'/'.OC_User::getUser().'/files/Shared/'); /** * Convert target path to source path and pass the function call to the correct storage provider @@ -168,19 +168,9 @@ class OC_Filestorage_Shared extends OC_Filestorage { // TODO fill in other components of array public function stat($path) { if ($path == "" || $path == "/") { - $stat["dev"] = ""; - $stat["ino"] = ""; - $stat["mode"] = ""; - $stat["nlink"] = ""; - $stat["uid"] = ""; - $stat["gid"] = ""; - $stat["rdev"] = ""; $stat["size"] = $this->filesize($path); - $stat["atime"] = $this->fileatime($path); $stat["mtime"] = $this->filemtime($path); $stat["ctime"] = $this->filectime($path); - $stat["blksize"] = ""; - $stat["blocks"] = ""; return $stat; } else { $source = $this->getSource($path); @@ -217,18 +207,7 @@ class OC_Filestorage_Shared extends OC_Filestorage { } public function getFolderSize($path) { - // Shared folder sizes are cached separately from the source folder sizes because folders can have different names - $path = rtrim($path, "/"); - $path = ltrim($path, "/"); - $path = preg_replace('{(/)\1+}', "/", $path); - $dbpath = rtrim($this->datadir.$path, "/"); - $query = OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path = ?"); - $size = $query->execute(array($dbpath))->fetchAll(); - if (count($size) > 0) { - return $size[0]['size']; - } else { - return $this->calculateFolderSize($path); - } + return 0; //depricated } private function calculateFolderSize($path) { @@ -249,8 +228,8 @@ class OC_Filestorage_Shared extends OC_Filestorage { } if ($size > 0) { $dbpath = rtrim($this->datadir.$path, "/"); - $query = OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)"); - $result = $query->execute(array($dbpath, $size)); +// $query = OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)"); +// $result = $query->execute(array($dbpath, $size)); } } return $size; @@ -263,8 +242,8 @@ class OC_Filestorage_Shared extends OC_Filestorage { $path = dirname($path); } $dbpath = rtrim($this->datadir.$path, "/"); - $query = OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?"); - $result = $query->execute(array($dbpath)); +// $query = OC_DB::prepare("DELETE FROM *PREFIX*/*foldersize*/ WHERE path = ?"); +// $result = $query->execute(array($dbpath)); if ($path != "/" && $path != "") { $parts = explode("/", $path); $part = array_pop($parts); @@ -320,8 +299,8 @@ class OC_Filestorage_Shared extends OC_Filestorage { $ctime = $tempctime; } } - return $ctime; } + return $ctime; } else { $source = $this->getSource($path); if ($source) { @@ -341,8 +320,8 @@ class OC_Filestorage_Shared extends OC_Filestorage { $mtime = $tempmtime; } } - return $mtime; } + return $mtime; } else { $source = $this->getSource($path); if ($source) { @@ -352,27 +331,6 @@ class OC_Filestorage_Shared extends OC_Filestorage { } } - public function fileatime($path) { - if ($path == "" || $path == "/") { - $atime = 0; - if ($dh = $this->opendir($path)) { - while (($filename = readdir($dh)) !== false) { - $tempatime = $this->fileatime($filename); - if ($tempatime > $atime) { - $atime = $tempatime; - } - } - return $atime; - } - } else { - $source = $this->getSource($path); - if ($source) { - $storage = OC_Filesystem::getStorage($source); - return $storage->fileatime($this->getInternalPath($source)); - } - } - } - public function file_get_contents($path) { $source = $this->getSource($path); if ($source) { @@ -501,23 +459,10 @@ class OC_Filestorage_Shared extends OC_Filestorage { } } - public function fromUploadedFile($tmpFile, $path) { - if ($this->is_writeable($path)) { - $source = $this->getSource($path); - if ($source) { - $storage = OC_Filesystem::getStorage($source); - $result = $storage->fromUploadedFile($tmpFile, $this->getInternalPath($source)); - if ($result) { - $this->clearFolderSizeCache($path); - } - return $result; - } - } else { - return false; - } - } - public function getMimeType($path) { + if ($path2 == "" || $path2 == "/") { + return 'httpd/unix-directory'; + } $source = $this->getSource($path); if ($source) { $storage = OC_Filesystem::getStorage($source); diff --git a/apps/files_texteditor/ajax/savefile.php b/apps/files_texteditor/ajax/savefile.php index 3d0771ea983..846159c13b7 100644 --- a/apps/files_texteditor/ajax/savefile.php +++ b/apps/files_texteditor/ajax/savefile.php @@ -32,7 +32,6 @@ $filecontents = htmlspecialchars_decode($_POST['filecontents']); $path = isset($_POST['path']) ? $_POST['path'] : ''; $mtime = isset($_POST['mtime']) ? $_POST['mtime'] : ''; - if($path != '' && $mtime != '') { // Get file mtime diff --git a/db_structure.xml b/db_structure.xml index ddb8c44d19d..13d5732a8d5 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -43,11 +43,20 @@ <table> - <name>*dbprefix*foldersize</name> + <name>*dbprefix*fscache</name> <declaration> <field> + <name>id</name> + <autoincrement>1</autoincrement> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <length>4</length> + </field> + + <field> <name>path</name> <type>text</type> <default></default> @@ -56,6 +65,24 @@ </field> <field> + <name>parent</name> + <type>integer</type> + <default> + </default> + <notnull>true</notnull> + <length>4</length> + </field> + + <field> + <name>name</name> + <type>text</type> + <default> + </default> + <notnull>true</notnull> + <length>512</length> + </field> + + <field> <name>size</name> <type>integer</type> <default></default> @@ -63,12 +90,85 @@ <length>4</length> </field> - <index> - <name>path_index</name> + <field> + <name>ctime</name> + <type>integer</type> + <default> + </default> + <notnull>true</notnull> + <length>4</length> + </field> + + <field> + <name>mtime</name> + <type>integer</type> + <default> + </default> + <notnull>true</notnull> + <length>4</length> + </field> + + <field> + <name>mimetype</name> + <type>text</type> + <default> + </default> + <notnull>true</notnull> + <length>32</length> + </field> + + <field> + <name>mimepart</name> + <type>text</type> + <default> + </default> + <notnull>true</notnull> + <length>32</length> + </field> + + <field> + <name>encrypted</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <length>1</length> + </field> + + <field> + <name>versioned</name> + <type>integer</type> + <default>0</default> + <notnull>true</notnull> + <length>1</length> + </field> + +<!-- <index> + <name>fscache_path_index</name> + <unique>true</unique> <field> <name>path</name> <sorting>ascending</sorting> </field> + </index>--> + + <index> + <name>parent_index</name> + <field> + <name>parent</name> + <sorting>ascending</sorting> + </field> + </index> + + <index> + <name>parent_name_index</name> + <field> + <name>parent</name> + <sorting>ascending</sorting> + </field> + <field> + <name>name</name> + <sorting>ascending</sorting> + </field> </index> </declaration> diff --git a/files/ajax/scan.php b/files/ajax/scan.php new file mode 100644 index 00000000000..dec949a819b --- /dev/null +++ b/files/ajax/scan.php @@ -0,0 +1,16 @@ +<?php + +require_once '../../lib/base.php'; + +$force=isset($_GET['force']) and $_GET['force']=='true'; +$checkOnly=isset($_GET['checkonly']) and $_GET['checkonly']=='true'; + +//create the file cache if necesary +if($force or !OC_FileCache::inCache('')){ + if(!$checkOnly){ + OC_FileCache::scan(''); + } + OC_JSON::success(array("data" => array( "done" => true))); +}else{ + OC_JSON::success(array("data" => array( "done" => false))); +}
\ No newline at end of file diff --git a/files/ajax/upload.php b/files/ajax/upload.php index 5f0f68d9531..241edc216ff 100644 --- a/files/ajax/upload.php +++ b/files/ajax/upload.php @@ -47,7 +47,7 @@ if(strpos($dir,'..') === false){ $fileCount=count($files['name']); for($i=0;$i<$fileCount;$i++){ $target=stripslashes($dir) . $files['name'][$i]; - if(OC_Filesystem::fromUploadedFile($files['tmp_name'][$i],$target)){ + if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i],$target)){ $result[]=array( "status" => "success", 'mime'=>OC_Filesystem::getMimeType($target),'size'=>OC_Filesystem::filesize($target),'name'=>$files['name'][$i]); } } diff --git a/files/css/files.css b/files/css/files.css index 6c4d603b4a6..5238c6a7f7b 100644 --- a/files/css/files.css +++ b/files/css/files.css @@ -75,4 +75,6 @@ a.action>img{ max-height:16px; max-width:16px; } /* add breadcrumb divider to the File item in navigation panel */ #navigation>ul>li:first-child { background:url('../../core/img/breadcrumb-start.svg') no-repeat 12.5em 0px; width:12.5em; padding-right:1em; position:fixed; } -#navigation>ul>li:first-child+li { padding-top:2.9em; }
\ No newline at end of file +#navigation>ul>li:first-child+li { padding-top:2.9em; } + +#scanning-message{ top:40%; left:40%; position:absolute; display:none } diff --git a/files/js/files.js b/files/js/files.js index 7c04245c223..649f193aa2d 100644 --- a/files/js/files.js +++ b/files/js/files.js @@ -336,8 +336,27 @@ $(document).ready(function() { $('#new>a').click(); }); }); + + //check if we need to scan the filesystem + $.get(OC.filePath('files','ajax','scan.php'),{checkonly:'true'}, function(response) { + if(response.data.done){ + scanFiles(); + } + }, "json"); }); +function scanFiles(force){ + force=!!force; //cast to bool + $('#scanning-message').show(); + $.get(OC.filePath('files','ajax','scan.php'),{force:force}, function(response) { + if(response && response.data && response.data.done){ + window.location.reload(); + }else{ + alert('error') + } + }, "json"); +} + function boolOperationFinished(data, callback) { result = jQuery.parseJSON(data.responseText); if(result.status == 'success'){ diff --git a/files/templates/index.php b/files/templates/index.php index 9ebfa41cef2..92c579c2442 100644 --- a/files/templates/index.php +++ b/files/templates/index.php @@ -60,3 +60,8 @@ <?php echo $l->t('The files you are trying to upload exceed the maximum size for file uploads on this server.');?> </p> </div> +<div id="scanning-message"> + <p> + <?php echo $l->t('Files are being scanned, please wait.');?> + </p> +</div> diff --git a/files/templates/part.list.php b/files/templates/part.list.php index a364862119d..92b6f37d8e7 100644 --- a/files/templates/part.list.php +++ b/files/templates/part.list.php @@ -10,8 +10,8 @@ $name = str_replace('%2F','/', $name); $directory = str_replace('+','%20',urlencode($file['directory'])); $directory = str_replace('%2F','/', $directory); ?> - <tr data-file="<?php echo $name;?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mime']?>" data-size='<?php echo $file['size'];?>' data-write='<?php echo $write;?>'> - <td class="filename svg" style="background-image:url(<?php if($file['type'] == 'dir') echo mimetype_icon('dir'); else echo mimetype_icon($file['mime']); ?>)"> + <tr data-file="<?php echo $name;?>" data-type="<?php echo ($file['type'] == 'dir')?'dir':'file'?>" data-mime="<?php echo $file['mimetype']?>" data-size='<?php echo $file['size'];?>' data-write='<?php echo $write;?>'> + <td class="filename svg" style="background-image:url(<?php if($file['type'] == 'dir') echo mimetype_icon('dir'); else echo mimetype_icon($file['mimetype']); ?>)"> <?php if(!isset($_['readonly']) || !$_['readonly']) { ?><input type="checkbox" /><?php } ?> <a class="name" href="<?php if($file['type'] == 'dir') echo $_['baseURL'].$directory.'/'.$name; else echo $_['downloadURL'].$directory.'/'.$name; ?>" title=""> <span class="nametext"> diff --git a/lib/base.php b/lib/base.php index 4da17c70a57..5b8eeb746b1 100644 --- a/lib/base.php +++ b/lib/base.php @@ -216,9 +216,6 @@ class OC{ OC_User::useBackend( OC_Config::getValue( "userbackend", "database" )); OC_Group::setBackend( OC_Config::getValue( "groupbackend", "database" )); - // Was in required file ... put it here - OC_Filesystem::registerStorageType('local','OC_Filestorage_Local',array('datadir'=>'string')); - // Set up file system unless forbidden global $RUNTIME_NOSETUPFS; if(!$RUNTIME_NOSETUPFS ){ diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 139c6b784b1..bb03851e39d 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -116,11 +116,11 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * @return array */ public function getQuotaInfo() { - + $rootInfo=OC_FileCache::get(''); return array( - OC_Filesystem::filesize('/'), + $rootInfo['size'], OC_Filesystem::free_space() - ); + ); } diff --git a/lib/filecache.php b/lib/filecache.php new file mode 100644 index 00000000000..928fc02e669 --- /dev/null +++ b/lib/filecache.php @@ -0,0 +1,353 @@ +<?php + +/** +* @author Robin Appelman +* @copyright 2011 Robin Appelman icewind1991@gmail.com +* +* 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/>. +* +*/ + +/** + * provide caching for filesystem info in the database + * + * not used by OC_Filesystem for reading filesystem info, + * instread apps should use OC_FileCache::get where possible + * + * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache + */ +class OC_FileCache{ + /** + * get the filesystem info from the cache + * @param string path + * @return array + * + * returns an assiciative array with the following keys: + * - size + * - mtime + * - ctime + * - mimetype + * - encrypted + * - versioned + */ + public static function get($path){ + $path=OC_Filesystem::getRoot().$path; + $query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned FROM *PREFIX*fscache WHERE path=?'); + $result=$query->execute(array($path))->fetchRow(); + if(is_array($result)){ + return $result; + }else{ + OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG); + return false; + } + } + + /** + * put filesystem info in the cache + * @param string $path + * @param array data + * + * $data is an assiciative array in the same format as returned by get + */ + public static function put($path,$data){ + $path=OC_Filesystem::getRoot().$path; + if($path=='/'){ + $parent=-1; + }else{ + $parent=self::getFileId(dirname($path)); + } + $id=self::getFileId($path); + if($id!=-1){ + self::update($id,$data); + return; + } + if(!isset($data['encrypted'])){ + $data['encrypted']=false; + } + if(!isset($data['versioned'])){ + $data['versioned']=false; + } + $mimePart=dirname($data['mimetype']); + $query=OC_DB::prepare('INSERT INTO *PREFIX*fscache(parent, name, path, size, mtime, ctime, mimetype, mimepart) VALUES(?,?,?,?,?,?,?,?)'); + $query->execute(array($parent,basename($path),$path,$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart)); + + } + + /** + * update filesystem info of a file + * @param int $id + * @param array $data + */ + private static function update($id,$data){ + $arguments=array(); + $queryParts=array(); + foreach(array('size','mtime','ctime','mimetype','encrypted','versioned') as $attribute){ + if(isset($data[$attribute])){ + $arguments[]=$data[$attribute]; + $queryParts[]=$attribute.'=?'; + } + } + if(isset($data['mimetype'])){ + $arguments[]=dirname($data['mimetype']); + $queryParts[]='mimepart=?'; + } + $arguments[]=$id; + $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET '.implode(' , ',$queryParts).' WHERE id=?'); + $query->execute($arguments); + } + + /** + * register a file move in the cache + * @param string oldPath + * @param string newPath + */ + public static function move($oldPath,$newPath){ + $oldPath=OC_Filesystem::getRoot().$oldPath; + $newPath=OC_Filesystem::getRoot().$newPath; + $newParent=self::getParentId($newPath); + $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET parent=? ,name=?, path=? WHERE path=?'); + $query->execute(array($newParent,basename($newPath),$newPath,$oldPath)); + } + + /** + * delete info from the cache + * @param string $path + */ + public static function delete($path){ + $path=OC_Filesystem::getRoot().$path; + $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path=?'); + $query->execute(array($path)); + } + + /** + * return array of filenames matching the querty + * @param string $query + * @return array of filepaths + */ + public static function search($search){ + $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ?'); + $result=$query->execute(array("%$search%")); + $names=array(); + while($row=$result->fetchRow()){ + $names[]=$row['path']; + } + return $names; + } + + /** + * get all files and folders in a folder + * @param string path + * @return array + * + * returns an array of assiciative arrays with the following keys: + * - name + * - size + * - mtime + * - ctime + * - mimetype + * - encrypted + * - versioned + */ + public static function getFolderContent($path){ + $path=OC_Filesystem::getRoot().$path; + $parent=self::getFileId($path); + $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned FROM *PREFIX*fscache WHERE parent=?'); + $result=$query->execute(array($parent))->fetchAll(); + if(is_array($result)){ + return $result; + }else{ + OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG); + return false; + } + } + + /** + * check if a file or folder is in the cache + * @param string $path + * @return bool + */ + public static function inCache($path){ + $path=OC_Filesystem::getRoot().$path; + $inCache=self::getFileId($path)!=-1; + return $inCache; + } + + /** + * get the file id as used in the cache + * @param string $path + * @return int + */ + private static function getFileId($path){ + $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path=?'); + $result=$query->execute(array($path))->fetchRow(); + if(is_array($result)){ + return $result['id']; + }else{ + OC_Log::write('file not found in cache ('.$path.')','core',OC_Log::DEBUG); + return -1; + } + } + + /** + * get the file id of the parent folder, taking into account '/' has no parent + * @param string $path + * @return int + */ + private static function getParentId($path){ + if($path=='/'){ + return -1; + }else{ + return self::getFileId(dirname($path)); + } + } + + /** + * called when changes are made to files + */ + public static function fileSystemWatcherWrite($params){ + $path=$params['path']; + $fullPath=OC_Filesystem::getRoot().$path; + $mimetype=OC_Filesystem::getMimeType($path); + if($mimetype=='httpd/unix-directory'){ + $size=0; + }else{ + $id=self::getFileId($fullPath); + if($id!=-1){ + $oldInfo=self::get($path); + $oldSize=$oldInfo['size']; + }else{ + $oldSize=0; + } + $size=OC_Filesystem::filesize($path); + self::increaseSize(dirname($fullPath),$size-$oldSize); + } + $mtime=OC_Filesystem::filemtime($path); + $ctime=OC_Filesystem::filectime($path); + self::put($path,array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype)); + } + + /** + * called when files are deleted + */ + public static function fileSystemWatcherDelete($params){ + $path=$params['path']; + $fullPath=OC_Filesystem::getRoot().$path; + if(self::getFileId($fullPath)==-1){ + return; + } + $size=OC_Filesystem::filesize($path); + self::increaseSize(dirname($fullPath),-$size); + self::delete($path); + } + + /** + * called when files are deleted + */ + public static function fileSystemWatcherRename($params){ + $oldPath=$params['oldpath']; + $newPath=$params['newpath']; + $fullOldPath=OC_Filesystem::getRoot().$oldPath; + $fullNewPath=OC_Filesystem::getRoot().$newPath; + if(($id=self::getFileId($fullOldPath))!=-1){ + $oldInfo=self::get($fullOldPath); + $oldSize=$oldInfo['size']; + }else{ + return; + } + $size=OC_Filesystem::filesize($oldPath); + self::increaseSize(dirname($fullOldPath),-$oldSize); + self::increaseSize(dirname($fullNewPath),$oldSize); + self::move($oldPath,$newPath); + } + + /** + * adjust the size of the parent folders + * @param string $path + * @param int $sizeDiff + */ + private static function increaseSize($path,$sizeDiff){ + while(($id=self::getFileId($path))!=-1){ + $query=OC_DB::prepare('UPDATE *PREFIX*fscache SET size=size+? WHERE id=?'); + $query->execute(array($sizeDiff,$id)); + $path=dirname($path); + } + } + + /** + * recursively scan the filesystem and fill the cache + * @param string $path + * @param bool $onlyChilds + */ + public static function scan($path,$onlyChilds=false){//PROBLEM due to the order things are added, all parents are -1 + $dh=OC_Filesystem::opendir($path); + $stat=OC_Filesystem::stat($path); + $mimetype=OC_Filesystem::getMimeType($path); + $stat['mimetype']=$mimetype; + if($path=='/'){ + $path=''; + } + self::put($path,$stat); + $fullPath=OC_Filesystem::getRoot().$path; + $totalSize=0; + if($dh){ + while (($filename = readdir($dh)) !== false) { + if($filename != '.' and $filename != '..'){ + $file=$path.'/'.$filename; + if(OC_Filesystem::is_dir($file)){ + self::scan($file,true); + }else{ + $stat=OC_Filesystem::stat($file); + $mimetype=OC_Filesystem::getMimeType($file); + $stat['mimetype']=$mimetype; + self::put($file,$stat); + $totalSize+=$stat['size']; + } + } + } + } + self::increaseSize($fullPath,$totalSize); + } + + /** + * fine files by mimetype + * @param string $part1 + * @param string $part2 (optional) + * @return array of file paths + * + * $part1 and $part2 together form the complete mimetype. + * e.g. searchByMime('text','plain') + * + * seccond mimetype part can be ommited + * e.g. searchByMime('audio') + */ + public static function searchByMime($part1,$part2=''){ + if($part2){ + $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimepart=?'); + $result=$query->execute(array($part1)); + }else{ + $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE mimetype=?'); + $result=$query->execute(array($part1.'/'.$part2)); + } + $names=array(); + while($row=$result->fetchRow()){ + $names[]=$row['path']; + } + return $names; + } +} + +//watch for changes and try to keep the cache up to date +OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache','fileSystemWatcherWrite'); +OC_Hook::connect('OC_Filesystem','delete','OC_FileCache','fileSystemWatcherDelete'); +OC_Hook::connect('OC_Filesystem','rename','OC_FileCache','fileSystemWatcherRename'); diff --git a/lib/fileproxy.php b/lib/fileproxy.php index 549b7015a6a..235fc8bf284 100644 --- a/lib/fileproxy.php +++ b/lib/fileproxy.php @@ -34,7 +34,7 @@ * A post-proxy recieves 2 arguments, the filepath and the result of the operation. * The return calue of the post-proxy will be used as the new result of the operation * The operations that have a post-proxy are - * file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, fileatime, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search + * file_get_contents, is_file, is_dir, file_exists, stat, is_readable, is_writable, filemtime, filectime, file_get_contents, getMimeType, hash, free_space and search */ class OC_FileProxy{ diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index f770c9cb32b..94a49176ee6 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -27,8 +27,10 @@ class OC_FileProxy_Quota extends OC_FileProxy{ private function getFreeSpace(){ - $usedSpace=OC_Filesystem::filesize(''); + $rootInfo=OC_FileCache::get(''); + $usedSpace=$rootInfo['size']; $totalSpace=OC_Preferences::getValue(OC_User::getUser(),'files','quota',0); + $totalSpace=OC_Helper::computerFileSize($totalSpace); if($totalSpace==0){ return 0; } diff --git a/lib/files.php b/lib/files.php index 9ae5320ad1d..5686287ecc4 100644 --- a/lib/files.php +++ b/lib/files.php @@ -36,44 +36,13 @@ class OC_Files { if(strpos($directory,OC::$CONFIG_DATADIRECTORY)===0){ $directory=substr($directory,strlen(OC::$CONFIG_DATADIRECTORY)); } - $filesfound=true; - $content=array(); - $dirs=array(); - $file=array(); - $files=array(); - if(OC_Filesystem::is_dir($directory)) { - if ($dh = OC_Filesystem::opendir($directory)) { - while (($filename = readdir($dh)) !== false) { - if($filename<>'.' and $filename<>'..' and substr($filename,0,1)!='.'){ - $file=array(); - $filesfound=true; - $file['name']=$filename; - $file['directory']=$directory; - $stat=OC_Filesystem::stat($directory.'/'.$filename); - $file=array_merge($file,$stat); - $file['size']=OC_Filesystem::filesize($directory.'/'.$filename); - $file['mime']=OC_Files::getMimeType($directory .'/'. $filename); - $file['readable']=OC_Filesystem::is_readable($directory .'/'. $filename); - $file['writeable']=OC_Filesystem::is_writeable($directory .'/'. $filename); - $file['type']=OC_Filesystem::filetype($directory .'/'. $filename); - if($file['type']=='dir'){ - $dirs[$file['name']]=$file; - }else{ - $files[$file['name']]=$file; - } - } - } - closedir($dh); - } + $files=OC_FileCache::getFolderContent($directory); + foreach($files as &$file){ + $file['directory']=$directory; + $file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file'; } - uksort($dirs, "strnatcasecmp"); uksort($files, "strnatcasecmp"); - $content=array_merge($dirs,$files); - if($filesfound){ - return $content; - }else{ - return false; - } + return $files; } diff --git a/lib/filestorage.php b/lib/filestorage.php index 34fa6457fd2..70aaf985b8b 100644 --- a/lib/filestorage.php +++ b/lib/filestorage.php @@ -39,7 +39,6 @@ class OC_Filestorage{ public function readfile($path){} public function filectime($path){} public function filemtime($path){} - public function fileatime($path){} public function file_get_contents($path){} public function file_put_contents($path,$data){} public function unlink($path){} @@ -48,7 +47,6 @@ class OC_Filestorage{ public function fopen($path,$mode){} public function toTmpFile($path){}//copy the file to a temporary file, used for cross-storage file actions public function fromTmpFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions - public function fromUploadedFile($tmpPath,$path){}//copy a file from a temporary file, used for cross-storage file actions public function getMimeType($path){} public function hash($type,$path,$raw){} public function free_space($path){} diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index e846aa420e4..61343652f61 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -13,13 +13,11 @@ class OC_Filestorage_Local extends OC_Filestorage{ } public function mkdir($path){ if($return=mkdir($this->datadir.$path)){ - $this->clearFolderSizeCache($path); } return $return; } public function rmdir($path){ if($return=rmdir($this->datadir.$path)){ - $this->clearFolderSizeCache($path); } return $return; } @@ -67,20 +65,15 @@ class OC_Filestorage_Local extends OC_Filestorage{ public function filemtime($path){ return filemtime($this->datadir.$path); } - public function fileatime($path){ - return fileatime($this->datadir.$path); - } public function file_get_contents($path){ return file_get_contents($this->datadir.$path); } public function file_put_contents($path,$data){ if($return=file_put_contents($this->datadir.$path,$data)){ - $this->clearFolderSizeCache($path); } } public function unlink($path){ $return=$this->delTree($path); - $this->clearFolderSizeCache($path); return $return; } public function rename($path1,$path2){ @@ -90,8 +83,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ } if($return=rename($this->datadir.$path1,$this->datadir.$path2)){ - $this->clearFolderSizeCache($path1); - $this->clearFolderSizeCache($path2); } return $return; } @@ -104,7 +95,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ $path2.=$source; } if($return=copy($this->datadir.$path1,$this->datadir.$path2)){ - $this->clearFolderSizeCache($path2); } return $return; } @@ -117,12 +107,10 @@ class OC_Filestorage_Local extends OC_Filestorage{ case 'w+': case 'x+': case 'a+': - $this->clearFolderSizeCache($path); break; case 'w': case 'x': case 'a': - $this->clearFolderSizeCache($path); break; } } @@ -192,18 +180,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ $fileStats = stat($tmpFile); if(rename($tmpFile,$this->datadir.$path)){ touch($this->datadir.$path, $fileStats['mtime'], $fileStats['atime']); - $this->clearFolderSizeCache($path); - return true; - }else{ - return false; - } - } - - public function fromUploadedFile($tmpFile,$path){ - $fileStats = stat($tmpFile); - if(move_uploaded_file($tmpFile,$this->datadir.$path)){ - touch($this->datadir.$path, $fileStats['mtime'], $fileStats['atime']); - $this->clearFolderSizeCache($path); return true; }else{ return false; @@ -219,7 +195,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ if ($item == '.' || $item == '..') continue; if(is_file($dir.'/'.$item)){ if(unlink($dir.'/'.$item)){ - $this->clearFolderSizeCache($dir); } }elseif(is_dir($dir.'/'.$item)){ if (!$this->delTree($dirRelative. "/" . $item)){ @@ -228,7 +203,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ } } if($return=rmdir($dir)){ - $this->clearFolderSizeCache($dir); } return $return; } @@ -268,75 +242,6 @@ class OC_Filestorage_Local extends OC_Filestorage{ * @return int size of folder and it's content */ public function getFolderSize($path){ - $path=str_replace('//','/',$path); - if($this->is_dir($path) and substr($path,-1)!='/'){ - $path.='/'; - } - $query=OC_DB::prepare("SELECT size FROM *PREFIX*foldersize WHERE path=?"); - $size=$query->execute(array($path))->fetchAll(); - if(count($size)>0){// we already the size, just return it - return $size[0]['size']; - }else{//the size of the folder isn't know, calulate it - return $this->calculateFolderSize($path); - } - } - - /** - * @brief calulate the size of folder and it's content and cache it - * @param string $path file path - * @return int size of folder and it's content - */ - public function calculateFolderSize($path){ - if($this->is_file($path)){ - $path=dirname($path); - } - $path=str_replace('//','/',$path); - if($this->is_dir($path) and substr($path,-1)!='/'){ - $path.='/'; - } - $size=0; - if ($dh = $this->opendir($path)) { - while (($filename = readdir($dh)) !== false) { - if($filename!='.' and $filename!='..'){ - $subFile=$path.'/'.$filename; - if($this->is_file($subFile)){ - $size+=$this->filesize($subFile); - }else{ - $size+=$this->getFolderSize($subFile); - } - } - } - if($size>0){ - $query=OC_DB::prepare("INSERT INTO *PREFIX*foldersize VALUES(?,?)"); - $result=$query->execute(array($path,$size)); - } - } - return $size; - } - - /** - * @brief clear the folder size cache of folders containing a file - * @param string $path - */ - public function clearFolderSizeCache($path){ - if($this->is_file($path)){ - $path=dirname($path); - } - $path=str_replace('//','/',$path); - if($this->is_dir($path) and substr($path,-1)!='/'){ - $path.='/'; - } - $query=OC_DB::prepare("DELETE FROM *PREFIX*foldersize WHERE path = ?"); - $result=$query->execute(array($path)); - if($path!='/' and $path!=''){ - $parts=explode('/',$path); - //pop empty part - $part=array_pop($parts); - if(empty($part)){ - array_pop($parts); - } - $parent=implode('/',$parts); - $this->clearFolderSizeCache($parent); - } + return 0;//depricated, use OC_FileCach instead } } diff --git a/lib/filestorage/remote.php b/lib/filestorage/remote.php deleted file mode 100644 index 88bdbca481c..00000000000 --- a/lib/filestorage/remote.php +++ /dev/null @@ -1,350 +0,0 @@ -<?php - -/** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2010 Frank Karlitschek karlitschek@kde.org -* -* 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_Filestorage_Remote extends OC_Filestorage{ - private $url; - private $username; - private $password; - private $remote=false; - private $statCache; - private $statCacheDir=false; - private $changed=array(); - - private function cacheDir($dir){ - if($this->statCacheDir!=$dir or $this->statCacheDir===false){ - $this->statCache=$this->remote->getFiles($dir); - $keys=array_keys($this->statCache); - $this->statCacheDir=$dir; - } - } - - public function __construct($arguments){ - $this->url=$arguments['url']; - $this->username=$arguments['username']; - $this->password=$arguments['password']; - } - private function connect(){ - if($this->remote===false){ - $this->remote=OC_Connect::connect($this->url,$this->username,$this->password); - } - } - public function mkdir($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $return=$this->remote->newFile($parent,$name,'dir'); - if($return){ - $this->notifyObservers($path,OC_FILEACTION_CREATE); - } - return $return; - } - public function rmdir($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $return=$this->remote->delete($parent,$name); - if($return){ - $this->notifyObservers($path,OC_FILEACTION_DELETE); - } - return $return; - } - public function opendir($path){ - $this->connect(); - $this->cacheDir($path); - $dirs=array_keys($this->statCache); - $id=uniqid(); - global $FAKEDIRS; - $FAKEDIRS[$id]=$dirs; - if($return=opendir("fakedir://$id")){ - $this->notifyObservers($path,OC_FILEACTION_READ); - } - return $return; - } - public function is_dir($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($path); - if($path=='' or $path=='/'){ - return true; - } - if(!isset($this->statCache[$name])){ - return false; - } - return ($this->statCache[$name]['type'=='dir']); - } - public function is_file($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return ($this->statCache[$name]['type'!='dir']); - } - public function stat($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return $false; - } - return $this->statCache[$name]; - } - public function filetype($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['type']; - } - public function filesize($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return $false; - } - return $this->statCache[$name]['size']; - } - public function is_readable($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['readable']; - } - public function is_writeable($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['writeable']; - } - public function file_exists($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - return isset($this->statCache[$name]); - } - public function readfile($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $file=$this->remote->getFile($parent,$name); - readfile($file); - unlink($file); - } - public function filectime($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['ctime']; - } - public function filemtime($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['mtime']; - } - public function fileatime($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['atime']; - } - public function file_get_contents($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $file=$this->remote->getFile($parent,$name); - file_get_contents($file); - unlink($file); - } - public function file_put_contents($path,$data){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $file=$this->remote->getFile($parent,$name); - $file=tempnam(get_temp_dir(),'oc_'); - file_put_contents($file,$data); - if($return=$this->remote->sendTmpFile($file,$parent,$name)){ - $this->notifyObservers($path,OC_FILEACTION_WRITE); - } - } - public function unlink($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - if($return=$this->remote->delete($paren,$name)){ - $this->notifyObservers($path,OC_FILEACTION_DELETE); - } - return $return; - } - public function rename($path1,$path2){ - $this->connect(); - $parent1=dirname($path1); - $name1=substr($path1,strlen($parent1)+1); - $parent2=dirname($path2); - $name2=substr($path2,strlen($parent2)+1); - if($return=$this->remote->move($parent1,$name1,$parent2,$name2)){ - $this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME); - } - return $return; - } - public function copy($path1,$path2){ - $this->connect(); - $parent1=dirname($path1); - $name1=substr($path1,strlen($parent1)+1); - $parent2=dirname($path2); - $name2=substr($path2,strlen($parent2)+1); - if($return=$this->copy->rename($parent1,$name1,$parent2,$name2)){ - $this->notifyObservers($path1.'->'.$path2,OC_FILEACTION_RENAME); - } - return $return; - } - public function fopen($path,$mode){ - $this->connect(); - $changed=false; - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - $file=$this->remote->getFile($parent,$name); - if($return=fopen($file,$mode)){ - switch($mode){ - case 'r': - $this->notifyObservers($path,OC_FILEACTION_READ); - break; - case 'r+': - case 'w+': - case 'x+': - case 'a+': - $this->notifyObservers($path,OC_FILEACTION_READ | OC_FILEACTION_WRITE); - $this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file); - break; - case 'w': - case 'x': - case 'a': - $this->notifyObservers($path,OC_FILEACTION_WRITE); - $this->changed[]=array('dir'=>$parent,'file'=>$name,'tmp'=>$file); - break; - } - } - return $return; - } - - public function getMimeType($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - if(substr($name,0,1)=='/'){ - $name=substr($name,1); - } - $this->cacheDir($parent); - if(!isset($this->statCache[$name])){ - return false; - } - return $this->statCache[$name]['mime']; - } - - public function toTmpFile($path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - if(substr($name,0,1)=='/'){ - $name=substr($name,1); - } - $filename=$this->remote->getFile($parent,$name); - if($filename){ - $this->notifyObservers($path,OC_FILEACTION_READ); - return $filename; - }else{ - return false; - } - } - - public function fromTmpFile($tmpFile,$path){ - $this->connect(); - $parent=dirname($path); - $name=substr($path,strlen($parent)+1); - if($this->remote->sendTmpFile($tmpFile,$parent,$name)){ - $this->notifyObservers($path,OC_FILEACTION_CREATE); - return true; - }else{ - return false; - } - } - - public function delTree($dir) { - $this->connect(); - $parent=dirname($dir); - $name=substr($dir,strlen($parent)+1); - $return=$this->remote->delete($parent,$name); - if($return=rmdir($dir)){ - $this->notifyObservers($dir,OC_FILEACTION_DELETE); - } - return $return; - } - - public function find($path){ - return $this->getTree($path); - } - - public function getTree($dir) { - $this->connect(); - if($return=$this->remote->getTree($dir)){ - $this->notifyObservers($dir,OC_FILEACTION_READ); - } - return $return; - } - - public function __destruct(){ - foreach($this->changed as $changed){ - $this->remote->sendTmpFile($changed['tmp'],$changed['dir'],$changed['file']); - } - } -} diff --git a/lib/filestoragecommon.php b/lib/filestoragecommon.php new file mode 100644 index 00000000000..35a926ecb07 --- /dev/null +++ b/lib/filestoragecommon.php @@ -0,0 +1,83 @@ +<?php + +/** +* ownCloud +* +* @author Michael Gapczynski +* @copyright 2012 Michael Gapczynski GapczynskiM@gmail.com +* +* 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_Filestorage_Common extends OC_Filestorage { + + public function __construct($parameters){} + public function mkdir($path){} + public function rmdir($path){} + public function opendir($path){} + public function is_dir($path){} + public function is_file($path){} + public function stat($path){} + public function filetype($path){} + public function filesize($path) { + $stat = $this->stat($path); + return $stat['size']; + } + public function is_readable($path){} + public function is_writeable($path){} + public function file_exists($path){} + public function readfile($path) { + $handle = $this->fopen($path, "r"); + $chunk = 1024; + while (!feof($handle)) { + echo fread($handle, $chunk); + } + return $this->filesize($path); + } + public function filectime($path) { + $stat = $this->stat($path); + return $stat['ctime']; + } + public function filemtime($path) { + $stat = $this->stat($path); + return $stat['mtime']; + } + public function fileatime($path) { + $stat = $this->stat($path); + return $stat['atime']; + } + public function file_get_contents($path) { + $handle = $this->fopen($path, "r"); + return fread($handle, $this->filesize($path)); + } + public function file_put_contents($path,$data) { + $handle = $this->fopen($path, "w"); + return fwrite($handle, $data); + } + public function unlink($path){} + public function rename($path1,$path2){} + public function copy($path1,$path2) { + $data = $this->file_get_contents($path1); + return $this->file_put_contents($path2, $data); + } + public function fopen($path,$mode){} + public function toTmpFile($path){} + public function fromTmpFile($tmpPath,$path){} + public function fromUploadedFile($tmpPath,$path){} + public function getMimeType($path){} + public function hash($type,$path,$raw){} + public function free_space($path){} + public function search($query){} + public function getLocalFile($path){} +} diff --git a/lib/filesystem.php b/lib/filesystem.php index bd953deb210..60d3f56a24c 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -42,11 +42,14 @@ * * the &run parameter can be set to false to prevent the operation from occuring */ + class OC_Filesystem{ static private $storages=array(); static private $mounts=array(); - static private $fakeRoot=''; static private $storageTypes=array(); + private $fakeRoot=''; + static private $defaultInstance; + /** * classname which used for hooks handling @@ -134,31 +137,69 @@ class OC_Filesystem{ */ const signal_param_run = 'run'; - /** - * register a storage type - * @param string type - * @param string classname - * @param array arguments an associative array in the form of name=>type (eg array('datadir'=>'string')) + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @param string path + * @return string */ - static public function registerStorageType($type,$classname,$arguments){ - self::$storageTypes[$type]=array('type'=>$type,'classname'=>$classname,'arguments'=>$arguments); + static public function getMountPoint($path){ + if(!$path){ + $path='/'; + } + if(substr($path,0,1)!=='/'){ + $path='/'.$path; + } + if(substr($path,-1)!=='/'){ + $path=$path.'/'; + } + $foundMountPoint=''; + foreach(OC_Filesystem::$mounts as $mountpoint=>$storage){ + if(substr($mountpoint,-1)!=='/'){ + $mountpoint=$mountpoint.'/'; + } + if($mountpoint==$path){ + return $mountpoint; + } + if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)){ + $foundMountPoint=$mountpoint; + } + } + return $foundMountPoint; } - + /** - * check if the filesystem supports a specific storagetype - * @param string type + * get the part of the path relative to the mountpoint of the storage it's stored in + * @param string path * @return bool */ - static public function hasStorageType($type){ - return isset(self::$storageTypes[$type]); + static public function getInternalPath($path){ + $mountPoint=self::getMountPoint($path); + $internalPath=substr($path,strlen($mountPoint)); + return $internalPath; } - /** - * get the list of names of storagetypes that the filesystem supports - * @return array + * get the storage object for a path + * @param string path + * @return OC_Filestorage */ - static public function getStorageTypeNames(){ - return array_keys(self::$storageTypes); + static public function getStorage($path){ + $mountpoint=self::getMountPoint($path); + if($mountpoint){ + if(!isset(OC_Filesystem::$storages[$mountpoint])){ + $mount=OC_Filesystem::$mounts[$mountpoint]; + OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']); + } + return OC_Filesystem::$storages[$mountpoint]; + } + } + + static public function init($root){ + if(self::$defaultInstance){ + return false; + } + self::$defaultInstance=new OC_FilesystemView($root); } /** @@ -177,13 +218,9 @@ class OC_Filesystem{ * @param array arguments * @return OC_Filestorage */ - static private function createStorage($type,$arguments){ - if(!self::hasStorageType($type)){ - return false; - } - $className=self::$storageTypes[$type]['classname']; - if(class_exists($className)){ - return new $className($arguments); + static private function createStorage($class,$arguments){ + if(class_exists($class)){ + return new $class($arguments); }else{ return false; } @@ -195,36 +232,27 @@ class OC_Filesystem{ * @return bool */ static public function chroot($fakeRoot){ - if(!$fakeRoot==''){ - if($fakeRoot[0]!=='/'){ - $fakeRoot='/'.$fakeRoot; - } - } - self::$fakeRoot=$fakeRoot; + return self::$defaultInstance->chroot($path); } - + /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * @param string path - * @return bool - */ - static public function getInternalPath($path){ - $mountPoint=self::getMountPoint($path); - $path=self::$fakeRoot.$path; - $internalPath=substr($path,strlen($mountPoint)); - return $internalPath; + * get the fake root + * @return string + */ + static public function getRoot(){ + return self::$defaultInstance->getRoot(); } - + /** * mount an OC_Filestorage in our virtual filesystem * @param OC_Filestorage storage * @param string mountpoint */ - static public function mount($type,$arguments,$mountpoint){ + static public function mount($class,$arguments,$mountpoint){ if(substr($mountpoint,0,1)!=='/'){ $mountpoint='/'.$mountpoint; } - self::$mounts[$mountpoint]=array('type'=>$type,'arguments'=>$arguments); + self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments); } /** @@ -239,65 +267,13 @@ class OC_Filesystem{ } /** - * get the storage object for a path - * @param string path - * @return OC_Filestorage - */ - static public function getStorage($path){ - $mountpoint=self::getMountPoint($path); - if($mountpoint){ - if(!isset(self::$storages[$mountpoint])){ - $mount=self::$mounts[$mountpoint]; - self::$storages[$mountpoint]=self::createStorage($mount['type'],$mount['arguments']); - } - return self::$storages[$mountpoint]; - } - } - - /** - * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account - * - * @param string path - * @return string - */ - static public function getMountPoint($path){ - if(!$path){ - $path='/'; - } - if(substr($path,0,1)!=='/'){ - $path='/'.$path; - } - if(substr($path,-1)!=='/'){ - $path=$path.'/'; - } - $path=self::$fakeRoot.$path; - $foundMountPoint=''; - foreach(self::$mounts as $mountpoint=>$storage){ - if(substr($mountpoint,-1)!=='/'){ - $mountpoint=$mountpoint.'/'; - } - if($mountpoint==$path){ - return $mountpoint; - } - if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)){ - $foundMountPoint=$mountpoint; - } - } - return $foundMountPoint; - } - - /** * return the path to a local version of the file * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed * @param string path * @return string */ static public function getLocalFile($path){ - $parent=substr($path,0,strrpos($path,'/')); - if(self::isValidPath($parent) and $storage=self::getStorage($path)){ - return $storage->getLocalFile(self::getInternalPath($path)); - } + return self::$defaultInstance->getLocalFile($path); } /** @@ -314,262 +290,90 @@ class OC_Filesystem{ } return true; } - + /** + * following functions are equivilent to their php buildin equivilents for arguments/return values. + */ static public function mkdir($path){ - return self::basicOperation('mkdir',$path,array('create','write')); + return self::$defaultInstance->mkdir($path); } static public function rmdir($path){ - return self::basicOperation('rmdir',$path,array('delete')); + return self::$defaultInstance->rmdir($path); } static public function opendir($path){ - return self::basicOperation('opendir',$path,array('read')); + return self::$defaultInstance->opendir($path); } static public function is_dir($path){ - if($path=='/'){ - return true; - } - return self::basicOperation('is_dir',$path); + return self::$defaultInstance->is_dir($path); } static public function is_file($path){ - if($path=='/'){ - return false; - } - return self::basicOperation('is_file',$path); + return self::$defaultInstance->is_file($path); } static public function stat($path){ - return self::basicOperation('stat',$path); + return self::$defaultInstance->stat($path); } static public function filetype($path){ - return self::basicOperation('filetype',$path); + return self::$defaultInstance->filetype($path); } static public function filesize($path){ - return self::basicOperation('filesize',$path); + return self::$defaultInstance->filesize($path); } static public function readfile($path){ - return self::basicOperation('readfile',$path,array('read')); + return self::$defaultInstance->readfile($path); } static public function is_readable($path){ - return self::basicOperation('is_readable',$path); + return self::$defaultInstance->is_readable($path); } static public function is_writeable($path){ - return self::basicOperation('is_writeable',$path); + return self::$defaultInstance->is_writeable($path); } static public function file_exists($path){ - if($path=='/'){ - return true; - } - return self::basicOperation('file_exists',$path); + return self::$defaultInstance->file_exists($path); } static public function filectime($path){ - return self::basicOperation('filectime',$path); + return self::$defaultInstance->filectime($path); } static public function filemtime($path){ - return self::basicOperation('filemtime',$path); - } - static public function fileatime($path){ - return self::basicOperation('fileatime',$path); + return self::$defaultInstance->filemtime($path); } static public function file_get_contents($path){ - return self::basicOperation('file_get_contents',$path,array('read')); + return self::$defaultInstance->file_get_contents($path); } static public function file_put_contents($path,$data){ - return self::basicOperation('file_put_contents',$path,array('create','write'),$data); + return self::$defaultInstance->file_put_contents($path,$data); } static public function unlink($path){ - return self::basicOperation('unlink',$path,array('delete')); + return self::$defaultInstance->unlink($path); } static public function rename($path1,$path2){ - if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and self::is_writeable($path1) and self::isValidPath($path2)){ - $run=true; - OC_Hook::emit( self::CLASSNAME, self::signal_rename, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run)); - if($run){ - $mp1=self::getMountPoint($path1); - $mp2=self::getMountPoint($path2); - if($mp1==$mp2){ - if($storage=self::getStorage($path1)){ - $result=$storage->rename(self::getInternalPath($path1),self::getInternalPath($path2)); - } - }elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){ - $tmpFile=$storage1->toTmpFile(self::getInternalPath($path1)); - $result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2)); - $storage1->unlink(self::getInternalPath($path1)); - } - OC_Hook::emit( self::CLASSNAME, self::signal_post_rename, array( self::signal_param_oldpath => $path1, self::signal_param_newpath=>$path2)); - return $result; - } - } + return self::$defaultInstance->rename($path1,$path2); } static public function copy($path1,$path2){ - if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and self::is_readable($path1) and self::isValidPath($path2)){ - $run=true; - OC_Hook::emit( self::CLASSNAME, self::signal_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2, self::signal_param_run => &$run)); - $exists=self::file_exists($path2); - if($run and !$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path2, self::signal_param_run => &$run)); - } - if($run){ - OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path2, self::signal_param_run => &$run)); - } - if($run){ - $mp1=self::getMountPoint($path1); - $mp2=self::getMountPoint($path2); - if($mp1==$mp2){ - if($storage=self::getStorage($path1)){ - $result=$storage->copy(self::getInternalPath($path1),self::getInternalPath($path2)); - } - }elseif($storage1=self::getStorage($path1) and $storage2=self::getStorage($path2)){ - $tmpFile=$storage1->toTmpFile(self::getInternalPath($path1)); - $result=$storage2->fromTmpFile($tmpFile,self::getInternalPath($path2)); - } - OC_Hook::emit( self::CLASSNAME, self::signal_post_copy, array( self::signal_param_oldpath => $path1 , self::signal_param_newpath=>$path2)); - if(!$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path2)); - } - OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path2)); - return $result; - } - } + return self::$defaultInstance->copy($path1,$path2); } static public function fopen($path,$mode){ - $hooks=array(); - switch($mode){ - case 'r': - $hooks[]='read'; - break; - case 'r+': - case 'w+': - case 'x+': - case 'a+': - $hooks[]='read'; - $hooks[]='write'; - break; - case 'w': - case 'x': - case 'a': - $hooks[]='write'; - break; - default: - OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR); - } - - return self::basicOperation('fopen',$path,$hooks,$mode); + return self::$defaultInstance->fopen($path,$mode); } static public function toTmpFile($path){ - if(OC_FileProxy::runPreProxies('toTmpFile',$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ - OC_Hook::emit( self::CLASSNAME, self::signal_read, array( self::signal_param_path => $path)); - return $storage->toTmpFile(self::getInternalPath($path)); - } + return self::$defaultInstance->toTmpFile($path); } static public function fromTmpFile($tmpFile,$path){ - if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ - $run=true; - $exists=self::file_exists($path); - if(!$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run)); - } - if($run){ - OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run)); - } - if($run){ - $result=$storage->fromTmpFile($tmpFile,self::getInternalPath($path)); - if(!$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path)); - } - OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path)); - return $result; - } - } - } - static public function fromUploadedFile($tmpFile,$path){ - if(OC_FileProxy::runPreProxies('fromUploadedFile',$tmpFile,$path) and self::isValidPath($path) and $storage=self::getStorage($path)){ - $run=true; - $exists=self::file_exists($path); - if(!$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_create, array( self::signal_param_path => $path, self::signal_param_run => &$run)); - } - if($run){ - OC_Hook::emit( self::CLASSNAME, self::signal_write, array( self::signal_param_path => $path, self::signal_param_run => &$run)); - } - if($run){ - $result=$storage->fromUploadedFile($tmpFile,self::getInternalPath($path)); - if(!$exists){ - OC_Hook::emit( self::CLASSNAME, self::signal_post_create, array( self::signal_param_path => $path)); - } - OC_Hook::emit( self::CLASSNAME, self::signal_post_write, array( self::signal_param_path => $path)); - return $result; - } - } + return self::$defaultInstance->fromTmpFile($tmpFile,$path); } + static public function getMimeType($path){ - return self::basicOperation('getMimeType',$path); + return self::$defaultInstance->getMimeType($path); } static public function hash($type,$path){ - return self::basicOperation('hash',$path,array('read')); + return self::$defaultInstance->hash($type,$path); } static public function free_space($path='/'){ - return self::basicOperation('free_space',$path); + return self::$defaultInstance->free_space($path); } static public function search($query){ - self::mountAll(); - $files=array(); - $fakeRoot=self::$fakeRoot; - $fakeRootLength=strlen($fakeRoot); - foreach(self::$storages as $mountpoint=>$storage){ - $results=$storage->search($query); - if(is_array($results)){ - foreach($results as $result){ - $file=str_replace('//','/',$mountpoint.$result); - if(substr($file,0,$fakeRootLength)==$fakeRoot){ - $file=substr($file,$fakeRootLength); - $files[]=$file; - } - } - } - } - return $files; - - } - - static public function update_session_file_hash($sessionname,$sessionvalue){ - $_SESSION[$sessionname] = $sessionvalue; - } - - /** - * abstraction for running most basic operations - * @param string $operation - * @param string #path - * @param array (optional) hooks - * @param mixed (optional) $extraParam - * @return mixed - */ - private static function basicOperation($operation,$path,$hooks=array(),$extraParam=null){ - if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and self::isValidPath($path) and $storage=self::getStorage($path)){ - $interalPath=self::getInternalPath($path); - $run=true; - foreach($hooks as $hook){ - if($hook!='read'){ - OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path, self::signal_param_run => &$run)); - }else{ - OC_Hook::emit( self::CLASSNAME, $hook, array( self::signal_param_path => $path)); - } - } - if($run){ - if($extraParam){ - $result=$storage->$operation($interalPath,$extraParam); - }else{ - $result=$storage->$operation($interalPath); - } - $result=OC_FileProxy::runPostProxies($operation,$path,$result); - foreach($hooks as $hook){ - if($hook!='read'){ - OC_Hook::emit( self::CLASSNAME, 'post_'.$hook, array( self::signal_param_path => $path)); - } - } - return $result; - } - } - return null; + return self::$defaultInstance->search($query); } } + +require_once('filecache.php'); diff --git a/lib/filesystemview.php b/lib/filesystemview.php new file mode 100644 index 00000000000..9687a8bceb4 --- /dev/null +++ b/lib/filesystemview.php @@ -0,0 +1,335 @@ +<?php + +/** +* ownCloud +* +* @author Frank Karlitschek +* @copyright 2010 Frank Karlitschek karlitschek@kde.org +* +* 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_FilesystemView { + private $fakeRoot=''; + + public function __construct($root){ + $this->fakeRoot=$root; + } + + public function getAbsolutePath($path){ + if(!$path){ + $path='/'; + } + if(substr($path,0,1)!=='/'){ + $path='/'.$path; + } + return $this->fakeRoot.$path; + } + + + /** + * change the root to a fake toor + * @param string fakeRoot + * @return bool + */ + public function chroot($fakeRoot){ + if(!$fakeRoot==''){ + if($fakeRoot[0]!=='/'){ + $fakeRoot='/'.$fakeRoot; + } + } + $this->fakeRoot=$fakeRoot; + } + + /** + * get the fake root + * @return string + */ + public function getRoot(){ + return $this->fakeRoot; + } + + /** + * get the part of the path relative to the mountpoint of the storage it's stored in + * @param string path + * @return bool + */ + public function getInternalPath($path){ + return OC_Filesystem::getInternalPath($this->getAbsolutePath($path)); + } + /** + * get the storage object for a path + * @param string path + * @return OC_Filestorage + */ + public function getStorage($path){ + return OC_Filesystem::getStorage($this->getAbsolutePath($path)); + } + + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @param string path + * @return string + */ + public function getMountPoint($path){ + return OC_Filesystem::getMountPoint($this->getAbsolutePath($path)); + } + + /** + * return the path to a local version of the file + * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * @param string path + * @return string + */ + public function getLocalFile($path){ + $parent=substr($path,0,strrpos($path,'/')); + if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)){ + return $storage->getLocalFile($this->getInternalPath($path)); + } + } + + /** + * following functions are equivilent to their php buildin equivilents for arguments/return values. + */ + public function mkdir($path){ + return $this->basicOperation('mkdir',$path,array('create','write')); + } + public function rmdir($path){ + return $this->basicOperation('rmdir',$path,array('delete')); + } + public function opendir($path){ + return $this->basicOperation('opendir',$path,array('read')); + } + public function is_dir($path){ + if($path=='/'){ + return true; + } + return $this->basicOperation('is_dir',$path); + } + public function is_file($path){ + if($path=='/'){ + return false; + } + return $this->basicOperation('is_file',$path); + } + public function stat($path){ + return $this->basicOperation('stat',$path); + } + public function filetype($path){ + return $this->basicOperation('filetype',$path); + } + public function filesize($path){ + return $this->basicOperation('filesize',$path); + } + public function readfile($path){ + return $this->basicOperation('readfile',$path,array('read')); + } + public function is_readable($path){ + return $this->basicOperation('is_readable',$path); + } + public function is_writeable($path){ + return $this->basicOperation('is_writeable',$path); + } + public function file_exists($path){ + if($path=='/'){ + return true; + } + return $this->basicOperation('file_exists',$path); + } + public function filectime($path){ + return $this->basicOperation('filectime',$path); + } + public function filemtime($path){ + return $this->basicOperation('filemtime',$path); + } + public function file_get_contents($path){ + return $this->basicOperation('file_get_contents',$path,array('read')); + } + public function file_put_contents($path,$data){ + return $this->basicOperation('file_put_contents',$path,array('create','write'),$data); + } + public function unlink($path){ + return $this->basicOperation('unlink',$path,array('delete')); + } + public function rename($path1,$path2){ + if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and $this->is_writeable($path1) and OC_Filesystem::isValidPath($path2)){ + $run=true; + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run)); + if($run){ + $mp1=$this->getMountPoint($path1); + $mp2=$this->getMountPoint($path2); + if($mp1==$mp2){ + if($storage=$this->getStorage($path1)){ + $result=$storage->rename($this->getInternalPath($path1),$this->getInternalPath($path2)); + } + }elseif($storage1=$this->getStorage($path1) and $storage2=$this->getStorage($path2)){ + $tmpFile=$storage1->toTmpFile($this->getInternalPath($path1)); + $result=$storage2->fromTmpFile($tmpFile,$this->getInternalPath($path2)); + $storage1->unlink($this->getInternalPath($path1)); + } + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, array( OC_Filesystem::signal_param_oldpath => $path1, OC_Filesystem::signal_param_newpath=>$path2)); + return $result; + } + } + } + public function copy($path1,$path2){ + if(OC_FileProxy::runPreProxies('copy',$path1,$path2) and $this->is_readable($path1) and OC_Filesystem::isValidPath($path2)){ + $run=true; + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run)); + $exists=$this->file_exists($path2); + if($run and !$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run)); + } + if($run){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path2, OC_Filesystem::signal_param_run => &$run)); + } + if($run){ + $mp1=$this->getMountPoint($path1); + $mp2=$this->getMountPoint($path2); + if($mp1==$mp2){ + if($storage=$this->getStorage($path1)){ + $result=$storage->copy($this->getInternalPath($path1),$this->getInternalPath($path2)); + } + }elseif($storage1=$this->getStorage($path1) and $storage2=$this->getStorage($path2)){ + $tmpFile=$storage1->toTmpFile($this->getInternalPath($path1)); + $result=$storage2->fromTmpFile($tmpFile,$this->getInternalPath($path2)); + } + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_copy, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2)); + if(!$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path2)); + } + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path2)); + return $result; + } + } + } + public function fopen($path,$mode){ + $hooks=array(); + switch($mode){ + case 'r': + $hooks[]='read'; + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + $hooks[]='read'; + $hooks[]='write'; + break; + case 'w': + case 'x': + case 'a': + $hooks[]='write'; + break; + default: + OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR); + } + + return $this->basicOperation('fopen',$path,$hooks,$mode); + } + public function toTmpFile($path){ + if(OC_FileProxy::runPreProxies('toTmpFile',$path) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_read, array( OC_Filesystem::signal_param_path => $path)); + return $storage->toTmpFile($this->getInternalPath($path)); + } + } + public function fromTmpFile($tmpFile,$path){ + if(OC_FileProxy::runPreProxies('copy',$tmpFile,$path) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){ + $run=true; + $exists=$this->file_exists($path); + if(!$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + } + if($run){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + } + if($run){ + $result=$storage->fromTmpFile($tmpFile,$this->getInternalPath($path)); + if(!$exists){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, array( OC_Filesystem::signal_param_path => $path)); + } + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path)); + return $result; + } + } + } + + public function getMimeType($path){ + return $this->basicOperation('getMimeType',$path); + } + public function hash($type,$path){ + return $this->basicOperation('hash',$path,array('read')); + } + + public function free_space($path='/'){ + return $this->basicOperation('free_space',$path); + } + + public function search($query){ + $files=array(); + $fakeRoot=$this->$fakeRoot; + $fakeRootLength=strlen($fakeRoot); + $results=OC_FileCache::search($query); + if(is_array($results)){ + foreach($results as $result){ + $file=str_replace('//','/',$mountpoint.$result); + if(substr($file,0,$fakeRootLength)==$fakeRoot){ + $file=substr($file,$fakeRootLength); + $files[]=$file; + } + } + } + return $files; + } + + /** + * abstraction for running most basic operations + * @param string $operation + * @param string #path + * @param array (optional) hooks + * @param mixed (optional) $extraParam + * @return mixed + */ + private function basicOperation($operation,$path,$hooks=array(),$extraParam=null){ + if(OC_FileProxy::runPreProxies($operation,$path, $extraParam) and OC_Filesystem::isValidPath($path) and $storage=$this->getStorage($path)){ + $interalPath=$this->getInternalPath($path); + $run=true; + foreach($hooks as $hook){ + if($hook!='read'){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path, OC_Filesystem::signal_param_run => &$run)); + }else{ + OC_Hook::emit( OC_Filesystem::CLASSNAME, $hook, array( OC_Filesystem::signal_param_path => $path)); + } + } + if($run){ + if($extraParam){ + $result=$storage->$operation($interalPath,$extraParam); + }else{ + $result=$storage->$operation($interalPath); + } + $result=OC_FileProxy::runPostProxies($operation,$path,$result); + foreach($hooks as $hook){ + if($hook!='read'){ + OC_Hook::emit( OC_Filesystem::CLASSNAME, 'post_'.$hook, array( OC_Filesystem::signal_param_path => $path)); + } + } + return $result; + } + } + return null; + } +} diff --git a/lib/util.php b/lib/util.php index 2fba1206bff..6c19c5416a2 100644 --- a/lib/util.php +++ b/lib/util.php @@ -37,7 +37,7 @@ class OC_Util { if( $user != "" ){ //if we aren't logged in, there is no use to set up the filesystem //first set up the local "root" storage - OC_Filesystem::mount('local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/'); + OC_Filesystem::mount('OC_Filestorage_Local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/'); OC::$CONFIG_DATADIRECTORY = $CONFIG_DATADIRECTORY_ROOT."/$user/$root"; if( !is_dir( OC::$CONFIG_DATADIRECTORY )){ @@ -45,7 +45,7 @@ class OC_Util { } //jail the user into his "home" directory - OC_Filesystem::chroot("/$user/$root"); + OC_Filesystem::init('/'.$user.'/'.$root); $quotaProxy=new OC_FileProxy_Quota(); OC_FileProxy::register($quotaProxy); self::$fsSetup=true; @@ -62,7 +62,7 @@ class OC_Util { * @return array */ public static function getVersion(){ - return array(3,00,0); + return array(3,00,1); } /** diff --git a/owncloud.db.filesystem b/owncloud.db.filesystem Binary files differnew file mode 100644 index 00000000000..082977a37ef --- /dev/null +++ b/owncloud.db.filesystem diff --git a/settings/ajax/setquota.php b/settings/ajax/setquota.php index 5c07285cfca..d4e3c58ac11 100644 --- a/settings/ajax/setquota.php +++ b/settings/ajax/setquota.php @@ -6,10 +6,13 @@ require_once('../../lib/base.php'); OC_JSON::checkAdminUser(); $username = $_POST["username"]; + +//make sure the quota is in the expected format $quota= OC_Helper::computerFileSize($_POST["quota"]); +$quota=OC_Helper::humanFileSize($quota); // Return Success story OC_Preferences::setValue($username,'files','quota',$quota); -OC_JSON::success(array("data" => array( "username" => $username ,'quota'=>OC_Helper::humanFileSize($quota)))); +OC_JSON::success(array("data" => array( "username" => $username ,'quota'=>$quota))); ?> diff --git a/settings/personal.php b/settings/personal.php index 787957f246f..8e888760052 100755 --- a/settings/personal.php +++ b/settings/personal.php @@ -16,7 +16,8 @@ OC_Util::addStyle( '3rdparty', 'chosen' ); OC_App::setActiveNavigationEntry( 'personal' ); // calculate the disc space -$used=OC_Filesystem::filesize('/'); +$rootInfo=OC_FileCache::get(''); +$used=$rootInfo['size']; $free=OC_Filesystem::free_space(); $total=$free+$used; $relative=round(($used/$total)*10000)/100; diff --git a/settings/users.php b/settings/users.php index 686c4b6a9bf..e5dcc049481 100644 --- a/settings/users.php +++ b/settings/users.php @@ -18,7 +18,7 @@ $users = array(); $groups = array(); foreach( OC_User::getUsers() as $i ){ - $users[] = array( "name" => $i, "groups" => join( ", ", OC_Group::getUserGroups( $i ) ),'quota'=>OC_Helper::humanFileSize(OC_Preferences::getValue($i,'files','quota',0))); + $users[] = array( "name" => $i, "groups" => join( ", ", OC_Group::getUserGroups( $i ) ),'quota'=>OC_Preferences::getValue($i,'files','quota',0)); } foreach( OC_Group::getGroups() as $i ){ |