]> granicus.if.org Git - php/commitdiff
@- FTP extension does support (auto)resuming now.
authorStefan Esser <sesser@php.net>
Fri, 26 Jul 2002 13:03:08 +0000 (13:03 +0000)
committerStefan Esser <sesser@php.net>
Fri, 26 Jul 2002 13:03:08 +0000 (13:03 +0000)
Added (Auto)Resuming functionality to ftp_(f)get/(f)put via optional 5th parameter.

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

index fdaf681c21cf9cc079d6d2d471d65579ff1ccd11..d2f1c256aaee40c0d42246747f64e10fc9c2a97a 100644 (file)
@@ -1,2 +1,3 @@
 FTP
 Andrew Skalski
+Stefan Esser
\ No newline at end of file
index ff5e775644af719bf0be94b1df88ce7177ca1c37..3effa5fcc486426c94a73d1e1865911d57462d60 100644 (file)
@@ -12,7 +12,8 @@
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Author: Andrew Skalski <askalski@chek.com>                           |
+   | Authors: Andrew Skalski <askalski@chek.com>                          |
+   |          Stefan Esser <sesser@php.net> (resume functions)            |
    +----------------------------------------------------------------------+
  */
 
@@ -114,7 +115,7 @@ ftp_open(const char *host, short port, long timeout_sec)
                perror("calloc");
                return NULL;
        }
-       
+
        tv.tv_sec = timeout_sec;
        tv.tv_usec = 0;
 
@@ -545,12 +546,13 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
 /* {{{ ftp_get
  */
 int
-ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type)
+ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos)
 {
        databuf_t               *data = NULL;
        char                    *ptr;
        int                     lastch;
        int                     rcvd;
+       char                    arg[11];
        TSRMLS_FETCH();
 
        if (ftp == NULL)
@@ -564,6 +566,16 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type)
                goto bail;
        }
 
+       if (resumepos>0) {
+               sprintf(arg, "%u", resumepos);
+               if (!ftp_putcmd(ftp, "REST", arg)) {
+                       goto bail;
+               }
+               if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
+                       goto bail;
+               }
+       }
+
        if (!ftp_putcmd(ftp, "RETR", path)) {
                goto bail;
        }
@@ -618,12 +630,13 @@ bail:
 /* {{{ ftp_put
  */
 int
-ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type)
+ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos)
 {
        databuf_t               *data = NULL;
        int                     size;
        char                    *ptr;
        int                     ch;
+       char                    arg[11];
        TSRMLS_FETCH();
 
        if (ftp == NULL)
@@ -635,6 +648,16 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type)
        if ((data = ftp_getdata(ftp)) == NULL)
                goto bail;
 
+       if (startpos>0) {
+               sprintf(arg, "%u", startpos);
+               if (!ftp_putcmd(ftp, "REST", arg)) {
+                       goto bail;
+               }
+               if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
+                       goto bail;
+               }
+       }
+
        if (!ftp_putcmd(ftp, "STOR", path))
                goto bail;
        if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125))
@@ -902,9 +925,9 @@ ftp_getresp(ftpbuf_t *ftp)
                }
 
                /* Break out when the end-tag is found */
-               if (isdigit(ftp->inbuf[0]) && 
-                       isdigit(ftp->inbuf[1]) && 
-                       isdigit(ftp->inbuf[2]) && 
+               if (isdigit(ftp->inbuf[0]) &&
+                       isdigit(ftp->inbuf[1]) &&
+                       isdigit(ftp->inbuf[2]) &&
                        ftp->inbuf[3] == ' ') {
                        break;
                }
index f980a8c757d65c05a739c555d2d6fb3ee68d779f..0dfb304810f77e741f01f16471015a9a9fc5954b 100644 (file)
@@ -13,6 +13,7 @@
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
    | Authors: Andrew Skalski <askalski@chek.com>                          |
+   |          Stefan Esser <sesser@php.net> (resume functions)            |
    +----------------------------------------------------------------------+
  */
 
@@ -29,6 +30,7 @@
 #endif
 
 #define        FTP_DEFAULT_TIMEOUT     90
+#define FTP_DEFAULT_AUTOSEEK 1
 
 /* XXX this should be configurable at runtime XXX */
 #define        FTP_BUFSIZE     4096
@@ -53,6 +55,7 @@ typedef struct ftpbuf
        int             pasv;                   /* 0=off; 1=pasv; 2=ready */
        php_sockaddr_storage    pasvaddr;       /* passive mode address */
        long    timeout_sec;    /* User configureable timeout (seconds) */
+       int                     autoseek;       /* User configureable autoseek flag */
 } ftpbuf_t;
 
 typedef struct databuf
@@ -131,12 +134,12 @@ int               ftp_pasv(ftpbuf_t *ftp, int pasv);
  * returns true on success, false on error
  */
 int            ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path,
-                       ftptype_t type);
+                       ftptype_t type, int resumepos);
 
 /* stores the data from a file, socket, or process as a file on the remote server
  * returns true on success, false on error
  */
-int            ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type);
+int            ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos);
 
 /* returns the size of the given file, or -1 on error */
 int            ftp_size(ftpbuf_t *ftp, const char *path);
index bbad02e88d45d468ac8fee3712bded4ad04aa7e5..1abe545231b838c0dd99365c39dde8d79e1e7609 100644 (file)
@@ -13,6 +13,7 @@
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
    | Authors: Andrew Skalski <askalski@chek.com>                          |
+   |          Stefan Esser <sesser@php.net> (resume functions)            |
    +----------------------------------------------------------------------+
  */
 
@@ -95,7 +96,9 @@ PHP_MINIT_FUNCTION(ftp)
        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_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS);
        REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
+       REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS);
        return SUCCESS;
 }
 
@@ -140,6 +143,9 @@ PHP_FUNCTION(ftp_connect)
                RETURN_FALSE;
        }
 
+       /* autoseek for resuming */
+       ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
+
        ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf);
 }
 /* }}} */
@@ -252,7 +258,7 @@ PHP_FUNCTION(ftp_exec)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &z_ftp, &cmd, &cmd_len) == FAILURE) {
                return;
        }
-       
+
        ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
 
        /* execute serverside command */
@@ -394,7 +400,7 @@ PHP_FUNCTION(ftp_systype)
 }
 /* }}} */
 
-/* {{{ proto bool ftp_fget(resource stream, resource fp, string remote_file, int mode)
+/* {{{ proto bool ftp_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos])
    Retrieves a file from the FTP server and writes it to an open file */
 PHP_FUNCTION(ftp_fget)
 {
@@ -403,9 +409,9 @@ PHP_FUNCTION(ftp_fget)
        ftptype_t       xtype;
        php_stream      *stream;
        char            *file;
-       int                     file_len, mode;
+       int                     file_len, mode, resumepos=0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl", &z_ftp, &z_file, &file, &file_len, &mode) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) {
                return;
        }
 
@@ -413,7 +419,22 @@ PHP_FUNCTION(ftp_fget)
        ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
        XTYPE(xtype, mode);
 
-       if (!ftp_get(ftp, stream, file, xtype) || php_stream_error(stream)) {
+       /* ignore autoresume if autoseek is switched off */
+       if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
+               resumepos = 0;
+       }
+
+       if (ftp->autoseek && resumepos) {
+               /* if autoresume is wanted seek to end */
+               if (resumepos == PHP_FTP_AUTORESUME) {
+                       php_stream_seek(stream, 0, SEEK_END);
+                       resumepos = php_stream_tell(stream);
+               } else {
+                       php_stream_seek(stream, resumepos, SEEK_SET);
+               }
+       }
+
+       if (!ftp_get(ftp, stream, file, xtype, resumepos) || php_stream_error(stream)) {
                php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
                RETURN_FALSE;
        }
@@ -449,71 +470,74 @@ PHP_FUNCTION(ftp_pasv)
 }
 /* }}} */
 
-/* {{{ proto bool ftp_get(resource stream, string local_file, string remote_file, int mode)
+/* {{{ proto bool ftp_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos])
    Retrieves a file from the FTP server and writes it to a local file */
 PHP_FUNCTION(ftp_get)
 {
        zval            *z_ftp;
        ftpbuf_t        *ftp;
        ftptype_t       xtype;
-       php_stream * tmpstream, *outstream;
+       php_stream      *outstream;
        char            *local, *remote;
-       int                     local_len, remote_len, mode;
+       int                     local_len, remote_len, mode, resumepos=0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl", &z_ftp, &local, &local_len, &remote, &remote_len, &mode) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
                return;
        }
-       
+
        ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
        XTYPE(xtype, mode);
 
-       /* get to temporary file, so if there is an error, no existing
-        * file gets clobbered
-        */
-       tmpstream = php_stream_fopen_tmpfile();
-       if (tmpstream == NULL) {
-               RETURN_FALSE;
-       }
-
-       if (!ftp_get(ftp, tmpstream, remote, xtype) || php_stream_error(tmpstream)) {
-               php_stream_close(tmpstream);
-               php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
-               RETURN_FALSE;
+       /* ignore autoresume if autoseek is switched off */
+       if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
+               resumepos = 0;
+       }
+
+       if (ftp->autoseek && resumepos) {
+               outstream = php_stream_fopen(local, "rb+", NULL);
+               if (outstream == NULL) {
+                       outstream = php_stream_fopen(local, "wb", NULL);
+               }
+               if (outstream != NULL) {
+                       /* if autoresume is wanted seek to end */
+                       if (resumepos == PHP_FTP_AUTORESUME) {
+                               php_stream_seek(outstream, 0, SEEK_END);
+                               resumepos = php_stream_tell(outstream);
+                       } else {
+                               php_stream_seek(outstream, resumepos, SEEK_SET);
+                       }
+               }
+       } else {
+               outstream = php_stream_fopen(local, "wb", NULL);
        }
 
-       outstream = php_stream_fopen(local, "wb", NULL);
-
        if (outstream == NULL)  {
-               php_stream_close(tmpstream);
                php_error(E_WARNING, "%s(): Error opening %s", get_active_function_name(TSRMLS_C), local);
                RETURN_FALSE;
        }
 
-       php_stream_rewind(tmpstream);
-       if (php_stream_copy_to_stream(tmpstream, outstream, PHP_STREAM_COPY_ALL) == 0)  {       
-               php_error(E_WARNING, "%s(): Error writing %s", get_active_function_name(TSRMLS_C), local);
-               RETVAL_FALSE;
+       if (!ftp_get(ftp, outstream, remote, xtype, resumepos) || php_stream_error(tmpstream)) {
+               php_stream_close(outstream);
+               php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
+               RETURN_FALSE;
        }
-       else
-               RETVAL_TRUE;
 
-       php_stream_close(tmpstream);
        php_stream_close(outstream);
 }
 /* }}} */
 
-/* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp, int mode)
+/* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp, int mode[, int startpos])
    Stores a file from an open file to the FTP server */
 PHP_FUNCTION(ftp_fput)
 {
        zval            *z_ftp, *z_file;
        ftpbuf_t        *ftp;
        ftptype_t       xtype;
-       int                     mode, remote_len;
+       int                     mode, remote_len, startpos=0;
        php_stream      *stream;
        char            *remote;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl", &z_ftp, &remote, &remote_len, &z_file, &mode) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
                return;
        }
 
@@ -521,7 +545,25 @@ PHP_FUNCTION(ftp_fput)
        ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
        XTYPE(xtype, mode);
 
-       if (!ftp_put(ftp, remote, stream, xtype)) {
+       /* ignore autoresume if autoseek is switched off */
+       if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
+               startpos = 0;
+       }
+
+       if (ftp->autoseek && startpos) {
+               /* if autoresume is wanted ask for remote size */
+               if (startpos == PHP_FTP_AUTORESUME) {
+                       startpos = ftp_size(ftp, remote);
+                       if (startpos < 0) {
+                               startpos = 0;
+                       }
+               }
+               if (startpos) {
+                       php_stream_seek(stream, startpos, SEEK_SET);
+               }
+       }
+
+       if (!ftp_put(ftp, remote, stream, xtype, startpos)) {
                php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
                RETURN_FALSE;
        }
@@ -530,7 +572,7 @@ PHP_FUNCTION(ftp_fput)
 }
 /* }}} */
 
-/* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file, int mode)
+/* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
    Stores a file on the FTP server */
 PHP_FUNCTION(ftp_put)
 {
@@ -538,13 +580,13 @@ PHP_FUNCTION(ftp_put)
        ftpbuf_t        *ftp;
        ftptype_t       xtype;
        char            *remote, *local;
-       int                     remote_len, local_len, mode;
+       int                     remote_len, local_len, mode, startpos=0;
        php_stream * instream;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
                return;
        }
-       
+
        ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
        XTYPE(xtype, mode);
 
@@ -554,7 +596,25 @@ PHP_FUNCTION(ftp_put)
                RETURN_FALSE;
        }
 
-       if (!ftp_put(ftp, remote, instream, xtype) || php_stream_error(instream)) {
+       /* ignore autoresume if autoseek is switched off */
+       if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
+               startpos = 0;
+       }
+
+       if (ftp->autoseek && startpos) {
+               /* if autoresume is wanted ask for remote size */
+               if (startpos == PHP_FTP_AUTORESUME) {
+                       startpos = ftp_size(ftp, remote);
+                       if (startpos < 0) {
+                               startpos = 0;
+                       }
+               }
+               if (startpos) {
+                       php_stream_seek(instream, startpos, SEEK_SET);
+               }
+       }
+
+       if (!ftp_put(ftp, remote, instream, xtype, startpos) || php_stream_error(instream)) {
                php_stream_close(instream);
                php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
                RETURN_FALSE;
@@ -696,7 +756,7 @@ PHP_FUNCTION(ftp_close)
        zend_list_delete(Z_LVAL_P(z_ftp));
 }
 /* }}} */
-       
+
 /* {{{ proto bool ftp_set_option(resource stream, int option, mixed value)
    Sets an FTP option */
 PHP_FUNCTION(ftp_set_option)
@@ -704,7 +764,7 @@ 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;
        }
@@ -726,6 +786,15 @@ PHP_FUNCTION(ftp_set_option)
                        ftp->timeout_sec = Z_LVAL_P(z_value);
                        RETURN_TRUE;
                        break;
+               case PHP_FTP_OPT_AUTOSEEK:
+                       if (Z_TYPE_P(z_value) != IS_BOOL) {
+                               php_error(E_WARNING, "%s(): Option AUTOSEEK expects value of type boolean, %s given",
+                                                 get_active_function_name(TSRMLS_C), zend_zval_type_name(z_value));
+                               RETURN_FALSE;
+                       }
+                       ftp->autoseek = 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;
@@ -741,7 +810,7 @@ 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;
        }
@@ -752,6 +821,8 @@ PHP_FUNCTION(ftp_get_option)
                case PHP_FTP_OPT_TIMEOUT_SEC:
                        RETURN_LONG(ftp->timeout_sec);
                        break;
+               case PHP_FTP_OPT_AUTOSEEK:
+                       RETURN_BOOL(ftp->autoseek);
                default:
                        php_error(E_WARNING, "%s(): Unknown option '%d'", get_active_function_name(TSRMLS_C), option);
                        RETURN_FALSE;
index d5d36b96e4783744b091c017931e4dcd470527e0..fdbb13b3e96c61086d776336476e27a985faa1ab 100644 (file)
@@ -12,7 +12,8 @@
    | obtain it through the world-wide-web, please send a note to          |
    | license@php.net so we can mail you a copy immediately.               |
    +----------------------------------------------------------------------+
-   | Author: Andrew Skalski <askalski@chek.com>                           |
+   | Authors: Andrew Skalski <askalski@chek.com>                          |
+   |          Stefan Esser <sesser@php.net> (resume functions)            |
    +----------------------------------------------------------------------+
  */
 
@@ -27,6 +28,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
+#define PHP_FTP_OPT_AUTOSEEK   1
+#define PHP_FTP_AUTORESUME             -1
 
 PHP_MINIT_FUNCTION(ftp);
 PHP_MINFO_FUNCTION(ftp);