diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 4156a04581316..330b689ce4013 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -610,7 +610,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 +618,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 +785,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 +806,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 +879,10 @@ ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, /* {{{ 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 +899,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 +956,7 @@ ftp_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, i /* {{{ ftp_size */ -int +long ftp_size(ftpbuf_t *ftp, const char *path) { if (ftp == NULL) { @@ -979,7 +971,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 +1133,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 +1226,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) { @@ -1704,7 +1697,7 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path TSRMLS_DC) /* {{{ 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 +1715,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 +1814,7 @@ ftp_nb_continue_read(ftpbuf_t *ftp TSRMLS_DC) /* {{{ 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 +1829,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 +1866,7 @@ ftp_nb_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type 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 7023723a403ad..a4d773d4710f4 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 6e232a5df2d3a..75a30c332393d 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 0000000000000..6c3b20245f95b --- /dev/null +++ b/ext/ftp/tests/filesize_large.phpt @@ -0,0 +1,20 @@ +--TEST-- +Verify php can handle filesizes >32bit +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(5368709120) 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 0000000000000..ce051fc3f1334 --- /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-- + +--FILE-- + +--CLEAN-- + +--EXPECT-- +string(1) "X" +int(5368709120) diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc index 86178806233f7..7dc8fa08d99ff 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 +?>