Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 3 |
|
0.00% |
0 / 43 |
CRAP | |
0.00% |
0 / 276 |
transfer | |
0.00% |
0 / 1 |
|
0.00% |
0 / 12 |
552.00 | |
0.00% |
0 / 69 |
__construct | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 5 |
|||
write_file | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 12 |
|||
overwrite_file | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 4 |
|||
make_dir | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 16 |
|||
copy_file | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 7 |
|||
delete_file | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 3 |
|||
remove_dir | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 3 |
|||
rename | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 3 |
|||
file_exists | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 7 |
|||
open_session | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
close_session | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
methods | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 7 |
|||
ftp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 14 |
1806.00 | |
0.00% |
0 / 84 |
__construct | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 10 |
|||
data | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 7 |
|||
_init | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 9 |
|||
_mkdir | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_rmdir | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_rename | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_chdir | |
0.00% |
0 / 1 |
30.00 | |
0.00% |
0 / 6 |
|||
_chmod | |
0.00% |
0 / 1 |
12.00 | |
0.00% |
0 / 7 |
|||
_put | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 9 |
|||
_delete | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_close | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_cwd | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_ls | |
0.00% |
0 / 1 |
90.00 | |
0.00% |
0 / 15 |
|||
_site | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
ftp_fsock | |
0.00% |
0 / 1 |
|
0.00% |
0 / 17 |
3422.00 | |
0.00% |
0 / 123 |
__construct | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 10 |
|||
data | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 7 |
|||
_init | |
0.00% |
0 / 1 |
42.00 | |
0.00% |
0 / 13 |
|||
_mkdir | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
_rmdir | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
_rename | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 2 |
|||
_chdir | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 4 |
|||
_chmod | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
_put | |
0.00% |
0 / 1 |
20.00 | |
0.00% |
0 / 11 |
|||
_delete | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 1 |
|||
_close | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_cwd | |
0.00% |
0 / 1 |
2.00 | |
0.00% |
0 / 2 |
|||
_ls | |
0.00% |
0 / 1 |
110.00 | |
0.00% |
0 / 22 |
|||
_send_command | |
0.00% |
0 / 1 |
30.00 | |
0.00% |
0 / 8 |
|||
_open_data_connection | |
0.00% |
0 / 1 |
90.00 | |
0.00% |
0 / 25 |
|||
_close_data_connection | |
0.00% |
0 / 1 |
6.00 | |
0.00% |
0 / 3 |
|||
_check_command | |
0.00% |
0 / 1 |
30.00 | |
0.00% |
0 / 9 |
<?php | |
/** | |
* | |
* This file is part of the phpBB Forum Software package. | |
* | |
* @copyright (c) phpBB Limited <https://www.phpbb.com> | |
* @license GNU General Public License, version 2 (GPL-2.0) | |
* | |
* For full copyright and license information, please see | |
* the docs/CREDITS.txt file. | |
* | |
*/ | |
/** | |
* @ignore | |
*/ | |
if (!defined('IN_PHPBB')) | |
{ | |
exit; | |
} | |
/** | |
* Transfer class, wrapper for ftp/sftp/ssh | |
*/ | |
class transfer | |
{ | |
var $connection; | |
var $host; | |
var $port; | |
var $username; | |
var $password; | |
var $timeout; | |
var $root_path; | |
var $tmp_path; | |
var $file_perms; | |
var $dir_perms; | |
/** | |
* Constructor - init some basic values | |
*/ | |
function __construct() | |
{ | |
global $phpbb_root_path; | |
$this->file_perms = 0644; | |
$this->dir_perms = 0777; | |
// We use the store directory as temporary path to circumvent open basedir restrictions | |
$this->tmp_path = $phpbb_root_path . 'store/'; | |
} | |
/** | |
* Write file to location | |
*/ | |
function write_file($destination_file = '', $contents = '') | |
{ | |
global $phpbb_root_path; | |
$destination_file = $this->root_path . str_replace($phpbb_root_path, '', $destination_file); | |
// need to create a temp file and then move that temp file. | |
// ftp functions can only move files around and can't create. | |
// This means that the users will need to have access to write | |
// temporary files or have write access on a folder within phpBB | |
// like the cache folder. If the user can't do either, then | |
// he/she needs to use the fsock ftp method | |
$temp_name = tempnam($this->tmp_path, 'transfer_'); | |
@unlink($temp_name); | |
$fp = @fopen($temp_name, 'w'); | |
if (!$fp) | |
{ | |
trigger_error('Unable to create temporary file ' . $temp_name, E_USER_ERROR); | |
} | |
@fwrite($fp, $contents); | |
@fclose($fp); | |
$result = $this->overwrite_file($temp_name, $destination_file); | |
// remove temporary file now | |
@unlink($temp_name); | |
return $result; | |
} | |
/** | |
* Moving file into location. If the destination file already exists it gets overwritten | |
*/ | |
function overwrite_file($source_file, $destination_file) | |
{ | |
/** | |
* @todo generally think about overwriting files in another way, by creating a temporary file and then renaming it | |
* @todo check for the destination file existance too | |
*/ | |
$this->_delete($destination_file); | |
$result = $this->_put($source_file, $destination_file); | |
$this->_chmod($destination_file, $this->file_perms); | |
return $result; | |
} | |
/** | |
* Create directory structure | |
*/ | |
function make_dir($dir) | |
{ | |
global $phpbb_root_path; | |
$dir = str_replace($phpbb_root_path, '', $dir); | |
$dir = explode('/', $dir); | |
$dirs = ''; | |
for ($i = 0, $total = count($dir); $i < $total; $i++) | |
{ | |
$result = true; | |
if (strpos($dir[$i], '.') === 0) | |
{ | |
continue; | |
} | |
$cur_dir = $dir[$i] . '/'; | |
if (!file_exists($phpbb_root_path . $dirs . $cur_dir)) | |
{ | |
// create the directory | |
$result = $this->_mkdir($dir[$i]); | |
$this->_chmod($dir[$i], $this->dir_perms); | |
} | |
$this->_chdir($this->root_path . $dirs . $dir[$i]); | |
$dirs .= $cur_dir; | |
} | |
$this->_chdir($this->root_path); | |
/** | |
* @todo stack result into array to make sure every path creation has been taken care of | |
*/ | |
return $result; | |
} | |
/** | |
* Copy file from source location to destination location | |
*/ | |
function copy_file($from_loc, $to_loc) | |
{ | |
global $phpbb_root_path; | |
$from_loc = ((strpos($from_loc, $phpbb_root_path) !== 0) ? $phpbb_root_path : '') . $from_loc; | |
$to_loc = $this->root_path . str_replace($phpbb_root_path, '', $to_loc); | |
if (!file_exists($from_loc)) | |
{ | |
return false; | |
} | |
$result = $this->overwrite_file($from_loc, $to_loc); | |
return $result; | |
} | |
/** | |
* Remove file | |
*/ | |
function delete_file($file) | |
{ | |
global $phpbb_root_path; | |
$file = $this->root_path . str_replace($phpbb_root_path, '', $file); | |
return $this->_delete($file); | |
} | |
/** | |
* Remove directory | |
* @todo remove child directories? | |
*/ | |
function remove_dir($dir) | |
{ | |
global $phpbb_root_path; | |
$dir = $this->root_path . str_replace($phpbb_root_path, '', $dir); | |
return $this->_rmdir($dir); | |
} | |
/** | |
* Rename a file or folder | |
*/ | |
function rename($old_handle, $new_handle) | |
{ | |
global $phpbb_root_path; | |
$old_handle = $this->root_path . str_replace($phpbb_root_path, '', $old_handle); | |
return $this->_rename($old_handle, $new_handle); | |
} | |
/** | |
* Check if a specified file exist... | |
*/ | |
function file_exists($directory, $filename) | |
{ | |
global $phpbb_root_path; | |
$directory = $this->root_path . str_replace($phpbb_root_path, '', $directory); | |
$this->_chdir($directory); | |
$result = $this->_ls(); | |
if ($result !== false && is_array($result)) | |
{ | |
return (in_array($filename, $result)) ? true : false; | |
} | |
return false; | |
} | |
/** | |
* Open session | |
*/ | |
function open_session() | |
{ | |
return $this->_init(); | |
} | |
/** | |
* Close current session | |
*/ | |
function close_session() | |
{ | |
return $this->_close(); | |
} | |
/** | |
* Determine methods able to be used | |
*/ | |
static public function methods() | |
{ | |
$methods = array(); | |
$disabled_functions = explode(',', @ini_get('disable_functions')); | |
if (@extension_loaded('ftp')) | |
{ | |
$methods[] = 'ftp'; | |
} | |
if (!in_array('fsockopen', $disabled_functions)) | |
{ | |
$methods[] = 'ftp_fsock'; | |
} | |
return $methods; | |
} | |
} | |
/** | |
* FTP transfer class | |
*/ | |
class ftp extends transfer | |
{ | |
/** | |
* Standard parameters for FTP session | |
*/ | |
function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) | |
{ | |
$this->host = $host; | |
$this->port = $port; | |
$this->username = $username; | |
$this->password = $password; | |
$this->timeout = $timeout; | |
// Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end) | |
$this->root_path = str_replace('\\', '/', $this->root_path); | |
if (!empty($root_path)) | |
{ | |
$this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); | |
} | |
// Init some needed values | |
parent::__construct(); | |
return; | |
} | |
/** | |
* Requests data | |
*/ | |
static public function data() | |
{ | |
global $user; | |
return array( | |
'host' => 'localhost', | |
'username' => 'anonymous', | |
'password' => '', | |
'root_path' => $user->page['root_script_path'], | |
'port' => 21, | |
'timeout' => 10 | |
); | |
} | |
/** | |
* Init FTP Session | |
* @access private | |
*/ | |
function _init() | |
{ | |
// connect to the server | |
$this->connection = @ftp_connect($this->host, $this->port, $this->timeout); | |
if (!$this->connection) | |
{ | |
return 'ERR_CONNECTING_SERVER'; | |
} | |
// login to the server | |
if (!@ftp_login($this->connection, $this->username, $this->password)) | |
{ | |
return 'ERR_UNABLE_TO_LOGIN'; | |
} | |
// attempt to turn pasv mode on | |
@ftp_pasv($this->connection, true); | |
// change to the root directory | |
if (!$this->_chdir($this->root_path)) | |
{ | |
return 'ERR_CHANGING_DIRECTORY'; | |
} | |
return true; | |
} | |
/** | |
* Create Directory (MKDIR) | |
* @access private | |
*/ | |
function _mkdir($dir) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_mkdir($this->connection, $dir); | |
} | |
/** | |
* Remove directory (RMDIR) | |
* @access private | |
*/ | |
function _rmdir($dir) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_rmdir($this->connection, $dir); | |
} | |
/** | |
* Rename file | |
* @access private | |
*/ | |
function _rename($old_handle, $new_handle) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_rename($this->connection, $old_handle, $new_handle); | |
} | |
/** | |
* Change current working directory (CHDIR) | |
* @access private | |
*/ | |
function _chdir($dir = '') | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
if ($dir && $dir !== '/') | |
{ | |
if (substr($dir, -1, 1) == '/') | |
{ | |
$dir = substr($dir, 0, -1); | |
} | |
} | |
return @ftp_chdir($this->connection, $dir); | |
} | |
/** | |
* change file permissions (CHMOD) | |
* @access private | |
*/ | |
function _chmod($file, $perms) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
if (function_exists('ftp_chmod')) | |
{ | |
$err = @ftp_chmod($this->connection, $perms, $file); | |
} | |
else | |
{ | |
// Unfortunatly CHMOD is not expecting an octal value... | |
// We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) | |
$chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file; | |
$err = $this->_site($chmod_cmd); | |
} | |
return $err; | |
} | |
/** | |
* Upload file to location (PUT) | |
* @access private | |
*/ | |
function _put($from_file, $to_file) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
// We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) | |
$mode = FTP_BINARY; | |
$to_dir = dirname($to_file); | |
$to_file = basename($to_file); | |
$this->_chdir($to_dir); | |
$result = @ftp_put($this->connection, $to_file, $from_file, $mode); | |
$this->_chdir($this->root_path); | |
return $result; | |
} | |
/** | |
* Delete file (DELETE) | |
* @access private | |
*/ | |
function _delete($file) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_delete($this->connection, $file); | |
} | |
/** | |
* Close ftp session (CLOSE) | |
* @access private | |
*/ | |
function _close() | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_quit($this->connection); | |
} | |
/** | |
* Return current working directory (CWD) | |
* At the moment not used by parent class | |
* @access private | |
*/ | |
function _cwd() | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_pwd($this->connection); | |
} | |
/** | |
* Return list of files in a given directory (LS) | |
* @access private | |
*/ | |
function _ls($dir = './') | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
$list = @ftp_nlist($this->connection, $dir); | |
// See bug #46295 - Some FTP daemons don't like './' | |
if ($dir === './') | |
{ | |
// Let's try some alternatives | |
$list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list; | |
$list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list; | |
} | |
// Return on error | |
if ($list === false) | |
{ | |
return false; | |
} | |
// Remove path if prepended | |
foreach ($list as $key => $item) | |
{ | |
// Use same separator for item and dir | |
$item = str_replace('\\', '/', $item); | |
$dir = str_replace('\\', '/', $dir); | |
if (!empty($dir) && strpos($item, $dir) === 0) | |
{ | |
$item = substr($item, strlen($dir)); | |
} | |
$list[$key] = $item; | |
} | |
return $list; | |
} | |
/** | |
* FTP SITE command (ftp-only function) | |
* @access private | |
*/ | |
function _site($command) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @ftp_site($this->connection, $command); | |
} | |
} | |
/** | |
* FTP fsock transfer class | |
*/ | |
class ftp_fsock extends transfer | |
{ | |
var $data_connection; | |
/** | |
* Standard parameters for FTP session | |
*/ | |
function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) | |
{ | |
$this->host = $host; | |
$this->port = $port; | |
$this->username = $username; | |
$this->password = $password; | |
$this->timeout = $timeout; | |
// Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end) | |
$this->root_path = str_replace('\\', '/', $this->root_path); | |
if (!empty($root_path)) | |
{ | |
$this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); | |
} | |
// Init some needed values | |
parent::__construct(); | |
return; | |
} | |
/** | |
* Requests data | |
*/ | |
static public function data() | |
{ | |
global $user; | |
return array( | |
'host' => 'localhost', | |
'username' => 'anonymous', | |
'password' => '', | |
'root_path' => $user->page['root_script_path'], | |
'port' => 21, | |
'timeout' => 10 | |
); | |
} | |
/** | |
* Init FTP Session | |
* @access private | |
*/ | |
function _init() | |
{ | |
$errno = 0; | |
$errstr = ''; | |
// connect to the server | |
$this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); | |
if (!$this->connection || !$this->_check_command()) | |
{ | |
return 'ERR_CONNECTING_SERVER'; | |
} | |
@stream_set_timeout($this->connection, $this->timeout); | |
// login | |
if (!$this->_send_command('USER', $this->username)) | |
{ | |
return 'ERR_UNABLE_TO_LOGIN'; | |
} | |
if (!$this->_send_command('PASS', $this->password)) | |
{ | |
return 'ERR_UNABLE_TO_LOGIN'; | |
} | |
// change to the root directory | |
if (!$this->_chdir($this->root_path)) | |
{ | |
return 'ERR_CHANGING_DIRECTORY'; | |
} | |
return true; | |
} | |
/** | |
* Create Directory (MKDIR) | |
* @access private | |
*/ | |
function _mkdir($dir) | |
{ | |
return $this->_send_command('MKD', $dir); | |
} | |
/** | |
* Remove directory (RMDIR) | |
* @access private | |
*/ | |
function _rmdir($dir) | |
{ | |
return $this->_send_command('RMD', $dir); | |
} | |
/** | |
* Rename File | |
* @access private | |
*/ | |
function _rename($old_handle, $new_handle) | |
{ | |
$this->_send_command('RNFR', $old_handle); | |
return $this->_send_command('RNTO', $new_handle); | |
} | |
/** | |
* Change current working directory (CHDIR) | |
* @access private | |
*/ | |
function _chdir($dir = '') | |
{ | |
if ($dir && $dir !== '/') | |
{ | |
if (substr($dir, -1, 1) == '/') | |
{ | |
$dir = substr($dir, 0, -1); | |
} | |
} | |
return $this->_send_command('CWD', $dir); | |
} | |
/** | |
* change file permissions (CHMOD) | |
* @access private | |
*/ | |
function _chmod($file, $perms) | |
{ | |
// Unfortunatly CHMOD is not expecting an octal value... | |
// We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) | |
return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file); | |
} | |
/** | |
* Upload file to location (PUT) | |
* @access private | |
*/ | |
function _put($from_file, $to_file) | |
{ | |
// We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) | |
// 'I' == BINARY | |
// 'A' == ASCII | |
if (!$this->_send_command('TYPE', 'I')) | |
{ | |
return false; | |
} | |
// open the connection to send file over | |
if (!$this->_open_data_connection()) | |
{ | |
return false; | |
} | |
$this->_send_command('STOR', $to_file, false); | |
// send the file | |
$fp = @fopen($from_file, 'rb'); | |
while (!@feof($fp)) | |
{ | |
@fwrite($this->data_connection, @fread($fp, 4096)); | |
} | |
@fclose($fp); | |
// close connection | |
$this->_close_data_connection(); | |
return $this->_check_command(); | |
} | |
/** | |
* Delete file (DELETE) | |
* @access private | |
*/ | |
function _delete($file) | |
{ | |
return $this->_send_command('DELE', $file); | |
} | |
/** | |
* Close ftp session (CLOSE) | |
* @access private | |
*/ | |
function _close() | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return $this->_send_command('QUIT'); | |
} | |
/** | |
* Return current working directory (CWD) | |
* At the moment not used by parent class | |
* @access private | |
*/ | |
function _cwd() | |
{ | |
$this->_send_command('PWD', '', false); | |
return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true)); | |
} | |
/** | |
* Return list of files in a given directory (LS) | |
* @access private | |
*/ | |
function _ls($dir = './') | |
{ | |
if (!$this->_open_data_connection()) | |
{ | |
return false; | |
} | |
$this->_send_command('NLST', $dir); | |
$list = array(); | |
while (!@feof($this->data_connection)) | |
{ | |
$filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512)); | |
if ($filename !== '') | |
{ | |
$list[] = $filename; | |
} | |
} | |
$this->_close_data_connection(); | |
// Clear buffer | |
$this->_check_command(); | |
// See bug #46295 - Some FTP daemons don't like './' | |
if ($dir === './' && empty($list)) | |
{ | |
// Let's try some alternatives | |
$list = $this->_ls('.'); | |
if (empty($list)) | |
{ | |
$list = $this->_ls(''); | |
} | |
return $list; | |
} | |
// Remove path if prepended | |
foreach ($list as $key => $item) | |
{ | |
// Use same separator for item and dir | |
$item = str_replace('\\', '/', $item); | |
$dir = str_replace('\\', '/', $dir); | |
if (!empty($dir) && strpos($item, $dir) === 0) | |
{ | |
$item = substr($item, strlen($dir)); | |
} | |
$list[$key] = $item; | |
} | |
return $list; | |
} | |
/** | |
* Send a command to server (FTP fsock only function) | |
* @access private | |
*/ | |
function _send_command($command, $args = '', $check = true) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
if (!empty($args)) | |
{ | |
$command = "$command $args"; | |
} | |
fwrite($this->connection, $command . "\r\n"); | |
if ($check === true && !$this->_check_command()) | |
{ | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Opens a connection to send data (FTP fosck only function) | |
* @access private | |
*/ | |
function _open_data_connection() | |
{ | |
// Try to find out whether we have a IPv4 or IPv6 (control) connection | |
if (function_exists('stream_socket_get_name')) | |
{ | |
$socket_name = stream_socket_get_name($this->connection, true); | |
$server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); | |
} | |
if (isset($server_ip) && filter_var($server_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) // ipv4 | |
{ | |
// Passive mode | |
$this->_send_command('PASV', '', false); | |
if (!$ip_port = $this->_check_command(true)) | |
{ | |
return false; | |
} | |
// open the connection to start sending the file | |
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)) | |
{ | |
// bad ip and port | |
return false; | |
} | |
$temp = explode(',', $temp[0]); | |
$server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; | |
$server_port = $temp[4] * 256 + $temp[5]; | |
} | |
else // ipv6 | |
{ | |
// Extended Passive Mode - RFC2428 | |
$this->_send_command('EPSV', '', false); | |
if (!$epsv_response = $this->_check_command(true)) | |
{ | |
return false; | |
} | |
// Response looks like "229 Entering Extended Passive Mode (|||12345|)" | |
// where 12345 is the tcp port for the data connection | |
if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) | |
{ | |
return false; | |
} | |
$server_port = (int) $match[1]; | |
// fsockopen expects IPv6 address in square brackets | |
$server_ip = "[$server_ip]"; | |
} | |
$errno = 0; | |
$errstr = ''; | |
if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) | |
{ | |
return false; | |
} | |
@stream_set_timeout($this->data_connection, $this->timeout); | |
return true; | |
} | |
/** | |
* Closes a connection used to send data | |
* @access private | |
*/ | |
function _close_data_connection() | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
return @fclose($this->data_connection); | |
} | |
/** | |
* Check to make sure command was successful (FTP fsock only function) | |
* @access private | |
*/ | |
function _check_command($return = false) | |
{ | |
if (!$this->connection) | |
{ | |
return false; | |
} | |
$response = ''; | |
do | |
{ | |
$result = @fgets($this->connection, 512); | |
$response .= $result; | |
} | |
while (substr($result, 3, 1) !== ' '); | |
if (!preg_match('#^[123]#', $response)) | |
{ | |
return false; | |
} | |
return ($return) ? $response : true; | |
} | |
} |