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