[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> functions_transfer.php (source)

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


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6