[ Index ] |
PHP Cross Reference of phpBB-3.3.14-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 parent::__construct(); 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 if (!$this->connection) 345 { 346 return false; 347 } 348 349 return @ftp_mkdir($this->connection, $dir); 350 } 351 352 /** 353 * Remove directory (RMDIR) 354 * @access private 355 */ 356 function _rmdir($dir) 357 { 358 if (!$this->connection) 359 { 360 return false; 361 } 362 363 return @ftp_rmdir($this->connection, $dir); 364 } 365 366 /** 367 * Rename file 368 * @access private 369 */ 370 function _rename($old_handle, $new_handle) 371 { 372 if (!$this->connection) 373 { 374 return false; 375 } 376 377 return @ftp_rename($this->connection, $old_handle, $new_handle); 378 } 379 380 /** 381 * Change current working directory (CHDIR) 382 * @access private 383 */ 384 function _chdir($dir = '') 385 { 386 if (!$this->connection) 387 { 388 return false; 389 } 390 391 if ($dir && $dir !== '/') 392 { 393 if (substr($dir, -1, 1) == '/') 394 { 395 $dir = substr($dir, 0, -1); 396 } 397 } 398 399 return @ftp_chdir($this->connection, $dir); 400 } 401 402 /** 403 * change file permissions (CHMOD) 404 * @access private 405 */ 406 function _chmod($file, $perms) 407 { 408 if (!$this->connection) 409 { 410 return false; 411 } 412 413 if (function_exists('ftp_chmod')) 414 { 415 $err = @ftp_chmod($this->connection, $perms, $file); 416 } 417 else 418 { 419 // Unfortunatly CHMOD is not expecting an octal value... 420 // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) 421 $chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file; 422 $err = $this->_site($chmod_cmd); 423 } 424 425 return $err; 426 } 427 428 /** 429 * Upload file to location (PUT) 430 * @access private 431 */ 432 function _put($from_file, $to_file) 433 { 434 if (!$this->connection) 435 { 436 return false; 437 } 438 439 // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) 440 $mode = FTP_BINARY; 441 442 $to_dir = dirname($to_file); 443 $to_file = basename($to_file); 444 $this->_chdir($to_dir); 445 446 $result = @ftp_put($this->connection, $to_file, $from_file, $mode); 447 $this->_chdir($this->root_path); 448 449 return $result; 450 } 451 452 /** 453 * Delete file (DELETE) 454 * @access private 455 */ 456 function _delete($file) 457 { 458 if (!$this->connection) 459 { 460 return false; 461 } 462 463 return @ftp_delete($this->connection, $file); 464 } 465 466 /** 467 * Close ftp session (CLOSE) 468 * @access private 469 */ 470 function _close() 471 { 472 if (!$this->connection) 473 { 474 return false; 475 } 476 477 return @ftp_quit($this->connection); 478 } 479 480 /** 481 * Return current working directory (CWD) 482 * At the moment not used by parent class 483 * @access private 484 */ 485 function _cwd() 486 { 487 if (!$this->connection) 488 { 489 return false; 490 } 491 492 return @ftp_pwd($this->connection); 493 } 494 495 /** 496 * Return list of files in a given directory (LS) 497 * @access private 498 */ 499 function _ls($dir = './') 500 { 501 if (!$this->connection) 502 { 503 return false; 504 } 505 506 $list = @ftp_nlist($this->connection, $dir); 507 508 // See bug #46295 - Some FTP daemons don't like './' 509 if ($dir === './') 510 { 511 // Let's try some alternatives 512 $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list; 513 $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list; 514 } 515 516 // Return on error 517 if ($list === false) 518 { 519 return false; 520 } 521 522 // Remove path if prepended 523 foreach ($list as $key => $item) 524 { 525 // Use same separator for item and dir 526 $item = str_replace('\\', '/', $item); 527 $dir = str_replace('\\', '/', $dir); 528 529 if (!empty($dir) && strpos($item, $dir) === 0) 530 { 531 $item = substr($item, strlen($dir)); 532 } 533 534 $list[$key] = $item; 535 } 536 537 return $list; 538 } 539 540 /** 541 * FTP SITE command (ftp-only function) 542 * @access private 543 */ 544 function _site($command) 545 { 546 if (!$this->connection) 547 { 548 return false; 549 } 550 551 return @ftp_site($this->connection, $command); 552 } 553 } 554 555 /** 556 * FTP fsock transfer class 557 */ 558 class ftp_fsock extends transfer 559 { 560 var $data_connection; 561 562 /** 563 * Standard parameters for FTP session 564 */ 565 function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) 566 { 567 $this->host = $host; 568 $this->port = $port; 569 $this->username = $username; 570 $this->password = $password; 571 $this->timeout = $timeout; 572 573 // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end) 574 $this->root_path = str_replace('\\', '/', $this->root_path); 575 576 if (!empty($root_path)) 577 { 578 $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); 579 } 580 581 // Init some needed values 582 parent::__construct(); 583 584 return; 585 } 586 587 /** 588 * Requests data 589 */ 590 static public function data() 591 { 592 global $user; 593 594 return array( 595 'host' => 'localhost', 596 'username' => 'anonymous', 597 'password' => '', 598 'root_path' => $user->page['root_script_path'], 599 'port' => 21, 600 'timeout' => 10 601 ); 602 } 603 604 /** 605 * Init FTP Session 606 * @access private 607 */ 608 function _init() 609 { 610 $errno = 0; 611 $errstr = ''; 612 613 // connect to the server 614 $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); 615 616 if (!$this->connection || !$this->_check_command()) 617 { 618 return 'ERR_CONNECTING_SERVER'; 619 } 620 621 @stream_set_timeout($this->connection, $this->timeout); 622 623 // login 624 if (!$this->_send_command('USER', $this->username)) 625 { 626 return 'ERR_UNABLE_TO_LOGIN'; 627 } 628 629 if (!$this->_send_command('PASS', $this->password)) 630 { 631 return 'ERR_UNABLE_TO_LOGIN'; 632 } 633 634 // change to the root directory 635 if (!$this->_chdir($this->root_path)) 636 { 637 return 'ERR_CHANGING_DIRECTORY'; 638 } 639 640 return true; 641 } 642 643 /** 644 * Create Directory (MKDIR) 645 * @access private 646 */ 647 function _mkdir($dir) 648 { 649 return $this->_send_command('MKD', $dir); 650 } 651 652 /** 653 * Remove directory (RMDIR) 654 * @access private 655 */ 656 function _rmdir($dir) 657 { 658 return $this->_send_command('RMD', $dir); 659 } 660 661 /** 662 * Rename File 663 * @access private 664 */ 665 function _rename($old_handle, $new_handle) 666 { 667 $this->_send_command('RNFR', $old_handle); 668 return $this->_send_command('RNTO', $new_handle); 669 } 670 671 /** 672 * Change current working directory (CHDIR) 673 * @access private 674 */ 675 function _chdir($dir = '') 676 { 677 if ($dir && $dir !== '/') 678 { 679 if (substr($dir, -1, 1) == '/') 680 { 681 $dir = substr($dir, 0, -1); 682 } 683 } 684 685 return $this->_send_command('CWD', $dir); 686 } 687 688 /** 689 * change file permissions (CHMOD) 690 * @access private 691 */ 692 function _chmod($file, $perms) 693 { 694 // Unfortunatly CHMOD is not expecting an octal value... 695 // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) 696 return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file); 697 } 698 699 /** 700 * Upload file to location (PUT) 701 * @access private 702 */ 703 function _put($from_file, $to_file) 704 { 705 // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) 706 // 'I' == BINARY 707 // 'A' == ASCII 708 if (!$this->_send_command('TYPE', 'I')) 709 { 710 return false; 711 } 712 713 // open the connection to send file over 714 if (!$this->_open_data_connection()) 715 { 716 return false; 717 } 718 719 $this->_send_command('STOR', $to_file, false); 720 721 // send the file 722 $fp = @fopen($from_file, 'rb'); 723 while (!@feof($fp)) 724 { 725 @fwrite($this->data_connection, @fread($fp, 4096)); 726 } 727 @fclose($fp); 728 729 // close connection 730 $this->_close_data_connection(); 731 732 return $this->_check_command(); 733 } 734 735 /** 736 * Delete file (DELETE) 737 * @access private 738 */ 739 function _delete($file) 740 { 741 return $this->_send_command('DELE', $file); 742 } 743 744 /** 745 * Close ftp session (CLOSE) 746 * @access private 747 */ 748 function _close() 749 { 750 if (!$this->connection) 751 { 752 return false; 753 } 754 755 return $this->_send_command('QUIT'); 756 } 757 758 /** 759 * Return current working directory (CWD) 760 * At the moment not used by parent class 761 * @access private 762 */ 763 function _cwd() 764 { 765 $this->_send_command('PWD', '', false); 766 return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true)); 767 } 768 769 /** 770 * Return list of files in a given directory (LS) 771 * @access private 772 */ 773 function _ls($dir = './') 774 { 775 if (!$this->_open_data_connection()) 776 { 777 return false; 778 } 779 780 $this->_send_command('NLST', $dir); 781 782 $list = array(); 783 while (!@feof($this->data_connection)) 784 { 785 $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512)); 786 787 if ($filename !== '') 788 { 789 $list[] = $filename; 790 } 791 } 792 $this->_close_data_connection(); 793 794 // Clear buffer 795 $this->_check_command(); 796 797 // See bug #46295 - Some FTP daemons don't like './' 798 if ($dir === './' && empty($list)) 799 { 800 // Let's try some alternatives 801 $list = $this->_ls('.'); 802 803 if (empty($list)) 804 { 805 $list = $this->_ls(''); 806 } 807 808 return $list; 809 } 810 811 // Remove path if prepended 812 foreach ($list as $key => $item) 813 { 814 // Use same separator for item and dir 815 $item = str_replace('\\', '/', $item); 816 $dir = str_replace('\\', '/', $dir); 817 818 if (!empty($dir) && strpos($item, $dir) === 0) 819 { 820 $item = substr($item, strlen($dir)); 821 } 822 823 $list[$key] = $item; 824 } 825 826 return $list; 827 } 828 829 /** 830 * Send a command to server (FTP fsock only function) 831 * @access private 832 */ 833 function _send_command($command, $args = '', $check = true) 834 { 835 if (!$this->connection) 836 { 837 return false; 838 } 839 840 if (!empty($args)) 841 { 842 $command = "$command $args"; 843 } 844 845 fwrite($this->connection, $command . "\r\n"); 846 847 if ($check === true && !$this->_check_command()) 848 { 849 return false; 850 } 851 852 return true; 853 } 854 855 /** 856 * Opens a connection to send data (FTP fosck only function) 857 * @access private 858 */ 859 function _open_data_connection() 860 { 861 // Try to find out whether we have a IPv4 or IPv6 (control) connection 862 if (function_exists('stream_socket_get_name')) 863 { 864 $socket_name = stream_socket_get_name($this->connection, true); 865 $server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); 866 } 867 868 if (isset($server_ip) && filter_var($server_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) // ipv4 869 { 870 // Passive mode 871 $this->_send_command('PASV', '', false); 872 873 if (!$ip_port = $this->_check_command(true)) 874 { 875 return false; 876 } 877 878 // open the connection to start sending the file 879 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)) 880 { 881 // bad ip and port 882 return false; 883 } 884 885 $temp = explode(',', $temp[0]); 886 $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; 887 $server_port = $temp[4] * 256 + $temp[5]; 888 } 889 else // ipv6 890 { 891 // Extended Passive Mode - RFC2428 892 $this->_send_command('EPSV', '', false); 893 894 if (!$epsv_response = $this->_check_command(true)) 895 { 896 return false; 897 } 898 899 // Response looks like "229 Entering Extended Passive Mode (|||12345|)" 900 // where 12345 is the tcp port for the data connection 901 if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) 902 { 903 return false; 904 } 905 $server_port = (int) $match[1]; 906 907 // fsockopen expects IPv6 address in square brackets 908 $server_ip = "[$server_ip]"; 909 } 910 911 $errno = 0; 912 $errstr = ''; 913 914 if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) 915 { 916 return false; 917 } 918 @stream_set_timeout($this->data_connection, $this->timeout); 919 920 return true; 921 } 922 923 /** 924 * Closes a connection used to send data 925 * @access private 926 */ 927 function _close_data_connection() 928 { 929 if (!$this->connection) 930 { 931 return false; 932 } 933 934 return @fclose($this->data_connection); 935 } 936 937 /** 938 * Check to make sure command was successful (FTP fsock only function) 939 * @access private 940 */ 941 function _check_command($return = false) 942 { 943 if (!$this->connection) 944 { 945 return false; 946 } 947 948 $response = ''; 949 950 do 951 { 952 $result = @fgets($this->connection, 512); 953 $response .= $result; 954 } 955 while (substr($result, 3, 1) !== ' '); 956 957 if (!preg_match('#^[123]#', $response)) 958 { 959 return false; 960 } 961 962 return ($return) ? $response : true; 963 } 964 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |