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.stream');
14
15 /**
16 * Bzip2 format adapter for the JArchive class
17 *
18 * @since 11.1
19 */
20 class JArchiveBzip2 implements JArchiveExtractable
21 {
22 /**
23 * Bzip2 file data buffer
24 *
25 * @var string
26 * @since 11.1
27 */
28 private $_data = null;
29
30 /**
31 * Extract a Bzip2 compressed file to a given path
32 *
33 * @param string $archive Path to Bzip2 archive to extract
34 * @param string $destination Path to extract archive to
35 * @param array $options Extraction options [unused]
36 *
37 * @return boolean True if successful
38 *
39 * @since 11.1
40 * @throws RuntimeException
41 */
42 public function extract($archive, $destination, array $options = array())
43 {
44 $this->_data = null;
45
46 if (!extension_loaded('bz2'))
47 {
48 $this->raiseWarning(100, 'The bz2 extension is not available.');
49 }
50
51 if (isset($options['use_streams']) && $options['use_streams'] != false)
52 {
53 return $this->extractStream($archive, $destination, $options);
54 }
55
56 // Old style: read the whole file and then parse it
57 $this->_data = file_get_contents($archive);
58
59 if (!$this->_data)
60 {
61 return $this->raiseWarning(100, 'Unable to read archive');
62 }
63
64 $buffer = bzdecompress($this->_data);
65 unset($this->_data);
66
67 if (empty($buffer))
68 {
69 return $this->raiseWarning(100, 'Unable to decompress data');
70 }
71
72 if (JFile::write($destination, $buffer) === false)
73 {
74 return $this->raiseWarning(100, 'Unable to write archive');
75 }
76
77 return true;
78 }
79
80 /**
81 * Method to extract archive using stream objects
82 *
83 * @param string $archive Path to Bzip2 archive to extract
84 * @param string $destination Path to extract archive to
85 * @param array $options Extraction options [unused]
86 *
87 * @return boolean True if successful
88 */
89 protected function extractStream($archive, $destination, $options = array())
90 {
91 // New style! streams!
92 $input = JFactory::getStream();
93
94 // Use bzip
95 $input->set('processingmethod', 'bz');
96
97 if (!$input->open($archive))
98 {
99 return $this->raiseWarning(100, 'Unable to read archive (bz2)');
100
101 }
102
103 $output = JFactory::getStream();
104
105 if (!$output->open($destination, 'w'))
106 {
107 $input->close();
108
109 return $this->raiseWarning(100, 'Unable to write archive (bz2)');
110
111 }
112
113 do
114 {
115 $this->_data = $input->read($input->get('chunksize', 8196));
116
117 if ($this->_data && !$output->write($this->_data))
118 {
119 $input->close();
120
121 return $this->raiseWarning(100, 'Unable to write archive (bz2)');
122 }
123 }
124
125 while ($this->_data);
126
127 $output->close();
128 $input->close();
129
130 return true;
131 }
132
133 /**
134 * Temporary private method to isolate JError from the extract method
135 * This code should be removed when JError is removed.
136 *
137 * @param int $code The application-internal error code for this error
138 * @param string $msg The error message, which may also be shown the user if need be.
139 *
140 * @return JException JException instance if JError class exists
141 *
142 * @throws RuntimeException if JError class does not exist
143 */
144 private function raiseWarning($code, $msg)
145 {
146 if (class_exists('JError'))
147 {
148 return JError::raiseWarning($code, $msg);
149 }
150
151 throw new RuntimeException($msg);
152 }
153
154 /**
155 * Tests whether this adapter can unpack files on this computer.
156 *
157 * @return boolean True if supported
158 *
159 * @since 11.3
160 */
161 public static function isSupported()
162 {
163 return extension_loaded('bz2');
164 }
165 }
166