Giter Club home page Giter Club logo

ftplibpp's Introduction

ftplibpp

Platform independent c++ library providing ftp client functionality.

ftplibpp contains a c++ class providing ftp client functionality. It supports all basic ftp functionality plus some advanced features like resuming, fxp, ssl/tls encryption, large file support, or logging to fit todays standards.

Build

Docker (Linux)

docker build -t build-env .
docker run -e -v $PWD:/src -w /src build-env make

MacOS without SSL

NOSSL=1 make

Documentation

ftplibpp provides a c++ class providing ftp client functionality. It supports all basic ftp functionality plus some advanced features like resuming, fxp, ssl/tls encryption, large file support, or logging to fit todays standards. The very base of ftplibpp is Thomas Pfau's ftplib c library.

Every ftp session is represented by an ftplib object, whose methods are called to communicate with the ftp server. The ftp sessions should begin with a call to myftp.Connect("myftp.org:21") (and maybe myftp.NegotiateEncryption() ), be followed with myftp.Login("myuser","mypass") and ended by myftp.Quit(). For the magic in between, read the class methods documentation. Most methods have their tasks pretty much explained in their name. ftplibpp uses OpenSSL for encryption functionality, if you don't need it you can set the NOSSL flag (e.g. g++ -c ftplib.cpp -DNOSSL). If your system does not feature large file support (or does not need specific LFS functions, because it's built in yet) you can use the NOLFS flag (e.g. g++ -c ftplib.cpp -DNOLFS). The flag _FTPLIB_SSL_CLIENT_METHOD_ exists to override the openssl client method in use, the default is TLSv1_2_client_method, override by compiling with -D_FTPLIB_SSL_CLIENT_METHOD_=${SOME_METHOD}.

Public types

Methods

Public static methods

Details

[typedef]

typedef int (*FtpCallbackIdle)(void *arg);

[typedef]

typedef void (* FtpCallbackLog)(char *str, void* arg, bool out);

Notes:

out indicates wether the log information in str is incoming or outgoing.

[typedef]

typedef int (*FtpCallbackXfer)(off64_t xfered, void *arg);

[typedef]

typedef int (*FtpCallbackCert)(void *arg, X509 *cert);

This type is used in RawOpen.

This type determines how data is transferred.

This type determines wether data is to be transferred using the pasv or active mode.

This type is used in the Fxp method.

This type determines wether data is encrypted or not.

[constructor]

Class constructor, an ftplib object is responsible for the ftp session.

LastResponse returns a pointer to the last response c-styled string sent by the server. This can be parsed by the user program todetermine more information about the last request or can be displayed along with an error message.

Returns:

A pointer to the last server response string. Otherwise, NULL is returned.

Connect establishes a connection to the FTP server on the specified machine and returns a handle which can be used to initiate data transfers. The host name should be specified in the form of <host>:<port> <host> may be either a host name or ip address. <port> may be either a service name or a port number.

Parameters:

  • host: The name of the host machine to connect to and optionally an alternate port number to use (ftp.myftp.com:321).

Returns:

If the connection to the remote server if successful, Connect() returns 1. Otherwise, 0 is returned.

Login attempts to login to the remote system with the supplied username and password.

Parameters:

  • user: Specifies the username.
  • pass: Specifies the user's password.

Returns:

Returns 1 if successful or 0 on error.

Site sends the specified command as an argument to a SITE command.

Parameters:

  • cmd: A string containing a SITE subcommand.

Returns:

Returns 1 if successful or 0 on error.

Raw sends the specified command unmodified.

Parameters:

  • cmd: A string containing a custom ftp command.

Returns:

Returns 1 if successful or 0 on error.

SysType issues a SYST command to the remote system and attempts to parse the system type out of the response and return it to the user's buffer.

Parameters:

  • buf: A pointer to a buffer where the result will be returned to.
  • max: Specifies the size of the user buffer.

Returns:

Returns 1 if successful or 0 on error.

Mkdir sends a make directory request to the remote system.

Parameters:

  • path: Specifies the argument to mkdir on the remote system.

Returns:

Returns 1 if successful or 0 on error.

Sends a change working directory request to the server using the specified path.

Parameters:

  • path: Specifies the desired working directory on the server.

Returns:

Returns 1 if successful or 0 on error.

Cdup sends a CDUP command to the remote server.

Returns:

Returns 1 if successful or 0 on error.

Rmdir sends a remove directory request to the remote server.

Parameters:

  • path: A string containing the name of a remote directory.

Returns:

Returns 1 if successful or 0 on error.

Pwd attempts to determine the current default directory at the server and return it to the user's buffer.

Parameters:

  • path: A pointer to a buffer where the result should be returned.
  • max: Specifies the size of the user's buffer.

Returns:

Returns 1 if successful or 0 on error.

Performs a short form directory listing of the specified path on the remote system. The results are written to the specified file.

Parameters:

  • output: Specifies the name of a file to receive the directory listing. path Specifies an argument to ls on the remote system.

Returns:

Returns 1 if successful or 0 on error.

Sends a LIST -aL command to the server with the specified path. The response to this is usually a long format directory listing which will be written to the file named in outputfile. If outputfile is specified as NULL, the list will be written to stdout.

Parameters:

  • output: Specifies the name of a file to receive the directory listing.
  • path: Specifies an argument to 'ls' on the remote system.

Returns:

Returns 1 if successful or 0 on error.

Size attempts to determine the size of a remote file.

Parameters:

  • path: A pointer to a buffer where the result should be returned.
  • size: A pointer to an int where the size will be returned.
  • mode: Specifies the transfer mode as ftplib::image or ftplib::ascii.

Returns:

If a good response is received and the size is successfully parsed out of the result, 1 is returned. Otherwise, 0 is returned.

ModDate attempts to determine the last access time of a remote file and return it to the user's buffer. The date and time are returned as a string in the format 'YYYYMMDDHHMMSS'.

Parameters:

  • path: Name of remote file to be checked.
  • buf: A pointer to a buffer where the result should be returned.
  • max: Specifies the size of the user's buffer.

Returns:

If a good response is received and the size is successfully parsed out of the result, 1 is returned. Otherwise, 0 is returned.

Copies the contents of a remote file to a local file.

Parameters:

  • output: Name of a local file to receive the contents of the remote file.
  • path: Name of remote file to be retrieved.
  • mode: Specifies the transfer mode as ftplib::image or ftplib::ascii.

Returns:

Returns 1 if successful or 0 on error.

Copies the contents of a remote file from a given offset and appends it to a local file. Not all ftp servers might implement this feature.

Parameters:

  • output: Name of a local file to receive the contents of the remote file.
  • path: Name of remote file to be retrieved. mode Specifies the transfer mode as ftplib::image or ftplib::ascii.
  • offset: Point from where the copy is suppossed to begin.

Returns:

Returns 1 if successful or 0 on error.

Transfers a local file to the remote system.

Parameters:

  • input: Specifies the name of a local file to be transfered to the server.
  • path: Specifies the name to be given to the file on the remote system.
  • mode: Specifies the transfer mode as ftplib::image or ftplib::ascii.

Returns:

Returns 1 if successful or 0 on error.

Copies the contents of a local file from a given offset and appends it to a remote file. Not all ftp servers might implement this feature.

Parameters:

  • input: Specifies the name of a local file to be transfered to the server.
  • path: Specifies the name to be given to the file on the remote system.
  • mode: Specifies the transfer mode as ftplib::image or ftplib::ascii.
  • offset: Point from where the copy begins.

Returns: Returns 1 if successful or 0 on error.

FtpRename sends a rename request to the remote server.

Parameters:

  • src: A string containing the current name of the remote file.
  • dst: A string containing the desired new name for the remote file.

Returns: Returns 1 if successful or 0 on error.

Requests that the server remove the specified file from the remote file system.

Parameters:

  • path: The path to the file which is to be removed.

Returns:

Returns 1 if successful or 0 on error.

On an already secured ftp session, SetDataEncryption() specifies if the data connection channel will be secured for the next data transfer.

Parameters:

  • enc: either ftplib::unencrypted or ftplib::secure.

Returns:

Returns 1 if successful and 0 if the control connection isn't secure or on error.

Notes:

See NegotiateEncryption

This Method is to be called after Connect and before Login to secure the ftp communication channel.

Returns:

Returns 1 if successful and 0 if the ssl negotiation failed.

Notes:

The ftplibpp library uses an ssl/tls encryption approach defined in the RFC4217 standard.

Quit() issues a 'QUIT' command and closes the connection to the remote server.

When SetCallbackBytes is set to a bigger value than 0, a callback function can be called during an ftp data transfer. If the callback function returns 0, the data transfer is aborted. The callback function has two parameters: xfered & arg. xfered is the amount of bytes yet transfered during the data connection and arg contains either NULL or a custom pointer set by SetCallbackArg. If pointer is specified as NULL the xfer callback is disabled.

Parameters:

  • pointer: A pointer to a static function of the type FtpCallbackXfer.

Notes:

Since FtpCallbackXferFunction only accepts pointers to static functions, it might appear problematic in an oo c++ context. However there's an easy way to use it anyway. Using SetCallbackArg you supply the class a pointer to the object the method of which you'd like to call from the ftplib object. That pointer is then passed back with call to the callback function. From the static callback function you can perform a cast of arg to a pointer of the your desired object, and call its method. valid code could look like this:

...
static int callback(off64_t xfered, void* arg); // static callback function defined in myclass.h
void mymethod(); // common myclass method
...
int myclass::callback(off64_t xfered, void* arg) {
  ((*myclass)(arg)->mymethod(); // casting the pointers to the correct type and calling class method
  return 1;
}
...
void myclass::mymethod() {
  DoSomething();
}
...
myftp.SetCallbackArg(this); // supply the myftp object the pointer to the current (myclass) object
myftp.SetCallbackBytes(1024); // issue a xfer callback every kb
myftp.SetCallbackXferFunction(class::callback);
...

SetCallbackLogFunction enables the logging callback. Every time there's been data read from the control connection, pointer is called with a c-styled string and a custom pointer specified in SetCallbackArg. If pointer is specified as NULL logging callback is disabled.

Parameters:

Notes:

See SetCallbackIdleFunction.

SetCallbackCertFunction enables the ssl/tls certification callback. When you use encryption and you call this method with a certification callback function, it is called when connecting to the server. In the callback function you decide via the boolean return value whether the certificate is valid or not. Certification checking is an advanced issue, and you should read into the openssl documentation if you plan to implement it. pointer is called with a custom pointer specified in SetCallbackArg and the certificate from the Server. If pointer is specified as NULL certification callback is disabled.

Parameters:

Notes:

Sample implementation:

bool MyCallbackCert(void *arg, X509 *cert) {
  if (cert == NULL) {
    printf("Peer sent no certificate.\n");
    return false;
  } else {
    char peer_CN[265];
    int len;
    X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_CN, 256);
    printf("subject: %s\n", peer_CN);
    X509_NAME_get_text_by_NID(X509_get_issuer_name(cert), NID_commonName, peer_CN, 256);
    printf("issuer: %s\n", peer_CN); return true;
  }
}

void SetCallbackIdleFunction ( FtpCallbackIdle pointer )

SetCallbackLogFunction enables the idle callback. When a connection idles, for a period bigger than 0 set in SetCallbackIdletime a callback to the argument function is issued.

Parameters:

Notes:

See SetCallbackXferFunction.

SetCallbackArg submits a pointer of custom type to the object, this pointer is returned with a callback function. A good idea is to store the ftplib owners (or whatever object should handle the callback) pointer in it to use it the way described in the SetCallbackXferFunction entry.

Parameters:

  • arg: A pointer of a custom type.

SetCallbackBytes specifies the frequency of xfer callbacks. The xfer callback returns the amount of bytes yet transfered on this transfer.

Parameters:

  • bytes: Specifies the frequency in transfered bytes. A value of 100000 would mean every 100000 bytes an xfer callback is issued.

SetCallbackIdletime specifies how long a data socket can idle, without an idle callback beeing issued.

Parameters:

  • time: Time in msec.

Notes:

The default value of 0, means that on every idle a callback happens. if you don't want this behaviour you have to set a (higher) value.

SetConnmode specifies which data connection method is to be used for the next data transfer.

Parameters:

  • mode: Either ftplib::pasv (passive mode, default) or ftplib::port (active mode).

Some Ftp-Servers, which run behind a NAT, return their local ip-adresses as PASV replies. When this option is turned on PASV replies are corrected using the ip address the ftp session is currently connected to.

Parameters:

  • b: true turns the correction on, false turns it off.

[static]

Fxp is a static function. It uses two ftp session objects and transfer a certain file between them.

Parameters:

  • src: Source ftplib object.
  • dst: Destination ftplib object.
  • pathSrc: Path to file to be copied copy (/incoming/myfile.tar.gz).
  • pathDst: Path to file destination (/pub/myfile_from_some_ftp.tar.gz).
  • mode: Either ftplib::ascii (ascii) or ftplib::image (binary). Method either ftplib::defaultfxp (PASV on dst, PORT on src) or ftplib::alternativefxp (PASV on src, PORT on dst).

Returns:

Returns 1 if successful, -1 if initilization failed ("PORT" and "PASV"), or 0 if the data transfer somehow failed.

Notes:

Fxp - direct Ftp to Ftp transfer - is rather an exploit than a feature and might thus be prevented by many servers. Currently Fxp does not work with encrypted data connections, so be sure to switch to unencrypted data channels before performing fxp.

### int RawRead ( void* buf, int max, ftphandle *handle )

RawRead copies up to max bytes of data from the specified data connection and returns it to the user's buffer. If the data connection was opened in ascii mode, no more than one line of data will be returned.

  • buf: Specifies the address of a buffer where received data will be written. max Specifies the size of the user's buffer.
  • handle: A handle returned by FtpAccess().

Returns:

Returns the number of bytes written to the user's buffer or -1 on error or end of file.

RawWrite sends data to a remote file. If the file were accessed in record mode, the necessary conversions are performed.

Parameters:

  • buf: A buffer containing the data to be sent to the remote file.
  • len: The number of bytes to be sent from 'buf'.
  • handle: A handle returned by RawOpen().

Returns:

Returns the number of bytes sent from the user's buffer or -1 on error.

RawOpen() opens a remote file or directory and returns a handle for the calling program to use to transfer data.

Parameters:

  • path: Specifies the name of the remote file or directory to open.
  • type: Specifies the type of transfer to be performed. ftplib::dir performs a terse directory. ftplib::dirverbose performs a verbose directory. ftplib::fileread opens a remote file for reading. ftplib::filewrite creates a remote file and readies it for writing. ftplib::filewriteappend and ftplib::filereadappend are for appending file operations.
  • mode: Specifies the transfer mode as ftplib::ascii or ftplib::image.

Returns:

Returns 1 if successful or 0 on error.

Closes the data connection specified by handle and frees associated resources.

Parameters:

Returns:

Returns 1 if successful or 0 on error.

ftplibpp's People

Contributors

mkay229 avatar mkulke avatar philipdeegan avatar wadealer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ftplibpp's Issues

Constructor bug - memory allocations

If one of the two allocs in the constructor fails, the code results in random memory access, and either the program will crash or the object will be left in an inconsistent state.

Not working with SFTP

Hi,
I've tried to use this library with a SFTP server, but the connect method always returns 0.

Does anyone knows how to use this lib with sftp?

The server i've tried is at:

199.71.215.197:2222

Works fine on FileZilla.

I've traced the code but i'm not able to figure out whats going on.
The problem seems the readline('2'... call which works ok nor normal ftp but not for sftp.

compile error on ubuntu server 14.02 version

rocky@rocky-VirtualBox:~/code/DevelopEnv/ftplibpp$ make
cc -shared -Wl,-install_name,libftp.so.2 -lssl -lc -o libftp.so.2.0 ftplib.o
/usr/bin/ld: bad -rpath option
collect2: error: ld returned 1 exit status
make: *** [libftp.so.2.0] Error 1

NegotiateEncryption not working after connection

Hello,
I'm trying to connect to our own FTPS server but can't seem to make an encrypted connection tried other servers like "test.rebex.net" but neither does connect to with ftplibpp but on filezilla i can send and recieve encrypted files. ı would be thankfull if someone can help me understand it
ftp.zip
.

"TLS Session resumption" not supported by ftplibpp ?

Hello,
I'm using ftplibpp with OpenSSL and I'm trying to connect to a Filezilla Server with FTP over TLS (FTPS).

I just found that ftplibpp can't transfer data (even if already securely connected) to a FileZilla Server that Requires TLS session resumption, since I get this error:
"450 TLS session of data connection has not resumed or the session does not match the control connection"

If I untick "Require TLS session resumption on data connection when using PROT P" in FileZilla Server settings, then I'm able to do the transfers.

So, is there a way to add "TLS session resumption" ability to the ftplibpp ??

ftplib::FtpClose - please add NULL pointer checking, otherwise unwanted crash may occur.

When NULL is not checked, passing NULL pointer causes crash when attempting to dereference nData->dir. As far as int FtpClose(ftphandle *nData); is not internal function, the argument passed cannot be guaranteed.

/*
 * 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);

Please add NULL pointer checking here:

/*
 * FtpClose - close a data connection
 */
int ftplib::FtpClose(ftphandle *nData)
{
  ftphandle *ctrl;

  if (nData==NULL) return 0;
  if (nData->dir == FTPLIB_WRITE)
  {
    if (nData->buf != NULL) writeline(NULL, 0, nData);
  }

Building error on VS2008

winsock2.h should be include. I did not test with more recent version of Visual Studio but on 2008 struct tv is not recognized.

#if defined(_WIN32)

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */

#include <time.h>
#include <Winsock.h>    // <--------- Add this
#endif

If this is only a problem for VS2008, then

#if _MSC_VER  <= 1500
    #include <Winsock.h>
#endif

Variable ret is never used - please suppress a warning

function ftplib::Connect - Current code uses a variable ret in only one branch.

#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

Proposed fix No1 - variable ret is completelly useles and so it can be elliminated anyway:

#if defined(_WIN32)
  if((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
  if(inet_aton(lhost, &sin.sin_addr) == 0)
#endif

Proposed alternative fix No2 - declare variable ret in one branch:

#if defined(_WIN32)
  if((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
  int ret = inet_aton(lhost, &sin.sin_addr);
  if(ret == 0)
#endif

Defect in ftplib::FtpXfer

I have found critical defect inside ftplib::FtpXfer function.

The rv variable is signalised to 0 when 'short write' occurs. But the signal is not used in the further code. It means that file written is cut and user is not notified about it.

Anyway, rv variable is only assigned a value that is never used.

I propose following fix at the end of the function:
------------------CURRENT---------------

	free(dbuf);
	fflush(local);
	if (localfile != NULL) fclose(local);
	return FtpClose(nData);
}

-----------------FIXED-----------------------

	free(dbuf);
	fflush(local);
	if (localfile != NULL) fclose(local);
        if(rv) return FtpClose(nData);
        FtpClose(nData);
       return 0;
}

Any other idea?


/*
 * 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_ftphandle->offset,SEEK_SET);
#else
		local = fopen(localfile, ac);
		if (type == ftplib::filewriteappend) fseek(local,mp_ftphandle->offset,SEEK_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_BUFSIZ));
	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);
}

Don't use the "select" system call, use poll or epoll

In "ftplib::socket_wait" select is used which contains the unfixable problem of memory corruption and memory leaks on any linux system that uses more then 1024 file descriptions (which hopefully all systems will become one day as this limit is a laughable low amount from 1970 days of Unix)

Only poll and epoll are useable in modern systems.

not really an issue

First, thanks for the excellent library. I just wonder why in the sample program you use "new" instead of instantiating the class directly, i.e.

    ftplib ftp;
    ftp.Connect(config().host.c_str());
    int loggedin = ftp.Login(config().username.c_str(), password.c_str());
    ftp.Quit();

ftplib::Login bad logic ?

Hi,

What is the logic behind this

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',mp_ftphandle))
	{
		if (mp_ftphandle->ctrl != NULL) return 1;
// ------>	if (*LastResponse() == '2') return 1; 
// <------------ HERE, is it to test for anonymous login ?
		return 0;
	}
	sprintf(tempbuf,"PASS %s",pass);
	return FtpSendCmd(tempbuf,'2',mp_ftphandle);
}

If we are losing the connection between the connect but before the Login operation this condition will be true and login function will return 1 (succeed) instead of returning 0 (failed) even if network are now down. If we remove this condition, the logic is going to be right.

What about removing this condition and leting the user use the Login function even if it was accepted as anonymous ?

Critical memory leak in int ftplib::FtpOpenPort

Original code:

  ftphandle *ctrl = static_cast<ftphandle*>(calloc(1,sizeof(ftphandle)));
  if (ctrl == NULL)
  {
    perror("calloc");
    net_close(sData);
    return -1;
  }
  if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc(FTPLIB_BUFSIZ))) == NULL))
  {
    perror("calloc");
    net_close(sData);
    free(ctrl);
    return -1;
  }

  if (!FtpSendCmd(cmd, '1', nControl))
  {
    FtpClose(*nData);
    *nData = NULL;
    return -1;     /// THIS CAUSES MEMORY LEAK IN CRTL!!!
  }

Proposed fix:

ftphandle *ctrl = static_cast<ftphandle*>(calloc(1,sizeof(ftphandle)));
 if (ctrl == NULL)
 {
   perror("calloc");
   net_close(sData);
   return -1;
 }
 if ((mode == 'A') && ((ctrl->buf = static_cast<char*>(malloc(FTPLIB_BUFSIZ))) == NULL))
 {
   perror("calloc");
   net_close(sData);
   free(ctrl);
   return -1;
 }

 if (!FtpSendCmd(cmd, '1', nControl))
 {
   FtpClose(*nData);
   *nData = NULL;
   free(ctrl);			// Fixed by JFO - potential memory leak.
   return -1;
 }

Hello world ? (Visual Studio)

Hi,
I spent a decent time reading the doc, but did not understand how to make a little Hello World!
(IMHO a key feature for such a distributed lib is to provide an quick way to see first example. Out-of the-box-hello-world is VERY important for user experience.)
Could you please explain how to build and run the Hello world on Windows/Visual Studio ?
Thank you!

如何获取文件列表?

Dir函数获取的列表,并没有包括文件类型
下载的时候如何判断是啥类型?

Build error on Unix/Linux

#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

ret is not declared, we should have

#if defined(_WIN32)
	if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
	int ret = inet_aton(lhost, &sin.sin_addr);
	if (ret == 0)
#endif

ls command missing

ls or list command is missing. i tried setting the ftp->FtpSendCmd("LIST -aL",'2',ftp->mp_ftphandle); command to public and sending manually with no avail. are there more debug messages in a flag ?

【Consultation】getservbyname alaways return NULL

I'm having some problems with the ftplib library and would like to ask you for advice.
I failed to call Connect() in initramfs to log in to the FTP server.
I checked the code of ftplib.cpp and found that getservbyname() returned a failure.

if ((pse = getservbyname("ftp","tcp")) == NULL)
	{
		perror("getservbyname");
		free(lhost);
		return 0;
	}

However,Connect in romfs can successfully login to the ftp server
I tried to copy /etc/services from romfs to initramfs , but it still failed to log in.
I do not know what is wrong, Can you give me some suggestions?

Makefile error

While building the project on Code::Blocks, encountered an error at Makefile...

-------------- Build: Debug in ftplibpp (compiler: GNU GCC Compiler)---------------

Checking if target is up-to-date: mingw32-make.exe -q -f Makefile Debug
Running command: mingw32-make.exe -f Makefile Debug
process_begin: CreateProcess(NULL, uname, ...) failed.
mingw32-make.exe: *** No rule to make target 'Debug'. Stop.
Process terminated with status 2 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))

ftplib::Pwd - useless postincrement causes unwanted warning

*
 * 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->response, '"');
  if (s == NULL) return 0;
   s++;
  while ((--l) && (*s) && (*s != '"')) *b++ = *s++;
  *b++ = '\0';  // !!!! This causes a warning
  return 1;
}

Proposed fix:

*
 * 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->response, '"');
  if (s == NULL) return 0;
   s++;
  while ((--l) && (*s) && (*s != '"')) *b++ = *s++;
  *b = '\0';
  return 1;
}

'ModDate' returns strange-format datetime

'Dir' returns the results like 'xxxx Aug 13 20:38', it's correct. but 'ModDate' returns '20230813123830.245', obviously it's not in 'YYYYMMDDHHMMSS' format. It happens on win10 22h2 and win11 22h2. I use vs2022 btw.

Get() requests multiple times and reports an error

An error will be reported when the number of Get() requests is too many. SSL_ Read feedback read:

No error
Control socket read failed: No error

It's not just Get() . This problem occurs when a function is frequently requested for a period of time

The function ftplib::sprint_rest() is wrong

Why do you think that only APPLE handles 64 bit variables?

Proese use this fix:
void ftplib::sprint_rest(char *buf, off64_t offset) {
#if sizeof(offset)>4
sprintf(buf,"REST %lld",offset);
#else
sprintf(buf,"REST %ld",offset);
#endif
}

or if you are paranoid enougs and absolutelly sure that thare does not exist 32 bit code on APPLE:
void ftplib::sprint_rest(char *buf, off64_t offset) {
#if defined(APPLE) || sizeof(offset)>4
sprintf(buf,"REST %lld",offset);
#else
sprintf(buf,"REST %ld",offset);
#endif
}

Working with SSL?

Sorry to open this here as an issue, but I've been struggling to get this working with SSL and I'm not sure if this is the right place to ask for help. I'm using Visual Studio 2005 to compile ftplibpp and openssl to work on Windows CE.
ftp=new ftplib();
if(ftp->Connect(":990")) {
ftp->SetCallbackCertFunction(CertificateCallback);
ret=ftp->NegotiateEncryption();

NegotiateEncryption stage which is returning with -1 and sometimes popping up a notepad editor with the text "write: errno=0".

Looking into the source of the NegotiateEncrypticon function, it looks like BIO_new_socket is succeeding and it's failing when it calls SSL_connect, but I'm not sure why. Has anyone else successfully connected to ftps and can give me some pointers?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.