Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: *//*** Net_FTP socket implementation of FTP functions.** The functions in this file emulate the ext/FTP functions through* ext/Socket.** PHP versions 4 and 5** LICENSE: This source file is subject to version 3.0 of the PHP license* that is available through the world-wide-web at the following URI:* http://www.php.net/license/3_0.txt. If you did not receive a copy of* the PHP License and are unable to obtain it through the web, please* send a note to license@php.net so we can mail you a copy immediately.** @category Networking* @package FTP* @author Tobias Schlitt <toby@php.net>* @copyright 1997-2008 The PHP Group* @license http://www.php.net/license/3_0.txt PHP License 3.0* @version CVS: $Id: Socket.php,v 1.5.2.2 2008/04/22 19:47:08 jschippers Exp $* @link http://pear.php.net/package/Net_FTP* @since File available since Release 0.0.1*/error_reporting(E_ALL);/*** Default FTP extension constants*/define('FTP_ASCII', 0);define('FTP_TEXT', 0);define('FTP_BINARY', 1);define('FTP_IMAGE', 1);define('FTP_TIMEOUT_SEC', 0);/*** What needs to be done overall?* #1 Install the rest of these functions* #2 Document better* #3 Alot of other things I don't remember*//** !!! NOTE !!!* Most of the comment's are "not working",* meaning they are not all up-to-date* !!! NOTE !!!*//*** &resource ftp_connect ( string host [, int port [, int timeout ] ] );** Opens an FTP connection and return resource or false on failure.** FTP Success respons code: 220** @param string $host Host to connect to* @param int $port Optional, port to connect to* @param int $timeout Optional, seconds until function timeouts** @todo The FTP extension has ftp_get_option() function which returns the* timeout variable. This function needs to be created and contain it as* static variable.* @todo The FTP extension has ftp_set_option() function which sets the* timeout variable. This function needs to be created and called here.* @access public* @return &resource*/function &ftp_connect($host, $port = 21, $timeout = 90){$false = false; // We are going to return refrence (E_STRICT)if (!is_string($host) || !is_integer($port) || !is_integer($timeout)) {return $false;}$control = @fsockopen($host, $port, $iError, $sError,$timeout);$GLOBALS['_NET_FTP']['timeout'] = $timeout;if (!is_resource($control)) {return $false;}stream_set_blocking($control, true);stream_set_timeout($control, $timeout);do {$content[] = fgets($control, 8129);$array = socket_get_status($control);} while ($array['unread_bytes'] > 0);if (substr($content[count($content)-1], 0, 3) == 220) {return $control;}return $false;}/*** boolean ftp_login ( resource stream, string username, string password );** Logs in to an given FTP connection stream.* Returns TRUE on success or FALSE on failure.** NOTE:* Username and password are *not* optional. Function will *not** assume "anonymous" if username and/or password is empty** FTP Success respons code: 230** @param resource &$control FTP resource to login to* @param string $username FTP Username to be used* @param string $password FTP Password to be used** @access public* @return boolean*/function ftp_login(&$control, $username, $password){if (!is_resource($control) || is_null($username)) {return false;}fputs($control, 'USER '.$username."\r\n");$contents = array();do {$contents[] = fgets($control, 8192);$array = socket_get_status($control);} while ($array['unread_bytes'] > 0);if (substr($contents[count($contents)-1], 0, 3) != 331) {return false;}fputs($control, 'PASS '.$password."\r\n");$contents = array();do {$contents[] = fgets($control, 8192);$array = socket_get_status($control);} while ($array['unread_bytes']);if (substr($contents[count($contents)-1], 0, 3) == 230) {return true;}trigger_error('ftp_login() [<a href="function.ftp-login">function.ftp-login'.'</a>]: '.$contents[count($contents)-1], E_USER_WARNING);return false;}/*** boolean ftp_quit ( resource stream );** Closes FTP connection.* Returns TRUE or FALSE on error.** NOTE: The PHP function ftp_quit is *alias* to ftp_close, here it is* the *other-way-around* ( ftp_close() is alias to ftp_quit() ).** NOTE:* resource is set to null since unset() can't unset the variable.** @param resource &$control FTP resource** @access public* @return boolean*/function ftp_quit(&$control){if (!is_resource($control)) {return false;}fputs($control, 'QUIT'."\r\n");fclose($control);$control = null;return true;}/*** Alias to ftp_quit()** @param resource &$control FTP resource** @see ftp_quit()* @access public* @return boolean*/function ftp_close(&$control){return ftp_quit($control);}/*** string ftp_pwd ( resource stream );** Gets the current directory name.* Returns the current directory.** Needs data connection: NO* Success response code: 257** @param resource &$control FTP resource** @access public* @return string*/function ftp_pwd(&$control){if (!is_resource($control)) {return $control;}fputs($control, 'PWD'."\r\n");$content = array();do {$content[] = fgets($control, 8192);$array = socket_get_status($control);} while ($array['unread_bytes'] > 0);if (substr($cont = $content[count($content)-1], 0, 3) == 257) {$pos = strpos($cont, '"')+1;$pos2 = strrpos($cont, '"') - $pos;$path = substr($cont, $pos, $pos2);return $path;}return false;}/*** boolean ftp_chdir ( resource stream, string directory );** Changes the current directory to the specified directory.* Returns TRUE on success or FALSE on failure.** FTP success response code: 250* Needs data connection: NO** @param resource &$control FTP stream* @param string $pwd Directory name** @access public* @return boolean*/function ftp_chdir(&$control, $pwd){if (!is_resource($control) || !is_string($pwd)) {return false;}fputs($control, 'CWD '.$pwd."\r\n");$content = array();do {$content[] = fgets($control, 8192);$array = socket_get_status($control);} while ($array['unread_bytes'] > 0);if (substr($content[count($content)-1], 0, 3) == 250) {return true;}trigger_error('ftp_chdir() [<ahref="function.ftp-chdir">function.ftp-chdir</a>]:' .$content[count($content)-1], E_USER_WARNING);return false;}$_NET_FTP = array();$_NET_FTP['USE_PASSIVE'] = false;$_NET_FTP['DATA'] = null;/*** boolean ftp_pasv ( resource stream, boolean passive );** Toggles passive mode ON/OFF.* Returns TRUE on success or FALSE on failure.** Comment:* Although my lack of C knowlege I checked how the PHP FTP extension* do things here. Seems like they create the data connection and store* it in object for other functions to use.* This is now done here.** FTP success response code: 227** @param stream &$control FTP stream* @param boolean $pasv True to switch to passive, false for active mode** @access public* @return boolean*/function ftp_pasv(&$control, $pasv){if (!is_resource($control) || !is_bool($pasv)) {return false;}// If data connection exists, destroy itif (isset($GLOBALS['_NET_FTP']['DATA'])) {fclose($GLOBALS['_NET_FTP']['DATA']);$GLOBALS['_NET_FTP']['DATA'] = null;do {fgets($control, 16);$array = socket_get_status($control);} while ($array['unread_bytes'] > 0);}// Are we suppost to create active or passive connection?if (!$pasv) {$GLOBALS['_NET_FTP']['USE_PASSIVE'] = false;// Pick random "low bit"$low = rand(39, 250);// Pick random "high bit"$high = rand(39, 250);// Lowest possible port would be; 10023// Highest possible port would be; 64246$port = ($low<<8)+$high;$ip = str_replace('.', ',', $_SERVER['SERVER_ADDR']);$s = $ip.','.$low.','.$high;$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);if (is_resource($socket)) {if (socket_bind($socket, '0.0.0.0', $port)) {if (socket_listen($socket)) {$GLOBALS['_NET_FTP']['DATA'] = &$socket;fputs($control, 'PORT '.$s."\r\n");$line = fgets($control, 512);if (substr($line, 0, 3) == 200) {return true;}}}}return false;}// Since we are here, we are suppost to create passive data connection.$i = fputs($control, 'PASV' ."\r\n");$content = array();do {$content[] = fgets($control, 128);$array = socket_get_status($control);} while ($array['unread_bytes']);if (substr($cont = $content[count($content)-1], 0, 3) != 227) {return false;}$pos = strpos($cont, '(')+1;$pos2 = strrpos($cont, ')')-$pos;$string = substr($cont, $pos, $pos2);$array = split(',', $string);// IP we are connecting to$ip = $array[0]. '.' .$array[1]. '.' .$array[2]. '.' .$array[3];// Port ( 256*lowbit + highbit$port = ($array[4] << 8)+$array[5];// Our data connection$data = fsockopen($ip, $port, $iError, $sError,$GLOBALS['_NET_FTP']['timeout']);if (is_resource($data)) {$GLOBALS['_NET_FTP']['USE_PASSIVE'] = true;$GLOBALS['_NET_FTP']['DATA'] = &$data;stream_set_blocking($data, true);stream_set_timeout($data, $GLOBALS['_NET_FTP']['timeout']);return true;}return false;}/*** array ftp_rawlist ( resource stream, string directory [,bool recursive] );** Returns a detailed list of files in the given directory.** Needs data connection: YES** @param integer &$control FTP resource* @param string $pwd Path to retrieve* @param boolean $recursive Optional, retrieve recursive listing** @todo Enable the recursive feature.* @access public* @return array*/function ftp_rawlist(&$control, $pwd, $recursive = false){if (!is_resource($control) || !is_string($pwd)) {return false;}if (!isset($GLOBALS['_NET_FTP']['DATA']) ||!is_resource($GLOBALS['_NET_FTP']['DATA'])) {ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']);}fputs($control, 'LIST '.$pwd."\r\n");$msg = fgets($control, 512);if (substr($msg, 0, 3) == 425) {return false;}$data = &$GLOBALS['_NET_FTP']['DATA'];if (!$GLOBALS['_NET_FTP']['USE_PASSIVE']) {$data = &socket_accept($data);}$content = array();switch ($GLOBALS['_NET_FTP']['USE_PASSIVE']) {case true:while (true) {$string = rtrim(fgets($data, 1024));if ($string=='') {break;}$content[] = $string;}fclose($data);break;case false:$string = socket_read($data, 1024, PHP_BINARY_READ);$content = explode("\n", $string);unset($content[count($content)-1]);socket_close($GLOBALS['_NET_FTP']['DATA']);socket_close($data);break;}$data = $GLOBALS['_NET_FTP']['DATA'] = null;$f = fgets($control, 1024);return $content;}/*** string ftp_systype ( resource stream );** Gets system type identifier of remote FTP server* Returns the remote system type** @param resource &$control FTP resource** @access public* @return string*/function ftp_systype(&$control){if (!is_resource($control)) {return false;}fputs($control, 'SYST'."\r\n");$line = fgets($control, 256);if (substr($line, 0, 3) != 215) {return false;}$os = substr($line, 4, strpos($line, ' ', 4)-4);return $os;}/*** boolean ftp_alloc ( resource stream, integer bytes [, string &message ] );** Allocates space for a file to be uploaded* Return TRUE on success or FALSE on failure** NOTE; Many FTP servers do not support this command and/or don't need it.** FTP success respons key: Belive it's 200* Needs data connection: NO** @param resource &$control FTP stream* @param integer $int Space to allocate* @param string &$msg Optional, textual representation of the servers response* will be returned by reference** @access public* @return boolean*/function ftp_alloc(&$control, $int, &$msg = null){if (!is_resource($control) || !is_integer($int)) {return false;}fputs($control, 'ALLO '.$int.' R '.$int."\r\n");$msg = rtrim(fgets($control, 256));$code = substr($msg, 0, 3);if ($code == 200 || $code == 202) {return true;}return false;}/*** bool ftp_put ( resource stream, string remote_file, string local_file,* int mode [, int startpos ] );** Uploads a file to the FTP server* Returns TRUE on success or FALSE on failure.** NOTE:* The transfer mode specified must be either FTP_ASCII or FTP_BINARY.** @param resource &$control FTP stream* @param string $remote Remote file to write* @param string $local Local file to upload* @param integer $mode Upload mode, FTP_ASCI || FTP_BINARY* @param integer $pos Optional, start upload at position** @access public* @return boolean*/function ftp_put(&$control, $remote, $local, $mode, $pos = 0){if (!is_resource($control) || !is_readable($local) ||!is_integer($mode) || !is_integer($pos)) {return false;}$types = array (0 => 'A',1 => 'I');$windows = array (0 => 't',1 => 'b');/*** TYPE values:* A ( ASCII )* I ( BINARY )* E ( EBCDIC )* L ( BYTE )*/if (!isset($GLOBALS['_NET_FTP']['DATA']) ||!is_resource($GLOBALS['_NET_FTP']['DATA'])) {ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']);}// Establish data connection variable$data = &$GLOBALS['_NET_FTP']['DATA'];// Decide TYPE to usefputs($control, 'TYPE '.$types[$mode]."\r\n");$line = fgets($control, 256); // "Type set to TYPE"if (substr($line, 0, 3) != 200) {return false;}fputs($control, 'STOR '.$remote."\r\n");sleep(1);$line = fgets($control, 256); // "Opening TYPE mode data connect."if (substr($line, 0, 3) != 150) {return false;}// Creating resource to $local file$fp = fopen($local, 'r'. $windows[$mode]);if (!is_resource($fp)) {$fp = null;return false;}// Loop throu that file and echo it to the data socket$i = 0;switch ($GLOBALS['_NET_FTP']['USE_PASSIVE']) {case false:$data = &socket_accept($data);while (!feof($fp)) {$i += socket_write($data, fread($fp, 10240), 10240);}socket_close($data);break;case true:while (!feof($fp)) {$i += fputs($data, fread($fp, 10240), 10240);}fclose($data);break;}$data = null;do {$line = fgets($control, 256);} while (substr($line, 0, 4) != "226 ");return true;}/*** Retrieve a remote file to a local file* Returns TRUE on success or FALSE on failure** @param integer &$control Stream ID* @param string $local Local filename* @param string $remote Remote filename* @param integer $mode Transfer mode (FTP_ASCII or FTP_BINARY)* @param integer $resume Resume the file transfer or not** @access public* @return boolean*/function ftp_get(&$control, $local, $remote, $mode, $resume = 0){if (!is_resource($control) || !is_writable(dirname($local)) ||!is_integer($mode) || !is_integer($resume)) {return false;}$types = array (0 => 'A',1 => 'I');$windows = array (0 => 't',1 => 'b');if (!isset($GLOBALS['_NET_FTP']['DATA']) ||!is_resource($GLOBALS['_NET_FTP'][ 'DATA'])) {ftp_pasv($control, $GLOBALS['_NET_FTP']['USE_PASSIVE']);}$data = &$GLOBALS['NET_FTP']['DATA'];fputs($control, 'TYPE '.$types[$mode]."\r\n");$line = fgets($control, 256);if (substr($line, 0, 3) != 200) {return false;}$fp = fopen($local, 'w'.$windows[$mode]);if (!is_resource($fp)) {$fp = null;return false;}}/*** Changes to the parent directory* Returns TRUE on success or FALSE on failure** @param integer &$control Stream ID** @access public* @return boolean*/function ftp_cdup(&$control){fputs($control, 'CDUP'."\r\n");$line = fgets($control, 256);if (substr($line, 0, 3) != 250) {return false;}return true;}/*** Set permissions on a file via FTP* Returns the new file permission on success or false on error** NOTE: This command is *not* supported by the standard* NOTE: This command not ready!** @param integer &$control Stream ID* @param integer $mode Octal value* @param string $file File to change permissions on** @todo Figure out a way to chmod files via FTP* @access public* @return integer*/function ftp_chmod(&$control, $mode, $file){if (!is_resource($control) || !is_integer($mode) || !is_string($file)) {return false;}// chmod not in the standard, proftpd doesn't recognize it// use SITE CHMOD?fputs($control, 'SITE CHMOD '.$mode. ' ' .$file."\r\n");$line = fgets($control, 256);if (substr($line, 0, 3) == 200) {return $mode;}trigger_error('ftp_chmod() [<ahref="function.ftp-chmod">function.ftp-chmod</a>]: ' .rtrim($line), E_USER_WARNING);return false;}/*** Deletes a file on the FTP server* Returns TRUE on success or FALSE on failure** @param integer &$control Stream ID* @param string $path File to delete** @access public* @return boolean*/function ftp_delete(&$control, $path){if (!is_resource($control) || !is_string($path)) {return false;}fputs($control, 'DELE '.$path."\r\n");$line = fgets($control, 256);if (substr($line, 0, 3) == 250) {return true;}return false;}/*** Requests execution of a program on the FTP server* NOTE; SITE EXEC is *not* supported by the standart* Returns TRUE on success or FALSE on error** @param integer &$control Stream ID* @param string $cmd Command to send** @access public* @todo Look a littlebit better into this* @return boolean*/function ftp_exec(&$control, $cmd){if (!is_resource($control) || !is_string($cmd)) {return false;}// Command not defined in the standart// proftpd doesn't recognize SITE EXEC (only help,chgrp,chmod and ratio)fputs($control, 'SITE EXEC '.$cmd."\r\n");$line = fgets($control, 256);// php.net/ftp_exec uses respons code 200 to verify if command was sent// successfully or not, so we'll just do the sameif (substr($line, 0, 3) == 200) {return true;}return false;}?>