]> granicus.if.org Git - php/commitdiff
- Added ftp_set_option(), ftp_get_option() and support for setting a
authorMarkus Fischer <mfischer@php.net>
Wed, 2 Jan 2002 14:58:17 +0000 (14:58 +0000)
committerMarkus Fischer <mfischer@php.net>
Wed, 2 Jan 2002 14:58:17 +0000 (14:58 +0000)
  custom timeout.
# Adding custom buffer size would be next, no promises though.

ext/ftp/ftp.c
ext/ftp/ftp.h
ext/ftp/php_ftp.c
ext/ftp/php_ftp.h

index df20efd49a03b0603cb090aacfc7422d539152cb..c9a23bedaf9b1abdc367bdb5a69c76965698341c 100644 (file)
@@ -66,11 +66,12 @@ static int          ftp_putcmd(     ftpbuf_t *ftp,
                                        const char *args);
 
 /* wrapper around send/recv to handle timeouts */
-static int             my_send(int s, void *buf, size_t len);
-static int             my_recv(int s, void *buf, size_t len);
-static int             my_connect(int s, const struct sockaddr *addr,
+static int             my_send(ftpbuf_t *ftp, int s, void *buf, size_t len);
+static int             my_recv(ftpbuf_t *ftp, int s, void *buf, size_t len);
+static int             my_connect(ftpbuf_t *ftp, int s, const struct sockaddr *addr,
                                int addrlen);
-static int             my_accept(int s, struct sockaddr *addr, int *addrlen);
+static int             my_accept(ftpbuf_t *ftp, int s, struct sockaddr *addr,
+                               int *addrlen);
 
 /* reads a line the socket , returns true on success, false on error */
 static int             ftp_readline(ftpbuf_t *ftp);
@@ -85,7 +86,7 @@ static int            ftp_type(ftpbuf_t *ftp, ftptype_t type);
 static databuf_t*      ftp_getdata(ftpbuf_t *ftp);
 
 /* accepts the data connection, returns updated data buffer */
-static databuf_t*      data_accept(databuf_t *data);
+static databuf_t*      data_accept(databuf_t *data, ftpbuf_t *ftp);
 
 /* closes the data connection, returns NULL */
 static databuf_t*      data_close(databuf_t *data);
@@ -104,7 +105,7 @@ union ipbox {
 /* {{{ ftp_open
  */
 ftpbuf_t*
-ftp_open(const char *host, short port)
+ftp_open(const char *host, short port, long timeout_sec)
 {
        int                     fd = -1;
        ftpbuf_t                *ftp;
@@ -134,13 +135,16 @@ ftp_open(const char *host, short port)
                return NULL;
        }
 
+       /* Default Settings */
+       ftp->timeout_sec = timeout_sec;
+
        /* connect */
        if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
                perror("socket");
                goto bail;
        }
 
-       if (my_connect(fd, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
+       if (my_connect(ftp, fd, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
                perror("connect");
                goto bail;
        }
@@ -533,24 +537,30 @@ ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
        if (ftp == NULL)
                return 0;
 
-       if (!ftp_type(ftp, type))
+       if (!ftp_type(ftp, type)) {
                goto bail;
+       }
 
-       if ((data = ftp_getdata(ftp)) == NULL)
+       if ((data = ftp_getdata(ftp)) == NULL) {
                goto bail;
+       }
 
-       if (!ftp_putcmd(ftp, "RETR", path))
+       if (!ftp_putcmd(ftp, "RETR", path)) {
                goto bail;
-       if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125))
+       }
+       if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
                goto bail;
+       }
 
-       if ((data = data_accept(data)) == NULL)
+       if ((data = data_accept(data, ftp)) == NULL) {
                goto bail;
+       }
 
        lastch = 0;
-       while ((rcvd = my_recv(data->fd, data->buf, FTP_BUFSIZE))) {
-               if (rcvd == -1)
+       while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
+               if (rcvd == -1) {
                        goto bail;
+               }
 
                if (type == FTPTYPE_ASCII) {
                        for (ptr = data->buf; rcvd; rcvd--, ptr++) {
@@ -571,11 +581,13 @@ ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
 
        data = data_close(data);
 
-       if (ferror(outfp))
+       if (ferror(outfp)) {
                goto bail;
+       }
 
-       if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250))
+       if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
                goto bail;
+       }
 
        return 1;
 bail:
@@ -608,7 +620,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, f
        if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125))
                goto bail;
 
-       if ((data = data_accept(data)) == NULL)
+       if ((data = data_accept(data, ftp)) == NULL)
                goto bail;
 
        size = 0;
@@ -616,7 +628,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, f
        while ((ch = FP_FGETC(insocket, infp, issock))!=EOF && !FP_FEOF(insocket, infp, issock)) {
                /* flush if necessary */
                if (FTP_BUFSIZE - size < 2) {
-                       if (my_send(data->fd, data->buf, size) != size)
+                       if (my_send(ftp, data->fd, data->buf, size) != size)
                                goto bail;
                        ptr = data->buf;
                        size = 0;
@@ -631,7 +643,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, int insocket, int issock, f
                size++;
        }
 
-       if (size && my_send(data->fd, data->buf, size) != size)
+       if (size && my_send(ftp, data->fd, data->buf, size) != size)
                goto bail;
 
        if (!issock && ferror(infp))
@@ -792,7 +804,7 @@ ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args)
        }
 
        data = ftp->outbuf;
-       if (my_send(ftp->fd, data, size) != size)
+       if (my_send(ftp, ftp->fd, data, size) != size)
                return 0;
 
        return 1;
@@ -841,8 +853,9 @@ ftp_readline(ftpbuf_t *ftp)
                }
 
                data = eol;
-               if ((rcvd = my_recv(ftp->fd, data, size)) < 1)
+               if ((rcvd = my_recv(ftp, ftp->fd, data, size)) < 1) {
                        return 0;
+               }
        } while (size);
 
        return 0;
@@ -896,7 +909,7 @@ ftp_getresp(ftpbuf_t *ftp)
 /* {{{ my_send
  */
 int
-my_send(int s, void *buf, size_t len)
+my_send(ftpbuf_t *ftp, int s, void *buf, size_t len)
 {
        fd_set          write_set;
        struct timeval  tv;
@@ -904,7 +917,7 @@ my_send(int s, void *buf, size_t len)
 
        size = len;
        while (size) {
-               tv.tv_sec = FTP_TIMEOUT;
+               tv.tv_sec = ftp->timeout_sec;
                tv.tv_usec = 0;
 
                FD_ZERO(&write_set);
@@ -933,13 +946,13 @@ my_send(int s, void *buf, size_t len)
 /* {{{ my_recv
  */
 int
-my_recv(int s, void *buf, size_t len)
+my_recv(ftpbuf_t *ftp, int s, void *buf, size_t len)
 {
        fd_set          read_set;
        struct timeval  tv;
        int             n;
 
-       tv.tv_sec = FTP_TIMEOUT;
+       tv.tv_sec = ftp->timeout_sec;
        tv.tv_usec = 0;
 
        FD_ZERO(&read_set);
@@ -960,7 +973,7 @@ my_recv(int s, void *buf, size_t len)
 /* {{{ my_connect
  */
 int
-my_connect(int s, const struct sockaddr *addr, int addrlen)
+my_connect(ftpbuf_t *ftp, int s, const struct sockaddr *addr, int addrlen)
 #ifndef PHP_WIN32
 {
        fd_set          conn_set;
@@ -980,7 +993,7 @@ my_connect(int s, const struct sockaddr *addr, int addrlen)
                FD_ZERO(&conn_set);
                FD_SET(s, &conn_set);
 
-               tv.tv_sec = FTP_TIMEOUT;
+               tv.tv_sec = ftp->timeout_sec;
                tv.tv_usec = 0;
 
                n = select(s + 1, &conn_set, &conn_set, NULL, &tv);
@@ -1015,13 +1028,13 @@ my_connect(int s, const struct sockaddr *addr, int addrlen)
 /* {{{ my_accept
  */
 int
-my_accept(int s, struct sockaddr *addr, int *addrlen)
+my_accept(ftpbuf_t *ftp, int s, struct sockaddr *addr, int *addrlen)
 {
        fd_set          accept_set;
        struct timeval  tv;
        int             n;
 
-       tv.tv_sec = FTP_TIMEOUT;
+       tv.tv_sec = ftp->timeout_sec;
        tv.tv_usec = 0;
        FD_ZERO(&accept_set);
        FD_SET(s, &accept_set);
@@ -1078,7 +1091,7 @@ ftp_getdata(ftpbuf_t *ftp)
                ftp->pasv = 1;
 
                /* connect */
-               if (my_connect(fd, (struct sockaddr*) &ftp->pasvaddr,
+               if (my_connect(ftp, fd, (struct sockaddr*) &ftp->pasvaddr,
                        sizeof(ftp->pasvaddr)) == -1)
                {
                        perror("connect");
@@ -1144,7 +1157,7 @@ bail:
 /* {{{ data_accept
  */
 databuf_t*
-data_accept(databuf_t *data)
+data_accept(databuf_t *data, ftpbuf_t *ftp)
 {
        struct sockaddr_in      addr;
        int                     size;
@@ -1153,7 +1166,7 @@ data_accept(databuf_t *data)
                return data;
 
        size = sizeof(addr);
-       data->fd = my_accept(data->listener, (struct sockaddr*) &addr, &size);
+       data->fd = my_accept(ftp, data->listener, (struct sockaddr*) &addr, &size);
        closesocket(data->listener);
        data->listener = -1;
 
@@ -1213,13 +1226,13 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path)
                goto bail;
 
        /* pull data buffer into tmpfile */
-       if ((data = data_accept(data)) == NULL)
+       if ((data = data_accept(data, ftp)) == NULL)
                goto bail;
 
        size = 0;
        lines = 0;
        lastch = 0;
-       while ((rcvd = my_recv(data->fd, data->buf, FTP_BUFSIZE))) {
+       while ((rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE))) {
                if (rcvd == -1)
                        goto bail;
 
index 8cd6c2f7048fe383130e06ca543962ac98021a5d..9546e53c44fb59bf89d088f9fe8b253c0e2d2c8e 100644 (file)
 #include <netinet/in.h>
 #endif
 
-/* XXX these should be configurable at runtime XXX */
+#define        FTP_DEFAULT_TIMEOUT     90
+
+/* XXX this should be configurable at runtime XXX */
 #define        FTP_BUFSIZE     4096
-#define        FTP_TIMEOUT     90
 
 typedef enum ftptype {
        FTPTYPE_ASCII,
@@ -50,6 +51,7 @@ typedef struct ftpbuf
        ftptype_t       type;                   /* current transfer type */
        int             pasv;                   /* 0=off; 1=pasv; 2=ready */
        struct sockaddr_in      pasvaddr;       /* passive mode address */
+       long    timeout_sec;    /* User configureable timeout (seconds) */
 } ftpbuf_t;
 
 typedef struct databuf
@@ -64,7 +66,7 @@ typedef struct databuf
 /* open a FTP connection, returns ftpbuf (NULL on error)
  * port is the ftp port in network byte order, or 0 for the default
  */
-ftpbuf_t*      ftp_open(const char *host, short port);
+ftpbuf_t*      ftp_open(const char *host, short port, long timeout_sec);
 
 /* quits from the ftp session (it still needs to be closed)
  * return true on success, false on error
index c69c290142eff967ccbc19d36967a2599fe1c33d..80f8790f3871abaf34c898449df328d0255ed4e0 100644 (file)
@@ -58,6 +58,8 @@ function_entry php_ftp_functions[] = {
        PHP_FE(ftp_delete,                      NULL)
        PHP_FE(ftp_site,                        NULL)
        PHP_FE(ftp_close,                       NULL)
+       PHP_FE(ftp_set_option,          NULL)
+       PHP_FE(ftp_get_option,          NULL)
        PHP_FALIAS(ftp_quit, ftp_close, NULL)
        {NULL, NULL, NULL}
 };
@@ -88,15 +90,12 @@ static void ftp_destructor_ftpbuf(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 
 PHP_MINIT_FUNCTION(ftp)
 {
-       le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, "ftp", module_number);
-       REGISTER_LONG_CONSTANT("FTP_ASCII", FTPTYPE_ASCII,
-               CONST_PERSISTENT | CONST_CS);
-       REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE,
-               CONST_PERSISTENT | CONST_CS);
-       REGISTER_LONG_CONSTANT("FTP_IMAGE", FTPTYPE_IMAGE,
-               CONST_PERSISTENT | CONST_CS);
-       REGISTER_LONG_CONSTANT("FTP_TEXT", FTPTYPE_ASCII,
-               CONST_PERSISTENT | CONST_CS);
+       le_ftpbuf = zend_register_list_destructors_ex(ftp_destructor_ftpbuf, NULL, le_ftpbuf_name, module_number);
+       REGISTER_LONG_CONSTANT("FTP_ASCII",      FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
+       REGISTER_LONG_CONSTANT("FTP_TEXT",   FTPTYPE_ASCII, CONST_PERSISTENT | CONST_CS);
+       REGISTER_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
+       REGISTER_LONG_CONSTANT("FTP_IMAGE",  FTPTYPE_IMAGE, CONST_PERSISTENT | CONST_CS);
+       REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
        return SUCCESS;
 }
 
@@ -123,14 +122,21 @@ PHP_FUNCTION(ftp_connect)
 {
        ftpbuf_t        *ftp;
        char            *host;
-       int                     host_len, port = 21;
+       int                     host_len, port = 0;
+       long            timeout_sec = FTP_DEFAULT_TIMEOUT;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &host, &host_len, &port) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &host, &host_len, &port, &timeout_sec) == FAILURE) {
                return;
        }
 
+       if (timeout_sec <= 0) {
+               php_error(E_WARNING, "%s(): timeout has to be greater than 0",
+                                 get_active_function_name(TSRMLS_C));
+               RETURN_FALSE;
+       }
+
        /* connect */
-       ftp = ftp_open(host, htons((short)port));
+       ftp = ftp_open(host, htons((short)port), timeout_sec);
        if (ftp == NULL) {
                RETURN_FALSE;
        }
@@ -701,6 +707,103 @@ PHP_FUNCTION(ftp_close)
        zend_list_delete(Z_LVAL_P(z_ftp));
 }
 /* }}} */
+       
+/* Temporarely copied over from zend_API.c until it gets exposed */
+static char *ze_zval_type_name(zval *arg)
+{
+       switch (Z_TYPE_P(arg)) {
+               case IS_NULL:
+                       return "null";
+
+               case IS_LONG:
+                       return "integer";
+
+               case IS_DOUBLE:
+                       return "double";
+
+               case IS_STRING:
+                       return "string";
+
+               case IS_ARRAY:
+                       return "array";
+
+               case IS_OBJECT:
+                       return "object";
+
+               case IS_BOOL:
+                       return "boolean";
+
+               case IS_RESOURCE:
+                       return "resource";
+
+               default:
+                       return "unknown";
+       }
+}
+
+
+/* {{{ proto bool ftp_set_option(resource stream, int option, mixed value)
+   Sets an FTP option. */
+PHP_FUNCTION(ftp_set_option)
+{
+       zval    *z_ftp, *z_value;
+       long    option;
+       ftpbuf_t        *ftp;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &z_ftp, &option, &z_value) == FAILURE) {
+               return;
+       }
+
+       ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
+
+       switch (option) {
+               case PHP_FTP_OPT_TIMEOUT_SEC:
+                       if (Z_TYPE_P(z_value) != IS_LONG) {
+                               php_error(E_WARNING, "%s(): option TIMEOUT_SEC expects value of type long, %s given",
+                                                 get_active_function_name(TSRMLS_C), ze_zval_type_name(z_value));
+                               RETURN_FALSE;
+                       }
+                       if (Z_LVAL_P(z_value) <= 0) {
+                               php_error(E_WARNING, "%s(): timeout has to be greater than 0",
+                                                 get_active_function_name(TSRMLS_C));
+                               RETURN_FALSE;
+                       }
+                       ftp->timeout_sec = Z_LVAL_P(z_value);
+                       RETURN_TRUE;
+                       break;
+               default:
+                       php_error(E_WARNING, "%s(): unknown option '%d'", get_active_function_name(TSRMLS_C), option);
+                       RETURN_FALSE;
+                       break;
+       }
+}
+/* }}} */
+
+/* {{{ proto mixed ftp_get_option(resource stream, int option)
+   Gets an FTP option. */
+PHP_FUNCTION(ftp_get_option)
+{
+       zval    *z_ftp;
+       long    option;
+       ftpbuf_t        *ftp;
+       
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &z_ftp, &option) == FAILURE) {
+               return;
+       }
+
+       ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
+
+       switch (option) {
+               case PHP_FTP_OPT_TIMEOUT_SEC:
+                       RETURN_LONG(ftp->timeout_sec);
+                       break;
+               default:
+                       php_error(E_WARNING, "%s(): unknown option '%d'", get_active_function_name(TSRMLS_C), option);
+                       RETURN_FALSE;
+                       break;
+       }
+}
+/* }}} */
 
 #endif /* HAVE_FTP */
 
index 4d93a1ffe9979e15855949e93a3bd12c56bd210d..4172ed295ed8b52d0f0f404c9e95257b700984d0 100644 (file)
@@ -27,6 +27,8 @@
 extern zend_module_entry php_ftp_module_entry;
 #define php_ftp_module_ptr &php_ftp_module_entry
 
+#define PHP_FTP_OPT_TIMEOUT_SEC        0
+
 PHP_MINIT_FUNCTION(ftp);
 PHP_MINFO_FUNCTION(ftp);
 
@@ -52,6 +54,8 @@ PHP_FUNCTION(ftp_rename);
 PHP_FUNCTION(ftp_delete);
 PHP_FUNCTION(ftp_site);
 PHP_FUNCTION(ftp_close);
+PHP_FUNCTION(ftp_set_option);
+PHP_FUNCTION(ftp_get_option);
 
 #define phpext_ftp_ptr php_ftp_module_ptr