Skip to content

Commit 29e4d4e

Browse files
blarnikic
authored andcommitted
Add ftp_append to create a new file or append data to an existing file (RFC959)
1 parent aa925cb commit 29e4d4e

8 files changed

Lines changed: 177 additions & 1 deletion

File tree

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 7.2.0beta3
44

5+
- FTP:
6+
. Added ftp_append() function. (blar)
7+
58
- Mbstring:
69
. Fixed bug #75001 (Wrong reflection on mb_eregi_replace). (Fabien
710
Villepinte)

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ See also: https://wiki.php.net/rfc/deprecations_php_7_2
233233
. DomNodeList implements Countable, added DomNodeList::count().
234234
. DOMNamedNodeMap implements Countable, added DOMNamedNodeMap::count().
235235

236+
- FTP:
237+
. Added ftp_append().
238+
236239
- GD:
237240
. Added imagesetclip() and imagegetclip().
238241
. Added imageopenpolygon().

ext/ftp/ftp.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,74 @@ ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *inst
10561056
}
10571057
/* }}} */
10581058

1059+
1060+
/* {{{ ftp_append
1061+
*/
1062+
int
1063+
ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type)
1064+
{
1065+
databuf_t *data = NULL;
1066+
zend_long size;
1067+
char *ptr;
1068+
int ch;
1069+
1070+
if (ftp == NULL) {
1071+
return 0;
1072+
}
1073+
if (!ftp_type(ftp, type)) {
1074+
goto bail;
1075+
}
1076+
if ((data = ftp_getdata(ftp)) == NULL) {
1077+
goto bail;
1078+
}
1079+
ftp->data = data;
1080+
1081+
if (!ftp_putcmd(ftp, "APPE", sizeof("APPE")-1, path, path_len)) {
1082+
goto bail;
1083+
}
1084+
if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
1085+
goto bail;
1086+
}
1087+
if ((data = data_accept(data, ftp)) == NULL) {
1088+
goto bail;
1089+
}
1090+
1091+
size = 0;
1092+
ptr = data->buf;
1093+
while (!php_stream_eof(instream) && (ch = php_stream_getc(instream))!=EOF) {
1094+
/* flush if necessary */
1095+
if (FTP_BUFSIZE - size < 2) {
1096+
if (my_send(ftp, data->fd, data->buf, size) != size) {
1097+
goto bail;
1098+
}
1099+
ptr = data->buf;
1100+
size = 0;
1101+
}
1102+
1103+
if (ch == '\n' && type == FTPTYPE_ASCII) {
1104+
*ptr++ = '\r';
1105+
size++;
1106+
}
1107+
1108+
*ptr++ = ch;
1109+
size++;
1110+
}
1111+
1112+
if (size && my_send(ftp, data->fd, data->buf, size) != size) {
1113+
goto bail;
1114+
}
1115+
ftp->data = data = data_close(ftp, data);
1116+
1117+
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250 && ftp->resp != 200)) {
1118+
goto bail;
1119+
}
1120+
return 1;
1121+
bail:
1122+
ftp->data = data_close(ftp, data);
1123+
return 0;
1124+
}
1125+
/* }}} */
1126+
10591127
/* {{{ ftp_size
10601128
*/
10611129
zend_long

ext/ftp/ftp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ int ftp_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, const size_
190190
*/
191191
int ftp_put(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type, zend_long startpos);
192192

193+
/* append the data from a file, socket, or process as a file on the remote server
194+
* returns true on success, false on error
195+
*/
196+
int ftp_append(ftpbuf_t *ftp, const char *path, const size_t path_len, php_stream *instream, ftptype_t type);
197+
193198
/* returns the size of the given file, or -1 on error */
194199
zend_long ftp_size(ftpbuf_t *ftp, const char *path, const size_t path_len);
195200

ext/ftp/php_ftp.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_put, 0, 0, 4)
191191
ZEND_ARG_INFO(0, startpos)
192192
ZEND_END_ARG_INFO()
193193

194+
ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_append, 0, 0, 4)
195+
ZEND_ARG_INFO(0, ftp)
196+
ZEND_ARG_INFO(0, remote_file)
197+
ZEND_ARG_INFO(0, local_file)
198+
ZEND_ARG_INFO(0, mode)
199+
ZEND_END_ARG_INFO()
200+
194201
ZEND_BEGIN_ARG_INFO_EX(arginfo_ftp_nb_put, 0, 0, 4)
195202
ZEND_ARG_INFO(0, ftp)
196203
ZEND_ARG_INFO(0, remote_file)
@@ -265,6 +272,7 @@ const zend_function_entry php_ftp_functions[] = {
265272
PHP_FE(ftp_get, arginfo_ftp_get)
266273
PHP_FE(ftp_fget, arginfo_ftp_fget)
267274
PHP_FE(ftp_put, arginfo_ftp_put)
275+
PHP_FE(ftp_append, arginfo_ftp_append)
268276
PHP_FE(ftp_fput, arginfo_ftp_fput)
269277
PHP_FE(ftp_size, arginfo_ftp_size)
270278
PHP_FE(ftp_mdtm, arginfo_ftp_mdtm)
@@ -1272,6 +1280,41 @@ PHP_FUNCTION(ftp_put)
12721280
}
12731281
/* }}} */
12741282

1283+
/* {{{ proto bool ftp_append(resource stream, string remote_file, string local_file, int mode)
1284+
Append content of a file a another file on the FTP server */
1285+
PHP_FUNCTION(ftp_append)
1286+
{
1287+
zval *z_ftp;
1288+
ftpbuf_t *ftp;
1289+
ftptype_t xtype;
1290+
char *remote, *local;
1291+
size_t remote_len, local_len;
1292+
zend_long mode;
1293+
php_stream *instream;
1294+
1295+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rppl", &z_ftp, &remote, &remote_len, &local, &local_len, &mode) == FAILURE) {
1296+
return;
1297+
}
1298+
1299+
if ((ftp = (ftpbuf_t *)zend_fetch_resource(Z_RES_P(z_ftp), le_ftpbuf_name, le_ftpbuf)) == NULL) {
1300+
RETURN_FALSE;
1301+
}
1302+
XTYPE(xtype, mode);
1303+
1304+
if (!(instream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt" : "rb", REPORT_ERRORS, NULL))) {
1305+
RETURN_FALSE;
1306+
}
1307+
1308+
if (!ftp_append(ftp, remote, remote_len, instream, xtype)) {
1309+
php_stream_close(instream);
1310+
php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf);
1311+
RETURN_FALSE;
1312+
}
1313+
php_stream_close(instream);
1314+
1315+
RETURN_TRUE;
1316+
}
1317+
/* }}} */
12751318

12761319
/* {{{ proto int ftp_nb_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
12771320
Stores a file on the FTP server */

ext/ftp/php_ftp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ PHP_FUNCTION(ftp_pasv);
6060
PHP_FUNCTION(ftp_get);
6161
PHP_FUNCTION(ftp_fget);
6262
PHP_FUNCTION(ftp_put);
63+
PHP_FUNCTION(ftp_append);
6364
PHP_FUNCTION(ftp_fput);
6465
PHP_FUNCTION(ftp_size);
6566
PHP_FUNCTION(ftp_mdtm);

ext/ftp/tests/ftp_append.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
ftp_append() create new file and append something
3+
--SKIPIF--
4+
<?php
5+
require 'skipif.inc';
6+
?>
7+
--FILE--
8+
<?php
9+
require 'server.inc';
10+
11+
$ftp = ftp_connect('127.0.0.1', $port);
12+
if (!$ftp) die("Couldn't connect to the server");
13+
14+
var_dump(ftp_login($ftp, 'user', 'pass'));
15+
16+
@unlink(__DIR__.'/ftp_append_foobar');
17+
18+
file_put_contents(__DIR__.'/ftp_append_foo', 'foo');
19+
var_dump(ftp_append($ftp, 'ftp_append_foobar', __DIR__.'/ftp_append_foo', FTP_BINARY));
20+
21+
file_put_contents(__DIR__.'/ftp_append_bar', 'bar');
22+
var_dump(ftp_append($ftp, 'ftp_append_foobar', __DIR__.'/ftp_append_bar', FTP_BINARY));
23+
24+
var_dump(file_get_contents(__DIR__.'/ftp_append_foobar'));
25+
26+
ftp_close($ftp);
27+
?>
28+
--EXPECTF--
29+
bool(true)
30+
bool(true)
31+
bool(true)
32+
string(6) "foobar"

ext/ftp/tests/server.inc

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,28 @@ if ($pid) {
267267
}
268268
}
269269

270-
} elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
270+
} elseif (preg_match("~^APPE ([\w/.-]+)\r\n$~", $buf, $m)) {
271+
fputs($s, "150 File status okay; about to open data connection\r\n");
272+
273+
if(empty($pasv))
274+
{
275+
if (!$fs = stream_socket_client("tcp://$host:$port")) {
276+
fputs($s, "425 Can't open data connection\r\n");
277+
continue;
278+
}
279+
280+
$data = stream_get_contents($fs);
281+
file_put_contents(__DIR__.'/'.$m[1], $data, FILE_APPEND);
282+
fputs($s, "226 Closing data Connection.\r\n");
283+
fclose($fs);
284+
}else{
285+
$data = stream_get_contents($fs);
286+
file_put_contents(__DIR__.'/'.$m[1], $data, FILE_APPEND);
287+
fputs($s, "226 Closing data Connection.\r\n");
288+
fclose($fs);
289+
}
290+
291+
}elseif (preg_match("~^CWD ([A-Za-z./]+)\r\n$~", $buf, $m)) {
271292
change_dir($m[1]);
272293
fputs($s, "250 CWD command successful.\r\n");
273294

0 commit comments

Comments
 (0)