Add ftp_append to create a new file or append data to an existing file (RFC959)

This commit is contained in:
Andreas Treichel 2017-07-08 19:36:22 +02:00 committed by Nikita Popov
parent aa925cb0ad
commit 29e4d4eee6
8 changed files with 177 additions and 1 deletions

3
NEWS
View File

@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 7.2.0beta3
- FTP:
. Added ftp_append() function. (blar)
- Mbstring:
. Fixed bug #75001 (Wrong reflection on mb_eregi_replace). (Fabien
Villepinte)

View File

@ -233,6 +233,9 @@ See also: https://wiki.php.net/rfc/deprecations_php_7_2
. DomNodeList implements Countable, added DomNodeList::count().
. DOMNamedNodeMap implements Countable, added DOMNamedNodeMap::count().
- FTP:
. Added ftp_append().
- GD:
. Added imagesetclip() and imagegetclip().
. Added imageopenpolygon().

View File

@ -1056,6 +1056,74 @@ bail:
}
/* }}} */
/* {{{ ftp_append
*/
int
ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type)
{
databuf_t *data = NULL;
zend_long size;
char *ptr;
int ch;
if (ftp == NULL) {
return 0;
}
if (!ftp_type(ftp, type)) {
goto bail;
}
if ((data = ftp_getdata(ftp)) == NULL) {
goto bail;
}
ftp->data = data;
if (!ftp_putcmd(ftp, "APPE", sizeof("APPE")-1, path, path_len)) {
goto bail;
}
if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
goto bail;
}
if ((data = data_accept(data, ftp)) == NULL) {
goto bail;
}
size = 0;
ptr = data->buf;
while (!php_stream_eof(instream) && (ch = php_stream_getc(instream))!=EOF) {
/* flush if necessary */
if (FTP_BUFSIZE - size < 2) {
if (my_send(ftp, data->fd, data->buf, size) != size) {
goto bail;
}
ptr = data->buf;
size = 0;
}
if (ch == '\n' && type == FTPTYPE_ASCII) {
*ptr++ = '\r';
size++;
}
*ptr++ = ch;
size++;
}
if (size && my_send(ftp, data->fd, data->buf, size) != size) {
goto bail;
}
ftp->data = data = data_close(ftp, data);
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) {
goto bail;
}
return 1;
bail:
ftp->data = data_close(ftp, data);
return 0;
}
/* }}} */
/* {{{ ftp_size
*/
zend_long

View File

@ -190,6 +190,11 @@ int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_
*/
int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos);
/* append the data from a file, socket, or process as a file on the remote server
* returns true on success, false on error
*/
int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type);
/* returns the size of the given file, or -1 on error */
zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len);

View File

@ -191,6 +191,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_put, 0, 0, 4)
ZEND_ARG_INFO(0, startpos)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_append, 0, 0, 4)
ZEND_ARG_INFO(0, ftp)
ZEND_ARG_INFO(0, remote_file)
ZEND_ARG_INFO(0, local_file)
ZEND_ARG_INFO(0, mode)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_put, 0, 0, 4)
ZEND_ARG_INFO(0, ftp)
ZEND_ARG_INFO(0, remote_file)
@ -265,6 +272,7 @@ const zend_function_entry php_ftp_functions[] = {
PHP_FE(ftp_get, arginfo_ftp_get)
PHP_FE(ftp_fget, arginfo_ftp_fget)
PHP_FE(ftp_put, arginfo_ftp_put)
PHP_FE(ftp_append, arginfo_ftp_append)
PHP_FE(ftp_fput, arginfo_ftp_fput)
PHP_FE(ftp_size, arginfo_ftp_size)
PHP_FE(ftp_mdtm, arginfo_ftp_mdtm)
@ -1272,6 +1280,41 @@ PHP_FUNCTION(ftp_put)
}
/* }}} */
/* {{{ proto bool ftp_append(resource stream, string remote_file, string local_file, int mode)
Append content of a file a another file on the FTP server */
PHP_FUNCTION(ftp_append)
{
zval *z_ftp;
ftpbuf_t *ftp;
ftptype_t xtype;
char *remote, *local;
size_t remote_len, local_len;
zend_long mode;
php_stream *instream;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rppl", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
return;
}
if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
RETURN_FALSE;
}
XTYPE(xtype, mode);
if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
RETURN_FALSE;
}
if (!ftp_append(ftp, remote, remote_len, instream, xtype)) {
php_stream_close(instream);
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
RETURN_FALSE;
}
php_stream_close(instream);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto int ftp_nb_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
Stores a file on the FTP server */

View File

@ -60,6 +60,7 @@ PHP_FUNCTION(ftp_pasv);
PHP_FUNCTION(ftp_get);
PHP_FUNCTION(ftp_fget);
PHP_FUNCTION(ftp_put);
PHP_FUNCTION(ftp_append);
PHP_FUNCTION(ftp_fput);
PHP_FUNCTION(ftp_size);
PHP_FUNCTION(ftp_mdtm);

View File

@ -0,0 +1,32 @@
--TEST--
ftp_append() create new file and append something
--SKIPIF--
<?php
require 'skipif.inc';
?>
--FILE--
<?php
require 'server.inc';
$ftp = ftp_connect('127.0.0.1', $port);
if (!$ftp) die("Couldn't connect to the server");
var_dump(ftp_login($ftp, 'user', 'pass'));
@unlink(__DIR__.'/ftp_append_foobar');
file_put_contents(__DIR__.'/ftp_append_foo', 'foo');
var_dump(ftp_append($ftp, 'ftp_append_foobar', __DIR__.'/ftp_append_foo', FTP_BINARY));
file_put_contents(__DIR__.'/ftp_append_bar', 'bar');
var_dump(ftp_append($ftp, 'ftp_append_foobar', __DIR__.'/ftp_append_bar', FTP_BINARY));
var_dump(file_get_contents(__DIR__.'/ftp_append_foobar'));
ftp_close($ftp);
?>
--EXPECTF--
bool(true)
bool(true)
bool(true)
string(6) "foobar"

View File

@ -267,7 +267,28 @@ if ($pid) {
}
}
} elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
} elseif (preg_match("~^APPE ([\w/.-]+)\r\n$~", $buf, $m)) {
fputs($s, "150 File status okay; about to open data connection\r\n");
if(empty($pasv))
{
if (!$fs = stream_socket_client("tcp://$host:$port")) {
fputs($s, "425 Can't open data connection\r\n");
continue;
}
$data = stream_get_contents($fs);
file_put_contents(__DIR__.'/'.$m[1], $data, FILE_APPEND);
fputs($s, "226 Closing data Connection.\r\n");
fclose($fs);
}else{
$data = stream_get_contents($fs);
file_put_contents(__DIR__.'/'.$m[1], $data, FILE_APPEND);
fputs($s, "226 Closing data Connection.\r\n");
fclose($fs);
}
}elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
change_dir($m[1]);
fputs($s, "250 CWD command successful.\r\n");