diff options
Diffstat (limited to 'ext/ftp')
-rw-r--r-- | ext/ftp/ftp.c | 71 | ||||
-rw-r--r-- | ext/ftp/ftp.h | 12 | ||||
-rw-r--r-- | ext/ftp/php_ftp.c | 16 | ||||
-rw-r--r-- | ext/ftp/tests/filesize_large.phpt | 23 | ||||
-rw-r--r-- | ext/ftp/tests/ftp_fget_basic.phpt | 2 | ||||
-rw-r--r-- | ext/ftp/tests/ftp_get_basic.phpt | 2 | ||||
-rw-r--r-- | ext/ftp/tests/ftp_nb_get_large.phpt | 36 | ||||
-rw-r--r-- | ext/ftp/tests/server.inc | 23 |
8 files changed, 125 insertions, 60 deletions
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 4c8a94f81..0d6704f9d 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -39,7 +39,7 @@ #ifdef PHP_WIN32 #include <winsock2.h> #elif defined(NETWARE) -#ifdef USE_WINSOCK /* Modified to use Winsock (NOVSOCK2.H), atleast for now */ +#ifdef USE_WINSOCK /* Modified to use Winsock (NOVSOCK2.H), at least for now */ #include <novsock2.h> #else #include <sys/socket.h> @@ -182,6 +182,7 @@ ftp_close(ftpbuf_t *ftp) #if HAVE_OPENSSL_EXT if (ftp->ssl_active) { SSL_shutdown(ftp->ssl_handle); + SSL_free(ftp->ssl_handle); } #endif closesocket(ftp->fd); @@ -297,6 +298,7 @@ ftp_login(ftpbuf_t *ftp, const char *user, const char *pass TSRMLS_DC) if (SSL_connect(ftp->ssl_handle) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS handshake failed"); SSL_shutdown(ftp->ssl_handle); + SSL_free(ftp->ssl_handle); return 0; } @@ -610,7 +612,7 @@ ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int filenam /* {{{ ftp_alloc */ int -ftp_alloc(ftpbuf_t *ftp, const int size, char **response) +ftp_alloc(ftpbuf_t *ftp, const long size, char **response) { char buffer[64]; @@ -618,8 +620,8 @@ ftp_alloc(ftpbuf_t *ftp, const int size, char **response) return 0; } - snprintf(buffer, sizeof(buffer) - 1, "%d", size); - + snprintf(buffer, sizeof(buffer) - 1, "%ld", size); + if (!ftp_putcmd(ftp, "ALLO", buffer)) { return 0; } @@ -785,7 +787,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv) /* {{{ ftp_get */ int -ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC) +ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC) { databuf_t *data = NULL; int lastch; @@ -806,11 +808,7 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, ftp->data = data; if (resumepos > 0) { - if (resumepos > 2147483647) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483647 bytes."); - goto bail; - } - snprintf(arg, sizeof(arg), "%u", resumepos); + snprintf(arg, sizeof(arg), "%ld", resumepos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } @@ -883,10 +881,10 @@ bail: /* {{{ ftp_put */ int -ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC) +ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC) { databuf_t *data = NULL; - int size; + long size; char *ptr; int ch; char arg[11]; @@ -903,11 +901,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, i ftp->data = data; if (startpos > 0) { - if (startpos > 2147483647) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes."); - goto bail; - } - snprintf(arg, sizeof(arg), "%u", startpos); + snprintf(arg, sizeof(arg), "%ld", startpos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } @@ -964,7 +958,7 @@ bail: /* {{{ ftp_size */ -int +long ftp_size(ftpbuf_t *ftp, const char *path) { if (ftp == NULL) { @@ -979,7 +973,7 @@ ftp_size(ftpbuf_t *ftp, const char *path) if (!ftp_getresp(ftp) || ftp->resp != 213) { return -1; } - return atoi(ftp->inbuf); + return atol(ftp->inbuf); } /* }}} */ @@ -1141,7 +1135,7 @@ ftp_putcmd(ftpbuf_t *ftp, const char *cmd, const char *args) int ftp_readline(ftpbuf_t *ftp) { - int size, rcvd; + long size, rcvd; char *data, *eol; /* shift the extra to the front */ @@ -1234,7 +1228,8 @@ ftp_getresp(ftpbuf_t *ftp) int my_send(ftpbuf_t *ftp, php_socket_t s, void *buf, size_t len) { - int n, size, sent; + long size, sent; + int n; size = len; while (size) { @@ -1548,6 +1543,7 @@ data_accepted: if (SSL_connect(data->ssl_handle) <= 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "data_accept: SSL/TLS handshake failed"); SSL_shutdown(data->ssl_handle); + SSL_free(data->ssl_handle); return 0; } @@ -1565,13 +1561,21 @@ data_accepted: databuf_t* data_close(ftpbuf_t *ftp, databuf_t *data) { +#if HAVE_OPENSSL_EXT + SSL_CTX *ctx; +#endif if (data == NULL) { return NULL; } if (data->listener != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { + + ctx = SSL_get_SSL_CTX(data->ssl_handle); + SSL_CTX_free(ctx); + SSL_shutdown(data->ssl_handle); + SSL_free(data->ssl_handle); data->ssl_active = 0; } #endif @@ -1580,7 +1584,11 @@ data_close(ftpbuf_t *ftp, databuf_t *data) if (data->fd != -1) { #if HAVE_OPENSSL_EXT if (data->ssl_active) { + ctx = SSL_get_SSL_CTX(data->ssl_handle); + SSL_CTX_free(ctx); + SSL_shutdown(data->ssl_handle); + SSL_free(data->ssl_handle); data->ssl_active = 0; } #endif @@ -1704,7 +1712,7 @@ bail: /* {{{ ftp_nb_get */ int -ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC) +ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC) { databuf_t *data = NULL; char arg[11]; @@ -1722,14 +1730,7 @@ ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t typ } if (resumepos>0) { - /* We are working on an architecture that supports 64-bit integers - * since php is 32 bit by design, we bail out with warning - */ - if (resumepos > 2147483647) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files greater than 2147483648 bytes."); - goto bail; - } - snprintf(arg, sizeof(arg), "%u", resumepos); + snprintf(arg, sizeof(arg), "%ld", resumepos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } @@ -1828,7 +1829,7 @@ bail: /* {{{ ftp_nb_put */ int -ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC) +ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC) { databuf_t *data = NULL; char arg[11]; @@ -1843,11 +1844,7 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type goto bail; } if (startpos > 0) { - if (startpos > 2147483647) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "PHP cannot handle files with a size greater than 2147483647 bytes."); - goto bail; - } - snprintf(arg, sizeof(arg), "%u", startpos); + snprintf(arg, sizeof(arg), "%ld", startpos); if (!ftp_putcmd(ftp, "REST", arg)) { goto bail; } @@ -1884,7 +1881,7 @@ bail: int ftp_nb_continue_write(ftpbuf_t *ftp TSRMLS_DC) { - int size; + long size; char *ptr; int ch; diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index c7db45789..69de7dbb7 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -146,7 +146,7 @@ int ftp_chmod(ftpbuf_t *ftp, const int mode, const char *filename, const int fi * however some servers will not accept STOR or APPE until ALLO is confirmed. * If response is passed, it is estrdup()ed from ftp->inbuf and must be freed * or assigned to a zval returned to the user */ -int ftp_alloc(ftpbuf_t *ftp, const int size, char **response); +int ftp_alloc(ftpbuf_t *ftp, const long size, char **response); /* returns a NULL-terminated array of filenames in the given path * or NULL on error. the return array must be freed (but don't @@ -169,15 +169,15 @@ int ftp_pasv(ftpbuf_t *ftp, int pasv); /* retrieves a file and saves its contents to outfp * returns true on success, false on error */ -int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC); +int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC); /* 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 startpos TSRMLS_DC); +int ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC); /* returns the size of the given file, or -1 on error */ -int ftp_size(ftpbuf_t *ftp, const char *path); +long 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); @@ -194,12 +194,12 @@ int ftp_site(ftpbuf_t *ftp, const char *cmd); /* retrieves part of a file and saves its contents to outfp * returns true on success, false on error */ -int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos TSRMLS_DC); +int ftp_nb_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, long resumepos TSRMLS_DC); /* 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_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos TSRMLS_DC); +int ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, long startpos TSRMLS_DC); /* continues a previous nb_(f)get command */ diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 73071936e..da22e0b63 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -784,8 +784,8 @@ PHP_FUNCTION(ftp_nb_fget) ftptype_t xtype; php_stream *stream; char *file; - int file_len, ret; - long mode, resumepos=0; + int file_len; + long mode, resumepos=0, ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrsl|l", &z_ftp, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { return; @@ -968,9 +968,7 @@ PHP_FUNCTION(ftp_nb_get) RETURN_LONG(PHP_FTP_FAILED); } - if (ret == PHP_FTP_FINISHED) { - php_stream_close(outstream); - } + php_stream_close(outstream); RETURN_LONG(ret); } @@ -982,7 +980,7 @@ PHP_FUNCTION(ftp_nb_continue) { zval *z_ftp; ftpbuf_t *ftp; - int ret; + long ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) { return; @@ -1120,7 +1118,7 @@ PHP_FUNCTION(ftp_put) ftpbuf_t *ftp; ftptype_t xtype; char *remote, *local; - int remote_len, local_len; + long remote_len, local_len; long mode, startpos=0; php_stream *instream; @@ -1173,8 +1171,8 @@ PHP_FUNCTION(ftp_nb_put) ftpbuf_t *ftp; ftptype_t xtype; char *remote, *local; - int remote_len, local_len, ret; - long mode, startpos=0; + int remote_len, local_len; + long mode, startpos=0, ret; php_stream *instream; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rppl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) { diff --git a/ext/ftp/tests/filesize_large.phpt b/ext/ftp/tests/filesize_large.phpt new file mode 100644 index 000000000..05f12a3e5 --- /dev/null +++ b/ext/ftp/tests/filesize_large.phpt @@ -0,0 +1,23 @@ +--TEST-- +Verify php can handle filesizes >32bit +--SKIPIF-- +<?php +require 'skipif.inc'; +if (2147483647 == PHP_INT_MAX) { + die('skip 64-bit only'); +} +?> +--FILE-- +<?php +require 'server.inc'; + +$ftp = ftp_connect('127.0.0.1', $port); +if (!$ftp) die("Couldn't connect to the server"); + +ftp_login($ftp, 'user', 'pass'); +var_dump(ftp_size($ftp, 'largefile')); + +ftp_close($ftp); +?> +--EXPECT-- +int(5368709120) diff --git a/ext/ftp/tests/ftp_fget_basic.phpt b/ext/ftp/tests/ftp_fget_basic.phpt index d736f8c45..355b8b846 100644 --- a/ext/ftp/tests/ftp_fget_basic.phpt +++ b/ext/ftp/tests/ftp_fget_basic.phpt @@ -27,7 +27,7 @@ var_dump(ftp_fget($ftp, $fp, 'binary data.bin', FTP_BINARY)); fseek($fp, $postition); var_dump(urlencode(fgets($fp))); -//test non-existant file request +//test non-existent file request ftp_fget($ftp, $fp ,'a warning.txt', FTP_ASCII); //remove file diff --git a/ext/ftp/tests/ftp_get_basic.phpt b/ext/ftp/tests/ftp_get_basic.phpt index 23fd8d07f..2fd8c7914 100644 --- a/ext/ftp/tests/ftp_get_basic.phpt +++ b/ext/ftp/tests/ftp_get_basic.phpt @@ -27,7 +27,7 @@ var_dump(ftp_get($ftp, $tmpfname, 'binary data.bin', FTP_BINARY)); var_dump(urlencode(file_get_contents($tmpfname))); unlink($tmpfname); -//test non-existant file request +//test non-existent file request ftp_get($ftp, $tmpfname ,'a warning.txt', FTP_ASCII); ?> --EXPECTF-- diff --git a/ext/ftp/tests/ftp_nb_get_large.phpt b/ext/ftp/tests/ftp_nb_get_large.phpt new file mode 100644 index 000000000..3fbf2a483 --- /dev/null +++ b/ext/ftp/tests/ftp_nb_get_large.phpt @@ -0,0 +1,36 @@ +--TEST-- +Testing ftp_nb_fget can handle large files incl. resume +--SKIPIF-- +<?php +require 'skipif.inc'; +if (2147483647 == PHP_INT_MAX) { + die('skip ot supported on this system'); +} +if (disk_free_space(__DIR__) < 10*1024*1024*1024) { + die('not enough disk space'); +} +?> +--FILE-- +<?php +require 'server.inc'; + +$ftp = ftp_connect('127.0.0.1', $port); +ftp_login($ftp, 'user', 'pass'); +if (!$ftp) die("Couldn't connect to the server"); + +$local_file = dirname(__FILE__) . DIRECTORY_SEPARATOR . "localfile.txt"; +touch($local_file); +ftp_nb_get($ftp, $local_file, 'fget_large.txt', FTP_BINARY, 5368709119); +$fp = fopen($local_file, 'r'); +fseek($fp, 5368709119); +var_dump(fread($fp, 1)); +var_dump(filesize($local_file)); +fclose($fp); +?> +--CLEAN-- +<?php +@unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . "localfile.txt"); +?> +--EXPECT-- +string(1) "X" +int(5368709120) diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc index 861788062..7dc8fa08d 100644 --- a/ext/ftp/tests/server.inc +++ b/ext/ftp/tests/server.inc @@ -357,7 +357,17 @@ if ($pid) { $transfer_type = $ascii? 'ASCII' : 'BINARY' ; fputs($fs, "Bar\r\n"); fputs($s, "226 Closing data Connection.\r\n"); - break; + break; + case "fget_large": + fputs($s, "150 File status okay; about to open data connection.\r\n"); + $transfer_type = $ascii? 'ASCII' : 'BINARY' ; + if ($GLOBALS['rest_pos'] == '5368709119') { + fputs($fs, "X"); + } else { + fputs($fs, "Y"); + } + fputs($s, "226 Closing data Connection.\r\n"); + break; default: fputs($s, "550 {$matches[1]}: No such file or directory \r\n"); break; @@ -393,11 +403,12 @@ if ($pid) { }elseif (preg_match('/^LIST no_exists\//', $buf, $matches)) { fputs($s, "425 Error establishing connection\r\n"); - }elseif (preg_match('/^REST \d+/', $buf, $matches)) { + }elseif (preg_match('/^REST (\d+)/', $buf, $matches)) { + $GLOBALS['rest_pos'] = $matches[1]; fputs($s, "350 OK\r\n"); - } - - else { + }elseif (preg_match('/^SIZE largefile/', $buf)) { + fputs($s, "213 5368709120\r\n"); + }else { fputs($s, "500 Syntax error, command unrecognized.\r\n"); dump_and_exit($buf); } @@ -407,4 +418,4 @@ if ($pid) { } fclose($socket); -?>
\ No newline at end of file +?> |