bombboyer
asked on
Link Errors: unresolved external symbol "__declspec(dllimport)
I'm working on a project that uses a SFTP library to connect to an SFTP server and send a file (using VC++ 6.0). Everything compiles file, but when I try to build, I get the following errors (basically, error everytime I call a function from the ftplib):
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall ftplib::~ftplib(void)" (__imp_??1ftplib@@QAE@XZ)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Quit(void)" (__imp_?Quit@ftplib@@QAEHX Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Put(char const *,char const *,enum ftplib::transfermode,long) " (__imp_?Put@ftplib@@QAEHPB D0W4transf ermode@1@J @Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::SetDataEncryption( enum ftplib::dataencryption)" (__imp_?SetDataEncryption@ ftplib@@QA EHW4dataen cryption@1 @@Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Delete(char const *)" (__imp_?Delete@ftplib@@QAE HPBD@Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::ModDate(char const *,char *,int)" (__imp_?ModDate@ftplib@@QA EHPBDPADH@ Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Login(char const *,char const *)" (__imp_?Login@ftplib@@QAEH PBD0@Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::NegotiateEncryptio n(void)" (__imp_?NegotiateEncryptio n@ftplib@@ QAEHXZ)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Connect(char const *)" (__imp_?Connect@ftplib@@QA EHPBD@Z)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall ftplib::ftplib(void)" (__imp_??0ftplib@@QAE@XZ)
Debug/xfer.exe : fatal error LNK1120: 10 unresolved externals
-------------------------- ---------- ---------- ---------- ---
Here's all my code:
-------------------------- ---
file: xfer.cpp
-------------------------- ---
#include <iostream>
#include <string>
#include <fstream>
#include "ftplib.h"
using namespace std;
struct xferReport
{
string filename;
bool status;
bool update;
string to_string()
{
if (status)
return ("Success, updated: " + filename);
else
{
if (update)
return ("FAILED, NEEDS UPDATE: " + filename);
else
return ("Skipped: " + filename);
}
}
};
xferReport xfer(string filepath, string user, string pass)
{
// code to transfer based on filemask
// returns a string of 1 or 0's, one for each file transferred
xferReport myReport;
int temp;
char remotedate[14]; // Format: YYYYMMDDHHMMSS
char localdate[14];
string filename; // only the file name and extension, ie. myFile.txt
int i = 0;
i = filepath.find_last_of("\\" );
filename = filepath.substr(i, filepath.length());
ftplib myFTP;
temp = myFTP.Connect("upload.quickbackups.com ");
temp = myFTP.NegotiateEncryption();
temp = myFTP.Login(user.c_str(),pass.c_str());
temp = myFTP.ModDate(filename.c_str(), remotedate, _MAX_PATH); // remote filedate is now recorded
if (localdate > remotedate)
{
// replace
cout << endl << "Removing older file from server...";
temp = myFTP.Delete(filename.c_str());
cout << endl << "Securing (Encrypting) Data Channel...";
temp = myFTP.SetDataEncryption(ftplib::dataencryption::secure);
cout << endl << "Transferring data, please wait... ... ...";
temp = myFTP.Put(filepath.c_str(), filename.c_str(), ftplib::transfermode::imag e);
cout << "DONE";
myReport.update = true;
if (temp == 1)
myReport.status = true;
else
myReport.status = false;
}
else
{
// file hasn't been changed since last upload, skip upload
myReport.status = false;
myReport.update = false;
}
myFTP.Quit();
return myReport;
}
int main(int argc, char * argv[])
{
string path;
string user;
string pass;
ifstream read;
read.open("info");
read >> user >> pass;
read.close();
if (argc > 1)
{
int i = 1;
cout << "here ";
while (i < argc)
{
cout << "here ";
path += argv[i];
i++;
}
}
else
{
cout << endl << "No argument";
return 0;
}
cout << endl << path << endl;
xferReport xferResults;
xferResults = xfer(path, user, pass); // do what it's meant to do, and report results
string myResults = xferResults.to_string();
cout << endl << endl << myResults << endl << endl;
return 0;
}
-------------------------- ------
file: filelib.h
-------------------------- ------
#ifndef FTPLIB_H
#define FTPLIB_H
#if defined(_WIN32)
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
#endif
#include <time.h>
//#include <unistd.h>
#include <windows.h>
#define off64_t long
#ifdef NOLFS
#define off64_t long
#endif
#ifndef NOSSL
#include <openssl/ssl.h>
#endif
using namespace std;
/**
*@author mkulke
*/
typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);
typedef int (*FtpCallbackIdle)(void *arg);
typedef void (*FtpCallbackLog)(char *str, void* arg, bool out);
#ifndef NOSSL
typedef bool (*FtpCallbackCert)(void *arg, X509 *cert);
#endif
struct ftphandle {
char *cput,*cget;
int handle;
int cavail,cleft;
char *buf;
int dir;
ftphandle *ctrl;
int cmode;
struct timeval idletime;
FtpCallbackXfer xfercb;
FtpCallbackIdle idlecb;
FtpCallbackLog logcb;
void *cbarg;
off64_t xfered;
off64_t cbbytes;
off64_t xfered1;
char response[256];
#ifndef NOSSL
SSL* ssl;
SSL_CTX* ctx;
BIO* sbio;
int tlsctrl;
int tlsdata;
FtpCallbackCert certcb;
#endif
off64_t offset;
bool correctpasv;
};
#if defined(_WIN32)
class DLLIMPORT ftplib {
#else
class ftplib {
#endif
public:
enum accesstype
{
dir = 1,
dirverbose,
fileread,
filewrite,
filereadappend,
filewriteappend
};
enum transfermode
{
ascii = 'A',
image = 'I'
};
enum connmode
{
pasv = 1,
port
};
enum fxpmethod
{
defaultfxp = 0,
alternativefxp
};
enum dataencryption
{
unencrypted = 0,
secure
};
ftplib();
~ftplib();
char* LastResponse();
int Connect(const char *host);
int Login(const char *user, const char *pass);
int Site(const char *cmd);
int Raw(const char *cmd);
int SysType(char *buf, int max);
int Mkdir(const char *path);
int Chdir(const char *path);
int Cdup();
int Rmdir(const char *path);
int Pwd(char *path, int max);
int Nlst(const char *outputfile, const char *path);
int Dir(const char *outputfile, const char *path);
int Size(const char *path, int *size, transfermode mode);
int ModDate(const char *path, char *dt, int max);
int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0);
int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0);
int Rename(const char *src, const char *dst);
int Delete(const char *path);
#ifndef NOSSL
int SetDataEncryption(dataencr yption enc);
int NegotiateEncryption();
void SetCallbackCertFunction(Ft pCallbackC ert pointer);
#endif
int Quit();
void SetCallbackIdleFunction(Ft pCallbackI dle pointer);
void SetCallbackLogFunction(Ftp CallbackLo g pointer);
void SetCallbackXferFunction(Ft pCallbackX fer pointer);
void SetCallbackArg(void *arg);
void SetCallbackBytes(off64_t bytes);
void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; };
void SetCallbackIdletime(int time);
void SetConnmode(connmode mode);
static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method);
ftphandle* RawOpen(const char *path, accesstype type, transfermode mode);
int RawClose(ftphandle* handle);
int RawWrite(void* buf, int len, ftphandle* handle);
int RawRead(void* buf, int max, ftphandle* handle);
private:
ftphandle* mp_ftphandle;
int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode);
int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl);
int FtpAcceptConnection(ftphan dle *nData, ftphandle *nControl);
int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
int FtpRead(void *buf, int max, ftphandle *nData);
int FtpWrite(void *buf, int len, ftphandle *nData);
int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
int FtpClose(ftphandle *nData);
int socket_wait(ftphandle *ctl);
int readline(char *buf,int max,ftphandle *ctl);
int writeline(char *buf, int len, ftphandle *nData);
int readresp(char c, ftphandle *nControl);
void ClearHandle();
int CorrectPasvResponse(unsign ed char *v);
};
#endif
-------------------------- --
file: ftplib.cpp
-------------------------- --
#ifndef NOLFS
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#include "ftplib.h"
#if defined(_WIN32)
#include <windows.h>
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#if defined(_WIN32)
#define SETSOCKOPT_OPTVAL_TYPE (const char *)
#else
#define SETSOCKOPT_OPTVAL_TYPE (void *)
#endif
#if defined(_WIN32)
#define net_read(x,y,z) recv(x,(char*)y,z,0)
#define net_write(x,y,z) send(x,(char*)y,z,0)
#define net_close closesocket
#else
#define net_read read
#define net_write write
#define net_close close
#endif
#if defined(_WIN32)
typedef int socklen_t;
#endif
using namespace std;
/* socket values */
//#define SETSOCKOPT_OPTVAL_TYPE (void *)
#define FTPLIB_BUFSIZ 1024
#define ACCEPT_TIMEOUT 30
/* io types */
#define FTPLIB_CONTROL 0
#define FTPLIB_READ 1
#define FTPLIB_WRITE 2
/* win32 dll initializer */
#if defined(_WIN32)
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
#endif
/*
* Constructor
*/
ftplib::ftplib()
{
#if defined(_WIN32)
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa))
{
printf("WSAStartup() failed, %lu\n", (unsigned long)GetLastError());
}
#endif
#ifndef NOSSL
SSL_library_init();
#endif
mp_ftphandle = static_cast<ftphandle *>(calloc(1,sizeof(ftphand le)));
if (mp_ftphandle == NULL) perror("calloc");
mp_ftphandle->buf = static_cast<char *>(malloc(FTPLIB_BUFSIZ));
if (mp_ftphandle->buf == NULL)
{
perror("calloc");
free(mp_ftphandle);
}
#ifndef NOSSL
mp_ftphandle->ctx = SSL_CTX_new(SSLv3_method() );
SSL_CTX_set_verify(mp_ftph andle->ctx , SSL_VERIFY_NONE, NULL);
mp_ftphandle->ssl = SSL_new(mp_ftphandle->ctx) ;
#endif
ClearHandle();
}
/*
* Destructor
*/
ftplib::~ftplib()
{
#ifndef NOSSL
SSL_free(mp_ftphandle->ssl );
SSL_CTX_free(mp_ftphandle- >ctx);
#endif
free(mp_ftphandle->buf);
free(mp_ftphandle);
}
/*
* socket_wait - wait for socket to receive or flush data
*
* return 1 if no user callback, otherwise, return value returned by
* user callback
*/
int ftplib::socket_wait(ftphan dle *ctl)
{
fd_set fd,*rfd = NULL,*wfd = NULL;
struct timeval tv;
int rv = 0;
if (ctl->idlecb == NULL) return 1;
/*if ((ctl->dir == FTPLIB_CONTROL)
|| (ctl->idlecb == NULL)
|| ((ctl->idletime.tv_sec == 0)
&& //(ctl->idletime.tv_usec 0))
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->respons e, strerror(errno), sizeof(ctl->ctrl->response ));
break;
}
else if (rv > 0)
{
rv = 1;
break;
}
} while ((rv = ctl->idlecb(ctl->cbarg)));
return rv;
}
/*
* read a line of text
*
* return -1 on error or bytecount
*/
int ftplib::readline(char *buf,int max,ftphandle *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 = static_cast<char*>(memccpy (bp,ctl->c get,'\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;
#ifndef NOSSL
if (ctl->tlsdata) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
else
{
if (ctl->tlsctrl) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
else x = net_read(ctl->handle,ctl-> cput,ctl-> cleft);
}
#else
x = net_read(ctl->handle,ctl-> cput,ctl-> cleft);
#endif
if ( x == -1)
{
perror("read");
retval = -1;
break;
}
// LOGGING FUNCTIONALITY!!!
if ((ctl->dir == FTPLIB_CONTROL) && (mp_ftphandle->logcb != NULL))
{
*((ctl->cput)+x) = '\0';
mp_ftphandle->logcb(ctl->c put, mp_ftphandle->cbarg, true);
}
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
*/
int ftplib::writeline(char *buf, int len, ftphandle *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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#else
w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#endif
if (w != FTPLIB_BUFSIZ)
{
printf("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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#else
w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#endif
if (w != FTPLIB_BUFSIZ)
{
printf("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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, nb);
else w = net_write(nData->handle, nbp, nb);
#else
w = net_write(nData->handle, nbp, nb);
#endif
if (w != nb)
{
printf("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
*/
int ftplib::readresp(char c, ftphandle *nControl)
{
char match[5];
if (readline(nControl->respon se,256,nCo ntrol) == -1)
{
perror("Control socket read failed");
return 0;
}
if (nControl->response[3] == '-')
{
strncpy(match,nControl->re sponse,3);
match[3] = ' ';
match[4] = '\0';
do
{
if (readline(nControl->respon se,256,nCo ntrol) == -1)
{
perror("Control socket read failed");
return 0;
}
} while (strncmp(nControl->respons e,match,4) );
}
if (nControl->response[0] == c) return 1;
return 0;
}
/*
* FtpLastResponse - return a pointer to the last response received
*/
char* ftplib::LastResponse()
{
if ((mp_ftphandle) && (mp_ftphandle->dir == FTPLIB_CONTROL)) return mp_ftphandle->response;
return NULL;
}
/*
* ftplib::Connect - connect to remote server
*
* return 1 if connected, 0 if not
*/
int ftplib::Connect(const char *host)
{
int sControl;
struct sockaddr_in sin;
struct hostent *phe;
struct servent *pse;
int on=1;
int ret;
char *lhost;
char *pnum;
mp_ftphandle->dir = FTPLIB_CONTROL;
mp_ftphandle->ctrl = NULL;
mp_ftphandle->xfered = 0;
mp_ftphandle->xfered1 = 0;
#ifndef NOSSL
mp_ftphandle->tlsctrl = 0;
mp_ftphandle->tlsdata = 0;
#endif
mp_ftphandle->offset = 0;
mp_ftphandle->handle = 0;
memset(&sin,0,sizeof(sin)) ;
sin.sin_family = AF_INET;
lhost = strdup(host);
pnum = strchr(lhost,':');
if (pnum == NULL)
{
if ((pse = getservbyname("ftp","tcp") ) == NULL)
{
perror("getservbyname");
return 0;
}
sin.sin_port = pse->s_port;
}
else
{
*pnum++ = '\0';
if (isdigit(*pnum)) sin.sin_port = htons(atoi(pnum));
else
{
pse = getservbyname(pnum,"tcp");
sin.sin_port = pse->s_port;
}
}
#if defined(_WIN32)
if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
ret = inet_aton(lhost, &sin.sin_addr);
if (ret == 0)
#endif
{
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_S OCKET,SO_R EUSEADDR, 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;
}
mp_ftphandle->handle = sControl;
if (readresp('2', mp_ftphandle) == 0)
{
net_close(sControl);
mp_ftphandle->handle = 0;
return 0;
}
return 1;
}
/*
* FtpSendCmd - send a command and wait for expected response
*
* return 1 if proper response received, 0 otherwise
*/
int ftplib::FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl)
{
char buf[256];
int x;
if (!nControl->handle) return 0;
if (nControl->dir != FTPLIB_CONTROL) return 0;
sprintf(buf,"%s\r\n",cmd);
#ifndef NOSSL
if (nControl->tlsctrl) x = SSL_write(nControl->ssl,bu f,strlen(b uf));
else x = net_write(nControl->handle ,buf,strle n(buf));
#else
x = net_write(nControl->handle ,buf,strle n(buf));
#endif
if (x <= 0)
{
perror("write");
return 0;
}
if (mp_ftphandle->logcb != NULL) mp_ftphandle->logcb(buf, mp_ftphandle->cbarg, false);
return readresp(expresp, nControl);
}
/*
* FtpLogin - log in to remote server
*
* return 1 if logged in, 0 otherwise
*/
int ftplib::Login(const char *user, const char *pass)
{
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',m p_ftphandl e))
{
if (mp_ftphandle->ctrl != NULL) return 1;
if (*LastResponse() == '2') return 1;
return 0;
}
sprintf(tempbuf,"PASS %s",pass);
return FtpSendCmd(tempbuf,'2',mp_ ftphandle) ;
}
/*
* FtpAcceptConnection - accept connection from server
*
* return 1 if successful, 0 otherwise
*/
int ftplib::FtpAcceptConnectio n(ftphandl e *nData, ftphandle *nControl)
{
int sData;
struct sockaddr addr;
socklen_t l;
int i;
struct timeval tv;
fd_set mask;
int rv = 0;
FD_ZERO(&mask);
FD_SET(nControl->handle, &mask);
FD_SET(nData->handle, &mask);
tv.tv_usec = 0;
tv.tv_sec = ACCEPT_TIMEOUT;
i = nControl->handle;
if (i < nData->handle) i = nData->handle;
i = select(i+1, &mask, NULL, NULL, &tv);
if (i == -1)
{
strncpy(nControl->response , strerror(errno), sizeof(nControl->response) );
net_close(nData->handle);
nData->handle = 0;
rv = 0;
}
else if (i == 0)
{
strcpy(nControl->response, "timed out waiting for connection");
net_close(nData->handle);
nData->handle = 0;
rv = 0;
}
else
{
if (FD_ISSET(nData->handle, &mask))
{
l = sizeof(addr);
sData = accept(nData->handle, &addr, &l);
i = errno;
net_close(nData->handle);
if (sData > 0)
{
rv = 1;
nData->handle = sData;
nData->ctrl = nControl;
}
else
{
strncpy(nControl->response , strerror(i), sizeof(nControl->response) );
nData->handle = 0;
rv = 0;
}
}
else if (FD_ISSET(nControl->handle , &mask))
{
net_close(nData->handle);
nData->handle = 0;
readresp('2', nControl);
rv = 0;
}
}
return rv;
}
/*
* FtpAccess - return a handle for a data stream
*
* return 1 if successful, 0 otherwise
*/
int ftplib::FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData)
{
char buf[256];
int dir, ret;
if ((path == NULL) && ((type == ftplib::filewrite)
|| (type == ftplib::fileread)
|| (type == ftplib::filereadappend)
|| (type == ftplib::filewriteappend)))
{
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 (type)
{
case ftplib::dir:
strcpy(buf,"NLST");
dir = FTPLIB_READ;
break;
case ftplib::dirverbose:
strcpy(buf,"LIST -aL");
dir = FTPLIB_READ;
break;
case ftplib::filereadappend:
case ftplib::fileread:
strcpy(buf,"RETR");
dir = FTPLIB_READ;
break;
case ftplib::filewriteappend:
case ftplib::filewrite:
strcpy(buf,"STOR");
dir = FTPLIB_WRITE;
break;
default:
sprintf(nControl->response , "Invalid open type %d\n", type);
return 0;
}
if (path != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(path) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],path);
}
if (nControl->cmode == ftplib::pasv)
{
if (FtpOpenPasv(nControl, nData, mode, dir, buf) == -1) return 0;
}
if (nControl->cmode == ftplib::port)
{
if (FtpOpenPort(nControl, nData, mode, dir, buf) == -1) return 0;
if (!FtpAcceptConnection(*nDa ta,nContro l))
{
FtpClose(*nData);
*nData = NULL;
return 0;
}
}
#ifndef NOSSL
if (nControl->tlsdata)
{
(*nData)->ssl = SSL_new(nControl->ctx);
(*nData)->sbio = BIO_new_socket((*nData)->h andle, BIO_NOCLOSE);
SSL_set_bio((*nData)->ssl, (*nData)-> sbio,(*nDa ta)->sbio) ;
ret = SSL_connect((*nData)->ssl) ;
if (ret != 1) return 0;
(*nData)->tlsdata = 1;
}
#endif
return 1;
}
/*
* FtpOpenPort - Establishes a PORT connection for data transfer
*
* return 1 if successful, -1 otherwise
*/
int ftplib::FtpOpenPort(ftphan dle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd)
{
int sData;
union {
struct sockaddr sa;
struct sockaddr_in in;
} sin;
struct linger lng = { 0, 0 };
socklen_t l;
int on=1;
ftphandle *ctrl;
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 (getsockname(nControl->han dle, &sin.sa, &l) < 0)
{
perror("getsockname");
return -1;
}
sData = socket(PF_INET,SOCK_STREAM ,IPPROTO_T CP);
if (sData == -1)
{
perror("socket");
return -1;
}
if (setsockopt(sData,SOL_SOCK ET,SO_REUS EADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (setsockopt(sData,SOL_SOCK ET,SO_LING ER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
{
perror("setsockopt");
net_close(sData);
return -1;
}
sin.in.sin_port = 0;
if (bind(sData, &sin.sa, sizeof(sin)) == -1)
{
perror("bind");
net_close(sData);
return -1;
}
if (listen(sData, 1) < 0)
{
perror("listen");
net_close(sData);
return -1;
}
if (getsockname(sData, &sin.sa, &l) < 0) return 0;
sprintf(buf, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,% hhu",
(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',nCont rol))
{
net_close(sData);
return -1;
}
if (mp_ftphandle->offset != 0)
{
char buf[256];
sprintf(buf,"REST %lld", mp_ftphandle->offset);
if (!FtpSendCmd(buf,'3',nCont rol))
{
net_close(sData);
return 0;
}
}
ctrl = static_cast<ftphandle*>(ca lloc(1,siz eof(ftphan dle)));
if (ctrl == NULL)
{
perror("calloc");
net_close(sData);
return -1;
}
if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc( FTPLIB_BUF SIZ))) == NULL))
{
perror("calloc");
net_close(sData);
free(ctrl);
return -1;
}
if (!FtpSendCmd(cmd, '1', nControl))
{
FtpClose(*nData);
*nData = NULL;
return -1;
}
ctrl->handle = sData;
ctrl->dir = dir;
ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
ctrl->idletime = nControl->idletime;
ctrl->cbarg = nControl->cbarg;
ctrl->xfered = 0;
ctrl->xfered1 = 0;
ctrl->cbbytes = nControl->cbbytes;
if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
else ctrl->idlecb = NULL;
if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
else ctrl->xfercb = NULL;
*nData = ctrl;
return 1;
}
/*
* FtpOpenPasv - Establishes a PASV connection for data transfer
*
* return 1 if successful, -1 otherwise
*/
int ftplib::FtpOpenPasv(ftphan dle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd)
{
int sData;
union {
struct sockaddr sa;
struct sockaddr_in in;
} sin;
struct linger lng = { 0, 0 };
unsigned int l;
int on=1;
ftphandle *ctrl;
char *cp;
unsigned char v[6];
int ret;
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);
memset(&sin, 0, l);
sin.in.sin_family = AF_INET;
if (!FtpSendCmd("PASV",'2',nC ontrol)) return -1;
cp = strchr(nControl->response, '(');
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu, %hhu,%hhu, %hhu",&v[2 ],&v[3],&v [4],&v[5], &v[0],&v[1 ]);
if (nControl->correctpasv) if (!CorrectPasvResponse(v)) return -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];
if (mp_ftphandle->offset != 0)
{
char buf[256];
sprintf(buf,"REST %lld",mp_ftphandle->offset );
if (!FtpSendCmd(buf,'3',nCont rol)) return 0;
}
sData = socket(PF_INET,SOCK_STREAM ,IPPROTO_T CP);
if (sData == -1)
{
perror("socket");
return -1;
}
if (setsockopt(sData,SOL_SOCK ET,SO_REUS EADDR, SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (setsockopt(sData,SOL_SOCK ET,SO_LING ER, SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (nControl->dir != FTPLIB_CONTROL) return -1;
sprintf(cmd,"%s\r\n",cmd);
#ifndef NOSSL
if (nControl->tlsctrl) ret = SSL_write(nControl->ssl,cm d,strlen(c md));
else ret = net_write(nControl->handle ,cmd,strle n(cmd));
#else
ret = net_write(nControl->handle ,cmd,strle n(cmd));
#endif
if (ret <= 0)
{
perror("write");
return -1;
}
if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)
{
perror("connect");
net_close(sData);
return -1;
}
if (!readresp('1', nControl))
{
net_close(sData);
return -1;
}
ctrl = static_cast<ftphandle*>(ca lloc(1,siz eof(ftphan dle)));
if (ctrl == NULL)
{
perror("calloc");
net_close(sData);
return -1;
}
if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc( FTPLIB_BUF SIZ))) == NULL))
{
perror("calloc");
net_close(sData);
free(ctrl);
return -1;
}
ctrl->handle = sData;
ctrl->dir = dir;
ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
ctrl->idletime = nControl->idletime;
ctrl->cbarg = nControl->cbarg;
ctrl->xfered = 0;
ctrl->xfered1 = 0;
ctrl->cbbytes = nControl->cbbytes;
if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
else ctrl->idlecb = NULL;
if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
else ctrl->xfercb = NULL;
*nData = ctrl;
return 1;
}
/*
* FtpClose - close a data connection
*/
int ftplib::FtpClose(ftphandle *nData)
{
ftphandle *ctrl;
if (nData->dir == FTPLIB_WRITE)
{
if (nData->buf != NULL) writeline(NULL, 0, nData);
}
else if (nData->dir != FTPLIB_READ) return 0;
if (nData->buf) free(nData->buf);
shutdown(nData->handle,2);
net_close(nData->handle);
ctrl = nData->ctrl;
#ifndef NOSSL
SSL_free(nData->ssl);
#endif
free(nData);
if (ctrl) return readresp('2', ctrl);
return 1;
}
/*
* FtpRead - read from a data connection
*/
int ftplib::FtpRead(void *buf, int max, ftphandle *nData)
{
int i;
if (nData->dir != FTPLIB_READ)
return 0;
if (nData->buf) i = readline(static_cast<char* >(buf), max, nData);
else
{
i = socket_wait(nData);
if (i != 1) return 0;
#ifndef NOSSL
if (nData->tlsdata) i = SSL_read(nData->ssl, buf, max);
else i = net_read(nData->handle,buf ,max);
#else
i = net_read(nData->handle,buf ,max);
#endif
}
if (i == -1) return 0;
nData->xfered += i;
if (nData->xfercb && nData->cbbytes)
{
nData->xfered1 += i;
if (nData->xfered1 > nData->cbbytes)
{
if (nData->xfercb(nData->xfer ed, nData->cbarg) == 0) return 0;
nData->xfered1 = 0;
}
}
return i;
}
/*
* FtpWrite - write to a data connection
*/
int ftplib::FtpWrite(void *buf, int len, ftphandle *nData)
{
int i;
if (nData->dir != FTPLIB_WRITE) return 0;
if (nData->buf) i = writeline(static_cast<char *>(buf), len, nData);
else
{
socket_wait(nData);
#ifndef NOSSL
if (nData->tlsdata) i = SSL_write(nData->ssl, buf, len);
else i = net_write(nData->handle, buf, len);
#else
i = net_write(nData->handle, buf, len);
i = net_write(nData->handle, buf, len);
#endif
}
if (i == -1) return 0;
nData->xfered += i;
if (nData->xfercb && nData->cbbytes)
{
nData->xfered1 += i;
if (nData->xfered1 > nData->cbbytes)
{
if (nData->xfercb(nData->xfer ed, nData->cbarg) == 0) return 0;
nData->xfered1 = 0;
}
}
return i;
}
/*
* FtpSite - send a SITE command
*
* return 1 if command successful, 0 otherwise
*/
int ftplib::Site(const char *cmd)
{
char buf[256];
if ((strlen(cmd) + 7) > sizeof(buf)) return 0;
sprintf(buf,"SITE %s",cmd);
if (!FtpSendCmd(buf,'2',mp_ft phandle)) return 0;
return 1;
}
/*
* FtpRaw - send a raw string string
*
* return 1 if command successful, 0 otherwise
*/
int ftplib::Raw(const char *cmd)
{
char buf[256];
strncpy(buf, cmd, 256);
if (!FtpSendCmd(buf,'2',mp_ft phandle)) 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
*/
int ftplib::SysType(char *buf, int max)
{
int l = max;
char *b = buf;
char *s;
if (!FtpSendCmd("SYST",'2',mp _ftphandle )) return 0;
s = &mp_ftphandle->response[4] ;
while ((--l) && (*s != ' ')) *b++ = *s++;
*b++ = '\0';
return 1;
}
/*
* FtpMkdir - create a directory at server
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Mkdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"MKD %s",path);
if (!FtpSendCmd(buf,'2', mp_ftphandle)) return 0;
return 1;
}
/*
* FtpChdir - change path at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Chdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"CWD %s",path);
if (!FtpSendCmd(buf,'2',mp_ft phandle)) return 0;
return 1;
}
/*
* FtpCDUp - move to parent directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Cdup()
{
if (!FtpSendCmd("CDUP",'2',mp _ftphandle )) return 0;
return 1;
}
/*
* FtpRmdir - remove directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Rmdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"RMD %s",path);
if (!FtpSendCmd(buf,'2',mp_ft phandle)) return 0;
return 1;
}
/*
* FtpPwd - get working directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Pwd(char *path, int max)
{
int l = max;
char *b = path;
char *s;
if (!FtpSendCmd("PWD",'2',mp_ ftphandle) ) return 0;
s = strchr(mp_ftphandle->respo nse, '"');
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
*/
int ftplib::FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode)
{
int l,c;
char *dbuf;
FILE *local = NULL;
ftphandle *nData;
int rv=1; // 3.1-1
if (localfile != NULL)
{
printf("localfile: -%s-", localfile);
//local = fopen(localfile, (typ == ftplib::filewrite) ? "r" : "w");
char ac[3] = " ";
if ((type == ftplib::dir) || (type == ftplib::dirverbose)) { ac[0] = 'w'; ac[1] = '\0'; }
if (type == ftplib::fileread) { ac[0] = 'w'; ac[1] = '\0'; }
if (type == ftplib::filewriteappend) { ac[0] = 'r'; ac[1] = '\0'; }
if (type == ftplib::filereadappend) { ac[0] = 'a'; ac[1] = '\0'; }
if (type == ftplib::filewrite) { ac[0] = 'r'; ac[1] = '\0'; }
if (mode == ftplib::image) ac[1] = 'b';
#ifndef NOLFS
local = fopen64(localfile, ac);
if (type == ftplib::filewriteappend) fseeko64(local,mp_ftphandl e->offset, SEEK_SET);
#else
local = fopen(localfile, ac);
if (type == ftplib::filewriteappend) fseek(local,mp_ftphandle-> offset,SEE K_SET);
#endif
if (local == NULL)
{
strncpy(nControl->response , strerror(errno), sizeof(nControl->response) );
return 0;
}
}
if (local == NULL) local = ((type == ftplib::filewrite)
|| (type == ftplib::filewriteappend)) ? stdin : stdout;
if (!FtpAccess(path, type, mode, nControl, &nData)) return 0;
dbuf = static_cast<char*>(malloc( FTPLIB_BUF SIZ));
if ((type == ftplib::filewrite) || (type == ftplib::filewriteappend))
{
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");
break;
}
}
}
free(dbuf);
fflush(local);
if (localfile != NULL)
fclose(local);
return FtpClose(nData);
return rv;
}
/*
* FtpNlst - issue an NLST command and write response to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Nlst(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dir, ftplib::ascii);
}
/*
* FtpDir - issue a LIST command and write response to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Dir(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dirverbose, ftplib::ascii);
}
/*
* FtpSize - determine the size of a remote file
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Size(const char *path, int *size, transfermode mode)
{
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', mp_ftphandle)) return 0;
sprintf(cmd,"SIZE %s",path);
if (!FtpSendCmd(cmd,'2',mp_ft phandle)) rv = 0;
else
{
if (sscanf(mp_ftphandle->resp onse, "%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
*/
int ftplib::ModDate(const char *path, char *dt, int max)
{
char buf[256];
int rv = 1;
if ((strlen(path) + 7) > sizeof(buf)) return 0;
sprintf(buf,"MDTM %s",path);
if (!FtpSendCmd(buf,'2',mp_ft phandle)) rv = 0;
else strncpy(dt, &mp_ftphandle->response[4] , max);
return rv;
}
/*
* FtpGet - issue a GET command and write received data to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Get(const char *outputfile, const char *path, transfermode mode, off64_t offset)
{
mp_ftphandle->offset = offset;
if (offset == 0) return FtpXfer(outputfile, path, mp_ftphandle, ftplib::fileread, mode);
else return FtpXfer(outputfile, path, mp_ftphandle, ftplib::filereadappend, mode);
}
/*
* FtpPut - issue a PUT command and send data from input
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Put(const char *inputfile, const char *path, transfermode mode, off64_t offset)
{
mp_ftphandle->offset = offset;
if (offset == 0) return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewrite, mode);
else return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewriteappend, mode);
}
int ftplib::Rename(const char *src, const char *dst)
{
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',mp_ft phandle)) return 0;
sprintf(cmd,"RNTO %s",dst);
if (!FtpSendCmd(cmd,'2',mp_ft phandle)) return 0;
return 1;
}
int ftplib::Delete(const char *path)
{
char cmd[256];
if ((strlen(path) + 7) > sizeof(cmd)) return 0;
sprintf(cmd,"DELE %s",path);
if (!FtpSendCmd(cmd,'2', mp_ftphandle)) return 0;
return 1;
}
/*
* FtpQuit - disconnect from remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Quit()
{
if (mp_ftphandle->dir != FTPLIB_CONTROL) return 0;
if (mp_ftphandle->handle == 0)
{
strcpy(mp_ftphandle->respo nse, "error: no anwser from server\n");
return 0;
}
if (!FtpSendCmd("QUIT",'2',mp _ftphandle ))
{
net_close(mp_ftphandle->ha ndle);
return 0;
}
else
{
net_close(mp_ftphandle->ha ndle);
return 1;
}
}
int ftplib::Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method)
{
char *cp;
unsigned char v[6];
char buf[256];
int retval = 0;
sprintf(buf, "TYPE %c", mode);
if (!dst->FtpSendCmd(buf,'2', dst->mp_ft phandle)) return -1;
if (!src->FtpSendCmd(buf,'2', src->mp_ft phandle)) return -1;
if (method == ftplib::defaultfxp)
{
// PASV dst
if (!dst->FtpSendCmd("PASV",' 2',dst->mp _ftphandle )) return -1;
cp = strchr(dst->mp_ftphandle-> response,' (');
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu, %hhu,%hhu, %hhu",&v[2 ],&v[3],&v [4],&v[5], &v[0],&v[1 ]);
if (dst->mp_ftphandle->correc tpasv) if (!dst->CorrectPasvResponse (v)) return -1;
// PORT src
sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v [1]);
if (!src->FtpSendCmd(buf,'2', src->mp_ft phandle)) return -1;
// RETR src
strcpy(buf,"RETR");
if (pathSrc != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathSrc);
}
if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle)) return 0;
// STOR dst
strcpy(buf,"STOR");
if (pathDst != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathDst);
}
if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle))
{
/* this closes the data connection, to abort the RETR on
the source ftp. all hail pftp, it took me several
hours and i was absolutely clueless, playing around with
ABOR and whatever, when i desperately checked the pftp
source which gave me this final hint. thanks dude(s). */
dst->FtpSendCmd("PASV", '2', dst->mp_ftphandle);
src->readresp('4', src->mp_ftphandle);
return 0;
}
retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle));
}
else
{
// PASV src
if (!src->FtpSendCmd("PASV",' 2',src->mp _ftphandle )) return -1;
cp = strchr(src->mp_ftphandle-> response,' (');
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu, %hhu,%hhu, %hhu",&v[2 ],&v[3],&v [4],&v[5], &v[0],&v[1 ]);
if (src->mp_ftphandle->correc tpasv) if (!src->CorrectPasvResponse (v)) return -1;
// PORT dst
sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v [1]);
if (!dst->FtpSendCmd(buf,'2', dst->mp_ft phandle)) return -1;
// STOR dest
strcpy(buf,"STOR");
if (pathDst != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathDst);
}
if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle)) return 0;
// RETR src
strcpy(buf,"RETR");
if (pathSrc != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathSrc);
}
if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle))
{
src->FtpSendCmd("PASV", '2', src->mp_ftphandle);
dst->readresp('4', dst->mp_ftphandle);
return 0;
}
// wait til its finished!
retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle));
}
return retval;
}
#ifndef NOSSL
int ftplib::SetDataEncryption( dataencryp tion enc)
{
if (!mp_ftphandle->tlsctrl) return 0;
if (!FtpSendCmd("PBSZ 0",'2',mp_ftphandle)) return 0;
switch(enc)
{
case ftplib::unencrypted:
mp_ftphandle->tlsdata = 0;
if (!FtpSendCmd("PROT C",'2',mp_ftphandle)) return 0;
break;
case ftplib::secure:
mp_ftphandle->tlsdata = 1;
if (!FtpSendCmd("PROT P",'2',mp_ftphandle)) return 0;
break;
default:
return 0;
}
return 1;
}
int ftplib::NegotiateEncryptio n()
{
int ret;
if (!FtpSendCmd("AUTH TLS",'2',mp_ftphandle)) return 0;
mp_ftphandle->sbio = BIO_new_socket(mp_ftphandl e->handle, BIO_NOCLOSE);
SSL_set_bio(mp_ftphandle-> ssl,mp_ftp handle->sb io,mp_ftph andle->sbi o);
ret = SSL_connect(mp_ftphandle-> ssl);
if (ret == 1) mp_ftphandle->tlsctrl = 1;
if (mp_ftphandle->certcb != NULL)
{
X509 *cert = SSL_get_peer_certificate(m p_ftphandl e->ssl);
if (!mp_ftphandle->certcb(mp_ ftphandle- >cbarg, cert)) return 0;
}
if (ret < 1) return 0;
return 1;
}
void ftplib::SetCallbackCertFun ction(FtpC allbackCer t pointer)
{
mp_ftphandle->certcb = pointer;
}
#endif
void ftplib::SetCallbackIdleFun ction(FtpC allbackIdl e pointer)
{
mp_ftphandle->idlecb = pointer;
}
void ftplib::SetCallbackXferFun ction(FtpC allbackXfe r pointer)
{
mp_ftphandle->xfercb = pointer;
}
void ftplib::SetCallbackLogFunc tion(FtpCa llbackLog pointer)
{
mp_ftphandle->logcb = pointer;
}
void ftplib::SetCallbackArg(voi d *arg)
{
mp_ftphandle->cbarg = arg;
}
void ftplib::SetCallbackBytes(o ff64_t bytes)
{
mp_ftphandle->cbbytes = bytes;
}
void ftplib::SetCallbackIdletim e(int time)
{
mp_ftphandle->idletime.tv_ sec = time / 1000;
mp_ftphandle->idletime.tv_ usec = (time % 1000) * 1000;
}
void ftplib::SetConnmode(connmo de mode)
{
mp_ftphandle->cmode = mode;
}
void ftplib::ClearHandle()
{
mp_ftphandle->dir = FTPLIB_CONTROL;
mp_ftphandle->ctrl = NULL;
mp_ftphandle->cmode = ftplib::pasv;
mp_ftphandle->idlecb = NULL;
mp_ftphandle->idletime.tv_ sec = mp_ftphandle->idletime.tv_ usec = 0;
mp_ftphandle->cbarg = NULL;
mp_ftphandle->xfered = 0;
mp_ftphandle->xfered1 = 0;
mp_ftphandle->cbbytes = 0;
#ifndef NOSSL
mp_ftphandle->tlsctrl = 0;
mp_ftphandle->tlsdata = 0;
mp_ftphandle->certcb = NULL;
#endif
mp_ftphandle->offset = 0;
mp_ftphandle->handle = 0;
mp_ftphandle->logcb = NULL;
mp_ftphandle->xfercb = NULL;
mp_ftphandle->correctpasv = false;
}
int ftplib::CorrectPasvRespons e(unsigned char *v)
{
struct sockaddr ipholder;
socklen_t ipholder_size = sizeof(ipholder);
if (getpeername(mp_ftphandle- >handle, &ipholder, &ipholder_size) == -1)
{
perror("getpeername");
net_close(mp_ftphandle->ha ndle);
return 0;
}
for (int i = 2; i < 6; i++) v[i] = ipholder.sa_data[i];
return 1;
}
ftphandle* ftplib::RawOpen(const char *path, accesstype type, transfermode mode)
{
int ret;
ftphandle* datahandle;
ret = FtpAccess(path, type, mode, mp_ftphandle, &datahandle);
if (ret) return datahandle;
else return NULL;
}
int ftplib::RawClose(ftphandle * handle)
{
return FtpClose(handle);
}
int ftplib::RawWrite(void* buf, int len, ftphandle* handle)
{
return FtpWrite(buf, len, handle);
}
int ftplib::RawRead(void* buf, int max, ftphandle* handle)
{
return FtpRead(buf, max, handle);
}
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall ftplib::~ftplib(void)" (__imp_??1ftplib@@QAE@XZ)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Quit(void)" (__imp_?Quit@ftplib@@QAEHX
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Put(char const *,char const *,enum ftplib::transfermode,long)
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::SetDataEncryption(
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Delete(char const *)" (__imp_?Delete@ftplib@@QAE
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::ModDate(char const *,char *,int)" (__imp_?ModDate@ftplib@@QA
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Login(char const *,char const *)" (__imp_?Login@ftplib@@QAEH
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::NegotiateEncryptio
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall ftplib::Connect(char const *)" (__imp_?Connect@ftplib@@QA
xfer.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: __thiscall ftplib::ftplib(void)" (__imp_??0ftplib@@QAE@XZ)
Debug/xfer.exe : fatal error LNK1120: 10 unresolved externals
--------------------------
Here's all my code:
--------------------------
file: xfer.cpp
--------------------------
#include <iostream>
#include <string>
#include <fstream>
#include "ftplib.h"
using namespace std;
struct xferReport
{
string filename;
bool status;
bool update;
string to_string()
{
if (status)
return ("Success, updated: " + filename);
else
{
if (update)
return ("FAILED, NEEDS UPDATE: " + filename);
else
return ("Skipped: " + filename);
}
}
};
xferReport xfer(string filepath, string user, string pass)
{
// code to transfer based on filemask
// returns a string of 1 or 0's, one for each file transferred
xferReport myReport;
int temp;
char remotedate[14]; // Format: YYYYMMDDHHMMSS
char localdate[14];
string filename; // only the file name and extension, ie. myFile.txt
int i = 0;
i = filepath.find_last_of("\\"
filename = filepath.substr(i, filepath.length());
ftplib myFTP;
temp = myFTP.Connect("upload.quickbackups.com
temp = myFTP.NegotiateEncryption();
temp = myFTP.Login(user.c_str(),pass.c_str());
temp = myFTP.ModDate(filename.c_str(), remotedate, _MAX_PATH); // remote filedate is now recorded
if (localdate > remotedate)
{
// replace
cout << endl << "Removing older file from server...";
temp = myFTP.Delete(filename.c_str());
cout << endl << "Securing (Encrypting) Data Channel...";
temp = myFTP.SetDataEncryption(ftplib::dataencryption::secure);
cout << endl << "Transferring data, please wait... ... ...";
temp = myFTP.Put(filepath.c_str(), filename.c_str(), ftplib::transfermode::imag
cout << "DONE";
myReport.update = true;
if (temp == 1)
myReport.status = true;
else
myReport.status = false;
}
else
{
// file hasn't been changed since last upload, skip upload
myReport.status = false;
myReport.update = false;
}
myFTP.Quit();
return myReport;
}
int main(int argc, char * argv[])
{
string path;
string user;
string pass;
ifstream read;
read.open("info");
read >> user >> pass;
read.close();
if (argc > 1)
{
int i = 1;
cout << "here ";
while (i < argc)
{
cout << "here ";
path += argv[i];
i++;
}
}
else
{
cout << endl << "No argument";
return 0;
}
cout << endl << path << endl;
xferReport xferResults;
xferResults = xfer(path, user, pass); // do what it's meant to do, and report results
string myResults = xferResults.to_string();
cout << endl << endl << myResults << endl << endl;
return 0;
}
--------------------------
file: filelib.h
--------------------------
#ifndef FTPLIB_H
#define FTPLIB_H
#if defined(_WIN32)
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
#endif
#include <time.h>
//#include <unistd.h>
#include <windows.h>
#define off64_t long
#ifdef NOLFS
#define off64_t long
#endif
#ifndef NOSSL
#include <openssl/ssl.h>
#endif
using namespace std;
/**
*@author mkulke
*/
typedef int (*FtpCallbackXfer)(off64_t
typedef int (*FtpCallbackIdle)(void *arg);
typedef void (*FtpCallbackLog)(char *str, void* arg, bool out);
#ifndef NOSSL
typedef bool (*FtpCallbackCert)(void *arg, X509 *cert);
#endif
struct ftphandle {
char *cput,*cget;
int handle;
int cavail,cleft;
char *buf;
int dir;
ftphandle *ctrl;
int cmode;
struct timeval idletime;
FtpCallbackXfer xfercb;
FtpCallbackIdle idlecb;
FtpCallbackLog logcb;
void *cbarg;
off64_t xfered;
off64_t cbbytes;
off64_t xfered1;
char response[256];
#ifndef NOSSL
SSL* ssl;
SSL_CTX* ctx;
BIO* sbio;
int tlsctrl;
int tlsdata;
FtpCallbackCert certcb;
#endif
off64_t offset;
bool correctpasv;
};
#if defined(_WIN32)
class DLLIMPORT ftplib {
#else
class ftplib {
#endif
public:
enum accesstype
{
dir = 1,
dirverbose,
fileread,
filewrite,
filereadappend,
filewriteappend
};
enum transfermode
{
ascii = 'A',
image = 'I'
};
enum connmode
{
pasv = 1,
port
};
enum fxpmethod
{
defaultfxp = 0,
alternativefxp
};
enum dataencryption
{
unencrypted = 0,
secure
};
ftplib();
~ftplib();
char* LastResponse();
int Connect(const char *host);
int Login(const char *user, const char *pass);
int Site(const char *cmd);
int Raw(const char *cmd);
int SysType(char *buf, int max);
int Mkdir(const char *path);
int Chdir(const char *path);
int Cdup();
int Rmdir(const char *path);
int Pwd(char *path, int max);
int Nlst(const char *outputfile, const char *path);
int Dir(const char *outputfile, const char *path);
int Size(const char *path, int *size, transfermode mode);
int ModDate(const char *path, char *dt, int max);
int Get(const char *outputfile, const char *path, transfermode mode, off64_t offset = 0);
int Put(const char *inputfile, const char *path, transfermode mode, off64_t offset = 0);
int Rename(const char *src, const char *dst);
int Delete(const char *path);
#ifndef NOSSL
int SetDataEncryption(dataencr
int NegotiateEncryption();
void SetCallbackCertFunction(Ft
#endif
int Quit();
void SetCallbackIdleFunction(Ft
void SetCallbackLogFunction(Ftp
void SetCallbackXferFunction(Ft
void SetCallbackArg(void *arg);
void SetCallbackBytes(off64_t bytes);
void SetCorrectPasv(bool b) { mp_ftphandle->correctpasv = b; };
void SetCallbackIdletime(int time);
void SetConnmode(connmode mode);
static int Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method);
ftphandle* RawOpen(const char *path, accesstype type, transfermode mode);
int RawClose(ftphandle* handle);
int RawWrite(void* buf, int len, ftphandle* handle);
int RawRead(void* buf, int max, ftphandle* handle);
private:
ftphandle* mp_ftphandle;
int FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode);
int FtpOpenPasv(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
int FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl);
int FtpAcceptConnection(ftphan
int FtpOpenPort(ftphandle *nControl, ftphandle **nData, transfermode mode, int dir, char *cmd);
int FtpRead(void *buf, int max, ftphandle *nData);
int FtpWrite(void *buf, int len, ftphandle *nData);
int FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData);
int FtpClose(ftphandle *nData);
int socket_wait(ftphandle *ctl);
int readline(char *buf,int max,ftphandle *ctl);
int writeline(char *buf, int len, ftphandle *nData);
int readresp(char c, ftphandle *nControl);
void ClearHandle();
int CorrectPasvResponse(unsign
};
#endif
--------------------------
file: ftplib.cpp
--------------------------
#ifndef NOLFS
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#include "ftplib.h"
#if defined(_WIN32)
#include <windows.h>
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#if defined(_WIN32)
#define SETSOCKOPT_OPTVAL_TYPE (const char *)
#else
#define SETSOCKOPT_OPTVAL_TYPE (void *)
#endif
#if defined(_WIN32)
#define net_read(x,y,z) recv(x,(char*)y,z,0)
#define net_write(x,y,z) send(x,(char*)y,z,0)
#define net_close closesocket
#else
#define net_read read
#define net_write write
#define net_close close
#endif
#if defined(_WIN32)
typedef int socklen_t;
#endif
using namespace std;
/* socket values */
//#define SETSOCKOPT_OPTVAL_TYPE (void *)
#define FTPLIB_BUFSIZ 1024
#define ACCEPT_TIMEOUT 30
/* io types */
#define FTPLIB_CONTROL 0
#define FTPLIB_READ 1
#define FTPLIB_WRITE 2
/* win32 dll initializer */
#if defined(_WIN32)
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
#endif
/*
* Constructor
*/
ftplib::ftplib()
{
#if defined(_WIN32)
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa))
{
printf("WSAStartup() failed, %lu\n", (unsigned long)GetLastError());
}
#endif
#ifndef NOSSL
SSL_library_init();
#endif
mp_ftphandle = static_cast<ftphandle *>(calloc(1,sizeof(ftphand
if (mp_ftphandle == NULL) perror("calloc");
mp_ftphandle->buf = static_cast<char *>(malloc(FTPLIB_BUFSIZ));
if (mp_ftphandle->buf == NULL)
{
perror("calloc");
free(mp_ftphandle);
}
#ifndef NOSSL
mp_ftphandle->ctx = SSL_CTX_new(SSLv3_method()
SSL_CTX_set_verify(mp_ftph
mp_ftphandle->ssl = SSL_new(mp_ftphandle->ctx)
#endif
ClearHandle();
}
/*
* Destructor
*/
ftplib::~ftplib()
{
#ifndef NOSSL
SSL_free(mp_ftphandle->ssl
SSL_CTX_free(mp_ftphandle-
#endif
free(mp_ftphandle->buf);
free(mp_ftphandle);
}
/*
* socket_wait - wait for socket to receive or flush data
*
* return 1 if no user callback, otherwise, return value returned by
* user callback
*/
int ftplib::socket_wait(ftphan
{
fd_set fd,*rfd = NULL,*wfd = NULL;
struct timeval tv;
int rv = 0;
if (ctl->idlecb == NULL) return 1;
/*if ((ctl->dir == FTPLIB_CONTROL)
|| (ctl->idlecb == NULL)
|| ((ctl->idletime.tv_sec == 0)
&& //(ctl->idletime.tv_usec 0))
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->respons
break;
}
else if (rv > 0)
{
rv = 1;
break;
}
} while ((rv = ctl->idlecb(ctl->cbarg)));
return rv;
}
/*
* read a line of text
*
* return -1 on error or bytecount
*/
int ftplib::readline(char *buf,int max,ftphandle *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 = static_cast<char*>(memccpy
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;
#ifndef NOSSL
if (ctl->tlsdata) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
else
{
if (ctl->tlsctrl) x = SSL_read(ctl->ssl, ctl->cput, ctl->cleft);
else x = net_read(ctl->handle,ctl->
}
#else
x = net_read(ctl->handle,ctl->
#endif
if ( x == -1)
{
perror("read");
retval = -1;
break;
}
// LOGGING FUNCTIONALITY!!!
if ((ctl->dir == FTPLIB_CONTROL) && (mp_ftphandle->logcb != NULL))
{
*((ctl->cput)+x) = '\0';
mp_ftphandle->logcb(ctl->c
}
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
*/
int ftplib::writeline(char *buf, int len, ftphandle *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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#else
w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#endif
if (w != FTPLIB_BUFSIZ)
{
printf("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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, FTPLIB_BUFSIZ);
else w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#else
w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
#endif
if (w != FTPLIB_BUFSIZ)
{
printf("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;
#ifndef NOSSL
if (nData->tlsctrl) w = SSL_write(nData->ssl, nbp, nb);
else w = net_write(nData->handle, nbp, nb);
#else
w = net_write(nData->handle, nbp, nb);
#endif
if (w != nb)
{
printf("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
*/
int ftplib::readresp(char c, ftphandle *nControl)
{
char match[5];
if (readline(nControl->respon
{
perror("Control socket read failed");
return 0;
}
if (nControl->response[3] == '-')
{
strncpy(match,nControl->re
match[3] = ' ';
match[4] = '\0';
do
{
if (readline(nControl->respon
{
perror("Control socket read failed");
return 0;
}
} while (strncmp(nControl->respons
}
if (nControl->response[0] == c) return 1;
return 0;
}
/*
* FtpLastResponse - return a pointer to the last response received
*/
char* ftplib::LastResponse()
{
if ((mp_ftphandle) && (mp_ftphandle->dir == FTPLIB_CONTROL)) return mp_ftphandle->response;
return NULL;
}
/*
* ftplib::Connect - connect to remote server
*
* return 1 if connected, 0 if not
*/
int ftplib::Connect(const char *host)
{
int sControl;
struct sockaddr_in sin;
struct hostent *phe;
struct servent *pse;
int on=1;
int ret;
char *lhost;
char *pnum;
mp_ftphandle->dir = FTPLIB_CONTROL;
mp_ftphandle->ctrl = NULL;
mp_ftphandle->xfered = 0;
mp_ftphandle->xfered1 = 0;
#ifndef NOSSL
mp_ftphandle->tlsctrl = 0;
mp_ftphandle->tlsdata = 0;
#endif
mp_ftphandle->offset = 0;
mp_ftphandle->handle = 0;
memset(&sin,0,sizeof(sin))
sin.sin_family = AF_INET;
lhost = strdup(host);
pnum = strchr(lhost,':');
if (pnum == NULL)
{
if ((pse = getservbyname("ftp","tcp")
{
perror("getservbyname");
return 0;
}
sin.sin_port = pse->s_port;
}
else
{
*pnum++ = '\0';
if (isdigit(*pnum)) sin.sin_port = htons(atoi(pnum));
else
{
pse = getservbyname(pnum,"tcp");
sin.sin_port = pse->s_port;
}
}
#if defined(_WIN32)
if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
ret = inet_aton(lhost, &sin.sin_addr);
if (ret == 0)
#endif
{
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_S
{
perror("setsockopt");
net_close(sControl);
return 0;
}
if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1)
{
perror("connect");
net_close(sControl);
return 0;
}
mp_ftphandle->handle = sControl;
if (readresp('2', mp_ftphandle) == 0)
{
net_close(sControl);
mp_ftphandle->handle = 0;
return 0;
}
return 1;
}
/*
* FtpSendCmd - send a command and wait for expected response
*
* return 1 if proper response received, 0 otherwise
*/
int ftplib::FtpSendCmd(const char *cmd, char expresp, ftphandle *nControl)
{
char buf[256];
int x;
if (!nControl->handle) return 0;
if (nControl->dir != FTPLIB_CONTROL) return 0;
sprintf(buf,"%s\r\n",cmd);
#ifndef NOSSL
if (nControl->tlsctrl) x = SSL_write(nControl->ssl,bu
else x = net_write(nControl->handle
#else
x = net_write(nControl->handle
#endif
if (x <= 0)
{
perror("write");
return 0;
}
if (mp_ftphandle->logcb != NULL) mp_ftphandle->logcb(buf, mp_ftphandle->cbarg, false);
return readresp(expresp, nControl);
}
/*
* FtpLogin - log in to remote server
*
* return 1 if logged in, 0 otherwise
*/
int ftplib::Login(const char *user, const char *pass)
{
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',m
{
if (mp_ftphandle->ctrl != NULL) return 1;
if (*LastResponse() == '2') return 1;
return 0;
}
sprintf(tempbuf,"PASS %s",pass);
return FtpSendCmd(tempbuf,'2',mp_
}
/*
* FtpAcceptConnection - accept connection from server
*
* return 1 if successful, 0 otherwise
*/
int ftplib::FtpAcceptConnectio
{
int sData;
struct sockaddr addr;
socklen_t l;
int i;
struct timeval tv;
fd_set mask;
int rv = 0;
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
net_close(nData->handle);
nData->handle = 0;
rv = 0;
}
else if (i == 0)
{
strcpy(nControl->response,
net_close(nData->handle);
nData->handle = 0;
rv = 0;
}
else
{
if (FD_ISSET(nData->handle, &mask))
{
l = sizeof(addr);
sData = accept(nData->handle, &addr, &l);
i = errno;
net_close(nData->handle);
if (sData > 0)
{
rv = 1;
nData->handle = sData;
nData->ctrl = nControl;
}
else
{
strncpy(nControl->response
nData->handle = 0;
rv = 0;
}
}
else if (FD_ISSET(nControl->handle
{
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
*/
int ftplib::FtpAccess(const char *path, accesstype type, transfermode mode, ftphandle *nControl, ftphandle **nData)
{
char buf[256];
int dir, ret;
if ((path == NULL) && ((type == ftplib::filewrite)
|| (type == ftplib::fileread)
|| (type == ftplib::filereadappend)
|| (type == ftplib::filewriteappend)))
{
sprintf(nControl->response
return 0;
}
sprintf(buf, "TYPE %c", mode);
if (!FtpSendCmd(buf, '2', nControl)) return 0;
switch (type)
{
case ftplib::dir:
strcpy(buf,"NLST");
dir = FTPLIB_READ;
break;
case ftplib::dirverbose:
strcpy(buf,"LIST -aL");
dir = FTPLIB_READ;
break;
case ftplib::filereadappend:
case ftplib::fileread:
strcpy(buf,"RETR");
dir = FTPLIB_READ;
break;
case ftplib::filewriteappend:
case ftplib::filewrite:
strcpy(buf,"STOR");
dir = FTPLIB_WRITE;
break;
default:
sprintf(nControl->response
return 0;
}
if (path != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(path) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],path);
}
if (nControl->cmode == ftplib::pasv)
{
if (FtpOpenPasv(nControl, nData, mode, dir, buf) == -1) return 0;
}
if (nControl->cmode == ftplib::port)
{
if (FtpOpenPort(nControl, nData, mode, dir, buf) == -1) return 0;
if (!FtpAcceptConnection(*nDa
{
FtpClose(*nData);
*nData = NULL;
return 0;
}
}
#ifndef NOSSL
if (nControl->tlsdata)
{
(*nData)->ssl = SSL_new(nControl->ctx);
(*nData)->sbio = BIO_new_socket((*nData)->h
SSL_set_bio((*nData)->ssl,
ret = SSL_connect((*nData)->ssl)
if (ret != 1) return 0;
(*nData)->tlsdata = 1;
}
#endif
return 1;
}
/*
* FtpOpenPort - Establishes a PORT connection for data transfer
*
* return 1 if successful, -1 otherwise
*/
int ftplib::FtpOpenPort(ftphan
{
int sData;
union {
struct sockaddr sa;
struct sockaddr_in in;
} sin;
struct linger lng = { 0, 0 };
socklen_t l;
int on=1;
ftphandle *ctrl;
char buf[256];
if (nControl->dir != FTPLIB_CONTROL) return -1;
if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
{
sprintf(nControl->response
return -1;
}
if ((mode != ftplib::ascii) && (mode != ftplib::image))
{
sprintf(nControl->response
return -1;
}
l = sizeof(sin);
if (getsockname(nControl->han
{
perror("getsockname");
return -1;
}
sData = socket(PF_INET,SOCK_STREAM
if (sData == -1)
{
perror("socket");
return -1;
}
if (setsockopt(sData,SOL_SOCK
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (setsockopt(sData,SOL_SOCK
{
perror("setsockopt");
net_close(sData);
return -1;
}
sin.in.sin_port = 0;
if (bind(sData, &sin.sa, sizeof(sin)) == -1)
{
perror("bind");
net_close(sData);
return -1;
}
if (listen(sData, 1) < 0)
{
perror("listen");
net_close(sData);
return -1;
}
if (getsockname(sData, &sin.sa, &l) < 0) return 0;
sprintf(buf, "PORT %hhu,%hhu,%hhu,%hhu,%hhu,%
(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',nCont
{
net_close(sData);
return -1;
}
if (mp_ftphandle->offset != 0)
{
char buf[256];
sprintf(buf,"REST %lld", mp_ftphandle->offset);
if (!FtpSendCmd(buf,'3',nCont
{
net_close(sData);
return 0;
}
}
ctrl = static_cast<ftphandle*>(ca
if (ctrl == NULL)
{
perror("calloc");
net_close(sData);
return -1;
}
if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc(
{
perror("calloc");
net_close(sData);
free(ctrl);
return -1;
}
if (!FtpSendCmd(cmd, '1', nControl))
{
FtpClose(*nData);
*nData = NULL;
return -1;
}
ctrl->handle = sData;
ctrl->dir = dir;
ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
ctrl->idletime = nControl->idletime;
ctrl->cbarg = nControl->cbarg;
ctrl->xfered = 0;
ctrl->xfered1 = 0;
ctrl->cbbytes = nControl->cbbytes;
if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
else ctrl->idlecb = NULL;
if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
else ctrl->xfercb = NULL;
*nData = ctrl;
return 1;
}
/*
* FtpOpenPasv - Establishes a PASV connection for data transfer
*
* return 1 if successful, -1 otherwise
*/
int ftplib::FtpOpenPasv(ftphan
{
int sData;
union {
struct sockaddr sa;
struct sockaddr_in in;
} sin;
struct linger lng = { 0, 0 };
unsigned int l;
int on=1;
ftphandle *ctrl;
char *cp;
unsigned char v[6];
int ret;
if (nControl->dir != FTPLIB_CONTROL) return -1;
if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
{
sprintf(nControl->response
return -1;
}
if ((mode != ftplib::ascii) && (mode != ftplib::image))
{
sprintf(nControl->response
return -1;
}
l = sizeof(sin);
memset(&sin, 0, l);
sin.in.sin_family = AF_INET;
if (!FtpSendCmd("PASV",'2',nC
cp = strchr(nControl->response,
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu,
if (nControl->correctpasv) if (!CorrectPasvResponse(v)) return -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];
if (mp_ftphandle->offset != 0)
{
char buf[256];
sprintf(buf,"REST %lld",mp_ftphandle->offset
if (!FtpSendCmd(buf,'3',nCont
}
sData = socket(PF_INET,SOCK_STREAM
if (sData == -1)
{
perror("socket");
return -1;
}
if (setsockopt(sData,SOL_SOCK
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (setsockopt(sData,SOL_SOCK
{
perror("setsockopt");
net_close(sData);
return -1;
}
if (nControl->dir != FTPLIB_CONTROL) return -1;
sprintf(cmd,"%s\r\n",cmd);
#ifndef NOSSL
if (nControl->tlsctrl) ret = SSL_write(nControl->ssl,cm
else ret = net_write(nControl->handle
#else
ret = net_write(nControl->handle
#endif
if (ret <= 0)
{
perror("write");
return -1;
}
if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)
{
perror("connect");
net_close(sData);
return -1;
}
if (!readresp('1', nControl))
{
net_close(sData);
return -1;
}
ctrl = static_cast<ftphandle*>(ca
if (ctrl == NULL)
{
perror("calloc");
net_close(sData);
return -1;
}
if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc(
{
perror("calloc");
net_close(sData);
free(ctrl);
return -1;
}
ctrl->handle = sData;
ctrl->dir = dir;
ctrl->ctrl = (nControl->cmode == ftplib::pasv) ? nControl : NULL;
ctrl->idletime = nControl->idletime;
ctrl->cbarg = nControl->cbarg;
ctrl->xfered = 0;
ctrl->xfered1 = 0;
ctrl->cbbytes = nControl->cbbytes;
if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec) ctrl->idlecb = nControl->idlecb;
else ctrl->idlecb = NULL;
if (ctrl->cbbytes ) ctrl->xfercb = nControl->xfercb;
else ctrl->xfercb = NULL;
*nData = ctrl;
return 1;
}
/*
* FtpClose - close a data connection
*/
int ftplib::FtpClose(ftphandle
{
ftphandle *ctrl;
if (nData->dir == FTPLIB_WRITE)
{
if (nData->buf != NULL) writeline(NULL, 0, nData);
}
else if (nData->dir != FTPLIB_READ) return 0;
if (nData->buf) free(nData->buf);
shutdown(nData->handle,2);
net_close(nData->handle);
ctrl = nData->ctrl;
#ifndef NOSSL
SSL_free(nData->ssl);
#endif
free(nData);
if (ctrl) return readresp('2', ctrl);
return 1;
}
/*
* FtpRead - read from a data connection
*/
int ftplib::FtpRead(void *buf, int max, ftphandle *nData)
{
int i;
if (nData->dir != FTPLIB_READ)
return 0;
if (nData->buf) i = readline(static_cast<char*
else
{
i = socket_wait(nData);
if (i != 1) return 0;
#ifndef NOSSL
if (nData->tlsdata) i = SSL_read(nData->ssl, buf, max);
else i = net_read(nData->handle,buf
#else
i = net_read(nData->handle,buf
#endif
}
if (i == -1) return 0;
nData->xfered += i;
if (nData->xfercb && nData->cbbytes)
{
nData->xfered1 += i;
if (nData->xfered1 > nData->cbbytes)
{
if (nData->xfercb(nData->xfer
nData->xfered1 = 0;
}
}
return i;
}
/*
* FtpWrite - write to a data connection
*/
int ftplib::FtpWrite(void *buf, int len, ftphandle *nData)
{
int i;
if (nData->dir != FTPLIB_WRITE) return 0;
if (nData->buf) i = writeline(static_cast<char
else
{
socket_wait(nData);
#ifndef NOSSL
if (nData->tlsdata) i = SSL_write(nData->ssl, buf, len);
else i = net_write(nData->handle, buf, len);
#else
i = net_write(nData->handle, buf, len);
i = net_write(nData->handle, buf, len);
#endif
}
if (i == -1) return 0;
nData->xfered += i;
if (nData->xfercb && nData->cbbytes)
{
nData->xfered1 += i;
if (nData->xfered1 > nData->cbbytes)
{
if (nData->xfercb(nData->xfer
nData->xfered1 = 0;
}
}
return i;
}
/*
* FtpSite - send a SITE command
*
* return 1 if command successful, 0 otherwise
*/
int ftplib::Site(const char *cmd)
{
char buf[256];
if ((strlen(cmd) + 7) > sizeof(buf)) return 0;
sprintf(buf,"SITE %s",cmd);
if (!FtpSendCmd(buf,'2',mp_ft
return 1;
}
/*
* FtpRaw - send a raw string string
*
* return 1 if command successful, 0 otherwise
*/
int ftplib::Raw(const char *cmd)
{
char buf[256];
strncpy(buf, cmd, 256);
if (!FtpSendCmd(buf,'2',mp_ft
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
*/
int ftplib::SysType(char *buf, int max)
{
int l = max;
char *b = buf;
char *s;
if (!FtpSendCmd("SYST",'2',mp
s = &mp_ftphandle->response[4]
while ((--l) && (*s != ' ')) *b++ = *s++;
*b++ = '\0';
return 1;
}
/*
* FtpMkdir - create a directory at server
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Mkdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"MKD %s",path);
if (!FtpSendCmd(buf,'2', mp_ftphandle)) return 0;
return 1;
}
/*
* FtpChdir - change path at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Chdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"CWD %s",path);
if (!FtpSendCmd(buf,'2',mp_ft
return 1;
}
/*
* FtpCDUp - move to parent directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Cdup()
{
if (!FtpSendCmd("CDUP",'2',mp
return 1;
}
/*
* FtpRmdir - remove directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Rmdir(const char *path)
{
char buf[256];
if ((strlen(path) + 6) > sizeof(buf)) return 0;
sprintf(buf,"RMD %s",path);
if (!FtpSendCmd(buf,'2',mp_ft
return 1;
}
/*
* FtpPwd - get working directory at remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Pwd(char *path, int max)
{
int l = max;
char *b = path;
char *s;
if (!FtpSendCmd("PWD",'2',mp_
s = strchr(mp_ftphandle->respo
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
*/
int ftplib::FtpXfer(const char *localfile, const char *path, ftphandle *nControl, accesstype type, transfermode mode)
{
int l,c;
char *dbuf;
FILE *local = NULL;
ftphandle *nData;
int rv=1; // 3.1-1
if (localfile != NULL)
{
printf("localfile: -%s-", localfile);
//local = fopen(localfile, (typ == ftplib::filewrite) ? "r" : "w");
char ac[3] = " ";
if ((type == ftplib::dir) || (type == ftplib::dirverbose)) { ac[0] = 'w'; ac[1] = '\0'; }
if (type == ftplib::fileread) { ac[0] = 'w'; ac[1] = '\0'; }
if (type == ftplib::filewriteappend) { ac[0] = 'r'; ac[1] = '\0'; }
if (type == ftplib::filereadappend) { ac[0] = 'a'; ac[1] = '\0'; }
if (type == ftplib::filewrite) { ac[0] = 'r'; ac[1] = '\0'; }
if (mode == ftplib::image) ac[1] = 'b';
#ifndef NOLFS
local = fopen64(localfile, ac);
if (type == ftplib::filewriteappend) fseeko64(local,mp_ftphandl
#else
local = fopen(localfile, ac);
if (type == ftplib::filewriteappend) fseek(local,mp_ftphandle->
#endif
if (local == NULL)
{
strncpy(nControl->response
return 0;
}
}
if (local == NULL) local = ((type == ftplib::filewrite)
|| (type == ftplib::filewriteappend)) ? stdin : stdout;
if (!FtpAccess(path, type, mode, nControl, &nData)) return 0;
dbuf = static_cast<char*>(malloc(
if ((type == ftplib::filewrite) || (type == ftplib::filewriteappend))
{
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");
break;
}
}
}
free(dbuf);
fflush(local);
if (localfile != NULL)
fclose(local);
return FtpClose(nData);
return rv;
}
/*
* FtpNlst - issue an NLST command and write response to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Nlst(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dir, ftplib::ascii);
}
/*
* FtpDir - issue a LIST command and write response to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Dir(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, ftplib::dirverbose, ftplib::ascii);
}
/*
* FtpSize - determine the size of a remote file
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Size(const char *path, int *size, transfermode mode)
{
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', mp_ftphandle)) return 0;
sprintf(cmd,"SIZE %s",path);
if (!FtpSendCmd(cmd,'2',mp_ft
else
{
if (sscanf(mp_ftphandle->resp
else rv = 0;
}
return rv;
}
/*
* FtpModDate - determine the modification date of a remote file
*
* return 1 if successful, 0 otherwise
*/
int ftplib::ModDate(const char *path, char *dt, int max)
{
char buf[256];
int rv = 1;
if ((strlen(path) + 7) > sizeof(buf)) return 0;
sprintf(buf,"MDTM %s",path);
if (!FtpSendCmd(buf,'2',mp_ft
else strncpy(dt, &mp_ftphandle->response[4]
return rv;
}
/*
* FtpGet - issue a GET command and write received data to output
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Get(const char *outputfile, const char *path, transfermode mode, off64_t offset)
{
mp_ftphandle->offset = offset;
if (offset == 0) return FtpXfer(outputfile, path, mp_ftphandle, ftplib::fileread, mode);
else return FtpXfer(outputfile, path, mp_ftphandle, ftplib::filereadappend, mode);
}
/*
* FtpPut - issue a PUT command and send data from input
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Put(const char *inputfile, const char *path, transfermode mode, off64_t offset)
{
mp_ftphandle->offset = offset;
if (offset == 0) return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewrite, mode);
else return FtpXfer(inputfile, path, mp_ftphandle, ftplib::filewriteappend, mode);
}
int ftplib::Rename(const char *src, const char *dst)
{
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',mp_ft
sprintf(cmd,"RNTO %s",dst);
if (!FtpSendCmd(cmd,'2',mp_ft
return 1;
}
int ftplib::Delete(const char *path)
{
char cmd[256];
if ((strlen(path) + 7) > sizeof(cmd)) return 0;
sprintf(cmd,"DELE %s",path);
if (!FtpSendCmd(cmd,'2', mp_ftphandle)) return 0;
return 1;
}
/*
* FtpQuit - disconnect from remote
*
* return 1 if successful, 0 otherwise
*/
int ftplib::Quit()
{
if (mp_ftphandle->dir != FTPLIB_CONTROL) return 0;
if (mp_ftphandle->handle == 0)
{
strcpy(mp_ftphandle->respo
return 0;
}
if (!FtpSendCmd("QUIT",'2',mp
{
net_close(mp_ftphandle->ha
return 0;
}
else
{
net_close(mp_ftphandle->ha
return 1;
}
}
int ftplib::Fxp(ftplib* src, ftplib* dst, const char *pathSrc, const char *pathDst, transfermode mode, fxpmethod method)
{
char *cp;
unsigned char v[6];
char buf[256];
int retval = 0;
sprintf(buf, "TYPE %c", mode);
if (!dst->FtpSendCmd(buf,'2',
if (!src->FtpSendCmd(buf,'2',
if (method == ftplib::defaultfxp)
{
// PASV dst
if (!dst->FtpSendCmd("PASV",'
cp = strchr(dst->mp_ftphandle->
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu,
if (dst->mp_ftphandle->correc
// PORT src
sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v
if (!src->FtpSendCmd(buf,'2',
// RETR src
strcpy(buf,"RETR");
if (pathSrc != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathSrc);
}
if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle)) return 0;
// STOR dst
strcpy(buf,"STOR");
if (pathDst != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathDst);
}
if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle))
{
/* this closes the data connection, to abort the RETR on
the source ftp. all hail pftp, it took me several
hours and i was absolutely clueless, playing around with
ABOR and whatever, when i desperately checked the pftp
source which gave me this final hint. thanks dude(s). */
dst->FtpSendCmd("PASV", '2', dst->mp_ftphandle);
src->readresp('4', src->mp_ftphandle);
return 0;
}
retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle));
}
else
{
// PASV src
if (!src->FtpSendCmd("PASV",'
cp = strchr(src->mp_ftphandle->
if (cp == NULL) return -1;
cp++;
sscanf(cp,"%hhu,%hhu,%hhu,
if (src->mp_ftphandle->correc
// PORT dst
sprintf(buf, "PORT %d,%d,%d,%d,%d,%d", v[2],v[3],v[4],v[5],v[0],v
if (!dst->FtpSendCmd(buf,'2',
// STOR dest
strcpy(buf,"STOR");
if (pathDst != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathDst) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathDst);
}
if (!dst->FtpSendCmd(buf, '1', dst->mp_ftphandle)) return 0;
// RETR src
strcpy(buf,"RETR");
if (pathSrc != NULL)
{
int i = strlen(buf);
buf[i++] = ' ';
if ((strlen(pathSrc) + i) >= sizeof(buf)) return 0;
strcpy(&buf[i],pathSrc);
}
if (!src->FtpSendCmd(buf, '1', src->mp_ftphandle))
{
src->FtpSendCmd("PASV", '2', src->mp_ftphandle);
dst->readresp('4', dst->mp_ftphandle);
return 0;
}
// wait til its finished!
retval = (src->readresp('2', src->mp_ftphandle)) & (dst->readresp('2', dst->mp_ftphandle));
}
return retval;
}
#ifndef NOSSL
int ftplib::SetDataEncryption(
{
if (!mp_ftphandle->tlsctrl) return 0;
if (!FtpSendCmd("PBSZ 0",'2',mp_ftphandle)) return 0;
switch(enc)
{
case ftplib::unencrypted:
mp_ftphandle->tlsdata = 0;
if (!FtpSendCmd("PROT C",'2',mp_ftphandle)) return 0;
break;
case ftplib::secure:
mp_ftphandle->tlsdata = 1;
if (!FtpSendCmd("PROT P",'2',mp_ftphandle)) return 0;
break;
default:
return 0;
}
return 1;
}
int ftplib::NegotiateEncryptio
{
int ret;
if (!FtpSendCmd("AUTH TLS",'2',mp_ftphandle)) return 0;
mp_ftphandle->sbio = BIO_new_socket(mp_ftphandl
SSL_set_bio(mp_ftphandle->
ret = SSL_connect(mp_ftphandle->
if (ret == 1) mp_ftphandle->tlsctrl = 1;
if (mp_ftphandle->certcb != NULL)
{
X509 *cert = SSL_get_peer_certificate(m
if (!mp_ftphandle->certcb(mp_
}
if (ret < 1) return 0;
return 1;
}
void ftplib::SetCallbackCertFun
{
mp_ftphandle->certcb = pointer;
}
#endif
void ftplib::SetCallbackIdleFun
{
mp_ftphandle->idlecb = pointer;
}
void ftplib::SetCallbackXferFun
{
mp_ftphandle->xfercb = pointer;
}
void ftplib::SetCallbackLogFunc
{
mp_ftphandle->logcb = pointer;
}
void ftplib::SetCallbackArg(voi
{
mp_ftphandle->cbarg = arg;
}
void ftplib::SetCallbackBytes(o
{
mp_ftphandle->cbbytes = bytes;
}
void ftplib::SetCallbackIdletim
{
mp_ftphandle->idletime.tv_
mp_ftphandle->idletime.tv_
}
void ftplib::SetConnmode(connmo
{
mp_ftphandle->cmode = mode;
}
void ftplib::ClearHandle()
{
mp_ftphandle->dir = FTPLIB_CONTROL;
mp_ftphandle->ctrl = NULL;
mp_ftphandle->cmode = ftplib::pasv;
mp_ftphandle->idlecb = NULL;
mp_ftphandle->idletime.tv_
mp_ftphandle->cbarg = NULL;
mp_ftphandle->xfered = 0;
mp_ftphandle->xfered1 = 0;
mp_ftphandle->cbbytes = 0;
#ifndef NOSSL
mp_ftphandle->tlsctrl = 0;
mp_ftphandle->tlsdata = 0;
mp_ftphandle->certcb = NULL;
#endif
mp_ftphandle->offset = 0;
mp_ftphandle->handle = 0;
mp_ftphandle->logcb = NULL;
mp_ftphandle->xfercb = NULL;
mp_ftphandle->correctpasv = false;
}
int ftplib::CorrectPasvRespons
{
struct sockaddr ipholder;
socklen_t ipholder_size = sizeof(ipholder);
if (getpeername(mp_ftphandle-
{
perror("getpeername");
net_close(mp_ftphandle->ha
return 0;
}
for (int i = 2; i < 6; i++) v[i] = ipholder.sa_data[i];
return 1;
}
ftphandle* ftplib::RawOpen(const char *path, accesstype type, transfermode mode)
{
int ret;
ftphandle* datahandle;
ret = FtpAccess(path, type, mode, mp_ftphandle, &datahandle);
if (ret) return datahandle;
else return NULL;
}
int ftplib::RawClose(ftphandle
{
return FtpClose(handle);
}
int ftplib::RawWrite(void* buf, int len, ftphandle* handle)
{
return FtpWrite(buf, len, handle);
}
int ftplib::RawRead(void* buf, int max, ftphandle* handle)
{
return FtpRead(buf, max, handle);
}
You'll need to add 'ftplib.lib' to your project.
ASKER
How can I use VC++ 6.0 to compile the library? All it came with was the .cpp and .h above. Where do I specify in my project to include the library once I've compiled it?
If you have just .cpp and .h, then will be easier. Just Add to your Project Files, all the .cpp and .h files that comes with SFTP. This will clear all errors.
ASKER
When I add the .cpp to my project, it produces 5 errors and 52 warnings.
All warnings deal with "inconsistent dll linkage. dllexport assumed."
errors:
ftplib.h(69) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(1243) : error C2065: 'fopen64' : undeclared identifier
ftplib.cpp(1243) : error C2440: '=' : cannot convert from 'int' to 'struct _iobuf *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
ftplib.cpp(1244) : error C2065: 'fseeko64' : undeclared identifier
All warnings deal with "inconsistent dll linkage. dllexport assumed."
errors:
ftplib.h(69) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(1243) : error C2065: 'fopen64' : undeclared identifier
ftplib.cpp(1243) : error C2440: '=' : cannot convert from 'int' to 'struct _iobuf *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
ftplib.cpp(1244) : error C2065: 'fseeko64' : undeclared identifier
All warnings deal with "inconsistent dll linkage. dllexport assumed."
Hmm, appears to be that all .cpp are the source code to build a dll, then you have to create a separated "windows dll" project. Include all those files and compile.
This will generate a .dll and a .lib
Include the .lib into your main project and build it.
Now your .exe file will load the .dll automatically when running.
Hmm, appears to be that all .cpp are the source code to build a dll, then you have to create a separated "windows dll" project. Include all those files and compile.
This will generate a .dll and a .lib
Include the .lib into your main project and build it.
Now your .exe file will load the .dll automatically when running.
ASKER
I tried Win32 Dynamic Link Library and Win32 Static Link Library, and I'm still getting the errors.
You'll need to set '_WIN32' in your project settings (that is, if we're talking about http://kasablanca.berlios.de/ftplibpp/ftplibpp.html)
ASKER
Yep, that's the library I'm using :)
Where do I set that in VC++?
Where do I set that in VC++?
Go to your project settings, choose the 'C++' tab and add that in the 'Preprocessor definitions' field.
ASKER
I put it in there, still having the same problem. Here are the contents of my preprossor directives:
"_WIN32,_DEBUG,_WINDOWS,_M BCS,_USRDL L,FTPLIB_E XPORTS"
"WIN32,_DEBUG,_WINDOWS,_MB CS,_USRDLL ,FTPLIB_EX PORTS,_WIN 32"
tried it both ways
"_WIN32,_DEBUG,_WINDOWS,_M
"WIN32,_DEBUG,_WINDOWS,_MB
tried it both ways
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Did the replacement and added ftplib.cpp to the project. All the warnings are gone, but the 5 errors remain:
ftplib.h(71) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(1243) : error C2065: 'fopen64' : undeclared identifier
ftplib.cpp(1243) : error C2440: '=' : cannot convert from 'int' to 'struct _iobuf *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
ftplib.cpp(1244) : error C2065: 'fseeko64' : undeclared identifier
ftplib.h(71) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(1243) : error C2065: 'fopen64' : undeclared identifier
ftplib.cpp(1243) : error C2440: '=' : cannot convert from 'int' to 'struct _iobuf *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
ftplib.cpp(1244) : error C2065: 'fseeko64' : undeclared identifier
Then, add 'NOSSL' and 'NOLFS' to the ''Preprocessor definitions''
ASKER
Will that compromise my ability to use the encrypted (SSL) part of ftplib? Thats the whole reason I'm using it.
No, not at all - if only affects the part of the code that is considered 'portable'.
ASKER
hrm, ok, turns out I can't use the NOSSL or I lose the NegotiateEncryption() and related functions. But the NOLFS fixed the errors. Except I still get the two std namespace errors
ftplib.h(71) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ftplib.h(71) : error C2871: 'std' : does not exist or is not a namespace
ftplib.cpp(89) : error C2871: 'std' : does not exist or is not a namespace
ASKER
If I take out the namespace std references, it gives me this:
Compiling...
ftplib.cpp(438) : warning C4101: 'ret' : unreferenced local variable
xfer.cpp
Linking...
ftplib.obj : error LNK2001: unresolved external symbol _SSL_new
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_set_verify
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_new
ftplib.obj : error LNK2001: unresolved external symbol _SSLv3_method
ftplib.obj : error LNK2001: unresolved external symbol _SSL_library_init
ftplib.obj : error LNK2001: unresolved external symbol _WSAStartup@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_free
ftplib.obj : error LNK2001: unresolved external symbol _SSL_free
ftplib.obj : error LNK2001: unresolved external symbol _select@20
ftplib.obj : error LNK2001: unresolved external symbol _recv@16
ftplib.obj : error LNK2001: unresolved external symbol _SSL_read
ftplib.obj : error LNK2001: unresolved external symbol _send@16
ftplib.obj : error LNK2001: unresolved external symbol _SSL_write
ftplib.obj : error LNK2001: unresolved external symbol _connect@12
ftplib.obj : error LNK2001: unresolved external symbol _closesocket@4
ftplib.obj : error LNK2001: unresolved external symbol _setsockopt@20
ftplib.obj : error LNK2001: unresolved external symbol _socket@12
ftplib.obj : error LNK2001: unresolved external symbol _gethostbyname@4
ftplib.obj : error LNK2001: unresolved external symbol _inet_addr@4
ftplib.obj : error LNK2001: unresolved external symbol _htons@4
ftplib.obj : error LNK2001: unresolved external symbol _getservbyname@8
ftplib.obj : error LNK2001: unresolved external symbol _accept@12
ftplib.obj : error LNK2001: unresolved external symbol ___WSAFDIsSet@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_connect
ftplib.obj : error LNK2001: unresolved external symbol _SSL_set_bio
ftplib.obj : error LNK2001: unresolved external symbol _BIO_new_socket
ftplib.obj : error LNK2001: unresolved external symbol _listen@8
ftplib.obj : error LNK2001: unresolved external symbol _bind@12
ftplib.obj : error LNK2001: unresolved external symbol _getsockname@12
ftplib.obj : error LNK2001: unresolved external symbol _shutdown@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_get_peer_certificate
ftplib.obj : error LNK2001: unresolved external symbol _getpeername@12
Debug/xfer.exe : fatal error LNK1120: 32 unresolved externals
Compiling...
ftplib.cpp(438) : warning C4101: 'ret' : unreferenced local variable
xfer.cpp
Linking...
ftplib.obj : error LNK2001: unresolved external symbol _SSL_new
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_set_verify
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_new
ftplib.obj : error LNK2001: unresolved external symbol _SSLv3_method
ftplib.obj : error LNK2001: unresolved external symbol _SSL_library_init
ftplib.obj : error LNK2001: unresolved external symbol _WSAStartup@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_CTX_free
ftplib.obj : error LNK2001: unresolved external symbol _SSL_free
ftplib.obj : error LNK2001: unresolved external symbol _select@20
ftplib.obj : error LNK2001: unresolved external symbol _recv@16
ftplib.obj : error LNK2001: unresolved external symbol _SSL_read
ftplib.obj : error LNK2001: unresolved external symbol _send@16
ftplib.obj : error LNK2001: unresolved external symbol _SSL_write
ftplib.obj : error LNK2001: unresolved external symbol _connect@12
ftplib.obj : error LNK2001: unresolved external symbol _closesocket@4
ftplib.obj : error LNK2001: unresolved external symbol _setsockopt@20
ftplib.obj : error LNK2001: unresolved external symbol _socket@12
ftplib.obj : error LNK2001: unresolved external symbol _gethostbyname@4
ftplib.obj : error LNK2001: unresolved external symbol _inet_addr@4
ftplib.obj : error LNK2001: unresolved external symbol _htons@4
ftplib.obj : error LNK2001: unresolved external symbol _getservbyname@8
ftplib.obj : error LNK2001: unresolved external symbol _accept@12
ftplib.obj : error LNK2001: unresolved external symbol ___WSAFDIsSet@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_connect
ftplib.obj : error LNK2001: unresolved external symbol _SSL_set_bio
ftplib.obj : error LNK2001: unresolved external symbol _BIO_new_socket
ftplib.obj : error LNK2001: unresolved external symbol _listen@8
ftplib.obj : error LNK2001: unresolved external symbol _bind@12
ftplib.obj : error LNK2001: unresolved external symbol _getsockname@12
ftplib.obj : error LNK2001: unresolved external symbol _shutdown@8
ftplib.obj : error LNK2001: unresolved external symbol _SSL_get_peer_certificate
ftplib.obj : error LNK2001: unresolved external symbol _getpeername@12
Debug/xfer.exe : fatal error LNK1120: 32 unresolved externals
You'll also need to add ws2_32.lib and the corresponding library for OpenSSL
ASKER
Alright! It compiles!
Any idea why it would be giving "abnormal program termination" when run on any PC but the one it was built on? Do I need to include more things?
Any idea why it would be giving "abnormal program termination" when run on any PC but the one it was built on? Do I need to include more things?
>>Any idea why it would be giving "abnormal program termination" when run on any PC but the one it >>was built on?
Have you installed OpenSSL on that machine as well? Remember, you need the runtime environment also...
Have you installed OpenSSL on that machine as well? Remember, you need the runtime environment also...
ASKER
Ah, I do need OpenSSL on every machine I run my program on then.
Anyway to compile it all (well, all that I need) into one exe?
Anyway to compile it all (well, all that I need) into one exe?
Nope, there might be a way to do so, but since the binaries are free to distribute, that's overkill and you might get in trouble with some Open Source license...
ASKER
OK, thanks jkl, full points!
Thanx! :o)
BTW, did the file modification time Q work for you?
BTW, did the file modification time Q work for you?
ASKER
Yep, it did!
So now I've got a basic SFTP client that only transfers the file if it is newer on the local computer.
Thanks!
So now I've got a basic SFTP client that only transfers the file if it is newer on the local computer.
Thanks!
ASKER
Do you happen to know of anyway to make it easier to distribute this program, without installing the full OpenSSL on every computer I want to use it on?
Can I just bring the *.lib with me, and put them in the same dir as the .exe (assuming I change where they are when I compile my project)?
Can I just bring the *.lib with me, and put them in the same dir as the .exe (assuming I change where they are when I compile my project)?
Will check, hang on...
ASKER
Thanks.
Actually, it should be enough if you copy the OpenSSL DLL in your program's directory.
ASKER
Do I have to build the DLL? Or has it been installed on my system?
ASKER
Never mind, found em
ASKER
Do I just need to included them in the program directory, or do I need to register them somehow?
No, registration is only necessary if a DLL exposes COM objects, which this one certainly does not. Copying it should be enough,
ASKER
Hrm, not working.
All I need are
ssleay32.dll
libeay32.dll
libssl32.dll
??
All I need are
ssleay32.dll
libeay32.dll
libssl32.dll
??
Try the DependencyWalker from www.dependencywalker.com to see if anything is missing.
It could be a .lib file or maybe comes with full source code as .cpp files