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