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