ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-ftp-sockets.php (8475B)


      1 <?php
      2 /**
      3  * PemFTP - An Ftp implementation in pure PHP
      4  *
      5  * @package PemFTP
      6  * @since 2.5.0
      7  *
      8  * @version 1.0
      9  * @copyright Alexey Dotsenko
     10  * @author Alexey Dotsenko
     11  * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
     12  * @license LGPL https://opensource.org/licenses/lgpl-license.html
     13  */
     14 
     15 /**
     16  * Socket Based FTP implementation
     17  *
     18  * @package PemFTP
     19  * @subpackage Socket
     20  * @since 2.5.0
     21  *
     22  * @version 1.0
     23  * @copyright Alexey Dotsenko
     24  * @author Alexey Dotsenko
     25  * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
     26  * @license LGPL https://opensource.org/licenses/lgpl-license.html
     27  */
     28 class ftp_sockets extends ftp_base {
     29 
     30 	function __construct($verb=FALSE, $le=FALSE) {
     31 		parent::__construct(true, $verb, $le);
     32 	}
     33 
     34 // <!-- --------------------------------------------------------------------------------------- -->
     35 // <!--       Private functions                                                                 -->
     36 // <!-- --------------------------------------------------------------------------------------- -->
     37 
     38 	function _settimeout($sock) {
     39 		if(!@socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
     40 			$this->PushError('_connect','socket set receive timeout',socket_strerror(socket_last_error($sock)));
     41 			@socket_close($sock);
     42 			return FALSE;
     43 		}
     44 		if(!@socket_set_option($sock, SOL_SOCKET , SO_SNDTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
     45 			$this->PushError('_connect','socket set send timeout',socket_strerror(socket_last_error($sock)));
     46 			@socket_close($sock);
     47 			return FALSE;
     48 		}
     49 		return true;
     50 	}
     51 
     52 	function _connect($host, $port) {
     53 		$this->SendMSG("Creating socket");
     54 		if(!($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
     55 			$this->PushError('_connect','socket create failed',socket_strerror(socket_last_error($sock)));
     56 			return FALSE;
     57 		}
     58 		if(!$this->_settimeout($sock)) return FALSE;
     59 		$this->SendMSG("Connecting to \"".$host.":".$port."\"");
     60 		if (!($res = @socket_connect($sock, $host, $port))) {
     61 			$this->PushError('_connect','socket connect failed',socket_strerror(socket_last_error($sock)));
     62 			@socket_close($sock);
     63 			return FALSE;
     64 		}
     65 		$this->_connected=true;
     66 		return $sock;
     67 	}
     68 
     69 	function _readmsg($fnction="_readmsg"){
     70 		if(!$this->_connected) {
     71 			$this->PushError($fnction,'Connect first');
     72 			return FALSE;
     73 		}
     74 		$result=true;
     75 		$this->_message="";
     76 		$this->_code=0;
     77 		$go=true;
     78 		do {
     79 			$tmp=@socket_read($this->_ftp_control_sock, 4096, PHP_BINARY_READ);
     80 			if($tmp===false) {
     81 				$go=$result=false;
     82 				$this->PushError($fnction,'Read failed', socket_strerror(socket_last_error($this->_ftp_control_sock)));
     83 			} else {
     84 				$this->_message.=$tmp;
     85 				$go = !preg_match("/^([0-9]{3})(-.+\\1)? [^".CRLF."]+".CRLF."$/Us", $this->_message, $regs);
     86 			}
     87 		} while($go);
     88 		if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF;
     89 		$this->_code=(int)$regs[1];
     90 		return $result;
     91 	}
     92 
     93 	function _exec($cmd, $fnction="_exec") {
     94 		if(!$this->_ready) {
     95 			$this->PushError($fnction,'Connect first');
     96 			return FALSE;
     97 		}
     98 		if($this->LocalEcho) echo "PUT > ",$cmd,CRLF;
     99 		$status=@socket_write($this->_ftp_control_sock, $cmd.CRLF);
    100 		if($status===false) {
    101 			$this->PushError($fnction,'socket write failed', socket_strerror(socket_last_error($this->stream)));
    102 			return FALSE;
    103 		}
    104 		$this->_lastaction=time();
    105 		if(!$this->_readmsg($fnction)) return FALSE;
    106 		return TRUE;
    107 	}
    108 
    109 	function _data_prepare($mode=FTP_ASCII) {
    110 		if(!$this->_settype($mode)) return FALSE;
    111 		$this->SendMSG("Creating data socket");
    112 		$this->_ftp_data_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    113 		if ($this->_ftp_data_sock < 0) {
    114 			$this->PushError('_data_prepare','socket create failed',socket_strerror(socket_last_error($this->_ftp_data_sock)));
    115 			return FALSE;
    116 		}
    117 		if(!$this->_settimeout($this->_ftp_data_sock)) {
    118 			$this->_data_close();
    119 			return FALSE;
    120 		}
    121 		if($this->_passive) {
    122 			if(!$this->_exec("PASV", "pasv")) {
    123 				$this->_data_close();
    124 				return FALSE;
    125 			}
    126 			if(!$this->_checkCode()) {
    127 				$this->_data_close();
    128 				return FALSE;
    129 			}
    130 			$ip_port = explode(",", preg_replace("/^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*$/s", "\\1", $this->_message));
    131 			$this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3];
    132 			$this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]);
    133 			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
    134 			if(!@socket_connect($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
    135 				$this->PushError("_data_prepare","socket_connect", socket_strerror(socket_last_error($this->_ftp_data_sock)));
    136 				$this->_data_close();
    137 				return FALSE;
    138 			}
    139 			else $this->_ftp_temp_sock=$this->_ftp_data_sock;
    140 		} else {
    141 			if(!@socket_getsockname($this->_ftp_control_sock, $addr, $port)) {
    142 				$this->PushError("_data_prepare","can't get control socket information", socket_strerror(socket_last_error($this->_ftp_control_sock)));
    143 				$this->_data_close();
    144 				return FALSE;
    145 			}
    146 			if(!@socket_bind($this->_ftp_data_sock,$addr)){
    147 				$this->PushError("_data_prepare","can't bind data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
    148 				$this->_data_close();
    149 				return FALSE;
    150 			}
    151 			if(!@socket_listen($this->_ftp_data_sock)) {
    152 				$this->PushError("_data_prepare","can't listen data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
    153 				$this->_data_close();
    154 				return FALSE;
    155 			}
    156 			if(!@socket_getsockname($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
    157 				$this->PushError("_data_prepare","can't get data socket information", socket_strerror(socket_last_error($this->_ftp_data_sock)));
    158 				$this->_data_close();
    159 				return FALSE;
    160 			}
    161 			if(!$this->_exec('PORT '.str_replace('.',',',$this->_datahost.'.'.($this->_dataport>>8).'.'.($this->_dataport&0x00FF)), "_port")) {
    162 				$this->_data_close();
    163 				return FALSE;
    164 			}
    165 			if(!$this->_checkCode()) {
    166 				$this->_data_close();
    167 				return FALSE;
    168 			}
    169 		}
    170 		return TRUE;
    171 	}
    172 
    173 	function _data_read($mode=FTP_ASCII, $fp=NULL) {
    174 		$NewLine=$this->_eol_code[$this->OS_local];
    175 		if(is_resource($fp)) $out=0;
    176 		else $out="";
    177 		if(!$this->_passive) {
    178 			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
    179 			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
    180 			if($this->_ftp_temp_sock===FALSE) {
    181 				$this->PushError("_data_read","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
    182 				$this->_data_close();
    183 				return FALSE;
    184 			}
    185 		}
    186 
    187 		while(($block=@socket_read($this->_ftp_temp_sock, $this->_ftp_buff_size, PHP_BINARY_READ))!==false) {
    188 			if($block==="") break;
    189 			if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block);
    190 			if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block));
    191 			else $out.=$block;
    192 		}
    193 		return $out;
    194 	}
    195 
    196 	function _data_write($mode=FTP_ASCII, $fp=NULL) {
    197 		$NewLine=$this->_eol_code[$this->OS_local];
    198 		if(is_resource($fp)) $out=0;
    199 		else $out="";
    200 		if(!$this->_passive) {
    201 			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
    202 			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
    203 			if($this->_ftp_temp_sock===FALSE) {
    204 				$this->PushError("_data_write","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
    205 				$this->_data_close();
    206 				return false;
    207 			}
    208 		}
    209 		if(is_resource($fp)) {
    210 			while(!feof($fp)) {
    211 				$block=fread($fp, $this->_ftp_buff_size);
    212 				if(!$this->_data_write_block($mode, $block)) return false;
    213 			}
    214 		} elseif(!$this->_data_write_block($mode, $fp)) return false;
    215 		return true;
    216 	}
    217 
    218 	function _data_write_block($mode, $block) {
    219 		if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block);
    220 		do {
    221 			if(($t=@socket_write($this->_ftp_temp_sock, $block))===FALSE) {
    222 				$this->PushError("_data_write","socket_write", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
    223 				$this->_data_close();
    224 				return FALSE;
    225 			}
    226 			$block=substr($block, $t);
    227 		} while(!empty($block));
    228 		return true;
    229 	}
    230 
    231 	function _data_close() {
    232 		@socket_close($this->_ftp_temp_sock);
    233 		@socket_close($this->_ftp_data_sock);
    234 		$this->SendMSG("Disconnected data from remote host");
    235 		return TRUE;
    236 	}
    237 
    238 	function _quit() {
    239 		if($this->_connected) {
    240 			@socket_close($this->_ftp_control_sock);
    241 			$this->_connected=false;
    242 			$this->SendMSG("Socket closed");
    243 		}
    244 	}
    245 }
    246 ?>