diff options
author | Stefan Esser <sesser@php.net> | 2002-07-26 22:00:25 +0000 |
---|---|---|
committer | Stefan Esser <sesser@php.net> | 2002-07-26 22:00:25 +0000 |
commit | 80e9724ccccf48c477cd21c80406335b472c1cb4 (patch) | |
tree | f1a46a521a53d29e5910d63ecec41d1ba2cd6999 /ext/ftp/ftp.c | |
parent | 8b853592b156768708274b25e20b11c6c05e05ab (diff) | |
download | php-git-80e9724ccccf48c477cd21c80406335b472c1cb4.tar.gz |
[EXPERIMENTAL] Added functions for asynchronous FTP transfers
Diffstat (limited to 'ext/ftp/ftp.c')
-rw-r--r-- | ext/ftp/ftp.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 3effa5fcc4..573b47902f 100644 --- a/ext/ftp/ftp.c +++ b/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 */ /* |