xref: /PHP-7.4/ext/ftp/php_ftp.c (revision 42c72ef4)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Andrew Skalski <askalski@chek.com>                          |
16    |          Stefan Esser <sesser@php.net> (resume functions)            |
17    +----------------------------------------------------------------------+
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "php.h"
25 
26 #ifdef HAVE_FTP_SSL
27 # include <openssl/ssl.h>
28 #endif
29 
30 #if HAVE_FTP
31 
32 #include "ext/standard/info.h"
33 #include "ext/standard/file.h"
34 
35 #include "php_ftp.h"
36 #include "ftp.h"
37 
38 static int le_ftpbuf;
39 #define le_ftpbuf_name "FTP Buffer"
40 
41 /* {{{ arginfo */
42 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_connect, 0, 0, 1)
43 	ZEND_ARG_INFO(0, host)
44 	ZEND_ARG_INFO(0, port)
45 	ZEND_ARG_INFO(0, timeout)
46 ZEND_END_ARG_INFO()
47 
48 #ifdef HAVE_FTP_SSL
49 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_ssl_connect, 0, 0, 1)
50 	ZEND_ARG_INFO(0, host)
51 	ZEND_ARG_INFO(0, port)
52 	ZEND_ARG_INFO(0, timeout)
53 ZEND_END_ARG_INFO()
54 #endif
55 
56 ZEND_BEGIN_ARG_INFO(arginfo_ftp_login, 0)
57 	ZEND_ARG_INFO(0, ftp)
58 	ZEND_ARG_INFO(0, username)
59 	ZEND_ARG_INFO(0, password)
60 ZEND_END_ARG_INFO()
61 
62 ZEND_BEGIN_ARG_INFO(arginfo_ftp_pwd, 0)
63 	ZEND_ARG_INFO(0, ftp)
64 ZEND_END_ARG_INFO()
65 
66 ZEND_BEGIN_ARG_INFO(arginfo_ftp_cdup, 0)
67 	ZEND_ARG_INFO(0, ftp)
68 ZEND_END_ARG_INFO()
69 
70 ZEND_BEGIN_ARG_INFO(arginfo_ftp_chdir, 0)
71 	ZEND_ARG_INFO(0, ftp)
72 	ZEND_ARG_INFO(0, directory)
73 ZEND_END_ARG_INFO()
74 
75 ZEND_BEGIN_ARG_INFO(arginfo_ftp_exec, 0)
76 	ZEND_ARG_INFO(0, ftp)
77 	ZEND_ARG_INFO(0, command)
78 ZEND_END_ARG_INFO()
79 
80 ZEND_BEGIN_ARG_INFO(arginfo_ftp_raw, 0)
81 	ZEND_ARG_INFO(0, ftp)
82 	ZEND_ARG_INFO(0, command)
83 ZEND_END_ARG_INFO()
84 
85 ZEND_BEGIN_ARG_INFO(arginfo_ftp_mkdir, 0)
86 	ZEND_ARG_INFO(0, ftp)
87 	ZEND_ARG_INFO(0, directory)
88 ZEND_END_ARG_INFO()
89 
90 ZEND_BEGIN_ARG_INFO(arginfo_ftp_rmdir, 0)
91 	ZEND_ARG_INFO(0, ftp)
92 	ZEND_ARG_INFO(0, directory)
93 ZEND_END_ARG_INFO()
94 
95 ZEND_BEGIN_ARG_INFO(arginfo_ftp_chmod, 0)
96 	ZEND_ARG_INFO(0, ftp)
97 	ZEND_ARG_INFO(0, mode)
98 	ZEND_ARG_INFO(0, filename)
99 ZEND_END_ARG_INFO()
100 
101 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_alloc, 0, 0, 2)
102 	ZEND_ARG_INFO(0, ftp)
103 	ZEND_ARG_INFO(0, size)
104 	ZEND_ARG_INFO(1, response)
105 ZEND_END_ARG_INFO()
106 
107 ZEND_BEGIN_ARG_INFO(arginfo_ftp_nlist, 0)
108 	ZEND_ARG_INFO(0, ftp)
109 	ZEND_ARG_INFO(0, directory)
110 ZEND_END_ARG_INFO()
111 
112 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_rawlist, 0, 0, 2)
113 	ZEND_ARG_INFO(0, ftp)
114 	ZEND_ARG_INFO(0, directory)
115 	ZEND_ARG_INFO(0, recursive)
116 ZEND_END_ARG_INFO()
117 
118 ZEND_BEGIN_ARG_INFO(arginfo_ftp_mlsd, 0)
119 	ZEND_ARG_INFO(0, ftp)
120 	ZEND_ARG_INFO(0, directory)
121 ZEND_END_ARG_INFO()
122 
123 ZEND_BEGIN_ARG_INFO(arginfo_ftp_systype, 0)
124 	ZEND_ARG_INFO(0, ftp)
125 ZEND_END_ARG_INFO()
126 
127 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_fget, 0, 0, 3)
128 	ZEND_ARG_INFO(0, ftp)
129 	ZEND_ARG_INFO(0, fp)
130 	ZEND_ARG_INFO(0, remote_file)
131 	ZEND_ARG_INFO(0, mode)
132 	ZEND_ARG_INFO(0, resumepos)
133 ZEND_END_ARG_INFO()
134 
135 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_fget, 0, 0, 3)
136 	ZEND_ARG_INFO(0, ftp)
137 	ZEND_ARG_INFO(0, fp)
138 	ZEND_ARG_INFO(0, remote_file)
139 	ZEND_ARG_INFO(0, mode)
140 	ZEND_ARG_INFO(0, resumepos)
141 ZEND_END_ARG_INFO()
142 
143 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_pasv, 0, 0, 2)
144 	ZEND_ARG_INFO(0, ftp)
145 	ZEND_ARG_INFO(0, pasv)
146 ZEND_END_ARG_INFO()
147 
148 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_get, 0, 0, 3)
149 	ZEND_ARG_INFO(0, ftp)
150 	ZEND_ARG_INFO(0, local_file)
151 	ZEND_ARG_INFO(0, remote_file)
152 	ZEND_ARG_INFO(0, mode)
153 	ZEND_ARG_INFO(0, resume_pos)
154 ZEND_END_ARG_INFO()
155 
156 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_get, 0, 0, 3)
157 	ZEND_ARG_INFO(0, ftp)
158 	ZEND_ARG_INFO(0, local_file)
159 	ZEND_ARG_INFO(0, remote_file)
160 	ZEND_ARG_INFO(0, mode)
161 	ZEND_ARG_INFO(0, resume_pos)
162 ZEND_END_ARG_INFO()
163 
164 ZEND_BEGIN_ARG_INFO(arginfo_ftp_nb_continue, 0)
165 	ZEND_ARG_INFO(0, ftp)
166 ZEND_END_ARG_INFO()
167 
168 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_fput, 0, 0, 3)
169 	ZEND_ARG_INFO(0, ftp)
170 	ZEND_ARG_INFO(0, remote_file)
171 	ZEND_ARG_INFO(0, fp)
172 	ZEND_ARG_INFO(0, mode)
173 	ZEND_ARG_INFO(0, startpos)
174 ZEND_END_ARG_INFO()
175 
176 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_fput, 0, 0, 3)
177 	ZEND_ARG_INFO(0, ftp)
178 	ZEND_ARG_INFO(0, remote_file)
179 	ZEND_ARG_INFO(0, fp)
180 	ZEND_ARG_INFO(0, mode)
181 	ZEND_ARG_INFO(0, startpos)
182 ZEND_END_ARG_INFO()
183 
184 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_put, 0, 0, 3)
185 	ZEND_ARG_INFO(0, ftp)
186 	ZEND_ARG_INFO(0, remote_file)
187 	ZEND_ARG_INFO(0, local_file)
188 	ZEND_ARG_INFO(0, mode)
189 	ZEND_ARG_INFO(0, startpos)
190 ZEND_END_ARG_INFO()
191 
192 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_append, 0, 0, 3)
193 	ZEND_ARG_INFO(0, ftp)
194 	ZEND_ARG_INFO(0, remote_file)
195 	ZEND_ARG_INFO(0, local_file)
196 	ZEND_ARG_INFO(0, mode)
197 ZEND_END_ARG_INFO()
198 
199 ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_put, 0, 0, 3)
200 	ZEND_ARG_INFO(0, ftp)
201 	ZEND_ARG_INFO(0, remote_file)
202 	ZEND_ARG_INFO(0, local_file)
203 	ZEND_ARG_INFO(0, mode)
204 	ZEND_ARG_INFO(0, startpos)
205 ZEND_END_ARG_INFO()
206 
207 ZEND_BEGIN_ARG_INFO(arginfo_ftp_size, 0)
208 	ZEND_ARG_INFO(0, ftp)
209 	ZEND_ARG_INFO(0, filename)
210 ZEND_END_ARG_INFO()
211 
212 ZEND_BEGIN_ARG_INFO(arginfo_ftp_mdtm, 0)
213 	ZEND_ARG_INFO(0, ftp)
214 	ZEND_ARG_INFO(0, filename)
215 ZEND_END_ARG_INFO()
216 
217 ZEND_BEGIN_ARG_INFO(arginfo_ftp_rename, 0)
218 	ZEND_ARG_INFO(0, ftp)
219 	ZEND_ARG_INFO(0, src)
220 	ZEND_ARG_INFO(0, dest)
221 ZEND_END_ARG_INFO()
222 
223 ZEND_BEGIN_ARG_INFO(arginfo_ftp_delete, 0)
224 	ZEND_ARG_INFO(0, ftp)
225 	ZEND_ARG_INFO(0, file)
226 ZEND_END_ARG_INFO()
227 
228 ZEND_BEGIN_ARG_INFO(arginfo_ftp_site, 0)
229 	ZEND_ARG_INFO(0, ftp)
230 	ZEND_ARG_INFO(0, cmd)
231 ZEND_END_ARG_INFO()
232 
233 ZEND_BEGIN_ARG_INFO(arginfo_ftp_close, 0)
234 	ZEND_ARG_INFO(0, ftp)
235 ZEND_END_ARG_INFO()
236 
237 ZEND_BEGIN_ARG_INFO(arginfo_ftp_set_option, 0)
238 	ZEND_ARG_INFO(0, ftp)
239 	ZEND_ARG_INFO(0, option)
240 	ZEND_ARG_INFO(0, value)
241 ZEND_END_ARG_INFO()
242 
243 ZEND_BEGIN_ARG_INFO(arginfo_ftp_get_option, 0)
244 	ZEND_ARG_INFO(0, ftp)
245 	ZEND_ARG_INFO(0, option)
246 ZEND_END_ARG_INFO()
247 
248 /* }}} */
249 
250 static const zend_function_entry php_ftp_functions[] = {
251 	PHP_FE(ftp_connect,			arginfo_ftp_connect)
252 #ifdef HAVE_FTP_SSL
253 	PHP_FE(ftp_ssl_connect,		arginfo_ftp_ssl_connect)
254 #endif
255 	PHP_FE(ftp_login,			arginfo_ftp_login)
256 	PHP_FE(ftp_pwd,				arginfo_ftp_pwd)
257 	PHP_FE(ftp_cdup,			arginfo_ftp_cdup)
258 	PHP_FE(ftp_chdir,			arginfo_ftp_chdir)
259 	PHP_FE(ftp_exec,			arginfo_ftp_exec)
260 	PHP_FE(ftp_raw,				arginfo_ftp_raw)
261 	PHP_FE(ftp_mkdir,			arginfo_ftp_mkdir)
262 	PHP_FE(ftp_rmdir,			arginfo_ftp_rmdir)
263 	PHP_FE(ftp_chmod,			arginfo_ftp_chmod)
264 	PHP_FE(ftp_alloc,			arginfo_ftp_alloc)
265 	PHP_FE(ftp_nlist,			arginfo_ftp_nlist)
266 	PHP_FE(ftp_rawlist,			arginfo_ftp_rawlist)
267 	PHP_FE(ftp_mlsd,			arginfo_ftp_mlsd)
268 	PHP_FE(ftp_systype,			arginfo_ftp_systype)
269 	PHP_FE(ftp_pasv,			arginfo_ftp_pasv)
270 	PHP_FE(ftp_get,				arginfo_ftp_get)
271 	PHP_FE(ftp_fget,			arginfo_ftp_fget)
272 	PHP_FE(ftp_put,				arginfo_ftp_put)
273 	PHP_FE(ftp_append,			arginfo_ftp_append)
274 	PHP_FE(ftp_fput,			arginfo_ftp_fput)
275 	PHP_FE(ftp_size,			arginfo_ftp_size)
276 	PHP_FE(ftp_mdtm,			arginfo_ftp_mdtm)
277 	PHP_FE(ftp_rename,			arginfo_ftp_rename)
278 	PHP_FE(ftp_delete,			arginfo_ftp_delete)
279 	PHP_FE(ftp_site,			arginfo_ftp_site)
280 	PHP_FE(ftp_close,			arginfo_ftp_close)
281 	PHP_FE(ftp_set_option,		arginfo_ftp_set_option)
282 	PHP_FE(ftp_get_option,		arginfo_ftp_get_option)
283 	PHP_FE(ftp_nb_fget,			arginfo_ftp_nb_fget)
284 	PHP_FE(ftp_nb_get,			arginfo_ftp_nb_get)
285 	PHP_FE(ftp_nb_continue,		arginfo_ftp_nb_continue)
286 	PHP_FE(ftp_nb_put,			arginfo_ftp_nb_put)
287 	PHP_FE(ftp_nb_fput,			arginfo_ftp_nb_fput)
288 	PHP_FALIAS(ftp_quit, ftp_close, arginfo_ftp_close)
289 	PHP_FE_END
290 };
291 
292 zend_module_entry php_ftp_module_entry = {
293 	STANDARD_MODULE_HEADER_EX,
294 	NULL,
295 	NULL,
296 	"ftp",
297 	php_ftp_functions,
298 	PHP_MINIT(ftp),
299 	NULL,
300 	NULL,
301 	NULL,
302 	PHP_MINFO(ftp),
303 	PHP_FTP_VERSION,
304 	STANDARD_MODULE_PROPERTIES
305 };
306 
307 #if COMPILE_DL_FTP
ZEND_GET_MODULE(php_ftp)308 ZEND_GET_MODULE(php_ftp)
309 #endif
310 
311 static void ftp_destructor_ftpbuf(zend_resource *rsrc)
312 {
313 	ftpbuf_t *ftp = (ftpbuf_t *)rsrc->ptr;
314 
315 	ftp_close(ftp);
316 }
317 
PHP_MINIT_FUNCTION(ftp)318 PHP_MINIT_FUNCTION(ftp)
319 {
320 #ifdef HAVE_FTP_SSL
321 #if OPENSSL_VERSION_NUMBER < 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
322 	SSL_library_init();
323 	OpenSSL_add_all_ciphers();
324 	OpenSSL_add_all_digests();
325 	OpenSSL_add_all_algorithms();
326 
327 	SSL_load_error_strings();
328 #endif
329 #endif
330 
331 	le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, le_ftpbuf_name, module_number);
332 	REGISTER_LONG_CONSTANT("FTP_ASCII",  FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
333 	REGISTER_LONG_CONSTANT("FTP_TEXT",   FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
334 	REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
335 	REGISTER_LONG_CONSTANT("FTP_IMAGE",  FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
336 	REGISTER_LONG_CONSTANT("FTP_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS);
337 	REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
338 	REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS);
339 	REGISTER_LONG_CONSTANT("FTP_USEPASVADDRESS", PHP_FTP_OPT_USEPASVADDRESS, CONST_PERSISTENT | CONST_CS);
340 	REGISTER_LONG_CONSTANT("FTP_FAILED", PHP_FTP_FAILED, CONST_PERSISTENT | CONST_CS);
341 	REGISTER_LONG_CONSTANT("FTP_FINISHED", PHP_FTP_FINISHED, CONST_PERSISTENT | CONST_CS);
342 	REGISTER_LONG_CONSTANT("FTP_MOREDATA", PHP_FTP_MOREDATA, CONST_PERSISTENT | CONST_CS);
343 	return SUCCESS;
344 }
345 
PHP_MINFO_FUNCTION(ftp)346 PHP_MINFO_FUNCTION(ftp)
347 {
348 	php_info_print_table_start();
349 	php_info_print_table_row(2, "FTP support", "enabled");
350 #ifdef HAVE_FTP_SSL
351 	php_info_print_table_row(2, "FTPS support", "enabled");
352 #else
353 	php_info_print_table_row(2, "FTPS support", "disabled");
354 #endif
355 	php_info_print_table_end();
356 }
357 
358 #define	XTYPE(xtype, mode)	{ \
359 								if (mode != FTPTYPE_ASCII && mode != FTPTYPE_IMAGE) { \
360 									php_error_docref(NULL, E_WARNING, "Mode must be FTP_ASCII or FTP_BINARY"); \
361 									RETURN_FALSE; \
362 								} \
363 								xtype = mode; \
364 							}
365 
366 
367 /* {{{ proto resource ftp_connect(string host [, int port [, int timeout]])
368    Opens a FTP stream */
PHP_FUNCTION(ftp_connect)369 PHP_FUNCTION(ftp_connect)
370 {
371 	ftpbuf_t	*ftp;
372 	char		*host;
373 	size_t		host_len;
374 	zend_long 		port = 0;
375 	zend_long		timeout_sec = FTP_DEFAULT_TIMEOUT;
376 
377 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
378 		return;
379 	}
380 
381 	if (timeout_sec <= 0) {
382 		php_error_docref(NULL, E_WARNING, "Timeout has to be greater than 0");
383 		RETURN_FALSE;
384 	}
385 
386 	/* connect */
387 	if (!(ftp = ftp_open(host, (short)port, timeout_sec))) {
388 		RETURN_FALSE;
389 	}
390 
391 	/* autoseek for resuming */
392 	ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
393 	ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
394 #ifdef HAVE_FTP_SSL
395 	/* disable ssl */
396 	ftp->use_ssl = 0;
397 #endif
398 
399 	RETURN_RES(zend_register_resource(ftp, le_ftpbuf));
400 }
401 /* }}} */
402 
403 #ifdef HAVE_FTP_SSL
404 /* {{{ proto resource ftp_ssl_connect(string host [, int port [, int timeout]])
405    Opens a FTP-SSL stream */
PHP_FUNCTION(ftp_ssl_connect)406 PHP_FUNCTION(ftp_ssl_connect)
407 {
408 	ftpbuf_t	*ftp;
409 	char		*host;
410 	size_t		host_len;
411 	zend_long		port = 0;
412 	zend_long		timeout_sec = FTP_DEFAULT_TIMEOUT;
413 
414 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
415 		return;
416 	}
417 
418 	if (timeout_sec <= 0) {
419 		php_error_docref(NULL, E_WARNING, "Timeout has to be greater than 0");
420 		RETURN_FALSE;
421 	}
422 
423 	/* connect */
424 	if (!(ftp = ftp_open(host, (short)port, timeout_sec))) {
425 		RETURN_FALSE;
426 	}
427 
428 	/* autoseek for resuming */
429 	ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
430 	ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
431 	/* enable ssl */
432 	ftp->use_ssl = 1;
433 
434 	RETURN_RES(zend_register_resource(ftp, le_ftpbuf));
435 }
436 /* }}} */
437 #endif
438 
439 /* {{{ proto bool ftp_login(resource stream, string username, string password)
440    Logs into the FTP server */
PHP_FUNCTION(ftp_login)441 PHP_FUNCTION(ftp_login)
442 {
443 	zval 		*z_ftp;
444 	ftpbuf_t	*ftp;
445 	char *user, *pass;
446 	size_t user_len, pass_len;
447 
448 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &z_ftp, &user, &user_len, &pass, &pass_len) == FAILURE) {
449 		return;
450 	}
451 
452 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
453 		RETURN_FALSE;
454 	}
455 
456 	/* log in */
457 	if (!ftp_login(ftp, user, user_len, pass, pass_len)) {
458 		if (*ftp->inbuf) {
459 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
460 		}
461 		RETURN_FALSE;
462 	}
463 
464 	RETURN_TRUE;
465 }
466 /* }}} */
467 
468 /* {{{ proto string ftp_pwd(resource stream)
469    Returns the present working directory */
PHP_FUNCTION(ftp_pwd)470 PHP_FUNCTION(ftp_pwd)
471 {
472 	zval 		*z_ftp;
473 	ftpbuf_t	*ftp;
474 	const char	*pwd;
475 
476 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
477 		return;
478 	}
479 
480 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
481 		RETURN_FALSE;
482 	}
483 
484 	if (!(pwd = ftp_pwd(ftp))) {
485 		if (*ftp->inbuf) {
486 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
487 		}
488 		RETURN_FALSE;
489 	}
490 
491 	RETURN_STRING((char*) pwd);
492 }
493 /* }}} */
494 
495 /* {{{ proto bool ftp_cdup(resource stream)
496    Changes to the parent directory */
PHP_FUNCTION(ftp_cdup)497 PHP_FUNCTION(ftp_cdup)
498 {
499 	zval 		*z_ftp;
500 	ftpbuf_t	*ftp;
501 
502 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
503 		return;
504 	}
505 
506 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
507 		RETURN_FALSE;
508 	}
509 
510 	if (!ftp_cdup(ftp)) {
511 		if (*ftp->inbuf) {
512 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
513 		}
514 		RETURN_FALSE;
515 	}
516 
517 	RETURN_TRUE;
518 }
519 /* }}} */
520 
521 /* {{{ proto bool ftp_chdir(resource stream, string directory)
522    Changes directories */
PHP_FUNCTION(ftp_chdir)523 PHP_FUNCTION(ftp_chdir)
524 {
525 	zval		*z_ftp;
526 	ftpbuf_t	*ftp;
527 	char		*dir;
528 	size_t			dir_len;
529 
530 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
531 		return;
532 	}
533 
534 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
535 		RETURN_FALSE;
536 	}
537 
538 	/* change directories */
539 	if (!ftp_chdir(ftp, dir, dir_len)) {
540 		if (*ftp->inbuf) {
541 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
542 		}
543 		RETURN_FALSE;
544 	}
545 
546 	RETURN_TRUE;
547 }
548 /* }}} */
549 
550 /* {{{ proto bool ftp_exec(resource stream, string command)
551    Requests execution of a program on the FTP server */
PHP_FUNCTION(ftp_exec)552 PHP_FUNCTION(ftp_exec)
553 {
554 	zval		*z_ftp;
555 	ftpbuf_t	*ftp;
556 	char		*cmd;
557 	size_t			cmd_len;
558 
559 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
560 		return;
561 	}
562 
563 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
564 		RETURN_FALSE;
565 	}
566 
567 	/* execute serverside command */
568 	if (!ftp_exec(ftp, cmd, cmd_len)) {
569 		if (*ftp->inbuf) {
570 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
571 		}
572 		RETURN_FALSE;
573 	}
574 
575 	RETURN_TRUE;
576 }
577 /* }}} */
578 
579 /* {{{ proto array ftp_raw(resource stream, string command)
580    Sends a literal command to the FTP server */
PHP_FUNCTION(ftp_raw)581 PHP_FUNCTION(ftp_raw)
582 {
583 	zval		*z_ftp;
584 	ftpbuf_t	*ftp;
585 	char		*cmd;
586 	size_t			cmd_len;
587 
588 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
589 		return;
590 	}
591 
592 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
593 		RETURN_FALSE;
594 	}
595 
596 	/* execute arbitrary ftp command */
597 	ftp_raw(ftp, cmd, cmd_len, return_value);
598 }
599 /* }}} */
600 
601 /* {{{ proto string ftp_mkdir(resource stream, string directory)
602    Creates a directory and returns the absolute path for the new directory or false on error */
PHP_FUNCTION(ftp_mkdir)603 PHP_FUNCTION(ftp_mkdir)
604 {
605 	zval		*z_ftp;
606 	ftpbuf_t	*ftp;
607 	char		*dir;
608 	zend_string *tmp;
609 	size_t		dir_len;
610 
611 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
612 		return;
613 	}
614 
615 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
616 		RETURN_FALSE;
617 	}
618 
619 	/* create directory */
620 	if (NULL == (tmp = ftp_mkdir(ftp, dir, dir_len))) {
621 		if (*ftp->inbuf) {
622 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
623 		}
624 		RETURN_FALSE;
625 	}
626 
627 	RETURN_STR(tmp);
628 }
629 /* }}} */
630 
631 /* {{{ proto bool ftp_rmdir(resource stream, string directory)
632    Removes a directory */
PHP_FUNCTION(ftp_rmdir)633 PHP_FUNCTION(ftp_rmdir)
634 {
635 	zval		*z_ftp;
636 	ftpbuf_t	*ftp;
637 	char		*dir;
638 	size_t		dir_len;
639 
640 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
641 		return;
642 	}
643 
644 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
645 		RETURN_FALSE;
646 	}
647 
648 	/* remove directorie */
649 	if (!ftp_rmdir(ftp, dir, dir_len)) {
650 		if (*ftp->inbuf) {
651 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
652 		}
653 		RETURN_FALSE;
654 	}
655 
656 	RETURN_TRUE;
657 }
658 /* }}} */
659 
660 /* {{{ proto int ftp_chmod(resource stream, int mode, string filename)
661    Sets permissions on a file */
PHP_FUNCTION(ftp_chmod)662 PHP_FUNCTION(ftp_chmod)
663 {
664 	zval		*z_ftp;
665 	ftpbuf_t	*ftp;
666 	char		*filename;
667 	size_t		filename_len;
668 	zend_long		mode;
669 
670 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlp", &z_ftp, &mode, &filename, &filename_len) == FAILURE) {
671 		RETURN_FALSE;
672 	}
673 
674 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
675 		RETURN_FALSE;
676 	}
677 
678 	if (!ftp_chmod(ftp, mode, filename, filename_len)) {
679 		if (*ftp->inbuf) {
680 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
681 		}
682 		RETURN_FALSE;
683 	}
684 
685 	RETURN_LONG(mode);
686 }
687 /* }}} */
688 
689 /* {{{ proto bool ftp_alloc(resource stream, int size[, &response])
690    Attempt to allocate space on the remote FTP server */
PHP_FUNCTION(ftp_alloc)691 PHP_FUNCTION(ftp_alloc)
692 {
693 	zval		*z_ftp, *zresponse = NULL;
694 	ftpbuf_t	*ftp;
695 	zend_long		size, ret;
696 	zend_string	*response = NULL;
697 
698 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|z", &z_ftp, &size, &zresponse) == FAILURE) {
699 		RETURN_FALSE;
700 	}
701 
702 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
703 		RETURN_FALSE;
704 	}
705 
706 	ret = ftp_alloc(ftp, size, zresponse ? &response : NULL);
707 
708 	if (response) {
709 		ZEND_TRY_ASSIGN_REF_STR(zresponse, response);
710 	}
711 
712 	if (!ret) {
713 		RETURN_FALSE;
714 	}
715 
716 	RETURN_TRUE;
717 }
718 /* }}} */
719 
720 /* {{{ proto array ftp_nlist(resource stream, string directory)
721    Returns an array of filenames in the given directory */
PHP_FUNCTION(ftp_nlist)722 PHP_FUNCTION(ftp_nlist)
723 {
724 	zval		*z_ftp;
725 	ftpbuf_t	*ftp;
726 	char		**nlist, **ptr, *dir;
727 	size_t		dir_len;
728 
729 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &dir, &dir_len) == FAILURE) {
730 		return;
731 	}
732 
733 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
734 		RETURN_FALSE;
735 	}
736 
737 	/* get list of files */
738 	if (NULL == (nlist = ftp_nlist(ftp, dir, dir_len))) {
739 		RETURN_FALSE;
740 	}
741 
742 	array_init(return_value);
743 	for (ptr = nlist; *ptr; ptr++) {
744 		add_next_index_string(return_value, *ptr);
745 	}
746 	efree(nlist);
747 }
748 /* }}} */
749 
750 /* {{{ proto array ftp_rawlist(resource stream, string directory [, bool recursive])
751    Returns a detailed listing of a directory as an array of output lines */
PHP_FUNCTION(ftp_rawlist)752 PHP_FUNCTION(ftp_rawlist)
753 {
754 	zval		*z_ftp;
755 	ftpbuf_t	*ftp;
756 	char		**llist, **ptr, *dir;
757 	size_t		dir_len;
758 	zend_bool	recursive = 0;
759 
760 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|b", &z_ftp, &dir, &dir_len, &recursive) == FAILURE) {
761 		return;
762 	}
763 
764 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
765 		RETURN_FALSE;
766 	}
767 
768 	/* get raw directory listing */
769 	if (NULL == (llist = ftp_list(ftp, dir, dir_len, recursive))) {
770 		RETURN_FALSE;
771 	}
772 
773 	array_init(return_value);
774 	for (ptr = llist; *ptr; ptr++) {
775 		add_next_index_string(return_value, *ptr);
776 	}
777 	efree(llist);
778 }
779 /* }}} */
780 
781 /* {{{ proto array ftp_mlsd(resource stream, string directory)
782    Returns a detailed listing of a directory as an array of parsed output lines */
PHP_FUNCTION(ftp_mlsd)783 PHP_FUNCTION(ftp_mlsd)
784 {
785 	zval		*z_ftp;
786 	ftpbuf_t	*ftp;
787 	char		**llist, **ptr, *dir;
788 	size_t		dir_len;
789 	zval		entry;
790 
791 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
792 		return;
793 	}
794 
795 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
796 		RETURN_FALSE;
797 	}
798 
799 	/* get raw directory listing */
800 	if (NULL == (llist = ftp_mlsd(ftp, dir, dir_len))) {
801 		RETURN_FALSE;
802 	}
803 
804 	array_init(return_value);
805 	for (ptr = llist; *ptr; ptr++) {
806 		array_init(&entry);
807 		if (ftp_mlsd_parse_line(Z_ARRVAL_P(&entry), *ptr) == SUCCESS) {
808 			zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &entry);
809 		} else {
810 			zval_ptr_dtor(&entry);
811 		}
812 	}
813 
814 	efree(llist);
815 }
816 /* }}} */
817 
818 /* {{{ proto string ftp_systype(resource stream)
819    Returns the system type identifier */
PHP_FUNCTION(ftp_systype)820 PHP_FUNCTION(ftp_systype)
821 {
822 	zval		*z_ftp;
823 	ftpbuf_t	*ftp;
824 	const char	*syst;
825 
826 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
827 		return;
828 	}
829 
830 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
831 		RETURN_FALSE;
832 	}
833 
834 	if (NULL == (syst = ftp_syst(ftp))) {
835 		if (*ftp->inbuf) {
836 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
837 		}
838 		RETURN_FALSE;
839 	}
840 
841 	RETURN_STRING((char*) syst);
842 }
843 /* }}} */
844 
845 /* {{{ proto bool ftp_fget(resource stream, resource fp, string remote_file, [, int mode [, int resumepos]])
846    Retrieves a file from the FTP server and writes it to an open file */
PHP_FUNCTION(ftp_fget)847 PHP_FUNCTION(ftp_fget)
848 {
849 	zval		*z_ftp, *z_file;
850 	ftpbuf_t	*ftp;
851 	ftptype_t	xtype;
852 	php_stream	*stream;
853 	char		*file;
854 	size_t		file_len;
855 	zend_long		mode=FTPTYPE_IMAGE, resumepos=0;
856 
857 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs|ll", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
858 		return;
859 	}
860 
861 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
862 		RETURN_FALSE;
863 	}
864 	php_stream_from_res(stream, Z_RES_P(z_file));
865 	XTYPE(xtype, mode);
866 
867 	/* ignore autoresume if autoseek is switched off */
868 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
869 		resumepos = 0;
870 	}
871 
872 	if (ftp->autoseek && resumepos) {
873 		/* if autoresume is wanted seek to end */
874 		if (resumepos == PHP_FTP_AUTORESUME) {
875 			php_stream_seek(stream, 0, SEEK_END);
876 			resumepos = php_stream_tell(stream);
877 		} else {
878 			php_stream_seek(stream, resumepos, SEEK_SET);
879 		}
880 	}
881 
882 	if (!ftp_get(ftp, stream, file, file_len, xtype, resumepos)) {
883 		if (*ftp->inbuf) {
884 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
885 		}
886 		RETURN_FALSE;
887 	}
888 
889 	RETURN_TRUE;
890 }
891 /* }}} */
892 
893 /* {{{ proto int ftp_nb_fget(resource stream, resource fp, string remote_file [, int mode [, int resumepos]])
894    Retrieves a file from the FTP server asynchronly and writes it to an open file */
PHP_FUNCTION(ftp_nb_fget)895 PHP_FUNCTION(ftp_nb_fget)
896 {
897 	zval		*z_ftp, *z_file;
898 	ftpbuf_t	*ftp;
899 	ftptype_t	xtype;
900 	php_stream	*stream;
901 	char		*file;
902 	size_t		file_len;
903 	zend_long		mode=FTPTYPE_IMAGE, resumepos=0, ret;
904 
905 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs|ll", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
906 		return;
907 	}
908 
909 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
910 		RETURN_FALSE;
911 	}
912 	php_stream_from_res(stream, Z_RES_P(z_file));
913 	XTYPE(xtype, mode);
914 
915 	/* ignore autoresume if autoseek is switched off */
916 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
917 		resumepos = 0;
918 	}
919 
920 	if (ftp->autoseek && resumepos) {
921 		/* if autoresume is wanted seek to end */
922 		if (resumepos == PHP_FTP_AUTORESUME) {
923 			php_stream_seek(stream, 0, SEEK_END);
924 			resumepos = php_stream_tell(stream);
925 		} else {
926 			php_stream_seek(stream, resumepos, SEEK_SET);
927 		}
928 	}
929 
930 	/* configuration */
931 	ftp->direction = 0;   /* recv */
932 	ftp->closestream = 0; /* do not close */
933 
934 	if ((ret = ftp_nb_get(ftp, stream, file, file_len, xtype, resumepos)) == PHP_FTP_FAILED) {
935 		if (*ftp->inbuf) {
936 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
937 		}
938 		RETURN_LONG(ret);
939 	}
940 
941 	RETURN_LONG(ret);
942 }
943 /* }}} */
944 
945 /* {{{ proto bool ftp_pasv(resource stream, bool pasv)
946    Turns passive mode on or off */
PHP_FUNCTION(ftp_pasv)947 PHP_FUNCTION(ftp_pasv)
948 {
949 	zval		*z_ftp;
950 	ftpbuf_t	*ftp;
951 	zend_bool	pasv;
952 
953 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rb", &z_ftp, &pasv) == FAILURE) {
954 		return;
955 	}
956 
957 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
958 		RETURN_FALSE;
959 	}
960 
961 	if (!ftp_pasv(ftp, pasv ? 1 : 0)) {
962 		RETURN_FALSE;
963 	}
964 
965 	RETURN_TRUE;
966 }
967 /* }}} */
968 
969 /* {{{ proto bool ftp_get(resource stream, string local_file, string remote_file [, int mode [, int resume_pos]])
970    Retrieves a file from the FTP server and writes it to a local file */
PHP_FUNCTION(ftp_get)971 PHP_FUNCTION(ftp_get)
972 {
973 	zval		*z_ftp;
974 	ftpbuf_t	*ftp;
975 	ftptype_t	xtype;
976 	php_stream	*outstream;
977 	char		*local, *remote;
978 	size_t		local_len, remote_len;
979 	zend_long		mode=FTPTYPE_IMAGE, resumepos=0;
980 
981 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
982 		return;
983 	}
984 
985 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
986 		RETURN_FALSE;
987 	}
988 	XTYPE(xtype, mode);
989 
990 	/* ignore autoresume if autoseek is switched off */
991 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
992 		resumepos = 0;
993 	}
994 
995 #ifdef PHP_WIN32
996 	mode = FTPTYPE_IMAGE;
997 #endif
998 
999 	if (ftp->autoseek && resumepos) {
1000 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
1001 		if (outstream == NULL) {
1002 			outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
1003 		}
1004 		if (outstream != NULL) {
1005 			/* if autoresume is wanted seek to end */
1006 			if (resumepos == PHP_FTP_AUTORESUME) {
1007 				php_stream_seek(outstream, 0, SEEK_END);
1008 				resumepos = php_stream_tell(outstream);
1009 			} else {
1010 				php_stream_seek(outstream, resumepos, SEEK_SET);
1011 			}
1012 		}
1013 	} else {
1014 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
1015 	}
1016 
1017 	if (outstream == NULL)	{
1018 		php_error_docref(NULL, E_WARNING, "Error opening %s", local);
1019 		RETURN_FALSE;
1020 	}
1021 
1022 	if (!ftp_get(ftp, outstream, remote, remote_len, xtype, resumepos)) {
1023 		php_stream_close(outstream);
1024 		VCWD_UNLINK(local);
1025 		if (*ftp->inbuf) {
1026 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1027 		}
1028 		RETURN_FALSE;
1029 	}
1030 
1031 	php_stream_close(outstream);
1032 	RETURN_TRUE;
1033 }
1034 /* }}} */
1035 
1036 /* {{{ proto int ftp_nb_get(resource stream, string local_file, string remote_file, [, int mode [, int resume_pos]])
1037    Retrieves a file from the FTP server nbhronly and writes it to a local file */
PHP_FUNCTION(ftp_nb_get)1038 PHP_FUNCTION(ftp_nb_get)
1039 {
1040 	zval		*z_ftp;
1041 	ftpbuf_t	*ftp;
1042 	ftptype_t	xtype;
1043 	php_stream	*outstream;
1044 	char		*local, *remote;
1045 	size_t		local_len, remote_len;
1046 	int ret;
1047 	zend_long		mode=FTPTYPE_IMAGE, resumepos=0;
1048 
1049 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss|ll", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
1050 		return;
1051 	}
1052 
1053 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1054 		RETURN_FALSE;
1055 	}
1056 	XTYPE(xtype, mode);
1057 
1058 	/* ignore autoresume if autoseek is switched off */
1059 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
1060 		resumepos = 0;
1061 	}
1062 #ifdef PHP_WIN32
1063 	mode = FTPTYPE_IMAGE;
1064 #endif
1065 	if (ftp->autoseek && resumepos) {
1066 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
1067 		if (outstream == NULL) {
1068 			outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
1069 		}
1070 		if (outstream != NULL) {
1071 			/* if autoresume is wanted seek to end */
1072 			if (resumepos == PHP_FTP_AUTORESUME) {
1073 				php_stream_seek(outstream, 0, SEEK_END);
1074 				resumepos = php_stream_tell(outstream);
1075 			} else {
1076 				php_stream_seek(outstream, resumepos, SEEK_SET);
1077 			}
1078 		}
1079 	} else {
1080 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
1081 	}
1082 
1083 	if (outstream == NULL)	{
1084 		php_error_docref(NULL, E_WARNING, "Error opening %s", local);
1085 		RETURN_FALSE;
1086 	}
1087 
1088 	/* configuration */
1089 	ftp->direction = 0;   /* recv */
1090 	ftp->closestream = 1; /* do close */
1091 
1092 	if ((ret = ftp_nb_get(ftp, outstream, remote, remote_len, xtype, resumepos)) == PHP_FTP_FAILED) {
1093 		php_stream_close(outstream);
1094 		ftp->stream = NULL;
1095 		VCWD_UNLINK(local);
1096 		if (*ftp->inbuf) {
1097 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1098 		}
1099 		RETURN_LONG(PHP_FTP_FAILED);
1100 	}
1101 
1102 	if (ret == PHP_FTP_FINISHED){
1103 		php_stream_close(outstream);
1104 		ftp->stream = NULL;
1105 	}
1106 
1107 	RETURN_LONG(ret);
1108 }
1109 /* }}} */
1110 
1111 /* {{{ proto int ftp_nb_continue(resource stream)
1112    Continues retrieving/sending a file nbronously */
PHP_FUNCTION(ftp_nb_continue)1113 PHP_FUNCTION(ftp_nb_continue)
1114 {
1115 	zval		*z_ftp;
1116 	ftpbuf_t	*ftp;
1117 	zend_long		ret;
1118 
1119 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
1120 		return;
1121 	}
1122 
1123 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1124 		RETURN_FALSE;
1125 	}
1126 
1127 	if (!ftp->nb) {
1128 		php_error_docref(NULL, E_WARNING, "no nbronous transfer to continue.");
1129 		RETURN_LONG(PHP_FTP_FAILED);
1130 	}
1131 
1132 	if (ftp->direction) {
1133 		ret=ftp_nb_continue_write(ftp);
1134 	} else {
1135 		ret=ftp_nb_continue_read(ftp);
1136 	}
1137 
1138 	if (ret != PHP_FTP_MOREDATA && ftp->closestream) {
1139 		php_stream_close(ftp->stream);
1140 		ftp->stream = NULL;
1141 	}
1142 
1143 	if (ret == PHP_FTP_FAILED) {
1144 		php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1145 	}
1146 
1147 	RETURN_LONG(ret);
1148 }
1149 /* }}} */
1150 
1151 /* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp [, int mode [, int startpos]])
1152    Stores a file from an open file to the FTP server */
PHP_FUNCTION(ftp_fput)1153 PHP_FUNCTION(ftp_fput)
1154 {
1155 	zval		*z_ftp, *z_file;
1156 	ftpbuf_t	*ftp;
1157 	ftptype_t	xtype;
1158 	size_t		remote_len;
1159 	zend_long		mode=FTPTYPE_IMAGE, startpos=0;
1160 	php_stream	*stream;
1161 	char		*remote;
1162 
1163 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsr|ll", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
1164 		return;
1165 	}
1166 
1167 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1168 		RETURN_FALSE;
1169 	}
1170 	php_stream_from_zval(stream, z_file);
1171 	XTYPE(xtype, mode);
1172 
1173 	/* ignore autoresume if autoseek is switched off */
1174 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1175 		startpos = 0;
1176 	}
1177 
1178 	if (ftp->autoseek && startpos) {
1179 		/* if autoresume is wanted ask for remote size */
1180 		if (startpos == PHP_FTP_AUTORESUME) {
1181 			startpos = ftp_size(ftp, remote, remote_len);
1182 			if (startpos < 0) {
1183 				startpos = 0;
1184 			}
1185 		}
1186 		if (startpos) {
1187 			php_stream_seek(stream, startpos, SEEK_SET);
1188 		}
1189 	}
1190 
1191 	if (!ftp_put(ftp, remote, remote_len, stream, xtype, startpos)) {
1192 		if (*ftp->inbuf) {
1193 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1194 		}
1195 		RETURN_FALSE;
1196 	}
1197 
1198 	RETURN_TRUE;
1199 }
1200 /* }}} */
1201 
1202 /* {{{ proto int ftp_nb_fput(resource stream, string remote_file, resource fp [, int mode [, int startpos]])
1203    Stores a file from an open file to the FTP server nbronly */
PHP_FUNCTION(ftp_nb_fput)1204 PHP_FUNCTION(ftp_nb_fput)
1205 {
1206 	zval		*z_ftp, *z_file;
1207 	ftpbuf_t	*ftp;
1208 	ftptype_t	xtype;
1209 	size_t		remote_len;
1210 	int             ret;
1211 	zend_long	mode=FTPTYPE_IMAGE, startpos=0;
1212 	php_stream	*stream;
1213 	char		*remote;
1214 
1215 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsr|ll", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
1216 		return;
1217 	}
1218 
1219 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1220 		RETURN_FALSE;
1221 	}
1222 	php_stream_from_res(stream, Z_RES_P(z_file));
1223 	XTYPE(xtype, mode);
1224 
1225 	/* ignore autoresume if autoseek is switched off */
1226 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1227 		startpos = 0;
1228 	}
1229 
1230 	if (ftp->autoseek && startpos) {
1231 		/* if autoresume is wanted ask for remote size */
1232 		if (startpos == PHP_FTP_AUTORESUME) {
1233 			startpos = ftp_size(ftp, remote, remote_len);
1234 			if (startpos < 0) {
1235 				startpos = 0;
1236 			}
1237 		}
1238 		if (startpos) {
1239 			php_stream_seek(stream, startpos, SEEK_SET);
1240 		}
1241 	}
1242 
1243 	/* configuration */
1244 	ftp->direction = 1;   /* send */
1245 	ftp->closestream = 0; /* do not close */
1246 
1247 	if (((ret = ftp_nb_put(ftp, remote, remote_len, stream, xtype, startpos)) == PHP_FTP_FAILED)) {
1248 		if (*ftp->inbuf) {
1249 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1250 		}
1251 		RETURN_LONG(ret);
1252 	}
1253 
1254 	RETURN_LONG(ret);
1255 }
1256 /* }}} */
1257 
1258 
1259 /* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file [, int mode [, int startpos]])
1260    Stores a file on the FTP server */
PHP_FUNCTION(ftp_put)1261 PHP_FUNCTION(ftp_put)
1262 {
1263 	zval		*z_ftp;
1264 	ftpbuf_t	*ftp;
1265 	ftptype_t	xtype;
1266 	char		*remote, *local;
1267 	size_t		remote_len, local_len;
1268 	zend_long		mode=FTPTYPE_IMAGE, startpos=0;
1269 	php_stream 	*instream;
1270 
1271 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
1272 		return;
1273 	}
1274 
1275 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1276 		RETURN_FALSE;
1277 	}
1278 	XTYPE(xtype, mode);
1279 
1280 	if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1281 		RETURN_FALSE;
1282 	}
1283 
1284 	/* ignore autoresume if autoseek is switched off */
1285 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1286 		startpos = 0;
1287 	}
1288 
1289 	if (ftp->autoseek && startpos) {
1290 		/* if autoresume is wanted ask for remote size */
1291 		if (startpos == PHP_FTP_AUTORESUME) {
1292 			startpos = ftp_size(ftp, remote, remote_len);
1293 			if (startpos < 0) {
1294 				startpos = 0;
1295 			}
1296 		}
1297 		if (startpos) {
1298 			php_stream_seek(instream, startpos, SEEK_SET);
1299 		}
1300 	}
1301 
1302 	if (!ftp_put(ftp, remote, remote_len, instream, xtype, startpos)) {
1303 		php_stream_close(instream);
1304 		if (*ftp->inbuf) {
1305 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1306 		}
1307 		RETURN_FALSE;
1308 	}
1309 	php_stream_close(instream);
1310 
1311 	RETURN_TRUE;
1312 }
1313 /* }}} */
1314 
1315 /* {{{ proto bool ftp_append(resource stream, string remote_file, string local_file [, int mode])
1316    Append content of a file a another file on the FTP server */
PHP_FUNCTION(ftp_append)1317 PHP_FUNCTION(ftp_append)
1318 {
1319 	zval		*z_ftp;
1320 	ftpbuf_t	*ftp;
1321 	ftptype_t	xtype;
1322 	char		*remote, *local;
1323 	size_t		remote_len, local_len;
1324 	zend_long		mode=FTPTYPE_IMAGE;
1325 	php_stream 	*instream;
1326 
1327 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
1328 		return;
1329 	}
1330 
1331 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1332 		RETURN_FALSE;
1333 	}
1334 	XTYPE(xtype, mode);
1335 
1336 	if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1337 		RETURN_FALSE;
1338 	}
1339 
1340 	if (!ftp_append(ftp, remote, remote_len, instream, xtype)) {
1341 		php_stream_close(instream);
1342 		if (*ftp->inbuf) {
1343 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1344 		}
1345 		RETURN_FALSE;
1346 	}
1347 	php_stream_close(instream);
1348 
1349 	RETURN_TRUE;
1350 }
1351 /* }}} */
1352 
1353 /* {{{ proto int ftp_nb_put(resource stream, string remote_file, string local_file [, int mode [, int startpos]])
1354    Stores a file on the FTP server */
PHP_FUNCTION(ftp_nb_put)1355 PHP_FUNCTION(ftp_nb_put)
1356 {
1357 	zval		*z_ftp;
1358 	ftpbuf_t	*ftp;
1359 	ftptype_t	xtype;
1360 	char		*remote, *local;
1361 	size_t		remote_len, local_len;
1362 	zend_long		mode=FTPTYPE_IMAGE, startpos=0, ret;
1363 	php_stream 	*instream;
1364 
1365 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rpp|ll", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
1366 		return;
1367 	}
1368 
1369 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1370 		RETURN_FALSE;
1371 	}
1372 	XTYPE(xtype, mode);
1373 
1374 	if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1375 		RETURN_FALSE;
1376 	}
1377 
1378 	/* ignore autoresume if autoseek is switched off */
1379 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1380 		startpos = 0;
1381 	}
1382 
1383 	if (ftp->autoseek && startpos) {
1384 		/* if autoresume is wanted ask for remote size */
1385 		if (startpos == PHP_FTP_AUTORESUME) {
1386 			startpos = ftp_size(ftp, remote, remote_len);
1387 			if (startpos < 0) {
1388 				startpos = 0;
1389 			}
1390 		}
1391 		if (startpos) {
1392 			php_stream_seek(instream, startpos, SEEK_SET);
1393 		}
1394 	}
1395 
1396 	/* configuration */
1397 	ftp->direction = 1;   /* send */
1398 	ftp->closestream = 1; /* do close */
1399 
1400 	ret = ftp_nb_put(ftp, remote, remote_len, instream, xtype, startpos);
1401 
1402 	if (ret != PHP_FTP_MOREDATA) {
1403 		php_stream_close(instream);
1404 		ftp->stream = NULL;
1405 	}
1406 
1407 	if (ret == PHP_FTP_FAILED) {
1408 		php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1409 	}
1410 
1411 	RETURN_LONG(ret);
1412 }
1413 /* }}} */
1414 
1415 /* {{{ proto int ftp_size(resource stream, string filename)
1416    Returns the size of the file, or -1 on error */
PHP_FUNCTION(ftp_size)1417 PHP_FUNCTION(ftp_size)
1418 {
1419 	zval		*z_ftp;
1420 	ftpbuf_t	*ftp;
1421 	char		*file;
1422 	size_t		file_len;
1423 
1424 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &file, &file_len) == FAILURE) {
1425 		return;
1426 	}
1427 
1428 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1429 		RETURN_FALSE;
1430 	}
1431 
1432 	/* get file size */
1433 	RETURN_LONG(ftp_size(ftp, file, file_len));
1434 }
1435 /* }}} */
1436 
1437 /* {{{ proto int ftp_mdtm(resource stream, string filename)
1438    Returns the last modification time of the file, or -1 on error */
PHP_FUNCTION(ftp_mdtm)1439 PHP_FUNCTION(ftp_mdtm)
1440 {
1441 	zval		*z_ftp;
1442 	ftpbuf_t	*ftp;
1443 	char		*file;
1444 	size_t		file_len;
1445 
1446 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &z_ftp, &file, &file_len) == FAILURE) {
1447 		return;
1448 	}
1449 
1450 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1451 		RETURN_FALSE;
1452 	}
1453 
1454 	/* get file mod time */
1455 	RETURN_LONG(ftp_mdtm(ftp, file, file_len));
1456 }
1457 /* }}} */
1458 
1459 /* {{{ proto bool ftp_rename(resource stream, string src, string dest)
1460    Renames the given file to a new path */
PHP_FUNCTION(ftp_rename)1461 PHP_FUNCTION(ftp_rename)
1462 {
1463 	zval		*z_ftp;
1464 	ftpbuf_t	*ftp;
1465 	char		*src, *dest;
1466 	size_t		src_len, dest_len;
1467 
1468 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &z_ftp, &src, &src_len, &dest, &dest_len) == FAILURE) {
1469 		return;
1470 	}
1471 
1472 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1473 		RETURN_FALSE;
1474 	}
1475 
1476 	/* rename the file */
1477 	if (!ftp_rename(ftp, src, src_len, dest, dest_len)) {
1478 		if (*ftp->inbuf) {
1479 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1480 		}
1481 		RETURN_FALSE;
1482 	}
1483 
1484 	RETURN_TRUE;
1485 }
1486 /* }}} */
1487 
1488 /* {{{ proto bool ftp_delete(resource stream, string file)
1489    Deletes a file */
PHP_FUNCTION(ftp_delete)1490 PHP_FUNCTION(ftp_delete)
1491 {
1492 	zval		*z_ftp;
1493 	ftpbuf_t	*ftp;
1494 	char		*file;
1495 	size_t		file_len;
1496 
1497 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &file, &file_len) == FAILURE) {
1498 		return;
1499 	}
1500 
1501 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1502 		RETURN_FALSE;
1503 	}
1504 
1505 	/* delete the file */
1506 	if (!ftp_delete(ftp, file, file_len)) {
1507 		if (*ftp->inbuf) {
1508 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1509 		}
1510 		RETURN_FALSE;
1511 	}
1512 
1513 	RETURN_TRUE;
1514 }
1515 /* }}} */
1516 
1517 /* {{{ proto bool ftp_site(resource stream, string cmd)
1518    Sends a SITE command to the server */
PHP_FUNCTION(ftp_site)1519 PHP_FUNCTION(ftp_site)
1520 {
1521 	zval		*z_ftp;
1522 	ftpbuf_t	*ftp;
1523 	char		*cmd;
1524 	size_t		cmd_len;
1525 
1526 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
1527 		return;
1528 	}
1529 
1530 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1531 		RETURN_FALSE;
1532 	}
1533 
1534 	/* send the site command */
1535 	if (!ftp_site(ftp, cmd, cmd_len)) {
1536 		if (*ftp->inbuf) {
1537 			php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1538 		}
1539 		RETURN_FALSE;
1540 	}
1541 
1542 	RETURN_TRUE;
1543 }
1544 /* }}} */
1545 
1546 /* {{{ proto bool ftp_close(resource stream)
1547    Closes the FTP stream */
PHP_FUNCTION(ftp_close)1548 PHP_FUNCTION(ftp_close)
1549 {
1550 	zval		*z_ftp;
1551 	ftpbuf_t	*ftp;
1552 
1553 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_ftp) == FAILURE) {
1554 		return;
1555 	}
1556 
1557 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1558 		RETURN_FALSE;
1559 	}
1560 
1561 	ftp_quit(ftp);
1562 
1563 	RETURN_BOOL(zend_list_close(Z_RES_P(z_ftp)) == SUCCESS);
1564 }
1565 /* }}} */
1566 
1567 /* {{{ proto bool ftp_set_option(resource stream, int option, mixed value)
1568    Sets an FTP option */
PHP_FUNCTION(ftp_set_option)1569 PHP_FUNCTION(ftp_set_option)
1570 {
1571 	zval		*z_ftp, *z_value;
1572 	zend_long		option;
1573 	ftpbuf_t	*ftp;
1574 
1575 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &z_ftp, &option, &z_value) == FAILURE) {
1576 		return;
1577 	}
1578 
1579 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1580 		RETURN_FALSE;
1581 	}
1582 
1583 	switch (option) {
1584 		case PHP_FTP_OPT_TIMEOUT_SEC:
1585 			if (Z_TYPE_P(z_value) != IS_LONG) {
1586 				php_error_docref(NULL, E_WARNING, "Option TIMEOUT_SEC expects value of type int, %s given",
1587 					zend_zval_type_name(z_value));
1588 				RETURN_FALSE;
1589 			}
1590 			if (Z_LVAL_P(z_value) <= 0) {
1591 				php_error_docref(NULL, E_WARNING, "Timeout has to be greater than 0");
1592 				RETURN_FALSE;
1593 			}
1594 			ftp->timeout_sec = Z_LVAL_P(z_value);
1595 			RETURN_TRUE;
1596 			break;
1597 		case PHP_FTP_OPT_AUTOSEEK:
1598 			if (Z_TYPE_P(z_value) != IS_TRUE && Z_TYPE_P(z_value) != IS_FALSE) {
1599 				php_error_docref(NULL, E_WARNING, "Option AUTOSEEK expects value of type bool, %s given",
1600 					zend_zval_type_name(z_value));
1601 				RETURN_FALSE;
1602 			}
1603 			ftp->autoseek = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0;
1604 			RETURN_TRUE;
1605 			break;
1606 		case PHP_FTP_OPT_USEPASVADDRESS:
1607 			if (Z_TYPE_P(z_value) != IS_TRUE && Z_TYPE_P(z_value) != IS_FALSE) {
1608 				php_error_docref(NULL, E_WARNING, "Option USEPASVADDRESS expects value of type bool, %s given",
1609 					zend_zval_type_name(z_value));
1610 				RETURN_FALSE;
1611 			}
1612 			ftp->usepasvaddress = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0;
1613 			RETURN_TRUE;
1614 			break;
1615 		default:
1616 			php_error_docref(NULL, E_WARNING, "Unknown option '" ZEND_LONG_FMT "'", option);
1617 			RETURN_FALSE;
1618 			break;
1619 	}
1620 }
1621 /* }}} */
1622 
1623 /* {{{ proto mixed ftp_get_option(resource stream, int option)
1624    Gets an FTP option */
PHP_FUNCTION(ftp_get_option)1625 PHP_FUNCTION(ftp_get_option)
1626 {
1627 	zval		*z_ftp;
1628 	zend_long		option;
1629 	ftpbuf_t	*ftp;
1630 
1631 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &z_ftp, &option) == FAILURE) {
1632 		return;
1633 	}
1634 
1635 	if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1636 		RETURN_FALSE;
1637 	}
1638 
1639 	switch (option) {
1640 		case PHP_FTP_OPT_TIMEOUT_SEC:
1641 			RETURN_LONG(ftp->timeout_sec);
1642 			break;
1643 		case PHP_FTP_OPT_AUTOSEEK:
1644 			RETURN_BOOL(ftp->autoseek);
1645 			break;
1646 		case PHP_FTP_OPT_USEPASVADDRESS:
1647 			RETURN_BOOL(ftp->usepasvaddress);
1648 			break;
1649 		default:
1650 			php_error_docref(NULL, E_WARNING, "Unknown option '" ZEND_LONG_FMT "'", option);
1651 			RETURN_FALSE;
1652 			break;
1653 	}
1654 }
1655 /* }}} */
1656 
1657 #endif /* HAVE_FTP */
1658