Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
tar.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 jimport('joomla.filesystem.folder');
14 jimport('joomla.filesystem.path');
15 
16 /**
17  * Tar format adapter for the JArchive class
18  *
19  * This class is inspired from and draws heavily in code and concept from the Compress package of
20  * The Horde Project <http://www.horde.org>
21  *
22  * @contributor Michael Slusarz <slusarz@horde.org>
23  * @contributor Michael Cochrane <mike@graftonhall.co.nz>
24  *
25  * @package Joomla.Platform
26  * @subpackage Archive
27  * @since 11.1
28  */
30 {
31  /**
32  * Tar file types.
33  *
34  * @var array
35  * @since 11.1
36  */
37  private $_types = array(
38  0x0 => 'Unix file',
39  0x30 => 'File',
40  0x31 => 'Link',
41  0x32 => 'Symbolic link',
42  0x33 => 'Character special file',
43  0x34 => 'Block special file',
44  0x35 => 'Directory',
45  0x36 => 'FIFO special file',
46  0x37 => 'Contiguous file');
47 
48  /**
49  * Tar file data buffer
50  *
51  * @var string
52  * @since 11.1
53  */
54  private $_data = null;
55 
56  /**
57  * Tar file metadata array
58  *
59  * @var array
60  * @since 11.1
61  */
62  private $_metadata = null;
63 
64  /**
65  * Extract a ZIP compressed file to a given path
66  *
67  * @param string $archive Path to ZIP archive to extract
68  * @param string $destination Path to extract archive into
69  * @param array $options Extraction options [unused]
70  *
71  * @return boolean True if successful
72  *
73  * @throws RuntimeException
74  * @since 11.1
75  */
76  public function extract($archive, $destination, array $options = array())
77  {
78  $this->_data = null;
79  $this->_metadata = null;
80 
81  $this->_data = file_get_contents($archive);
82 
83  if (!$this->_data)
84  {
85  if (class_exists('JError'))
86  {
87  return JError::raiseWarning(100, 'Unable to read archive');
88  }
89  else
90  {
91  throw new RuntimeException('Unable to read archive');
92  }
93  }
94 
95  $this->_getTarInfo($this->_data);
96 
97  for ($i = 0, $n = count($this->_metadata); $i < $n; $i++)
98  {
99  $type = strtolower($this->_metadata[$i]['type']);
100 
101  if ($type == 'file' || $type == 'unix file')
102  {
103  $buffer = $this->_metadata[$i]['data'];
104  $path = JPath::clean($destination . '/' . $this->_metadata[$i]['name']);
105 
106  // Make sure the destination folder exists
107  if (!JFolder::create(dirname($path)))
108  {
109  if (class_exists('JError'))
110  {
111  return JError::raiseWarning(100, 'Unable to create destination');
112  }
113  else
114  {
115  throw new RuntimeException('Unable to create destination');
116  }
117  }
118  if (JFile::write($path, $buffer) === false)
119  {
120  if (class_exists('JError'))
121  {
122  return JError::raiseWarning(100, 'Unable to write entry');
123  }
124  else
125  {
126  throw new RuntimeException('Unable to write entry');
127  }
128  }
129  }
130  }
131  return true;
132  }
133 
134  /**
135  * Tests whether this adapter can unpack files on this computer.
136  *
137  * @return boolean True if supported
138  *
139  * @since 11.3
140  */
141  public static function isSupported()
142  {
143  return true;
144  }
145 
146  /**
147  * Get the list of files/data from a Tar archive buffer.
148  *
149  * @param string &$data The Tar archive buffer.
150  *
151  * @return array Archive metadata array
152  * <pre>
153  * KEY: Position in the array
154  * VALUES: 'attr' -- File attributes
155  * 'data' -- Raw file contents
156  * 'date' -- File modification time
157  * 'name' -- Filename
158  * 'size' -- Original file size
159  * 'type' -- File type
160  * </pre>
161  *
162  * @since 11.1
163  */
164  protected function _getTarInfo(& $data)
165  {
166  $position = 0;
167  $return_array = array();
168 
169  while ($position < strlen($data))
170  {
171  $info = @unpack(
172  "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/Ctypeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor",
173  substr($data, $position)
174  );
175 
176  if (!$info)
177  {
178  if (class_exists('JError'))
179  {
180  return JError::raiseWarning(100, 'Unable to decompress data');
181  }
182  else
183  {
184  throw new RuntimeException('Unable to decompress data');
185  }
186  }
187 
188  $position += 512;
189  $contents = substr($data, $position, octdec($info['size']));
190  $position += ceil(octdec($info['size']) / 512) * 512;
191 
192  if ($info['filename'])
193  {
194  $file = array(
195  'attr' => null,
196  'data' => null,
197  'date' => octdec($info['mtime']),
198  'name' => trim($info['filename']),
199  'size' => octdec($info['size']),
200  'type' => isset($this->_types[$info['typeflag']]) ? $this->_types[$info['typeflag']] : null);
201 
202  if (($info['typeflag'] == 0) || ($info['typeflag'] == 0x30) || ($info['typeflag'] == 0x35))
203  {
204  /* File or folder. */
205  $file['data'] = $contents;
206 
207  $mode = hexdec(substr($info['mode'], 4, 3));
208  $file['attr'] = (($info['typeflag'] == 0x35) ? 'd' : '-') . (($mode & 0x400) ? 'r' : '-') . (($mode & 0x200) ? 'w' : '-') .
209  (($mode & 0x100) ? 'x' : '-') . (($mode & 0x040) ? 'r' : '-') . (($mode & 0x020) ? 'w' : '-') . (($mode & 0x010) ? 'x' : '-') .
210  (($mode & 0x004) ? 'r' : '-') . (($mode & 0x002) ? 'w' : '-') . (($mode & 0x001) ? 'x' : '-');
211  }
212  else
213  {
214  /* Some other type. */
215  }
216  $return_array[] = $file;
217  }
218  }
219  $this->_metadata = $return_array;
220 
221  return true;
222  }
223 }