xref: /PHP-5.6/ext/ftp/php_ftp.c (revision 49493a2d)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2016 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 #if HAVE_OPENSSL_EXT
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 #if HAVE_OPENSSL_EXT
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 #if HAVE_OPENSSL_EXT
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,
286 	"ftp",
287 	php_ftp_functions,
288 	PHP_MINIT(ftp),
289 	NULL,
290 	NULL,
291 	NULL,
292 	PHP_MINFO(ftp),
293     NO_VERSION_YET,
294 	STANDARD_MODULE_PROPERTIES
295 };
296 
297 #if COMPILE_DL_FTP
ZEND_GET_MODULE(php_ftp)298 ZEND_GET_MODULE(php_ftp)
299 #endif
300 
301 static void ftp_destructor_ftpbuf(zend_rsrc_list_entry *rsrc TSRMLS_DC)
302 {
303 	ftpbuf_t *ftp = (ftpbuf_t *)rsrc->ptr;
304 
305 	ftp_close(ftp);
306 }
307 
PHP_MINIT_FUNCTION(ftp)308 PHP_MINIT_FUNCTION(ftp)
309 {
310 	le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, le_ftpbuf_name, module_number);
311 	REGISTER_LONG_CONSTANT("FTP_ASCII",  FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
312 	REGISTER_LONG_CONSTANT("FTP_TEXT",   FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
313 	REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
314 	REGISTER_LONG_CONSTANT("FTP_IMAGE",  FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
315 	REGISTER_LONG_CONSTANT("FTP_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS);
316 	REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
317 	REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS);
318 	REGISTER_LONG_CONSTANT("FTP_USEPASVADDRESS", PHP_FTP_OPT_USEPASVADDRESS, CONST_PERSISTENT | CONST_CS);
319 	REGISTER_LONG_CONSTANT("FTP_FAILED", PHP_FTP_FAILED, CONST_PERSISTENT | CONST_CS);
320 	REGISTER_LONG_CONSTANT("FTP_FINISHED", PHP_FTP_FINISHED, CONST_PERSISTENT | CONST_CS);
321 	REGISTER_LONG_CONSTANT("FTP_MOREDATA", PHP_FTP_MOREDATA, CONST_PERSISTENT | CONST_CS);
322 	return SUCCESS;
323 }
324 
PHP_MINFO_FUNCTION(ftp)325 PHP_MINFO_FUNCTION(ftp)
326 {
327 	php_info_print_table_start();
328 	php_info_print_table_row(2, "FTP support", "enabled");
329 	php_info_print_table_end();
330 }
331 
332 #define	XTYPE(xtype, mode)	{ \
333 								if (mode != FTPTYPE_ASCII && mode != FTPTYPE_IMAGE) { \
334 									php_error_docref(NULL TSRMLS_CC, E_WARNING, "Mode must be FTP_ASCII or FTP_BINARY"); \
335 									RETURN_FALSE; \
336 								} \
337 								xtype = mode; \
338 							}
339 
340 
341 /* {{{ proto resource ftp_connect(string host [, int port [, int timeout]])
342    Opens a FTP stream */
PHP_FUNCTION(ftp_connect)343 PHP_FUNCTION(ftp_connect)
344 {
345 	ftpbuf_t	*ftp;
346 	char		*host;
347 	int		host_len;
348 	long 		port = 0;
349 	long		timeout_sec = FTP_DEFAULT_TIMEOUT;
350 
351 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
352 		return;
353 	}
354 
355 	if (timeout_sec <= 0) {
356 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0");
357 		RETURN_FALSE;
358 	}
359 
360 	/* connect */
361 	if (!(ftp = ftp_open(host, (short)port, timeout_sec TSRMLS_CC))) {
362 		RETURN_FALSE;
363 	}
364 
365 	/* autoseek for resuming */
366 	ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
367 	ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
368 #if HAVE_OPENSSL_EXT
369 	/* disable ssl */
370 	ftp->use_ssl = 0;
371 #endif
372 
373 	ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf);
374 }
375 /* }}} */
376 
377 #if HAVE_OPENSSL_EXT
378 /* {{{ proto resource ftp_ssl_connect(string host [, int port [, int timeout]])
379    Opens a FTP-SSL stream */
PHP_FUNCTION(ftp_ssl_connect)380 PHP_FUNCTION(ftp_ssl_connect)
381 {
382 	ftpbuf_t	*ftp;
383 	char		*host;
384 	int		host_len;
385 	long		port = 0;
386 	long		timeout_sec = FTP_DEFAULT_TIMEOUT;
387 
388 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
389 		return;
390 	}
391 
392 	if (timeout_sec <= 0) {
393 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0");
394 		RETURN_FALSE;
395 	}
396 
397 	/* connect */
398 	if (!(ftp = ftp_open(host, (short)port, timeout_sec TSRMLS_CC))) {
399 		RETURN_FALSE;
400 	}
401 
402 	/* autoseek for resuming */
403 	ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
404 	ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
405 	/* enable ssl */
406 	ftp->use_ssl = 1;
407 
408 	ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf);
409 }
410 /* }}} */
411 #endif
412 
413 /* {{{ proto bool ftp_login(resource stream, string username, string password)
414    Logs into the FTP server */
PHP_FUNCTION(ftp_login)415 PHP_FUNCTION(ftp_login)
416 {
417 	zval 		*z_ftp;
418 	ftpbuf_t	*ftp;
419 	char *user, *pass;
420 	int user_len, pass_len;
421 
422 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &z_ftp, &user, &user_len, &pass, &pass_len) == FAILURE) {
423 		return;
424 	}
425 
426 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
427 
428 	/* log in */
429 	if (!ftp_login(ftp, user, pass TSRMLS_CC)) {
430 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
431 		RETURN_FALSE;
432 	}
433 
434 	RETURN_TRUE;
435 }
436 /* }}} */
437 
438 /* {{{ proto string ftp_pwd(resource stream)
439    Returns the present working directory */
PHP_FUNCTION(ftp_pwd)440 PHP_FUNCTION(ftp_pwd)
441 {
442 	zval 		*z_ftp;
443 	ftpbuf_t	*ftp;
444 	const char	*pwd;
445 
446 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
447 		return;
448 	}
449 
450 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
451 
452 	if (!(pwd = ftp_pwd(ftp))) {
453 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
454 		RETURN_FALSE;
455 	}
456 
457 	RETURN_STRING((char*) pwd, 1);
458 }
459 /* }}} */
460 
461 /* {{{ proto bool ftp_cdup(resource stream)
462    Changes to the parent directory */
PHP_FUNCTION(ftp_cdup)463 PHP_FUNCTION(ftp_cdup)
464 {
465 	zval 		*z_ftp;
466 	ftpbuf_t	*ftp;
467 
468 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
469 		return;
470 	}
471 
472 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
473 
474 	if (!ftp_cdup(ftp)) {
475 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
476 		RETURN_FALSE;
477 	}
478 
479 	RETURN_TRUE;
480 }
481 /* }}} */
482 
483 /* {{{ proto bool ftp_chdir(resource stream, string directory)
484    Changes directories */
PHP_FUNCTION(ftp_chdir)485 PHP_FUNCTION(ftp_chdir)
486 {
487 	zval		*z_ftp;
488 	ftpbuf_t	*ftp;
489 	char		*dir;
490 	int			dir_len;
491 
492 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
493 		return;
494 	}
495 
496 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
497 
498 	/* change directories */
499 	if (!ftp_chdir(ftp, dir)) {
500 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
501 		RETURN_FALSE;
502 	}
503 
504 	RETURN_TRUE;
505 }
506 /* }}} */
507 
508 /* {{{ proto bool ftp_exec(resource stream, string command)
509    Requests execution of a program on the FTP server */
PHP_FUNCTION(ftp_exec)510 PHP_FUNCTION(ftp_exec)
511 {
512 	zval		*z_ftp;
513 	ftpbuf_t	*ftp;
514 	char		*cmd;
515 	int			cmd_len;
516 
517 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
518 		return;
519 	}
520 
521 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
522 
523 	/* execute serverside command */
524 	if (!ftp_exec(ftp, cmd)) {
525 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
526 		RETURN_FALSE;
527 	}
528 
529 	RETURN_TRUE;
530 }
531 /* }}} */
532 
533 /* {{{ proto array ftp_raw(resource stream, string command)
534    Sends a literal command to the FTP server */
PHP_FUNCTION(ftp_raw)535 PHP_FUNCTION(ftp_raw)
536 {
537 	zval		*z_ftp;
538 	ftpbuf_t	*ftp;
539 	char		*cmd;
540 	int			cmd_len;
541 
542 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
543 		return;
544 	}
545 
546 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
547 
548 	/* execute arbitrary ftp command */
549 	ftp_raw(ftp, cmd, return_value);
550 }
551 /* }}} */
552 
553 /* {{{ proto string ftp_mkdir(resource stream, string directory)
554    Creates a directory and returns the absolute path for the new directory or false on error */
PHP_FUNCTION(ftp_mkdir)555 PHP_FUNCTION(ftp_mkdir)
556 {
557 	zval		*z_ftp;
558 	ftpbuf_t	*ftp;
559 	char		*dir, *tmp;
560 	int		dir_len;
561 
562 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
563 		return;
564 	}
565 
566 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
567 
568 	/* create directorie */
569 	if (NULL == (tmp = ftp_mkdir(ftp, dir))) {
570 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
571 		RETURN_FALSE;
572 	}
573 
574 	RETURN_STRING(tmp, 0);
575 }
576 /* }}} */
577 
578 /* {{{ proto bool ftp_rmdir(resource stream, string directory)
579    Removes a directory */
PHP_FUNCTION(ftp_rmdir)580 PHP_FUNCTION(ftp_rmdir)
581 {
582 	zval		*z_ftp;
583 	ftpbuf_t	*ftp;
584 	char		*dir;
585 	int		dir_len;
586 
587 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &dir, &dir_len) == FAILURE) {
588 		return;
589 	}
590 
591 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
592 
593 	/* remove directorie */
594 	if (!ftp_rmdir(ftp, dir)) {
595 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
596 		RETURN_FALSE;
597 	}
598 
599 	RETURN_TRUE;
600 }
601 /* }}} */
602 
603 /* {{{ proto int ftp_chmod(resource stream, int mode, string filename)
604    Sets permissions on a file */
PHP_FUNCTION(ftp_chmod)605 PHP_FUNCTION(ftp_chmod)
606 {
607 	zval		*z_ftp;
608 	ftpbuf_t	*ftp;
609 	char		*filename;
610 	int		filename_len;
611 	long		mode;
612 
613 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlp", &z_ftp, &mode, &filename, &filename_len) == FAILURE) {
614 		RETURN_FALSE;
615 	}
616 
617 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
618 
619 	if (!ftp_chmod(ftp, mode, filename, filename_len)) {
620 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
621 		RETURN_FALSE;
622 	}
623 
624 	RETURN_LONG(mode);
625 }
626 /* }}} */
627 
628 /* {{{ proto bool ftp_alloc(resource stream, int size[, &response])
629    Attempt to allocate space on the remote FTP server */
PHP_FUNCTION(ftp_alloc)630 PHP_FUNCTION(ftp_alloc)
631 {
632 	zval		*z_ftp, *zresponse = NULL;
633 	ftpbuf_t	*ftp;
634 	long		size, ret;
635 	char		*response = NULL;
636 
637 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|z", &z_ftp, &size, &zresponse) == FAILURE) {
638 		RETURN_FALSE;
639 	}
640 
641 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
642 
643 	ret = ftp_alloc(ftp, size, zresponse ? &response : NULL);
644 	if (response) {
645 		zval_dtor(zresponse);
646 		ZVAL_STRING(zresponse, response, 0);
647 	}
648 
649 	if (!ret) {
650 		RETURN_FALSE;
651 	}
652 
653 	RETURN_TRUE;
654 }
655 /* }}} */
656 
657 /* {{{ proto array ftp_nlist(resource stream, string directory)
658    Returns an array of filenames in the given directory */
PHP_FUNCTION(ftp_nlist)659 PHP_FUNCTION(ftp_nlist)
660 {
661 	zval		*z_ftp;
662 	ftpbuf_t	*ftp;
663 	char		**nlist, **ptr, *dir;
664 	int		dir_len;
665 
666 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &dir, &dir_len) == FAILURE) {
667 		return;
668 	}
669 
670 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
671 
672 	/* get list of files */
673 	if (NULL == (nlist = ftp_nlist(ftp, dir TSRMLS_CC))) {
674 		RETURN_FALSE;
675 	}
676 
677 	array_init(return_value);
678 	for (ptr = nlist; *ptr; ptr++) {
679 		add_next_index_string(return_value, *ptr, 1);
680 	}
681 	efree(nlist);
682 }
683 /* }}} */
684 
685 /* {{{ proto array ftp_rawlist(resource stream, string directory [, bool recursive])
686    Returns a detailed listing of a directory as an array of output lines */
PHP_FUNCTION(ftp_rawlist)687 PHP_FUNCTION(ftp_rawlist)
688 {
689 	zval		*z_ftp;
690 	ftpbuf_t	*ftp;
691 	char		**llist, **ptr, *dir;
692 	int		dir_len;
693 	zend_bool	recursive = 0;
694 
695 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|b", &z_ftp, &dir, &dir_len, &recursive) == FAILURE) {
696 		return;
697 	}
698 
699 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
700 
701 	/* get raw directory listing */
702 	if (NULL == (llist = ftp_list(ftp, dir, recursive TSRMLS_CC))) {
703 		RETURN_FALSE;
704 	}
705 
706 	array_init(return_value);
707 	for (ptr = llist; *ptr; ptr++) {
708 		add_next_index_string(return_value, *ptr, 1);
709 	}
710 	efree(llist);
711 }
712 /* }}} */
713 
714 /* {{{ proto string ftp_systype(resource stream)
715    Returns the system type identifier */
PHP_FUNCTION(ftp_systype)716 PHP_FUNCTION(ftp_systype)
717 {
718 	zval		*z_ftp;
719 	ftpbuf_t	*ftp;
720 	const char	*syst;
721 
722 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
723 		return;
724 	}
725 
726 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
727 
728 	if (NULL == (syst = ftp_syst(ftp))) {
729 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
730 		RETURN_FALSE;
731 	}
732 
733 	RETURN_STRING((char*) syst, 1);
734 }
735 /* }}} */
736 
737 /* {{{ proto bool ftp_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos])
738    Retrieves a file from the FTP server and writes it to an open file */
PHP_FUNCTION(ftp_fget)739 PHP_FUNCTION(ftp_fget)
740 {
741 	zval		*z_ftp, *z_file;
742 	ftpbuf_t	*ftp;
743 	ftptype_t	xtype;
744 	php_stream	*stream;
745 	char		*file;
746 	int		file_len;
747 	long		mode, resumepos=0;
748 
749 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
750 		return;
751 	}
752 
753 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
754 	php_stream_from_zval(stream, &z_file);
755 	XTYPE(xtype, mode);
756 
757 	/* ignore autoresume if autoseek is switched off */
758 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
759 		resumepos = 0;
760 	}
761 
762 	if (ftp->autoseek && resumepos) {
763 		/* if autoresume is wanted seek to end */
764 		if (resumepos == PHP_FTP_AUTORESUME) {
765 			php_stream_seek(stream, 0, SEEK_END);
766 			resumepos = php_stream_tell(stream);
767 		} else {
768 			php_stream_seek(stream, resumepos, SEEK_SET);
769 		}
770 	}
771 
772 	if (!ftp_get(ftp, stream, file, xtype, resumepos TSRMLS_CC)) {
773 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
774 		RETURN_FALSE;
775 	}
776 
777 	RETURN_TRUE;
778 }
779 /* }}} */
780 
781 /* {{{ proto int ftp_nb_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos])
782    Retrieves a file from the FTP server asynchronly and writes it to an open file */
PHP_FUNCTION(ftp_nb_fget)783 PHP_FUNCTION(ftp_nb_fget)
784 {
785 	zval		*z_ftp, *z_file;
786 	ftpbuf_t	*ftp;
787 	ftptype_t	xtype;
788 	php_stream	*stream;
789 	char		*file;
790 	int		file_len;
791 	long		mode, resumepos=0, ret;
792 
793 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
794 		return;
795 	}
796 
797 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
798 	php_stream_from_zval(stream, &z_file);
799 	XTYPE(xtype, mode);
800 
801 	/* ignore autoresume if autoseek is switched off */
802 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
803 		resumepos = 0;
804 	}
805 
806 	if (ftp->autoseek && resumepos) {
807 		/* if autoresume is wanted seek to end */
808 		if (resumepos == PHP_FTP_AUTORESUME) {
809 			php_stream_seek(stream, 0, SEEK_END);
810 			resumepos = php_stream_tell(stream);
811 		} else {
812 			php_stream_seek(stream, resumepos, SEEK_SET);
813 		}
814 	}
815 
816 	/* configuration */
817 	ftp->direction = 0;   /* recv */
818 	ftp->closestream = 0; /* do not close */
819 
820 	if ((ret = ftp_nb_get(ftp, stream, file, xtype, resumepos TSRMLS_CC)) == PHP_FTP_FAILED) {
821 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
822 		RETURN_LONG(ret);
823 	}
824 
825 	RETURN_LONG(ret);
826 }
827 /* }}} */
828 
829 /* {{{ proto bool ftp_pasv(resource stream, bool pasv)
830    Turns passive mode on or off */
PHP_FUNCTION(ftp_pasv)831 PHP_FUNCTION(ftp_pasv)
832 {
833 	zval		*z_ftp;
834 	ftpbuf_t	*ftp;
835 	zend_bool	pasv;
836 
837 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &z_ftp, &pasv) == FAILURE) {
838 		return;
839 	}
840 
841 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
842 
843 	if (!ftp_pasv(ftp, pasv ? 1 : 0)) {
844 		RETURN_FALSE;
845 	}
846 
847 	RETURN_TRUE;
848 }
849 /* }}} */
850 
851 /* {{{ proto bool ftp_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos])
852    Retrieves a file from the FTP server and writes it to a local file */
PHP_FUNCTION(ftp_get)853 PHP_FUNCTION(ftp_get)
854 {
855 	zval		*z_ftp;
856 	ftpbuf_t	*ftp;
857 	ftptype_t	xtype;
858 	php_stream	*outstream;
859 	char		*local, *remote;
860 	int		local_len, remote_len;
861 	long		mode, resumepos=0;
862 
863 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
864 		return;
865 	}
866 
867 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
868 	XTYPE(xtype, mode);
869 
870 	/* ignore autoresume if autoseek is switched off */
871 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
872 		resumepos = 0;
873 	}
874 
875 #ifdef PHP_WIN32
876 	mode = FTPTYPE_IMAGE;
877 #endif
878 
879 	if (ftp->autoseek && resumepos) {
880 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
881 		if (outstream == NULL) {
882 			outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
883 		}
884 		if (outstream != NULL) {
885 			/* if autoresume is wanted seek to end */
886 			if (resumepos == PHP_FTP_AUTORESUME) {
887 				php_stream_seek(outstream, 0, SEEK_END);
888 				resumepos = php_stream_tell(outstream);
889 			} else {
890 				php_stream_seek(outstream, resumepos, SEEK_SET);
891 			}
892 		}
893 	} else {
894 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
895 	}
896 
897 	if (outstream == NULL)	{
898 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening %s", local);
899 		RETURN_FALSE;
900 	}
901 
902 	if (!ftp_get(ftp, outstream, remote, xtype, resumepos TSRMLS_CC)) {
903 		php_stream_close(outstream);
904 		VCWD_UNLINK(local);
905 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
906 		RETURN_FALSE;
907 	}
908 
909 	php_stream_close(outstream);
910 	RETURN_TRUE;
911 }
912 /* }}} */
913 
914 /* {{{ proto int ftp_nb_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos])
915    Retrieves a file from the FTP server nbhronly and writes it to a local file */
PHP_FUNCTION(ftp_nb_get)916 PHP_FUNCTION(ftp_nb_get)
917 {
918 	zval		*z_ftp;
919 	ftpbuf_t	*ftp;
920 	ftptype_t	xtype;
921 	php_stream	*outstream;
922 	char		*local, *remote;
923 	int		local_len, remote_len, ret;
924 	long		mode, resumepos=0;
925 
926 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
927 		return;
928 	}
929 
930 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
931 	XTYPE(xtype, mode);
932 
933 	/* ignore autoresume if autoseek is switched off */
934 	if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
935 		resumepos = 0;
936 	}
937 #ifdef PHP_WIN32
938 	mode = FTPTYPE_IMAGE;
939 #endif
940 	if (ftp->autoseek && resumepos) {
941 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL);
942 		if (outstream == NULL) {
943 			outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
944 		}
945 		if (outstream != NULL) {
946 			/* if autoresume is wanted seek to end */
947 			if (resumepos == PHP_FTP_AUTORESUME) {
948 				php_stream_seek(outstream, 0, SEEK_END);
949 				resumepos = php_stream_tell(outstream);
950 			} else {
951 				php_stream_seek(outstream, resumepos, SEEK_SET);
952 			}
953 		}
954 	} else {
955 		outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL);
956 	}
957 
958 	if (outstream == NULL)	{
959 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error opening %s", local);
960 		RETURN_FALSE;
961 	}
962 
963 	/* configuration */
964 	ftp->direction = 0;   /* recv */
965 	ftp->closestream = 1; /* do close */
966 
967 	if ((ret = ftp_nb_get(ftp, outstream, remote, xtype, resumepos TSRMLS_CC)) == PHP_FTP_FAILED) {
968 		php_stream_close(outstream);
969 		ftp->stream = NULL;
970 		VCWD_UNLINK(local);
971 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
972 		RETURN_LONG(PHP_FTP_FAILED);
973 	}
974 
975 	if (ret == PHP_FTP_FINISHED){
976 		php_stream_close(outstream);
977 		ftp->stream = NULL;
978 	}
979 
980 	RETURN_LONG(ret);
981 }
982 /* }}} */
983 
984 /* {{{ proto int ftp_nb_continue(resource stream)
985    Continues retrieving/sending a file nbronously */
PHP_FUNCTION(ftp_nb_continue)986 PHP_FUNCTION(ftp_nb_continue)
987 {
988 	zval		*z_ftp;
989 	ftpbuf_t	*ftp;
990 	long		ret;
991 
992 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
993 		return;
994 	}
995 
996 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
997 
998 	if (!ftp->nb) {
999 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "no nbronous transfer to continue.");
1000 		RETURN_LONG(PHP_FTP_FAILED);
1001 	}
1002 
1003 	if (ftp->direction) {
1004 		ret=ftp_nb_continue_write(ftp TSRMLS_CC);
1005 	} else {
1006 		ret=ftp_nb_continue_read(ftp TSRMLS_CC);
1007 	}
1008 
1009 	if (ret != PHP_FTP_MOREDATA && ftp->closestream) {
1010 		php_stream_close(ftp->stream);
1011 		ftp->stream = NULL;
1012 	}
1013 
1014 	if (ret == PHP_FTP_FAILED) {
1015 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1016 	}
1017 
1018 	RETURN_LONG(ret);
1019 }
1020 /* }}} */
1021 
1022 /* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp, int mode[, int startpos])
1023    Stores a file from an open file to the FTP server */
PHP_FUNCTION(ftp_fput)1024 PHP_FUNCTION(ftp_fput)
1025 {
1026 	zval		*z_ftp, *z_file;
1027 	ftpbuf_t	*ftp;
1028 	ftptype_t	xtype;
1029 	int		remote_len;
1030 	long		mode, startpos=0;
1031 	php_stream	*stream;
1032 	char		*remote;
1033 
1034 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
1035 		return;
1036 	}
1037 
1038 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1039 	php_stream_from_zval(stream, &z_file);
1040 	XTYPE(xtype, mode);
1041 
1042 	/* ignore autoresume if autoseek is switched off */
1043 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1044 		startpos = 0;
1045 	}
1046 
1047 	if (ftp->autoseek && startpos) {
1048 		/* if autoresume is wanted ask for remote size */
1049 		if (startpos == PHP_FTP_AUTORESUME) {
1050 			startpos = ftp_size(ftp, remote);
1051 			if (startpos < 0) {
1052 				startpos = 0;
1053 			}
1054 		}
1055 		if (startpos) {
1056 			php_stream_seek(stream, startpos, SEEK_SET);
1057 		}
1058 	}
1059 
1060 	if (!ftp_put(ftp, remote, stream, xtype, startpos TSRMLS_CC)) {
1061 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1062 		RETURN_FALSE;
1063 	}
1064 
1065 	RETURN_TRUE;
1066 }
1067 /* }}} */
1068 
1069 /* {{{ proto int ftp_nb_fput(resource stream, string remote_file, resource fp, int mode[, int startpos])
1070    Stores a file from an open file to the FTP server nbronly */
PHP_FUNCTION(ftp_nb_fput)1071 PHP_FUNCTION(ftp_nb_fput)
1072 {
1073 	zval		*z_ftp, *z_file;
1074 	ftpbuf_t	*ftp;
1075 	ftptype_t	xtype;
1076 	int		remote_len, ret;
1077 	long		mode, startpos=0;
1078 	php_stream	*stream;
1079 	char		*remote;
1080 
1081 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
1082 		return;
1083 	}
1084 
1085 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1086 	php_stream_from_zval(stream, &z_file);
1087 	XTYPE(xtype, mode);
1088 
1089 	/* ignore autoresume if autoseek is switched off */
1090 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1091 		startpos = 0;
1092 	}
1093 
1094 	if (ftp->autoseek && startpos) {
1095 		/* if autoresume is wanted ask for remote size */
1096 		if (startpos == PHP_FTP_AUTORESUME) {
1097 			startpos = ftp_size(ftp, remote);
1098 			if (startpos < 0) {
1099 				startpos = 0;
1100 			}
1101 		}
1102 		if (startpos) {
1103 			php_stream_seek(stream, startpos, SEEK_SET);
1104 		}
1105 	}
1106 
1107 	/* configuration */
1108 	ftp->direction = 1;   /* send */
1109 	ftp->closestream = 0; /* do not close */
1110 
1111 	if (((ret = ftp_nb_put(ftp, remote, stream, xtype, startpos TSRMLS_CC)) == PHP_FTP_FAILED)) {
1112 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1113 		RETURN_LONG(ret);
1114 	}
1115 
1116 	RETURN_LONG(ret);
1117 }
1118 /* }}} */
1119 
1120 
1121 /* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
1122    Stores a file on the FTP server */
PHP_FUNCTION(ftp_put)1123 PHP_FUNCTION(ftp_put)
1124 {
1125 	zval		*z_ftp;
1126 	ftpbuf_t	*ftp;
1127 	ftptype_t	xtype;
1128 	char		*remote, *local;
1129 	long		remote_len, local_len;
1130 	long		mode, startpos=0;
1131 	php_stream 	*instream;
1132 
1133 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
1134 		return;
1135 	}
1136 
1137 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1138 	XTYPE(xtype, mode);
1139 
1140 	if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1141 		RETURN_FALSE;
1142 	}
1143 
1144 	/* ignore autoresume if autoseek is switched off */
1145 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1146 		startpos = 0;
1147 	}
1148 
1149 	if (ftp->autoseek && startpos) {
1150 		/* if autoresume is wanted ask for remote size */
1151 		if (startpos == PHP_FTP_AUTORESUME) {
1152 			startpos = ftp_size(ftp, remote);
1153 			if (startpos < 0) {
1154 				startpos = 0;
1155 			}
1156 		}
1157 		if (startpos) {
1158 			php_stream_seek(instream, startpos, SEEK_SET);
1159 		}
1160 	}
1161 
1162 	if (!ftp_put(ftp, remote, instream, xtype, startpos TSRMLS_CC)) {
1163 		php_stream_close(instream);
1164 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1165 		RETURN_FALSE;
1166 	}
1167 	php_stream_close(instream);
1168 
1169 	RETURN_TRUE;
1170 }
1171 /* }}} */
1172 
1173 
1174 /* {{{ proto int ftp_nb_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
1175    Stores a file on the FTP server */
PHP_FUNCTION(ftp_nb_put)1176 PHP_FUNCTION(ftp_nb_put)
1177 {
1178 	zval		*z_ftp;
1179 	ftpbuf_t	*ftp;
1180 	ftptype_t	xtype;
1181 	char		*remote, *local;
1182 	int		remote_len, local_len;
1183 	long		mode, startpos=0, ret;
1184 	php_stream 	*instream;
1185 
1186 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
1187 		return;
1188 	}
1189 
1190 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1191 	XTYPE(xtype, mode);
1192 
1193 	if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1194 		RETURN_FALSE;
1195 	}
1196 
1197 	/* ignore autoresume if autoseek is switched off */
1198 	if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
1199 		startpos = 0;
1200 	}
1201 
1202 	if (ftp->autoseek && startpos) {
1203 		/* if autoresume is wanted ask for remote size */
1204 		if (startpos == PHP_FTP_AUTORESUME) {
1205 			startpos = ftp_size(ftp, remote);
1206 			if (startpos < 0) {
1207 				startpos = 0;
1208 			}
1209 		}
1210 		if (startpos) {
1211 			php_stream_seek(instream, startpos, SEEK_SET);
1212 		}
1213 	}
1214 
1215 	/* configuration */
1216 	ftp->direction = 1;   /* send */
1217 	ftp->closestream = 1; /* do close */
1218 
1219 	ret = ftp_nb_put(ftp, remote, instream, xtype, startpos TSRMLS_CC);
1220 
1221 	if (ret != PHP_FTP_MOREDATA) {
1222 		php_stream_close(instream);
1223 		ftp->stream = NULL;
1224 	}
1225 
1226 	if (ret == PHP_FTP_FAILED) {
1227 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1228 	}
1229 
1230 	RETURN_LONG(ret);
1231 }
1232 /* }}} */
1233 
1234 /* {{{ proto int ftp_size(resource stream, string filename)
1235    Returns the size of the file, or -1 on error */
PHP_FUNCTION(ftp_size)1236 PHP_FUNCTION(ftp_size)
1237 {
1238 	zval		*z_ftp;
1239 	ftpbuf_t	*ftp;
1240 	char		*file;
1241 	int		file_len;
1242 
1243 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) {
1244 		return;
1245 	}
1246 
1247 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1248 
1249 	/* get file size */
1250 	RETURN_LONG(ftp_size(ftp, file));
1251 }
1252 /* }}} */
1253 
1254 /* {{{ proto int ftp_mdtm(resource stream, string filename)
1255    Returns the last modification time of the file, or -1 on error */
PHP_FUNCTION(ftp_mdtm)1256 PHP_FUNCTION(ftp_mdtm)
1257 {
1258 	zval		*z_ftp;
1259 	ftpbuf_t	*ftp;
1260 	char		*file;
1261 	int		file_len;
1262 
1263 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &z_ftp, &file, &file_len) == FAILURE) {
1264 		return;
1265 	}
1266 
1267 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1268 
1269 	/* get file mod time */
1270 	RETURN_LONG(ftp_mdtm(ftp, file));
1271 }
1272 /* }}} */
1273 
1274 /* {{{ proto bool ftp_rename(resource stream, string src, string dest)
1275    Renames the given file to a new path */
PHP_FUNCTION(ftp_rename)1276 PHP_FUNCTION(ftp_rename)
1277 {
1278 	zval		*z_ftp;
1279 	ftpbuf_t	*ftp;
1280 	char		*src, *dest;
1281 	int		src_len, dest_len;
1282 
1283 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &z_ftp, &src, &src_len, &dest, &dest_len) == FAILURE) {
1284 		return;
1285 	}
1286 
1287 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1288 
1289 	/* rename the file */
1290 	if (!ftp_rename(ftp, src, dest)) {
1291 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1292 		RETURN_FALSE;
1293 	}
1294 
1295 	RETURN_TRUE;
1296 }
1297 /* }}} */
1298 
1299 /* {{{ proto bool ftp_delete(resource stream, string file)
1300    Deletes a file */
PHP_FUNCTION(ftp_delete)1301 PHP_FUNCTION(ftp_delete)
1302 {
1303 	zval		*z_ftp;
1304 	ftpbuf_t	*ftp;
1305 	char		*file;
1306 	int		file_len;
1307 
1308 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &file, &file_len) == FAILURE) {
1309 		return;
1310 	}
1311 
1312 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1313 
1314 	/* delete the file */
1315 	if (!ftp_delete(ftp, file)) {
1316 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1317 		RETURN_FALSE;
1318 	}
1319 
1320 	RETURN_TRUE;
1321 }
1322 /* }}} */
1323 
1324 /* {{{ proto bool ftp_site(resource stream, string cmd)
1325    Sends a SITE command to the server */
PHP_FUNCTION(ftp_site)1326 PHP_FUNCTION(ftp_site)
1327 {
1328 	zval		*z_ftp;
1329 	ftpbuf_t	*ftp;
1330 	char		*cmd;
1331 	int		cmd_len;
1332 
1333 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
1334 		return;
1335 	}
1336 
1337 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1338 
1339 	/* send the site command */
1340 	if (!ftp_site(ftp, cmd)) {
1341 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ftp->inbuf);
1342 		RETURN_FALSE;
1343 	}
1344 
1345 	RETURN_TRUE;
1346 }
1347 /* }}} */
1348 
1349 /* {{{ proto bool ftp_close(resource stream)
1350    Closes the FTP stream */
PHP_FUNCTION(ftp_close)1351 PHP_FUNCTION(ftp_close)
1352 {
1353 	zval		*z_ftp;
1354 	ftpbuf_t	*ftp;
1355 
1356 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
1357 		return;
1358 	}
1359 
1360 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1361 
1362 	ftp_quit(ftp);
1363 
1364 	RETURN_BOOL(zend_list_delete(Z_LVAL_P(z_ftp)) == SUCCESS);
1365 }
1366 /* }}} */
1367 
1368 /* {{{ proto bool ftp_set_option(resource stream, int option, mixed value)
1369    Sets an FTP option */
PHP_FUNCTION(ftp_set_option)1370 PHP_FUNCTION(ftp_set_option)
1371 {
1372 	zval		*z_ftp, *z_value;
1373 	long		option;
1374 	ftpbuf_t	*ftp;
1375 
1376 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &z_ftp, &option, &z_value) == FAILURE) {
1377 		return;
1378 	}
1379 
1380 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1381 
1382 	switch (option) {
1383 		case PHP_FTP_OPT_TIMEOUT_SEC:
1384 			if (Z_TYPE_P(z_value) != IS_LONG) {
1385 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option TIMEOUT_SEC expects value of type long, %s given",
1386 					zend_zval_type_name(z_value));
1387 				RETURN_FALSE;
1388 			}
1389 			if (Z_LVAL_P(z_value) <= 0) {
1390 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timeout has to be greater than 0");
1391 				RETURN_FALSE;
1392 			}
1393 			ftp->timeout_sec = Z_LVAL_P(z_value);
1394 			RETURN_TRUE;
1395 			break;
1396 		case PHP_FTP_OPT_AUTOSEEK:
1397 			if (Z_TYPE_P(z_value) != IS_BOOL) {
1398 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option AUTOSEEK expects value of type boolean, %s given",
1399 					zend_zval_type_name(z_value));
1400 				RETURN_FALSE;
1401 			}
1402 			ftp->autoseek = Z_LVAL_P(z_value);
1403 			RETURN_TRUE;
1404 			break;
1405 		case PHP_FTP_OPT_USEPASVADDRESS:
1406 			if (Z_TYPE_P(z_value) != IS_BOOL) {
1407 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option USEPASVADDRESS expects value of type boolean, %s given",
1408 					zend_zval_type_name(z_value));
1409 				RETURN_FALSE;
1410 			}
1411 			ftp->usepasvaddress = Z_LVAL_P(z_value);
1412 			RETURN_TRUE;
1413 			break;
1414 		default:
1415 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option '%ld'", option);
1416 			RETURN_FALSE;
1417 			break;
1418 	}
1419 }
1420 /* }}} */
1421 
1422 /* {{{ proto mixed ftp_get_option(resource stream, int option)
1423    Gets an FTP option */
PHP_FUNCTION(ftp_get_option)1424 PHP_FUNCTION(ftp_get_option)
1425 {
1426 	zval		*z_ftp;
1427 	long		option;
1428 	ftpbuf_t	*ftp;
1429 
1430 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &z_ftp, &option) == FAILURE) {
1431 		return;
1432 	}
1433 
1434 	ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
1435 
1436 	switch (option) {
1437 		case PHP_FTP_OPT_TIMEOUT_SEC:
1438 			RETURN_LONG(ftp->timeout_sec);
1439 			break;
1440 		case PHP_FTP_OPT_AUTOSEEK:
1441 			RETURN_BOOL(ftp->autoseek);
1442 			break;
1443 		case PHP_FTP_OPT_USEPASVADDRESS:
1444 			RETURN_BOOL(ftp->usepasvaddress);
1445 			break;
1446 		default:
1447 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option '%ld'", option);
1448 			RETURN_FALSE;
1449 			break;
1450 	}
1451 }
1452 /* }}} */
1453 
1454 #endif /* HAVE_FTP */
1455 
1456 /*
1457  * Local variables:
1458  * tab-width: 4
1459  * c-basic-offset: 4
1460  * indent-tabs-mode: t
1461  * End:
1462  */
1463