[ Index ]

PHP Cross Reference of phpBB-3.3.11-deutsch

title

Body

[close]

/includes/ -> functions_compress.php (source)

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


Generated: Sat Nov 4 14:26:03 2023 Cross-referenced by PHPXref 0.7.1