parent
a1dfe16d0a
commit
11c848b221
@ -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; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue