phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_compress.php

History | View | Annotate | Download (18.6 kB)

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