summaryrefslogtreecommitdiff
path: root/ext/ftp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/ftp')
-rw-r--r--ext/ftp/ftp.c68
-rw-r--r--ext/ftp/ftp.h5
-rw-r--r--ext/ftp/php_ftp.c43
-rw-r--r--ext/ftp/php_ftp.h1
-rw-r--r--ext/ftp/tests/ftp_append.phpt32
-rw-r--r--ext/ftp/tests/server.inc23
6 files changed, 171 insertions, 1 deletions
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 499a8b40b2..d1fffc2b2f 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -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
diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h
index d1576f0a8a..38e34acfe2 100644
--- a/ext/ftp/ftp.h
+++ b/ext/ftp/ftp.h
@@ -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);
diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c
index bad5690039..eb6589ebc2 100644
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@ -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 */
diff --git a/ext/ftp/php_ftp.h b/ext/ftp/php_ftp.h
index 37b75f6b9b..3927738306 100644
--- a/ext/ftp/php_ftp.h
+++ b/ext/ftp/php_ftp.h
@@ -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);
diff --git a/ext/ftp/tests/ftp_append.phpt b/ext/ftp/tests/ftp_append.phpt
new file mode 100644
index 0000000000..5f52ac923c
--- /dev/null
+++ b/ext/ftp/tests/ftp_append.phpt
@@ -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"
diff --git a/ext/ftp/tests/server.inc b/ext/ftp/tests/server.inc
index 5f003cc04d..a1bf074f90 100644
--- a/ext/ftp/tests/server.inc
+++ b/ext/ftp/tests/server.inc
@@ -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");