more path normalization

This commit is contained in:
Robin Appelman 2012-08-17 01:22:26 +02:00
parent 70e8a7e25c
commit 53a888cc81
5 changed files with 80 additions and 58 deletions

View File

@ -92,7 +92,7 @@ $maxUploadFilesize = min($maxUploadFilesize ,$freeSpace);
$tmpl = new OCP\Template( 'files', 'index', 'user' ); $tmpl = new OCP\Template( 'files', 'index', 'user' );
$tmpl->assign( 'fileList', $list->fetchPage(), false ); $tmpl->assign( 'fileList', $list->fetchPage(), false );
$tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage(), false ); $tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage(), false );
$tmpl->assign( 'dir', $dir); $tmpl->assign( 'dir', OC_Filesystem::normalizePath($dir));
$tmpl->assign( 'readonly', !OC_Filesystem::is_writable($dir.'/')); $tmpl->assign( 'readonly', !OC_Filesystem::is_writable($dir.'/'));
$tmpl->assign( 'files', $files ); $tmpl->assign( 'files', $files );
$tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize);

View File

@ -33,6 +33,10 @@ class OC_Files {
* @param dir $directory path under datadirectory * @param dir $directory path under datadirectory
*/ */
public static function getDirectoryContent($directory, $mimetype_filter = ''){ public static function getDirectoryContent($directory, $mimetype_filter = ''){
$directory=OC_Filesystem::normalizePath($directory);
if($directory=='/'){
$directory='';
}
$files=OC_FileCache::getFolderContent($directory, false, $mimetype_filter); $files=OC_FileCache::getFolderContent($directory, false, $mimetype_filter);
foreach($files as &$file){ foreach($files as &$file){
$file['directory']=$directory; $file['directory']=$directory;

View File

@ -495,7 +495,16 @@ class OC_Filesystem{
OC_Connector_Sabre_Node::removeETagPropertyForPath($path); OC_Connector_Sabre_Node::removeETagPropertyForPath($path);
} }
public static function normalizePath($path){ /**
* normalize a path
* @param string path
* @param bool $stripTrailingSlash
* @return string
*/
public static function normalizePath($path,$stripTrailingSlash=true){
if($path==''){
return '/';
}
//no windows style slashes //no windows style slashes
$path=str_replace('\\','/',$path); $path=str_replace('\\','/',$path);
//add leading slash //add leading slash
@ -503,7 +512,7 @@ class OC_Filesystem{
$path='/'.$path; $path='/'.$path;
} }
//remove trainling slash //remove trainling slash
if(strlen($path)>1 and substr($path,-1,1)==='/'){ if($stripTrailingSlash and strlen($path)>1 and substr($path,-1,1)==='/'){
$path=substr($path,0,-1); $path=substr($path,0,-1);
} }
//remove duplicate slashes //remove duplicate slashes

View File

@ -54,7 +54,7 @@ class OC_FilesystemView {
if($path[0]!=='/'){ if($path[0]!=='/'){
$path='/'.$path; $path='/'.$path;
} }
return OC_Filesystem::normalizePath($this->fakeRoot.$path); return $this->fakeRoot.$path;
} }
/** /**
@ -227,7 +227,7 @@ class OC_FilesystemView {
} }
public function file_put_contents($path, $data) { public function file_put_contents($path, $data) {
if(is_resource($data)) {//not having to deal with streams in file_put_contents makes life easier if(is_resource($data)) {//not having to deal with streams in file_put_contents makes life easier
$absolutePath = $this->getAbsolutePath($path); $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path));
if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) { if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath); $path = $this->getRelativePath($absolutePath);
$exists = $this->file_exists($path); $exists = $this->file_exists($path);
@ -287,11 +287,14 @@ class OC_FilesystemView {
return $this->basicOperation( 'deleteAll', $directory, array('delete'), $empty ); return $this->basicOperation( 'deleteAll', $directory, array('delete'), $empty );
} }
public function rename($path1, $path2) { public function rename($path1, $path2) {
$absolutePath1 = $this->getAbsolutePath($path1); $postFix1=(substr($path1,-1,1)==='/')?'/':'';
$absolutePath2 = $this->getAbsolutePath($path2); $postFix2=(substr($path2,-1,1)==='/')?'/':'';
$absolutePath1 = OC_Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = OC_Filesystem::normalizePath($this->getAbsolutePath($path2));
if(OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { if(OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) {
$path1 = $this->getRelativePath($absolutePath1); $path1 = $this->getRelativePath($absolutePath1);
$path2 = $this->getRelativePath($absolutePath2); $path2 = $this->getRelativePath($absolutePath2);
if($path1 == null or $path2 == null) { if($path1 == null or $path2 == null) {
return false; return false;
} }
@ -305,20 +308,20 @@ class OC_FilesystemView {
) )
); );
if($run) { if($run) {
$mp1 = $this->getMountPoint($path1); $mp1 = $this->getMountPoint($path1.$postFix1);
$mp2 = $this->getMountPoint($path2); $mp2 = $this->getMountPoint($path2.$postFix2);
if($mp1 == $mp2) { if($mp1 == $mp2) {
if($storage = $this->getStorage($path1)) { if($storage = $this->getStorage($path1)) {
$result = $storage->rename($this->getInternalPath($path1), $this->getInternalPath($path2)); $result = $storage->rename($this->getInternalPath($path1.$postFix1), $this->getInternalPath($path2.$postFix2));
} }
} else { } else {
$source = $this->fopen($path1, 'r'); $source = $this->fopen($path1.$postFix1, 'r');
$target = $this->fopen($path2, 'w'); $target = $this->fopen($path2.$postFix2, 'w');
$count = OC_Helper::streamCopy($source, $target); $count = OC_Helper::streamCopy($source, $target);
$storage1 = $this->getStorage($path1); $storage1 = $this->getStorage($path1);
$storage1->unlink($this->getInternalPath($path1)); $storage1->unlink($this->getInternalPath($path1.$postFix1));
$result = $count>0; $result = $count>0;
} }
OC_Hook::emit( OC_Hook::emit(
OC_Filesystem::CLASSNAME, OC_Filesystem::CLASSNAME,
OC_Filesystem::signal_post_rename, OC_Filesystem::signal_post_rename,
@ -332,11 +335,14 @@ class OC_FilesystemView {
} }
} }
public function copy($path1, $path2) { public function copy($path1, $path2) {
$absolutePath1 = $this->getAbsolutePath($path1); $postFix1=(substr($path1,-1,1)==='/')?'/':'';
$absolutePath2 = $this->getAbsolutePath($path2); $postFix2=(substr($path2,-1,1)==='/')?'/':'';
$absolutePath1 = OC_Filesystem::normalizePath($this->getAbsolutePath($path1));
$absolutePath2 = OC_Filesystem::normalizePath($this->getAbsolutePath($path2));
if(OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { if(OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) {
$path1 = $this->getRelativePath($absolutePath1); $path1 = $this->getRelativePath($absolutePath1);
$path2 = $this->getRelativePath($absolutePath2); $path2 = $this->getRelativePath($absolutePath2);
if($path1 == null or $path2 == null) { if($path1 == null or $path2 == null) {
return false; return false;
} }
@ -372,15 +378,15 @@ class OC_FilesystemView {
); );
} }
if($run) { if($run) {
$mp1=$this->getMountPoint($path1); $mp1=$this->getMountPoint($path1.$postFix1);
$mp2=$this->getMountPoint($path2); $mp2=$this->getMountPoint($path2.$postFix2);
if($mp1 == $mp2){ if($mp1 == $mp2){
if($storage = $this->getStorage($path1)) { if($storage = $this->getStorage($path1.$postFix1)) {
$result=$storage->copy($this->getInternalPath($path1), $this->getInternalPath($path2)); $result=$storage->copy($this->getInternalPath($path1.$postFix1), $this->getInternalPath($path2.$postFix2));
} }
} else { } else {
$source = $this->fopen($path1, 'r'); $source = $this->fopen($path1.$postFix1, 'r');
$target = $this->fopen($path2, 'w'); $target = $this->fopen($path2.$postFix2, 'w');
$result = OC_Helper::streamCopy($source, $target); $result = OC_Helper::streamCopy($source, $target);
} }
OC_Hook::emit( OC_Hook::emit(
@ -475,7 +481,8 @@ class OC_FilesystemView {
return $this->basicOperation('getMimeType', $path); return $this->basicOperation('getMimeType', $path);
} }
public function hash($type, $path, $raw = false) { public function hash($type, $path, $raw = false) {
$absolutePath = $this->getAbsolutePath($path); $postFix=(substr($path,-1,1)==='/')?'/':'';
$absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path));
if (OC_FileProxy::runPreProxies('hash', $absolutePath) && OC_Filesystem::isValidPath($path)) { if (OC_FileProxy::runPreProxies('hash', $absolutePath) && OC_Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath); $path = $this->getRelativePath($absolutePath);
if ($path == null) { if ($path == null) {
@ -488,8 +495,8 @@ class OC_FilesystemView {
array( OC_Filesystem::signal_param_path => $path) array( OC_Filesystem::signal_param_path => $path)
); );
} }
if ($storage = $this->getStorage($path)) { if ($storage = $this->getStorage($path.$postFix)) {
$result = $storage->hash($type, $this->getInternalPath($path), $raw); $result = $storage->hash($type, $this->getInternalPath($path.$postFix), $raw);
$result = OC_FileProxy::runPostProxies('hash', $absolutePath, $result); $result = OC_FileProxy::runPostProxies('hash', $absolutePath, $result);
return $result; return $result;
} }
@ -514,35 +521,16 @@ class OC_FilesystemView {
* OC_Filestorage for delegation to a storage backend for execution * OC_Filestorage for delegation to a storage backend for execution
*/ */
private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) { private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) {
$absolutePath = $this->getAbsolutePath($path); $postFix=(substr($path,-1,1)==='/')?'/':'';
$absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path));
if(OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { if(OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) {
$path = $this->getRelativePath($absolutePath); $path = $this->getRelativePath($absolutePath);
if($path == null) { if($path == null) {
return false; return false;
} }
$internalPath = $this->getInternalPath($path); $internalPath = $this->getInternalPath($path.$postFix);
$run = true; $run=$this->runHooks($hooks,$path);
if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { if($run and $storage = $this->getStorage($path.$postFix)) {
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 and $storage = $this->getStorage($path)) {
if(!is_null($extraParam)) { if(!is_null($extraParam)) {
$result = $storage->$operation($internalPath, $extraParam); $result = $storage->$operation($internalPath, $extraParam);
} else { } else {
@ -551,15 +539,7 @@ class OC_FilesystemView {
$result = OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); $result = OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result);
if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) {
if($operation!='fopen') {//no post hooks for fopen, the file stream is still open if($operation!='fopen') {//no post hooks for fopen, the file stream is still open
foreach($hooks as $hook) { $this->runHooks($hooks,$path,true);
if($hook!='read'){
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
'post_'.$hook,
array( OC_Filesystem::signal_param_path => $path)
);
}
}
} }
} }
return $result; return $result;
@ -568,6 +548,34 @@ class OC_FilesystemView {
return null; return null;
} }
private function runHooks($hooks,$path,$post=false){
$prefix=($post)?'post_':'';
$run=true;
if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) {
foreach($hooks as $hook) {
if($hook!='read') {
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
$prefix.$hook,
array(
OC_Filesystem::signal_param_run => &$run,
OC_Filesystem::signal_param_path => $path
)
);
} elseif(!$post) {
OC_Hook::emit(
OC_Filesystem::CLASSNAME,
$prefix.$hook,
array(
OC_Filesystem::signal_param_path => $path
)
);
}
}
}
return $run;
}
/** /**
* check if a file or folder has been updated since $time * check if a file or folder has been updated since $time
* @param int $time * @param int $time

View File

@ -62,6 +62,7 @@ class Test_Filesystem extends UnitTestCase{
public function testNormalize(){ public function testNormalize(){
$this->assertEqual('/path',OC_Filesystem::normalizePath('/path/')); $this->assertEqual('/path',OC_Filesystem::normalizePath('/path/'));
$this->assertEqual('/path/',OC_Filesystem::normalizePath('/path/',false));
$this->assertEqual('/path',OC_Filesystem::normalizePath('path')); $this->assertEqual('/path',OC_Filesystem::normalizePath('path'));
$this->assertEqual('/path',OC_Filesystem::normalizePath('\path')); $this->assertEqual('/path',OC_Filesystem::normalizePath('\path'));
$this->assertEqual('/foo/bar',OC_Filesystem::normalizePath('/foo//bar/')); $this->assertEqual('/foo/bar',OC_Filesystem::normalizePath('/foo//bar/'));