commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,984 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "filesystem/ftp_lib.h"
#include "nstring/nstring.h"
#include "platform_config.h"
#include "alloc/ialloc.h"
#include "log/log.h"
using namespace GS;
#define ConnectionBufferSize 1024
#if __PLATFORM_WINDOWS__
#define SETSOCKOPT_OPTVAL_TYPE (const char *)
#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
typedef int socklen_t;
#elif (__PLATFORM_LINUX__ || __PLATFORM_OSX__)
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define SETSOCKOPT_OPTVAL_TYPE (void *)
#define net_read read
#define net_write write
#define net_close close
#define SOCKET int
#endif
//------------------------------------------------------------------------------
#if (__PLATFORM_WINDOWS__ || __PLATFORM_LINUX__ || __PLATFORM_OSX__)
#define FTP_PROPAGATE_ERROR__(__C__) { State s = __C__; if (s != FtpOk) return s; }
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
//----------------------------
FtpConnection::FtpConnection()
//----------------------------
{
handle = -1;
ready = false;
buffer = 0;
buffer_usage = 0;
}
//---------------------------------------------
void FtpConnection::FreeBuffer()
//---------------------------------------------
{ _safe_delete_array(buffer); }
//-------------------------------------------------
bool FtpConnection::AllocateBuffer()
//-------------------------------------------------
{
FreeBuffer();
return (buffer = new char[ConnectionBufferSize]) != NULL ? true : false;
}
//-------------------------------------------------------------------
FtpLibrary::State FtpLibrary::WaitSocket(FtpConnection *connection)
//-------------------------------------------------------------------
{
fd_set fd, *rfd = NULL, *wfd = NULL;
FD_ZERO(&fd);
if (connection->direction == FtpConnection::Upload)
wfd = &fd;
else
rfd = &fd;
forever
{
FD_SET(connection->handle, &fd);
// 5 seconds timeout.
timeval tv;
tv.tv_sec = 4;
tv.tv_usec = 100000;
SOCKET rv = select((int)(connection->handle + 1), rfd, wfd, NULL, &tv);
if (rv == -1)
return FtpError;
else if (!rv)
return FtpSocketTimeout;
else
break;
/*
if (!IdleCallback())
FtpSocketTimeout;
*/
}
return FtpOk;
}
//---------------------------------------------------
bool FtpLibrary::CheckResponse(char c)
//---------------------------------------------------
{
char match[5];
int length;
if (ReadASCII(response, 256, &master_connection, length) != FtpOk)
return false;
if (response[3] == '-')
{
strncpy(match, response, 3);
match[3] = ' ';
match[4] = '\0';
do
{
if (ReadASCII(response, 256, &master_connection, length) != FtpOk)
return false;
} while (strncmp(response, match, 4));
}
return (response[0] == c) ? true : false;
}
//-------------------------------------------------------
bool FtpLibrary::Connect(const char *host)
//-------------------------------------------------------
{
sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
char *lhost = strdup(host), *pnum = strchr(lhost,':');
servent *pse;
if (!pnum)
{
if ((pse = getservbyname("ftp", "tcp")) == NULL)
__ERR__(__LOG__ << "[!] (FTP) Failed to get service port.\n", false)
sin.sin_port = pse->s_port;
}
else
{
*pnum++ = 0;
if (isdigit(*pnum))
sin.sin_port = htons((u_short)atoi(pnum));
else
{
pse = getservbyname(pnum, "tcp");
sin.sin_port = pse->s_port;
}
}
#if __PLATFORM_WINDOWS__
if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
#else
if (!inet_aton(lhost, &sin.sin_addr))
#endif
{
hostent *phe;
if ((phe = gethostbyname(lhost)) == NULL)
__ERR__(__LOG__ << "[!] (FTP) Failed to resolve host.\n", false)
memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
}
free(lhost);
//-------------------------------------------------------------------------------------------------------
#define __ConnectError__(_S_)\
{ __LOG__ << _S_; net_close(master_connection.handle); master_connection.handle = 0; return false; }
//-------------------------------------------------------------------------------------------------------
master_connection.handle = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (master_connection.handle == -1)
__ConnectError__("[!] (FTP) Failed to create socket.\n")
int on = 1;
if (setsockopt(master_connection.handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
__ConnectError__("[!] (FTP) Set socket option failed.\n")
if (connect(master_connection.handle, (struct sockaddr *)&sin, sizeof(sin)) == -1)
__ConnectError__("[!] (FTP) Socket failed to connect.\n")
if (!CheckResponse('2'))
__ConnectError__("")
return true;
}
//-----------------------------------------------------------------
bool FtpLibrary::CheckPASVResponse(unsigned char *v)
//-----------------------------------------------------------------
{
sockaddr sa;
socklen_t l = sizeof(sa);
if (getpeername(master_connection.handle, &sa, &l) == -1)
{
net_close(master_connection.handle);
return false;
}
for (int i = 2; i < 6; ++i)
v[i] = sa.sa_data[i];
return true;
}
//---------------------------------------------------------------------------
bool FtpLibrary::FtpSendCmd(const char *command, char expresp)
//---------------------------------------------------------------------------
{
if (!master_connection.handle)
return 0;
char ftp_command[256];
_snprintf(ftp_command, 255, "%s\r\n", command);
if (net_write(master_connection.handle, ftp_command, (int)strlen(ftp_command)) <= 0)
return false;
SendCommandCallback(ftp_command);
return CheckResponse(expresp);
}
//---------------------------------------------------------------------------
bool FtpLibrary::Login(const char *user, const char *password)
//---------------------------------------------------------------------------
{
char ftp_command[64];
// Send user.
_snprintf(ftp_command, 63, "USER %s", user);
if (!FtpSendCmd(ftp_command, '3'))
{
if (*GetLastResponse() == '2')
return true;
return false;
}
// Send password.
_snprintf(ftp_command, 63, "PASS %s", password);
return FtpSendCmd(ftp_command, '2');
}
//------------------------------------------------------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreatePORTConnection(TransferMode mode, FtpConnection::Direction dir, char *connection_command)
//------------------------------------------------------------------------------------------------------------------------------
{
union
{
sockaddr sa;
sockaddr_in in;
} sin;
// Create the new connection.
FtpConnection *connection = new FtpConnection;
if (!connection)
__ERR__(__LOG__ << "[!] (FTP) Failed to allocate new connection object.\n", NULL)
// Get socket from the master connection.
socklen_t l = sizeof(sin);
if (getsockname(master_connection.handle, &sin.sa, &l) < 0)
return connection;
// Create socket.
connection->handle = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connection->handle == -1)
return connection;
// Set socket options.
int on = 1;
if (setsockopt(connection->handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
return connection;
linger lng = { 0, 0 };
if (setsockopt(connection->handle, SOL_SOCKET, SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng, sizeof(lng)) == -1)
return connection;
// Bind socket.
sin.in.sin_port = 0;
if (
(bind(connection->handle, &sin.sa, sizeof(sin)) == -1) ||
(listen(connection->handle, 1) < 0) ||
(getsockname(connection->handle, &sin.sa, &l) < 0)
)
return connection;
// Open PORT connection.
char ftp_command[256];
_snprintf(ftp_command, 255, "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(ftp_command, '2'))
return connection;
// Handle resuming.
if (offset)
{
_snprintf(ftp_command, 255, "REST %lld", offset);
if (!FtpSendCmd(ftp_command, '3'))
return connection; // TODO allow for a full restart here?
}
// Allocate buffer for binary transaction.
if ((mode == TransferASCII) && !connection->AllocateBuffer())
return connection;
// Finally send the connection command.
if (!FtpSendCmd(connection_command, '1'))
return connection;
// Connection is ready.
connection->direction = dir;
connection->ready = true;
return connection;
}
//------------------------------------------------------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreatePASVConnection(TransferMode mode, FtpConnection::Direction dir, char *connection_command)
//------------------------------------------------------------------------------------------------------------------------------
{
// Set PASV mode.
if (!FtpSendCmd("PASV", '2'))
return NULL;
// Check server answer.
char *cp = strchr(response,'(');
if (!cp)
return NULL;
unsigned char v[6];
sscanf(++cp, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", &v[2], &v[3], &v[4], &v[5], &v[0], &v[1]);
if (correctpasv && !CheckPASVResponse(v))
__ERR__(__LOG__ << "[!] (FTP) Incorrect PASV response.\n", NULL)
struct sockaddr sa;
sa.sa_family = AF_INET;
sa.sa_data[2] = v[2];
sa.sa_data[3] = v[3];
sa.sa_data[4] = v[4];
sa.sa_data[5] = v[5];
sa.sa_data[0] = v[0];
sa.sa_data[1] = v[1];
// Handle resume.
char ftp_command[256];
if (offset)
{
_snprintf(ftp_command, 255, "REST %lld", offset);
if (!FtpSendCmd(ftp_command, '3'))
return NULL;
}
// Create the new connection.
FtpConnection *connection = new FtpConnection;
if (!connection)
__ERR__(__LOG__ << "[!] (FTP) Failed to allocate new connection object.\n", NULL)
// Create socket.
int on = 1;
linger lng = { 0, 0 };
connection->handle = (int)socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (
(connection->handle == -1) ||
(setsockopt(connection->handle, SOL_SOCKET, SO_REUSEADDR, SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1) ||
(setsockopt(connection->handle, SOL_SOCKET, SO_LINGER, SETSOCKOPT_OPTVAL_TYPE &lng, sizeof(lng)) == -1)
)
return connection;
// Setup connection.
_snprintf(ftp_command, 255, "%s\r\n", connection_command);
if (net_write(master_connection.handle, ftp_command, (int)strlen(ftp_command)) <= 0)
return connection;
// Connect socket.
if ((connect(connection->handle, &sa, sizeof(sa)) == -1) || !CheckResponse('1'))
return connection;
// Allocate buffer for binary transaction.
if ((mode == TransferASCII) && !connection->AllocateBuffer())
return connection;
// Connection is ready.
connection->direction = dir;
connection->ready = true;
return connection;
}
//----------------------------------------------------------------------------
bool FtpLibrary::FtpAcceptConnection(FtpConnection *connection)
//----------------------------------------------------------------------------
{
// Reset all connections.
fd_set mask;
FD_ZERO(&mask);
FD_SET(master_connection.handle, &mask);
FD_SET(connection->handle, &mask);
// Setup timeout.
timeval tv;
tv.tv_usec = 0;
tv.tv_sec = 30;
// Select handle.
int i = (int)master_connection.handle;
if (i < connection->handle)
i = connection->handle;
i = select((int)(i + 1), &mask, NULL, NULL, &tv);
switch (i)
{
case -1: // Error.
strncpy(response, strerror(errno), sizeof(response));
break;
case 0: // Time out.
strcpy(response, "Time out waiting for connection.");
break;
default:
if (FD_ISSET(connection->handle, &mask))
{
sockaddr addr;
socklen_t l = sizeof(addr);
int handle = (int)accept(connection->handle, &addr, &l);
i = errno;
net_close(connection->handle);
if (handle > 0)
{
connection->handle = handle;
return true;
}
strncpy(response, strerror((int)i), sizeof(response));
connection->handle = 0;
return false;
}
else
if (FD_ISSET(connection->handle, &mask))
CheckResponse('2');
break;
}
net_close(connection->handle);
connection->handle = 0;
return false;
}
//------------------------------------------------------------------------------
FtpConnection *FtpLibrary::CreateConnection(const char *path, AccessType type, TransferMode mode)
{
if (!path && ((type == AccessFileWrite) || (type == AccessFileRead) || (type == AccessFileReadAppend) || (type == AccessFileWriteAppend)))
__ERR__(__LOG__ << "[!] (FTP) Missing path argument.\n", NULL)
// Setup transfer mode.
char ftp_command[256];
_snprintf(ftp_command, 255, "TYPE %c", mode);
if (!FtpSendCmd(ftp_command, '2'))
__ERR__(__LOG__ << "[!] (FTP) Failed to set tranfer mode.\n", NULL)
// Select sub command.
const char *sub_command;
FtpConnection::Direction direction = FtpConnection::Download;
switch (type)
{
case AccessDir:
sub_command = "NLST";
break;
case AccessDirVerbose:
sub_command = "LIST -aL";
break;
case AccessFileReadAppend:
case AccessFileRead:
sub_command = "RETR";
break;
case AccessFileWriteAppend:
case AccessFileWrite:
sub_command = "STOR";
direction = FtpConnection::Upload;
break;
default:
__ERR__(__LOG__ << "[!] (FTP) Invalid access type.\n", NULL)
}
// Append path.
if (path)
_snprintf(ftp_command, 255, "%s %s", sub_command, path);
// Open connection.
FtpConnection *connection = NULL;
switch (connection_mode)
{
case ConnectionPASV:
connection = CreatePASVConnection(mode, direction, ftp_command);
break;
case ConnectionPORT:
connection = CreatePORTConnection(mode, direction, ftp_command);
if (!connection || !connection->ready)
break;
if (!FtpAcceptConnection(connection))
{
CloseConnection(connection);
return NULL;
}
break;
}
return connection;
}
bool FtpLibrary::CloseConnection(FtpConnection *connection)
{
// Sanity check.
if (connection == &master_connection)
return false;
// Purge writing cache.
int length;
if (connection->direction == FtpConnection::Upload)
if (connection->buffer)
WriteASCII(NULL, 0, connection, length);
shutdown(connection->handle, 2);
net_close(connection->handle);
_safe_delete(connection);
return CheckResponse('2');
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::ReadASCII(char *buf, int max, FtpConnection *connection, int &total_read_count)
{
/// TODO
// Early exit case.
if (max == 0)
return FtpOk;
if ((connection != &master_connection) && (connection->direction != FtpConnection::Download))
return FtpError;
// Read.
total_read_count = 0;
char *p_buffer = buf;
forever
{
// Check available data on cache.
if (connection->buffer_usage > 0)
{
// Determine read size.
char *eol = (char *)memchr(connection->buffer, '\n', connection->buffer_usage);
int read_size = (int)(eol ? eol - connection->buffer + 1 : connection->buffer_usage);
if (read_size > (max - 1))
read_size = max - 1;
// Perform reading.
memcpy(p_buffer, connection->buffer, read_size);
max -= read_size;
total_read_count += read_size;
p_buffer += read_size;
// Update cache.
if (read_size < connection->buffer_usage)
memcpy(connection->buffer, &connection->buffer[read_size], connection->buffer_usage - read_size);
connection->buffer_usage -= read_size;
// Catch end of buffer.
if ((max == 1) || eol)
{
p_buffer[0] = 0;
break;
}
}
// Wait socket.
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
// Fill cache.
int buffer_left = (ConnectionBufferSize - connection->buffer_usage) - 1,
read_count = net_read(connection->handle, &connection->buffer[connection->buffer_usage], buffer_left);
connection->buffer_usage += read_count;
if (read_count == -1)
__ERR__(__LOG__ << "[!] (FTP) Read error.\n", FtpError)
else if (!read_count)
break; // EOF
}
return FtpOk;
}
FtpLibrary::State FtpLibrary::WriteASCII(char *output, int length, FtpConnection *connection, int &x)
{
/// TODO
if (connection->direction != FtpConnection::Upload)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
if ((x = net_write(connection->handle, output, length)) != length)
return FtpError;
return FtpOk;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::ReadBinary(void *buf, int max, FtpConnection *connection, int &length)
{
if (connection->direction != FtpConnection::Download)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
length = net_read(connection->handle, buf, max);
if (length == -1)
return FtpError;
DataReadCallback(connection);
return FtpOk;
}
FtpLibrary::State FtpLibrary::WriteBinary(void *buf, int len, FtpConnection *connection)
{
if (connection->direction != FtpConnection::Upload)
return FtpError;
FTP_PROPAGATE_ERROR__(WaitSocket(connection))
if (net_write(connection->handle, buf, len) != len)
return FtpError;
DataWriteCallback(connection);
return FtpOk;
}
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::DataTransfer(const char *localfile, const char *path, AccessType type, TransferMode mode)
//-----------------------------------------------------------------------------------------------------------------------
{
// Open local file or I/O stream.
FILE *file;
if (localfile)
{
const char *access;
switch (type)
{
default:
case AccessDir:
case AccessDirVerbose:
case AccessFileRead:
access = (mode == TransferBinary) ? "wb" : "w";
break;
case AccessFileReadAppend:
access = (mode == TransferBinary) ? "ab" : "a";
break;
case AccessFileWriteAppend:
case AccessFileWrite:
access = (mode == TransferBinary) ? "rb" : "r";
break;
}
file = fopen(localfile, access);
if (!file)
__ERR__(__LOG_E__ << "Failed to open FTP output file.\n", FtpError)
if (type == AccessFileWriteAppend)
if (fseek(file, offset, SEEK_SET))
{
fclose(file);
__ERR__(__LOG_E__ << "Failed to seek in FTP file for transfer.\n", FtpError)
}
}
else
file = (type == AccessFileWrite || type == AccessFileWriteAppend) ? stdin : stdout;
// Create a new connection.
FtpConnection *connection = CreateConnection(path, type, mode);
if (!connection)
{
if (localfile)
fclose(file);
return FtpError;
}
// Perform transfer.
State retv = FtpOk;
GS::Array <char> temp_buffer(ConnectionBufferSize);
int length;
if ((type == AccessFileWrite) || (type == AccessFileWriteAppend))
{
while ((length = (int)fread(temp_buffer, 1, ConnectionBufferSize, file)) > 0)
if (WriteBinary(temp_buffer, length, connection) != FtpOk)
{
retv = FtpError; // FTP write failed.
break;
}
}
else
{
while ((retv = ReadBinary(temp_buffer, ConnectionBufferSize, connection, length)) == FtpOk)
if (!length || (fwrite(temp_buffer, 1, length, file) <= 0))
break; // Done.
}
// Flush file.
fflush(file);
if (localfile)
fclose(file);
CloseConnection(connection);
return retv;
}
//------------------------------------------------------------------------------
FtpLibrary::State FtpLibrary::Download(const char *file, const char *path, TransferMode mode, int _offset)
{
offset = _offset;
if (!offset)
return DataTransfer(file, path, AccessFileRead, mode);
else return DataTransfer(file, path, AccessFileReadAppend, mode);
}
FtpLibrary::State FtpLibrary::Upload(const char *file, const char *path, TransferMode mode, int _offset)
{
offset = _offset;
if (!offset)
return DataTransfer(file, path, AccessFileWrite, mode);
else return DataTransfer(file, path, AccessFileWriteAppend, mode);
}
//------------------------------------------------------------------------------
//------------------------------------
bool FtpLibrary::Quit()
//------------------------------------
{
if (!master_connection.handle)
return true;
bool r = FtpSendCmd("QUIT", '2');
net_close(master_connection.handle);
master_connection.handle = 0;
return r;
}
//------------------------------------------------------------------------------
bool FtpLibrary::DeleteFile(const char *path)
{ return FtpSendCmd(String::Format("DELE %s", path).c_str(), '2'); }
bool FtpLibrary::ChangeDirectory(const char *path)
{ return FtpSendCmd(String::Format("CWD %s", path).c_str(), '2'); }
bool FtpLibrary::UpDirectory()
{ return FtpSendCmd("CDUP", '2'); }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int FtpLibrary::GetFileSize(const char *path, TransferMode mode)
//------------------------------------------------------------------------------
{
int rs, sz = -1;
if ( FtpSendCmd(String::Format("TYPE %c", mode).c_str(), '2') &&
FtpSendCmd(String::Format("SIZE %s", path).c_str(), '2') &&
(sscanf(response, "%d %d", &rs, &sz) == 2) )
return sz;
return -1;
}
//----------------------------------------------------------------------------
bool FtpLibrary::Nlst(const char *outputfile, const char *path)
//----------------------------------------------------------------------------
{
offset = 0;
return DataTransfer(outputfile, path, FtpLibrary::AccessDir, FtpLibrary::TransferASCII) == FtpOk ? true : false;
}
//------------------------------------------------------------------------------
FtpLibrary::FtpLibrary()
{
#if __PLATFORM_WINDOWS__
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa))
__LOG__ << "[!] (FTP) WINSOCK startup error.\n";
#endif
connection_mode = ConnectionPORT;
master_connection.AllocateBuffer();
//
offset = 0;
correctpasv = false;
}
FtpLibrary::~FtpLibrary()
{ Quit(); }
//------------------------------------------------------------------------------
#endif
/*
int FtpLibrary::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_ftphandle)) return 0;
return 1;
}
int FtpLibrary::Raw(const char *cmd)
{
char buf[256];
strncpy(buf, cmd, 256);
if (!FtpSendCmd(buf,'2',mp_ftphandle)) return 0;
return 1;
}
int FtpLibrary::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;
}
int FtpLibrary::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;
}
int FtpLibrary::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_ftphandle)) return 0;
return 1;
}
int FtpLibrary::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;
}
int FtpLibrary::Dir(const char *outputfile, const char *path)
{
mp_ftphandle->offset = 0;
return FtpXfer(outputfile, path, mp_ftphandle, FtpLibrary::dirverbose, FtpLibrary::ascii);
}
int FtpLibrary::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_ftphandle)) rv = 0;
else strncpy(dt, &mp_ftphandle->response[4], max);
return rv;
}
int FtpLibrary::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_ftphandle)) return 0;
sprintf(cmd,"RNTO %s",dst);
if (!FtpSendCmd(cmd,'2',mp_ftphandle)) return 0;
return 1;
}
void FtpLibrary::SetConnmode(connmode mode)
{
mp_ftphandle->cmode = mode;
}
ftphandle* FtpLibrary::RawOpen(const char *path, accesstype type, transfermode mode)
{
int ret;
ftphandle* datahandle;
ret = CreateConnection(path, type, mode, mp_ftphandle, &datahandle);
if (ret) return datahandle;
else return NULL;
}
int FtpLibrary::RawClose(ftphandle* handle)
{
return FtpClose(handle);
}
int FtpLibrary::RawWrite(void* buf, int len, ftphandle* handle)
{
return FtpWrite(buf, len, handle);
}
int FtpLibrary::RawRead(void* buf, int max, ftphandle* handle)
{
return FtpRead(buf, max, handle);
}
*/