PageRenderTime 84ms CodeModel.GetById 42ms RepoModel.GetById 0ms app.codeStats 1ms

/administrator/components/com_virtuemart/Tar.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 1681 lines | 1249 code | 198 blank | 234 comment | 333 complexity | 12c4de903cceb03e43a0ffaf172ecdd9 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

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

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

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