diff options
Diffstat (limited to 'lib/libftp/ftplib.c')
-rw-r--r-- | lib/libftp/ftplib.c | 1625 |
1 files changed, 0 insertions, 1625 deletions
diff --git a/lib/libftp/ftplib.c b/lib/libftp/ftplib.c deleted file mode 100644 index 24908c24..00000000 --- a/lib/libftp/ftplib.c +++ /dev/null @@ -1,1625 +0,0 @@ -/***************************************************************************/ -/* */ -/* ftplib.c - callable ftp access routines */ -/* Copyright (C) 1996-2000 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. */ -/* */ -/***************************************************************************/ - -#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> -#include <time.h> -#if defined(__unix__) || defined(__APPLE__) -#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; - netbuf *data; - 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-1 9/16/00, copyright 1996-2000 Thomas Pfau"; - -GLOBALDEF int ftplib_debug = 0; - -#if defined(__unix__) || defined(VMS) || defined(__APPLE__) -#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 - - /* - * 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) -{ - unsigned 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; -} -/* - * 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; -} - -/* - * 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 - /* we don't use this 'version' variable */ - version=NULL; -} - -/* - * 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"); - if(pse == NULL) { - perror("getservbyname"); - return 0; - } - sin.sin_port = pse->s_port; - } - } - if ((signed)(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->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->cbbytes) - 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; - } - 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); - *nData = NULL; - return 0; - } - (*nData)->ctrl = nControl; - nControl->data = *nData; - if (nControl->cmode == FTPLIB_PORT) - { - if (!FtpAcceptConnection(*nData,nControl)) - { - FtpClose(*nData); - *nData = NULL; - nControl->data = 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 - { - i = socket_wait(nData); - if (i != 1) - return 0; - i = net_read(nData->handle, buf, max); - } - if (i == -1) - return 0; - nData->xfered += i; - if (nData->idlecb && nData->cbbytes) - { - nData->xfered1 += i; - if (nData->xfered1 > nData->cbbytes) - { - if (nData->idlecb(nData, nData->xfered, nData->idlearg) == 0) - return 0; - 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); - } - if (i == -1) - return 0; - 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) -{ - netbuf *ctrl; - switch (nData->dir) - { - case FTPLIB_WRITE: - /* potential problem - if buffer flush fails, how to notify user? */ - if (nData->buf != NULL) - writeline(NULL, 0, nData); - case FTPLIB_READ: - if (nData->buf) - free(nData->buf); - shutdown(nData->handle,2); - net_close(nData->handle); - ctrl = nData->ctrl; - free(nData); - if (ctrl) - { - ctrl->data = NULL; - return(readresp('2', ctrl)); - } - return 1; - case FTPLIB_CONTROL: - if (nData->data) - { - nData->ctrl = NULL; - FtpClose(nData); - } - net_close(nData->handle); - free(nData); - return 0; - } - 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(const char *localfile, const char *path, - netbuf *nControl, int typ, int mode) -{ - int l,c; - char *dbuf; - FILE *local = NULL; - netbuf *nData; - int rv=1; - - if (localfile != NULL) - { - char ac[4] = "a"; - if (typ == FTPLIB_FILE_WRITE) - ac[0] = 'r'; - if (mode == FTPLIB_IMAGE) - ac[1] = 'b'; - local = fopen(localfile, ac); - if (local == NULL) - { - strncpy(nControl->response, strerror(errno), - sizeof(nControl->response)); - return 0; - } - } - 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); - rv = 0; - break; - } - } - else - { - while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0) - if (fwrite(dbuf, 1, l, local) < (unsigned)l) - { - perror("\nlocalfile write"); - rv = 0; - break; - } - } - free(dbuf); - fflush(local); - if (localfile != NULL) - fclose(local); - FtpClose(nData); - return rv; -} - -/* - * FtpNlst - issue an NLST command and write response to output - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpNlst(const char *outputfile, const char *path, - netbuf *nControl) -{ - return FtpXfer(outputfile, 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(const char *outputfile, const char *path, netbuf *nControl) -{ - return FtpXfer(outputfile, 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; -} - -/* - * FtpRestart - issue a REST command - * - * return 1 if successful, 0 otherwise - */ -GLOBALDEF int FtpRestart(int offset, netbuf *nControl) -{ - char cmd[256]; - int rv=1; - - sprintf(cmd,"REST %d",offset); - if (!FtpSendCmd(cmd,'3',nControl)) - 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(const char *outputfile, const char *path, - char mode, netbuf *nControl) -{ - return FtpXfer(outputfile, 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(const char *inputfile, const char *path, char mode, - netbuf *nControl) -{ - return FtpXfer(inputfile, 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); -} - -/* - * HttpConnect - connect to remote server - * - * return 1 if connected, 0 if not - */ -GLOBALREF int HttpConnect(const char *host, unsigned short port, netbuf **nControl) -{ - int sControl; - struct sockaddr_in sin; - struct hostent *phe; - struct servent *pse; - 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(80); -#else - /* we pass a port variable instead (for use with proxies) - * - if ((pse = getservbyname("http","tcp")) == NULL) - { - perror("getservbyname"); - return 0; - } - sin.sin_port = pse->s_port; - */ - sin.sin_port = htons(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 ((signed)(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 (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 = NULL; - 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; - *nControl = ctrl; - return 1; -} - -/* - * HttpSendCmd - send a command - * - * return 1 if proper response received, 0 otherwise - */ -static int HttpSendCmd(const char *cmd, char expresp, netbuf *nControl) -{ - int ret = 0; - char *buf = nControl->response; - /* if (nControl->dir != FTPLIB_CONTROL) - return 0; */ - if (ftplib_debug > 2) - fprintf(stderr,"%s\n",cmd); - if (net_write(nControl->handle,cmd,strlen(cmd)) <= 0) - { - perror("write"); - return 0; - } - while (ret < 256) { - if (socket_wait(nControl) != 1) - return 0; - if (net_read(nControl->handle,buf,1) != 1) { - break; - } - ret++; - if (*buf == '\r') continue; - if (*buf == '\n') break; - buf++; - } - *buf = 0; - if (nControl->response[9] == expresp) - return 1; - return 0; -} - -/* - * HttpXfer - issue a command and transfer data - * - * return 1 if successful, 0 otherwise - */ -static int HttpXfer(const char *localfile, const char *path, int *size, - netbuf *nControl, int typ, int mode) -{ - int l,c; - char *dbuf; - FILE *local = NULL; - int rv=1; - int bytes = 0; - - /* we don't use this 'path' variable */ - path=NULL; - - if (localfile != NULL) - { - char ac[4] = "a"; - if (typ == FTPLIB_FILE_WRITE) - ac[0] = 'r'; - if (mode == FTPLIB_IMAGE) - ac[1] = 'b'; - local = fopen(localfile, ac); - if (local == NULL) - { - strncpy(nControl->response, strerror(errno), - sizeof(nControl->response)); - return 0; - } - } - if (local == NULL) - local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout; - dbuf = malloc(FTPLIB_BUFSIZ); - if (typ == FTPLIB_FILE_WRITE) - { - while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0) - if ((c = FtpWrite(dbuf, l, nControl)) < l) - { - printf("short write: passed %d, wrote %d\n", l, c); - rv = 0; - break; - } - } - else - { - nControl->dir = FTPLIB_READ; - while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nControl)) > 0) { - if ((signed)fwrite(dbuf, 1, l, local) < l) - { - perror("\nlocalfile write"); - rv = 0; - break; - } - bytes += l; - if(size && bytes >= *size) { - break; - } - } - } - free(dbuf); - fflush(local); - if (localfile != NULL) - fclose(local); - free(nControl->data); - return rv; -} - -/* - * HttpGet - issue a GET command and write received data to output - * - * return 1 if successful, 0 otherwise - */ -GLOBALREF int HttpGet(const char *host, const char *outputfile, const char *path, - int *size, netbuf *nControl, unsigned int offset, - const struct tm *mtime1, struct tm *mtime2) -{ - char buf[512]; - - sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\n", path, host); - if (offset > 0) - sprintf(buf, "%sRange: bytes=%d-\r\n", buf, offset); - if (mtime1 && mtime1->tm_year) - { - char mtime[30]; - /* Format: - * "If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\r\n" */ - strftime(mtime, sizeof(mtime), "%a, %d %b %Y %H:%M:%S GMT", mtime1); - sprintf(buf, "%sIf-Modified-Since: %s\r\n", buf, mtime); - } - sprintf(buf, "%s\r\n", buf); - - if (!HttpSendCmd(buf,'2',nControl)) - { - if (nControl->response[9] == '3') - { - /* If the answer from the server is 304, the requested file - * hasn't been modified: no need to retrieve it */ - if (mtime1 && mtime1->tm_year && nControl->response[11] == '4') - return 0; - /* otherwise, it is a redirection */ - printf("redirection not supported\n"); - } - return 0; - } - - while (1) - { - int ret = 0; - char *buf = nControl->response; - while (ret < 256) { - if (socket_wait(nControl) != 1) - return 0; - if (net_read(nControl->handle,buf,1) != 1) - break; - ret++; - if (*buf == '\r') continue; - if (*buf == '\n') break; - buf++; - } - *buf = 0; - if (strstr(nControl->response,"Content-Length")) - { - sscanf(nControl->response,"Content-Length: %d",size); - if (offset > 0) - *size += offset; - } - else if (mtime2 && strstr(nControl->response,"Last-Modified")) - { - /* Format: - * "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\r\n" */ - char *c = nControl->response+20; - int mint, j; - static const int months[12] = { - ('J'<<16)|('a'<<8)|'n', - ('F'<<16)|('e'<<8)|'b', - ('M'<<16)|('a'<<8)|'r', - ('A'<<16)|('p'<<8)|'r', - ('M'<<16)|('a'<<8)|'y', - ('J'<<16)|('u'<<8)|'n', - ('J'<<16)|('u'<<8)|'l', - ('A'<<16)|('u'<<8)|'g', - ('S'<<16)|('e'<<8)|'p', - ('O'<<16)|('c'<<8)|'t', - ('N'<<16)|('o'<<8)|'v', - ('D'<<16)|('e'<<8)|'c' - }; - mtime2->tm_mday = (c[0]-'0')*10+c[1]-'0'; - mint = (c[3]<<16)|(c[4]<<8)|c[5]; - mtime2->tm_mon = 0; - for(j = 0; j < 12; j++) - { - if (mint == months[j]) - { - mtime2->tm_mon = j; - break; - } - } - mtime2->tm_year = ((c[7]-'0')*10+(c[8]-'0')-19)*100; - mtime2->tm_year += (c[9]-'0')*10+c[10]-'0'; - mtime2->tm_hour = (c[12]-'0')*10+c[13]-'0'; - mtime2->tm_min = (c[15]-'0')*10+c[16]-'0'; - mtime2->tm_sec = (c[18]-'0')*10+c[19]-'0'; - } - if (strlen(nControl->response) == 0) - break; - } - - return HttpXfer(outputfile, path, size, nControl, FTPLIB_FILE_READ, FTPLIB_IMAGE); -} - -/* - * HttpQuit - disconnect from remote - * - * return 1 if successful, 0 otherwise - */ -GLOBALREF void HttpQuit(netbuf *nControl) -{ - if(nControl) { - net_close(nControl->handle); - free(nControl); - } -} |