diff options
author | Andrew Skalski <askalski@php.net> | 1999-09-20 14:10:25 +0000 |
---|---|---|
committer | Andrew Skalski <askalski@php.net> | 1999-09-20 14:10:25 +0000 |
commit | 85ca1dfb0856579548339210235a4d5bdf934438 (patch) | |
tree | 2c5b291ac287a0c6d096037e2bb8907edbf23e05 | |
parent | fffbcf529736810b542fd0b3b62229e3ab15902e (diff) | |
download | php-git-85ca1dfb0856579548339210235a4d5bdf934438.tar.gz |
Replaced ftplib because of incompatible license.
-rw-r--r-- | ext/ftp/Makefile.am | 2 | ||||
-rw-r--r-- | ext/ftp/ftp.c | 1093 | ||||
-rw-r--r-- | ext/ftp/ftp.h | 149 | ||||
-rw-r--r-- | ext/ftp/ftplib.c | 1253 | ||||
-rw-r--r-- | ext/ftp/ftplib.h | 129 | ||||
-rw-r--r-- | ext/ftp/php_ftp.c | 631 | ||||
-rw-r--r-- | ext/ftp/php_ftp.h | 38 |
7 files changed, 1350 insertions, 1945 deletions
diff --git a/ext/ftp/Makefile.am b/ext/ftp/Makefile.am index f609671ac4..ea032672b0 100644 --- a/ext/ftp/Makefile.am +++ b/ext/ftp/Makefile.am @@ -2,4 +2,4 @@ INCLUDES=@INCLUDES@ -I@top_srcdir@ -I@top_srcdir@/libzend noinst_LIBRARIES=libphpext_ftp.a -libphpext_ftp_a_SOURCES=ftp.c ftplib.c +libphpext_ftp_a_SOURCES=php_ftp.c ftp.c diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index f955ddab3f..502022ad24 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -29,674 +29,699 @@ */ #include "php.h" -#include "php_globals.h" -#include <ftplib.h> +#if HAVE_FTP + +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> #include "ftp.h" -#if HAVE_FTP +/* reads an ftp response, returns true on success, false on error */ +static int ftp_getresp(ftpbuf_t *ftp); -static int le_netbuf; - - -function_entry php3_ftp_functions[] = { - PHP_FE(ftp_connect, NULL) - PHP_FE(ftp_login, NULL) - PHP_FE(ftp_pwd, NULL) - PHP_FE(ftp_cdup, NULL) - PHP_FE(ftp_chdir, NULL) - PHP_FE(ftp_mkdir, NULL) - PHP_FE(ftp_rmdir, NULL) - PHP_FE(ftp_nlist, NULL) - PHP_FE(ftp_listraw, NULL) - PHP_FE(ftp_systype, NULL) - PHP_FE(ftp_get, NULL) - PHP_FE(ftp_put, NULL) - PHP_FE(ftp_quit, NULL) - {NULL, NULL, NULL} -}; - -php3_module_entry php3_ftp_module_entry = { - "FTP Functions", - php3_ftp_functions, - PHP_MINIT(ftp), - NULL, - NULL, - NULL, - NULL, - STANDARD_MODULE_PROPERTIES -}; - -static void ftp_destructor_netbuf(netbuf *net) -{ - if (net) { - FtpQuit(net); - } -} +/* sets the ftp transfer type */ +static int ftp_type(ftpbuf_t *ftp, ftptype_t type); -PHP_MINIT_FUNCTION(ftp) -{ - le_netbuf = register_list_destructors(ftp_destructor_netbuf, NULL); - REGISTER_MAIN_LONG_CONSTANT("FTP_ASCII", FTPLIB_ASCII, - CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("FTP_BINARY", FTPLIB_BINARY, - CONST_PERSISTENT | CONST_CS); - return SUCCESS; -} +/* opens up a port for ftp transfer */ +static databuf_t* ftp_port(ftpbuf_t *ftp); + +/* accepts the data connection, returns updated data buffer */ +static databuf_t* data_accept(databuf_t *data); + +/* closes the data connection, returns NULL */ +static databuf_t* data_close(databuf_t *data); -/* {{{ proto int ftp_connect(string host) - Open a FTP stream */ -PHP_FUNCTION(ftp_connect) +/* generic file lister */ +static char** ftp_genlist(ftpbuf_t *ftp, + const char *cmd, const char *path); + + +ftpbuf_t* +ftp_open(const char *host, short port) { - pval *arg1; - int id; - netbuf *net; - - /* arg1 - hostname - */ - if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; + int fd = -1; + ftpbuf_t *ftp; + struct sockaddr_in addr; + struct hostent *he; + int size; + + + /* set up the address */ + if ((he = gethostbyname(host)) == NULL) { + herror("gethostbyname"); + return NULL; } - convert_to_string(arg1); + memset(&addr, 0, sizeof(addr)); + memcpy(&addr.sin_addr, he->h_addr, he->h_length); + addr.sin_port = port ? port : htons(21); + + + /* alloc the ftp structure */ + ftp = calloc(1, sizeof(*ftp)); + if (ftp == NULL) { + perror("calloc"); + return NULL; + } /* connect */ - if (!FtpConnect(arg1->value.str.val, &net)) { - php_error(E_WARNING, "FtpConnect: %s", FtpLastResponse(net)); - RETURN_FALSE; + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + perror("socket"); + goto bail; } - id = php3_list_insert(net, le_netbuf); - RETURN_LONG(id); -} -/* }}} */ + if (connect(fd, (struct sockaddr*) &addr, sizeof(addr)) == -1) { + perror("connect"); + goto bail; + } -/* {{{ proto int ftp_login(int stream, string username, string password) - Logs into the FTP server. */ -PHP_FUNCTION(ftp_login) -{ - pval *arg1, *arg2, *arg3; - int id, type; - netbuf *net; - - /* arg1 - netbuf - * arg2 - username - * arg3 - password - */ - if ( ARG_COUNT(ht) != 3 || - getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) - { - WRONG_PARAM_COUNT; + size = sizeof(addr); + if (getsockname(fd, (struct sockaddr*) &addr, &size) == -1) { + perror("getsockname"); + goto bail; } - convert_to_long(arg1); - convert_to_string(arg2); - convert_to_string(arg3); + ftp->localaddr = addr.sin_addr; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; + if ((ftp->fp = fdopen(fd, "r+")) == NULL) { + perror("fdopen"); + goto bail; } - /* log in */ - if (!FtpLogin(arg2->value.str.val, arg3->value.str.val, net)) { - php_error(E_WARNING, "FtpLogin: %s", FtpLastResponse(net)); - RETURN_FALSE; + if (!ftp_getresp(ftp) || ftp->resp != 220) { + goto bail; } - RETURN_TRUE; + return ftp; + +bail: + if (ftp->fp) + fclose(ftp->fp); + else if (fd != -1) + close(fd); + free(ftp); + return NULL; } -/* }}} */ -/* {{{ proto string ftp_pwd(int stream) - Returns the present working directory. */ -PHP_FUNCTION(ftp_pwd) + +ftpbuf_t* +ftp_close(ftpbuf_t *ftp) { - pval *arg1; - int id, type; - netbuf *net; - char buf[512]; - - /* arg1 - netbuf - */ - if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; - } + if (ftp == NULL) + return NULL; + if (ftp->fp) + fclose(ftp->fp); + ftp_gc(ftp); + free(ftp); + return NULL; +} - convert_to_long(arg1); - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } +void +ftp_gc(ftpbuf_t *ftp) +{ + if (ftp == NULL) + return; - if (!FtpPwd(buf, sizeof(buf), net)) { - php_error(E_WARNING, "FtpPwd: %s", FtpLastResponse(net)); - RETURN_FALSE; - } + free(ftp->pwd); + ftp->pwd = NULL; + free(ftp->syst); + ftp->syst = NULL; +} - RETURN_STRING(buf, 1); + +int +ftp_quit(ftpbuf_t *ftp) +{ + if (ftp == NULL) + return 0; + + fprintf(ftp->fp, "QUIT\r\n"); + if (!ftp_getresp(ftp) || ftp->resp != 221) + return 0; + + free(ftp->pwd); + ftp->pwd = NULL; + + return 1; } -/* }}} */ -/* {{{ proto int ftp_cdup(int stream) - Changes to the parent directory */ -PHP_FUNCTION(ftp_cdup) + +int +ftp_login(ftpbuf_t *ftp, const char *user, const char *pass) { - pval *arg1; - int id, type; - netbuf *net; - - /* arg1 - netbuf - */ - if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; - } + if (ftp == NULL) + return 0; + + fprintf(ftp->fp, "USER %s\r\n", user); + if (!ftp_getresp(ftp)) + return 0; + if (ftp->resp == 230) + return 1; + if (ftp->resp != 331) + return 0; + fprintf(ftp->fp, "PASS %s\r\n", pass); + if (!ftp_getresp(ftp)) + return 0; + return (ftp->resp == 230); +} - convert_to_long(arg1); - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } +int +ftp_reinit(ftpbuf_t *ftp) +{ + if (ftp == NULL) + return 0; - if (!FtpCDUp(net)) { - php_error(E_WARNING, "FtpCdup: %s", FtpLastResponse(net)); - RETURN_FALSE; - } + ftp_gc(ftp); + + fprintf(ftp->fp, "REIN\r\n"); + if (!ftp_getresp(ftp) || ftp->resp != 220) + return 0; - RETURN_TRUE; + return 1; } -/* }}} */ -/* {{{ proto int ftp_chdir(int stream, string directory) - Changes directories */ -PHP_FUNCTION(ftp_chdir) + +const char* +ftp_syst(ftpbuf_t *ftp) { - pval *arg1, *arg2; - int id, type; - netbuf *net; - - /* arg1 - netbuf - * arg2 - directory - */ - if ( ARG_COUNT(ht) != 2 || - getParameters(ht, 2, &arg1, &arg2) == FAILURE) - { - WRONG_PARAM_COUNT; - } + char *syst, *end; - convert_to_long(arg1); - convert_to_string(arg2); + if (ftp == NULL) + return NULL; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + /* default to cached value */ + if (ftp->syst) + return ftp->syst; - /* change directories */ - if (!FtpChdir(arg2->value.str.val, net)) { - php_error(E_WARNING, "FtpChdir: %s", FtpLastResponse(net)); - RETURN_FALSE; - } + fprintf(ftp->fp, "SYST\r\n"); + if (!ftp_getresp(ftp) || ftp->resp != 215) + return NULL; + + syst = ftp->inbuf; + if ((end = strchr(syst, ' '))) + *end = 0; + ftp->syst = strdup(syst); + if (end) + *end = ' '; - RETURN_TRUE; + return ftp->syst; } -/* }}} */ -/* {{{ proto int ftp_mkdir(int stream, string directory) - Creates a directory */ -PHP_FUNCTION(ftp_mkdir) + +const char* +ftp_pwd(ftpbuf_t *ftp) { - pval *arg1, *arg2; - int id, type; - netbuf *net; - - /* arg1 - netbuf - * arg2 - directory - */ - if ( ARG_COUNT(ht) != 2 || - getParameters(ht, 2, &arg1, &arg2) == FAILURE) - { - WRONG_PARAM_COUNT; - } + char *pwd, *end; - convert_to_long(arg1); - convert_to_string(arg2); + if (ftp == NULL) + return NULL; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + /* default to cached value */ + if (ftp->pwd) + return ftp->pwd; - /* change directories */ - if (!FtpMkdir(arg2->value.str.val, net)) { - php_error(E_WARNING, "FtpMkdir: %s", FtpLastResponse(net)); - RETURN_FALSE; - } + fprintf(ftp->fp, "PWD\r\n"); + if (!ftp_getresp(ftp) || ftp->resp != 257) + return NULL; + + /* copy out the pwd from response */ + if ((pwd = strchr(ftp->inbuf, '"')) == NULL) + return NULL; + end = strrchr(++pwd, '"'); + *end = 0; + ftp->pwd = strdup(pwd); + *end = '"'; - RETURN_TRUE; + return ftp->pwd; } -/* }}} */ -/* {{{ proto int ftp_rmdir(int stream, string directory) - Removes a directory */ -PHP_FUNCTION(ftp_rmdir) + +int +ftp_chdir(ftpbuf_t *ftp, const char *dir) { - pval *arg1, *arg2; - int id, type; - netbuf *net; - - /* arg1 - netbuf - * arg2 - directory - */ - if ( ARG_COUNT(ht) != 2 || - getParameters(ht, 2, &arg1, &arg2) == FAILURE) - { - WRONG_PARAM_COUNT; - } + if (ftp == NULL) + return 0; - convert_to_long(arg1); - convert_to_string(arg2); + free(ftp->pwd); + ftp->pwd = NULL; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + fprintf(ftp->fp, "CWD %s\r\n", dir); + if (!ftp_getresp(ftp) || ftp->resp != 250) + return 0; + + return 1; +} - /* change directories */ - if (!FtpRmdir(arg2->value.str.val, net)) { - php_error(E_WARNING, "FtpRmdir: %s", FtpLastResponse(net)); - RETURN_FALSE; - } - RETURN_TRUE; +int +ftp_cdup(ftpbuf_t *ftp) +{ + if (ftp == NULL) + return 0; + + free(ftp->pwd); + ftp->pwd = NULL; + + fprintf(ftp->fp, "CDUP\r\n"); + if (!ftp_getresp(ftp) || ftp->resp != 250) + return 0; + + return 1; } -/* }}} */ -/* {{{ proto array ftp_nlist(int stream, string directory) - Returns an array of filenames in the given directory */ -PHP_FUNCTION(ftp_nlist) + +char* +ftp_mkdir(ftpbuf_t *ftp, const char *dir) { - pval *arg1, *arg2; - int id, type; - netbuf *net; - FILE *outfp; - char *entry = NULL; - char *ptr; - long size; - char ch; + char *mkd, *end; + if (ftp == NULL) + return NULL; - /* arg1 - netbuf - * arg2 - directory - */ - if ( ARG_COUNT(ht) != 2 || - getParameters(ht, 2, &arg1, &arg2) == FAILURE) - { - WRONG_PARAM_COUNT; - } + fprintf(ftp->fp, "MKD %s\r\n", dir); + if (!ftp_getresp(ftp) || ftp->resp != 257) + return NULL; - convert_to_long(arg1); - convert_to_string(arg2); + /* copy out the dir from response */ + if ((mkd = strchr(ftp->inbuf, '"')) == NULL) + return NULL; + end = strrchr(++mkd, '"'); + *end = 0; + mkd = strdup(mkd); + *end = '"'; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + return mkd; +} - /* set up a temporary output file */ - if ((outfp = tmpfile()) == NULL) { - php_error(E_WARNING, "error opening tmpfile"); - RETURN_FALSE; - } - /* list to the temporary file */ - if (!FtpNlst(outfp, arg2->value.str.val, net) || ferror(outfp)) { - fclose(outfp); - RETURN_FALSE; - } +int +ftp_rmdir(ftpbuf_t *ftp, const char *dir) +{ + if (ftp == NULL) + return 0; - array_init(return_value); - rewind(outfp); + fprintf(ftp->fp, "RMD %s\r\n", dir); + if (!ftp_getresp(ftp) || ftp->resp != 250) + return 0; - /* Pluck out each file name and save to the return array. */ - do { - /* scan for end of line */ - size = 1; - while ((ch = getc(outfp)) != '\n') { - if (ch == EOF) { - size = -1; - break; - } - size++; - } + return 1; +} - if (size > 0) { - /* seek back to the start of file name and copy - * to a buffer. add the buffer to the array. - */ - fseek(outfp, -size, SEEK_CUR); - entry = emalloc(size); - ptr = entry; - while (--size) - *ptr++ = getc(outfp); - *ptr = 0; - add_next_index_string(return_value, entry, 0); - } +char** +ftp_nlist(ftpbuf_t *ftp, const char *path) +{ + return ftp_genlist(ftp, "NLST", path); +} + - /* eat the \n */ - (void) getc(outfp); - } while (size != -1); - fclose(outfp); +char** +ftp_list(ftpbuf_t *ftp, const char *path) +{ + return ftp_genlist(ftp, "LIST", path); } -/* }}} */ -/* {{{ proto array ftp_listraw(int stream, string directory) - Returns a detailed listing of a directory as an array of output lines */ -PHP_FUNCTION(ftp_listraw) + +int +ftp_getresp(ftpbuf_t *ftp) { - pval *arg1, *arg2; - int id, type; - netbuf *net; - FILE *outfp; - char *entry = NULL; + char tag[4]; + int ch; + char *buf; char *ptr; - long size; - char ch; + if (ftp == NULL) + return 0; + buf = ftp->inbuf; + ftp->resp = 0; - /* arg1 - netbuf - * arg2 - directory - */ - if ( ARG_COUNT(ht) != 2 || - getParameters(ht, 2, &arg1, &arg2) == FAILURE) - { - WRONG_PARAM_COUNT; - } + do { + if (!fread(tag, 4, 1, ftp->fp)) + return 0; + + if (tag[3] == '-') { + while ((ch = getc(ftp->fp)) != '\n') + if (ch == EOF) { + return 0; + } + } + else if (tag[3] == ' ') { + ptr = fgets(buf, FTP_BUFSIZE, ftp->fp); + if (!ptr || !(ptr = strchr(buf, '\n'))) + return 0; + if (ptr > buf && ptr[-1] == '\r') + ptr--; + *ptr = 0; + } + else { + return 0; + } + } while (tag[3] == '-'); - convert_to_long(arg1); - convert_to_string(arg2); - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + /* translate the tag */ + if (!isdigit(tag[0]) || !isdigit(tag[1]) || !isdigit(tag[2])) + return 0; - /* set up a temporary output file */ - if ((outfp = tmpfile()) == NULL) { - php_error(E_WARNING, "error opening tmpfile"); - RETURN_FALSE; - } + ftp->resp = 100 * (tag[0] - '0') + + 10 * (tag[1] - '0') + + (tag[2] - '0'); + return 1; +} - /* list to the temporary file */ - if (!FtpDir(outfp, arg2->value.str.val, net) || ferror(outfp)) { - fclose(outfp); - RETURN_FALSE; - } - array_init(return_value); - rewind(outfp); +int +ftp_type(ftpbuf_t *ftp, ftptype_t type) +{ + char typechar; - /* Pluck out each file name and save to the return array. */ - do { - /* scan for end of line */ - size = 1; - while ((ch = getc(outfp)) != '\n') { - if (ch == EOF) { - size = -1; - break; - } - size++; - } + if (ftp == NULL) + return 0; - if (size > 0) { - /* seek back to the start of file name and copy - * to a buffer. add the buffer to the array. - */ - fseek(outfp, -size, SEEK_CUR); - entry = emalloc(size); - ptr = entry; - while (--size) - *ptr++ = getc(outfp); - *ptr = 0; + if (type == ftp->type) + return 1; - add_next_index_string(return_value, entry, 0); - } + if (type == FTPTYPE_ASCII) + typechar = 'A'; + else if (type == FTPTYPE_IMAGE) + typechar = 'I'; + else + return 0; + + fprintf(ftp->fp, "TYPE %c\r\n", typechar); + if (!ftp_getresp(ftp) || ftp->resp != 200) + return 0; - /* eat the \n */ - (void) getc(outfp); - } while (size != -1); - fclose(outfp); + ftp->type = type; + + return 1; } -/* }}} */ -/* {{{ proto string ftp_systype(int stream) - Returns the system type identifier */ -PHP_FUNCTION(ftp_systype) + +int +ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, ftptype_t type) { - pval *arg1; - int id, type; - netbuf *net; - char buf[64]; + databuf_t *data = NULL; + int ch, lastch; + if (ftp == NULL) + return 0; - /* arg1 - netbuf - * arg2 - directory - */ - if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; - } + if (!ftp_type(ftp, type)) + goto bail; - convert_to_long(arg1); + if ((data = ftp_port(ftp)) == NULL) + goto bail; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + fprintf(ftp->fp, "RETR %s\r\n", path); + if (!ftp_getresp(ftp) || ftp->resp != 150) + goto bail; - if (!FtpSysType(buf, sizeof(buf), net)) { - php_error(E_WARNING, "FtpSysType: %s", FtpLastResponse(net)); - RETURN_FALSE; + if ((data = data_accept(data)) == NULL) + goto bail; + + lastch = 0; + while ((ch = getc(data->fp)) != EOF) { + if (type == FTPTYPE_ASCII) { + if (lastch == '\r' && ch != '\n') + putc('\r', outfp); + if (ch != '\r') + putc(ch, outfp); + lastch = ch; + } + else { + putc(ch, outfp); + } } + if (type == FTPTYPE_ASCII && lastch == '\r') + putc('\r', outfp); + + if (ferror(data->fp) || ferror(outfp)) + goto bail; + + data = data_close(data); - RETURN_STRING(buf, 1); + if (!ftp_getresp(ftp) || ftp->resp != 226) + goto bail; + + return 1; +bail: + data_close(data); + return 0; } -/* }}} */ -/* {{{ proto int ftp_get(int stream, string local_file, string remote_file, int mode) - Retrieves a file from the FTP server. */ -PHP_FUNCTION(ftp_get) + +int +ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, ftptype_t type) { - pval *arg1, *arg2, *arg3, *arg4; - int id, type; - netbuf *net; - FILE *outfp, *tmpfp; - char *entry = NULL; - char *ptr; - long size; - char ch; - - - /* arg1 - netbuf - * arg2 - destination (local) file - * arg3 - source (remote) file - * arg4 - transfer mode - */ - if ( ARG_COUNT(ht) != 4 || - getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) - { - WRONG_PARAM_COUNT; - } + databuf_t *data = NULL; + int ch; - convert_to_long(arg1); - convert_to_string(arg2); - convert_to_string(arg3); - convert_to_long(arg4); + if (ftp == NULL) + return 0; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; - } + if (!ftp_type(ftp, type)) + goto bail; + + if ((data = ftp_port(ftp)) == NULL) + goto bail; - if ( arg4->value.lval != FTPLIB_ASCII && - arg4->value.lval != FTPLIB_BINARY) - { - php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_BINARY"); - RETURN_FALSE; + fprintf(ftp->fp, "STOR %s\r\n", path); + if (!ftp_getresp(ftp) || ftp->resp != 150) + goto bail; + + if ((data = data_accept(data)) == NULL) + goto bail; + + while ((ch = getc(infp)) != EOF) { + if (type == FTPTYPE_ASCII && ch == '\n') + putc('\r', data->fp); + putc(ch, data->fp); } + if (ferror(data->fp) || ferror(infp)) + goto bail; + + data = data_close(data); + + if (!ftp_getresp(ftp) || ftp->resp != 226) + goto bail; + + return 1; +bail: + data_close(data); + return 0; +} + - /* get to temporary file, so if there is an error, no existing - * file gets clobbered - */ - if ((tmpfp = tmpfile()) == NULL) { - php_error(E_WARNING, "error opening tmpfile"); - RETURN_FALSE; +databuf_t* +ftp_port(ftpbuf_t *ftp) +{ + int fd = -1; + databuf_t *data; + struct sockaddr_in addr; + int size; + union { + unsigned long l[1]; + unsigned short s[2]; + unsigned char c[4]; + } ipbox; + + /* alloc the data structure */ + data = calloc(1, sizeof(*data)); + if (data == NULL) { + perror("calloc"); + return NULL; } + data->listener = -1; + data->type = ftp->type; - if ( !FtpGet(tmpfp, arg3->value.str.val, arg4->value.lval, net) || - ferror(tmpfp)) - { - fclose(tmpfp); - php_error(E_WARNING, "FtpGet: %s", FtpLastResponse(net)); - RETURN_FALSE; + /* bind/listen */ + if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + perror("socket"); + goto bail; } - rewind(tmpfp); + /* bind to a local address */ + memset(&addr, 0, sizeof(addr)); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = 0; - if ((outfp = fopen(arg2->value.str.val, "w")) == NULL) { - fclose(tmpfp); - php_error(E_WARNING, "error opening %s", arg2->value.str.val); - RETURN_FALSE; + if (bind(fd, (struct sockaddr*) &addr, sizeof(addr)) == -1) { + perror("bind"); + goto bail; } - while ((ch = getc(tmpfp)) != EOF) - putc(ch, outfp); + size = sizeof(addr); + if (getsockname(fd, (struct sockaddr*) &addr, &size) == -1) { + perror("getsockname"); + goto bail; + } - if (ferror(tmpfp) || ferror(outfp)) { - fclose(tmpfp); - fclose(outfp); - php_error(E_WARNING, "error writing %s", arg2->value.str.val); - RETURN_FALSE; + if (listen(fd, 5) == -1) { + perror("listen"); + goto bail; } - fclose(tmpfp); - fclose(outfp); + data->listener = fd; + + /* send the PORT */ + ipbox.l[0] = ftp->localaddr.s_addr; + fprintf(ftp->fp, "PORT %u,%u,%u,%u,", + ipbox.c[0], ipbox.c[1], ipbox.c[2], ipbox.c[3]); + ipbox.s[0] = addr.sin_port; + fprintf(ftp->fp, "%u,%u\r\n", + ipbox.c[0], ipbox.c[1]); + + if (!ftp_getresp(ftp) || ftp->resp != 200) + goto bail; + + return data; - RETURN_TRUE; +bail: + if (fd != -1) + close(fd); + free(data); + return NULL; } -/* }}} */ -/* {{{ proto int ftp_put(int stream, string remote_file, string local_file, int mode) - Stores a file on the FTP server */ -PHP_FUNCTION(ftp_put) + +databuf_t* +data_accept(databuf_t *data) { - pval *arg1, *arg2, *arg3, *arg4; - int id, type; - netbuf *net; - FILE *infp; - char *entry = NULL; - char *ptr; - long size; - char ch; - - - /* arg1 - netbuf - * arg2 - destination (remote) file - * arg3 - source (local) file - * arg4 - transfer mode - */ - if ( ARG_COUNT(ht) != 4 || - getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) - { - WRONG_PARAM_COUNT; - } + struct sockaddr_in addr; + int size; + int fd; - convert_to_long(arg1); - convert_to_string(arg2); - convert_to_string(arg3); - convert_to_long(arg4); + size = sizeof(addr); + fd = accept(data->listener, (struct sockaddr*) &addr, &size); + close(data->listener); + data->listener = -1; - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; + if (fd == -1) { + free(data); + return NULL; } - if ( arg4->value.lval != FTPLIB_ASCII && - arg4->value.lval != FTPLIB_BINARY) - { - php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_BINARY"); - RETURN_FALSE; + if ((data->fp = fdopen(fd, "r+")) == NULL) { + close(fd); + free(data); + return NULL; } - if ((infp = fopen(arg3->value.str.val, "r")) == NULL) { - php_error(E_WARNING, "error opening %s", arg3->value.str.val); - RETURN_FALSE; - } - if ( !FtpPut(infp, arg2->value.str.val, arg4->value.lval, net) || - ferror(infp)) - { - fclose(infp); - php_error(E_WARNING, "FtpPut: %s", FtpLastResponse(net)); - RETURN_FALSE; - } - fclose(infp); + return data; +} + - RETURN_TRUE; +databuf_t* +data_close(databuf_t *data) +{ + if (data == NULL) + return NULL; + if (data->listener != -1) + close(data->listener); + if (data->fp) + fclose(data->fp); + free(data); + return NULL; } -/* }}} */ -/* {{{ proto int ftp_quit(int stream) - Closes the FTP stream */ -PHP_FUNCTION(ftp_quit) + +char** +ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path) { - pval *arg1; - int id, type; - netbuf *net; - - /* arg1 - netbuf - */ - if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { - WRONG_PARAM_COUNT; + FILE *tmpfp = NULL; + databuf_t *data = NULL; + int ch, lastch; + int size; + int lines; + char **ret = NULL; + char **entry; + char *text; + + + if ((tmpfp = tmpfile()) == NULL) + return NULL; + + if (!ftp_type(ftp, FTPTYPE_ASCII)) + goto bail; + + if ((data = ftp_port(ftp)) == NULL) + goto bail; + + if (path) + fprintf(ftp->fp, "%s %s\r\n", cmd, path); + else + fprintf(ftp->fp, "%s\r\n", cmd); + if (!ftp_getresp(ftp) || ftp->resp != 150) + goto bail; + + /* pull data buffer into tmpfile */ + if ((data = data_accept(data)) == NULL) + goto bail; + + size = 0; + lines = 0; + lastch = 0; + while ((ch = getc(data->fp)) != EOF) { + if (ch == '\n' && lastch == '\r') + lines++; + else + size++; + putc(ch, tmpfp); + lastch = ch; + } + data = data_close(data); + + if (ferror(tmpfp)) + goto bail; + + rewind(tmpfp); + + ret = malloc((lines + 1) * sizeof(char**) + size * sizeof(char*)); + if (ret == NULL) { + perror("malloc"); + goto bail; } - convert_to_long(arg1); - id = arg1->value.lval; - net = php3_list_find(id, &type); - if (!net || type != le_netbuf) { - php_error(E_WARNING, "Unable to find netbuf %d", id); - RETURN_FALSE; + entry = ret; + text = (char*) (ret + lines + 1); + *entry = text; + lastch = 0; + while ((ch = getc(tmpfp)) != EOF) { + if (ch == '\n' && lastch == '\r') { + *(text - 1) = 0; + *++entry = text; + } + else { + *text++ = ch; + } + lastch = ch; } + *entry = NULL; - php3_list_delete(id); + if (ferror(tmpfp)) + goto bail; - RETURN_TRUE; + fclose(tmpfp); + + if (!ftp_getresp(ftp) || ftp->resp != 226) { + free(ret); + return NULL; + } + + return ret; +bail: + data_close(data); + fclose(tmpfp); + free(ret); + return NULL; } -/* }}} */ #endif /* HAVE_FTP */ diff --git a/ext/ftp/ftp.h b/ext/ftp/ftp.h index 1a71ba70a1..f9a2cf549c 100644 --- a/ext/ftp/ftp.h +++ b/ext/ftp/ftp.h @@ -1,38 +1,131 @@ -/* $Id$ */ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: | + | Andrew Skalski <askalski@chek.com> | + +----------------------------------------------------------------------+ + */ -#ifndef _INCLUDED_FTP_H -#define _INCLUDED_FTP_H +#ifndef _FTP_H +#define _FTP_H -#if COMPILE_DL -#undef HAVE_FTP -#define HAVE_FTP 1 -#endif +#include <stdio.h> +#include <netinet/in.h> + + +#define FTP_BUFSIZE 4096 + +typedef enum ftptype { + FTPTYPE_ASCII, + FTPTYPE_IMAGE, +} ftptype_t; + +typedef struct ftpbuf +{ + FILE *fp; /* control connection */ + struct in_addr localaddr; /* local inet address */ + int resp; /* last response code */ + char inbuf[FTP_BUFSIZE]; /* last response text */ + char *pwd; /* cached pwd */ + char *syst; /* cached system type */ + ftptype_t type; /* current transfer type */ +} ftpbuf_t; + +typedef struct databuf +{ + int listener; /* listener socket */ + FILE *fp; /* data connection */ + ftptype_t type; /* transfer type */ +} databuf_t; + + +/* open a FTP connection, returns ftpbuf (NULL on error) + * port is the ftp port in network byte order, or 0 for the default + */ +ftpbuf_t* ftp_open(const char *host, short port); + +/* quits from the ftp session (it still needs to be closed) + * return true on success, false on error + */ +int ftp_quit(ftpbuf_t *ftp); + +/* frees up any cached data held in the ftp buffer */ +void ftp_gc(ftpbuf_t *ftp); + +/* close the FTP connection and return NULL */ +ftpbuf_t* ftp_close(ftpbuf_t *ftp); + +/* logs into the FTP server, returns true on success, false on error */ +int ftp_login(ftpbuf_t *ftp, const char *user, const char *pass); + +/* reinitializes the connection, returns true on success, false on error */ +int ftp_reinit(ftpbuf_t *ftp); + +/* returns the remote system type (NULL on error) */ +const char* ftp_syst(ftpbuf_t *ftp); + +/* returns the present working directory (NULL on error) */ +const char* ftp_pwd(ftpbuf_t *ftp); + +/* changes directories, return true on success, false on error */ +int ftp_chdir(ftpbuf_t *ftp, const char *dir); + +/* changes to parent directory, return true on success, false on error */ +int ftp_cdup(ftpbuf_t *ftp); -#if HAVE_FTP +/* creates a directory, return the directory name on success, NULL on error. + * the return value must be freed + */ +char* ftp_mkdir(ftpbuf_t *ftp, const char *dir); -extern php3_module_entry php3_ftp_module_entry; -#define php3_ftp_module_ptr &php3_ftp_module_entry +/* removes a directory, return true on success, false on error */ +int ftp_rmdir(ftpbuf_t *ftp, const char *dir); -extern PHP_MINIT_FUNCTION(ftp); +/* returns a NULL-terminated array of filenames in the given path + * or NULL on error. the return array must be freed (but don't + * free the array elements) + */ +char** ftp_nlist(ftpbuf_t *ftp, const char *path); -PHP_FUNCTION(ftp_connect); -PHP_FUNCTION(ftp_login); -PHP_FUNCTION(ftp_pwd); -PHP_FUNCTION(ftp_cdup); -PHP_FUNCTION(ftp_chdir); -PHP_FUNCTION(ftp_mkdir); -PHP_FUNCTION(ftp_rmdir); -PHP_FUNCTION(ftp_nlist); -PHP_FUNCTION(ftp_listraw); -PHP_FUNCTION(ftp_systype); -PHP_FUNCTION(ftp_get); -PHP_FUNCTION(ftp_put); -PHP_FUNCTION(ftp_quit); +/* returns a NULL-terminated array of lines returned by the ftp + * LIST command for the given path or NULL on error. the return + * array must be freed (but don't + * free the array elements) + */ +char** ftp_list(ftpbuf_t *ftp, const char *path); -#define phpext_ftp_ptr php3_ftp_module_ptr +/* retrieves a file and saves its contents to outfp + * returns true on success, false on error + */ +int ftp_get(ftpbuf_t *ftp, FILE *outfp, const char *path, + ftptype_t type); -#else -#define php3_ftp_module_ptr NULL -#endif /* HAVE_FTP */ +/* stores the data from infp as a file on the remote server + * returns true on success, false on error + */ +int ftp_put(ftpbuf_t *ftp, const char *path, FILE *infp, + ftptype_t type); #endif diff --git a/ext/ftp/ftplib.c b/ext/ftp/ftplib.c deleted file mode 100644 index 35a06d6cd4..0000000000 --- a/ext/ftp/ftplib.c +++ /dev/null @@ -1,1253 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftplib.c - callable ftp access routines */ -/* Copyright (C) 1996, 1997, 1998 Thomas Pfau, pfau@cnj.digex.net */ -/* 73 Catherine Street, South Bound Brook, NJ, 08880 */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU Library General Public */ -/* License as published by the Free Software Foundation; either */ -/* version 2 of the License, or (at your option) any later version. */ -/* */ -/* This library is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* Library General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU Library General Public */ -/* License along with this progam; if not, write to the */ -/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ -/* Boston, MA 02111-1307, USA. */ -/* */ -/***************************************************************************/ - -/* Adapted by Andrew Skalski <askalski@chek.com> for use with PHP. */ - - -#include "php.h" - -#if HAVE_FTP - -#if defined(__unix__) || defined(__VMS) -#include <unistd.h> -#endif -#if defined(_WIN32) -#include <windows.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#if defined(__unix__) -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#elif defined(VMS) -#include <types.h> -#include <socket.h> -#include <in.h> -#include <netdb.h> -#include <inet.h> -#elif defined(_WIN32) -#include <winsock.h> -#endif - -#define BUILDING_LIBRARY -#include "ftplib.h" - -#if defined(_WIN32) -#define SETSOCKOPT_OPTVAL_TYPE (const char *) -#else -#define SETSOCKOPT_OPTVAL_TYPE (void *) -#endif - -#define FTPLIB_BUFSIZ 8192 -#define ACCEPT_TIMEOUT 30 - -#define FTPLIB_CONTROL 0 -#define FTPLIB_READ 1 -#define FTPLIB_WRITE 2 - -#if !defined FTPLIB_DEFMODE -#define FTPLIB_DEFMODE FTPLIB_PASSIVE -#endif - -struct NetBuf { - char *cput,*cget; - int handle; - int cavail,cleft; - char *buf; - int dir; - netbuf *ctrl; - int cmode; - struct timeval idletime; - FtpCallback idlecb; - void *idlearg; - int xfered; - int cbbytes; - int xfered1; - char response[256]; -}; - -static char *version = - "ftplib Release 3.1 6/xx/98, copyright 1996, 1997, 1998 Thomas Pfau"; - -GLOBALDEF int ftplib_debug = 0; - -#if defined(__unix__) || defined(VMS) -#define net_read read -#define net_write write -#define net_close close -#elif defined(_WIN32) -#define net_read(x,y,z) recv(x,y,z,0) -#define net_write(x,y,z) send(x,y,z,0) -#define net_close closesocket -#endif - -#if defined(NEED_MEMCCPY) -/* - * VAX C does not supply a memccpy routine so I provide my own - */ -void *memccpy(void *dest, const void *src, int c, size_t n) -{ - int i=0; - const unsigned char *ip=src; - unsigned char *op=dest; - - while (i < n) - { - if ((*op++ = *ip++) == c) - break; - i++; - } - if (i == n) - return NULL; - return op; -} -#endif -#if defined(NEED_STRDUP) -/* - * strdup - return a malloc'ed copy of a string - */ -char *strdup(const char *src) -{ - int l = strlen(src) + 1; - char *dst = malloc(l); - if (dst) - strcpy(dst,src); - return dst; -} -#endif - -/* - * socket_wait - wait for socket to receive or flush data - * - * return 1 if no user callback, otherwise, return value returned by - * user callback - */ -static int socket_wait(netbuf *ctl) -{ - fd_set fd,*rfd = NULL,*wfd = NULL; - struct timeval tv; - int rv = 0; - if ((ctl->dir == FTPLIB_CONTROL) || (ctl->idlecb == NULL)) - return 1; - if (ctl->dir == FTPLIB_WRITE) - wfd = &fd; - else - rfd = &fd; - FD_ZERO(&fd); - do - { - FD_SET(ctl->handle,&fd); - tv = ctl->idletime; - rv = select(ctl->handle+1, rfd, wfd, NULL, &tv); - if (rv == -1) - { - rv = 0; - strncpy(ctl->ctrl->response, strerror(errno), - sizeof(ctl->ctrl->response)); - break; - } - else if (rv > 0) - { - rv = 1; - break; - } - } - while ((rv = ctl->idlecb(ctl, ctl->xfered, ctl->idlearg))); - return rv; -} - -/* - * read a line of text - * - * return -1 on error or bytecount - */ -static int readline(char *buf,int max,netbuf *ctl) -{ - int x,retval = 0; - char *end,*bp=buf; - int eof = 0; - - if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ)) - return -1; - if (max == 0) - return 0; - do - { - if (ctl->cavail > 0) - { - x = (max >= ctl->cavail) ? ctl->cavail : max-1; - end = memccpy(bp,ctl->cget,'\n',x); - if (end != NULL) - x = end - bp; - retval += x; - bp += x; - *bp = '\0'; - max -= x; - ctl->cget += x; - ctl->cavail -= x; - if (end != NULL) - { - bp -= 2; - if (strcmp(bp,"\r\n") == 0) - { - *bp++ = '\n'; - *bp++ = '\0'; - --retval; - } - break; - } - } - if (max == 1) - { - *buf = '\0'; - break; - } - if (ctl->cput == ctl->cget) - { - ctl->cput = ctl->cget = ctl->buf; - ctl->cavail = 0; - ctl->cleft = FTPLIB_BUFSIZ; - } - if (eof) - { - if (retval == 0) - retval = -1; - break; - } - if (!socket_wait(ctl)) - return retval; - if ((x = net_read(ctl->handle,ctl->cput,ctl->cleft)) == -1) - { - perror("read"); - retval = -1; - break; - } - if (x == 0) - eof = 1; - ctl->cleft -= x; - ctl->cavail += x; - ctl->cput += x; - } - while (1); - return retval; -} - -/* - * write lines of text - * - * return -1 on error or bytecount - */ -static int writeline(char *buf, int len, netbuf *nData) -{ - int x, nb=0, w; - char *ubp = buf, *nbp; - char lc=0; - - if (nData->dir != FTPLIB_WRITE) - return -1; - nbp = nData->buf; - for (x=0; x < len; x++) - { - if ((*ubp == '\n') && (lc != '\r')) - { - if (nb == FTPLIB_BUFSIZ) - { - if (!socket_wait(nData)) - return x; - w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); - if (w != FTPLIB_BUFSIZ) - { - printf("net_write(1) returned %d, errno = %d\n", w, errno); - return(-1); - } - nb = 0; - } - nbp[nb++] = '\r'; - } - if (nb == FTPLIB_BUFSIZ) - { - if (!socket_wait(nData)) - return x; - w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); - if (w != FTPLIB_BUFSIZ) - { - printf("net_write(2) returned %d, errno = %d\n", w, errno); - return(-1); - } - nb = 0; - } - nbp[nb++] = lc = *ubp++; - } - if (nb) - { - if (!socket_wait(nData)) - return x; - w = net_write(nData->handle, nbp, nb); - if (w != nb) - { - printf("net_write(3) returned %d, errno = %d\n", w, errno); - return(-1); - } - } - return len; -} - -/* - * read a response from the server - * - * return 0 if first char doesn't match - * return 1 if first char matches - */ -static int readresp(char c, netbuf *nControl) -{ - char match[5]; - if (readline(nControl->response,256,nControl) == -1) - { - perror("Control socket read failed"); - return 0; - } - if (ftplib_debug > 1) - fprintf(stderr,"%s",nControl->response); - if (nControl->response[3] == '-') - { - strncpy(match,nControl->response,3); - match[3] = ' '; - match[4] = '\0'; - do - { - if (readline(nControl->response,256,nControl) == -1) - { - perror("Control socket read failed"); - return 0; - } - if (ftplib_debug > 1) - fprintf(stderr,"%s",nControl->response); - } - while (strncmp(nControl->response,match,4)); - } - if (nControl->response[0] == c) - return 1; - return 0; -} - -/* - * FtpInit for stupid operating systems that require it (Windows NT) - */ -GLOBALDEF void FtpInit(void) -{ -#if defined(_WIN32) - WORD wVersionRequested; - WSADATA wsadata; - int err; - wVersionRequested = MAKEWORD(1,1); - if ((err = WSAStartup(wVersionRequested,&wsadata)) != 0) - fprintf(stderr,"Network failed to start: %d\n",err); -#endif -} - -/* - * FtpLastResponse - return a pointer to the last response received - */ -GLOBALDEF char *FtpLastResponse(netbuf *nControl) -{ - if ((nControl) && (nControl->dir == FTPLIB_CONTROL)) - return nControl->response; - return NULL; -} - -/* - * FtpConnect - connect to remote server - * - * return 1 if connected, 0 if not - */ -GLOBALDEF int FtpConnect(const char *host, netbuf **nControl) -{ - int sControl; - struct sockaddr_in sin; - struct hostent *phe; - struct servent *pse; - int on=1; - netbuf *ctrl; - char *lhost; - char *pnum; - - memset(&sin,0,sizeof(sin)); - sin.sin_family = AF_INET; - lhost = strdup(host); - pnum = strchr(lhost,':'); - if (pnum == NULL) - { -#if defined(VMS) - sin.sin_port = htons(21); -#else - if ((pse = getservbyname("ftp","tcp")) == NULL) - { - perror("getservbyname"); - return 0; - } - sin.sin_port = pse->s_port; -#endif - } - else - { - *pnum++ = '\0'; - if (isdigit(*pnum)) - sin.sin_port = htons(atoi(pnum)); - else - { - pse = getservbyname(pnum,"tcp"); - sin.sin_port = pse->s_port; - } - } - if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1) - { - if ((phe = gethostbyname(lhost)) == NULL) - { - perror("gethostbyname"); - return 0; - } - memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length); - } - free(lhost); - sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sControl == -1) - { - perror("socket"); - return 0; - } - if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR, - SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1) - { - perror("setsockopt"); - net_close(sControl); - return 0; - } - if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1) - { - perror("connect"); - net_close(sControl); - return 0; - } - ctrl = calloc(1,sizeof(netbuf)); - if (ctrl == NULL) - { - perror("calloc"); - net_close(sControl); - return 0; - } - ctrl->buf = malloc(FTPLIB_BUFSIZ); - if (ctrl->buf == NULL) - { - perror("calloc"); - net_close(sControl); - free(ctrl); - return 0; - } - ctrl->handle = sControl; - ctrl->dir = FTPLIB_CONTROL; - ctrl->ctrl = NULL; - ctrl->cmode = FTPLIB_DEFMODE; - ctrl->idlecb = NULL; - ctrl->idletime.tv_sec = ctrl->idletime.tv_usec = 0; - ctrl->idlearg = NULL; - ctrl->xfered = 0; - ctrl->xfered1 = 0; - ctrl->cbbytes = 0; - if (readresp('2', ctrl) == 0) - { - net_close(sControl); - free(ctrl->buf); - free(ctrl); - return 0; - } - *nControl = ctrl; - return 1; -} - -/* - * FtpOptions - change connection options - * - * returns 1 if successful, 0 on error - */ -GLOBALDEF int FtpOptions(int opt, long val, netbuf *nControl) -{ - int v,rv=0; - switch (opt) - { - case FTPLIB_CONNMODE: - v = (int) val; - if ((v == FTPLIB_PASSIVE) || (v == FTPLIB_PORT)) - { - nControl->cmode = v; - rv = 1; - } - break; - case FTPLIB_CALLBACK: - nControl->idlecb = (FtpCallback) val; - rv = 1; - break; - case FTPLIB_IDLETIME: - v = (int) val; - rv = 1; - nControl->idletime.tv_sec = v / 1000; - nControl->idletime.tv_usec = (v % 1000) * 1000; - break; - case FTPLIB_CALLBACKARG: - rv = 1; - nControl->idlearg = (void *) val; - break; - case FTPLIB_CALLBACKBYTES: - rv = 1; - nControl->cbbytes = (int) val; - break; - } - return rv; -} - -/* - * FtpSendCmd - send a command and wait for expected response - * - * return 1 if proper response received, 0 otherwise - */ -static int FtpSendCmd(const char *cmd, char expresp, netbuf *nControl) -{ - char buf[256]; - if (nControl->dir != FTPLIB_CONTROL) - return 0; - if (ftplib_debug > 2) - fprintf(stderr,"%s\n",cmd); - if ((strlen(cmd) + 3) > sizeof(buf)) - return 0; - sprintf(buf,"%s\r\n",cmd); - if (net_write(nControl->handle,buf,strlen(buf)) <= 0) - { - perror("write"); - return 0; - } - return readresp(expresp, nControl); -} - -/* - * FtpLogin - log in to remote server - * - * return 1 if logged in, 0 otherwise - */ -GLOBALDEF int FtpLogin(const char *user, const char *pass, netbuf *nControl) -{ - char tempbuf[64]; - - if (((strlen(user) + 7) > sizeof(tempbuf)) || - ((strlen(pass) + 7) > sizeof(tempbuf))) - return 0; - sprintf(tempbuf,"USER %s",user); - if (!FtpSendCmd(tempbuf,'3',nControl)) - { - if (nControl->response[0] == '2') - return 1; - return 0; - } - sprintf(tempbuf,"PASS %s",pass); - return FtpSendCmd(tempbuf,'2',nControl); -} - -/* - * FtpOpenPort - set up data connection - * - * return 1 if successful, 0 otherwise - */ -static int FtpOpenPort(netbuf *nControl, netbuf **nData, int mode, int dir) -{ - int sData; - union { - struct sockaddr sa; - struct sockaddr_in in; - } sin; - struct linger lng = { 0, 0 }; - unsigned int l; - int on=1; - netbuf *ctrl; - char *cp; - unsigned int v[6]; - char buf[256]; - - if (nControl->dir != FTPLIB_CONTROL) - return -1; - if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE)) - { - sprintf(nControl->response, "Invalid direction %d\n", dir); - return -1; - } - if ((mode != FTPLIB_ASCII) && (mode != FTPLIB_IMAGE)) - { - sprintf(nControl->response, "Invalid mode %c\n", mode); - return -1; - } - l = sizeof(sin); - if (nControl->cmode == FTPLIB_PASSIVE) - { - memset(&sin, 0, l); - sin.in.sin_family = AF_INET; - if (!FtpSendCmd("PASV",'2',nControl)) - return -1; - cp = strchr(nControl->response,'('); - if (cp == NULL) - return -1; - cp++; - sscanf(cp,"%u,%u,%u,%u,%u,%u",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]); - sin.sa.sa_data[2] = v[2]; - sin.sa.sa_data[3] = v[3]; - sin.sa.sa_data[4] = v[4]; - sin.sa.sa_data[5] = v[5]; - sin.sa.sa_data[0] = v[0]; - sin.sa.sa_data[1] = v[1]; - } - else - { - if (getsockname(nControl->handle, &sin.sa, &l) < 0) - { - perror("getsockname"); - return 0; - } - } - sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); - if (sData == -1) - { - perror("socket"); - return -1; - } - if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR, - SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1) - { - perror("setsockopt"); - net_close(sData); - return -1; - } - if (setsockopt(sData,SOL_SOCKET,SO_LINGER, - SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1) - { - perror("setsockopt"); - net_close(sData); - return -1; - } - if (nControl->cmode == FTPLIB_PASSIVE) - { - if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1) - { - perror("connect"); - net_close(sData); - return -1; - } - } - else - { - sin.in.sin_port = 0; - if (bind(sData, &sin.sa, sizeof(sin)) == -1) - { - perror("bind"); - net_close(sData); - return 0; - } - if (listen(sData, 1) < 0) - { - perror("listen"); - net_close(sData); - return 0; - } - if (getsockname(sData, &sin.sa, &l) < 0) - return 0; - sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", - (unsigned char) sin.sa.sa_data[2], - (unsigned char) sin.sa.sa_data[3], - (unsigned char) sin.sa.sa_data[4], - (unsigned char) sin.sa.sa_data[5], - (unsigned char) sin.sa.sa_data[0], - (unsigned char) sin.sa.sa_data[1]); - if (!FtpSendCmd(buf,'2',nControl)) - { - net_close(sData); - return 0; - } - } - ctrl = calloc(1,sizeof(netbuf)); - if (ctrl == NULL) - { - perror("calloc"); - net_close(sData); - return -1; - } - if ((mode == 'A') && ((ctrl->buf = malloc(FTPLIB_BUFSIZ)) == NULL)) - { - perror("calloc"); - net_close(sData); - free(ctrl); - return -1; - } - ctrl->handle = sData; - ctrl->dir = dir; - ctrl->ctrl = (nControl->cmode == FTPLIB_PASSIVE) ? nControl : NULL; - ctrl->idletime = nControl->idletime; - ctrl->idlearg = nControl->idlearg; - ctrl->xfered = 0; - ctrl->xfered1 = 0; - ctrl->cbbytes = nControl->cbbytes; - if (ctrl->idletime.tv_sec | ctrl->idletime.tv_usec) - ctrl->idlecb = nControl->idlecb; - else - ctrl->idlecb = NULL; - *nData = ctrl; - return 1; -} - -/* - * FtpAcceptConnection - accept connection from server - * - * return 1 if successful, 0 otherwise - */ -static int FtpAcceptConnection(netbuf *nData, netbuf *nControl) -{ - int sData; - struct sockaddr addr; - unsigned int l; - int i; - struct timeval tv; - fd_set mask; - int rv; - - FD_ZERO(&mask); - FD_SET(nControl->handle, &mask); - FD_SET(nData->handle, &mask); - tv.tv_usec = 0; - tv.tv_sec = ACCEPT_TIMEOUT; - i = nControl->handle; - if (i < nData->handle) - i = nData->handle; - i = select(i+1, &mask, NULL, NULL, &tv); - if (i == -1) - { - strncpy(nControl->response, strerror(errno), - sizeof(nControl->response)); - net_close(nData->handle); - nData->handle = 0; - rv = 0; - } - else if (i == 0) - { - strcpy(nControl->response, "timed out waiting for connection"); - net_close(nData->handle); - nData->handle = 0; - rv = 0; - } - else - { - if (FD_ISSET(nData->handle, &mask)) - { - l = sizeof(addr); - sData = accept(nData->handle, &addr, &l); - i = errno; - net_close(nData->handle); - if (sData > 0) - { - rv = 1; - nData->handle = sData; - nData->ctrl = nControl; - } - else - { - strncpy(nControl->response, strerror(i), - sizeof(nControl->response)); - nData->handle = 0; - rv = 0; - } - } - else if (FD_ISSET(nControl->handle, &mask)) - { - net_close(nData->handle); - nData->handle = 0; - readresp('2', nControl); - rv = 0; - } - } - return rv; -} - -/* - * FtpAccess - return a handle for a data stream - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, - netbuf **nData) -{ - char buf[256]; - int dir; - if ((path == NULL) && - ((typ == FTPLIB_FILE_WRITE) || (typ == FTPLIB_FILE_READ))) - { - sprintf(nControl->response, - "Missing path argument for file transfer\n"); - return 0; - } - sprintf(buf, "TYPE %c", mode); - if (!FtpSendCmd(buf, '2', nControl)) - return 0; - switch (typ) - { - case FTPLIB_DIR: - strcpy(buf,"NLST"); - dir = FTPLIB_READ; - break; - case FTPLIB_DIR_VERBOSE: - strcpy(buf,"LIST"); - dir = FTPLIB_READ; - break; - case FTPLIB_FILE_READ: - strcpy(buf,"RETR"); - dir = FTPLIB_READ; - break; - case FTPLIB_FILE_WRITE: - strcpy(buf,"STOR"); - dir = FTPLIB_WRITE; - break; - default: - sprintf(nControl->response, "Invalid open type %d\n", typ); - return 0; - } - if (path != NULL) - { - int i = strlen(buf); - buf[i++] = ' '; - if ((strlen(path) + i) >= sizeof(buf)) - return 0; - strcpy(&buf[i],path); - } - if (FtpOpenPort(nControl, nData, mode, dir) == -1) - return 0; - if (!FtpSendCmd(buf, '1', nControl)) - { - FtpClose(*nData, 0); - *nData = NULL; - return 0; - } - if (nControl->cmode == FTPLIB_PORT) - { - if (!FtpAcceptConnection(*nData,nControl)) - { - FtpClose(*nData, 0); - *nData = NULL; - return 0; - } - } - return 1; -} - -/* - * FtpRead - read from a data connection - */ -GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData) -{ - int i; - if (nData->dir != FTPLIB_READ) - return 0; - if (nData->buf) - i = readline(buf, max, nData); - else - { - socket_wait(nData); - i = net_read(nData->handle, buf, max); - } - nData->xfered += i; - if (nData->idlecb && nData->cbbytes) - { - nData->xfered1 += i; - if (nData->xfered1 > nData->cbbytes) - { - nData->idlecb(nData, nData->xfered, nData->idlearg); - nData->xfered1 = 0; - } - } - return i; -} - -/* - * FtpWrite - write to a data connection - */ -GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData) -{ - int i; - if (nData->dir != FTPLIB_WRITE) - return 0; - if (nData->buf) - i = writeline(buf, len, nData); - else - { - socket_wait(nData); - i = net_write(nData->handle, buf, len); - } - nData->xfered += i; - if (nData->idlecb && nData->cbbytes) - { - nData->xfered1 += i; - if (nData->xfered1 > nData->cbbytes) - { - nData->idlecb(nData, nData->xfered, nData->idlearg); - nData->xfered1 = 0; - } - } - return i; -} - -/* - * FtpClose - close a data connection - */ -GLOBALDEF int FtpClose(netbuf *nData, int readResp) -{ - netbuf *ctrl; - if (nData->dir == FTPLIB_WRITE) - { - if (nData->buf != NULL) - writeline(NULL, 0, nData); - } - else if (nData->dir != FTPLIB_READ) - return 0; - if (nData->buf) - free(nData->buf); - shutdown(nData->handle,2); - net_close(nData->handle); - ctrl = nData->ctrl; - free(nData); - if (readResp && ctrl) - return(readresp('2', ctrl)); - return 1; -} - -/* - * FtpSite - send a SITE command - * - * return 1 if command successful, 0 otherwise - */ -GLOBALDEF int FtpSite(const char *cmd, netbuf *nControl) -{ - char buf[256]; - - if ((strlen(cmd) + 7) > sizeof(buf)) - return 0; - sprintf(buf,"SITE %s",cmd); - if (!FtpSendCmd(buf,'2',nControl)) - return 0; - return 1; -} - -/* - * FtpSysType - send a SYST command - * - * Fills in the user buffer with the remote system type. If more - * information from the response is required, the user can parse - * it out of the response buffer returned by FtpLastResponse(). - * - * return 1 if command successful, 0 otherwise - */ -GLOBALDEF int FtpSysType(char *buf, int max, netbuf *nControl) -{ - int l = max; - char *b = buf; - char *s; - if (!FtpSendCmd("SYST",'2',nControl)) - return 0; - s = &nControl->response[4]; - while ((--l) && (*s != ' ')) - *b++ = *s++; - *b++ = '\0'; - return 1; -} - -/* - * FtpMkdir - create a directory at server - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpMkdir(const char *path, netbuf *nControl) -{ - char buf[256]; - - if ((strlen(path) + 6) > sizeof(buf)) - return 0; - sprintf(buf,"MKD %s",path); - if (!FtpSendCmd(buf,'2', nControl)) - return 0; - return 1; -} - -/* - * FtpChdir - change path at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpChdir(const char *path, netbuf *nControl) -{ - char buf[256]; - - if ((strlen(path) + 6) > sizeof(buf)) - return 0; - sprintf(buf,"CWD %s",path); - if (!FtpSendCmd(buf,'2',nControl)) - return 0; - return 1; -} - -/* - * FtpCDUp - move to parent directory at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpCDUp(netbuf *nControl) -{ - if (!FtpSendCmd("CDUP",'2',nControl)) - return 0; - return 1; -} - -/* - * FtpRmdir - remove directory at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpRmdir(const char *path, netbuf *nControl) -{ - char buf[256]; - - if ((strlen(path) + 6) > sizeof(buf)) - return 0; - sprintf(buf,"RMD %s",path); - if (!FtpSendCmd(buf,'2',nControl)) - return 0; - return 1; -} - -/* - * FtpPwd - get working directory at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpPwd(char *path, int max, netbuf *nControl) -{ - int l = max; - char *b = path; - char *s; - if (!FtpSendCmd("PWD",'2',nControl)) - return 0; - s = strchr(nControl->response, '"'); - if (s == NULL) - return 0; - s++; - while ((--l) && (*s) && (*s != '"')) - *b++ = *s++; - *b++ = '\0'; - return 1; -} - -/* - * FtpXfer - issue a command and transfer data - * - * return 1 if successful, 0 otherwise - */ -static int FtpXfer(FILE *local, const char *path, - netbuf *nControl, int typ, int mode) -{ - int l,c; - char *dbuf; - netbuf *nData; - - if (local == NULL) - local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout; - if (!FtpAccess(path, typ, mode, nControl, &nData)) - return 0; - dbuf = malloc(FTPLIB_BUFSIZ); - if (typ == FTPLIB_FILE_WRITE) - { - while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0) - if ((c = FtpWrite(dbuf, l, nData)) < l) - printf("short write: passed %d, wrote %d\n", l, c); - } - else - { - while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0) - if (fwrite(dbuf, 1, l, local) <= 0) - { - perror("localfile write"); - break; - } - } - free(dbuf); - fflush(local); - return FtpClose(nData, 1); -} - -/* - * FtpNlst - issue an NLST command and write response to output - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpNlst(FILE *outfp, const char *path, netbuf *nControl) -{ - return FtpXfer(outfp, path, nControl, FTPLIB_DIR, FTPLIB_ASCII); -} - -/* - * FtpDir - issue a LIST command and write response to output - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpDir(FILE *outfp, const char *path, netbuf *nControl) -{ - return FtpXfer(outfp, path, nControl, FTPLIB_DIR_VERBOSE, FTPLIB_ASCII); -} - -/* - * FtpSize - determine the size of a remote file - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpSize(const char *path, int *size, char mode, netbuf *nControl) -{ - char cmd[256]; - int resp,sz,rv=1; - - if ((strlen(path) + 7) > sizeof(cmd)) - return 0; - sprintf(cmd, "TYPE %c", mode); - if (!FtpSendCmd(cmd, '2', nControl)) - return 0; - sprintf(cmd,"SIZE %s",path); - if (!FtpSendCmd(cmd,'2',nControl)) - rv = 0; - else - { - if (sscanf(nControl->response, "%d %d", &resp, &sz) == 2) - *size = sz; - else - rv = 0; - } - return rv; -} - -/* - * FtpModDate - determine the modification date of a remote file - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl) -{ - char buf[256]; - int rv = 1; - - if ((strlen(path) + 7) > sizeof(buf)) - return 0; - sprintf(buf,"MDTM %s",path); - if (!FtpSendCmd(buf,'2',nControl)) - rv = 0; - else - strncpy(dt, &nControl->response[4], max); - return rv; -} - -/* - * FtpGet - issue a GET command and write received data to output - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpGet(FILE *outfp, const char *path, char mode, netbuf *nControl) -{ - return FtpXfer(outfp, path, nControl, FTPLIB_FILE_READ, mode); -} - -/* - * FtpPut - issue a PUT command and send data from input - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpPut(FILE *infp, const char *path, char mode, netbuf *nControl) -{ - return FtpXfer(infp, path, nControl, FTPLIB_FILE_WRITE, mode); -} - -/* - * FtpRename - rename a file at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpRename(const char *src, const char *dst, netbuf *nControl) -{ - char cmd[256]; - - if (((strlen(src) + 7) > sizeof(cmd)) || - ((strlen(dst) + 7) > sizeof(cmd))) - return 0; - sprintf(cmd,"RNFR %s",src); - if (!FtpSendCmd(cmd,'3',nControl)) - return 0; - sprintf(cmd,"RNTO %s",dst); - if (!FtpSendCmd(cmd,'2',nControl)) - return 0; - return 1; -} - -/* - * FtpDelete - delete a file at remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpDelete(const char *fnm, netbuf *nControl) -{ - char cmd[256]; - - if ((strlen(fnm) + 7) > sizeof(cmd)) - return 0; - sprintf(cmd,"DELE %s",fnm); - if (!FtpSendCmd(cmd,'2', nControl)) - return 0; - return 1; -} - -/* - * FtpQuit - disconnect from remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF void FtpQuit(netbuf *nControl) -{ - if (nControl->dir != FTPLIB_CONTROL) - return; - FtpSendCmd("QUIT",'2',nControl); - net_close(nControl->handle); - free(nControl->buf); - free(nControl); -} - -#endif /* HAVE_FTP */ diff --git a/ext/ftp/ftplib.h b/ext/ftp/ftplib.h deleted file mode 100644 index e71e18ff36..0000000000 --- a/ext/ftp/ftplib.h +++ /dev/null @@ -1,129 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftplib.h - header file for callable ftp access routines */ -/* Copyright (C) 1996, 1997 Thomas Pfau, pfau@cnj.digex.net */ -/* 73 Catherine Street, South Bound Brook, NJ, 08880 */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it under the terms of the GNU Library General Public */ -/* License as published by the Free Software Foundation; either */ -/* version 2 of the License, or (at your option) any later version. */ -/* */ -/* This library is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* Library General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU Library General Public */ -/* License along with this progam; if not, write to the */ -/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ -/* Boston, MA 02111-1307, USA. */ -/* */ -/***************************************************************************/ - -/* Adapted by Andrew Skalski <askalski@chek.com> for use with PHP. */ - -#if !defined(__FTPLIB_H) -#define __FTPLIB_H - -#if defined(__unix__) || defined(VMS) -#define GLOBALDEF -#define GLOBALREF extern -#elif defined(_WIN32) -#if defined BUILDING_LIBRARY -#define GLOBALDEF __declspec(dllexport) -#define GLOBALREF __declspec(dllexport) -#else -#define GLOBALREF __declspec(dllimport) -#endif -#endif - -/* FtpAccess() type codes */ -#define FTPLIB_DIR 1 -#define FTPLIB_DIR_VERBOSE 2 -#define FTPLIB_FILE_READ 3 -#define FTPLIB_FILE_WRITE 4 - -/* FtpAccess() mode codes */ -#define FTPLIB_ASCII 'A' -#define FTPLIB_IMAGE 'I' -#define FTPLIB_TEXT FTPLIB_ASCII -#define FTPLIB_BINARY FTPLIB_IMAGE - -/* connection modes */ -#define FTPLIB_PASSIVE 1 -#define FTPLIB_PORT 2 - -/* connection option names */ -#define FTPLIB_CONNMODE 1 -#define FTPLIB_CALLBACK 2 -#define FTPLIB_IDLETIME 3 -#define FTPLIB_CALLBACKARG 4 -#define FTPLIB_CALLBACKBYTES 5 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct NetBuf netbuf; -typedef int (*FtpCallback)(netbuf *nControl, int xfered, void *arg); - -#define _FTPLIB_NO_COMPAT 1 - -/* v1 compatibility stuff */ -#if !defined(_FTPLIB_NO_COMPAT) -netbuf *DefaultNetbuf; - -#define ftplib_lastresp FtpLastResponse(DefaultNetbuf) -#define ftpInit FtpInit -#define ftpOpen(x) FtpConnect(x, &DefaultNetbuf) -#define ftpLogin(x,y) FtpLogin(x, y, DefaultNetbuf) -#define ftpSite(x) FtpSite(x, DefaultNetbuf) -#define ftpMkdir(x) FtpMkdir(x, DefaultNetbuf) -#define ftpChdir(x) FtpChdir(x, DefaultNetbuf) -#define ftpRmdir(x) FtpRmdir(x, DefaultNetbuf) -#define ftpNlst(x, y) FtpNlst(x, y, DefaultNetbuf) -#define ftpDir(x, y) FtpDir(x, y, DefaultNetbuf) -#define ftpGet(x, y, z) FtpGet(x, y, z, DefaultNetbuf) -#define ftpPut(x, y, z) FtpPut(x, y, z, DefaultNetbuf) -#define ftpRename(x, y) FtpRename(x, y, DefaultNetbuf) -#define ftpDelete(x) FtpDelete(x, DefaultNetbuf) -#define ftpQuit() FtpQuit(DefaultNetbuf) -#endif /* (_FTPLIB_NO_COMPAT) */ -/* end v1 compatibility stuff */ - -GLOBALREF int ftplib_debug; -GLOBALREF void FtpInit(void); -GLOBALREF char *FtpLastResponse(netbuf *nControl); -GLOBALREF int FtpConnect(const char *host, netbuf **nControl); -GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl); -GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl); -GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, - netbuf **nData); -GLOBALREF int FtpRead(void *buf, int max, netbuf *nData); -GLOBALREF int FtpWrite(void *buf, int len, netbuf *nData); -GLOBALREF int FtpClose(netbuf *nData, int readResp); -GLOBALREF int FtpSite(const char *cmd, netbuf *nControl); -GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl); -GLOBALREF int FtpMkdir(const char *path, netbuf *nControl); -GLOBALREF int FtpChdir(const char *path, netbuf *nControl); -GLOBALREF int FtpCDUp(netbuf *nControl); -GLOBALREF int FtpRmdir(const char *path, netbuf *nControl); -GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl); -GLOBALREF int FtpNlst(FILE *outfp, const char *path, netbuf *nControl); -GLOBALREF int FtpDir(FILE *outfp, const char *path, netbuf *nControl); -GLOBALREF int FtpSize(const char *path, int *size, char mode, netbuf *nControl); -GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl); -GLOBALREF int FtpGet(FILE *outfp, const char *path, char mode, - netbuf *nControl); -GLOBALREF int FtpPut(FILE *infp, const char *path, char mode, - netbuf *nControl); -GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl); -GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl); -GLOBALREF void FtpQuit(netbuf *nControl); - -#ifdef __cplusplus -}; -#endif - -#endif /* __FTPLIB_H */ diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c new file mode 100644 index 0000000000..cd3b019193 --- /dev/null +++ b/ext/ftp/php_ftp.c @@ -0,0 +1,631 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: | + | Andrew Skalski <askalski@chek.com> | + +----------------------------------------------------------------------+ + */ + +#include "php.h" +#include "php_globals.h" + +#if HAVE_FTP + +#include "php_ftp.h" +#include "ftp.h" + +static int le_ftpbuf; + + +function_entry php3_ftp_functions[] = { + PHP_FE(ftp_connect, NULL) + PHP_FE(ftp_login, NULL) + PHP_FE(ftp_pwd, NULL) + PHP_FE(ftp_cdup, NULL) + PHP_FE(ftp_chdir, NULL) + PHP_FE(ftp_mkdir, NULL) + PHP_FE(ftp_rmdir, NULL) + PHP_FE(ftp_nlist, NULL) + PHP_FE(ftp_listraw, NULL) + PHP_FE(ftp_systype, NULL) + PHP_FE(ftp_get, NULL) + PHP_FE(ftp_put, NULL) + PHP_FE(ftp_quit, NULL) + {NULL, NULL, NULL} +}; + +php3_module_entry php3_ftp_module_entry = { + "FTP Functions", + php3_ftp_functions, + PHP_MINIT(ftp), + NULL, + NULL, + NULL, + NULL, + STANDARD_MODULE_PROPERTIES +}; + +static void ftp_destructor_ftpbuf(ftpbuf_t *ftp) +{ + ftp_close(ftp); +} + +PHP_MINIT_FUNCTION(ftp) +{ + le_ftpbuf = register_list_destructors(ftp_destructor_ftpbuf, NULL); + REGISTER_MAIN_LONG_CONSTANT("FTP_ASCII", FTPTYPE_ASCII, + CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("FTP_BINARY", FTPTYPE_IMAGE, + CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("FTP_IMAGE", FTPTYPE_IMAGE, + CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("FTP_TEXT", FTPTYPE_ASCII, + CONST_PERSISTENT | CONST_CS); + return SUCCESS; +} + +/* {{{ proto int ftp_connect(string host) + Open a FTP stream */ +PHP_FUNCTION(ftp_connect) +{ + pval *arg1; + int id; + ftpbuf_t *ftp; + + /* arg1 - hostname + */ + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string(arg1); + + /* connect */ + ftp = ftp_open(arg1->value.str.val, 0); + if (ftp == NULL) { + php_error(E_WARNING, "ftp_connect: %s", ftp->inbuf); + RETURN_FALSE; + } + + id = php3_list_insert(ftp, le_ftpbuf); + RETURN_LONG(id); +} +/* }}} */ + +/* {{{ proto int ftp_login(int stream, string username, string password) + Logs into the FTP server. */ +PHP_FUNCTION(ftp_login) +{ + pval *arg1, *arg2, *arg3; + int id, type; + ftpbuf_t *ftp; + + /* arg1 - ftp + * arg2 - username + * arg3 - password + */ + if ( ARG_COUNT(ht) != 3 || + getParameters(ht, 3, &arg1, &arg2, &arg3) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_string(arg3); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* log in */ + if (!ftp_login(ftp, arg2->value.str.val, arg3->value.str.val)) { + php_error(E_WARNING, "ftp_login: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string ftp_pwd(int stream) + Returns the present working directory. */ +PHP_FUNCTION(ftp_pwd) +{ + pval *arg1; + int id, type; + ftpbuf_t *ftp; + const char *pwd; + + /* arg1 - ftp + */ + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + pwd = ftp_pwd(ftp); + if (pwd == NULL) { + php_error(E_WARNING, "ftp_pwd: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_STRING((char*) pwd, 1); +} +/* }}} */ + +/* {{{ proto int ftp_cdup(int stream) + Changes to the parent directory */ +PHP_FUNCTION(ftp_cdup) +{ + pval *arg1; + int id, type; + ftpbuf_t *ftp; + + /* arg1 - ftp + */ + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + if (!ftp_cdup(ftp)) { + php_error(E_WARNING, "ftp_cdup: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int ftp_chdir(int stream, string directory) + Changes directories */ +PHP_FUNCTION(ftp_chdir) +{ + pval *arg1, *arg2; + int id, type; + ftpbuf_t *ftp; + + /* arg1 - ftp + * arg2 - directory + */ + if ( ARG_COUNT(ht) != 2 || + getParameters(ht, 2, &arg1, &arg2) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* change directories */ + if (!ftp_chdir(ftp, arg2->value.str.val)) { + php_error(E_WARNING, "ftp_chdir: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto string ftp_mkdir(int stream, string directory) + Creates a directory */ +PHP_FUNCTION(ftp_mkdir) +{ + pval *arg1, *arg2; + int id, type; + ftpbuf_t *ftp; + char *ret, *tmp; + + /* arg1 - ftp + * arg2 - directory + */ + if ( ARG_COUNT(ht) != 2 || + getParameters(ht, 2, &arg1, &arg2) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* change directories */ + tmp = ftp_mkdir(ftp, arg2->value.str.val); + if (tmp == NULL) { + php_error(E_WARNING, "ftp_mkdir: %s", ftp->inbuf); + RETURN_FALSE; + } + + if ((ret = estrdup(tmp)) == NULL) { + free(tmp); + php_error(E_WARNING, "estrdup failed"); + RETURN_FALSE; + } + + RETURN_STRING(ret, 0); +} +/* }}} */ + +/* {{{ proto int ftp_rmdir(int stream, string directory) + Removes a directory */ +PHP_FUNCTION(ftp_rmdir) +{ + pval *arg1, *arg2; + int id, type; + ftpbuf_t *ftp; + + /* arg1 - ftp + * arg2 - directory + */ + if ( ARG_COUNT(ht) != 2 || + getParameters(ht, 2, &arg1, &arg2) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* change directories */ + if (!ftp_rmdir(ftp, arg2->value.str.val)) { + php_error(E_WARNING, "ftp_rmdir: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto array ftp_nlist(int stream, string directory) + Returns an array of filenames in the given directory */ +PHP_FUNCTION(ftp_nlist) +{ + pval *arg1, *arg2; + int id, type; + ftpbuf_t *ftp; + char **nlist, **ptr; + + /* arg1 - ftp + * arg2 - directory + */ + if ( ARG_COUNT(ht) != 2 || + getParameters(ht, 2, &arg1, &arg2) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* get list of files */ + nlist = ftp_nlist(ftp, arg2->value.str.val); + if (nlist == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + for (ptr = nlist; *ptr; ptr++) + add_next_index_string(return_value, *ptr, 1); + free(nlist); +} +/* }}} */ + +/* {{{ proto array ftp_listraw(int stream, string directory) + Returns a detailed listing of a directory as an array of output lines */ +PHP_FUNCTION(ftp_listraw) +{ + pval *arg1, *arg2; + int id, type; + ftpbuf_t *ftp; + char **llist, **ptr; + + /* arg1 - ftp + * arg2 - directory + */ + if ( ARG_COUNT(ht) != 2 || + getParameters(ht, 2, &arg1, &arg2) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + /* get directory listing */ + llist = ftp_list(ftp, arg2->value.str.val); + if (llist == NULL) { + RETURN_FALSE; + } + + array_init(return_value); + for (ptr = llist; *ptr; ptr++) + add_next_index_string(return_value, *ptr, 1); + free(llist); +} +/* }}} */ + +/* {{{ proto string ftp_systype(int stream) + Returns the system type identifier */ +PHP_FUNCTION(ftp_systype) +{ + pval *arg1; + int id, type; + ftpbuf_t *ftp; + const char *syst; + + + /* arg1 - ftp + * arg2 - directory + */ + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + syst = ftp_syst(ftp); + if (syst == NULL) { + php_error(E_WARNING, "ftp_syst: %s", ftp->inbuf); + RETURN_FALSE; + } + + RETURN_STRING((char*) syst, 1); +} +/* }}} */ + +/* {{{ proto int ftp_get(int stream, string local_file, string remote_file, int mode) + Retrieves a file from the FTP server. */ +PHP_FUNCTION(ftp_get) +{ + pval *arg1, *arg2, *arg3, *arg4; + int id, type; + ftpbuf_t *ftp; + ftptype_t xtype; + FILE *outfp, *tmpfp; + int ch; + + + /* arg1 - ftp + * arg2 - destination (local) file + * arg3 - source (remote) file + * arg4 - transfer mode + */ + if ( ARG_COUNT(ht) != 4 || + getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_string(arg3); + convert_to_long(arg4); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + if ( arg4->value.lval != FTPTYPE_ASCII && + arg4->value.lval != FTPTYPE_IMAGE) + { + php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_IMAGE"); + RETURN_FALSE; + } + + xtype = arg4->value.lval; + + /* get to temporary file, so if there is an error, no existing + * file gets clobbered + */ + if ((tmpfp = tmpfile()) == NULL) { + php_error(E_WARNING, "error opening tmpfile"); + RETURN_FALSE; + } + + if ( !ftp_get(ftp, tmpfp, arg3->value.str.val, xtype) || + ferror(tmpfp)) + { + fclose(tmpfp); + php_error(E_WARNING, "ftp_get: %s", ftp->inbuf); + RETURN_FALSE; + } + + if ((outfp = fopen(arg2->value.str.val, "w")) == NULL) { + fclose(tmpfp); + php_error(E_WARNING, "error opening %s", arg2->value.str.val); + RETURN_FALSE; + } + + rewind(tmpfp); + while ((ch = getc(tmpfp)) != EOF) + putc(ch, outfp); + + if (ferror(tmpfp) || ferror(outfp)) { + fclose(tmpfp); + fclose(outfp); + php_error(E_WARNING, "error writing %s", arg2->value.str.val); + RETURN_FALSE; + } + + fclose(tmpfp); + fclose(outfp); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int ftp_put(int stream, string remote_file, string local_file, int mode) + Stores a file on the FTP server */ +PHP_FUNCTION(ftp_put) +{ + pval *arg1, *arg2, *arg3, *arg4; + int id, type; + ftpbuf_t *ftp; + ftptype_t xtype; + FILE *infp; + + + /* arg1 - ftp + * arg2 - destination (remote) file + * arg3 - source (local) file + * arg4 - transfer mode + */ + if ( ARG_COUNT(ht) != 4 || + getParameters(ht, 4, &arg1, &arg2, &arg3, &arg4) == FAILURE) + { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + convert_to_string(arg2); + convert_to_string(arg3); + convert_to_long(arg4); + + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + if ( arg4->value.lval != FTPTYPE_ASCII && + arg4->value.lval != FTPTYPE_IMAGE) + { + php_error(E_WARNING, "arg4 must be FTP_ASCII or FTP_IMAGE"); + RETURN_FALSE; + } + + xtype = arg4->value.lval; + + if ((infp = fopen(arg3->value.str.val, "r")) == NULL) { + php_error(E_WARNING, "error opening %s", arg3->value.str.val); + RETURN_FALSE; + } + if ( !ftp_put(ftp, arg2->value.str.val, infp, xtype) || + ferror(infp)) + { + fclose(infp); + php_error(E_WARNING, "ftp_put: %s", ftp->inbuf); + RETURN_FALSE; + } + fclose(infp); + + RETURN_TRUE; +} +/* }}} */ + +/* {{{ proto int ftp_quit(int stream) + Closes the FTP stream */ +PHP_FUNCTION(ftp_quit) +{ + pval *arg1; + int id, type; + ftpbuf_t *ftp; + + /* arg1 - ftp + */ + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &arg1) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(arg1); + id = arg1->value.lval; + ftp = php3_list_find(id, &type); + if (!ftp || type != le_ftpbuf) { + php_error(E_WARNING, "Unable to find ftpbuf %d", id); + RETURN_FALSE; + } + + php3_list_delete(id); + + RETURN_TRUE; +} +/* }}} */ + +#endif /* HAVE_FTP */ diff --git a/ext/ftp/php_ftp.h b/ext/ftp/php_ftp.h new file mode 100644 index 0000000000..1a71ba70a1 --- /dev/null +++ b/ext/ftp/php_ftp.h @@ -0,0 +1,38 @@ +/* $Id$ */ + +#ifndef _INCLUDED_FTP_H +#define _INCLUDED_FTP_H + +#if COMPILE_DL +#undef HAVE_FTP +#define HAVE_FTP 1 +#endif + +#if HAVE_FTP + +extern php3_module_entry php3_ftp_module_entry; +#define php3_ftp_module_ptr &php3_ftp_module_entry + +extern PHP_MINIT_FUNCTION(ftp); + +PHP_FUNCTION(ftp_connect); +PHP_FUNCTION(ftp_login); +PHP_FUNCTION(ftp_pwd); +PHP_FUNCTION(ftp_cdup); +PHP_FUNCTION(ftp_chdir); +PHP_FUNCTION(ftp_mkdir); +PHP_FUNCTION(ftp_rmdir); +PHP_FUNCTION(ftp_nlist); +PHP_FUNCTION(ftp_listraw); +PHP_FUNCTION(ftp_systype); +PHP_FUNCTION(ftp_get); +PHP_FUNCTION(ftp_put); +PHP_FUNCTION(ftp_quit); + +#define phpext_ftp_ptr php3_ftp_module_ptr + +#else +#define php3_ftp_module_ptr NULL +#endif /* HAVE_FTP */ + +#endif |