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