From 3e450bfc664c55e1e185953ba47e83f2b981ee68 Mon Sep 17 00:00:00 2001 From: llornkcor Date: Tue, 12 Mar 2002 01:17:36 +0000 Subject: added opieftp- the opief tp client --- (limited to 'noncore') diff --git a/noncore/net/opieftp/ftplib.c b/noncore/net/opieftp/ftplib.c new file mode 100644 index 0000000..b9ca746 --- a/dev/null +++ b/noncore/net/opieftp/ftplib.c @@ -0,0 +1,1294 @@ +/***************************************************************************/ +/* 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 +#endif +#if defined(_WIN32) +#include +#endif +#include +#include +#include +#include +#include +#if defined(__unix__) +#include +#include +#include +#include +#include +#include +#elif defined(VMS) +#include +#include +#include +#include +#include +#elif defined(_WIN32) +#include +#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) +#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->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] = "w"; + 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) <= 0) + { + perror("localfile 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; +} + +/* + * 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); +} diff --git a/noncore/net/opieftp/ftplib.h b/noncore/net/opieftp/ftplib.h new file mode 100644 index 0000000..75a90ae --- a/dev/null +++ b/noncore/net/opieftp/ftplib.h @@ -0,0 +1,124 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/***************************************************************************/ + +#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); + +/* 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); +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(const char *output, const char *path, netbuf *nControl); +GLOBALREF int FtpDir(const char *output, 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(const char *output, const char *path, char mode, + netbuf *nControl); +GLOBALREF int FtpPut(const char *input, 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/noncore/net/opieftp/inputDialog.cpp b/noncore/net/opieftp/inputDialog.cpp new file mode 100644 index 0000000..22205d3 --- a/dev/null +++ b/noncore/net/opieftp/inputDialog.cpp @@ -0,0 +1,40 @@ +/**************************************************************************** + inputDialog.cpp + ------------------- +** Created: Sat Mar 9 23:33:09 2002 + copyright : (C) 2002 by ljp + email : ljp@llornkcor.com + * This program is free software; you can redistribute it and/or modify * + * it under the terms of 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. * + ***************************************************************************/ + +#include "inputDialog.h" + +#include +#include +#include +#include +#include + + +InputDialog::InputDialog( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) +{ + if ( !name ) + setName( "InputDialog" ); + resize( 234, 50 ); + setMaximumSize( QSize( 240, 50 ) ); + setCaption( tr(name ) ); + + LineEdit1 = new QLineEdit( this, "LineEdit1" ); + LineEdit1->setGeometry( QRect( 10, 10, 216, 22 ) ); +} + +InputDialog::~InputDialog() +{ + inputText= LineEdit1->text(); + +} + diff --git a/noncore/net/opieftp/inputDialog.h b/noncore/net/opieftp/inputDialog.h new file mode 100644 index 0000000..2cd8285 --- a/dev/null +++ b/noncore/net/opieftp/inputDialog.h @@ -0,0 +1,34 @@ +/*************************************************************************** + inputDialog.h + ------------------- +** Created: Sat Mar 9 23:33:09 2002 + copyright : (C) 2002 by ljp + email : ljp@llornkcor.com + * This program is free software; you can redistribute it and/or modify * + * it under the terms of 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. * + ***************************************************************************/ +#ifndef INPUTDIALOG_H +#define INPUTDIALOG_H + +#include +#include +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QLineEdit; + +class InputDialog : public QDialog +{ + Q_OBJECT + +public: + InputDialog( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~InputDialog(); + QString inputText; + QLineEdit* LineEdit1; + +}; + +#endif // INPUTDIALOG_H diff --git a/noncore/net/opieftp/main.cpp b/noncore/net/opieftp/main.cpp new file mode 100644 index 0000000..28676e1 --- a/dev/null +++ b/noncore/net/opieftp/main.cpp @@ -0,0 +1,31 @@ + +/*************************************************************************** + main.cpp - description + ------------------- + begin : March 10, 2002 + copyright : (C) 2002 by llornkcor + email : ljp@llornkcor.com + * This program is free software; you can redistribute it and/or modify * + * it under the terms of 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. * + ***************************************************************************/ +#include +#include +#include +#include +#include + + + +#include "opieftp.h" + +int main(int argc, char *argv[]) +{ + QPEApplication a(argc, argv); + + OpieFtp opieftp; + a.showMainWidget( &opieftp); + return a.exec(); +} + diff --git a/noncore/net/opieftp/opie-opieftp.control b/noncore/net/opieftp/opie-opieftp.control new file mode 100644 index 0000000..d5b31eb --- a/dev/null +++ b/noncore/net/opieftp/opie-opieftp.control @@ -0,0 +1,10 @@ +Files: bin/opieftp pics/opieftp apps/Applications/opieftp.desktop +Priority: optional +Package: opieftp +Section: opie/applications +Maintainer: L.J. Potter +Architecture: arm +Version: $QPE_VERSION-$SUB_VERSION +Depends: opie-base ($QPE_VERSION) +Description: OpieFtp + The ftp client for the Opie environment. diff --git a/noncore/net/opieftp/opieftp.cpp b/noncore/net/opieftp/opieftp.cpp new file mode 100644 index 0000000..151be84 --- a/dev/null +++ b/noncore/net/opieftp/opieftp.cpp @@ -0,0 +1,719 @@ +/*************************************************************************** + opieftp.cpp + ------------------- +** Created: Sat Mar 9 23:33:09 2002 + copyright : (C) 2002 by ljp + email : ljp@llornkcor.com + * This program is free software; you can redistribute it and/or modify * + * it under the terms of 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. * + ***************************************************************************/ + +#include "opieftp.h" +#include "ftplib.h" +#include "inputDialog.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +QProgressBar *ProgressBar; +static netbuf *conn=NULL; + +static int log_progress(netbuf *ctl, int xfered, void *arg) +{ + int fsz = *(int *)arg; + int pct = (xfered * 100) / fsz; +// printf("%3d%%\r", pct); +// fflush(stdout); + ProgressBar->setProgress(xfered); + qApp->processEvents(); + return 1; +} + +OpieFtp::OpieFtp( ) + : QMainWindow( ) +{ + resize( 236, 290 ); + setMaximumSize( QSize( 240, 320 ) ); + setCaption( tr( "OpieFtp" ) ); + + connect( qApp,SIGNAL( aboutToQuit()),SLOT( cleanUp()) ); + + QPEMenuBar *menuBar = new QPEMenuBar( this ); + connectionMenu = new QPopupMenu( this ); + localMenu = new QPopupMenu( this ); + remoteMenu = new QPopupMenu( this ); + menuBar->insertItem( tr( "Connection" ), connectionMenu); + menuBar->insertItem( tr( "Local" ), localMenu); + menuBar->insertItem( tr( "Remote" ), remoteMenu); + + connectionMenu->insertItem( tr( "New" ), this, SLOT( newConnection() )); + connectionMenu->insertItem( tr( "Connect" ), this, SLOT( connector() )); + connectionMenu->insertItem( tr( "Disconnect" ), this, SLOT( disConnector() )); + + localMenu->insertItem( tr( "Show Hidden Files" ), this, SLOT( showHidden() )); + localMenu->insertItem( tr( "Upload" ), this, SLOT( localUpload() )); + localMenu->insertItem( tr( "Make Directory" ), this, SLOT( localMakDir() )); + localMenu->insertItem( tr( "Rename" ), this, SLOT( localRename() )); + localMenu->insertSeparator(); + localMenu->insertItem( tr( "Delete" ), this, SLOT( localDelete() )); + + remoteMenu->insertItem( tr( "Download" ), this, SLOT( remoteDownload() )); + remoteMenu->insertItem( tr( "Make Directory" ), this, SLOT( remoteMakDir() )); + remoteMenu->insertItem( tr( "Rename" ), this, SLOT( remoteRename() )); + remoteMenu->insertSeparator(); + remoteMenu->insertItem( tr( "Delete" ), this, SLOT( remoteDelete() )); + + ProgressBar = new QProgressBar( this, "ProgressBar" ); + ProgressBar->setGeometry( QRect( 5, 268, 231, 15 ) ); + + TabWidget = new QTabWidget( this, "TabWidget2" ); + TabWidget->setGeometry( QRect( 3, 25, 240, 220 ) ); + TabWidget->setTabShape(QTabWidget::Triangular); + + tab = new QWidget( TabWidget, "tab" ); + + Local_View = new QListView( tab, "Local_View" ); + Local_View->setGeometry( QRect( 3, 2, 225, 195 ) ); + Local_View->addColumn( "File",120); + Local_View->addColumn( "Size",-1); + Local_View->setColumnAlignment(1,QListView::AlignRight); + Local_View->addColumn( "Date",-1); + Local_View->setColumnAlignment(2,QListView::AlignRight); + Local_View->setAllColumnsShowFocus(TRUE); + QPEApplication::setStylusOperation( Local_View->viewport(),QPEApplication::RightOnHold); + + connect( Local_View, SIGNAL( doubleClicked( QListViewItem*)), + this,SLOT( localListClicked(QListViewItem *)) ); + connect( Local_View, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint&, int)), + this,SLOT( ListPressed(int, QListViewItem *, const QPoint&, int)) ); + + TabWidget->insertTab( tab, tr( "Local" ) ); + + tab_2 = new QWidget( TabWidget, "tab_2" ); + + Remote_View = new QListView( tab_2, "Remote_View" ); + Remote_View->setGeometry( QRect( 3, 2, 225, 195 ) ); + Remote_View->addColumn( "File",120); + Remote_View->addColumn( "Size",-1); + Remote_View->setColumnAlignment(1,QListView::AlignRight); + Remote_View->addColumn( "Date",-1); + Remote_View->setColumnAlignment(2,QListView::AlignRight); + Remote_View->setAllColumnsShowFocus(TRUE); + QPEApplication::setStylusOperation( Remote_View->viewport(),QPEApplication::RightOnHold); + + connect( Remote_View, SIGNAL( doubleClicked( QListViewItem*)), + this,SLOT( remoteListClicked(QListViewItem *)) ); + connect( Remote_View, SIGNAL( mouseButtonPressed( int, QListViewItem *, const QPoint&, int)), + this,SLOT( RemoteListPressed(int, QListViewItem *, const QPoint&, int)) ); + + TabWidget->insertTab( tab_2, tr( "Remote" ) ); + + tab_3 = new QWidget( TabWidget, "tab_3" ); + + TextLabel1 = new QLabel( tab_3, "TextLabel1" ); + TextLabel1->setGeometry( QRect( 10, 10, 60, 16 ) ); + TextLabel1->setText( tr( "Username" ) ); + UsernameComboBox = new QComboBox( FALSE, tab_3, "UsernameComboBox" ); + UsernameComboBox->setGeometry( QRect( 10, 25, 196, 21 ) ); + UsernameComboBox->setEditable(TRUE); + UsernameComboBox->lineEdit()->setText("root"); + + TextLabel2 = new QLabel( tab_3, "TextLabel2" ); + TextLabel2->setGeometry( QRect( 10, 50, 65, 16 ) ); + TextLabel2->setText( tr( "Password" ) ); + PasswordEdit = new QLineEdit( "", tab_3, "PasswordComboBox" ); + PasswordEdit->setGeometry( QRect( 10, 65, 195, 16 ) ); + PasswordEdit->setEchoMode(QLineEdit::Password); + + TextLabel3 = new QLabel( tab_3, "TextLabel3" ); + TextLabel3->setGeometry( QRect( 10, 90, 95, 16 ) ); + TextLabel3->setText( tr( "Remote server" ) ); + ServerComboBox = new QComboBox( FALSE, tab_3, "ServerComboBox" ); + ServerComboBox->setGeometry( QRect( 10, 105, 195, 21 ) ); + ServerComboBox->setEditable(TRUE); + ServerComboBox->lineEdit()->setText( tr( "192.168.129.201" ) ); + + QLabel *TextLabel5 = new QLabel( tab_3, "TextLabel5" ); + TextLabel5->setGeometry( QRect( 10, 130, 95, 16 ) ); + TextLabel5->setText( tr( "Remote path" ) ); + remotePath = new QLineEdit( "/", tab_3, "remotePath" ); + remotePath->setGeometry( QRect( 10, 145, 195, 16 ) ); + remotePath->setText( currentRemoteDir = "/"); + + TextLabel4 = new QLabel( tab_3, "TextLabel4" ); + TextLabel4->setGeometry( QRect( 10, 170, 30, 21 ) ); + TextLabel4->setText( tr( "Port" ) ); + PortSpinBox = new QSpinBox( tab_3, "PortSpinBox" ); + PortSpinBox->setGeometry( QRect( 40, 175, 75, 20 ) ); + PortSpinBox->setButtonSymbols( QSpinBox::UpDownArrows ); + PortSpinBox->setMaxValue(32786); + PortSpinBox->setValue( 4242 ); + TabWidget->insertTab( tab_3, tr( "Config" ) ); + + connect(TabWidget,SIGNAL(currentChanged(QWidget *)), + this,SLOT(tabChanged(QWidget*))); + + currentDir.setFilter( QDir::Files | QDir::Dirs/* | QDir::Hidden*/ | QDir::All); + currentDir.setPath( QDir::currentDirPath()); +// currentDir.setSorting(/* QDir::Size*/ /*| QDir::Reversed | */QDir::DirsFirst); + currentPathEdit = new QLineEdit( "/", this, "currentPathEdit" ); + currentPathEdit->setGeometry( QRect( 5, 248, 220, 18 ) ); + currentPathEdit->setText( currentDir.canonicalPath()); + connect( currentPathEdit,SIGNAL(returnPressed()),this,SLOT(currentPathEditChanged())); + + filterStr="*"; + populateLocalView(); +} + +OpieFtp::~OpieFtp() +{ +} + +void OpieFtp::cleanUp() +{ + if(conn) + FtpQuit(conn); + QFile f("./._temp"); + if(f.exists()) + f. remove(); +} + +void OpieFtp::tabChanged(QWidget *w) +{ + if (TabWidget->currentPageIndex() == 0) { + currentPathEdit->setText( currentDir.canonicalPath()); + } else if (TabWidget->currentPageIndex() == 1) { + currentPathEdit->setText( currentRemoteDir ); + } +} + +void OpieFtp::localUpload() +{ + int fsz; + QCopEnvelope ( "QPE/System", "busy()" ); + qApp->processEvents(); + QString strItem = Local_View->currentItem()->text(0); + QString localFile = currentDir.canonicalPath()+"/"+strItem; + QString remoteFile= currentRemoteDir+strItem; + QFileInfo fi(localFile); + if( !fi.isDir()) { + fsz=fi.size(); + ProgressBar->setTotalSteps(fsz); + + FtpOptions(FTPLIB_CALLBACK, (long) log_progress, conn); + FtpOptions(FTPLIB_IDLETIME, (long) 1000, conn); + FtpOptions(FTPLIB_CALLBACKARG, (long) &fsz, conn); + FtpOptions(FTPLIB_CALLBACKBYTES, (long) fsz/10, conn); + qDebug("Put: %s, %s",localFile.latin1(),remoteFile.latin1()); + + if( !FtpPut( localFile.latin1(), remoteFile.latin1(),FTPLIB_IMAGE, conn ) ) { + QString msg; + msg.sprintf("Unable to upload\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + FtpQuit(conn); + } + ProgressBar->reset(); + } else { + QMessageBox::message("Note","Cannot upload directories"); + } + TabWidget->setCurrentPage(1); + populateRemoteView(); + QCopEnvelope ( "QPE/System", "notBusy()" ); +} + +void OpieFtp::remoteDownload() +{ + int fsz; + QCopEnvelope ( "QPE/System", "busy()" ); + qApp->processEvents(); + QString strItem = Remote_View->currentItem()->text(0); + QString localFile = currentDir.canonicalPath()+"/"+strItem; + QString remoteFile= currentRemoteDir+strItem; + if (!FtpSize( remoteFile.latin1(), &fsz, FTPLIB_ASCII, conn)) + fsz = 0; + QString temp; + temp.sprintf( remoteFile+" "+" %dkb", fsz); + + ProgressBar->setTotalSteps(fsz); + FtpOptions(FTPLIB_CALLBACK, (long) log_progress, conn); + FtpOptions(FTPLIB_IDLETIME, (long) 1000, conn); + FtpOptions(FTPLIB_CALLBACKARG, (long) &fsz, conn); + FtpOptions(FTPLIB_CALLBACKBYTES, (long) fsz/10, conn); + qDebug("Get: %s, %s",localFile.latin1(),remoteFile.latin1()); + + if(!FtpGet( localFile.latin1(), remoteFile.latin1(),FTPLIB_IMAGE, conn ) ) { + QString msg; + msg.sprintf("Unable to download \n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + FtpQuit(conn); + } + ProgressBar->reset(); + TabWidget->setCurrentPage(0); + populateLocalView(); + QCopEnvelope ( "QPE/System", "notBusy()" ); +} + + +void OpieFtp::newConnection() +{ + TabWidget->setCurrentPage(2); +} + +void OpieFtp::connector() +{ + QCopEnvelope ( "QPE/System", "busy()" ); + qApp->processEvents(); + currentRemoteDir=remotePath->text(); + if(ServerComboBox->currentText().isEmpty()) { + QMessageBox::warning(this,"Ftp","Please set the server info","Ok",0,0); + TabWidget->setCurrentPage(2); + ServerComboBox->setFocus(); + return; + } + FtpInit(); + TabWidget->setCurrentPage(1); + QString ftp_host = ServerComboBox->currentText(); + QString ftp_user = UsernameComboBox->currentText(); + QString ftp_pass = PasswordEdit->text(); + QString port=PortSpinBox->cleanText(); + port.stripWhiteSpace(); + + if(ftp_host.find("ftp://",0, TRUE) != -1 ) + ftp_host=ftp_host.right(ftp_host.length()-6); + ftp_host+=":"+port; + if (!FtpConnect( ftp_host.latin1(), &conn)) { + QMessageBox::message("Note","Unable to connect to\n"+ftp_host); + return ; + } + if (!FtpLogin( ftp_user.latin1(), ftp_pass.latin1(),conn )) { + QString msg; + msg.sprintf("Unable to log in\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + FtpQuit(conn); + return ; + } + remoteDirList("/") ; + setCaption(ftp_host); + QCopEnvelope ( "QPE/System", "notBusy()" ); +} + +void OpieFtp::disConnector() +{ + FtpQuit(conn); + setCaption("OpieFtp"); + currentRemoteDir="/"; + Remote_View->clear(); +} + +bool OpieFtp::remoteDirList(const QString &dir) +{ + QCopEnvelope ( "QPE/System", "busy()" ); + if (!FtpDir( "./._temp", dir.latin1(), conn) ) { + QString msg; + msg.sprintf("Unable to list the directory\n"+dir+"\n%s",FtpLastResponse(conn) ); + QMessageBox::message("Note",msg); + FtpQuit(conn); + return false; + } + populateRemoteView(); + QCopEnvelope ( "QPE/System", "notBusy()" ); + return true; +} + +bool OpieFtp::remoteChDir(const QString &dir) +{ + QCopEnvelope ( "QPE/System", "busy()" ); + if (!FtpChdir( dir.latin1(), conn )) { + QString msg; + msg.sprintf("Unable to change directories "+dir+"\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + FtpQuit(conn); + QCopEnvelope ( "QPE/System", "notBusy()" ); + return FALSE; + } + QCopEnvelope ( "QPE/System", "notBusy()" ); + return TRUE; +} + +void OpieFtp::populateLocalView() +{ + Local_View->clear(); + currentDir.setSorting(/* QDir::Size*/ /*| QDir::Reversed | */QDir::DirsFirst); + currentDir.setMatchAllDirs(TRUE); + currentDir.setNameFilter(filterStr); + QString fileL, fileS, fileDate; + const QFileInfoList *list = currentDir.entryInfoList( /*QDir::All*/ /*, QDir::SortByMask*/); + QFileInfoListIterator it(*list); + QFileInfo *fi; + while ( (fi=it.current()) ) { + if (fi->isSymLink() ){ + QString symLink=fi->readLink(); +// qDebug("Symlink detected "+symLink); + QFileInfo sym( symLink); + fileS.sprintf( "%10li", sym.size() ); + fileL.sprintf( "%s -> %s", sym.fileName().data(),sym.absFilePath().data() ); + fileDate = sym.lastModified().toString(); + } else { +// qDebug("Not a dir: "+currentDir.canonicalPath()+fileL); + fileS.sprintf( "%10li", fi->size() ); + fileL.sprintf( "%s",fi->fileName().data() ); + fileDate= fi->lastModified().toString(); + if( QDir(QDir::cleanDirPath(currentDir.canonicalPath()+"/"+fileL)).exists() ) { + fileL+="/"; +// qDebug( fileL); + } + } + item= new QListViewItem( Local_View,fileL,fileS, fileDate); + ++it; + } + Local_View->setSorting( 3,FALSE); + currentPathEdit->setText( currentDir.canonicalPath() ); +} + +bool OpieFtp::populateRemoteView() +{ + Remote_View->clear(); + QFile tmp("./._temp"); + QString s, File_Name; + QString fileL, fileS, fileDate; + new QListViewItem( Remote_View, "../"); + if (tmp.open(IO_ReadOnly)) { + QTextStream t( &tmp ); // use a text stream + while ( !t.eof()) { + s = t.readLine(); + fileL = s.right(s.length()-55); + fileL = fileL.stripWhiteSpace(); + if(s.left(1) == "d") + fileL = fileL+"/"; + fileS = s.mid( 30, 42-30); + fileS = fileS.stripWhiteSpace(); + fileDate = s.mid( 42, 55-42); + fileDate = fileDate.stripWhiteSpace(); + if(fileL.find("total",0,TRUE) == -1) + new QListViewItem( Remote_View, fileL, fileS, fileDate); + } + tmp.close(); + } + return true; +} + +void OpieFtp::remoteListClicked(QListViewItem *selectedItem) +{ + QCopEnvelope ( "QPE/System", "busy()" ); + QString strItem=selectedItem->text(0); + strItem=strItem.simplifyWhiteSpace(); + if(strItem == "../") { + if( FtpCDUp( conn) == 0) { + QString msg; + msg.sprintf("Unable to change directories \n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + char path[256]; + if( FtpPwd( path,sizeof(path),conn) == 0) { + QString msg; + msg.sprintf("Unable to get working dir\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + currentRemoteDir=path; + } else { + if(strItem.find("/",0,TRUE) != -1) { + if( remoteChDir( (const QString &)currentRemoteDir+strItem) ==0) { + QString msg; + msg.sprintf("Unable to change directories \n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + currentRemoteDir = currentRemoteDir+strItem; + } else { + qDebug("download "+strItem); + } + } + if(currentRemoteDir.right(1) !="/") + currentRemoteDir +="/"; + currentPathEdit->setText( currentRemoteDir ); + remoteDirList( (const QString &)currentRemoteDir); + QCopEnvelope ( "QPE/System", "notBusy()" ); +} + + void OpieFtp::localListClicked(QListViewItem *selectedItem) +{ + QString strItem=selectedItem->text(0); + QString strSize=selectedItem->text(1); + strSize=strSize.stripWhiteSpace(); + if(strItem.find("@",0,TRUE) !=-1 || strItem.find("->",0,TRUE) !=-1 ) { //if symlink + // is symlink + QString strItem2=strItem.right( (strItem.length()-strItem.find("->",0,TRUE)) -4); + if(QDir(strItem2).exists() ) { + currentDir.cd(strItem2, TRUE); + populateLocalView(); + } + } else { // not a symlink + if(strItem.find(". .",0,TRUE) && strItem.find("/",0,TRUE)!=-1 ) { + if(QDir(QDir::cleanDirPath(currentDir.canonicalPath()+"/"+strItem)).exists() ) { + strItem=QDir::cleanDirPath(currentDir.canonicalPath()+"/"+strItem); + currentDir.cd(strItem,FALSE); + populateLocalView(); + } else { + currentDir.cdUp(); + populateLocalView(); + } + if(QDir(strItem).exists()){ + currentDir.cd(strItem, TRUE); + populateLocalView(); + } + } else { + strItem=QDir::cleanDirPath(currentDir.canonicalPath()+"/"+strItem); + if( QFile::exists(strItem ) ) { + qDebug("upload "+strItem); + } + } //end not symlink + chdir(strItem.latin1()); + } +} + +void OpieFtp::showHidden() +{ + if (!b) { + currentDir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden | QDir::All); +// currentDir.setSorting(/* QDir::Size*/ /*| QDir::Reversed | */QDir::DirsFirst); + b=TRUE; + + } else { + currentDir.setFilter( QDir::Files | QDir::Dirs/* | QDir::Hidden*/ | QDir::All); +// currentDir.setSorting(/* QDir::Size*/ /*| QDir::Reversed | */QDir::DirsFirst); + b=FALSE; + } + populateLocalView(); +} + +void OpieFtp::ListPressed( int mouse, QListViewItem *item, const QPoint &point, int i) +{ + switch (mouse) { + case 1: + break; + case 2: + showLocalMenu(); + break; + }; +} + +void OpieFtp::RemoteListPressed( int mouse, QListViewItem *item, const QPoint &point, int i) +{ + switch (mouse) { + case 1: + break; + case 2: + showRemoteMenu(); + break; + }; +} + +void OpieFtp::showRemoteMenu() +{ + QPopupMenu m;// = new QPopupMenu( Local_View ); + m.insertItem( tr( "Download" ), this, SLOT( remoteDownload() )); + m.insertItem( tr( "Make Directory" ), this, SLOT( remoteMakDir() )); + m.insertItem( tr( "Rename" ), this, SLOT( remoteRename() )); + m.insertSeparator(); + m.insertItem( tr( "Delete" ), this, SLOT( remoteDelete() )); + m.exec( QCursor::pos() ); +} + +void OpieFtp::showLocalMenu() +{ + QPopupMenu m; + m.insertItem( tr( "Show Hidden Files" ), this, SLOT( showHidden() )); + m.insertItem( tr( "Upload" ), this, SLOT( localUpload() )); + m.insertItem( tr( "Make Directory" ), this, SLOT( localMakDir() )); + m.insertItem( tr( "Rename" ), this, SLOT( localRename() )); + m.insertSeparator(); + m.insertItem( tr( "Delete" ), this, SLOT( localDelete() )); + m.exec( QCursor::pos() ); +} + +void OpieFtp::localMakDir() +{ + InputDialog *fileDlg; + fileDlg = new InputDialog(this,"Make Directory",TRUE, 0); + fileDlg->exec(); + if( fileDlg->result() == 1 ) { + QString filename = fileDlg->LineEdit1->text(); + currentDir.mkdir( currentDir.canonicalPath()+"/"+filename); + } + populateLocalView(); +} + +void OpieFtp::localDelete() +{ + QString f = Local_View->currentItem()->text(0); + if(QDir(f).exists() ) { + switch ( QMessageBox::warning(this,"Delete","Do you really want to delete\n"+f+ + " ?\nIt must be empty","Yes","No",0,0,1) ) { + case 0: { + f=currentDir.canonicalPath()+"/"+f; + QString cmd="rmdir "+f; + system( cmd.latin1()); + populateLocalView(); + } + break; + case 1: + // exit + break; + }; + + } else { + switch ( QMessageBox::warning(this,"Delete","Do you really want to delete\n"+f + +" ?","Yes","No",0,0,1) ) { + case 0: { + f=currentDir.canonicalPath()+"/"+f; + QString cmd="rm "+f; + system( cmd.latin1()); + populateLocalView(); + } + break; + case 1: + // exit + break; + }; + } +} + +void OpieFtp::remoteMakDir() +{ + InputDialog *fileDlg; + fileDlg = new InputDialog(this,"Make Directory",TRUE, 0); + fileDlg->exec(); + if( fileDlg->result() == 1 ) { + QString filename = fileDlg->LineEdit1->text();//+".playlist"; + QString tmp=currentRemoteDir+filename; + QCopEnvelope ( "QPE/System", "busy()" ); + if(FtpMkdir( tmp.latin1(), conn) == 0) { + QString msg; + msg.sprintf("Unable to make directory\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + QCopEnvelope ( "QPE/System", "notBusy()" ); + } + populateRemoteView(); +} + +void OpieFtp::remoteDelete() +{ + QString f = Remote_View->currentItem()->text(0); + QCopEnvelope ( "QPE/System", "busy()" ); + if( f.right(1) =="/") { + QString path= currentRemoteDir+f; + switch ( QMessageBox::warning(this,"Delete","Do you really want to delete\n"+f+"?" + ,"Yes","No",0,0,1) ) { + case 0: { + f=currentDir.canonicalPath()+"/"+f; + if(FtpRmdir( path.latin1(), conn) ==0) { + QString msg; + msg.sprintf("Unable to remove directory\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + } + break; + }; + } else { + switch ( QMessageBox::warning(this,"Delete","Do you really want to delete\n"+f+"?" + ,"Yes","No",0,0,1) ) { + case 0: { + QString path= currentRemoteDir+f; + if(FtpDelete( path.latin1(), conn)==0) { + QString msg; + msg.sprintf("Unable to delete file\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + } + break; + }; + } + QCopEnvelope ( "QPE/System", "notBusy()" ); +} + +void OpieFtp::remoteRename() +{ + QString curFile = Remote_View->currentItem()->text(0); + InputDialog *fileDlg; + fileDlg = new InputDialog(this,"Rename",TRUE, 0); + fileDlg->inputText = curFile; + fileDlg->exec(); + if( fileDlg->result() == 1 ) { + QString oldName = currentRemoteDir +"/"+ curFile; + QString newName = currentRemoteDir +"/"+ fileDlg->LineEdit1->text();//+".playlist"; + QCopEnvelope ( "QPE/System", "busy()" ); + if(FtpRename( oldName.latin1(), newName.latin1(),conn) == 0) { + QString msg; + msg.sprintf("Unable to rename file\n%s",FtpLastResponse(conn)); + QMessageBox::message("Note",msg); + } + QCopEnvelope ( "QPE/System", "notBusy()" ); + } + populateRemoteView(); +} + +void OpieFtp::localRename() +{ + QString curFile = Local_View->currentItem()->text(0); + InputDialog *fileDlg; + fileDlg = new InputDialog(this,"Rename",TRUE, 0); + fileDlg->inputText = curFile; + fileDlg->exec(); + if( fileDlg->result() == 1 ) { + QString oldname = currentDir.canonicalPath() + "/" + curFile; + QString newName = currentDir.canonicalPath() + "/" + fileDlg->LineEdit1->text();//+".playlist"; + if( rename(oldname.latin1(), newName.latin1())== -1) + QMessageBox::message("Note","Could not rename"); + } + populateLocalView(); +} + +void OpieFtp::currentPathEditChanged() +{ + if (TabWidget->currentPageIndex() == 0) { + if(QDir( currentPathEdit->text()).exists()) { + currentDir.setPath( currentPathEdit->text() ); + populateLocalView(); + } else { + QMessageBox::message("Note","That directory does not exist"); + } + } + if (TabWidget->currentPageIndex() == 1) { + currentRemoteDir = currentPathEdit->text(); + if(currentRemoteDir.right(1) !="/") { + currentRemoteDir = currentRemoteDir +"/"; + currentPathEdit->setText( currentRemoteDir ); + } + remoteChDir( (const QString &)currentRemoteDir); + remoteDirList( (const QString &)currentRemoteDir); + } +} diff --git a/noncore/net/opieftp/opieftp.h b/noncore/net/opieftp/opieftp.h new file mode 100644 index 0000000..20dd0d0 --- a/dev/null +++ b/noncore/net/opieftp/opieftp.h @@ -0,0 +1,92 @@ +/*************************************************************************** + opieftp.h + ------------------- +** Created: Sat Mar 9 23:33:09 2002 + copyright : (C) 2002 by ljp + email : ljp@llornkcor.com + * This program is free software; you can redistribute it and/or modify * + * it under the terms of 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. * + ***************************************************************************/ +#ifndef OPIEFTP_H +#define OPIEFTP_H + +#include +#include +#include +#include +#include +#include + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QComboBox; +class QListView; +class QListviewItem; +class QLabel; +class QProgressBar; +class QSpinBox; +class QTabWidget; +class QWidget; +class QPEToolBar; +class QPEMenuBar; +class QPopupMenu; +class QFile; +class QListViewItem; +class QLineEdit; + +class OpieFtp : public QMainWindow +{ + Q_OBJECT + +public: + OpieFtp( ); + ~OpieFtp(); + + QTabWidget *TabWidget; + QWidget *tab, *tab_2, *tab_3;; + QListView *Local_View, *Remote_View; + + QComboBox *UsernameComboBox, *ServerComboBox; + QLineEdit *PasswordEdit, *remotePath, *currentPathEdit; + QLabel *TextLabel2, *TextLabel1, *TextLabel3, *TextLabel4;; + QSpinBox* PortSpinBox; + QPopupMenu *connectionMenu, *localMenu, *remoteMenu; + QDir currentDir; + QString currentRemoteDir; + QString filterStr; + QListViewItem * item; + bool b; + +protected slots: + void showLocalMenu( ); + void showRemoteMenu( ); + void localUpload(); + void remoteDownload(); + void newConnection(); + void connector(); + void disConnector(); + void populateLocalView(); + bool populateRemoteView(); + void showHidden(); + + void localListClicked(QListViewItem *); + void remoteListClicked(QListViewItem *); + void ListPressed( int, QListViewItem *, const QPoint&, int); + void RemoteListPressed( int, QListViewItem *, const QPoint&, int); + void localMakDir(); + void localDelete(); + void remoteMakDir(); + void remoteDelete(); + bool remoteDirList(const QString &); + bool remoteChDir(const QString &); + void tabChanged(QWidget*); + void cleanUp(); + void remoteRename(); + void localRename(); + void currentPathEditChanged(); +}; + +#endif // OPIEFTP_H diff --git a/noncore/net/opieftp/opieftp.pro b/noncore/net/opieftp/opieftp.pro new file mode 100644 index 0000000..b4d0b4c --- a/dev/null +++ b/noncore/net/opieftp/opieftp.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +CONFIG += qt warn_on release +HEADERS = opieftp.h inputDialog.h ftplib.h +SOURCES = opieftp.cpp inputDialog.cpp ftplib.c main.cpp +TARGET = opieftp +REQUIRES=medium-config +DESTDIR = $(OPIEDIR)/bin +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += -lqpe + -- cgit v0.9.0.2