TYPO3 API  SVNRelease
class.tx_em_tools_unzip.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) Vincent Blavet <vincent@phpconcept.net>
00006  *  (c) 2005-2010 Karsten Dambekalns <karsten@typo3.org>
00007  *  All rights reserved
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License as published by the Free Software Foundation; either
00012  *  version 2.1 of the License, or (at your option) any later version.
00013  *
00014  *  This library is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  *  Lesser General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU Lesser General Public
00020  *  License along with this library; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00022  *  MA  02110-1301  USA
00023  *
00024  *  This copyright notice MUST APPEAR in all copies of the script!
00025  ***************************************************************/
00026 /**
00027  * Module: Extension manager
00028  *
00029  * $Id: class.tx_em_tools_unzip.php 1977 2010-03-09 03:13:20Z mkrause $
00030  *
00031  * @author  Vincent Blavet <vincent@phpconcept.net>
00032  * @author  Karsten Dambekalns <karsten@typo3.org>
00033  */
00034 
00035 
00036 // Constants
00037 define('ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048);
00038 
00039 // File list separator
00040 define('ARCHIVE_ZIP_SEPARATOR', ',');
00041 
00042 define('ARCHIVE_ZIP_TEMPORARY_DIR', '');
00043 
00044 // Error codes
00045 define('ARCHIVE_ZIP_ERR_NO_ERROR', 0);
00046 define('ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1);
00047 define('ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2);
00048 define('ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3);
00049 define('ARCHIVE_ZIP_ERR_MISSING_FILE', -4);
00050 define('ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5);
00051 define('ARCHIVE_ZIP_ERR_INVALID_ZIP', -6);
00052 define('ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7);
00053 define('ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8);
00054 define('ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9);
00055 define('ARCHIVE_ZIP_ERR_BAD_FORMAT', -10);
00056 define('ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11);
00057 define('ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12);
00058 define('ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13);
00059 define('ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14);
00060 define('ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15);
00061 define('ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16);
00062 
00063 // Warning codes
00064 define('ARCHIVE_ZIP_WARN_NO_WARNING', 0);
00065 define('ARCHIVE_ZIP_WARN_FILE_EXIST', 1);
00066 
00067 // Methods parameters
00068 define('ARCHIVE_ZIP_PARAM_PATH', 'path');
00069 define('ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path');
00070 define('ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path');
00071 define('ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path');
00072 define('ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod');
00073 define('ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string');
00074 define('ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression');
00075 
00076 define('ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract');
00077 define('ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract');
00078 define('ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add');
00079 define('ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add');
00080 
00081 
00082 /**
00083  * Class for unpacking zip archive files
00084  *
00085  * @author   Vincent Blavet <vincent@blavet.net>
00086  * @author   Karsten Dambekalns <karsten@typo3.org>
00087  */
00088 class tx_em_Tools_Unzip {
00089     /**
00090      * The filename of the zip archive.
00091      *
00092      * @var string Name of the Zip file
00093      */
00094     var $_zipname = '';
00095 
00096     /**
00097      * File descriptor of the opened Zip file.
00098      *
00099      * @var int Internal zip file descriptor
00100      */
00101     var $_zip_fd = 0;
00102 
00103     /**
00104      * @var int last error code
00105      */
00106     var $_error_code = 1;
00107 
00108     /**
00109      * @var string Last error description
00110      */
00111     var $_error_string = '';
00112 
00113     /**
00114      * tx_em_Tools_Unzip Class constructor. This flavour of the constructor only
00115      * declare a new tx_em_Tools_Unzip object, identifying it by the name of the
00116      * zip file.
00117      *
00118      * @param   string  $p_zipname  The name of the zip archive to create
00119      * @access public
00120      */
00121     public function __construct($p_zipname) {
00122 
00123         // Check the zlib
00124         if (!extension_loaded('zlib')) {
00125             throw new RuntimeException(
00126                 'TYPO3 Fatal Error: ' . "The extension 'zlib' couldn't be found.\n" .
00127                         "Please make sure your version of PHP was built " .
00128                         "with 'zlib' support.\n",
00129                 1270853984
00130             );
00131         }
00132 
00133         // Set the attributes
00134         $this->_zipname = $p_zipname;
00135         $this->_zip_fd = 0;
00136 
00137         return;
00138     }
00139 
00140 
00141     /**
00142      * This method extract the files and folders which are in the zip archive.
00143      * It can extract all the archive or a part of the archive by using filter
00144      * feature (extract by name, by index, by ereg, by preg). The extraction
00145      * can occur in the current path or an other path.
00146      * All the advanced features are activated by the use of variable
00147      * parameters.
00148      * The return value is an array of entry descriptions which gives
00149      * information on extracted files (See listContent()).
00150      * The method may return a success value (an array) even if some files
00151      * are not correctly extracted (see the file status in listContent()).
00152      * The supported variable parameters for this method are :
00153      *   'add_path' : Path where the files and directories are to be extracted
00154      *
00155      * @access public
00156      * @param   mixed  $p_params  An array of variable parameters and values.
00157      * @return mixed An array of file description on success,
00158      *             0 on an unrecoverable failure, an error code is logged.
00159      */
00160     function extract($p_params = 0) {
00161         $this->_errorReset();
00162 
00163         // Check archive
00164         if (!$this->_checkFormat()) {
00165             return (0);
00166         }
00167 
00168         // Set default values
00169         if ($p_params === 0) {
00170             $p_params = array();
00171         }
00172         if ($this->_check_parameters($p_params,
00173             array('extract_as_string' => false,
00174                 'add_path' => '',
00175                 'remove_path' => '',
00176                 'remove_all_path' => false,
00177                 'callback_pre_extract' => '',
00178                 'callback_post_extract' => '',
00179                 'set_chmod' => 0)) != 1) {
00180             return 0;
00181         }
00182 
00183         // Call the extracting fct
00184         $v_list = array();
00185         if ($this->_extractByRule($v_list, $p_params) != 1) {
00186             unset($v_list);
00187             return (0);
00188         }
00189 
00190         return $v_list;
00191     }
00192 
00193     /**
00194      * Method that gives the lastest error code.
00195      *
00196      * @access public
00197      * @return integer The error code value.
00198      */
00199     function errorCode() {
00200         return ($this->_error_code);
00201     }
00202 
00203     /**
00204      * This method gives the latest error code name.
00205      *
00206      * @access public
00207      * @param  boolean $p_with_code  If true, gives the name and the int value.
00208      * @return string The error name.
00209      */
00210     function errorName($p_with_code = false) {
00211         $v_const_list = get_defined_constants();
00212 
00213         // Extract error constants from all const.
00214         for (reset($v_const_list);
00215             list($v_key, $v_value) = each($v_const_list);) {
00216             if (substr($v_key, 0, strlen('ARCHIVE_ZIP_ERR_')) == 'ARCHIVE_ZIP_ERR_') {
00217                 $v_error_list[$v_key] = $v_value;
00218             }
00219         }
00220 
00221         // Search the name form the code value
00222         $v_key = array_search($this->_error_code, $v_error_list, true);
00223         if ($v_key != false) {
00224             $v_value = $v_key;
00225         } else {
00226             $v_value = 'NoName';
00227         }
00228 
00229         if ($p_with_code) {
00230             return ($v_value . ' (' . $this->_error_code . ')');
00231         } else {
00232             return ($v_value);
00233         }
00234     }
00235 
00236     /**
00237      * This method returns the description associated with the latest error.
00238      *
00239      * @access public
00240      * @param  boolean $p_full If set to true gives the description with the
00241      *                       error code, the name and the description.
00242      *                       If set to false gives only the description
00243      *                       and the error code.
00244      * @return string The error description.
00245      */
00246     function errorInfo($p_full = false) {
00247         if ($p_full) {
00248             return ($this->errorName(true) . " : " . $this->_error_string);
00249         } else {
00250             return ($this->_error_string . " [code " . $this->_error_code . "]");
00251         }
00252     }
00253 
00254 
00255     /**
00256      * tx_em_Tools_Unzip::_checkFormat()
00257      *
00258      * { Description }
00259      *
00260      * @param integer $p_level
00261      */
00262     function _checkFormat($p_level = 0) {
00263         $v_result = true;
00264 
00265         // Reset the error handler
00266         $this->_errorReset();
00267 
00268         // Look if the file exits
00269         if (!is_file($this->_zipname)) {
00270             // Error log
00271             $this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE,
00272                     "Missing archive file '" . $this->_zipname . "'");
00273             return (false);
00274         }
00275 
00276         // Check that the file is readeable
00277         if (!is_readable($this->_zipname)) {
00278             // Error log
00279             $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00280                     "Unable to read archive '" . $this->_zipname . "'");
00281             return (false);
00282         }
00283 
00284         // Check the magic code
00285         // TBC
00286 
00287         // Check the central header
00288         // TBC
00289 
00290         // Check each file header
00291         // TBC
00292 
00293         // Return
00294         return $v_result;
00295     }
00296 
00297 
00298     /**
00299      * tx_em_Tools_Unzip::_openFd()
00300      *
00301      * { Description }
00302      *
00303      */
00304     function _openFd($p_mode) {
00305         $v_result = 1;
00306 
00307         // Look if already open
00308         if ($this->_zip_fd != 0) {
00309             $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00310                     'Zip file \'' . $this->_zipname . '\' already open');
00311             return tx_em_Tools_Unzip::errorCode();
00312         }
00313 
00314         // Open the zip file
00315         if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0) {
00316             $this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL,
00317                     'Unable to open archive \'' . $this->_zipname
00318                             . '\' in ' . $p_mode . ' mode');
00319             return tx_em_Tools_Unzip::errorCode();
00320         }
00321 
00322         // Return
00323         return $v_result;
00324     }
00325 
00326     /**
00327      * tx_em_Tools_Unzip::_closeFd()
00328      *
00329      * { Description }
00330      *
00331      */
00332     function _closeFd() {
00333         $v_result = 1;
00334 
00335         if ($this->_zip_fd != 0) {
00336             @fclose($this->_zip_fd);
00337         }
00338         $this->_zip_fd = 0;
00339 
00340         // Return
00341         return $v_result;
00342     }
00343 
00344 
00345     /**
00346      * tx_em_Tools_Unzip::_convertHeader2FileInfo()
00347      *
00348      * { Description }
00349      *
00350      */
00351     function _convertHeader2FileInfo($p_header, &$p_info) {
00352         $v_result = 1;
00353 
00354         // Get the interesting attributes
00355         $p_info['filename'] = $p_header['filename'];
00356         $p_info['stored_filename'] = $p_header['stored_filename'];
00357         $p_info['size'] = $p_header['size'];
00358         $p_info['compressed_size'] = $p_header['compressed_size'];
00359         $p_info['mtime'] = $p_header['mtime'];
00360         $p_info['comment'] = $p_header['comment'];
00361         $p_info['folder'] = (($p_header['external'] & 0x00000010) == 0x00000010);
00362         $p_info['index'] = $p_header['index'];
00363         $p_info['status'] = $p_header['status'];
00364 
00365         // Return
00366         return $v_result;
00367     }
00368 
00369 
00370     // Function : _extractByRule()
00371     // Description :
00372     //   Extract a file or directory depending of rules (by index, by name, ...)
00373     // Parameters :
00374     //   $p_file_list : An array where will be placed the properties of each
00375     //                  extracted file
00376     //   $p_path : Path to add while writing the extracted files
00377     //   $p_remove_path : Path to remove (from the file memorized path) while writing the
00378     //                    extracted files. If the path does not match the file path,
00379     //                    the file is extracted with its memorized path.
00380     //                    $p_remove_path does not apply to 'list' mode.
00381     //                    $p_path and $p_remove_path are commulative.
00382     // Return Values :
00383     //   1 on success,0 or less on error (see error code list)
00384 
00385     /**
00386      * tx_em_Tools_Unzip::_extractByRule()
00387      *
00388      * { Description }
00389      *
00390      */
00391     function _extractByRule(&$p_file_list, &$p_params) {
00392         $v_result = 1;
00393 
00394         $p_path = $p_params['add_path'];
00395         $p_remove_path = $p_params['remove_path'];
00396         $p_remove_all_path = $p_params['remove_all_path'];
00397 
00398         // Check the path
00399         if (($p_path == "")
00400                 || ((substr($p_path, 0, 1) != "/")
00401                         && (substr($p_path, 0, 3) != "../") && (substr($p_path, 1, 2) != ":/"))) {
00402             $p_path = "./" . $p_path;
00403         }
00404 
00405         // Reduce the path last (and duplicated) '/'
00406         if (($p_path != "./") && ($p_path != "/")) {
00407             // Look for the path end '/'
00408             while (substr($p_path, -1) == "/") {
00409                 $p_path = substr($p_path, 0, strlen($p_path) - 1);
00410             }
00411         }
00412 
00413         // Open the zip file
00414         if (($v_result = $this->_openFd('rb')) != 1) {
00415             return $v_result;
00416         }
00417 
00418         // Read the central directory informations
00419         $v_central_dir = array();
00420         if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) {
00421             // Close the zip file
00422             $this->_closeFd();
00423 
00424             return $v_result;
00425         }
00426 
00427         // Start at beginning of Central Dir
00428         $v_pos_entry = $v_central_dir['offset'];
00429 
00430         // Read each entry
00431         $j_start = 0;
00432         for ($i = 0, $v_nb_extracted = 0; $i < $v_central_dir['entries']; $i++) {
00433             // Read next Central dir entry
00434             @rewind($this->_zip_fd);
00435             if (@fseek($this->_zip_fd, $v_pos_entry)) {
00436                 $this->_closeFd();
00437 
00438                 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP,
00439                     'Invalid archive size');
00440 
00441                 return tx_em_Tools_Unzip::errorCode();
00442             }
00443 
00444             // Read the file header
00445             $v_header = array();
00446             if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) {
00447                 $this->_closeFd();
00448 
00449                 return $v_result;
00450             }
00451 
00452             // Store the index
00453             $v_header['index'] = $i;
00454 
00455             // Store the file position
00456             $v_pos_entry = ftell($this->_zip_fd);
00457 
00458 
00459             // Go to the file position
00460             @rewind($this->_zip_fd);
00461             if (@fseek($this->_zip_fd, $v_header['offset'])) {
00462                 // Close the zip file
00463                 $this->_closeFd();
00464 
00465                 // Error log
00466                 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
00467 
00468                 // Return
00469                 return tx_em_Tools_Unzip::errorCode();
00470             }
00471 
00472             // Extracting the file
00473             if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1) {
00474                 // Close the zip file
00475                 $this->_closeFd();
00476 
00477                 return $v_result;
00478             }
00479 
00480             // Get the only interesting attributes
00481             if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
00482                 // Close the zip file
00483                 $this->_closeFd();
00484 
00485                 return $v_result;
00486             }
00487         }
00488 
00489         // Close the zip file
00490         $this->_closeFd();
00491 
00492         // Return
00493         return $v_result;
00494     }
00495 
00496     /**
00497      * tx_em_Tools_Unzip::_extractFile()
00498      *
00499      * { Description }
00500      *
00501      */
00502     function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params) {
00503         $v_result = 1;
00504 
00505         // Read the file header
00506         $v_header = '';
00507         if (($v_result = $this->_readFileHeader($v_header)) != 1) {
00508             // Return
00509             return $v_result;
00510         }
00511 
00512 
00513         // Check that the file header is coherent with $p_entry info
00514         // TBC
00515 
00516         // Look for all path to remove
00517         if ($p_remove_all_path == true) {
00518             // Get the basename of the path
00519             $p_entry['filename'] = basename($p_entry['filename']);
00520         }
00521 
00522             // Look for path to remove
00523         else {
00524             if ($p_remove_path != "") {
00525                 //if (strcmp($p_remove_path, $p_entry['filename'])==0)
00526                 if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2) {
00527 
00528                     // Change the file status
00529                     $p_entry['status'] = "filtered";
00530 
00531                     // Return
00532                     return $v_result;
00533                 }
00534 
00535                 $p_remove_path_size = strlen($p_remove_path);
00536                 if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) {
00537 
00538                     // Remove the path
00539                     $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
00540 
00541                 }
00542             }
00543         }
00544 
00545             // added by TYPO3 secteam to check for invalid paths
00546         if (!t3lib_div::validPathStr($p_entry['filename'])) {
00547                 return $v_result;
00548         }
00549 
00550         // Add the path
00551         if ($p_path != '') {
00552             $p_entry['filename'] = $p_path . "/" . $p_entry['filename'];
00553         }
00554 
00555         // Look for pre-extract callback
00556         if ((isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]))
00557                 && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) {
00558 
00559             // Generate a local information
00560             $v_local_header = array();
00561             $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00562 
00563             // Call the callback
00564             // Here I do not use call_user_func() because I need to send a reference to the
00565             // header.
00566             eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] . '(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);');
00567             if ($v_result == 0) {
00568                 // Change the file status
00569                 $p_entry['status'] = "skipped";
00570                 $v_result = 1;
00571             }
00572 
00573             // Update the informations
00574             // Only some fields can be modified
00575             $p_entry['filename'] = $v_local_header['filename'];
00576         }
00577 
00578         // Trace
00579 
00580         // Look if extraction should be done
00581         if ($p_entry['status'] == 'ok') {
00582 
00583             // Look for specific actions while the file exist
00584             if (file_exists($p_entry['filename'])) {
00585                 // Look if file is a directory
00586                 if (is_dir($p_entry['filename'])) {
00587                     // Change the file status
00588                     $p_entry['status'] = "already_a_directory";
00589 
00590                     // Return
00591                     //return $v_result;
00592                 }
00593                     // Look if file is write protected
00594                 else {
00595                     if (!is_writeable($p_entry['filename'])) {
00596                         // Change the file status
00597                         $p_entry['status'] = "write_protected";
00598 
00599                         // Return
00600                         //return $v_result;
00601                     }
00602 
00603                         // Look if the extracted file is older
00604                     else {
00605                         if (filemtime($p_entry['filename']) > $p_entry['mtime']) {
00606                             // Change the file status
00607                             $p_entry['status'] = "newer_exist";
00608 
00609                             // Return
00610                             //return $v_result;
00611                         }
00612                     }
00613                 }
00614             }
00615 
00616                 // Check the directory availability and create it if necessary
00617             else {
00618                 if ((($p_entry['external'] & 0x00000010) == 0x00000010) || (substr($p_entry['filename'], -1) == '/')) {
00619                     $v_dir_to_check = $p_entry['filename'];
00620                 }
00621                 else {
00622                     if (!strstr($p_entry['filename'], "/")) {
00623                         $v_dir_to_check = "";
00624                     }
00625                     else
00626                     {
00627                         $v_dir_to_check = dirname($p_entry['filename']);
00628                     }
00629                 }
00630 
00631                 if (($v_result = $this->_dirCheck($v_dir_to_check, (($p_entry['external'] & 0x00000010) == 0x00000010))) != 1) {
00632                     // Change the file status
00633                     $p_entry['status'] = "path_creation_fail";
00634 
00635                     // Return
00636                     //return $v_result;
00637                     $v_result = 1;
00638                 }
00639             }
00640         }
00641 
00642         // Look if extraction should be done
00643         if ($p_entry['status'] == 'ok') {
00644             // Do the extraction (if not a folder)
00645             if (!(($p_entry['external'] & 0x00000010) == 0x00000010)) {
00646                 // Look for not compressed file
00647                 if ($p_entry['compressed_size'] == $p_entry['size']) {
00648                     // Opening destination file
00649                     if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00650                         // Change the file status
00651                         $p_entry['status'] = "write_error";
00652 
00653                         // Return
00654                         return $v_result;
00655                     }
00656 
00657 
00658                     // Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks
00659                     $v_size = $p_entry['compressed_size'];
00660                     while ($v_size != 0) {
00661                         $v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
00662                         $v_buffer = fread($this->_zip_fd, $v_read_size);
00663                         $v_binary_data = pack('a' . $v_read_size, $v_buffer);
00664                         @fwrite($v_dest_file, $v_binary_data, $v_read_size);
00665                         $v_size -= $v_read_size;
00666                     }
00667 
00668                     // Closing the destination file
00669                     fclose($v_dest_file);
00670 
00671                     // Change the file mtime
00672                     touch($p_entry['filename'], $p_entry['mtime']);
00673                 } else {
00674                     // Trace
00675 
00676                     // Opening destination file
00677                     if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
00678 
00679                         // Change the file status
00680                         $p_entry['status'] = "write_error";
00681 
00682                         return $v_result;
00683                     }
00684 
00685 
00686                     // Read the compressed file in a buffer (one shot)
00687                     $v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']);
00688 
00689                     // Decompress the file
00690                     $v_file_content = gzinflate($v_buffer);
00691                     unset($v_buffer);
00692 
00693                     // Write the uncompressed data
00694                     @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
00695                     unset($v_file_content);
00696 
00697                     // Closing the destination file
00698                     @fclose($v_dest_file);
00699 
00700                     // Change the file mtime
00701                     @touch($p_entry['filename'], $p_entry['mtime']);
00702                 }
00703 
00704                 // Look for chmod option
00705                 if ((isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]))
00706                         && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) {
00707 
00708                     // Change the mode of the file
00709                     chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]);
00710                 }
00711 
00712             }
00713         }
00714 
00715         // Look for post-extract callback
00716         if ((isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]))
00717                 && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) {
00718 
00719             // Generate a local information
00720             $v_local_header = array();
00721             $this->_convertHeader2FileInfo($p_entry, $v_local_header);
00722 
00723             // Call the callback
00724             // Here I do not use call_user_func() because I need to send a reference to the
00725             // header.
00726             eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] . '(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);');
00727         }
00728 
00729         // Return
00730         return $v_result;
00731     }
00732 
00733     /**
00734      * tx_em_Tools_Unzip::_readFileHeader()
00735      *
00736      * { Description }
00737      *
00738      */
00739     function _readFileHeader(&$p_header) {
00740         $v_result = 1;
00741 
00742         // Read the 4 bytes signature
00743         $v_binary_data = @fread($this->_zip_fd, 4);
00744         $v_data = unpack('Vid', $v_binary_data);
00745 
00746         // Check signature
00747         if ($v_data['id'] != 0x04034b50) {
00748 
00749             // Error log
00750             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00751 
00752             // Return
00753             return tx_em_Tools_Unzip::errorCode();
00754         }
00755 
00756         // Read the first 42 bytes of the header
00757         $v_binary_data = fread($this->_zip_fd, 26);
00758 
00759         // Look for invalid block size
00760         if (strlen($v_binary_data) != 26) {
00761             $p_header['filename'] = "";
00762             $p_header['status'] = "invalid_header";
00763 
00764             // Error log
00765             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : " . strlen($v_binary_data));
00766 
00767             // Return
00768             return tx_em_Tools_Unzip::errorCode();
00769         }
00770 
00771         // Extract the values
00772         $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
00773 
00774         // Get filename
00775         $p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']);
00776 
00777         // Get extra_fields
00778         if ($v_data['extra_len'] != 0) {
00779             $p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']);
00780         }
00781         else {
00782             $p_header['extra'] = '';
00783         }
00784 
00785         // Extract properties
00786         $p_header['compression'] = $v_data['compression'];
00787         $p_header['size'] = $v_data['size'];
00788         $p_header['compressed_size'] = $v_data['compressed_size'];
00789         $p_header['crc'] = $v_data['crc'];
00790         $p_header['flag'] = $v_data['flag'];
00791 
00792         // Recuperate date in UNIX format
00793         $p_header['mdate'] = $v_data['mdate'];
00794         $p_header['mtime'] = $v_data['mtime'];
00795         if ($p_header['mdate'] && $p_header['mtime']) {
00796             // Extract time
00797             $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00798             $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00799             $v_seconde = ($p_header['mtime'] & 0x001F) * 2;
00800 
00801             // Extract date
00802             $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00803             $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00804             $v_day = $p_header['mdate'] & 0x001F;
00805 
00806             // Get UNIX date format
00807             $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00808 
00809         } else {
00810             $p_header['mtime'] = $GLOBALS['EXEC_TIME'];
00811         }
00812 
00813         // Other informations
00814 
00815         // TBC
00816         //for(reset($v_data); $key = key($v_data); next($v_data)) {
00817         //}
00818 
00819         // Set the stored filename
00820         $p_header['stored_filename'] = $p_header['filename'];
00821 
00822         // Set the status field
00823         $p_header['status'] = "ok";
00824 
00825         // Return
00826         return $v_result;
00827     }
00828 
00829     /**
00830      * tx_em_Tools_Unzip::_readCentralFileHeader()
00831      *
00832      * { Description }
00833      *
00834      */
00835     function _readCentralFileHeader(&$p_header) {
00836         $v_result = 1;
00837 
00838         // Read the 4 bytes signature
00839         $v_binary_data = @fread($this->_zip_fd, 4);
00840         $v_data = unpack('Vid', $v_binary_data);
00841 
00842         // Check signature
00843         if ($v_data['id'] != 0x02014b50) {
00844 
00845             // Error log
00846             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
00847 
00848             // Return
00849             return tx_em_Tools_Unzip::errorCode();
00850         }
00851 
00852         // Read the first 42 bytes of the header
00853         $v_binary_data = fread($this->_zip_fd, 42);
00854 
00855         // Look for invalid block size
00856         if (strlen($v_binary_data) != 42) {
00857             $p_header['filename'] = "";
00858             $p_header['status'] = "invalid_header";
00859 
00860             // Error log
00861             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, "Invalid block size : " . strlen($v_binary_data));
00862 
00863             // Return
00864             return tx_em_Tools_Unzip::errorCode();
00865         }
00866 
00867         // Extract the values
00868         $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
00869 
00870         // Get filename
00871         if ($p_header['filename_len'] != 0) {
00872             $p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']);
00873         }
00874         else
00875         {
00876             $p_header['filename'] = '';
00877         }
00878 
00879         // Get extra
00880         if ($p_header['extra_len'] != 0) {
00881             $p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']);
00882         }
00883         else
00884         {
00885             $p_header['extra'] = '';
00886         }
00887 
00888         // Get comment
00889         if ($p_header['comment_len'] != 0) {
00890             $p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']);
00891         }
00892         else
00893         {
00894             $p_header['comment'] = '';
00895         }
00896 
00897         // Extract properties
00898 
00899         // Recuperate date in UNIX format
00900         if ($p_header['mdate'] && $p_header['mtime']) {
00901             // Extract time
00902             $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
00903             $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
00904             $v_seconde = ($p_header['mtime'] & 0x001F) * 2;
00905 
00906             // Extract date
00907             $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
00908             $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
00909             $v_day = $p_header['mdate'] & 0x001F;
00910 
00911             // Get UNIX date format
00912             $p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
00913 
00914         } else {
00915             $p_header['mtime'] = $GLOBALS['EXEC_TIME'];
00916         }
00917 
00918         // Set the stored filename
00919         $p_header['stored_filename'] = $p_header['filename'];
00920 
00921         // Set default status to ok
00922         $p_header['status'] = 'ok';
00923 
00924         // Look if it is a directory
00925         if (substr($p_header['filename'], -1) == '/') {
00926             $p_header['external'] = 0x41FF0010;
00927         }
00928 
00929 
00930         // Return
00931         return $v_result;
00932     }
00933 
00934     /**
00935      * tx_em_Tools_Unzip::_readEndCentralDir()
00936      *
00937      * { Description }
00938      *
00939      */
00940     function _readEndCentralDir(&$p_central_dir) {
00941         $v_result = 1;
00942 
00943         // Go to the end of the zip file
00944         $v_size = filesize($this->_zipname);
00945         @fseek($this->_zip_fd, $v_size);
00946         if (@ftell($this->_zip_fd) != $v_size) {
00947             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00948                     'Unable to go to the end of the archive \''
00949                             . $this->_zipname . '\'');
00950             return tx_em_Tools_Unzip::errorCode();
00951         }
00952 
00953         // First try : look if this is an archive with no commentaries
00954         // (most of the time)
00955         // in this case the end of central dir is at 22 bytes of the file end
00956         $v_found = 0;
00957         if ($v_size > 26) {
00958             @fseek($this->_zip_fd, $v_size - 22);
00959             if (($v_pos = @ftell($this->_zip_fd)) != ($v_size - 22)) {
00960                 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00961                         'Unable to seek back to the middle of the archive \''
00962                                 . $this->_zipname . '\'');
00963                 return tx_em_Tools_Unzip::errorCode();
00964             }
00965 
00966             // Read for bytes
00967             $v_binary_data = @fread($this->_zip_fd, 4);
00968             $v_data = unpack('Vid', $v_binary_data);
00969 
00970             // Check signature
00971             if ($v_data['id'] == 0x06054b50) {
00972                 $v_found = 1;
00973             }
00974 
00975             $v_pos = ftell($this->_zip_fd);
00976         }
00977 
00978         // Go back to the maximum possible size of the Central Dir End Record
00979         if (!$v_found) {
00980             $v_maximum_size = 65557; // 0xFFFF + 22;
00981             if ($v_maximum_size > $v_size) {
00982                 $v_maximum_size = $v_size;
00983             }
00984             @fseek($this->_zip_fd, $v_size - $v_maximum_size);
00985             if (@ftell($this->_zip_fd) != ($v_size - $v_maximum_size)) {
00986                 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
00987                         'Unable to seek back to the middle of the archive \''
00988                                 . $this->_zipname . '\'');
00989                 return tx_em_Tools_Unzip::errorCode();
00990             }
00991 
00992             // Read byte per byte in order to find the signature
00993             $v_pos = ftell($this->_zip_fd);
00994             $v_bytes = 0x00000000;
00995             while ($v_pos < $v_size) {
00996                 // Read a byte
00997                 $v_byte = @fread($this->_zip_fd, 1);
00998 
00999                 //  Add the byte
01000                 $v_bytes = ($v_bytes << 8) | Ord($v_byte);
01001 
01002                 // Compare the bytes
01003                 if ($v_bytes == 0x504b0506) {
01004                     $v_pos++;
01005                     break;
01006                 }
01007 
01008                 $v_pos++;
01009             }
01010 
01011             // Look if not found end of central dir
01012             if ($v_pos == $v_size) {
01013                 $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01014                     "Unable to find End of Central Dir Record signature");
01015                 return tx_em_Tools_Unzip::errorCode();
01016             }
01017         }
01018 
01019         // Read the first 18 bytes of the header
01020         $v_binary_data = fread($this->_zip_fd, 18);
01021 
01022         // Look for invalid block size
01023         if (strlen($v_binary_data) != 18) {
01024             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01025                     "Invalid End of Central Dir Record size : "
01026                             . strlen($v_binary_data));
01027             return tx_em_Tools_Unzip::errorCode();
01028         }
01029 
01030         // Extract the values
01031         $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
01032 
01033         // Check the global size
01034         if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
01035             $this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT,
01036                 "Fail to find the right signature");
01037             return tx_em_Tools_Unzip::errorCode();
01038         }
01039 
01040         // Get comment
01041         if ($v_data['comment_size'] != 0) {
01042             $p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']);
01043         }
01044         else
01045         {
01046             $p_central_dir['comment'] = '';
01047         }
01048 
01049         $p_central_dir['entries'] = $v_data['entries'];
01050         $p_central_dir['disk_entries'] = $v_data['disk_entries'];
01051         $p_central_dir['offset'] = $v_data['offset'];
01052         $p_central_dir['size'] = $v_data['size'];
01053         $p_central_dir['disk'] = $v_data['disk'];
01054         $p_central_dir['disk_start'] = $v_data['disk_start'];
01055 
01056         // Return
01057         return $v_result;
01058     }
01059 
01060     /**
01061      * tx_em_Tools_Unzip::_dirCheck()
01062      *
01063      * { Description }
01064      *
01065      * @param [type] $p_is_dir
01066      */
01067     function _dirCheck($p_dir, $p_is_dir = false) {
01068         $v_result = 1;
01069 
01070         // Remove the final '/'
01071         if (($p_is_dir) && (substr($p_dir, -1) == '/')) {
01072             $p_dir = substr($p_dir, 0, strlen($p_dir) - 1);
01073         }
01074 
01075         // Check the directory availability
01076         if ((is_dir($p_dir)) || ($p_dir == "")) {
01077             return 1;
01078         }
01079 
01080         // Extract parent directory
01081         $p_parent_dir = dirname($p_dir);
01082 
01083         // Just a check
01084         if ($p_parent_dir != $p_dir) {
01085             // Look for parent directory
01086             if ($p_parent_dir != "") {
01087                 if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) {
01088                     return $v_result;
01089                 }
01090             }
01091         }
01092 
01093         // Create the directory
01094         if (!@mkdir($p_dir, 0777)) {
01095             $this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL,
01096                 "Unable to create directory '$p_dir'");
01097             return tx_em_Tools_Unzip::errorCode();
01098         }
01099 
01100         // Return
01101         return $v_result;
01102     }
01103 
01104     /**
01105      * tx_em_Tools_Unzip::_check_parameters()
01106      *
01107      * { Description }
01108      *
01109      * @param integer $p_error_code
01110      * @param string $p_error_string
01111      */
01112     function _check_parameters(&$p_params, $p_default) {
01113 
01114         // Check that param is an array
01115         if (!is_array($p_params)) {
01116             $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01117                 'Unsupported parameter, waiting for an array');
01118             return tx_em_Tools_Unzip::errorCode();
01119         }
01120 
01121         // Check that all the params are valid
01122         for (reset($p_params); list($v_key, $v_value) = each($p_params);) {
01123             if (!isset($p_default[$v_key])) {
01124                 $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER,
01125                         'Unsupported parameter with key \'' . $v_key . '\'');
01126 
01127                 return tx_em_Tools_Unzip::errorCode();
01128             }
01129         }
01130 
01131         // Set the default values
01132         for (reset($p_default); list($v_key, $v_value) = each($p_default);) {
01133             if (!isset($p_params[$v_key])) {
01134                 $p_params[$v_key] = $p_default[$v_key];
01135             }
01136         }
01137 
01138         // Check specific parameters
01139         $v_callback_list = array('callback_pre_add', 'callback_post_add',
01140             'callback_pre_extract', 'callback_post_extract');
01141         for ($i = 0; $i < sizeof($v_callback_list); $i++) {
01142             $v_key = $v_callback_list[$i];
01143             if ((isset($p_params[$v_key])) && ($p_params[$v_key] != '')) {
01144                 if (!function_exists($p_params[$v_key])) {
01145                     $this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE,
01146                             "Callback '" . $p_params[$v_key]
01147                                     . "()' is not an existing function for "
01148                                     . "parameter '" . $v_key . "'");
01149                     return tx_em_Tools_Unzip::errorCode();
01150                 }
01151             }
01152         }
01153 
01154         return (1);
01155     }
01156 
01157     /**
01158      * tx_em_Tools_Unzip::_errorLog()
01159      *
01160      * { Description }
01161      *
01162      * @param integer $p_error_code
01163      * @param string $p_error_string
01164      */
01165     function _errorLog($p_error_code = 0, $p_error_string = '') {
01166         $this->_error_code = $p_error_code;
01167         $this->_error_string = $p_error_string;
01168     }
01169 
01170     /**
01171      * tx_em_Tools_Unzip::_errorReset()
01172      *
01173      * { Description }
01174      *
01175      */
01176     function _errorReset() {
01177         $this->_error_code = 1;
01178         $this->_error_string = '';
01179     }
01180 
01181     /**
01182      * _tool_PathReduction()
01183      *
01184      * { Description }
01185      *
01186      */
01187     function _tool_PathReduction($p_dir) {
01188         $v_result = "";
01189 
01190         // Look for not empty path
01191         if ($p_dir != "") {
01192             // Explode path by directory names
01193             $v_list = explode("/", $p_dir);
01194 
01195             // Study directories from last to first
01196             for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
01197                 // Look for current path
01198                 if ($v_list[$i] == ".") {
01199                     // Ignore this directory
01200                     // Should be the first $i=0, but no check is done
01201                 } else {
01202                     if ($v_list[$i] == "..") {
01203                         // Ignore it and ignore the $i-1
01204                         $i--;
01205                     } else {
01206                         if (($v_list[$i] == "") && ($i != (sizeof($v_list) - 1)) && ($i != 0)) {
01207                             // Ignore only the double '//' in path,
01208                             // but not the first and last '/'
01209                         } else {
01210                             $v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? "/" . $v_result : "");
01211                         }
01212                     }
01213                 }
01214             }
01215         }
01216 
01217         // Return
01218         return $v_result;
01219     }
01220 
01221     /**
01222      * _tool_PathInclusion()
01223      *
01224      * { Description }
01225      *
01226      */
01227     function _tool_PathInclusion($p_dir, $p_path) {
01228         $v_result = 1;
01229 
01230         // Explode dir and path by directory separator
01231         $v_list_dir = explode("/", $p_dir);
01232         $v_list_dir_size = sizeof($v_list_dir);
01233         $v_list_path = explode("/", $p_path);
01234         $v_list_path_size = sizeof($v_list_path);
01235 
01236         // Study directories paths
01237         $i = 0;
01238         $j = 0;
01239         while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
01240             // Look for empty dir (path reduction)
01241             if ($v_list_dir[$i] == '') {
01242                 $i++;
01243                 continue;
01244             }
01245             if ($v_list_path[$j] == '') {
01246                 $j++;
01247                 continue;
01248             }
01249 
01250             // Compare the items
01251             if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ($v_list_path[$j] != '')) {
01252                 $v_result = 0;
01253             }
01254 
01255             // Next items
01256             $i++;
01257             $j++;
01258         }
01259 
01260         // Look if everything seems to be the same
01261         if ($v_result) {
01262             // Skip all the empty items
01263             while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) {
01264                 $j++;
01265             }
01266             while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) {
01267                 $i++;
01268             }
01269 
01270             if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
01271                 // There are exactly the same
01272                 $v_result = 2;
01273             } else {
01274                 if ($i < $v_list_dir_size) {
01275                     // The path is shorter than the dir
01276                     $v_result = 0;
01277                 }
01278             }
01279         }
01280 
01281         // Return
01282         return $v_result;
01283     }
01284 
01285     /**
01286      * _tool_CopyBlock()
01287      *
01288      * { Description }
01289      *
01290      * @param integer $p_mode
01291      */
01292     function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode = 0) {
01293         $v_result = 1;
01294 
01295         if ($p_mode == 0) {
01296             while ($p_size != 0) {
01297                 $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01298                         ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01299                 $v_buffer = @fread($p_src, $v_read_size);
01300                 @fwrite($p_dest, $v_buffer, $v_read_size);
01301                 $p_size -= $v_read_size;
01302             }
01303         } else {
01304             if ($p_mode == 1) {
01305                 while ($p_size != 0) {
01306                     $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01307                             ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01308                     $v_buffer = @gzread($p_src, $v_read_size);
01309                     @fwrite($p_dest, $v_buffer, $v_read_size);
01310                     $p_size -= $v_read_size;
01311                 }
01312             } else {
01313                 if ($p_mode == 2) {
01314                     while ($p_size != 0) {
01315                         $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01316                                 ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01317                         $v_buffer = @fread($p_src, $v_read_size);
01318                         @gzwrite($p_dest, $v_buffer, $v_read_size);
01319                         $p_size -= $v_read_size;
01320                     }
01321                 }
01322                 else {
01323                     if ($p_mode == 3) {
01324                         while ($p_size != 0) {
01325                             $v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE
01326                                     ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE);
01327                             $v_buffer = @gzread($p_src, $v_read_size);
01328                             @gzwrite($p_dest, $v_buffer, $v_read_size);
01329                             $p_size -= $v_read_size;
01330                         }
01331                     }
01332                 }
01333             }
01334         }
01335 
01336         // Return
01337         return $v_result;
01338     }
01339 
01340     /**
01341      * _tool_Rename()
01342      *
01343      * { Description }
01344      *
01345      */
01346     function _tool_Rename($p_src, $p_dest) {
01347         $v_result = 1;
01348 
01349         // Try to rename the files
01350         if (!@rename($p_src, $p_dest)) {
01351 
01352             // Try to copy & unlink the src
01353             if (!@copy($p_src, $p_dest)) {
01354                 $v_result = 0;
01355             } else {
01356                 if (!@unlink($p_src)) {
01357                     $v_result = 0;
01358                 }
01359             }
01360         }
01361 
01362         // Return
01363         return $v_result;
01364     }
01365 
01366     /**
01367      * _tool_TranslateWinPath()
01368      *
01369      * { Description }
01370      *
01371      * @param [type] $p_remove_disk_letter
01372      */
01373     function _tool_TranslateWinPath($p_path, $p_remove_disk_letter = true) {
01374         if (stristr(php_uname(), 'windows')) {
01375             // Look for potential disk letter
01376             if (($p_remove_disk_letter)
01377                     && (($v_position = strpos($p_path, ':')) != false)) {
01378                 $p_path = substr($p_path, $v_position + 1);
01379             }
01380             // Change potential windows directory separator
01381             if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
01382                 $p_path = strtr($p_path, '\\', '/');
01383             }
01384         }
01385         return $p_path;
01386     }
01387 
01388 }
01389 
01390 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/tools/class.tx_em_tools_unzip.php'])) {
01391     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/sysext/em/classes/tools/class.tx_em_tools_unzip.php']);
01392 }
01393 ?>