PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/php/Archive/Tar.php

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

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