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