phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_compress.php

History | View | Annotate | Download (18.6 kB)

1 5114 acydburn
<?php
2 8146 acydburn
/**
3 5114 acydburn
*
4 5114 acydburn
* @package phpBB3
5 8146 acydburn
* @copyright (c) 2005 phpBB Group
6 11653 git-gate
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7 5114 acydburn
*
8 5114 acydburn
*/
9 4287 psotfx
10 5114 acydburn
/**
11 8146 acydburn
* @ignore
12 8146 acydburn
*/
13 8146 acydburn
if (!defined('IN_PHPBB'))
14 8146 acydburn
{
15 8146 acydburn
        exit;
16 8146 acydburn
}
17 8146 acydburn
18 8146 acydburn
/**
19 6058 acydburn
* Class for handling archives (compression/decompression)
20 5114 acydburn
* @package phpBB3
21 5114 acydburn
*/
22 7877 davidmj
class compress
23 4287 psotfx
{
24 4287 psotfx
        var $fp = 0;
25 5315 acydburn
26 6015 acydburn
        /**
27 6015 acydburn
        * Add file to archive
28 6015 acydburn
        */
29 4353 psotfx
        function add_file($src, $src_rm_prefix = '', $src_add_prefix = '', $skip_files = '')
30 4287 psotfx
        {
31 4287 psotfx
                global $phpbb_root_path;
32 4287 psotfx
33 4291 psotfx
                $skip_files = explode(',', $skip_files);
34 4291 psotfx
35 5315 acydburn
                // Remove rm prefix from src path
36 5853 naderman
                $src_path = ($src_rm_prefix) ? preg_replace('#^(' . preg_quote($src_rm_prefix, '#') . ')#', '', $src) : $src;
37 4355 psotfx
                // Add src prefix
38 4355 psotfx
                $src_path = ($src_add_prefix) ? ($src_add_prefix . ((substr($src_add_prefix, -1) != '/') ? '/' : '') . $src_path) : $src_path;
39 4353 psotfx
                // Remove initial "/" if present
40 4353 psotfx
                $src_path = (substr($src_path, 0, 1) == '/') ? substr($src_path, 1) : $src_path;
41 4353 psotfx
42 4287 psotfx
                if (is_file($phpbb_root_path . $src))
43 4287 psotfx
                {
44 5422 davidmj
                        $this->data($src_path, file_get_contents("$phpbb_root_path$src"), false, stat("$phpbb_root_path$src"));
45 4287 psotfx
                }
46 4287 psotfx
                else if (is_dir($phpbb_root_path . $src))
47 4287 psotfx
                {
48 4353 psotfx
                        // Clean up path, add closing / if not present
49 4353 psotfx
                        $src_path = ($src_path && substr($src_path, -1) != '/') ? $src_path . '/' : $src_path;
50 4305 psotfx
51 4353 psotfx
                        $filelist = array();
52 4418 psotfx
                        $filelist = filelist("$phpbb_root_path$src", '', '*');
53 4355 psotfx
                        krsort($filelist);
54 4287 psotfx
55 10761 git-gate
                        /**
56 10761 git-gate
                        * Commented out, as adding the folders produces corrupted archives
57 4353 psotfx
                        if ($src_path)
58 4287 psotfx
                        {
59 5385 davidmj
                                $this->data($src_path, '', true, stat("$phpbb_root_path$src"));
60 4287 psotfx
                        }
61 10761 git-gate
                        */
62 4287 psotfx
63 4287 psotfx
                        foreach ($filelist as $path => $file_ary)
64 4287 psotfx
                        {
65 10761 git-gate
                                /**
66 10761 git-gate
                                * Commented out, as adding the folders produces corrupted archives
67 4287 psotfx
                                if ($path)
68 4287 psotfx
                                {
69 4353 psotfx
                                        // Same as for src_path
70 4353 psotfx
                                        $path = (substr($path, 0, 1) == '/') ? substr($path, 1) : $path;
71 4353 psotfx
                                        $path = ($path && substr($path, -1) != '/') ? $path . '/' : $path;
72 4287 psotfx
73 5385 davidmj
                                        $this->data("$src_path$path", '', true, stat("$phpbb_root_path$src$path"));
74 4287 psotfx
                                }
75 10761 git-gate
                                */
76 4287 psotfx
77 4287 psotfx
                                foreach ($file_ary as $file)
78 4287 psotfx
                                {
79 4291 psotfx
                                        if (in_array($path . $file, $skip_files))
80 4291 psotfx
                                        {
81 4291 psotfx
                                                continue;
82 4291 psotfx
                                        }
83 4291 psotfx
84 5422 davidmj
                                        $this->data("$src_path$path$file", file_get_contents("$phpbb_root_path$src$path$file"), false, stat("$phpbb_root_path$src$path$file"));
85 4287 psotfx
                                }
86 4287 psotfx
                        }
87 6015 acydburn
                }
88 10558 git-gate
                else
89 10558 git-gate
                {
90 10558 git-gate
                        // $src does not exist
91 10558 git-gate
                        return false;
92 10558 git-gate
                }
93 4287 psotfx
94 4287 psotfx
                return true;
95 4287 psotfx
        }
96 4287 psotfx
97 6015 acydburn
        /**
98 6015 acydburn
        * Add custom file (the filepath will not be adjusted)
99 6015 acydburn
        */
100 5315 acydburn
        function add_custom_file($src, $filename)
101 5315 acydburn
        {
102 10558 git-gate
                if (!file_exists($src))
103 10558 git-gate
                {
104 10558 git-gate
                        return false;
105 10558 git-gate
                }
106 10558 git-gate
107 5521 davidmj
                $this->data($filename, file_get_contents($src), false, stat($src));
108 5315 acydburn
                return true;
109 5315 acydburn
        }
110 6015 acydburn
111 6015 acydburn
        /**
112 6015 acydburn
        * Add file data
113 6015 acydburn
        */
114 4287 psotfx
        function add_data($src, $name)
115 4287 psotfx
        {
116 5647 davidmj
                $stat = array();
117 5351 davidmj
                $stat[2] = 436; //384
118 5351 davidmj
                $stat[4] = $stat[5] = 0;
119 5351 davidmj
                $stat[7] = strlen($src);
120 5351 davidmj
                $stat[9] = time();
121 5351 davidmj
                $this->data($name, $src, false, $stat);
122 4287 psotfx
                return true;
123 4287 psotfx
        }
124 4381 psotfx
125 6015 acydburn
        /**
126 6015 acydburn
        * Return available methods
127 6015 acydburn
        */
128 4381 psotfx
        function methods()
129 4381 psotfx
        {
130 5422 davidmj
                $methods = array('.tar');
131 5422 davidmj
                $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
132 4381 psotfx
133 5315 acydburn
                foreach ($available_methods as $type => $module)
134 4381 psotfx
                {
135 4381 psotfx
                        if (!@extension_loaded($module))
136 4381 psotfx
                        {
137 5315 acydburn
                                continue;
138 4381 psotfx
                        }
139 4381 psotfx
                        $methods[] = $type;
140 4381 psotfx
                }
141 4381 psotfx
142 4381 psotfx
                return $methods;
143 4381 psotfx
        }
144 4305 psotfx
}
145 4287 psotfx
146 5114 acydburn
/**
147 8146 acydburn
* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux,
148 5114 acydburn
* Marc Delisle, http://www.phpmyadmin.net/
149 5114 acydburn
*
150 5351 davidmj
* Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com
151 5114 acydburn
*
152 5765 acydburn
* Modified extensively by psoTFX and DavidMJ, (c) phpBB Group, 2003
153 5351 davidmj
*
154 5114 acydburn
* Based on work by Eric Mueller and Denis125
155 5114 acydburn
* Official ZIP file format: http://www.pkware.com/appnote.txt
156 6058 acydburn
*
157 6058 acydburn
* @package phpBB3
158 5114 acydburn
*/
159 4305 psotfx
class compress_zip extends compress
160 4305 psotfx
{
161 4305 psotfx
        var $datasec = array();
162 4305 psotfx
        var $ctrl_dir = array();
163 4356 psotfx
        var $eof_cdh = "\x50\x4b\x05\x06\x00\x00\x00\x00";
164 4305 psotfx
165 4305 psotfx
        var $old_offset = 0;
166 4305 psotfx
        var $datasec_len = 0;
167 4305 psotfx
168 6015 acydburn
        /**
169 6015 acydburn
        * Constructor
170 6015 acydburn
        */
171 4305 psotfx
        function compress_zip($mode, $file)
172 4305 psotfx
        {
173 9768 bantu
                $this->fp = @fopen($file, $mode . 'b');
174 9768 bantu
175 9768 bantu
                if (!$this->fp)
176 9768 bantu
                {
177 9768 bantu
                        trigger_error('Unable to open file ' . $file . ' [' . $mode . 'b]');
178 9768 bantu
                }
179 4305 psotfx
        }
180 4305 psotfx
181 6015 acydburn
        /**
182 6015 acydburn
        * Convert unix to dos time
183 6015 acydburn
        */
184 4305 psotfx
        function unix_to_dos_time($time)
185 4305 psotfx
        {
186 4305 psotfx
                $timearray = (!$time) ? getdate() : getdate($time);
187 4305 psotfx
188 4305 psotfx
                if ($timearray['year'] < 1980)
189 4305 psotfx
                {
190 4305 psotfx
                        $timearray['year'] = 1980;
191 4305 psotfx
                        $timearray['mon'] = $timearray['mday'] = 1;
192 4305 psotfx
                        $timearray['hours'] = $timearray['minutes'] = $timearray['seconds'] = 0;
193 4305 psotfx
                }
194 4305 psotfx
195 4305 psotfx
                return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
196 4305 psotfx
        }
197 4305 psotfx
198 6015 acydburn
        /**
199 6015 acydburn
        * Extract archive
200 6015 acydburn
        */
201 4287 psotfx
        function extract($dst)
202 8639 acydburn
        {
203 5351 davidmj
                // Loop the file, looking for files and folders
204 5377 acydburn
                $dd_try = false;
205 5579 davidmj
                rewind($this->fp);
206 4309 psotfx
207 5498 davidmj
                while (!feof($this->fp))
208 4309 psotfx
                {
209 5351 davidmj
                        // Check if the signature is valid...
210 5351 davidmj
                        $signature = fread($this->fp, 4);
211 5351 davidmj
212 5351 davidmj
                        switch ($signature)
213 4418 psotfx
                        {
214 5351 davidmj
                                // 'Local File Header'
215 5351 davidmj
                                case "\x50\x4b\x03\x04":
216 5579 davidmj
                                        // Lets get everything we need.
217 5579 davidmj
                                        // We don't store the version needed to extract, the general purpose bit flag or the date and time fields
218 5579 davidmj
                                        $data = unpack("@4/vc_method/@10/Vcrc/Vc_size/Vuc_size/vname_len/vextra_field", fread($this->fp, 26));
219 5579 davidmj
                                        $file_name = fread($this->fp, $data['name_len']); // filename
220 5416 acydburn
221 5579 davidmj
                                        if ($data['extra_field'])
222 5416 acydburn
                                        {
223 5579 davidmj
                                                fread($this->fp, $data['extra_field']); // extra field
224 5416 acydburn
                                        }
225 5416 acydburn
226 5498 davidmj
                                        $target_filename = "$dst$file_name";
227 4309 psotfx
228 5579 davidmj
                                        if (!$data['uc_size'] && !$data['crc'] && substr($file_name, -1, 1) == '/')
229 5498 davidmj
                                        {
230 5498 davidmj
                                                if (!is_dir($target_filename))
231 5498 davidmj
                                                {
232 5498 davidmj
                                                        $str = '';
233 5498 davidmj
                                                        $folders = explode('/', $target_filename);
234 4353 psotfx
235 5498 davidmj
                                                        // Create and folders and subfolders if they do not exist
236 5498 davidmj
                                                        foreach ($folders as $folder)
237 5498 davidmj
                                                        {
238 8639 acydburn
                                                                $folder = trim($folder);
239 8639 acydburn
                                                                if (!$folder)
240 8639 acydburn
                                                                {
241 8639 acydburn
                                                                        continue;
242 8639 acydburn
                                                                }
243 8639 acydburn
244 5498 davidmj
                                                                $str = (!empty($str)) ? $str . '/' . $folder : $folder;
245 5498 davidmj
                                                                if (!is_dir($str))
246 5498 davidmj
                                                                {
247 5498 davidmj
                                                                        if (!@mkdir($str, 0777))
248 5498 davidmj
                                                                        {
249 5498 davidmj
                                                                                trigger_error("Could not create directory $folder");
250 5498 davidmj
                                                                        }
251 8780 acydburn
                                                                        phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
252 5498 davidmj
                                                                }
253 5498 davidmj
                                                        }
254 5498 davidmj
                                                }
255 5498 davidmj
                                                // This is a directory, we are not writting files
256 5498 davidmj
                                                continue;
257 5498 davidmj
                                        }
258 5786 davidmj
                                        else
259 5786 davidmj
                                        {
260 8505 davidmj
                                                // Some archivers are punks, they don't include folders in their archives!
261 5786 davidmj
                                                $str = '';
262 5786 davidmj
                                                $folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME));
263 5498 davidmj
264 5786 davidmj
                                                // Create and folders and subfolders if they do not exist
265 5786 davidmj
                                                foreach ($folders as $folder)
266 5786 davidmj
                                                {
267 8639 acydburn
                                                        $folder = trim($folder);
268 8639 acydburn
                                                        if (!$folder)
269 8639 acydburn
                                                        {
270 8639 acydburn
                                                                continue;
271 8639 acydburn
                                                        }
272 8639 acydburn
273 5786 davidmj
                                                        $str = (!empty($str)) ? $str . '/' . $folder : $folder;
274 5786 davidmj
                                                        if (!is_dir($str))
275 5786 davidmj
                                                        {
276 5786 davidmj
                                                                if (!@mkdir($str, 0777))
277 5786 davidmj
                                                                {
278 5786 davidmj
                                                                        trigger_error("Could not create directory $folder");
279 5786 davidmj
                                                                }
280 8780 acydburn
                                                                phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
281 5786 davidmj
                                                        }
282 5786 davidmj
                                                }
283 5786 davidmj
                                        }
284 5786 davidmj
285 5579 davidmj
                                        if (!$data['uc_size'])
286 5498 davidmj
                                        {
287 5498 davidmj
                                                $content = '';
288 5498 davidmj
                                        }
289 5498 davidmj
                                        else
290 5498 davidmj
                                        {
291 5579 davidmj
                                                $content = fread($this->fp, $data['c_size']);
292 5498 davidmj
                                        }
293 5498 davidmj
294 5498 davidmj
                                        $fp = fopen($target_filename, "w");
295 5498 davidmj
296 5579 davidmj
                                        switch ($data['c_method'])
297 5498 davidmj
                                        {
298 5498 davidmj
                                                case 0:
299 5498 davidmj
                                                        // Not compressed
300 5498 davidmj
                                                        fwrite($fp, $content);
301 5498 davidmj
                                                break;
302 8639 acydburn
303 5498 davidmj
                                                case 8:
304 5498 davidmj
                                                        // Deflate
305 5579 davidmj
                                                        fwrite($fp, gzinflate($content, $data['uc_size']));
306 5498 davidmj
                                                break;
307 5498 davidmj
308 5498 davidmj
                                                case 12:
309 5498 davidmj
                                                        // Bzip2
310 5498 davidmj
                                                        fwrite($fp, bzdecompress($content));
311 5498 davidmj
                                                break;
312 5498 davidmj
                                        }
313 8639 acydburn
314 5498 davidmj
                                        fclose($fp);
315 5377 acydburn
                                break;
316 5377 acydburn
317 5511 davidmj
                                // We hit the 'Central Directory Header', we can stop because nothing else in here requires our attention
318 5511 davidmj
                                // or we hit the end of the central directory record, we can safely end the loop as we are totally finished with looking for files and folders
319 5351 davidmj
                                case "\x50\x4b\x01\x02":
320 5511 davidmj
                                // This case should simply never happen.. but it does exist..
321 5351 davidmj
                                case "\x50\x4b\x05\x06":
322 5377 acydburn
                                break 2;
323 8639 acydburn
324 5498 davidmj
                                // 'Packed to Removable Disk', ignore it and look for the next signature...
325 5351 davidmj
                                case 'PK00':
326 5377 acydburn
                                continue 2;
327 8639 acydburn
328 5351 davidmj
                                // We have encountered a header that is weird. Lets look for better data...
329 5351 davidmj
                                default:
330 5377 acydburn
                                        if (!$dd_try)
331 5351 davidmj
                                        {
332 5351 davidmj
                                                // Unexpected header. Trying to detect wrong placed 'Data Descriptor';
333 5377 acydburn
                                                $dd_try = true;
334 5351 davidmj
                                                fseek($this->fp, 8, SEEK_CUR); // Jump over 'crc-32'(4) 'compressed-size'(4), 'uncompressed-size'(4)
335 5351 davidmj
                                                continue 2;
336 5351 davidmj
                                        }
337 5351 davidmj
                                        trigger_error("Unexpected header, ending loop");
338 5498 davidmj
                                break 2;
339 4353 psotfx
                        }
340 6015 acydburn
341 5377 acydburn
                        $dd_try = false;
342 4353 psotfx
                }
343 4287 psotfx
        }
344 4287 psotfx
345 6015 acydburn
        /**
346 6015 acydburn
        * Close archive
347 6015 acydburn
        */
348 4287 psotfx
        function close()
349 4287 psotfx
        {
350 4381 psotfx
                // Write out central file directory and footer ... if it exists
351 4381 psotfx
                if (sizeof($this->ctrl_dir))
352 4381 psotfx
                {
353 4381 psotfx
                        fwrite($this->fp, $this->file());
354 4381 psotfx
                }
355 4287 psotfx
                fclose($this->fp);
356 4287 psotfx
        }
357 4287 psotfx
358 6015 acydburn
        /**
359 6015 acydburn
        * Create the structures ... note we assume version made by is MSDOS
360 6015 acydburn
        */
361 5351 davidmj
        function data($name, $data, $is_dir = false, $stat)
362 4287 psotfx
        {
363 4287 psotfx
                $name = str_replace('\\', '/', $name);
364 4287 psotfx
365 6371 davidmj
                $hexdtime = pack('V', $this->unix_to_dos_time($stat[9]));
366 4287 psotfx
367 4353 psotfx
                if ($is_dir)
368 4353 psotfx
                {
369 4353 psotfx
                        $unc_len = $c_len = $crc = 0;
370 4353 psotfx
                        $zdata = '';
371 5579 davidmj
                        $var_ext = 10;
372 4353 psotfx
                }
373 4353 psotfx
                else
374 4353 psotfx
                {
375 4353 psotfx
                        $unc_len = strlen($data);
376 4353 psotfx
                        $crc = crc32($data);
377 5496 davidmj
                        $zdata = gzdeflate($data);
378 4353 psotfx
                        $c_len = strlen($zdata);
379 5579 davidmj
                        $var_ext = 20;
380 4355 psotfx
381 4355 psotfx
                        // Did we compress? No, then use data as is
382 4356 psotfx
                        if ($c_len >= $unc_len)
383 4355 psotfx
                        {
384 4355 psotfx
                                $zdata = $data;
385 4355 psotfx
                                $c_len = $unc_len;
386 5579 davidmj
                                $var_ext = 10;
387 4355 psotfx
                        }
388 4353 psotfx
                }
389 4287 psotfx
                unset($data);
390 4287 psotfx
391 4355 psotfx
                // If we didn't compress set method to store, else deflate
392 5315 acydburn
                $c_method = ($c_len == $unc_len) ? "\x00\x00" : "\x08\x00";
393 4355 psotfx
394 4356 psotfx
                // Are we a file or a directory? Set archive for file
395 4356 psotfx
                $attrib = ($is_dir) ? 16 : 32;
396 6015 acydburn
397 4356 psotfx
                // File Record Header
398 4355 psotfx
                $fr = "\x50\x4b\x03\x04";                // Local file header 4bytes
399 5579 davidmj
                $fr .= pack('v', $var_ext);                // ver needed to extract 2bytes
400 4355 psotfx
                $fr .= "\x00\x00";                                // gen purpose bit flag 2bytes
401 4355 psotfx
                $fr .= $c_method;                                // compression method 2bytes
402 4355 psotfx
                $fr .= $hexdtime;                                // last mod time and date 2+2bytes
403 4355 psotfx
                $fr .= pack('V', $crc);                        // crc32 4bytes
404 4355 psotfx
                $fr .= pack('V', $c_len);                // compressed filesize 4bytes
405 4355 psotfx
                $fr .= pack('V', $unc_len);                // uncompressed filesize 4bytes
406 4355 psotfx
                $fr .= pack('v', strlen($name));// length of filename 2bytes
407 4356 psotfx
408 4355 psotfx
                $fr .= pack('v', 0);                        // extra field length 2bytes
409 4355 psotfx
                $fr .= $name;
410 4287 psotfx
                $fr .= $zdata;
411 4287 psotfx
                unset($zdata);
412 4287 psotfx
413 4287 psotfx
                $this->datasec_len += strlen($fr);
414 4287 psotfx
415 4356 psotfx
                // Add data to file ... by writing data out incrementally we save some memory
416 4287 psotfx
                fwrite($this->fp, $fr);
417 4287 psotfx
                unset($fr);
418 4287 psotfx
419 4356 psotfx
                // Central Directory Header
420 4355 psotfx
                $cdrec = "\x50\x4b\x01\x02";                // header 4bytes
421 6015 acydburn
                $cdrec .= "\x00\x00";                                // version made by
422 5579 davidmj
                $cdrec .= pack('v', $var_ext);                // version needed to extract
423 6015 acydburn
                $cdrec .= "\x00\x00";                                // gen purpose bit flag
424 5315 acydburn
                $cdrec .= $c_method;                                // compression method
425 6015 acydburn
                $cdrec .= $hexdtime;                                // last mod time & date
426 6015 acydburn
                $cdrec .= pack('V', $crc);                        // crc32
427 6015 acydburn
                $cdrec .= pack('V', $c_len);                // compressed filesize
428 6015 acydburn
                $cdrec .= pack('V', $unc_len);                // uncompressed filesize
429 6015 acydburn
                $cdrec .= pack('v', strlen($name));        // length of filename
430 6015 acydburn
                $cdrec .= pack('v', 0);                                // extra field length
431 6015 acydburn
                $cdrec .= pack('v', 0);                                // file comment length
432 6015 acydburn
                $cdrec .= pack('v', 0);                                // disk number start
433 6015 acydburn
                $cdrec .= pack('v', 0);                                // internal file attributes
434 4356 psotfx
                $cdrec .= pack('V', $attrib);                // external file attributes
435 6015 acydburn
                $cdrec .= pack('V', $this->old_offset);        // relative offset of local header
436 4287 psotfx
                $cdrec .= $name;
437 4287 psotfx
438 4287 psotfx
                // Save to central directory
439 4287 psotfx
                $this->ctrl_dir[] = $cdrec;
440 4287 psotfx
441 4287 psotfx
                $this->old_offset = $this->datasec_len;
442 4287 psotfx
        }
443 4287 psotfx
444 6015 acydburn
        /**
445 6015 acydburn
        * file
446 6015 acydburn
        */
447 4287 psotfx
        function file()
448 4287 psotfx
        {
449 4287 psotfx
                $ctrldir = implode('', $this->ctrl_dir);
450 4287 psotfx
451 5315 acydburn
                return $ctrldir . $this->eof_cdh .
452 4287 psotfx
                        pack('v', sizeof($this->ctrl_dir)) .        // total # of entries "on this disk"
453 4287 psotfx
                        pack('v', sizeof($this->ctrl_dir)) .        // total # of entries overall
454 4287 psotfx
                        pack('V', strlen($ctrldir)) .                        // size of central dir
455 4287 psotfx
                        pack('V', $this->datasec_len) .                        // offset to start of central dir
456 4356 psotfx
                        "\x00\x00";                                                                // .zip file comment length
457 4287 psotfx
        }
458 5074 acydburn
459 6015 acydburn
        /**
460 6015 acydburn
        * Download archive
461 6015 acydburn
        */
462 7134 acydburn
        function download($filename, $download_name = false)
463 5074 acydburn
        {
464 5074 acydburn
                global $phpbb_root_path;
465 5074 acydburn
466 7134 acydburn
                if ($download_name === false)
467 7134 acydburn
                {
468 7134 acydburn
                        $download_name = $filename;
469 7134 acydburn
                }
470 7134 acydburn
471 5074 acydburn
                $mimetype = 'application/zip';
472 5074 acydburn
473 5074 acydburn
                header('Pragma: no-cache');
474 7134 acydburn
                header("Content-Type: $mimetype; name=\"$download_name.zip\"");
475 7134 acydburn
                header("Content-disposition: attachment; filename=$download_name.zip");
476 5074 acydburn
477 7877 davidmj
                $fp = @fopen("{$phpbb_root_path}store/$filename.zip", 'rb');
478 7877 davidmj
                if ($fp)
479 5074 acydburn
                {
480 7877 davidmj
                        while ($buffer = fread($fp, 1024))
481 7877 davidmj
                        {
482 7877 davidmj
                                echo $buffer;
483 7877 davidmj
                        }
484 7877 davidmj
                        fclose($fp);
485 5074 acydburn
                }
486 5074 acydburn
        }
487 4287 psotfx
}
488 4287 psotfx
489 5114 acydburn
/**
490 5114 acydburn
* Tar/tar.gz compression routine
491 6015 acydburn
* Header/checksum creation derived from tarfile.pl, (c) Tom Horsley, 1994
492 6058 acydburn
*
493 6058 acydburn
* @package phpBB3
494 5114 acydburn
*/
495 8146 acydburn
class compress_tar extends compress
496 4287 psotfx
{
497 4305 psotfx
        var $isgz = false;
498 4306 psotfx
        var $isbz = false;
499 4398 psotfx
        var $filename = '';
500 4398 psotfx
        var $mode = '';
501 5074 acydburn
        var $type = '';
502 5497 davidmj
        var $wrote = false;
503 4287 psotfx
504 6015 acydburn
        /**
505 6015 acydburn
        * Constructor
506 6015 acydburn
        */
507 4353 psotfx
        function compress_tar($mode, $file, $type = '')
508 4287 psotfx
        {
509 4353 psotfx
                $type = (!$type) ? $file : $type;
510 10625 git-gate
                $this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type);
511 10625 git-gate
                $this->isbz = preg_match('#\.tar\.bz2$#', $type);
512 4287 psotfx
513 4398 psotfx
                $this->mode = &$mode;
514 4398 psotfx
                $this->file = &$file;
515 5074 acydburn
                $this->type = &$type;
516 4398 psotfx
                $this->open();
517 4287 psotfx
        }
518 4287 psotfx
519 6015 acydburn
        /**
520 6015 acydburn
        * Extract archive
521 6015 acydburn
        */
522 4305 psotfx
        function extract($dst)
523 4287 psotfx
        {
524 6073 acydburn
                $fzread = ($this->isbz && function_exists('bzread')) ? 'bzread' : (($this->isgz && @extension_loaded('zlib')) ? 'gzread' : 'fread');
525 4308 psotfx
526 4398 psotfx
                // Run through the file and grab directory entries
527 4308 psotfx
                while ($buffer = $fzread($this->fp, 512))
528 4308 psotfx
                {
529 6549 davidmj
                        $tmp = unpack('A6magic', substr($buffer, 257, 6));
530 4308 psotfx
531 4308 psotfx
                        if (trim($tmp['magic']) == 'ustar')
532 4308 psotfx
                        {
533 6549 davidmj
                                $tmp = unpack('A100name', $buffer);
534 4308 psotfx
                                $filename = trim($tmp['name']);
535 4308 psotfx
536 6549 davidmj
                                $tmp = unpack('Atype', substr($buffer, 156, 1));
537 4308 psotfx
                                $filetype = (int) trim($tmp['type']);
538 4308 psotfx
539 6549 davidmj
                                $tmp = unpack('A12size', substr($buffer, 124, 12));
540 5497 davidmj
                                $filesize = octdec((int) trim($tmp['size']));
541 5497 davidmj
542 8505 davidmj
                                $target_filename = "$dst$filename";
543 8505 davidmj
544 4308 psotfx
                                if ($filetype == 5)
545 4308 psotfx
                                {
546 8505 davidmj
                                        if (!is_dir($target_filename))
547 5351 davidmj
                                        {
548 5497 davidmj
                                                $str = '';
549 8505 davidmj
                                                $folders = explode('/', $target_filename);
550 5497 davidmj
551 5497 davidmj
                                                // Create and folders and subfolders if they do not exist
552 5497 davidmj
                                                foreach ($folders as $folder)
553 5351 davidmj
                                                {
554 8639 acydburn
                                                        $folder = trim($folder);
555 8639 acydburn
                                                        if (!$folder)
556 8639 acydburn
                                                        {
557 8639 acydburn
                                                                continue;
558 8639 acydburn
                                                        }
559 8639 acydburn
560 5497 davidmj
                                                        $str = (!empty($str)) ? $str . '/' . $folder : $folder;
561 5497 davidmj
                                                        if (!is_dir($str))
562 5497 davidmj
                                                        {
563 5497 davidmj
                                                                if (!@mkdir($str, 0777))
564 5497 davidmj
                                                                {
565 5497 davidmj
                                                                        trigger_error("Could not create directory $folder");
566 5497 davidmj
                                                                }
567 8780 acydburn
                                                                phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
568 5497 davidmj
                                                        }
569 5351 davidmj
                                                }
570 5351 davidmj
                                        }
571 4398 psotfx
                                }
572 8505 davidmj
                                else if ($filesize >= 0 && ($filetype == 0 || $filetype == "\0"))
573 4398 psotfx
                                {
574 8505 davidmj
                                        // Some archivers are punks, they don't properly order the folders in their archives!
575 8505 davidmj
                                        $str = '';
576 8505 davidmj
                                        $folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME));
577 8505 davidmj
578 8505 davidmj
                                        // Create and folders and subfolders if they do not exist
579 8505 davidmj
                                        foreach ($folders as $folder)
580 8505 davidmj
                                        {
581 8639 acydburn
                                                $folder = trim($folder);
582 8639 acydburn
                                                if (!$folder)
583 8639 acydburn
                                                {
584 8639 acydburn
                                                        continue;
585 8639 acydburn
                                                }
586 8639 acydburn
587 8505 davidmj
                                                $str = (!empty($str)) ? $str . '/' . $folder : $folder;
588 8505 davidmj
                                                if (!is_dir($str))
589 8505 davidmj
                                                {
590 8505 davidmj
                                                        if (!@mkdir($str, 0777))
591 8505 davidmj
                                                        {
592 8505 davidmj
                                                                trigger_error("Could not create directory $folder");
593 8505 davidmj
                                                        }
594 8780 acydburn
                                                        phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
595 8505 davidmj
                                                }
596 8505 davidmj
                                        }
597 8505 davidmj
598 5497 davidmj
                                        // Write out the files
599 8505 davidmj
                                        if (!($fp = fopen($target_filename, 'wb')))
600 4308 psotfx
                                        {
601 5351 davidmj
                                                trigger_error("Couldn't create file $filename");
602 4308 psotfx
                                        }
603 8780 acydburn
                                        phpbb_chmod($target_filename, CHMOD_READ);
604 4308 psotfx
605 5497 davidmj
                                        // Grab the file contents
606 8505 davidmj
                                        fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize);
607 5497 davidmj
                                        fclose($fp);
608 4308 psotfx
                                }
609 4308 psotfx
                        }
610 4308 psotfx
                }
611 4287 psotfx
        }
612 4287 psotfx
613 6015 acydburn
        /**
614 6015 acydburn
        * Close archive
615 6015 acydburn
        */
616 4305 psotfx
        function close()
617 4287 psotfx
        {
618 6073 acydburn
                $fzclose = ($this->isbz && function_exists('bzclose')) ? 'bzclose' : (($this->isgz && @extension_loaded('zlib')) ? 'gzclose' : 'fclose');
619 5416 acydburn
620 8146 acydburn
                if ($this->wrote)
621 5416 acydburn
                {
622 6073 acydburn
                        $fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');
623 6015 acydburn
624 7877 davidmj
                        // The end of a tar archive ends in two records of all NULLs (1024 bytes of \0)
625 7877 davidmj
                        $fzwrite($this->fp, str_repeat("\0", 1024));
626 5416 acydburn
                }
627 5416 acydburn
628 4305 psotfx
                $fzclose($this->fp);
629 4287 psotfx
        }
630 4287 psotfx
631 6015 acydburn
        /**
632 6015 acydburn
        * Create the structures
633 6015 acydburn
        */
634 5351 davidmj
        function data($name, $data, $is_dir = false, $stat)
635 4287 psotfx
        {
636 5351 davidmj
                $this->wrote = true;
637 6073 acydburn
                $fzwrite =         ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');
638 4287 psotfx
639 4305 psotfx
                $typeflag = ($is_dir) ? '5' : '';
640 4287 psotfx
641 5351 davidmj
                // This is the header data, it contains all the info we know about the file or folder that we are about to archive
642 4306 psotfx
                $header = '';
643 6549 davidmj
                $header .= pack('a100', $name);                                                // file name
644 6549 davidmj
                $header .= pack('a8', sprintf("%07o", $stat[2]));        // file mode
645 6549 davidmj
                $header .= pack('a8', sprintf("%07o", $stat[4]));        // owner id
646 6549 davidmj
                $header .= pack('a8', sprintf("%07o", $stat[5]));        // group id
647 6549 davidmj
                $header .= pack('a12', sprintf("%011o", $stat[7]));        // file size
648 6549 davidmj
                $header .= pack('a12', sprintf("%011o", $stat[9]));        // last mod time
649 4287 psotfx
650 4306 psotfx
                // Checksum
651 5074 acydburn
                $checksum = 0;
652 5581 davidmj
                for ($i = 0; $i < 148; $i++)
653 4287 psotfx
                {
654 6549 davidmj
                        $checksum += ord($header[$i]);
655 4287 psotfx
                }
656 4287 psotfx
657 5581 davidmj
                // We precompute the rest of the hash, this saves us time in the loop and allows us to insert our hash without resorting to string functions
658 5581 davidmj
                $checksum += 2415 + (($is_dir) ? 53 : 0);
659 4287 psotfx
660 6549 davidmj
                $header .= pack('a8', sprintf("%07o", $checksum));        // checksum
661 6549 davidmj
                $header .= pack('a1', $typeflag);                                        // link indicator
662 6549 davidmj
                $header .= pack('a100', '');                                                // name of linked file
663 6549 davidmj
                $header .= pack('a6', 'ustar');                                                // ustar indicator
664 6549 davidmj
                $header .= pack('a2', '00');                                                // ustar version
665 6549 davidmj
                $header .= pack('a32', 'Unknown');                                        // owner name
666 6549 davidmj
                $header .= pack('a32', 'Unknown');                                        // group name
667 6549 davidmj
                $header .= pack('a8', '');                                                        // device major number
668 6549 davidmj
                $header .= pack('a8', '');                                                        // device minor number
669 6549 davidmj
                $header .= pack('a155', '');                                                // filename prefix
670 6549 davidmj
                $header .= pack('a12', '');                                                        // end
671 5581 davidmj
672 5581 davidmj
                // This writes the entire file in one shot. Header, followed by data and then null padded to a multiple of 512
673 6549 davidmj
                $fzwrite($this->fp, $header . (($stat[7] !== 0 && !$is_dir) ? $data . str_repeat("\0", (($stat[7] + 511) &~ 511) - $stat[7]) : ''));
674 5581 davidmj
                unset($data);
675 4287 psotfx
        }
676 4398 psotfx
677 6015 acydburn
        /**
678 6015 acydburn
        * Open archive
679 6015 acydburn
        */
680 5074 acydburn
        function open()
681 4398 psotfx
        {
682 6073 acydburn
                $fzopen = ($this->isbz && function_exists('bzopen')) ? 'bzopen' : (($this->isgz && @extension_loaded('zlib')) ? 'gzopen' : 'fopen');
683 6688 davidmj
                $this->fp = @$fzopen($this->file, $this->mode . (($fzopen == 'bzopen') ? '' : 'b') . (($fzopen == 'gzopen') ? '9' : ''));
684 5315 acydburn
685 5315 acydburn
                if (!$this->fp)
686 5315 acydburn
                {
687 5315 acydburn
                        trigger_error('Unable to open file ' . $this->file . ' [' . $fzopen . ' - ' . $this->mode . 'b]');
688 5315 acydburn
                }
689 4398 psotfx
        }
690 5074 acydburn
691 6015 acydburn
        /**
692 6015 acydburn
        * Download archive
693 6015 acydburn
        */
694 7134 acydburn
        function download($filename, $download_name = false)
695 5074 acydburn
        {
696 5074 acydburn
                global $phpbb_root_path;
697 5074 acydburn
698 7134 acydburn
                if ($download_name === false)
699 7134 acydburn
                {
700 7134 acydburn
                        $download_name = $filename;
701 7134 acydburn
                }
702 7134 acydburn
703 5074 acydburn
                switch ($this->type)
704 5074 acydburn
                {
705 5647 davidmj
                        case '.tar':
706 5074 acydburn
                                $mimetype = 'application/x-tar';
707 5377 acydburn
                        break;
708 5074 acydburn
709 5647 davidmj
                        case '.tar.gz':
710 5074 acydburn
                                $mimetype = 'application/x-gzip';
711 5377 acydburn
                        break;
712 5074 acydburn
713 5647 davidmj
                        case '.tar.bz2':
714 5074 acydburn
                                $mimetype = 'application/x-bzip2';
715 5377 acydburn
                        break;
716 5315 acydburn
717 5074 acydburn
                        default:
718 5074 acydburn
                                $mimetype = 'application/octet-stream';
719 5377 acydburn
                        break;
720 5074 acydburn
                }
721 5074 acydburn
722 5074 acydburn
                header('Pragma: no-cache');
723 7134 acydburn
                header("Content-Type: $mimetype; name=\"$download_name$this->type\"");
724 7134 acydburn
                header("Content-disposition: attachment; filename=$download_name$this->type");
725 5074 acydburn
726 7877 davidmj
                $fp = @fopen("{$phpbb_root_path}store/$filename$this->type", 'rb');
727 7877 davidmj
                if ($fp)
728 5074 acydburn
                {
729 7877 davidmj
                        while ($buffer = fread($fp, 1024))
730 7877 davidmj
                        {
731 7877 davidmj
                                echo $buffer;
732 7877 davidmj
                        }
733 7877 davidmj
                        fclose($fp);
734 5074 acydburn
                }
735 5074 acydburn
        }
736 4287 psotfx
}