phpBB
Statistics
| Revision:

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