mirror of
https://github.com/php/php-src.git
synced 2024-09-22 10:27:25 +00:00
[EXPERIMENTAL] Added functions for asynchronous FTP transfers
This commit is contained in:
parent
8b853592b1
commit
80e9724ccc
289
ext/ftp/ftp.c
289
ext/ftp/ftp.c
@ -126,6 +126,7 @@ ftp_open(const char *host, short port, long timeout_sec)
|
||||
|
||||
/* Default Settings */
|
||||
ftp->timeout_sec = timeout_sec;
|
||||
ftp->async = 0;
|
||||
|
||||
size = sizeof(ftp->localaddr);
|
||||
memset(&ftp->localaddr, 0, size);
|
||||
@ -232,6 +233,8 @@ ftp_reinit(ftpbuf_t *ftp)
|
||||
|
||||
ftp_gc(ftp);
|
||||
|
||||
ftp->async = 0;
|
||||
|
||||
if (!ftp_putcmd(ftp, "REIN", NULL))
|
||||
return 0;
|
||||
if (!ftp_getresp(ftp) || ftp->resp != 220)
|
||||
@ -1018,6 +1021,59 @@ my_recv(ftpbuf_t *ftp, int s, void *buf, size_t len)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ data_available
|
||||
*/
|
||||
int
|
||||
data_available(ftpbuf_t *ftp, int s)
|
||||
{
|
||||
fd_set read_set;
|
||||
struct timeval tv;
|
||||
int n;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
FD_SET(s, &read_set);
|
||||
n = select(s + 1, &read_set, NULL, NULL, &tv);
|
||||
if (n < 1) {
|
||||
#ifndef PHP_WIN32
|
||||
if (n == 0)
|
||||
errno = ETIMEDOUT;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
/* {{{ data_writeable
|
||||
*/
|
||||
int
|
||||
data_writeable(ftpbuf_t *ftp, int s)
|
||||
{
|
||||
fd_set write_set;
|
||||
struct timeval tv;
|
||||
int n;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1;
|
||||
|
||||
FD_ZERO(&write_set);
|
||||
FD_SET(s, &write_set);
|
||||
n = select(s + 1, NULL, &write_set, NULL, &tv);
|
||||
if (n < 1) {
|
||||
#ifndef PHP_WIN32
|
||||
if (n == 0)
|
||||
errno = ETIMEDOUT;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ my_accept
|
||||
*/
|
||||
int
|
||||
@ -1309,6 +1365,239 @@ bail:
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_async_get
|
||||
*/
|
||||
int
|
||||
ftp_async_get(ftpbuf_t *ftp, php_stream *outstream, const char *path, ftptype_t type, int resumepos)
|
||||
{
|
||||
databuf_t *data = NULL;
|
||||
char *ptr;
|
||||
int lastch;
|
||||
int rcvd;
|
||||
char arg[11];
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (ftp == NULL)
|
||||
goto bail;
|
||||
|
||||
if (!ftp_type(ftp, type)) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if ((data = ftp_getdata(ftp)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (resumepos>0) {
|
||||
sprintf(arg, "%u", resumepos);
|
||||
if (!ftp_putcmd(ftp, "REST", arg)) {
|
||||
goto bail;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ftp_putcmd(ftp, "RETR", path)) {
|
||||
goto bail;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125)) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if ((data = data_accept(data, ftp)) == NULL) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ftp->data = data;
|
||||
ftp->stream = outstream;
|
||||
ftp->lastch = 0;
|
||||
ftp->async = 1;
|
||||
|
||||
return (ftp_async_continue_read(ftp));
|
||||
|
||||
bail:
|
||||
data_close(data);
|
||||
return PHP_FTP_FAILED;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_aget
|
||||
*/
|
||||
int
|
||||
ftp_async_continue_read(ftpbuf_t *ftp)
|
||||
{
|
||||
databuf_t *data = NULL;
|
||||
char *ptr;
|
||||
int lastch;
|
||||
int rcvd;
|
||||
ftptype_t type;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
data = ftp->data;
|
||||
|
||||
/* check if there is already more data */
|
||||
if (!data_available(ftp, data->fd)) {
|
||||
return PHP_FTP_MOREDATA;
|
||||
}
|
||||
|
||||
type = ftp->type;
|
||||
|
||||
lastch = ftp->lastch;
|
||||
if (rcvd = my_recv(ftp, data->fd, data->buf, FTP_BUFSIZE)) {
|
||||
if (rcvd == -1) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (type == FTPTYPE_ASCII) {
|
||||
for (ptr = data->buf; rcvd; rcvd--, ptr++) {
|
||||
if (lastch == '\r' && *ptr != '\n')
|
||||
php_stream_putc(ftp->stream, '\r');
|
||||
if (*ptr != '\r')
|
||||
php_stream_putc(ftp->stream, *ptr);
|
||||
lastch = *ptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
php_stream_write(ftp->stream, data->buf, rcvd);
|
||||
}
|
||||
|
||||
ftp->lastch = lastch;
|
||||
return PHP_FTP_MOREDATA;
|
||||
}
|
||||
|
||||
if (type == FTPTYPE_ASCII && lastch == '\r')
|
||||
php_stream_putc(ftp->stream, '\r');
|
||||
|
||||
data = data_close(data);
|
||||
|
||||
if (php_stream_error(ftp->stream)) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250)) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ftp->async = 0;
|
||||
return PHP_FTP_FINISHED;
|
||||
bail:
|
||||
ftp->async = 0;
|
||||
data_close(data);
|
||||
return PHP_FTP_FAILED;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ftp_async_put
|
||||
*/
|
||||
int
|
||||
ftp_async_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos)
|
||||
{
|
||||
databuf_t *data = NULL;
|
||||
int size;
|
||||
char *ptr;
|
||||
int ch;
|
||||
char arg[11];
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (ftp == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ftp_type(ftp, type))
|
||||
goto bail;
|
||||
|
||||
if ((data = ftp_getdata(ftp)) == NULL)
|
||||
goto bail;
|
||||
|
||||
if (startpos>0) {
|
||||
sprintf(arg, "%u", startpos);
|
||||
if (!ftp_putcmd(ftp, "REST", arg)) {
|
||||
goto bail;
|
||||
}
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 350)) {
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ftp_putcmd(ftp, "STOR", path))
|
||||
goto bail;
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 150 && ftp->resp != 125))
|
||||
goto bail;
|
||||
|
||||
if ((data = data_accept(data, ftp)) == NULL)
|
||||
goto bail;
|
||||
|
||||
ftp->data = data;
|
||||
ftp->stream = instream;
|
||||
ftp->lastch = 0;
|
||||
ftp->async = 1;
|
||||
|
||||
return (ftp_async_continue_write(ftp));
|
||||
|
||||
bail:
|
||||
data_close(data);
|
||||
return PHP_FTP_FAILED;
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ ftp_async_continue_write
|
||||
*/
|
||||
int
|
||||
ftp_async_continue_write(ftpbuf_t *ftp)
|
||||
{
|
||||
int size;
|
||||
char *ptr;
|
||||
int ch;
|
||||
|
||||
/* check if we can write more data */
|
||||
if (!data_writeable(ftp, ftp->data->fd)) {
|
||||
return PHP_FTP_MOREDATA;
|
||||
}
|
||||
|
||||
size = 0;
|
||||
ptr = ftp->data->buf;
|
||||
while ((ch = php_stream_getc(ftp->stream))!=EOF && !php_stream_eof(ftp->stream)) {
|
||||
|
||||
if (ch == '\n' && ftp->type == FTPTYPE_ASCII) {
|
||||
*ptr++ = '\r';
|
||||
size++;
|
||||
}
|
||||
|
||||
*ptr++ = ch;
|
||||
size++;
|
||||
|
||||
/* flush if necessary */
|
||||
if (FTP_BUFSIZE - size < 2) {
|
||||
if (my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size)
|
||||
goto bail;
|
||||
return PHP_FTP_MOREDATA;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (size && my_send(ftp, ftp->data->fd, ftp->data->buf, size) != size)
|
||||
goto bail;
|
||||
|
||||
if (php_stream_error(ftp->stream))
|
||||
goto bail;
|
||||
|
||||
ftp->data = data_close(ftp->data);
|
||||
|
||||
if (!ftp_getresp(ftp) || (ftp->resp != 226 && ftp->resp != 250))
|
||||
goto bail;
|
||||
|
||||
ftp->async = 0;
|
||||
return PHP_FTP_FINISHED;
|
||||
bail:
|
||||
data_close(ftp->data);
|
||||
ftp->async = 0;
|
||||
return PHP_FTP_FAILED;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
#endif /* HAVE_FTP */
|
||||
|
||||
/*
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
#define FTP_DEFAULT_TIMEOUT 90
|
||||
#define FTP_DEFAULT_AUTOSEEK 1
|
||||
#define PHP_FTP_FAILED 0
|
||||
#define PHP_FTP_FINISHED 1
|
||||
#define PHP_FTP_MOREDATA 2
|
||||
|
||||
/* XXX this should be configurable at runtime XXX */
|
||||
#define FTP_BUFSIZE 4096
|
||||
@ -40,6 +43,14 @@ typedef enum ftptype {
|
||||
FTPTYPE_IMAGE
|
||||
} ftptype_t;
|
||||
|
||||
typedef struct databuf
|
||||
{
|
||||
int listener; /* listener socket */
|
||||
int fd; /* data connection */
|
||||
ftptype_t type; /* transfer type */
|
||||
char buf[FTP_BUFSIZE]; /* data buffer */
|
||||
} databuf_t;
|
||||
|
||||
typedef struct ftpbuf
|
||||
{
|
||||
int fd; /* control connection */
|
||||
@ -56,15 +67,15 @@ typedef struct ftpbuf
|
||||
php_sockaddr_storage pasvaddr; /* passive mode address */
|
||||
long timeout_sec; /* User configureable timeout (seconds) */
|
||||
int autoseek; /* User configureable autoseek flag */
|
||||
|
||||
int async; /* asyncronous transfer in progress */
|
||||
databuf_t *data; /* Data connection for asyncrounous transfers */
|
||||
php_stream *stream; /* output stream for asyncrounous transfers */
|
||||
int lastch; /* last char of previous call */
|
||||
int direction; /* recv = 0 / send = 1 */
|
||||
int closestream;/* close or not close stream */
|
||||
} ftpbuf_t;
|
||||
|
||||
typedef struct databuf
|
||||
{
|
||||
int listener; /* listener socket */
|
||||
int fd; /* data connection */
|
||||
ftptype_t type; /* transfer type */
|
||||
char buf[FTP_BUFSIZE]; /* data buffer */
|
||||
} databuf_t;
|
||||
|
||||
|
||||
/* open a FTP connection, returns ftpbuf (NULL on error)
|
||||
@ -156,4 +167,24 @@ int ftp_delete(ftpbuf_t *ftp, const char *path);
|
||||
/* sends a SITE command to the server */
|
||||
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_async_get(ftpbuf_t *ftp, php_stream *outstream, const char *path,
|
||||
ftptype_t type, int resumepos);
|
||||
|
||||
/* 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_async_put(ftpbuf_t *ftp, const char *path, php_stream *instream, ftptype_t type, int startpos);
|
||||
|
||||
/* continues a previous async_(f)get command
|
||||
*/
|
||||
int ftp_async_continue_read(ftpbuf_t *ftp);
|
||||
|
||||
/* continues a previous async_(f)put command
|
||||
*/
|
||||
int ftp_async_continue_write(ftpbuf_t *ftp);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -61,6 +61,11 @@ function_entry php_ftp_functions[] = {
|
||||
PHP_FE(ftp_close, NULL)
|
||||
PHP_FE(ftp_set_option, NULL)
|
||||
PHP_FE(ftp_get_option, NULL)
|
||||
PHP_FE(ftp_async_fget, NULL)
|
||||
PHP_FE(ftp_async_get, NULL)
|
||||
PHP_FE(ftp_async_continue, NULL)
|
||||
PHP_FE(ftp_async_put, NULL)
|
||||
PHP_FE(ftp_async_fput, NULL)
|
||||
PHP_FALIAS(ftp_quit, ftp_close, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
@ -99,6 +104,9 @@ PHP_MINIT_FUNCTION(ftp)
|
||||
REGISTER_LONG_CONSTANT("FTP_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_FAILED", PHP_FTP_FAILED, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_FINISHED", PHP_FTP_FINISHED, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_MOREDATA", PHP_FTP_MOREDATA, CONST_PERSISTENT | CONST_CS);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -448,6 +456,53 @@ PHP_FUNCTION(ftp_fget)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ftp_async_fget(resource stream, resource fp, string remote_file, int mode[, int resumepos])
|
||||
Retrieves a file from the FTP server asynchronly and writes it to an open file */
|
||||
PHP_FUNCTION(ftp_async_fget)
|
||||
{
|
||||
zval *z_ftp, *z_file;
|
||||
ftpbuf_t *ftp;
|
||||
ftptype_t xtype;
|
||||
php_stream *stream;
|
||||
char *file;
|
||||
int file_len, 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;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
|
||||
ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
|
||||
XTYPE(xtype, mode);
|
||||
|
||||
/* ignore autoresume if autoseek is switched off */
|
||||
if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
|
||||
resumepos = 0;
|
||||
}
|
||||
|
||||
if (ftp->autoseek && resumepos) {
|
||||
/* if autoresume is wanted seek to end */
|
||||
if (resumepos == PHP_FTP_AUTORESUME) {
|
||||
php_stream_seek(stream, 0, SEEK_END);
|
||||
resumepos = php_stream_tell(stream);
|
||||
} else {
|
||||
php_stream_seek(stream, resumepos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
/* configuration */
|
||||
ftp->direction = 0; /* recv */
|
||||
ftp->closestream = 0; /* do not close */
|
||||
|
||||
if ((ret = ftp_async_get(ftp, stream, file, xtype, resumepos)) == PHP_FTP_FAILED || php_stream_error(stream)) {
|
||||
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ftp_pasv(resource stream, bool pasv)
|
||||
Turns passive mode on or off */
|
||||
PHP_FUNCTION(ftp_pasv)
|
||||
@ -526,6 +581,107 @@ PHP_FUNCTION(ftp_get)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto inf ftp_async_get(resource stream, string local_file, string remote_file, int mode[, int resume_pos])
|
||||
Retrieves a file from the FTP server asynchronly and writes it to a local file */
|
||||
PHP_FUNCTION(ftp_async_get)
|
||||
{
|
||||
zval *z_ftp;
|
||||
ftpbuf_t *ftp;
|
||||
ftptype_t xtype;
|
||||
php_stream *outstream;
|
||||
char *local, *remote;
|
||||
int local_len, remote_len, mode, resumepos=0, ret;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
|
||||
XTYPE(xtype, mode);
|
||||
|
||||
/* ignore autoresume if autoseek is switched off */
|
||||
if (!ftp->autoseek && resumepos == PHP_FTP_AUTORESUME) {
|
||||
resumepos = 0;
|
||||
}
|
||||
|
||||
if (ftp->autoseek && resumepos) {
|
||||
outstream = php_stream_fopen(local, "rb+", NULL);
|
||||
if (outstream == NULL) {
|
||||
outstream = php_stream_fopen(local, "wb", NULL);
|
||||
}
|
||||
if (outstream != NULL) {
|
||||
/* if autoresume is wanted seek to end */
|
||||
if (resumepos == PHP_FTP_AUTORESUME) {
|
||||
php_stream_seek(outstream, 0, SEEK_END);
|
||||
resumepos = php_stream_tell(outstream);
|
||||
} else {
|
||||
php_stream_seek(outstream, resumepos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outstream = php_stream_fopen(local, "wb", NULL);
|
||||
}
|
||||
|
||||
if (outstream == NULL) {
|
||||
php_error(E_WARNING, "%s(): Error opening %s", get_active_function_name(TSRMLS_C), local);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* configuration */
|
||||
ftp->direction = 0; /* recv */
|
||||
ftp->closestream = 1; /* do close */
|
||||
|
||||
if ((ret = ftp_async_get(ftp, outstream, remote, xtype, resumepos)) == PHP_FTP_FAILED || php_stream_error(outstream)) {
|
||||
php_stream_close(outstream);
|
||||
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
|
||||
RETURN_LONG(PHP_FTP_FAILED);
|
||||
}
|
||||
|
||||
if (ret == PHP_FTP_FINISHED) {
|
||||
php_stream_close(outstream);
|
||||
}
|
||||
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int ftp_async_continue(resource stream)
|
||||
Continues retrieving/sending a file asyncronously */
|
||||
PHP_FUNCTION(ftp_async_continue)
|
||||
{
|
||||
zval *z_ftp;
|
||||
ftpbuf_t *ftp;
|
||||
int ret;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ftp) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
|
||||
|
||||
if (!ftp->async) {
|
||||
php_error(E_WARNING, "%s(): no asyncronous transfer to continue.", get_active_function_name(TSRMLS_C));
|
||||
RETURN_LONG(PHP_FTP_FAILED);
|
||||
}
|
||||
|
||||
if (ftp->direction) {
|
||||
ret=ftp_async_continue_write(ftp);
|
||||
} else {
|
||||
ret=ftp_async_continue_read(ftp);
|
||||
}
|
||||
|
||||
if (ret != PHP_FTP_MOREDATA && ftp->closestream) {
|
||||
php_stream_close(ftp->stream);
|
||||
}
|
||||
|
||||
if (ret == PHP_FTP_FAILED || php_stream_error(ftp->stream)) {
|
||||
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
|
||||
}
|
||||
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ftp_fput(resource stream, string remote_file, resource fp, int mode[, int startpos])
|
||||
Stores a file from an open file to the FTP server */
|
||||
PHP_FUNCTION(ftp_fput)
|
||||
@ -572,6 +728,57 @@ PHP_FUNCTION(ftp_fput)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool ftp_async_fput(resource stream, string remote_file, resource fp, int mode[, int startpos])
|
||||
Stores a file from an open file to the FTP server asyncronly */
|
||||
PHP_FUNCTION(ftp_async_fput)
|
||||
{
|
||||
zval *z_ftp, *z_file;
|
||||
ftpbuf_t *ftp;
|
||||
ftptype_t xtype;
|
||||
int mode, remote_len, startpos=0, ret;
|
||||
php_stream *stream;
|
||||
char *remote;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrl|l", &z_ftp, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
|
||||
ZEND_FETCH_RESOURCE(stream, php_stream*, &z_file, -1, "File-Handle", php_file_le_stream());
|
||||
XTYPE(xtype, mode);
|
||||
|
||||
/* ignore autoresume if autoseek is switched off */
|
||||
if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
|
||||
startpos = 0;
|
||||
}
|
||||
|
||||
if (ftp->autoseek && startpos) {
|
||||
/* if autoresume is wanted ask for remote size */
|
||||
if (startpos == PHP_FTP_AUTORESUME) {
|
||||
startpos = ftp_size(ftp, remote);
|
||||
if (startpos < 0) {
|
||||
startpos = 0;
|
||||
}
|
||||
}
|
||||
if (startpos) {
|
||||
php_stream_seek(stream, startpos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
/* configuration */
|
||||
ftp->direction = 1; /* send */
|
||||
ftp->closestream = 0; /* do not close */
|
||||
|
||||
if (((ret = ftp_async_put(ftp, remote, stream, xtype, startpos)) == PHP_FTP_FAILED) || php_stream_error(stream)) {
|
||||
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto bool ftp_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
|
||||
Stores a file on the FTP server */
|
||||
PHP_FUNCTION(ftp_put)
|
||||
@ -580,7 +787,7 @@ PHP_FUNCTION(ftp_put)
|
||||
ftpbuf_t *ftp;
|
||||
ftptype_t xtype;
|
||||
char *remote, *local;
|
||||
int remote_len, local_len, mode, startpos=0;
|
||||
int remote_len, local_len, mode, startpos=0, ret;
|
||||
php_stream * instream;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
|
||||
@ -625,6 +832,67 @@ PHP_FUNCTION(ftp_put)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto bool ftp_async_put(resource stream, string remote_file, string local_file, int mode[, int startpos])
|
||||
Stores a file on the FTP server */
|
||||
PHP_FUNCTION(ftp_async_put)
|
||||
{
|
||||
zval *z_ftp;
|
||||
ftpbuf_t *ftp;
|
||||
ftptype_t xtype;
|
||||
char *remote, *local;
|
||||
int remote_len, local_len, mode, startpos=0, ret;
|
||||
php_stream * instream;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rssl|l", &z_ftp, &remote, &remote_len, &local, &local_len, &mode, &startpos) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(ftp, ftpbuf_t*, &z_ftp, -1, le_ftpbuf_name, le_ftpbuf);
|
||||
XTYPE(xtype, mode);
|
||||
|
||||
instream = php_stream_fopen(local, "rb", NULL);
|
||||
|
||||
if (instream == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* ignore autoresume if autoseek is switched off */
|
||||
if (!ftp->autoseek && startpos == PHP_FTP_AUTORESUME) {
|
||||
startpos = 0;
|
||||
}
|
||||
|
||||
if (ftp->autoseek && startpos) {
|
||||
/* if autoresume is wanted ask for remote size */
|
||||
if (startpos == PHP_FTP_AUTORESUME) {
|
||||
startpos = ftp_size(ftp, remote);
|
||||
if (startpos < 0) {
|
||||
startpos = 0;
|
||||
}
|
||||
}
|
||||
if (startpos) {
|
||||
php_stream_seek(instream, startpos, SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
/* configuration */
|
||||
ftp->direction = 1; /* send */
|
||||
ftp->closestream = 1; /* do close */
|
||||
|
||||
ret = ftp_async_put(ftp, remote, instream, xtype, startpos);
|
||||
|
||||
if (ret != PHP_FTP_MOREDATA) {
|
||||
php_stream_close(instream);
|
||||
}
|
||||
|
||||
if (ret == PHP_FTP_FAILED || php_stream_error(instream)) {
|
||||
php_error(E_WARNING, "%s(): %s", get_active_function_name(TSRMLS_C), ftp->inbuf);
|
||||
}
|
||||
|
||||
RETURN_LONG(ret);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int ftp_size(resource stream, string filename)
|
||||
Returns the size of the file, or -1 on error */
|
||||
PHP_FUNCTION(ftp_size)
|
||||
|
@ -58,6 +58,11 @@ PHP_FUNCTION(ftp_site);
|
||||
PHP_FUNCTION(ftp_close);
|
||||
PHP_FUNCTION(ftp_set_option);
|
||||
PHP_FUNCTION(ftp_get_option);
|
||||
PHP_FUNCTION(ftp_async_get);
|
||||
PHP_FUNCTION(ftp_async_fget);
|
||||
PHP_FUNCTION(ftp_async_put);
|
||||
PHP_FUNCTION(ftp_async_fput);
|
||||
PHP_FUNCTION(ftp_async_continue);
|
||||
|
||||
#define phpext_ftp_ptr php_ftp_module_ptr
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user