[ Index ] |
PHP Cross Reference of phpBB-3.2.11-deutsch |
[Summary view] [Print] [Text view]
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 * Transfer class, wrapper for ftp/sftp/ssh 24 */ 25 class transfer 26 { 27 var $connection; 28 var $host; 29 var $port; 30 var $username; 31 var $password; 32 var $timeout; 33 var $root_path; 34 var $tmp_path; 35 var $file_perms; 36 var $dir_perms; 37 38 /** 39 * Constructor - init some basic values 40 */ 41 function __construct() 42 { 43 global $phpbb_root_path; 44 45 $this->file_perms = 0644; 46 $this->dir_perms = 0777; 47 48 // We use the store directory as temporary path to circumvent open basedir restrictions 49 $this->tmp_path = $phpbb_root_path . 'store/'; 50 } 51 52 /** 53 * Write file to location 54 */ 55 function write_file($destination_file = '', $contents = '') 56 { 57 global $phpbb_root_path; 58 59 $destination_file = $this->root_path . str_replace($phpbb_root_path, '', $destination_file); 60 61 // need to create a temp file and then move that temp file. 62 // ftp functions can only move files around and can't create. 63 // This means that the users will need to have access to write 64 // temporary files or have write access on a folder within phpBB 65 // like the cache folder. If the user can't do either, then 66 // he/she needs to use the fsock ftp method 67 $temp_name = tempnam($this->tmp_path, 'transfer_'); 68 @unlink($temp_name); 69 70 $fp = @fopen($temp_name, 'w'); 71 72 if (!$fp) 73 { 74 trigger_error('Unable to create temporary file ' . $temp_name, E_USER_ERROR); 75 } 76 77 @fwrite($fp, $contents); 78 @fclose($fp); 79 80 $result = $this->overwrite_file($temp_name, $destination_file); 81 82 // remove temporary file now 83 @unlink($temp_name); 84 85 return $result; 86 } 87 88 /** 89 * Moving file into location. If the destination file already exists it gets overwritten 90 */ 91 function overwrite_file($source_file, $destination_file) 92 { 93 /** 94 * @todo generally think about overwriting files in another way, by creating a temporary file and then renaming it 95 * @todo check for the destination file existance too 96 */ 97 $this->_delete($destination_file); 98 $result = $this->_put($source_file, $destination_file); 99 $this->_chmod($destination_file, $this->file_perms); 100 101 return $result; 102 } 103 104 /** 105 * Create directory structure 106 */ 107 function make_dir($dir) 108 { 109 global $phpbb_root_path; 110 111 $dir = str_replace($phpbb_root_path, '', $dir); 112 $dir = explode('/', $dir); 113 $dirs = ''; 114 115 for ($i = 0, $total = count($dir); $i < $total; $i++) 116 { 117 $result = true; 118 119 if (strpos($dir[$i], '.') === 0) 120 { 121 continue; 122 } 123 $cur_dir = $dir[$i] . '/'; 124 125 if (!file_exists($phpbb_root_path . $dirs . $cur_dir)) 126 { 127 // create the directory 128 $result = $this->_mkdir($dir[$i]); 129 $this->_chmod($dir[$i], $this->dir_perms); 130 } 131 132 $this->_chdir($this->root_path . $dirs . $dir[$i]); 133 $dirs .= $cur_dir; 134 } 135 136 $this->_chdir($this->root_path); 137 138 /** 139 * @todo stack result into array to make sure every path creation has been taken care of 140 */ 141 return $result; 142 } 143 144 /** 145 * Copy file from source location to destination location 146 */ 147 function copy_file($from_loc, $to_loc) 148 { 149 global $phpbb_root_path; 150 151 $from_loc = ((strpos($from_loc, $phpbb_root_path) !== 0) ? $phpbb_root_path : '') . $from_loc; 152 $to_loc = $this->root_path . str_replace($phpbb_root_path, '', $to_loc); 153 154 if (!file_exists($from_loc)) 155 { 156 return false; 157 } 158 159 $result = $this->overwrite_file($from_loc, $to_loc); 160 161 return $result; 162 } 163 164 /** 165 * Remove file 166 */ 167 function delete_file($file) 168 { 169 global $phpbb_root_path; 170 171 $file = $this->root_path . str_replace($phpbb_root_path, '', $file); 172 173 return $this->_delete($file); 174 } 175 176 /** 177 * Remove directory 178 * @todo remove child directories? 179 */ 180 function remove_dir($dir) 181 { 182 global $phpbb_root_path; 183 184 $dir = $this->root_path . str_replace($phpbb_root_path, '', $dir); 185 186 return $this->_rmdir($dir); 187 } 188 189 /** 190 * Rename a file or folder 191 */ 192 function rename($old_handle, $new_handle) 193 { 194 global $phpbb_root_path; 195 196 $old_handle = $this->root_path . str_replace($phpbb_root_path, '', $old_handle); 197 198 return $this->_rename($old_handle, $new_handle); 199 } 200 201 /** 202 * Check if a specified file exist... 203 */ 204 function file_exists($directory, $filename) 205 { 206 global $phpbb_root_path; 207 208 $directory = $this->root_path . str_replace($phpbb_root_path, '', $directory); 209 210 $this->_chdir($directory); 211 $result = $this->_ls(); 212 213 if ($result !== false && is_array($result)) 214 { 215 return (in_array($filename, $result)) ? true : false; 216 } 217 218 return false; 219 } 220 221 /** 222 * Open session 223 */ 224 function open_session() 225 { 226 return $this->_init(); 227 } 228 229 /** 230 * Close current session 231 */ 232 function close_session() 233 { 234 return $this->_close(); 235 } 236 237 /** 238 * Determine methods able to be used 239 */ 240 static public function methods() 241 { 242 $methods = array(); 243 $disabled_functions = explode(',', @ini_get('disable_functions')); 244 245 if (@extension_loaded('ftp')) 246 { 247 $methods[] = 'ftp'; 248 } 249 250 if (!in_array('fsockopen', $disabled_functions)) 251 { 252 $methods[] = 'ftp_fsock'; 253 } 254 255 return $methods; 256 } 257 } 258 259 /** 260 * FTP transfer class 261 */ 262 class ftp extends transfer 263 { 264 /** 265 * Standard parameters for FTP session 266 */ 267 function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) 268 { 269 $this->host = $host; 270 $this->port = $port; 271 $this->username = $username; 272 $this->password = $password; 273 $this->timeout = $timeout; 274 275 // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end) 276 $this->root_path = str_replace('\\', '/', $this->root_path); 277 278 if (!empty($root_path)) 279 { 280 $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); 281 } 282 283 // Init some needed values 284 $this->transfer(); 285 286 return; 287 } 288 289 /** 290 * Requests data 291 */ 292 static public function data() 293 { 294 global $user; 295 296 return array( 297 'host' => 'localhost', 298 'username' => 'anonymous', 299 'password' => '', 300 'root_path' => $user->page['root_script_path'], 301 'port' => 21, 302 'timeout' => 10 303 ); 304 } 305 306 /** 307 * Init FTP Session 308 * @access private 309 */ 310 function _init() 311 { 312 // connect to the server 313 $this->connection = @ftp_connect($this->host, $this->port, $this->timeout); 314 315 if (!$this->connection) 316 { 317 return 'ERR_CONNECTING_SERVER'; 318 } 319 320 // login to the server 321 if (!@ftp_login($this->connection, $this->username, $this->password)) 322 { 323 return 'ERR_UNABLE_TO_LOGIN'; 324 } 325 326 // attempt to turn pasv mode on 327 @ftp_pasv($this->connection, true); 328 329 // change to the root directory 330 if (!$this->_chdir($this->root_path)) 331 { 332 return 'ERR_CHANGING_DIRECTORY'; 333 } 334 335 return true; 336 } 337 338 /** 339 * Create Directory (MKDIR) 340 * @access private 341 */ 342 function _mkdir($dir) 343 { 344 return @ftp_mkdir($this->connection, $dir); 345 } 346 347 /** 348 * Remove directory (RMDIR) 349 * @access private 350 */ 351 function _rmdir($dir) 352 { 353 return @ftp_rmdir($this->connection, $dir); 354 } 355 356 /** 357 * Rename file 358 * @access private 359 */ 360 function _rename($old_handle, $new_handle) 361 { 362 return @ftp_rename($this->connection, $old_handle, $new_handle); 363 } 364 365 /** 366 * Change current working directory (CHDIR) 367 * @access private 368 */ 369 function _chdir($dir = '') 370 { 371 if ($dir && $dir !== '/') 372 { 373 if (substr($dir, -1, 1) == '/') 374 { 375 $dir = substr($dir, 0, -1); 376 } 377 } 378 379 return @ftp_chdir($this->connection, $dir); 380 } 381 382 /** 383 * change file permissions (CHMOD) 384 * @access private 385 */ 386 function _chmod($file, $perms) 387 { 388 if (function_exists('ftp_chmod')) 389 { 390 $err = @ftp_chmod($this->connection, $perms, $file); 391 } 392 else 393 { 394 // Unfortunatly CHMOD is not expecting an octal value... 395 // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) 396 $chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file; 397 $err = $this->_site($chmod_cmd); 398 } 399 400 return $err; 401 } 402 403 /** 404 * Upload file to location (PUT) 405 * @access private 406 */ 407 function _put($from_file, $to_file) 408 { 409 // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) 410 $mode = FTP_BINARY; 411 412 $to_dir = dirname($to_file); 413 $to_file = basename($to_file); 414 $this->_chdir($to_dir); 415 416 $result = @ftp_put($this->connection, $to_file, $from_file, $mode); 417 $this->_chdir($this->root_path); 418 419 return $result; 420 } 421 422 /** 423 * Delete file (DELETE) 424 * @access private 425 */ 426 function _delete($file) 427 { 428 return @ftp_delete($this->connection, $file); 429 } 430 431 /** 432 * Close ftp session (CLOSE) 433 * @access private 434 */ 435 function _close() 436 { 437 if (!$this->connection) 438 { 439 return false; 440 } 441 442 return @ftp_quit($this->connection); 443 } 444 445 /** 446 * Return current working directory (CWD) 447 * At the moment not used by parent class 448 * @access private 449 */ 450 function _cwd() 451 { 452 return @ftp_pwd($this->connection); 453 } 454 455 /** 456 * Return list of files in a given directory (LS) 457 * @access private 458 */ 459 function _ls($dir = './') 460 { 461 $list = @ftp_nlist($this->connection, $dir); 462 463 // See bug #46295 - Some FTP daemons don't like './' 464 if ($dir === './') 465 { 466 // Let's try some alternatives 467 $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list; 468 $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list; 469 } 470 471 // Return on error 472 if ($list === false) 473 { 474 return false; 475 } 476 477 // Remove path if prepended 478 foreach ($list as $key => $item) 479 { 480 // Use same separator for item and dir 481 $item = str_replace('\\', '/', $item); 482 $dir = str_replace('\\', '/', $dir); 483 484 if (!empty($dir) && strpos($item, $dir) === 0) 485 { 486 $item = substr($item, strlen($dir)); 487 } 488 489 $list[$key] = $item; 490 } 491 492 return $list; 493 } 494 495 /** 496 * FTP SITE command (ftp-only function) 497 * @access private 498 */ 499 function _site($command) 500 { 501 return @ftp_site($this->connection, $command); 502 } 503 } 504 505 /** 506 * FTP fsock transfer class 507 */ 508 class ftp_fsock extends transfer 509 { 510 var $data_connection; 511 512 /** 513 * Standard parameters for FTP session 514 */ 515 function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) 516 { 517 $this->host = $host; 518 $this->port = $port; 519 $this->username = $username; 520 $this->password = $password; 521 $this->timeout = $timeout; 522 523 // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end) 524 $this->root_path = str_replace('\\', '/', $this->root_path); 525 526 if (!empty($root_path)) 527 { 528 $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); 529 } 530 531 // Init some needed values 532 parent::__construct(); 533 534 return; 535 } 536 537 /** 538 * Requests data 539 */ 540 static public function data() 541 { 542 global $user; 543 544 return array( 545 'host' => 'localhost', 546 'username' => 'anonymous', 547 'password' => '', 548 'root_path' => $user->page['root_script_path'], 549 'port' => 21, 550 'timeout' => 10 551 ); 552 } 553 554 /** 555 * Init FTP Session 556 * @access private 557 */ 558 function _init() 559 { 560 $errno = 0; 561 $errstr = ''; 562 563 // connect to the server 564 $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); 565 566 if (!$this->connection || !$this->_check_command()) 567 { 568 return 'ERR_CONNECTING_SERVER'; 569 } 570 571 @stream_set_timeout($this->connection, $this->timeout); 572 573 // login 574 if (!$this->_send_command('USER', $this->username)) 575 { 576 return 'ERR_UNABLE_TO_LOGIN'; 577 } 578 579 if (!$this->_send_command('PASS', $this->password)) 580 { 581 return 'ERR_UNABLE_TO_LOGIN'; 582 } 583 584 // change to the root directory 585 if (!$this->_chdir($this->root_path)) 586 { 587 return 'ERR_CHANGING_DIRECTORY'; 588 } 589 590 return true; 591 } 592 593 /** 594 * Create Directory (MKDIR) 595 * @access private 596 */ 597 function _mkdir($dir) 598 { 599 return $this->_send_command('MKD', $dir); 600 } 601 602 /** 603 * Remove directory (RMDIR) 604 * @access private 605 */ 606 function _rmdir($dir) 607 { 608 return $this->_send_command('RMD', $dir); 609 } 610 611 /** 612 * Rename File 613 * @access private 614 */ 615 function _rename($old_handle, $new_handle) 616 { 617 $this->_send_command('RNFR', $old_handle); 618 return $this->_send_command('RNTO', $new_handle); 619 } 620 621 /** 622 * Change current working directory (CHDIR) 623 * @access private 624 */ 625 function _chdir($dir = '') 626 { 627 if ($dir && $dir !== '/') 628 { 629 if (substr($dir, -1, 1) == '/') 630 { 631 $dir = substr($dir, 0, -1); 632 } 633 } 634 635 return $this->_send_command('CWD', $dir); 636 } 637 638 /** 639 * change file permissions (CHMOD) 640 * @access private 641 */ 642 function _chmod($file, $perms) 643 { 644 // Unfortunatly CHMOD is not expecting an octal value... 645 // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) 646 return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file); 647 } 648 649 /** 650 * Upload file to location (PUT) 651 * @access private 652 */ 653 function _put($from_file, $to_file) 654 { 655 // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) 656 // 'I' == BINARY 657 // 'A' == ASCII 658 if (!$this->_send_command('TYPE', 'I')) 659 { 660 return false; 661 } 662 663 // open the connection to send file over 664 if (!$this->_open_data_connection()) 665 { 666 return false; 667 } 668 669 $this->_send_command('STOR', $to_file, false); 670 671 // send the file 672 $fp = @fopen($from_file, 'rb'); 673 while (!@feof($fp)) 674 { 675 @fwrite($this->data_connection, @fread($fp, 4096)); 676 } 677 @fclose($fp); 678 679 // close connection 680 $this->_close_data_connection(); 681 682 return $this->_check_command(); 683 } 684 685 /** 686 * Delete file (DELETE) 687 * @access private 688 */ 689 function _delete($file) 690 { 691 return $this->_send_command('DELE', $file); 692 } 693 694 /** 695 * Close ftp session (CLOSE) 696 * @access private 697 */ 698 function _close() 699 { 700 if (!$this->connection) 701 { 702 return false; 703 } 704 705 return $this->_send_command('QUIT'); 706 } 707 708 /** 709 * Return current working directory (CWD) 710 * At the moment not used by parent class 711 * @access private 712 */ 713 function _cwd() 714 { 715 $this->_send_command('PWD', '', false); 716 return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true)); 717 } 718 719 /** 720 * Return list of files in a given directory (LS) 721 * @access private 722 */ 723 function _ls($dir = './') 724 { 725 if (!$this->_open_data_connection()) 726 { 727 return false; 728 } 729 730 $this->_send_command('NLST', $dir); 731 732 $list = array(); 733 while (!@feof($this->data_connection)) 734 { 735 $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512)); 736 737 if ($filename !== '') 738 { 739 $list[] = $filename; 740 } 741 } 742 $this->_close_data_connection(); 743 744 // Clear buffer 745 $this->_check_command(); 746 747 // See bug #46295 - Some FTP daemons don't like './' 748 if ($dir === './' && empty($list)) 749 { 750 // Let's try some alternatives 751 $list = $this->_ls('.'); 752 753 if (empty($list)) 754 { 755 $list = $this->_ls(''); 756 } 757 758 return $list; 759 } 760 761 // Remove path if prepended 762 foreach ($list as $key => $item) 763 { 764 // Use same separator for item and dir 765 $item = str_replace('\\', '/', $item); 766 $dir = str_replace('\\', '/', $dir); 767 768 if (!empty($dir) && strpos($item, $dir) === 0) 769 { 770 $item = substr($item, strlen($dir)); 771 } 772 773 $list[$key] = $item; 774 } 775 776 return $list; 777 } 778 779 /** 780 * Send a command to server (FTP fsock only function) 781 * @access private 782 */ 783 function _send_command($command, $args = '', $check = true) 784 { 785 if (!empty($args)) 786 { 787 $command = "$command $args"; 788 } 789 790 fwrite($this->connection, $command . "\r\n"); 791 792 if ($check === true && !$this->_check_command()) 793 { 794 return false; 795 } 796 797 return true; 798 } 799 800 /** 801 * Opens a connection to send data (FTP fosck only function) 802 * @access private 803 */ 804 function _open_data_connection() 805 { 806 // Try to find out whether we have a IPv4 or IPv6 (control) connection 807 if (function_exists('stream_socket_get_name')) 808 { 809 $socket_name = stream_socket_get_name($this->connection, true); 810 $server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); 811 } 812 813 if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip)) 814 { 815 // Passive mode 816 $this->_send_command('PASV', '', false); 817 818 if (!$ip_port = $this->_check_command(true)) 819 { 820 return false; 821 } 822 823 // open the connection to start sending the file 824 if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) 825 { 826 // bad ip and port 827 return false; 828 } 829 830 $temp = explode(',', $temp[0]); 831 $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; 832 $server_port = $temp[4] * 256 + $temp[5]; 833 } 834 else 835 { 836 // Extended Passive Mode - RFC2428 837 $this->_send_command('EPSV', '', false); 838 839 if (!$epsv_response = $this->_check_command(true)) 840 { 841 return false; 842 } 843 844 // Response looks like "229 Entering Extended Passive Mode (|||12345|)" 845 // where 12345 is the tcp port for the data connection 846 if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) 847 { 848 return false; 849 } 850 $server_port = (int) $match[1]; 851 852 // fsockopen expects IPv6 address in square brackets 853 $server_ip = "[$server_ip]"; 854 } 855 856 $errno = 0; 857 $errstr = ''; 858 859 if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) 860 { 861 return false; 862 } 863 @stream_set_timeout($this->data_connection, $this->timeout); 864 865 return true; 866 } 867 868 /** 869 * Closes a connection used to send data 870 * @access private 871 */ 872 function _close_data_connection() 873 { 874 return @fclose($this->data_connection); 875 } 876 877 /** 878 * Check to make sure command was successful (FTP fsock only function) 879 * @access private 880 */ 881 function _check_command($return = false) 882 { 883 $response = ''; 884 885 do 886 { 887 $result = @fgets($this->connection, 512); 888 $response .= $result; 889 } 890 while (substr($result, 3, 1) !== ' '); 891 892 if (!preg_match('#^[123]#', $response)) 893 { 894 return false; 895 } 896 897 return ($return) ? $response : true; 898 } 899 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 11 20:33:01 2020 | Cross-referenced by PHPXref 0.7.1 |