]> granicus.if.org Git - php/commitdiff
Added functions ftp_{pasv,size,mdtm,fget,fput}
authorAndrew Skalski <askalski@php.net>
Mon, 27 Sep 1999 14:07:09 +0000 (14:07 +0000)
committerAndrew Skalski <askalski@php.net>
Mon, 27 Sep 1999 14:07:09 +0000 (14:07 +0000)
PASV mode is now supported; file size and last-modified time can now
be fetched from servers that support them; files now may be stored to and
retrieved from open files, in addition to disk files.

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

index 4cd11238943a3814bbecaf88efb277f4a714c6f4..b83f34b8a6b9ffd025d62748dff08ef76860a64e 100644 (file)
 
 #if HAVE_FTP
 
+#include <stdio.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
@@ -48,8 +51,8 @@ static int            ftp_getresp(ftpbuf_t *ftp);
 /* sets the ftp transfer type */
 static int             ftp_type(ftpbuf_t *ftp, ftptype_t type);
 
-/* opens up a port for ftp transfer */
-static databuf_t*      ftp_port(ftpbuf_t *ftp);
+/* opens up a data stream */
+static databuf_t*      ftp_getdata(ftpbuf_t *ftp);
 
 /* accepts the data connection, returns updated data buffer */
 static databuf_t*      data_accept(databuf_t *data);
@@ -61,6 +64,13 @@ static databuf_t*    data_close(databuf_t *data);
 static char**          ftp_genlist(ftpbuf_t *ftp,
                                const char *cmd, const char *path);
 
+/* IP and port conversion box */
+union ipbox {
+       unsigned long   l[2];
+       unsigned short  s[4];
+       unsigned char   c[8];
+};
+
 
 ftpbuf_t*
 ftp_open(const char *host, short port)
@@ -427,6 +437,49 @@ ftp_type(ftpbuf_t *ftp, ftptype_t type)
 }
 
 
+int
+ftp_pasv(ftpbuf_t *ftp, int pasv)
+{
+       char                    *ptr;
+       union ipbox             ipbox;
+       unsigned long           b[6];
+       int                     n;
+
+       if (ftp == NULL)
+               return 0;
+
+       if (pasv && ftp->pasv == 2)
+               return 1;
+
+       ftp->pasv = 0;
+       if (!pasv)
+               return 1;
+
+       fprintf(ftp->fp, "PASV\r\n");
+       if (!ftp_getresp(ftp) || ftp->resp != 227)
+               return 0;
+
+       /* parse out the IP and port */
+       for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
+       n = sscanf(ptr, "%u,%u,%u,%u,%u,%u",
+               &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]);
+       if (n != 6)
+               return 0;
+
+       for (n=0; n<6; n++)
+               ipbox.c[n] = b[n];
+
+       memset(&ftp->pasvaddr, 0, sizeof(ftp->pasvaddr));
+       ftp->pasvaddr.sin_family = AF_INET;
+       ftp->pasvaddr.sin_addr.s_addr = ipbox.l[0];
+       ftp->pasvaddr.sin_port = ipbox.s[2];
+
+       ftp->pasv = 2;
+
+       return 1;
+}
+
+
 int
 ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
 {
@@ -439,7 +492,7 @@ ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type)
        if (!ftp_type(ftp, type))
                goto bail;
 
-       if ((data = ftp_port(ftp)) == NULL)
+       if ((data = ftp_getdata(ftp)) == NULL)
                goto bail;
 
        fprintf(ftp->fp, "RETR %s\r\n", path);
@@ -492,7 +545,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, ftptype_t type)
        if (!ftp_type(ftp, type))
                goto bail;
 
-       if ((data = ftp_port(ftp)) == NULL)
+       if ((data = ftp_getdata(ftp)) == NULL)
                goto bail;
 
        fprintf(ftp->fp, "STOR %s\r\n", path);
@@ -523,18 +576,77 @@ bail:
 }
 
 
+int
+ftp_size(ftpbuf_t *ftp, const char *path)
+{
+       if (ftp == NULL)
+               return -1;
+
+       fprintf(ftp->fp, "SIZE %s\r\n", path);
+       if (!ftp_getresp(ftp) || ftp->resp != 213)
+               return -1;
+
+       return atoi(ftp->inbuf);
+}
+
+
+time_t
+ftp_mdtm(ftpbuf_t *ftp, const char *path)
+{
+       time_t          stamp;
+       struct tm       *gmt;
+       struct tm       tm;
+       char            *ptr;
+       int             n;
+
+       if (ftp == NULL)
+               return -1;
+
+       fprintf(ftp->fp, "MDTM %s\r\n", path);
+       if (!ftp_getresp(ftp) || ftp->resp != 213)
+               return -1;
+
+       /* parse out the timestamp */
+       for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++);
+       n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u",
+               &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+               &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+       if (n != 6)
+               return -1;
+       tm.tm_year -= 1900;
+       tm.tm_mon--;
+       tm.tm_isdst = -1;
+
+       /* figure out the GMT offset */
+       stamp = time(NULL);
+       gmt = gmtime(&stamp);
+       gmt->tm_isdst = -1;
+
+       /* apply the GMT offset */
+       tm.tm_sec += stamp - mktime(gmt);
+       tm.tm_isdst = gmt->tm_isdst;
+
+       stamp = mktime(&tm);
+
+       return stamp;
+}
+
+
+/* static functions */
+
 databuf_t*
-ftp_port(ftpbuf_t *ftp)
+ftp_getdata(ftpbuf_t *ftp)
 {
        int                     fd = -1;
        databuf_t               *data;
        struct sockaddr_in      addr;
        int                     size;
-       union {
-               unsigned long   l[1];
-               unsigned short  s[2];
-               unsigned char   c[4];
-       }                       ipbox;
+       union ipbox             ipbox;
+
+
+       /* ask for a passive connection if we need one */
+       if (ftp->pasv && !ftp_pasv(ftp, 1))
+               return NULL;
 
        /* alloc the data structure */
        data = calloc(1, sizeof(*data));
@@ -551,6 +663,36 @@ ftp_port(ftpbuf_t *ftp)
                goto bail;
        }
 
+       /* passive connection handler */
+       if (ftp->pasv) {
+               /* clear the ready status */
+               ftp->pasv = 1;
+
+               /* connect */
+               if (connect(fd, (struct sockaddr*) &ftp->pasvaddr,
+                       sizeof(ftp->pasvaddr)) == -1)
+               {
+                       perror("connect");
+                       close(fd);
+                       free(data);
+                       return NULL;
+               }
+
+               /* wrap fd in a FILE stream */
+               data->fp = fdopen(fd, "r+");
+               if (data->fp == NULL) {
+                       perror("fdopen");
+                       close(fd);
+                       free(data);
+                       return NULL;
+               }
+
+               return data;
+       }
+
+
+       /* active (normal) connection */
+
        /* bind to a local address */
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
@@ -577,11 +719,10 @@ ftp_port(ftpbuf_t *ftp)
 
        /* send the PORT */
        ipbox.l[0] = ftp->localaddr.s_addr;
-       fprintf(ftp->fp, "PORT %u,%u,%u,%u,",
-               ipbox.c[0], ipbox.c[1], ipbox.c[2], ipbox.c[3]);
-       ipbox.s[0] = addr.sin_port;
-       fprintf(ftp->fp, "%u,%u\r\n",
-               ipbox.c[0], ipbox.c[1]);
+       ipbox.s[2] = addr.sin_port;
+       fprintf(ftp->fp, "PORT %u,%u,%u,%u,%u,%u\r\n",
+               ipbox.c[0], ipbox.c[1], ipbox.c[2], ipbox.c[3],
+               ipbox.c[4], ipbox.c[5]);
 
        if (!ftp_getresp(ftp) || ftp->resp != 200)
                goto bail;
@@ -603,6 +744,10 @@ data_accept(databuf_t *data)
        int                     size;
        int                     fd;
 
+
+       if (data->fp)
+               return data;
+
        size = sizeof(addr);
        fd = accept(data->listener, (struct sockaddr*) &addr, &size);
        close(data->listener);
@@ -656,7 +801,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path)
        if (!ftp_type(ftp, FTPTYPE_ASCII))
                goto bail;
 
-       if ((data = ftp_port(ftp)) == NULL)
+       if ((data = ftp_getdata(ftp)) == NULL)
                goto bail;
 
        if (path)
index 800a9a197f526fbacc960112473340e193ff08a8..ddfe9aa1182ab64a333b1813a6a22a5dac89e465 100644 (file)
@@ -53,6 +53,8 @@ typedef struct ftpbuf
        char            *pwd;                   /* cached pwd */
        char            *syst;                  /* cached system type */
        ftptype_t       type;                   /* current transfer type */
+       int             pasv;                   /* 0=off; 1=pasv; 2=ready */
+       struct sockaddr_in      pasvaddr;       /* passive mode address */
 } ftpbuf_t;
 
 typedef struct databuf
@@ -118,6 +120,11 @@ char**             ftp_nlist(ftpbuf_t *ftp, const char *path);
  */
 char**         ftp_list(ftpbuf_t *ftp, const char *path);
 
+/* switches passive mode on or off
+ * returns true on success, false on error
+ */
+int            ftp_pasv(ftpbuf_t *ftp, int pasv);
+
 /* retrieves a file and saves its contents to outfp
  * returns true on success, false on error
  */
@@ -130,4 +137,10 @@ int                ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path,
 int            ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp,
                        ftptype_t type);
 
+/* returns the size of the given file, or -1 on error */
+int            ftp_size(ftpbuf_t *ftp, const char *path);
+
+/* returns the last modified time  of the given file, or -1 on error */
+time_t         ftp_mdtm(ftpbuf_t *ftp, const char *path);
+
 #endif
index 8e641fa54977368c2812fa356027cf8d3c477956..2307b0aa9c915f21340ad0e75516669d550d8695 100644 (file)
@@ -57,8 +57,13 @@ function_entry php3_ftp_functions[] = {
        PHP_FE(ftp_nlist,                       NULL)
        PHP_FE(ftp_rawlist,                     NULL)
        PHP_FE(ftp_systype,                     NULL)
+       PHP_FE(ftp_pasv,                        NULL)
        PHP_FE(ftp_get,                         NULL)
+       PHP_FE(ftp_fget,                        NULL)
        PHP_FE(ftp_put,                         NULL)
+       PHP_FE(ftp_fput,                        NULL)
+       PHP_FE(ftp_size,                        NULL)
+       PHP_FE(ftp_mdtm,                        NULL)
        PHP_FE(ftp_quit,                        NULL)
        {NULL, NULL, NULL}
 };
@@ -101,12 +106,47 @@ PHP_MINIT_FUNCTION(ftp)
        return SUCCESS;
 }
 
+
+#define        FTPBUF(ftp, pval) { \
+       int     id, type; \
+       convert_to_long(pval); \
+       id = (pval)->value.lval; \
+       (ftp) = php3_list_find(id, &type); \
+       if (!(ftp) || type != le_ftpbuf) { \
+               php_error(E_WARNING, "Unable to find ftpbuf %d", id); \
+               RETURN_FALSE; \
+       } \
+       }
+
+#define        XTYPE(xtype, pval) { \
+       convert_to_long(pval); \
+       if (    pval->value.lval != FTPTYPE_ASCII && \
+               pval->value.lval != FTPTYPE_IMAGE) \
+       { \
+               php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_IMAGE"); \
+               RETURN_FALSE; \
+       } \
+       (xtype) = pval->value.lval; \
+       }
+
+#define        FILEP(fp, pval) { \
+       int     id, type; \
+       int     le_fp; \
+       le_fp = php3i_get_le_fp(); \
+       convert_to_long(pval); \
+       id = (pval)->value.lval; \
+       (fp) = php3_list_find(id, &type); \
+       if (!(fp) || type != le_fp) { \
+               php_error(E_WARNING, "Unable to find fp %d", id); \
+               RETURN_FALSE; \
+       } \
+       }
+
 /* {{{ proto int ftp_connect(string host [, int port])
    Open a FTP stream */
 PHP_FUNCTION(ftp_connect)
 {
        pval            *arg1, *arg2;
-       int             id;
        ftpbuf_t        *ftp;
        short           port = 0;
 
@@ -137,8 +177,7 @@ PHP_FUNCTION(ftp_connect)
        if (ftp == NULL)
                RETURN_FALSE;
 
-       id = php3_list_insert(ftp, le_ftpbuf);
-       RETURN_LONG(id);
+       RETURN_LONG(php3_list_insert(ftp, le_ftpbuf));
 }
 /* }}} */
 
@@ -147,7 +186,6 @@ PHP_FUNCTION(ftp_connect)
 PHP_FUNCTION(ftp_login)
 {
        pval            *arg1, *arg2, *arg3;
-       int             id, type;
        ftpbuf_t        *ftp;
 
        /* arg1 - ftp
@@ -160,16 +198,10 @@ PHP_FUNCTION(ftp_login)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
        convert_to_string(arg3);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* log in */
        if (!ftp_login(ftp, arg2->value.str.val, arg3->value.str.val)) {
@@ -186,7 +218,6 @@ PHP_FUNCTION(ftp_login)
 PHP_FUNCTION(ftp_pwd)
 {
        pval            *arg1;
-       int             id, type;
        ftpbuf_t        *ftp;
        const char      *pwd;
 
@@ -196,14 +227,7 @@ PHP_FUNCTION(ftp_pwd)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
-
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        pwd = ftp_pwd(ftp);
        if (pwd == NULL) {
@@ -220,7 +244,6 @@ PHP_FUNCTION(ftp_pwd)
 PHP_FUNCTION(ftp_cdup)
 {
        pval            *arg1;
-       int             id, type;
        ftpbuf_t        *ftp;
 
        /* arg1 - ftp
@@ -229,14 +252,7 @@ PHP_FUNCTION(ftp_cdup)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
-
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        if (!ftp_cdup(ftp)) {
                php_error(E_WARNING, "ftp_cdup: %s", ftp->inbuf);
@@ -252,7 +268,6 @@ PHP_FUNCTION(ftp_cdup)
 PHP_FUNCTION(ftp_chdir)
 {
        pval            *arg1, *arg2;
-       int             id, type;
        ftpbuf_t        *ftp;
 
        /* arg1 - ftp
@@ -264,15 +279,9 @@ PHP_FUNCTION(ftp_chdir)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* change directories */
        if (!ftp_chdir(ftp, arg2->value.str.val)) {
@@ -289,7 +298,6 @@ PHP_FUNCTION(ftp_chdir)
 PHP_FUNCTION(ftp_mkdir)
 {
        pval            *arg1, *arg2;
-       int             id, type;
        ftpbuf_t        *ftp;
        char            *ret, *tmp;
 
@@ -302,15 +310,9 @@ PHP_FUNCTION(ftp_mkdir)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* change directories */
        tmp = ftp_mkdir(ftp, arg2->value.str.val);
@@ -334,7 +336,6 @@ PHP_FUNCTION(ftp_mkdir)
 PHP_FUNCTION(ftp_rmdir)
 {
        pval            *arg1, *arg2;
-       int             id, type;
        ftpbuf_t        *ftp;
 
        /* arg1 - ftp
@@ -346,15 +347,9 @@ PHP_FUNCTION(ftp_rmdir)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* change directories */
        if (!ftp_rmdir(ftp, arg2->value.str.val)) {
@@ -371,7 +366,6 @@ PHP_FUNCTION(ftp_rmdir)
 PHP_FUNCTION(ftp_nlist)
 {
        pval            *arg1, *arg2;
-       int             id, type;
        ftpbuf_t        *ftp;
        char            **nlist, **ptr;
 
@@ -384,15 +378,9 @@ PHP_FUNCTION(ftp_nlist)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* get list of files */
        nlist = ftp_nlist(ftp, arg2->value.str.val);
@@ -412,7 +400,6 @@ PHP_FUNCTION(ftp_nlist)
 PHP_FUNCTION(ftp_rawlist)
 {
        pval            *arg1, *arg2;
-       int             id, type;
        ftpbuf_t        *ftp;
        char            **llist, **ptr;
 
@@ -425,15 +412,9 @@ PHP_FUNCTION(ftp_rawlist)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        convert_to_string(arg2);
 
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        /* get directory listing */
        llist = ftp_list(ftp, arg2->value.str.val);
@@ -453,7 +434,6 @@ PHP_FUNCTION(ftp_rawlist)
 PHP_FUNCTION(ftp_systype)
 {
        pval            *arg1;
-       int             id, type;
        ftpbuf_t        *ftp;
        const char      *syst;
 
@@ -465,14 +445,7 @@ PHP_FUNCTION(ftp_systype)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
-
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
+       FTPBUF(ftp, arg1);
 
        syst = ftp_syst(ftp);
        if (syst == NULL) {
@@ -484,12 +457,76 @@ PHP_FUNCTION(ftp_systype)
 }
 /* }}} */
 
+/* {{{ proto int ftp_fget(int stream, int fp, string remote_file, int mode)
+   Retrieves a file from the FTP server and writes it to an open file. */
+PHP_FUNCTION(ftp_fget)
+{
+       pval            *arg1, *arg2, *arg3, *arg4;
+       ftpbuf_t        *ftp;
+       ftptype_t       xtype;
+       FILE            *fp;
+
+       /* arg1 - ftp
+        * arg2 - fp
+        * arg3 - remote file
+        * arg4 - transfer mode
+        */
+       if (    ARG_COUNT(ht) != 4 ||
+               getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE)
+       {
+                       WRONG_PARAM_COUNT;
+       }
+
+       FTPBUF(ftp, arg1);
+       FILEP(fp, arg2);
+       convert_to_string(arg3);
+       XTYPE(xtype, arg4);
+
+       if (!ftp_get(ftp, fp, arg3->value.str.val, xtype) || ferror(fp)) {
+               php_error(E_WARNING, "ftp_get: %s", ftp->inbuf);
+               RETURN_FALSE;
+       }
+
+       if (ferror(fp)) {
+               php_error(E_WARNING, "error writing %s", arg2->value.str.val);
+               RETURN_FALSE;
+       }
+
+       RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int ftp_pasv(int stream, int pasv)
+   Turns passive mode on or off. */
+PHP_FUNCTION(ftp_pasv)
+{
+       pval            *arg1, *arg2;
+       ftpbuf_t        *ftp;
+
+       /* arg1 - ftp
+        * arg2 - pasv
+        */
+       if (    ARG_COUNT(ht) != 2 ||
+               getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       FTPBUF(ftp, arg1);
+       convert_to_long(arg2);
+
+       if (!ftp_pasv(ftp, (arg2->value.lval) ? 1 : 0))
+               RETURN_FALSE;
+
+       RETURN_TRUE;
+}
+/* }}} */
+
 /* {{{ proto int ftp_get(int stream, string local_file, string remote_file, int mode)
-   Retrieves a file from the FTP server. */
+   Retrieves a file from the FTP server and writes it to a local file. */
 PHP_FUNCTION(ftp_get)
 {
        pval            *arg1, *arg2, *arg3, *arg4;
-       int             id, type;
        ftpbuf_t        *ftp;
        ftptype_t       xtype;
        FILE            *outfp, *tmpfp;
@@ -507,26 +544,10 @@ PHP_FUNCTION(ftp_get)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
+       FTPBUF(ftp, arg1);
        convert_to_string(arg2);
        convert_to_string(arg3);
-       convert_to_long(arg4);
-
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
-
-       if (    arg4->value.lval != FTPTYPE_ASCII &&
-               arg4->value.lval != FTPTYPE_IMAGE)
-       {
-               php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_IMAGE");
-               RETURN_FALSE;
-       }
-
-       xtype = arg4->value.lval;
+       XTYPE(xtype, arg4);
 
        /* get to temporary file, so if there is an error, no existing
         * file gets clobbered
@@ -568,12 +589,45 @@ PHP_FUNCTION(ftp_get)
 }
 /* }}} */
 
+/* {{{ proto int ftp_fput(int stream, string local_file, string remote_file, int mode)
+   Stores a file from an open file to the FTP server. */
+PHP_FUNCTION(ftp_fput)
+{
+       pval            *arg1, *arg2, *arg3, *arg4;
+       ftpbuf_t        *ftp;
+       ftptype_t       xtype;
+       FILE            *fp;
+
+       /* arg1 - ftp
+        * arg2 - remote file
+        * arg3 - fp
+        * arg4 - transfer mode
+        */
+       if (    ARG_COUNT(ht) != 4 ||
+               getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       FTPBUF(ftp, arg1);
+       convert_to_string(arg2);
+       FILEP(fp, arg3);
+       XTYPE(xtype, arg4);
+
+       if (!ftp_put(ftp, arg2->value.str.val, fp, xtype)) {
+               php_error(E_WARNING, "ftp_put: %s", ftp->inbuf);
+               RETURN_FALSE;
+       }
+
+       RETURN_TRUE;
+}
+/* }}} */
+
 /* {{{ proto int ftp_put(int stream, string remote_file, string local_file, int mode)
    Stores a file on the FTP server */
 PHP_FUNCTION(ftp_put)
 {
        pval            *arg1, *arg2, *arg3, *arg4;
-       int             id, type;
        ftpbuf_t        *ftp;
        ftptype_t       xtype;
        FILE            *infp;
@@ -590,26 +644,10 @@ PHP_FUNCTION(ftp_put)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
+       FTPBUF(ftp, arg1);
        convert_to_string(arg2);
        convert_to_string(arg3);
-       convert_to_long(arg4);
-
-       id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
-
-       if (    arg4->value.lval != FTPTYPE_ASCII &&
-               arg4->value.lval != FTPTYPE_IMAGE)
-       {
-               php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_IMAGE");
-               RETURN_FALSE;
-       }
-
-       xtype = arg4->value.lval;
+       XTYPE(xtype, arg4);
 
        if ((infp = fopen(arg3->value.str.val, "r")) == NULL) {
                php_error(E_WARNING, "error opening %s", arg3->value.str.val);
@@ -628,13 +666,60 @@ PHP_FUNCTION(ftp_put)
 }
 /* }}} */
 
+/* {{{ proto int ftp_size(int stream, string path)
+   Returns the size of the file, or -1 on error. */
+PHP_FUNCTION(ftp_size)
+{
+       pval            *arg1, *arg2;
+       ftpbuf_t        *ftp;
+
+       /* arg1 - ftp
+        * arg2 - path
+        */
+       if (    ARG_COUNT(ht) != 2 ||
+               getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       FTPBUF(ftp, arg1);
+       convert_to_string(arg2);
+
+       /* get file size */
+       RETURN_LONG(ftp_size(ftp, arg2->value.str.val));
+}
+/* }}} */
+
+/* {{{ proto int ftp_mdtm(int stream, string path)
+   Returns the last modification time of the file, or -1 on error */
+PHP_FUNCTION(ftp_mdtm)
+{
+       pval            *arg1, *arg2;
+       ftpbuf_t        *ftp;
+
+       /* arg1 - ftp
+        * arg2 - path
+        */
+       if (    ARG_COUNT(ht) != 2 ||
+               getParameters(ht, 2, &arg1, &arg2) == FAILURE)
+       {
+               WRONG_PARAM_COUNT;
+       }
+
+       FTPBUF(ftp, arg1);
+       convert_to_string(arg2);
+
+       /* get file mod time */
+       RETURN_LONG(ftp_mdtm(ftp, arg2->value.str.val));
+}
+/* }}} */
+
 /* {{{ proto int ftp_quit(int stream)
    Closes the FTP stream */
 PHP_FUNCTION(ftp_quit)
 {
        pval            *arg1;
        int             id, type;
-       ftpbuf_t        *ftp;
 
        /* arg1 - ftp
         */
@@ -642,15 +727,9 @@ PHP_FUNCTION(ftp_quit)
                WRONG_PARAM_COUNT;
        }
 
-       convert_to_long(arg1);
        id = arg1->value.lval;
-       ftp = php3_list_find(id, &type);
-       if (!ftp || type != le_ftpbuf) {
-               php_error(E_WARNING, "Unable to find ftpbuf %d", id);
-               RETURN_FALSE;
-       }
-
-       php3_list_delete(id);
+       if (php3_list_find(id, &type) && type == le_ftpbuf)
+               php3_list_delete(id);
 
        RETURN_TRUE;
 }
index 05173d5909bb27e210d39346debd90049026fa8f..1515b79725dc53b6df0a344d2dae6bb57e4a00b1 100644 (file)
@@ -59,8 +59,13 @@ PHP_FUNCTION(ftp_rmdir);
 PHP_FUNCTION(ftp_nlist);
 PHP_FUNCTION(ftp_rawlist);
 PHP_FUNCTION(ftp_systype);
+PHP_FUNCTION(ftp_pasv);
 PHP_FUNCTION(ftp_get);
+PHP_FUNCTION(ftp_fget);
 PHP_FUNCTION(ftp_put);
+PHP_FUNCTION(ftp_fput);
+PHP_FUNCTION(ftp_size);
+PHP_FUNCTION(ftp_mdtm);
 PHP_FUNCTION(ftp_quit);
 
 #define phpext_ftp_ptr php3_ftp_module_ptr