PageRenderTime 57ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/html/modules/system/system.tar.inc

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

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