PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/tar/Archive_Tar.php

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

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