Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_compress.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 19.55 KiB


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