/libraries/joomla/filesystem/archive/gzip.php

https://github.com/chdemko/joomla-cms · PHP · 193 lines · 107 code · 26 blank · 60 comment · 17 complexity · d6ad70567bb0bf93b6d5aebe9262538a MD5 · raw file

  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage FileSystem
  5. *
  6. * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. /**
  11. * Gzip format adapter for the JArchive class
  12. *
  13. * This class is inspired from and draws heavily in code and concept from the Compress package of
  14. * The Horde Project <http://www.horde.org>
  15. *
  16. * @contributor Michael Slusarz <slusarz@horde.org>
  17. * @contributor Michael Cochrane <mike@graftonhall.co.nz>
  18. *
  19. * @package Joomla.Platform
  20. * @subpackage FileSystem
  21. * @since 11.1
  22. */
  23. class JArchiveGzip extends JObject
  24. {
  25. /**
  26. * Gzip file flags.
  27. *
  28. * @var array
  29. * @since 11.1
  30. */
  31. private $_flags = array('FTEXT' => 0x01, 'FHCRC' => 0x02, 'FEXTRA' => 0x04, 'FNAME' => 0x08, 'FCOMMENT' => 0x10);
  32. /**
  33. * Gzip file data buffer
  34. *
  35. * @var string
  36. * @since 11.1
  37. */
  38. private $_data = null;
  39. /**
  40. * Extract a Gzip compressed file to a given path
  41. *
  42. * @param string $archive Path to ZIP archive to extract
  43. * @param string $destination Path to extract archive to
  44. * @param array $options Extraction options [unused]
  45. *
  46. * @return boolean True if successful
  47. *
  48. * @since 11.1
  49. */
  50. public function extract($archive, $destination, $options = array ())
  51. {
  52. // Initialise variables.
  53. $this->_data = null;
  54. if (!extension_loaded('zlib'))
  55. {
  56. $this->set('error.message', JText::_('JLIB_FILESYSTEM_GZIP_NOT_SUPPORTED'));
  57. return JError::raiseWarning(100, $this->get('error.message'));
  58. }
  59. if (!isset($options['use_streams']) || $options['use_streams'] == false)
  60. {
  61. if (!$this->_data = JFile::read($archive))
  62. {
  63. $this->set('error.message', 'Unable to read archive');
  64. return JError::raiseWarning(100, $this->get('error.message'));
  65. }
  66. $position = $this->_getFilePosition();
  67. $buffer = gzinflate(substr($this->_data, $position, strlen($this->_data) - $position));
  68. if (empty($buffer))
  69. {
  70. $this->set('error.message', 'Unable to decompress data');
  71. return JError::raiseWarning(100, $this->get('error.message'));
  72. }
  73. if (JFile::write($destination, $buffer) === false)
  74. {
  75. $this->set('error.message', 'Unable to write archive');
  76. return JError::raiseWarning(100, $this->get('error.message'));
  77. }
  78. }
  79. else
  80. {
  81. // New style! streams!
  82. $input = JFactory::getStream();
  83. $input->set('processingmethod', 'gz'); // use gz
  84. if (!$input->open($archive))
  85. {
  86. $this->set('error.message', JText::_('JLIB_FILESYSTEM_GZIP_UNABLE_TO_READ'));
  87. return JError::raiseWarning(100, $this->get('error.message'));
  88. }
  89. $output = JFactory::getStream();
  90. if (!$output->open($destination, 'w'))
  91. {
  92. $this->set('error.message', JText::_('JLIB_FILESYSTEM_GZIP_UNABLE_TO_WRITE'));
  93. $input->close(); // close the previous file
  94. return JError::raiseWarning(100, $this->get('error.message'));
  95. }
  96. do
  97. {
  98. $this->_data = $input->read($input->get('chunksize', 8196));
  99. if ($this->_data)
  100. {
  101. if (!$output->write($this->_data))
  102. {
  103. $this->set('error.message', JText::_('JLIB_FILESYSTEM_GZIP_UNABLE_TO_WRITE_FILE'));
  104. return JError::raiseWarning(100, $this->get('error.message'));
  105. }
  106. }
  107. }
  108. while ($this->_data);
  109. $output->close();
  110. $input->close();
  111. }
  112. return true;
  113. }
  114. /**
  115. * Tests whether this adapter can unpack files on this computer.
  116. *
  117. * @return boolean True if supported
  118. *
  119. * @since 11.3
  120. */
  121. public static function isSupported()
  122. {
  123. return extension_loaded('zlib');
  124. }
  125. /**
  126. * Get file data offset for archive
  127. *
  128. * @return integer Data position marker for archive
  129. *
  130. * @since 11.1
  131. */
  132. public function _getFilePosition()
  133. {
  134. // gzipped file... unpack it first
  135. $position = 0;
  136. $info = @ unpack('CCM/CFLG/VTime/CXFL/COS', substr($this->_data, $position + 2));
  137. if (!$info)
  138. {
  139. $this->set('error.message', JText::_('JLIB_FILESYSTEM_GZIP_UNABLE_TO_DECOMPRESS'));
  140. return false;
  141. }
  142. $position += 10;
  143. if ($info['FLG'] & $this->_flags['FEXTRA'])
  144. {
  145. $XLEN = unpack('vLength', substr($this->_data, $position + 0, 2));
  146. $XLEN = $XLEN['Length'];
  147. $position += $XLEN + 2;
  148. }
  149. if ($info['FLG'] & $this->_flags['FNAME'])
  150. {
  151. $filenamePos = strpos($this->_data, "\x0", $position);
  152. $position = $filenamePos + 1;
  153. }
  154. if ($info['FLG'] & $this->_flags['FCOMMENT'])
  155. {
  156. $commentPos = strpos($this->_data, "\x0", $position);
  157. $position = $commentPos + 1;
  158. }
  159. if ($info['FLG'] & $this->_flags['FHCRC'])
  160. {
  161. $hcrc = unpack('vCRC', substr($this->_data, $position + 0, 2));
  162. $hcrc = $hcrc['CRC'];
  163. $position += 2;
  164. }
  165. return $position;
  166. }
  167. }