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