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