mirror of
https://github.com/glest/glest-source.git
synced 2025-08-09 09:56:30 +02:00
- got my plumbers suit on and added the plumbing for FTP file xfers
This commit is contained in:
344
source/shared_lib/sources/feathery_ftp/ftpSession.c
Normal file
344
source/shared_lib/sources/feathery_ftp/ftpSession.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
|
||||
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
|
||||
*
|
||||
* ftpSession.c - Session handling of connected clients
|
||||
*
|
||||
* A ftp session is a TCP connection between the server and a ftp client.
|
||||
* Each session has its own unique session id. The session id refers
|
||||
* (index in session[]) to a struct ftpSession_S which holds all
|
||||
* relevant data. The virtual chroot environment is also part of the
|
||||
* session management.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ftpTypes.h"
|
||||
#include "ftpConfig.h"
|
||||
#include "ftp.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief array that holds the data of all ftp sessions
|
||||
*
|
||||
* The index represents the session ID.
|
||||
*/
|
||||
LOCAL ftpSession_S sessions[MAX_CONNECTIONS];
|
||||
|
||||
/**
|
||||
* @brief number of active file or directory transmission
|
||||
*/
|
||||
LOCAL int actTransCnt;
|
||||
|
||||
/**
|
||||
* @brief Scratch-buffer for path manipulation
|
||||
*/
|
||||
LOCAL char pathScratchBuf[MAX_PATH_LEN];
|
||||
|
||||
|
||||
/**
|
||||
* @brief Opens a ftp session
|
||||
*
|
||||
* Searches in 'sessions' for an empty entry and inits the session data.
|
||||
* Call this function after accepting a tcp connection from a ftp client.
|
||||
*
|
||||
* @param ctrlSocket control socket which initiated the the ftp session
|
||||
* @param remoteIp IP address of the client
|
||||
* @param remotePort TCP-Port of the client
|
||||
*
|
||||
* @return session id or -1 if session limit is reached
|
||||
*/
|
||||
int ftpOpenSession(socket_t ctrlSocket, ip_t remoteIp, port_t remotePort)
|
||||
{
|
||||
int n;
|
||||
for(n = 0; n < MAX_CONNECTIONS; n++)
|
||||
{
|
||||
if(!sessions[n].open)
|
||||
{
|
||||
sessions[n].open = TRUE;
|
||||
sessions[n].authenticated = FALSE;
|
||||
sessions[n].userId = 0;
|
||||
sessions[n].workingDir[0] = '\0';
|
||||
sessions[n].remoteIp = remoteIp;
|
||||
sessions[n].remotePort = remotePort;
|
||||
sessions[n].remoteDataPort = 0;
|
||||
sessions[n].passive = FALSE;
|
||||
sessions[n].binary = TRUE;
|
||||
sessions[n].timeLastCmd = ftpGetUnixTime();
|
||||
sessions[n].ctrlSocket = ctrlSocket;
|
||||
sessions[n].passiveDataSocket = -1;
|
||||
sessions[n].rxBufWriteIdx = 0;
|
||||
sessions[n].activeTrans.op = OP_NOP;
|
||||
sessions[n].activeTrans.fsHandle = NULL;
|
||||
sessions[n].activeTrans.dataSocket = -1;
|
||||
sessions[n].activeTrans.fileSize = 0;
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Marks the current ftp session as 'authenticated'
|
||||
*
|
||||
* @param id Session id
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
int ftpAuthSession(int id)
|
||||
{
|
||||
sessions[id].authenticated = TRUE;
|
||||
strcpy(sessions[id].workingDir, "/");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Closes a ftp session
|
||||
*
|
||||
* Closes the TCP control connection and releases the session struct.
|
||||
*
|
||||
* @param id Session id
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
int ftpCloseSession(int id)
|
||||
{
|
||||
ftpCloseSocket(sessions[id].ctrlSocket);
|
||||
ftpCloseTransmission(id);
|
||||
|
||||
sessions[id].open = FALSE;
|
||||
|
||||
#if DBG_LOG
|
||||
printf("Session %d closed\n", id);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns pointer to session struct
|
||||
*
|
||||
* @param id Session id
|
||||
*
|
||||
* @return pointer to session data
|
||||
*/
|
||||
ftpSession_S* ftpGetSession(int id)
|
||||
{
|
||||
return &sessions[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalizes a path string
|
||||
*
|
||||
* The function resolves all dot and doubledot directory entries in the
|
||||
* passed path. If the normalized path refers beyond root, root is returned.
|
||||
*
|
||||
* @param path string of an absolute path
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
LOCAL int normalizePath(char* path)
|
||||
{
|
||||
char *in;
|
||||
char *r = NULL;
|
||||
|
||||
r = path;
|
||||
in = path;
|
||||
|
||||
while((in = strchr(in, '/')))
|
||||
{
|
||||
if(!strncmp(in, "/./", 3))
|
||||
{
|
||||
ftpStrcpy(in, &in[2]);
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(in, "/."))
|
||||
{
|
||||
in[1] = '\0';
|
||||
continue;
|
||||
}
|
||||
if(!strncmp(in, "/../", 4))
|
||||
{
|
||||
*in = '\0';
|
||||
r = strrchr(path, '/');
|
||||
if(r == NULL)
|
||||
r = path;
|
||||
ftpStrcpy(r, &in[3]);
|
||||
in = r;
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(in, "/.."))
|
||||
{
|
||||
*in = '\0';
|
||||
r = strrchr(path, '/');
|
||||
if(r)
|
||||
{
|
||||
if(r == path)
|
||||
r[1] = '\0';
|
||||
else
|
||||
*r = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
in[0] = '/';
|
||||
in[1] = '\0';
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Translate a ftp session path to server path
|
||||
*
|
||||
* The translated path depends on the current working directory of the
|
||||
* session and the root path of the session. In addition the path will
|
||||
* be normalized.
|
||||
* The server path is generated as followed:
|
||||
* passed path is relative => server path = ftp user root + session working dir + path
|
||||
* passed path is absolute => server path = ftp user root + path
|
||||
*
|
||||
* @param id Session id
|
||||
* @param path ftp session path (can be relative or absolute)
|
||||
* @param if != 0 dot and doubledot directories will be resolved
|
||||
*
|
||||
* @return translated absolute server path
|
||||
*/
|
||||
const char* ftpGetRealPath(int id, const char* path, int normalize)
|
||||
{
|
||||
const char* ftpRoot;
|
||||
int len;
|
||||
|
||||
ftpRoot = ftpGetRoot(sessions[id].userId, &len);
|
||||
|
||||
#if DBG_LOG
|
||||
printf("ftpGetRealPath path [%s] ftpRoot [%s] sessions[id].workingDir [%s]\n", path, ftpRoot, sessions[id].workingDir);
|
||||
#endif
|
||||
|
||||
pathScratchBuf[0]='\0';
|
||||
if(path[0] == '/' || strcmp(path,sessions[id].workingDir) == 0) // absolute path?
|
||||
{
|
||||
ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ftpMergePaths(pathScratchBuf, ftpRoot, sessions[id].workingDir, "/", path, NULL);
|
||||
//ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
|
||||
}
|
||||
|
||||
#if DBG_LOG
|
||||
printf("#2 ftpGetRealPath path [%s] ftpRoot [%s]\n", path, ftpRoot);
|
||||
#endif
|
||||
|
||||
ftpRemoveDoubleSlash(pathScratchBuf);
|
||||
if(normalize) {
|
||||
normalizePath(pathScratchBuf);
|
||||
}
|
||||
ftpRemoveTrailingSlash(pathScratchBuf);
|
||||
|
||||
#if DBG_LOG
|
||||
printf("#2 ftpGetRealPath path [%s] ftpRoot [%s] pathScratchBuf [%s]\n", path, ftpRoot, pathScratchBuf);
|
||||
#endif
|
||||
|
||||
return pathScratchBuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change the current working directory of the session
|
||||
*
|
||||
* @param id Session id
|
||||
* @param path destination ftp path (can be relative or absolute)
|
||||
*
|
||||
* @return 0 on success; -2 if the directory doesn't exist
|
||||
*/
|
||||
int ftpChangeDir(int id, const char* path)
|
||||
{
|
||||
ftpPathInfo_S fileInfo;
|
||||
const char* realPath = ftpGetRealPath(id, path, TRUE);
|
||||
int len;
|
||||
|
||||
|
||||
ftpGetRoot(sessions[id].userId, &len); // determine len of root-path
|
||||
if(len == 1) // if len == 1 root-path == '/'
|
||||
len = 0;
|
||||
|
||||
#if DBG_LOG
|
||||
printf("ftpChangeDir path [%s] realPath [%s] sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
|
||||
#endif
|
||||
|
||||
if(ftpStat(realPath, &fileInfo) || (fileInfo.type != TYPE_DIR)) // directory accessible?
|
||||
return -2;
|
||||
|
||||
strncpy(sessions[id].workingDir, &realPath[len], MAX_PATH_LEN); // apply path
|
||||
if(sessions[id].workingDir[0] == '\0')
|
||||
strcpy(sessions[id].workingDir, "/");
|
||||
|
||||
#if DBG_LOG
|
||||
printf("ftpChangeDir path [%s] realPath [%s] NEW sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo documentation
|
||||
*/
|
||||
void ftpOpenTransmission(int id, operation_E op, void* fsHandle, socket_t dataSocket, uint32_t fileSize)
|
||||
{
|
||||
actTransCnt++;
|
||||
sessions[id].activeTrans.op = op;
|
||||
sessions[id].activeTrans.fsHandle = fsHandle;
|
||||
sessions[id].activeTrans.dataSocket = dataSocket;
|
||||
sessions[id].activeTrans.fileSize = fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo documentation
|
||||
*/
|
||||
void ftpCloseTransmission(int id)
|
||||
{
|
||||
if(sessions[id].activeTrans.op != OP_NOP) // is thera an active transmission?
|
||||
{
|
||||
ftpCloseSocket(sessions[id].activeTrans.dataSocket);
|
||||
if(sessions[id].activeTrans.op == OP_LIST)
|
||||
{
|
||||
ftpCloseDir(sessions[id].activeTrans.fsHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
ftpCloseFile(sessions[id].activeTrans.fsHandle);
|
||||
}
|
||||
sessions[id].activeTrans.op = OP_NOP;
|
||||
actTransCnt--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo documentation
|
||||
*/
|
||||
int ftpGetActiveTransCnt(void)
|
||||
{
|
||||
return actTransCnt;
|
||||
}
|
Reference in New Issue
Block a user