cvs: php4 /ext/ftp CREDITS ftp.c ftp.h php_ftp.c php_ftp.h
| From: | Stefan Esser | Date: | Fri, 26 Jul 2002 13:03:09 +0000 |
| Subject: | cvs: php4 /ext/ftp CREDITS ftp.c ftp.h php_ftp.c php_ftp.h | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-12988@lists.php.net to get a copy of this message | ||
sesser Fri Jul 26 09:03:09 2002 EDT
Modified files:
/php4/ext/ftp CREDITS ftp.c ftp.h php_ftp.c php_ftp.h
Log:
@- FTP extension does support (auto)resuming now.
Added (Auto)Resuming functionality to ftp_(f)get/(f)put via optional 5th parameter.
Index: php4/ext/ftp/CREDITS diff -u php4/ext/ftp/CREDITS:1.1 php4/ext/ftp/CREDITS:1.2 --- php4/ext/ftp/CREDITS:1.1 Mon Nov 20 05:31:22 2000 +++ php4/ext/ftp/CREDITS Fri Jul 26 09:03:08 2002 @@ -1,2 +1,3 @@ FTP Andrew Skalski +Stefan Esser \ No newline at end of file Index: php4/ext/ftp/ftp.c diff -u php4/ext/ftp/ftp.c:1.52 php4/ext/ftp/ftp.c:1.53 --- php4/ext/ftp/ftp.c:1.52 Mon Jul 22 14:46:26 2002 +++ php4/ext/ftp/ftp.c Fri Jul 26 09:03:08 2002 @@ -12,11 +12,12 @@ | 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) | +----------------------------------------------------------------------+ */ -/* $Id: ftp.c,v 1.52 2002/07/22 18:46:26 jason Exp $ */ +/* $Id: ftp.c,v 1.53 2002/07/26 13:03:08 sesser Exp $ */ #include "php.h" @@ -114,7 +115,7 @@ perror("calloc"); return NULL; } - + tv.tv_sec = timeout_sec; tv.tv_usec = 0; @@ -545,12 +546,13 @@ /* {{{ 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 @@ 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 @@ /* {{{ 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 @@ 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 @@ } /* 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: php4/ext/ftp/ftp.h diff -u php4/ext/ftp/ftp.h:1.24 php4/ext/ftp/ftp.h:1.25 --- php4/ext/ftp/ftp.h:1.24 Thu Jul 4 09:48:48 2002 +++ php4/ext/ftp/ftp.h Fri Jul 26 09:03:08 2002 @@ -13,10 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski <askalski@chek.com> | + | Stefan Esser <sesser@php.net> (resume functions) | +----------------------------------------------------------------------+ */ -/* $Id: ftp.h,v 1.24 2002/07/04 13:48:48 sniper Exp $ */ +/* $Id: ftp.h,v 1.25 2002/07/26 13:03:08 sesser Exp $ */ #ifndef FTP_H #define FTP_H @@ -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 @@ 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 @@ * 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: php4/ext/ftp/php_ftp.c diff -u php4/ext/ftp/php_ftp.c:1.62 php4/ext/ftp/php_ftp.c:1.63 --- php4/ext/ftp/php_ftp.c:1.62 Thu Jul 11 16:29:53 2002 +++ php4/ext/ftp/php_ftp.c Fri Jul 26 09:03:08 2002 @@ -13,10 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski <askalski@chek.com> | + | Stefan Esser <sesser@php.net> (resume functions) | +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.c,v 1.62 2002/07/11 20:29:53 sniper Exp $ */ +/* $Id: php_ftp.c,v 1.63 2002/07/26 13:03:08 sesser Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -95,7 +96,9 @@ 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 @@ RETURN_FALSE; } + /* autoseek for resuming */ + ftp->autoseek = FTP_DEFAULT_AUTOSEEK; + ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); } /* }}} */ @@ -252,7 +258,7 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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: php4/ext/ftp/php_ftp.h diff -u php4/ext/ftp/php_ftp.h:1.17 php4/ext/ftp/php_ftp.h:1.18 --- php4/ext/ftp/php_ftp.h:1.17 Thu Feb 28 03:26:10 2002 +++ php4/ext/ftp/php_ftp.h Fri Jul 26 09:03:08 2002 @@ -12,11 +12,12 @@ | 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) | +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.h,v 1.17 2002/02/28 08:26:10 sebastian Exp $ */ +/* $Id: php_ftp.h,v 1.18 2002/07/26 13:03:08 sesser Exp $ */ #ifndef _INCLUDED_FTP_H #define _INCLUDED_FTP_H @@ -27,6 +28,8 @@ #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);
Index: php4/ext/ftp/CREDITS diff -u php4/ext/ftp/CREDITS:1.1 php4/ext/ftp/CREDITS:1.2 --- php4/ext/ftp/CREDITS:1.1 Mon Nov 20 05:31:22 2000 +++ php4/ext/ftp/CREDITS Fri Jul 26 09:03:08 2002 @@ -1,2 +1,3 @@ FTP Andrew Skalski +Stefan Esser \ No newline at end of file Index: php4/ext/ftp/ftp.c diff -u php4/ext/ftp/ftp.c:1.52 php4/ext/ftp/ftp.c:1.53 --- php4/ext/ftp/ftp.c:1.52 Mon Jul 22 14:46:26 2002 +++ php4/ext/ftp/ftp.c Fri Jul 26 09:03:08 2002 @@ -12,11 +12,12 @@ | 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) | +----------------------------------------------------------------------+ */ -/* $Id: ftp.c,v 1.52 2002/07/22 18:46:26 jason Exp $ */ +/* $Id: ftp.c,v 1.53 2002/07/26 13:03:08 sesser Exp $ */ #include "php.h" @@ -114,7 +115,7 @@ perror("calloc"); return NULL; } - + tv.tv_sec = timeout_sec; tv.tv_usec = 0; @@ -545,12 +546,13 @@ /* {{{ 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 @@ 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 @@ /* {{{ 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 @@ 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 @@ } /* 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: php4/ext/ftp/ftp.h diff -u php4/ext/ftp/ftp.h:1.24 php4/ext/ftp/ftp.h:1.25 --- php4/ext/ftp/ftp.h:1.24 Thu Jul 4 09:48:48 2002 +++ php4/ext/ftp/ftp.h Fri Jul 26 09:03:08 2002 @@ -13,10 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski <askalski@chek.com> | + | Stefan Esser <sesser@php.net> (resume functions) | +----------------------------------------------------------------------+ */ -/* $Id: ftp.h,v 1.24 2002/07/04 13:48:48 sniper Exp $ */ +/* $Id: ftp.h,v 1.25 2002/07/26 13:03:08 sesser Exp $ */ #ifndef FTP_H #define FTP_H @@ -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 @@ 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 @@ * 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: php4/ext/ftp/php_ftp.c diff -u php4/ext/ftp/php_ftp.c:1.62 php4/ext/ftp/php_ftp.c:1.63 --- php4/ext/ftp/php_ftp.c:1.62 Thu Jul 11 16:29:53 2002 +++ php4/ext/ftp/php_ftp.c Fri Jul 26 09:03:08 2002 @@ -13,10 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Andrew Skalski <askalski@chek.com> | + | Stefan Esser <sesser@php.net> (resume functions) | +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.c,v 1.62 2002/07/11 20:29:53 sniper Exp $ */ +/* $Id: php_ftp.c,v 1.63 2002/07/26 13:03:08 sesser Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -95,7 +96,9 @@ 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 @@ RETURN_FALSE; } + /* autoseek for resuming */ + ftp->autoseek = FTP_DEFAULT_AUTOSEEK; + ZEND_REGISTER_RESOURCE(return_value, ftp, le_ftpbuf); } /* }}} */ @@ -252,7 +258,7 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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: php4/ext/ftp/php_ftp.h diff -u php4/ext/ftp/php_ftp.h:1.17 php4/ext/ftp/php_ftp.h:1.18 --- php4/ext/ftp/php_ftp.h:1.17 Thu Feb 28 03:26:10 2002 +++ php4/ext/ftp/php_ftp.h Fri Jul 26 09:03:08 2002 @@ -12,11 +12,12 @@ | 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) | +----------------------------------------------------------------------+ */ -/* $Id: php_ftp.h,v 1.17 2002/02/28 08:26:10 sebastian Exp $ */ +/* $Id: php_ftp.h,v 1.18 2002/07/26 13:03:08 sesser Exp $ */ #ifndef _INCLUDED_FTP_H #define _INCLUDED_FTP_H @@ -27,6 +28,8 @@ #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);