Adding IArchive interface
authorTim Düsterhus <timwolla@arcor.de>
Fri, 11 May 2012 12:59:45 +0000 (14:59 +0200)
committerTim Düsterhus <timwolla@arcor.de>
Fri, 11 May 2012 12:59:45 +0000 (14:59 +0200)
wcfsetup/install/files/lib/system/io/IArchive.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/io/Tar.class.php
wcfsetup/install/files/lib/system/io/Zip.class.php

diff --git a/wcfsetup/install/files/lib/system/io/IArchive.class.php b/wcfsetup/install/files/lib/system/io/IArchive.class.php
new file mode 100644 (file)
index 0000000..259db55
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+namespace wcf\system\io;
+
+/**
+ * Represents an archive of files.
+ * 
+ * @author     Tim Düsterhus
+ * @copyright  2012 Tim Düsterhus
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    com.woltlab.wcf
+ * @subpackage system.io
+ * @category   Community Framework
+ */
+interface IArchive {
+       /**
+        * Returns an associative array with information
+        * about a specific file in the archive.
+        *
+        * @param       mixed   $index  index or name of the requested file
+        * @return      array
+        */
+       public function getFileInfo($index);
+       
+       /**
+        * Extracts a specific file and returns the content as string.
+        * Returns false if extraction failed.
+        * 
+        * @param       mixed           $index          index or name of the requested file
+        * @return      string                          content of the requested file
+        */
+       public function extractToString($index);
+       
+       /**
+        * Extracts a specific file and writes it's content
+        * to the file specified with $destination.
+        * 
+        * @param       mixed           $index          index or name of the requested file
+        * @param       string          $destination
+        * @return      boolean         $success
+        */
+       public function extract($index, $destination);
+       
+       /**
+        * Searchs a file in the tar archive
+        * and returns the numeric fileindex.
+        * Returns false if not found.
+        *
+        * @param       string          $filename
+        * @return      integer                         index of the requested file
+        */
+       public function getIndexByFilename($filename);
+}
index 0ef0b1006db9e57661e899000c8c9bb0199896f3..99a8fa0f6095467a740febdf9a9caef3b83fef0b 100644 (file)
@@ -21,7 +21,7 @@ use wcf\util\FileUtil;
  * @subpackage system.io
  * @category   Community Framework
  */
-class Tar {
+class Tar implements IArchive {
        /**
         * name of the archive
         * @var string
@@ -309,7 +309,7 @@ class Tar {
                if (strlen($binaryData) != 512) {
                        return false;   
                }
-
+               
                $header = array();
                $checksum = 0;
                // First part of the header
@@ -325,7 +325,7 @@ class Tar {
                for ($i = 156; $i < 512; $i++) {
                        $checksum += ord(substr($binaryData, $i, 1));
                }
-
+               
                // Extract the values
                //$data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $binaryData);
                $data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor/a155prefix", $binaryData);
index 26aa7b8c3276cb9334501633644ceba428c690a0..59b9a4810ce23c6967eaaf65bcd57233350011ec 100644 (file)
@@ -13,7 +13,7 @@ use wcf\util\FileUtil;
  * @subpackage system.io
  * @category   Community Framework
  */
-class Zip extends File {
+class Zip extends File implements IArchive {
        const LOCAL_FILE_SIGNATURE = "\x50\x4b\x03\x04";
        const CENTRAL_DIRECTORY_SIGNATURE = "\x50\x4b\x01\x02";
        const EOF_SIGNATURE = "\x50\x4b\x05\x06";
@@ -26,12 +26,9 @@ class Zip extends File {
        }
        
        /**
-        * Returns the offset for the given file and false of failure.
-        * 
-        * @param       string  $filename       file to search
-        * @return      mixed
+        * @see wcf\system\io\IArchive::getIndexByFilename()
         */
-       public function getOffsetByFilename($filename) {
+       public function getIndexByFilename($filename) {
                $this->jumpToCentralDirectory();
                $centralDirectory = $this->readCentralDirectory();
                
@@ -39,6 +36,16 @@ class Zip extends File {
                return false;
        }
        
+       /**
+        * @see wcf\system\io\IArchive::getFileInfo()
+        */
+       public function getFileInfo($offset) {
+               if (!is_int($offset)) $offset = $this->getIndexByFilename($offset);
+               
+               $info = $this->readFile($offset);
+               return $info['header'];
+       }
+       
        /**
         * Extracts all files to the given destination.
         * The directory-structure inside the .zip is preserved.
@@ -53,36 +60,41 @@ class Zip extends File {
                        $offset = $this->tell();
                        $file = $this->readFile();
                        $filename = $file['header']['filename'];
-                       $this->extract($offset, $destination.dirname($filename));
+                       $this->extract($offset, $destination.$filename);
                }
        }
        
        /**
-        * Extracts the file at the given offset to a string.
-        * 
-        * @param       integer         $offset         The offset to extract
-        * @return      string
+        * @see wcf\system\io\IArchive::extractToString()
         */
        public function extractToString($offset) {
-               $file = $this->readFile($offset);
+               if (!is_int($offset)) $offset = $this->getIndexByFilename($offset);
+               
+               try {
+                       $file = $this->readFile($offset);
+               }
+               catch (SystemException $e) {
+                       return false;
+               }
                
                return $file['content'];
        }
        
        /**
-        * Extracts the file at the given offset to the given destination.
-        * The directory-structure inside the .zip is ignored.
-        *
-        * @param       integer         $offset         The offset to extract
-        * @param       string          $destination    Where to extract
-        * @param       string          $filename       The filename. When not given the original filename is used
+        * @see wcf\system\io\IArchive::extract()
         */
-       public function extract($offset, $destination, $filename = null) {
-               $file = $this->readFile($offset);
-               $filename = ($filename ?: $file['header']['filename']);
+       public function extract($offset, $destination) {
+               if (!is_int($offset)) $offset = $this->getIndexByFilename($offset);
                
-               FileUtil::makePath($destination);
-               $targetFile = new File(FileUtil::addTrailingSlash($destination).basename($filename));
+               try {
+                       $file = $this->readFile($offset);
+               }
+               catch (SystemException $e) {
+                       return false;
+               }
+               
+               FileUtil::makePath(dirname($destination));
+               $targetFile = new File($destination);
                $targetFile->write($file['content'], strlen($file['content']));
                $targetFile->close();
                
@@ -98,9 +110,11 @@ class Zip extends File {
                }
                
                // check filesize
-               if (filesize(FileUtil::addTrailingSlash($destination).basename($filename)) != $file['header']['uncompressedSize']) {
-                       throw new SystemException("Could not unzip file '".$file['header']['filename']."' to '".FileUtil::addTrailingSlash($destination).basename($filename)."'. Maybe disk quota exceeded in folder '".$destination."'.");
+               if (filesize($destination) != $file['header']['uncompressedSize']) {
+                       throw new SystemException("Could not unzip file '".$file['header']['filename']."' to '".$destination."'. Maybe disk quota exceeded in folder '".dirname($destination)."'.");
                }
+               
+               return true;
        }
        
        /**
@@ -125,6 +139,7 @@ class Zip extends File {
         */
        public function readCentralDirectory($offset = null) {
                if ($offset === null) $offset = $this->tell();
+               if ($offset === false) throw new SystemException('Invalid offset passed to readCentralDirectory');
                
                $this->seek($offset);
                // check signature
@@ -184,6 +199,7 @@ class Zip extends File {
         */
        public function isFile($offset = null) {
                if ($offset === null) $offset = $this->tell();
+               if ($offset === false) throw new SystemException('Invalid offset passed to isFile');
                
                $oldOffset = $this->tell();
                $this->seek($offset);
@@ -201,6 +217,8 @@ class Zip extends File {
         */
        public function skipFile($offset = null) {
                if ($offset === null) $offset = $this->tell();
+               if (!is_int($offset)) $offset = $this->getIndexByFilename($offset);
+               if ($offset === false) throw new SystemException('Invalid offset passed to skipFile');
                
                $this->seek($offset);
                // check signature
@@ -229,6 +247,8 @@ class Zip extends File {
         */
        public function readFile($offset = null) {
                if ($offset === null) $offset = $this->tell();
+               if (!is_int($offset)) $offset = $this->getIndexByFilename($offset);
+               if ($offset === false) throw new SystemException('Invalid offset passed to readFile');
                
                $this->seek($offset);
                // check signature