Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
gzip.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Archive
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 jimport('joomla.filesystem.file');
13 
14 /**
15  * Gzip format adapter for the JArchive class
16  *
17  * This class is inspired from and draws heavily in code and concept from the Compress package of
18  * The Horde Project <http://www.horde.org>
19  *
20  * @contributor Michael Slusarz <slusarz@horde.org>
21  * @contributor Michael Cochrane <mike@graftonhall.co.nz>
22  *
23  * @package Joomla.Platform
24  * @subpackage Archive
25  * @since 11.1
26  */
28 {
29  /**
30  * Gzip file flags.
31  *
32  * @var array
33  * @since 11.1
34  */
35  private $_flags = array('FTEXT' => 0x01, 'FHCRC' => 0x02, 'FEXTRA' => 0x04, 'FNAME' => 0x08, 'FCOMMENT' => 0x10);
36 
37  /**
38  * Gzip file data buffer
39  *
40  * @var string
41  * @since 11.1
42  */
43  private $_data = null;
44 
45  /**
46  * Extract a Gzip compressed file to a given path
47  *
48  * @param string $archive Path to ZIP archive to extract
49  * @param string $destination Path to extract archive to
50  * @param array $options Extraction options [unused]
51  *
52  * @return boolean True if successful
53  *
54  * @since 11.1
55  * @throws RuntimeException
56  */
57  public function extract($archive, $destination, array $options = array ())
58  {
59  $this->_data = null;
60 
61  if (!extension_loaded('zlib'))
62  {
63  if (class_exists('JError'))
64  {
65  return JError::raiseWarning(100, 'The zlib extension is not available.');
66  }
67  else
68  {
69  throw new RuntimeException('The zlib extension is not available.');
70  }
71  }
72 
73  if (!isset($options['use_streams']) || $options['use_streams'] == false)
74  {
75  $this->_data = file_get_contents($archive);
76 
77  if (!$this->_data)
78  {
79  if (class_exists('JError'))
80  {
81  return JError::raiseWarning(100, 'Unable to read archive');
82  }
83  else
84  {
85  throw new RuntimeException('Unable to read archive');
86  }
87  }
88 
89  $position = $this->_getFilePosition();
90  $buffer = gzinflate(substr($this->_data, $position, strlen($this->_data) - $position));
91 
92  if (empty($buffer))
93  {
94  if (class_exists('JError'))
95  {
96  return JError::raiseWarning(100, 'Unable to decompress data');
97  }
98  else
99  {
100  throw new RuntimeException('Unable to decompress data');
101  }
102  }
103 
104  if (JFile::write($destination, $buffer) === false)
105  {
106  if (class_exists('JError'))
107  {
108  return JError::raiseWarning(100, 'Unable to write archive');
109  }
110  else
111  {
112  throw new RuntimeException('Unable to write archive');
113  }
114  }
115  }
116  else
117  {
118  // New style! streams!
119  $input = JFactory::getStream();
120 
121  // Use gz
122  $input->set('processingmethod', 'gz');
123 
124  if (!$input->open($archive))
125  {
126  if (class_exists('JError'))
127  {
128  return JError::raiseWarning(100, 'Unable to read archive (gz)');
129  }
130  else
131  {
132  throw new RuntimeException('Unable to read archive (gz)');
133  }
134  }
135 
136  $output = JFactory::getStream();
137 
138  if (!$output->open($destination, 'w'))
139  {
140  $input->close();
141 
142  if (class_exists('JError'))
143  {
144  return JError::raiseWarning(100, 'Unable to write archive (gz)');
145  }
146  else
147  {
148  throw new RuntimeException('Unable to write archive (gz)');
149  }
150  }
151 
152  do
153  {
154  $this->_data = $input->read($input->get('chunksize', 8196));
155 
156  if ($this->_data)
157  {
158  if (!$output->write($this->_data))
159  {
160  $input->close();
161 
162  if (class_exists('JError'))
163  {
164  return JError::raiseWarning(100, 'Unable to write file (gz)');
165  }
166  else
167  {
168  throw new RuntimeException('Unable to write file (gz)');
169  }
170  }
171  }
172  }
173  while ($this->_data);
174 
175  $output->close();
176  $input->close();
177  }
178  return true;
179  }
180 
181  /**
182  * Tests whether this adapter can unpack files on this computer.
183  *
184  * @return boolean True if supported
185  *
186  * @since 11.3
187  */
188  public static function isSupported()
189  {
190  return extension_loaded('zlib');
191  }
192 
193  /**
194  * Get file data offset for archive
195  *
196  * @return integer Data position marker for archive
197  *
198  * @since 11.1
199  * @throws RuntimeException
200  */
201  public function _getFilePosition()
202  {
203  // Gzipped file... unpack it first
204  $position = 0;
205  $info = @ unpack('CCM/CFLG/VTime/CXFL/COS', substr($this->_data, $position + 2));
206 
207  if (!$info)
208  {
209  if (class_exists('JError'))
210  {
211  return JError::raiseWarning(100, 'Unable to decompress data.');
212  }
213  else
214  {
215  throw new RuntimeException('Unable to decompress data.');
216  }
217  }
218 
219  $position += 10;
220 
221  if ($info['FLG'] & $this->_flags['FEXTRA'])
222  {
223  $XLEN = unpack('vLength', substr($this->_data, $position + 0, 2));
224  $XLEN = $XLEN['Length'];
225  $position += $XLEN + 2;
226  }
227 
228  if ($info['FLG'] & $this->_flags['FNAME'])
229  {
230  $filenamePos = strpos($this->_data, "\x0", $position);
231  $position = $filenamePos + 1;
232  }
233 
234  if ($info['FLG'] & $this->_flags['FCOMMENT'])
235  {
236  $commentPos = strpos($this->_data, "\x0", $position);
237  $position = $commentPos + 1;
238  }
239 
240  if ($info['FLG'] & $this->_flags['FHCRC'])
241  {
242  $hcrc = unpack('vCRC', substr($this->_data, $position + 0, 2));
243  $hcrc = $hcrc['CRC'];
244  $position += 2;
245  }
246 
247  return $position;
248  }
249 }