|
TYPO3 API
SVNRelease
|
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 ?>
1.8.0