From 48505c5626a9558ccc825d8b6d85df5d44e9498d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 18 May 2012 01:54:02 +0200 Subject: [PATCH] improve tar archive backend --- apps/files_archive/lib/storage.php | 2 +- apps/files_archive/tests/storage.php | 16 ++++++++- lib/archive/tar.php | 51 +++++++++++++++++++++++++--- tests/lib/filestorage.php | 1 + 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/apps/files_archive/lib/storage.php b/apps/files_archive/lib/storage.php index 086a338db2..b8f7d46838 100644 --- a/apps/files_archive/lib/storage.php +++ b/apps/files_archive/lib/storage.php @@ -89,7 +89,7 @@ class OC_Filestorage_Archive extends OC_Filestorage_Common{ if($path==''){ return file_exists($this->path); } - return $this->archive->fileExists($path) or $this->archive->fileExists($path.'/'); + return $this->archive->fileExists($path); } public function unlink($path){ $path=$this->stripPath($path); diff --git a/apps/files_archive/tests/storage.php b/apps/files_archive/tests/storage.php index 7ebcce4ac6..74ddf22870 100644 --- a/apps/files_archive/tests/storage.php +++ b/apps/files_archive/tests/storage.php @@ -22,4 +22,18 @@ class Test_Filestorage_Archive_Zip extends Test_FileStorage { } } -?> \ No newline at end of file +class Test_Filestorage_Archive_Tar extends Test_FileStorage { + /** + * @var string tmpDir + */ + private $tmpFile; + + public function setUp(){ + $this->tmpFile=OCP\Files::tmpFile('.tar.gz'); + $this->instance=new OC_Filestorage_Archive(array('archive'=>$this->tmpFile)); + } + + public function tearDown(){ + unlink($this->tmpFile); + } +} diff --git a/lib/archive/tar.php b/lib/archive/tar.php index 07f0ba5bd8..4ff7877983 100644 --- a/lib/archive/tar.php +++ b/lib/archive/tar.php @@ -12,6 +12,8 @@ class OC_Archive_TAR extends OC_Archive{ const PLAIN=0; const GZIP=1; const BZIP=2; + + private $fileList; /** * @var Archive_Tar tar @@ -64,6 +66,7 @@ class OC_Archive_TAR extends OC_Archive{ mkdir($tmpBase.$path); $result=$this->tar->addModify(array($tmpBase.$path),'',$tmpBase); rmdir($tmpBase.$path); + $this->fileList=false; return $result; } /** @@ -84,6 +87,7 @@ class OC_Archive_TAR extends OC_Archive{ }else{ $result=$this->tar->addString($path,$source); } + $this->fileList=false; return $result; } @@ -103,12 +107,14 @@ class OC_Archive_TAR extends OC_Archive{ $types=array(null,'gz','bz'); $this->tar=new Archive_Tar($this->path,$types[self::getTarType($this->path)]); $this->tar->createModify(array($tmp),'',$tmp.'/'); + $this->fileList=false; + return true; } private function getHeader($file){ $headers=$this->tar->listContent(); foreach($headers as $header){ - if($file==$header['filename'] or $file.'/'==$header['filename']){ + if($file==$header['filename'] or $file.'/'==$header['filename'] or '/'.$file.'/'==$header['filename'] or '/'.$file==$header['filename']){ return $header; } } @@ -144,9 +150,16 @@ class OC_Archive_TAR extends OC_Archive{ $folderContent=array(); $pathLength=strlen($path); foreach($files as $file){ + if(substr($file,0,1)=='/'){ + $file=substr($file,1); + } if(substr($file,0,$pathLength)==$path and $file!=$path){ - if(strrpos(substr($file,0,-1),'/')<=$pathLength){ - $folderContent[]=substr($file,$pathLength); + $result=substr($file,$pathLength); + if($pos=strpos($result,'/')){ + $result=substr($result,0,$pos+1); + } + if(array_search($result,$folderContent)===false){ + $folderContent[]=$result; } } } @@ -157,11 +170,15 @@ class OC_Archive_TAR extends OC_Archive{ * @return array */ function getFiles(){ + if($this->fileList){ + return $this->fileList; + } $headers=$this->tar->listContent(); $files=array(); foreach($headers as $header){ $files[]=$header['filename']; } + $this->fileList=$files; return $files; } /** @@ -183,7 +200,11 @@ class OC_Archive_TAR extends OC_Archive{ if(!$this->fileExists($path)){ return false; } - $success=$this->tar->extractList(array($path),$tmp); + if($this->fileExists('/'.$path)){ + $success=$this->tar->extractList(array('/'.$path),$tmp); + }else{ + $success=$this->tar->extractList(array($path),$tmp); + } if($success){ rename($tmp.$path,$dest); } @@ -205,7 +226,26 @@ class OC_Archive_TAR extends OC_Archive{ * @return bool */ function fileExists($path){ - return $this->getHeader($path)!==null; + $files=$this->getFiles(); + if((array_search($path,$files)!==false) or (array_search($path.'/',$files)!==false)){ + return true; + }else{ + $folderPath=$path; + if(substr($folderPath,-1,1)!='/'){ + $folderPath.='/'; + } + $pathLength=strlen($folderPath); + foreach($files as $file){ + if(strlen($file)>$pathLength and substr($file,0,$pathLength)==$folderPath){ + return true; + } + } + } + if(substr($path,0,1)!='/'){//not all programs agree on the use of a leading / + return $this->fileExists('/'.$path); + }else{ + return false; + } } /** @@ -217,6 +257,7 @@ class OC_Archive_TAR extends OC_Archive{ if(!$this->fileExists($path)){ return false; } + $this->fileList=false; //no proper way to delete, extract entire archive, delete file and remake archive $tmp=OCP\Files::tmpFolder(); $this->tar->extract($tmp); diff --git a/tests/lib/filestorage.php b/tests/lib/filestorage.php index b58e28cefd..f71b658253 100644 --- a/tests/lib/filestorage.php +++ b/tests/lib/filestorage.php @@ -88,6 +88,7 @@ abstract class Test_FileStorage extends UnitTestCase { //fill a file with string data $this->instance->file_put_contents('/lorem.txt',$sourceText); + $this->assertFalse($this->instance->is_dir('/lorem.txt')); $this->assertEqual($sourceText,$this->instance->file_get_contents('/lorem.txt'),'data returned from file_get_contents is not equal to the source data'); //empty the file