PageRenderTime 92ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/pear/archive_tar/Archive_Tar.php

https://bitbucket.org/asosso/joomla15
PHP | 1850 lines | 1400 code | 195 blank | 255 comment | 356 complexity | 8fbc2ee7afda44adce338e923c345ad4 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * File::CSV
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * Copyright (c) 1997-2008,
  9. * Vincent Blavet <vincent@phpconcept.net>
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * * Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  27. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  28. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. *
  33. * @category File_Formats
  34. * @package Archive_Tar
  35. * @author Vincent Blavet <vincent@phpconcept.net>
  36. * @copyright 1997-2008 The Authors
  37. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  38. * @version CVS: $Id: Tar.php,v 1.42 2007/08/18 23:04:10 cellog Exp $
  39. * @link http://pear.php.net/package/Archive_Tar
  40. */
  41. // Check to ensure this file is within the rest of the framework
  42. defined('JPATH_BASE') or die();
  43. jimport('pear.PEAR');
  44. define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
  45. define ('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
  46. /**
  47. * Creates a (compressed) Tar archive
  48. *
  49. * @author Vincent Blavet <vincent@phpconcept.net>
  50. * @version $Revision: 1.42 $
  51. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  52. * @package Archive_Tar
  53. */
  54. class Archive_Tar extends PEAR
  55. {
  56. /**
  57. * @var string Name of the Tar
  58. */
  59. var $_tarname='';
  60. /**
  61. * @var boolean if true, the Tar file will be gzipped
  62. */
  63. var $_compress=false;
  64. /**
  65. * @var string Type of compression : 'none', 'gz' or 'bz2'
  66. */
  67. var $_compress_type='none';
  68. /**
  69. * @var string Explode separator
  70. */
  71. var $_separator=' ';
  72. /**
  73. * @var file descriptor
  74. */
  75. var $_file=0;
  76. /**
  77. * @var string Local Tar name of a remote Tar (http:// or ftp://)
  78. */
  79. var $_temp_tarname='';
  80. // {{{ constructor
  81. /**
  82. * Archive_Tar Class constructor. This flavour of the constructor only
  83. * declare a new Archive_Tar object, identifying it by the name of the
  84. * tar file.
  85. * If the compress argument is set the tar will be read or created as a
  86. * gzip or bz2 compressed TAR file.
  87. *
  88. * @param string $p_tarname The name of the tar archive to create
  89. * @param string $p_compress can be null, 'gz' or 'bz2'. This
  90. * parameter indicates if gzip or bz2 compression
  91. * is required. For compatibility reason the
  92. * boolean value 'true' means 'gz'.
  93. * @access public
  94. */
  95. function Archive_Tar($p_tarname, $p_compress = null)
  96. {
  97. $this->PEAR();
  98. $this->_compress = false;
  99. $this->_compress_type = 'none';
  100. if (($p_compress === null) || ($p_compress == '')) {
  101. if (@file_exists($p_tarname)) {
  102. if ($fp = @fopen($p_tarname, "rb")) {
  103. // look for gzip magic cookie
  104. $data = fread($fp, 2);
  105. fclose($fp);
  106. if ($data == "\37\213") {
  107. $this->_compress = true;
  108. $this->_compress_type = 'gz';
  109. // No sure it's enought for a magic code ....
  110. } elseif ($data == "BZ") {
  111. $this->_compress = true;
  112. $this->_compress_type = 'bz2';
  113. }
  114. }
  115. } else {
  116. // probably a remote file or some file accessible
  117. // through a stream interface
  118. if (substr($p_tarname, -2) == 'gz') {
  119. $this->_compress = true;
  120. $this->_compress_type = 'gz';
  121. } elseif ((substr($p_tarname, -3) == 'bz2') ||
  122. (substr($p_tarname, -2) == 'bz')) {
  123. $this->_compress = true;
  124. $this->_compress_type = 'bz2';
  125. }
  126. }
  127. } else {
  128. if (($p_compress === true) || ($p_compress == 'gz')) {
  129. $this->_compress = true;
  130. $this->_compress_type = 'gz';
  131. } else if ($p_compress == 'bz2') {
  132. $this->_compress = true;
  133. $this->_compress_type = 'bz2';
  134. } else {
  135. die("Unsupported compression type '$p_compress'\n".
  136. "Supported types are 'gz' and 'bz2'.\n");
  137. return false;
  138. }
  139. }
  140. $this->_tarname = $p_tarname;
  141. if ($this->_compress) { // assert zlib or bz2 extension support
  142. if ($this->_compress_type == 'gz')
  143. $extname = 'zlib';
  144. else if ($this->_compress_type == 'bz2')
  145. $extname = 'bz2';
  146. if (!extension_loaded($extname)) {
  147. PEAR::loadExtension($extname);
  148. }
  149. if (!extension_loaded($extname)) {
  150. die("The extension '$extname' couldn't be found.\n".
  151. "Please make sure your version of PHP was built ".
  152. "with '$extname' support.\n");
  153. return false;
  154. }
  155. }
  156. }
  157. // }}}
  158. // {{{ destructor
  159. function _Archive_Tar()
  160. {
  161. $this->_close();
  162. // ----- Look for a local copy to delete
  163. if ($this->_temp_tarname != '')
  164. @unlink($this->_temp_tarname);
  165. $this->_PEAR();
  166. }
  167. // }}}
  168. // {{{ create()
  169. /**
  170. * This method creates the archive file and add the files / directories
  171. * that are listed in $p_filelist.
  172. * If a file with the same name exist and is writable, it is replaced
  173. * by the new tar.
  174. * The method return false and a PEAR error text.
  175. * The $p_filelist parameter can be an array of string, each string
  176. * representing a filename or a directory name with their path if
  177. * needed. It can also be a single string with names separated by a
  178. * single blank.
  179. * For each directory added in the archive, the files and
  180. * sub-directories are also added.
  181. * See also createModify() method for more details.
  182. *
  183. * @param array $p_filelist An array of filenames and directory names, or a
  184. * single string with names separated by a single
  185. * blank space.
  186. * @return true on success, false on error.
  187. * @see createModify()
  188. * @access public
  189. */
  190. function create($p_filelist)
  191. {
  192. return $this->createModify($p_filelist, '', '');
  193. }
  194. // }}}
  195. // {{{ add()
  196. /**
  197. * This method add the files / directories that are listed in $p_filelist in
  198. * the archive. If the archive does not exist it is created.
  199. * The method return false and a PEAR error text.
  200. * The files and directories listed are only added at the end of the archive,
  201. * even if a file with the same name is already archived.
  202. * See also createModify() method for more details.
  203. *
  204. * @param array $p_filelist An array of filenames and directory names, or a
  205. * single string with names separated by a single
  206. * blank space.
  207. * @return true on success, false on error.
  208. * @see createModify()
  209. * @access public
  210. */
  211. function add($p_filelist)
  212. {
  213. return $this->addModify($p_filelist, '', '');
  214. }
  215. // }}}
  216. // {{{ extract()
  217. function extract($p_path='')
  218. {
  219. return $this->extractModify($p_path, '');
  220. }
  221. // }}}
  222. // {{{ listContent()
  223. function listContent()
  224. {
  225. $v_list_detail = array();
  226. if ($this->_openRead()) {
  227. if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
  228. unset($v_list_detail);
  229. $v_list_detail = 0;
  230. }
  231. $this->_close();
  232. }
  233. return $v_list_detail;
  234. }
  235. // }}}
  236. // {{{ createModify()
  237. /**
  238. * This method creates the archive file and add the files / directories
  239. * that are listed in $p_filelist.
  240. * If the file already exists and is writable, it is replaced by the
  241. * new tar. It is a create and not an add. If the file exists and is
  242. * read-only or is a directory it is not replaced. The method return
  243. * false and a PEAR error text.
  244. * The $p_filelist parameter can be an array of string, each string
  245. * representing a filename or a directory name with their path if
  246. * needed. It can also be a single string with names separated by a
  247. * single blank.
  248. * The path indicated in $p_remove_dir will be removed from the
  249. * memorized path of each file / directory listed when this path
  250. * exists. By default nothing is removed (empty path '')
  251. * The path indicated in $p_add_dir will be added at the beginning of
  252. * the memorized path of each file / directory listed. However it can
  253. * be set to empty ''. The adding of a path is done after the removing
  254. * of path.
  255. * The path add/remove ability enables the user to prepare an archive
  256. * for extraction in a different path than the origin files are.
  257. * See also addModify() method for file adding properties.
  258. *
  259. * @param array $p_filelist An array of filenames and directory names,
  260. * or a single string with names separated by
  261. * a single blank space.
  262. * @param string $p_add_dir A string which contains a path to be added
  263. * to the memorized path of each element in
  264. * the list.
  265. * @param string $p_remove_dir A string which contains a path to be
  266. * removed from the memorized path of each
  267. * element in the list, when relevant.
  268. * @return boolean true on success, false on error.
  269. * @access public
  270. * @see addModify()
  271. */
  272. function createModify($p_filelist, $p_add_dir, $p_remove_dir='')
  273. {
  274. $v_result = true;
  275. if (!$this->_openWrite())
  276. return false;
  277. if ($p_filelist != '') {
  278. if (is_array($p_filelist))
  279. $v_list = $p_filelist;
  280. elseif (is_string($p_filelist))
  281. $v_list = explode($this->_separator, $p_filelist);
  282. else {
  283. $this->_cleanFile();
  284. $this->_error('Invalid file list');
  285. return false;
  286. }
  287. $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
  288. }
  289. if ($v_result) {
  290. $this->_writeFooter();
  291. $this->_close();
  292. } else
  293. $this->_cleanFile();
  294. return $v_result;
  295. }
  296. // }}}
  297. // {{{ addModify()
  298. /**
  299. * This method add the files / directories listed in $p_filelist at the
  300. * end of the existing archive. If the archive does not yet exists it
  301. * is created.
  302. * The $p_filelist parameter can be an array of string, each string
  303. * representing a filename or a directory name with their path if
  304. * needed. It can also be a single string with names separated by a
  305. * single blank.
  306. * The path indicated in $p_remove_dir will be removed from the
  307. * memorized path of each file / directory listed when this path
  308. * exists. By default nothing is removed (empty path '')
  309. * The path indicated in $p_add_dir will be added at the beginning of
  310. * the memorized path of each file / directory listed. However it can
  311. * be set to empty ''. The adding of a path is done after the removing
  312. * of path.
  313. * The path add/remove ability enables the user to prepare an archive
  314. * for extraction in a different path than the origin files are.
  315. * If a file/dir is already in the archive it will only be added at the
  316. * end of the archive. There is no update of the existing archived
  317. * file/dir. However while extracting the archive, the last file will
  318. * replace the first one. This results in a none optimization of the
  319. * archive size.
  320. * If a file/dir does not exist the file/dir is ignored. However an
  321. * error text is send to PEAR error.
  322. * If a file/dir is not readable the file/dir is ignored. However an
  323. * error text is send to PEAR error.
  324. *
  325. * @param array $p_filelist An array of filenames and directory
  326. * names, or a single string with names
  327. * separated by a single blank space.
  328. * @param string $p_add_dir A string which contains a path to be
  329. * added to the memorized path of each
  330. * element in the list.
  331. * @param string $p_remove_dir A string which contains a path to be
  332. * removed from the memorized path of
  333. * each element in the list, when
  334. * relevant.
  335. * @return true on success, false on error.
  336. * @access public
  337. */
  338. function addModify($p_filelist, $p_add_dir, $p_remove_dir='')
  339. {
  340. $v_result = true;
  341. if (!$this->_isArchive())
  342. $v_result = $this->createModify($p_filelist, $p_add_dir,
  343. $p_remove_dir);
  344. else {
  345. if (is_array($p_filelist))
  346. $v_list = $p_filelist;
  347. elseif (is_string($p_filelist))
  348. $v_list = explode($this->_separator, $p_filelist);
  349. else {
  350. $this->_error('Invalid file list');
  351. return false;
  352. }
  353. $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
  354. }
  355. return $v_result;
  356. }
  357. // }}}
  358. // {{{ addString()
  359. /**
  360. * This method add a single string as a file at the
  361. * end of the existing archive. If the archive does not yet exists it
  362. * is created.
  363. *
  364. * @param string $p_filename A string which contains the full
  365. * filename path that will be associated
  366. * with the string.
  367. * @param string $p_string The content of the file added in
  368. * the archive.
  369. * @return true on success, false on error.
  370. * @access public
  371. */
  372. function addString($p_filename, $p_string)
  373. {
  374. $v_result = true;
  375. if (!$this->_isArchive()) {
  376. if (!$this->_openWrite()) {
  377. return false;
  378. }
  379. $this->_close();
  380. }
  381. if (!$this->_openAppend())
  382. return false;
  383. // Need to check the get back to the temporary file ? ....
  384. $v_result = $this->_addString($p_filename, $p_string);
  385. $this->_writeFooter();
  386. $this->_close();
  387. return $v_result;
  388. }
  389. // }}}
  390. // {{{ extractModify()
  391. /**
  392. * This method extract all the content of the archive in the directory
  393. * indicated by $p_path. When relevant the memorized path of the
  394. * files/dir can be modified by removing the $p_remove_path path at the
  395. * beginning of the file/dir path.
  396. * While extracting a file, if the directory path does not exists it is
  397. * created.
  398. * While extracting a file, if the file already exists it is replaced
  399. * without looking for last modification date.
  400. * While extracting a file, if the file already exists and is write
  401. * protected, the extraction is aborted.
  402. * While extracting a file, if a directory with the same name already
  403. * exists, the extraction is aborted.
  404. * While extracting a directory, if a file with the same name already
  405. * exists, the extraction is aborted.
  406. * While extracting a file/directory if the destination directory exist
  407. * and is write protected, or does not exist but can not be created,
  408. * the extraction is aborted.
  409. * If after extraction an extracted file does not show the correct
  410. * stored file size, the extraction is aborted.
  411. * When the extraction is aborted, a PEAR error text is set and false
  412. * is returned. However the result can be a partial extraction that may
  413. * need to be manually cleaned.
  414. *
  415. * @param string $p_path The path of the directory where the
  416. * files/dir need to by extracted.
  417. * @param string $p_remove_path Part of the memorized path that can be
  418. * removed if present at the beginning of
  419. * the file/dir path.
  420. * @return boolean true on success, false on error.
  421. * @access public
  422. * @see extractList()
  423. */
  424. function extractModify($p_path, $p_remove_path)
  425. {
  426. $v_result = true;
  427. $v_list_detail = array();
  428. if ($v_result = $this->_openRead()) {
  429. $v_result = $this->_extractList($p_path, $v_list_detail,
  430. "complete", 0, $p_remove_path);
  431. $this->_close();
  432. }
  433. return $v_result;
  434. }
  435. // }}}
  436. // {{{ extractInString()
  437. /**
  438. * This method extract from the archive one file identified by $p_filename.
  439. * The return value is a string with the file content, or NULL on error.
  440. * @param string $p_filename The path of the file to extract in a string.
  441. * @return a string with the file content or NULL.
  442. * @access public
  443. */
  444. function extractInString($p_filename)
  445. {
  446. if ($this->_openRead()) {
  447. $v_result = $this->_extractInString($p_filename);
  448. $this->_close();
  449. } else {
  450. $v_result = NULL;
  451. }
  452. return $v_result;
  453. }
  454. // }}}
  455. // {{{ extractList()
  456. /**
  457. * This method extract from the archive only the files indicated in the
  458. * $p_filelist. These files are extracted in the current directory or
  459. * in the directory indicated by the optional $p_path parameter.
  460. * If indicated the $p_remove_path can be used in the same way as it is
  461. * used in extractModify() method.
  462. * @param array $p_filelist An array of filenames and directory names,
  463. * or a single string with names separated
  464. * by a single blank space.
  465. * @param string $p_path The path of the directory where the
  466. * files/dir need to by extracted.
  467. * @param string $p_remove_path Part of the memorized path that can be
  468. * removed if present at the beginning of
  469. * the file/dir path.
  470. * @return true on success, false on error.
  471. * @access public
  472. * @see extractModify()
  473. */
  474. function extractList($p_filelist, $p_path='', $p_remove_path='')
  475. {
  476. $v_result = true;
  477. $v_list_detail = array();
  478. if (is_array($p_filelist))
  479. $v_list = $p_filelist;
  480. elseif (is_string($p_filelist))
  481. $v_list = explode($this->_separator, $p_filelist);
  482. else {
  483. $this->_error('Invalid string list');
  484. return false;
  485. }
  486. if ($v_result = $this->_openRead()) {
  487. $v_result = $this->_extractList($p_path, $v_list_detail, "partial",
  488. $v_list, $p_remove_path);
  489. $this->_close();
  490. }
  491. return $v_result;
  492. }
  493. // }}}
  494. // {{{ setAttribute()
  495. /**
  496. * This method set specific attributes of the archive. It uses a variable
  497. * list of parameters, in the format attribute code + attribute values :
  498. * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
  499. * @param mixed $argv variable list of attributes and values
  500. * @return true on success, false on error.
  501. * @access public
  502. */
  503. function setAttribute()
  504. {
  505. $v_result = true;
  506. // ----- Get the number of variable list of arguments
  507. if (($v_size = func_num_args()) == 0) {
  508. return true;
  509. }
  510. // ----- Get the arguments
  511. $v_att_list = &func_get_args();
  512. // ----- Read the attributes
  513. $i=0;
  514. while ($i<$v_size) {
  515. // ----- Look for next option
  516. switch ($v_att_list[$i]) {
  517. // ----- Look for options that request a string value
  518. case ARCHIVE_TAR_ATT_SEPARATOR :
  519. // ----- Check the number of parameters
  520. if (($i+1) >= $v_size) {
  521. $this->_error('Invalid number of parameters for '
  522. .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
  523. return false;
  524. }
  525. // ----- Get the value
  526. $this->_separator = $v_att_list[$i+1];
  527. $i++;
  528. break;
  529. default :
  530. $this->_error('Unknow attribute code '.$v_att_list[$i].'');
  531. return false;
  532. }
  533. // ----- Next attribute
  534. $i++;
  535. }
  536. return $v_result;
  537. }
  538. // }}}
  539. // {{{ _error()
  540. function _error($p_message)
  541. {
  542. // ----- To be completed
  543. $this->raiseError($p_message);
  544. }
  545. // }}}
  546. // {{{ _warning()
  547. function _warning($p_message)
  548. {
  549. // ----- To be completed
  550. $this->raiseError($p_message);
  551. }
  552. // }}}
  553. // {{{ _isArchive()
  554. function _isArchive($p_filename=NULL)
  555. {
  556. if ($p_filename == NULL) {
  557. $p_filename = $this->_tarname;
  558. }
  559. clearstatcache();
  560. return @is_file($p_filename) && !@is_link($p_filename);
  561. }
  562. // }}}
  563. // {{{ _openWrite()
  564. function _openWrite()
  565. {
  566. if ($this->_compress_type == 'gz')
  567. $this->_file = @gzopen($this->_tarname, "wb9");
  568. else if ($this->_compress_type == 'bz2')
  569. $this->_file = @bzopen($this->_tarname, "w");
  570. else if ($this->_compress_type == 'none')
  571. $this->_file = @fopen($this->_tarname, "wb");
  572. else
  573. $this->_error('Unknown or missing compression type ('
  574. .$this->_compress_type.')');
  575. if ($this->_file == 0) {
  576. $this->_error('Unable to open in write mode \''
  577. .$this->_tarname.'\'');
  578. return false;
  579. }
  580. return true;
  581. }
  582. // }}}
  583. // {{{ _openRead()
  584. function _openRead()
  585. {
  586. if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
  587. // ----- Look if a local copy need to be done
  588. if ($this->_temp_tarname == '') {
  589. $this->_temp_tarname = uniqid('tar').'.tmp';
  590. if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
  591. $this->_error('Unable to open in read mode \''
  592. .$this->_tarname.'\'');
  593. $this->_temp_tarname = '';
  594. return false;
  595. }
  596. if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
  597. $this->_error('Unable to open in write mode \''
  598. .$this->_temp_tarname.'\'');
  599. $this->_temp_tarname = '';
  600. return false;
  601. }
  602. while ($v_data = @fread($v_file_from, 1024))
  603. @fwrite($v_file_to, $v_data);
  604. @fclose($v_file_from);
  605. @fclose($v_file_to);
  606. }
  607. // ----- File to open if the local copy
  608. $v_filename = $this->_temp_tarname;
  609. } else
  610. // ----- File to open if the normal Tar file
  611. $v_filename = $this->_tarname;
  612. if ($this->_compress_type == 'gz')
  613. $this->_file = @gzopen($v_filename, "rb");
  614. else if ($this->_compress_type == 'bz2')
  615. $this->_file = @bzopen($v_filename, "r");
  616. else if ($this->_compress_type == 'none')
  617. $this->_file = @fopen($v_filename, "rb");
  618. else
  619. $this->_error('Unknown or missing compression type ('
  620. .$this->_compress_type.')');
  621. if ($this->_file == 0) {
  622. $this->_error('Unable to open in read mode \''.$v_filename.'\'');
  623. return false;
  624. }
  625. return true;
  626. }
  627. // }}}
  628. // {{{ _openReadWrite()
  629. function _openReadWrite()
  630. {
  631. if ($this->_compress_type == 'gz')
  632. $this->_file = @gzopen($this->_tarname, "r+b");
  633. else if ($this->_compress_type == 'bz2') {
  634. $this->_error('Unable to open bz2 in read/write mode \''
  635. .$this->_tarname.'\' (limitation of bz2 extension)');
  636. return false;
  637. } else if ($this->_compress_type == 'none')
  638. $this->_file = @fopen($this->_tarname, "r+b");
  639. else
  640. $this->_error('Unknown or missing compression type ('
  641. .$this->_compress_type.')');
  642. if ($this->_file == 0) {
  643. $this->_error('Unable to open in read/write mode \''
  644. .$this->_tarname.'\'');
  645. return false;
  646. }
  647. return true;
  648. }
  649. // }}}
  650. // {{{ _close()
  651. function _close()
  652. {
  653. //if (isset($this->_file)) {
  654. if (is_resource($this->_file)) {
  655. if ($this->_compress_type == 'gz')
  656. @gzclose($this->_file);
  657. else if ($this->_compress_type == 'bz2')
  658. @bzclose($this->_file);
  659. else if ($this->_compress_type == 'none')
  660. @fclose($this->_file);
  661. else
  662. $this->_error('Unknown or missing compression type ('
  663. .$this->_compress_type.')');
  664. $this->_file = 0;
  665. }
  666. // ----- Look if a local copy need to be erase
  667. // Note that it might be interesting to keep the url for a time : ToDo
  668. if ($this->_temp_tarname != '') {
  669. @unlink($this->_temp_tarname);
  670. $this->_temp_tarname = '';
  671. }
  672. return true;
  673. }
  674. // }}}
  675. // {{{ _cleanFile()
  676. function _cleanFile()
  677. {
  678. $this->_close();
  679. // ----- Look for a local copy
  680. if ($this->_temp_tarname != '') {
  681. // ----- Remove the local copy but not the remote tarname
  682. @unlink($this->_temp_tarname);
  683. $this->_temp_tarname = '';
  684. } else {
  685. // ----- Remove the local tarname file
  686. @unlink($this->_tarname);
  687. }
  688. $this->_tarname = '';
  689. return true;
  690. }
  691. // }}}
  692. // {{{ _writeBlock()
  693. function _writeBlock($p_binary_data, $p_len=null)
  694. {
  695. if (is_resource($this->_file)) {
  696. if ($p_len === null) {
  697. if ($this->_compress_type == 'gz')
  698. @gzputs($this->_file, $p_binary_data);
  699. else if ($this->_compress_type == 'bz2')
  700. @bzwrite($this->_file, $p_binary_data);
  701. else if ($this->_compress_type == 'none')
  702. @fputs($this->_file, $p_binary_data);
  703. else
  704. $this->_error('Unknown or missing compression type ('
  705. .$this->_compress_type.')');
  706. } else {
  707. if ($this->_compress_type == 'gz')
  708. @gzputs($this->_file, $p_binary_data, $p_len);
  709. else if ($this->_compress_type == 'bz2')
  710. @bzwrite($this->_file, $p_binary_data, $p_len);
  711. else if ($this->_compress_type == 'none')
  712. @fputs($this->_file, $p_binary_data, $p_len);
  713. else
  714. $this->_error('Unknown or missing compression type ('
  715. .$this->_compress_type.')');
  716. }
  717. }
  718. return true;
  719. }
  720. // }}}
  721. // {{{ _readBlock()
  722. function _readBlock()
  723. {
  724. $v_block = null;
  725. if (is_resource($this->_file)) {
  726. if ($this->_compress_type == 'gz')
  727. $v_block = @gzread($this->_file, 512);
  728. else if ($this->_compress_type == 'bz2')
  729. $v_block = @bzread($this->_file, 512);
  730. else if ($this->_compress_type == 'none')
  731. $v_block = @fread($this->_file, 512);
  732. else
  733. $this->_error('Unknown or missing compression type ('
  734. .$this->_compress_type.')');
  735. }
  736. return $v_block;
  737. }
  738. // }}}
  739. // {{{ _jumpBlock()
  740. function _jumpBlock($p_len=null)
  741. {
  742. if (is_resource($this->_file)) {
  743. if ($p_len === null)
  744. $p_len = 1;
  745. if ($this->_compress_type == 'gz') {
  746. @gzseek($this->_file, gztell($this->_file)+($p_len*512));
  747. }
  748. else if ($this->_compress_type == 'bz2') {
  749. // ----- Replace missing bztell() and bzseek()
  750. for ($i=0; $i<$p_len; $i++)
  751. $this->_readBlock();
  752. } else if ($this->_compress_type == 'none')
  753. @fseek($this->_file, ftell($this->_file)+($p_len*512));
  754. else
  755. $this->_error('Unknown or missing compression type ('
  756. .$this->_compress_type.')');
  757. }
  758. return true;
  759. }
  760. // }}}
  761. // {{{ _writeFooter()
  762. function _writeFooter()
  763. {
  764. if (is_resource($this->_file)) {
  765. // ----- Write the last 0 filled block for end of archive
  766. $v_binary_data = pack('a1024', '');
  767. $this->_writeBlock($v_binary_data);
  768. }
  769. return true;
  770. }
  771. // }}}
  772. // {{{ _addList()
  773. function _addList($p_list, $p_add_dir, $p_remove_dir)
  774. {
  775. $v_result=true;
  776. $v_header = array();
  777. // ----- Remove potential windows directory separator
  778. $p_add_dir = $this->_translateWinPath($p_add_dir);
  779. $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
  780. if (!$this->_file) {
  781. $this->_error('Invalid file descriptor');
  782. return false;
  783. }
  784. if (sizeof($p_list) == 0)
  785. return true;
  786. foreach ($p_list as $v_filename) {
  787. if (!$v_result) {
  788. break;
  789. }
  790. // ----- Skip the current tar name
  791. if ($v_filename == $this->_tarname)
  792. continue;
  793. if ($v_filename == '')
  794. continue;
  795. if (!file_exists($v_filename)) {
  796. $this->_warning("File '$v_filename' does not exist");
  797. continue;
  798. }
  799. // ----- Add the file or directory header
  800. if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
  801. return false;
  802. if (@is_dir($v_filename) && !@is_link($v_filename)) {
  803. if (!($p_hdir = opendir($v_filename))) {
  804. $this->_warning("Directory '$v_filename' can not be read");
  805. continue;
  806. }
  807. while (false !== ($p_hitem = readdir($p_hdir))) {
  808. if (($p_hitem != '.') && ($p_hitem != '..')) {
  809. if ($v_filename != ".")
  810. $p_temp_list[0] = $v_filename.'/'.$p_hitem;
  811. else
  812. $p_temp_list[0] = $p_hitem;
  813. $v_result = $this->_addList($p_temp_list,
  814. $p_add_dir,
  815. $p_remove_dir);
  816. }
  817. }
  818. unset($p_temp_list);
  819. unset($p_hdir);
  820. unset($p_hitem);
  821. }
  822. }
  823. return $v_result;
  824. }
  825. // }}}
  826. // {{{ _addFile()
  827. function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
  828. {
  829. if (!$this->_file) {
  830. $this->_error('Invalid file descriptor');
  831. return false;
  832. }
  833. if ($p_filename == '') {
  834. $this->_error('Invalid file name');
  835. return false;
  836. }
  837. // ----- Calculate the stored filename
  838. $p_filename = $this->_translateWinPath($p_filename, false);;
  839. $v_stored_filename = $p_filename;
  840. if (strcmp($p_filename, $p_remove_dir) == 0) {
  841. return true;
  842. }
  843. if ($p_remove_dir != '') {
  844. if (substr($p_remove_dir, -1) != '/')
  845. $p_remove_dir .= '/';
  846. if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir)
  847. $v_stored_filename = substr($p_filename, strlen($p_remove_dir));
  848. }
  849. $v_stored_filename = $this->_translateWinPath($v_stored_filename);
  850. if ($p_add_dir != '') {
  851. if (substr($p_add_dir, -1) == '/')
  852. $v_stored_filename = $p_add_dir.$v_stored_filename;
  853. else
  854. $v_stored_filename = $p_add_dir.'/'.$v_stored_filename;
  855. }
  856. $v_stored_filename = $this->_pathReduction($v_stored_filename);
  857. if ($this->_isArchive($p_filename)) {
  858. if (($v_file = @fopen($p_filename, "rb")) == 0) {
  859. $this->_warning("Unable to open file '".$p_filename
  860. ."' in binary read mode");
  861. return true;
  862. }
  863. if (!$this->_writeHeader($p_filename, $v_stored_filename))
  864. return false;
  865. while (($v_buffer = fread($v_file, 512)) != '') {
  866. $v_binary_data = pack("a512", "$v_buffer");
  867. $this->_writeBlock($v_binary_data);
  868. }
  869. fclose($v_file);
  870. } else {
  871. // ----- Only header for dir
  872. if (!$this->_writeHeader($p_filename, $v_stored_filename))
  873. return false;
  874. }
  875. return true;
  876. }
  877. // }}}
  878. // {{{ _addString()
  879. function _addString($p_filename, $p_string)
  880. {
  881. if (!$this->_file) {
  882. $this->_error('Invalid file descriptor');
  883. return false;
  884. }
  885. if ($p_filename == '') {
  886. $this->_error('Invalid file name');
  887. return false;
  888. }
  889. // ----- Calculate the stored filename
  890. $p_filename = $this->_translateWinPath($p_filename, false);;
  891. if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
  892. time(), 384, "", 0, 0))
  893. return false;
  894. $i=0;
  895. while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
  896. $v_binary_data = pack("a512", $v_buffer);
  897. $this->_writeBlock($v_binary_data);
  898. }
  899. return true;
  900. }
  901. // }}}
  902. // {{{ _writeHeader()
  903. function _writeHeader($p_filename, $p_stored_filename)
  904. {
  905. if ($p_stored_filename == '')
  906. $p_stored_filename = $p_filename;
  907. $v_reduce_filename = $this->_pathReduction($p_stored_filename);
  908. if (strlen($v_reduce_filename) > 99) {
  909. if (!$this->_writeLongHeader($v_reduce_filename))
  910. return false;
  911. }
  912. $v_info = lstat($p_filename);
  913. $v_uid = sprintf("%6s ", DecOct($v_info[4]));
  914. $v_gid = sprintf("%6s ", DecOct($v_info[5]));
  915. $v_perms = sprintf("%6s ", DecOct($v_info['mode']));
  916. $v_mtime = sprintf("%11s", DecOct($v_info['mode']));
  917. $v_linkname = '';
  918. if (@is_link($p_filename)) {
  919. $v_typeflag = '2';
  920. $v_linkname = readlink($p_filename);
  921. $v_size = sprintf("%11s ", DecOct(0));
  922. } elseif (@is_dir($p_filename)) {
  923. $v_typeflag = "5";
  924. $v_size = sprintf("%11s ", DecOct(0));
  925. } else {
  926. $v_typeflag = '';
  927. clearstatcache();
  928. $v_size = sprintf("%11s ", DecOct($v_info['size']));
  929. }
  930. $v_magic = '';
  931. $v_version = '';
  932. $v_uname = '';
  933. $v_gname = '';
  934. $v_devmajor = '';
  935. $v_devminor = '';
  936. $v_prefix = '';
  937. $v_binary_data_first = pack("a100a8a8a8a12A12",
  938. $v_reduce_filename, $v_perms, $v_uid,
  939. $v_gid, $v_size, $v_mtime);
  940. $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
  941. $v_typeflag, $v_linkname, $v_magic,
  942. $v_version, $v_uname, $v_gname,
  943. $v_devmajor, $v_devminor, $v_prefix, '');
  944. // ----- Calculate the checksum
  945. $v_checksum = 0;
  946. // ..... First part of the header
  947. for ($i=0; $i<148; $i++)
  948. $v_checksum += ord(substr($v_binary_data_first,$i,1));
  949. // ..... Ignore the checksum value and replace it by ' ' (space)
  950. for ($i=148; $i<156; $i++)
  951. $v_checksum += ord(' ');
  952. // ..... Last part of the header
  953. for ($i=156, $j=0; $i<512; $i++, $j++)
  954. $v_checksum += ord(substr($v_binary_data_last,$j,1));
  955. // ----- Write the first 148 bytes of the header in the archive
  956. $this->_writeBlock($v_binary_data_first, 148);
  957. // ----- Write the calculated checksum
  958. $v_checksum = sprintf("%6s ", DecOct($v_checksum));
  959. $v_binary_data = pack("a8", $v_checksum);
  960. $this->_writeBlock($v_binary_data, 8);
  961. // ----- Write the last 356 bytes of the header in the archive
  962. $this->_writeBlock($v_binary_data_last, 356);
  963. return true;
  964. }
  965. // }}}
  966. // {{{ _writeHeaderBlock()
  967. function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
  968. $p_type='', $p_uid=0, $p_gid=0)
  969. {
  970. $p_filename = $this->_pathReduction($p_filename);
  971. if (strlen($p_filename) > 99) {
  972. if (!$this->_writeLongHeader($p_filename))
  973. return false;
  974. }
  975. if ($p_type == "5") {
  976. $v_size = sprintf("%11s ", DecOct(0));
  977. } else {
  978. $v_size = sprintf("%11s ", DecOct($p_size));
  979. }
  980. $v_uid = sprintf("%6s ", DecOct($p_uid));
  981. $v_gid = sprintf("%6s ", DecOct($p_gid));
  982. $v_perms = sprintf("%6s ", DecOct($p_perms));
  983. $v_mtime = sprintf("%11s", DecOct($p_mtime));
  984. $v_linkname = '';
  985. $v_magic = '';
  986. $v_version = '';
  987. $v_uname = '';
  988. $v_gname = '';
  989. $v_devmajor = '';
  990. $v_devminor = '';
  991. $v_prefix = '';
  992. $v_binary_data_first = pack("a100a8a8a8a12A12",
  993. $p_filename, $v_perms, $v_uid, $v_gid,
  994. $v_size, $v_mtime);
  995. $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
  996. $p_type, $v_linkname, $v_magic,
  997. $v_version, $v_uname, $v_gname,
  998. $v_devmajor, $v_devminor, $v_prefix, '');
  999. // ----- Calculate the checksum
  1000. $v_checksum = 0;
  1001. // ..... First part of the header
  1002. for ($i=0; $i<148; $i++)
  1003. $v_checksum += ord(substr($v_binary_data_first,$i,1));
  1004. // ..... Ignore the checksum value and replace it by ' ' (space)
  1005. for ($i=148; $i<156; $i++)
  1006. $v_checksum += ord(' ');
  1007. // ..... Last part of the header
  1008. for ($i=156, $j=0; $i<512; $i++, $j++)
  1009. $v_checksum += ord(substr($v_binary_data_last,$j,1));
  1010. // ----- Write the first 148 bytes of the header in the archive
  1011. $this->_writeBlock($v_binary_data_first, 148);
  1012. // ----- Write the calculated checksum
  1013. $v_checksum = sprintf("%6s ", DecOct($v_checksum));
  1014. $v_binary_data = pack("a8", $v_checksum);
  1015. $this->_writeBlock($v_binary_data, 8);
  1016. // ----- Write the last 356 bytes of the header in the archive
  1017. $this->_writeBlock($v_binary_data_last, 356);
  1018. return true;
  1019. }
  1020. // }}}
  1021. // {{{ _writeLongHeader()
  1022. function _writeLongHeader($p_filename)
  1023. {
  1024. $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
  1025. $v_typeflag = 'L';
  1026. $v_linkname = '';
  1027. $v_magic = '';
  1028. $v_version = '';
  1029. $v_uname = '';
  1030. $v_gname = '';
  1031. $v_devmajor = '';
  1032. $v_devminor = '';
  1033. $v_prefix = '';
  1034. $v_binary_data_first = pack("a100a8a8a8a12A12",
  1035. '././@LongLink', 0, 0, 0, $v_size, 0);
  1036. $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
  1037. $v_typeflag, $v_linkname, $v_magic,
  1038. $v_version, $v_uname, $v_gname,
  1039. $v_devmajor, $v_devminor, $v_prefix, '');
  1040. // ----- Calculate the checksum
  1041. $v_checksum = 0;
  1042. // ..... First part of the header
  1043. for ($i=0; $i<148; $i++)
  1044. $v_checksum += ord(substr($v_binary_data_first,$i,1));
  1045. // ..... Ignore the checksum value and replace it by ' ' (space)
  1046. for ($i=148; $i<156; $i++)
  1047. $v_checksum += ord(' ');
  1048. // ..... Last part of the header
  1049. for ($i=156, $j=0; $i<512; $i++, $j++)
  1050. $v_checksum += ord(substr($v_binary_data_last,$j,1));
  1051. // ----- Write the first 148 bytes of the header in the archive
  1052. $this->_writeBlock($v_binary_data_first, 148);
  1053. // ----- Write the calculated checksum
  1054. $v_checksum = sprintf("%6s ", DecOct($v_checksum));
  1055. $v_binary_data = pack("a8", $v_checksum);
  1056. $this->_writeBlock($v_binary_data, 8);
  1057. // ----- Write the last 356 bytes of the header in the archive
  1058. $this->_writeBlock($v_binary_data_last, 356);
  1059. // ----- Write the filename as content of the block
  1060. $i=0;
  1061. while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') {
  1062. $v_binary_data = pack("a512", "$v_buffer");
  1063. $this->_writeBlock($v_binary_data);
  1064. }
  1065. return true;
  1066. }
  1067. // }}}
  1068. // {{{ _readHeader()
  1069. function _readHeader($v_binary_data, &$v_header)
  1070. {
  1071. if (strlen($v_binary_data)==0) {
  1072. $v_header['filename'] = '';
  1073. return true;
  1074. }
  1075. if (strlen($v_binary_data) != 512) {
  1076. $v_header['filename'] = '';
  1077. $this->_error('Invalid block size : '.strlen($v_binary_data));
  1078. return false;
  1079. }
  1080. if (!is_array($v_header)) {
  1081. $v_header = array();
  1082. }
  1083. // ----- Calculate the checksum
  1084. $v_checksum = 0;
  1085. // ..... First part of the header
  1086. for ($i=0; $i<148; $i++)
  1087. $v_checksum+=ord(substr($v_binary_data,$i,1));
  1088. // ..... Ignore the checksum value and replace it by ' ' (space)
  1089. for ($i=148; $i<156; $i++)
  1090. $v_checksum += ord(' ');
  1091. // ..... Last part of the header
  1092. for ($i=156; $i<512; $i++)
  1093. $v_checksum+=ord(substr($v_binary_data,$i,1));
  1094. $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
  1095. ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
  1096. ."a32uname/a32gname/a8devmajor/a8devminor",
  1097. $v_binary_data);
  1098. // ----- Extract the checksum
  1099. $v_header['checksum'] = OctDec(trim($v_data['checksum']));
  1100. if ($v_header['checksum'] != $v_checksum) {
  1101. $v_header['filename'] = '';
  1102. // ----- Look for last block (empty block)
  1103. if (($v_checksum == 256) && ($v_header['checksum'] == 0))
  1104. return true;
  1105. $this->_error('Invalid checksum for file "'.$v_data['filename']
  1106. .'" : '.$v_checksum.' calculated, '
  1107. .$v_header['checksum'].' expected');
  1108. return false;
  1109. }
  1110. // ----- Extract the properties
  1111. $v_header['filename'] = trim($v_data['filename']);
  1112. if ($this->_maliciousFilename($v_header['filename'])) {
  1113. $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
  1114. '" will not install in desired directory tree');
  1115. return false;
  1116. }
  1117. $v_header['mode'] = OctDec(trim($v_data['mode']));
  1118. $v_header['uid'] = OctDec(trim($v_data['uid']));
  1119. $v_header['gid'] = OctDec(trim($v_data['gid']));
  1120. $v_header['size'] = OctDec(trim($v_data['size']));
  1121. $v_header['mtime'] = OctDec(trim($v_data['mtime']));
  1122. if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
  1123. $v_header['size'] = 0;
  1124. }
  1125. $v_header['link'] = trim($v_data['link']);
  1126. /* ----- All these fields are removed form the header because
  1127. they do not carry interesting info
  1128. $v_header[magic] = trim($v_data[magic]);
  1129. $v_header[version] = trim($v_data[version]);
  1130. $v_header[uname] = trim($v_data[uname]);
  1131. $v_header[gname] = trim($v_data[gname]);
  1132. $v_header[devmajor] = trim($v_data[devmajor]);
  1133. $v_header[devminor] = trim($v_data[devminor]);
  1134. */
  1135. return true;
  1136. }
  1137. // }}}
  1138. // {{{ _maliciousFilename()
  1139. /**
  1140. * Detect and report a malicious file name
  1141. *
  1142. * @param string $file
  1143. * @return bool
  1144. * @access private
  1145. */
  1146. function _maliciousFilename($file)
  1147. {
  1148. if (strpos($file, '/../') !== false) {
  1149. return true;
  1150. }
  1151. if (strpos($file, '../') === 0) {
  1152. return true;
  1153. }
  1154. return false;
  1155. }
  1156. // }}}
  1157. // {{{ _readLongHeader()
  1158. function _readLongHeader(&$v_header)
  1159. {
  1160. $v_filename = '';
  1161. $n = floor($v_header['size']/512);
  1162. for ($i=0; $i<$n; $i++) {
  1163. $v_content = $this->_readBlock();
  1164. $v_filename .= $v_content;
  1165. }
  1166. if (($v_header['size'] % 512) != 0) {
  1167. $v_content = $this->_readBlock();
  1168. $v_filename .= $v_content;
  1169. }
  1170. // ----- Read the next header
  1171. $v_binary_data = $this->_readBlock();
  1172. if (!$this->_readHeader($v_binary_data, $v_header))
  1173. return false;
  1174. $v_filename = trim($v_filename);
  1175. $v_header['filename'] = $v_filename;
  1176. if ($this->_maliciousFilename($v_filename)) {
  1177. $this->_error('Malicious .tar detected, file "' . $v_filename .
  1178. '" will not install in desired directory tree');
  1179. return false;
  1180. }
  1181. return true;
  1182. }
  1183. // }}}
  1184. // {{{ _extractInString()
  1185. /**
  1186. * This method extract from the archive one file identified by $p_filename.
  1187. * The return value is a string with the file content, or NULL on error.
  1188. * @param string $p_filename The path of the file to extract in a string.
  1189. * @return a string with the file content or NULL.
  1190. * @access private
  1191. */
  1192. function _extractInString($p_filename)
  1193. {
  1194. $v_result_str = "";
  1195. While (strlen($v_binary_data = $this->_readBlock()) != 0)
  1196. {
  1197. if (!$this->_readHeader($v_binary_data, $v_header))
  1198. return NULL;
  1199. if ($v_header['filename'] == '')
  1200. continue;
  1201. // ----- Look for long filename
  1202. if ($v_header['typeflag'] == 'L') {
  1203. if (!$this->_readLongHeader($v_header))
  1204. return NULL;
  1205. }
  1206. if ($v_header['filename'] == $p_filename) {
  1207. if ($v_header['typeflag'] == "5") {
  1208. $this->_error('Unable to extract in string a directory '
  1209. .'entry {'.$v_header['filename'].'}');
  1210. return NULL;
  1211. } else {
  1212. $n = floor($v_header['size']/512);
  1213. for ($i=0; $i<$n; $i++) {
  1214. $v_result_str .= $this->_readBlock();
  1215. }
  1216. if (($v_header['size'] % 512) != 0) {
  1217. $v_content = $this->_readBlock();
  1218. $v_result_str .= substr($v_content, 0,
  1219. ($v_header['size'] % 512));
  1220. }
  1221. return $v_result_str;
  1222. }
  1223. } else {
  1224. $this->_jumpBlock(ceil(($v_header['size']/512)));
  1225. }
  1226. }
  1227. return NULL;
  1228. }
  1229. // }}}
  1230. // {{{ _extractList()
  1231. function _extractList($p_path, &$p_list_detail, $p_mode,
  1232. $p_file_list, $p_remove_path)
  1233. {
  1234. $v_result=true;
  1235. $v_nb = 0;
  1236. $v_extract_all = true;
  1237. $v_listing = false;
  1238. $p_path = $this->_translateWinPath($p_path, false);
  1239. if ($p_path == '' || (substr($p_path, 0, 1) != '/'
  1240. && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
  1241. $p_path = "./".$p_path;
  1242. }
  1243. $p_remove_path = $this->_translateWinPath($p_remove_path);
  1244. // ----- Look for path to remove format (should end by /)
  1245. if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/'))
  1246. $p_remove_path .= '/';
  1247. $p_remove_path_size = strlen($p_remove_path);
  1248. switch ($p_mode) {
  1249. case "complete" :
  1250. $v_extract_all = TRUE;
  1251. $v_listing = FALSE;
  1252. break;
  1253. case "partial" :
  1254. $v_extract_all = FALSE;
  1255. $v_listing = FALSE;
  1256. break;
  1257. case "list" :
  1258. $v_extract_all = FALSE;
  1259. $v_listing = TRUE;
  1260. break;
  1261. default :
  1262. $this->_error('Invalid extract mode ('.$p_mode.')');
  1263. return false;
  1264. }
  1265. clearstatcache();
  1266. while (strlen($v_binary_data = $this->_readBlock()) != 0)
  1267. {
  1268. $v_extract_file = FALSE;
  1269. $v_extraction_stopped = 0;
  1270. if (!$this->_readHeader($v_binary_data, $v_header))
  1271. return false;
  1272. if ($v_header['filename'] == '') {
  1273. continue;
  1274. }
  1275. // ----- Look for long filename
  1276. if ($v_header['typeflag'] == 'L') {
  1277. if (!$this->_readLongHeader($v_header))
  1278. return false;
  1279. }
  1280. if ((!$v_extract_all) && (is_array($p_file_list))) {
  1281. // ----- By default no unzip if the file is not found
  1282. $v_extract_file = false;

Large files files are truncated, but you can click here to view the full file