1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Archive
5 *
6 * @copyright Copyright (C) 2005 - 2017 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
15 /**
16 * An Archive handling class
17 *
18 * @since 11.1
19 */
20 class JArchive
21 {
22 /**
23 * @var array The array of instantiated archive adapters.
24 * @since 12.1
25 */
26 protected static $adapters = array();
27
28 /**
29 * Extract an archive file to a directory.
30 *
31 * @param string $archivename The name of the archive file
32 * @param string $extractdir Directory to unpack into
33 *
34 * @return boolean True for success
35 *
36 * @since 11.1
37 * @throws InvalidArgumentException
38 */
39 public static function extract($archivename, $extractdir)
40 {
41 $untar = false;
42 $result = false;
43 $ext = JFile::getExt(strtolower($archivename));
44
45 // Check if a tar is embedded...gzip/bzip2 can just be plain files!
46 if (JFile::getExt(JFile::stripExt(strtolower($archivename))) == 'tar')
47 {
48 $untar = true;
49 }
50
51 switch ($ext)
52 {
53 case 'zip':
54 $adapter = self::getAdapter('zip');
55
56 if ($adapter)
57 {
58 $result = $adapter->extract($archivename, $extractdir);
59 }
60 break;
61
62 case 'tar':
63 $adapter = self::getAdapter('tar');
64
65 if ($adapter)
66 {
67 $result = $adapter->extract($archivename, $extractdir);
68 }
69 break;
70
71 case 'tgz':
72 // This format is a tarball gzip'd
73 $untar = true;
74
75 case 'gz':
76 case 'gzip':
77 // This may just be an individual file (e.g. sql script)
78 $adapter = self::getAdapter('gzip');
79
80 if ($adapter)
81 {
82 $config = JFactory::getConfig();
83 $tmpfname = $config->get('tmp_path') . '/' . uniqid('gzip');
84 $gzresult = $adapter->extract($archivename, $tmpfname);
85
86 if ($gzresult instanceof Exception)
87 {
88 @unlink($tmpfname);
89
90 return false;
91 }
92
93 if ($untar)
94 {
95 // Try to untar the file
96 $tadapter = self::getAdapter('tar');
97
98 if ($tadapter)
99 {
100 $result = $tadapter->extract($tmpfname, $extractdir);
101 }
102 }
103 else
104 {
105 $path = JPath::clean($extractdir);
106 JFolder::create($path);
107 $result = JFile::copy($tmpfname, $path . '/' . JFile::stripExt(basename(strtolower($archivename))), null, 1);
108 }
109
110 @unlink($tmpfname);
111 }
112 break;
113
114 case 'tbz2':
115 // This format is a tarball bzip2'd
116 $untar = true;
117
118 case 'bz2':
119 case 'bzip2':
120 // This may just be an individual file (e.g. sql script)
121 $adapter = self::getAdapter('bzip2');
122
123 if ($adapter)
124 {
125 $config = JFactory::getConfig();
126 $tmpfname = $config->get('tmp_path') . '/' . uniqid('bzip2');
127 $bzresult = $adapter->extract($archivename, $tmpfname);
128
129 if ($bzresult instanceof Exception)
130 {
131 @unlink($tmpfname);
132
133 return false;
134 }
135
136 if ($untar)
137 {
138 // Try to untar the file
139 $tadapter = self::getAdapter('tar');
140
141 if ($tadapter)
142 {
143 $result = $tadapter->extract($tmpfname, $extractdir);
144 }
145 }
146 else
147 {
148 $path = JPath::clean($extractdir);
149 JFolder::create($path);
150 $result = JFile::copy($tmpfname, $path . '/' . JFile::stripExt(basename(strtolower($archivename))), null, 1);
151 }
152
153 @unlink($tmpfname);
154 }
155 break;
156
157 default:
158 throw new InvalidArgumentException('Unknown Archive Type');
159 }
160
161 if (!$result || $result instanceof Exception)
162 {
163 return false;
164 }
165
166 return true;
167 }
168
169 /**
170 * Get a file compression adapter.
171 *
172 * @param string $type The type of adapter (bzip2|gzip|tar|zip).
173 *
174 * @return JArchiveExtractable Adapter for the requested type
175 *
176 * @since 11.1
177 * @throws UnexpectedValueException
178 */
179 public static function getAdapter($type)
180 {
181 if (!isset(self::$adapters[$type]))
182 {
183 // Try to load the adapter object
184 $class = 'JArchive' . ucfirst($type);
185
186 if (!class_exists($class))
187 {
188 throw new UnexpectedValueException('Unable to load archive', 500);
189 }
190
191 self::$adapters[$type] = new $class;
192 }
193
194 return self::$adapters[$type];
195 }
196 }
197