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