- updated line endings to unix style characters to fix Bug #3085838

This commit is contained in:
Mark Vejvoda
2011-01-20 15:56:30 +00:00
parent 53327900b3
commit 66261ad662
105 changed files with 26229 additions and 20874 deletions

View File

@@ -1,177 +1,177 @@
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpAccount.c - User account handling
*
* User account management is based on username, password and
* access-rights. An account can be created with the function
* ftpCreateAccount.
*
*
* 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 <string.h>
#include "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
/**
* @brief User account data
*/
typedef struct
{
char name[MAXLEN_USERNAME]; ///< user name
char passw[MAXLEN_PASSWORD]; ///< password of the account
char ftpRoot[MAX_PATH_LEN]; ///< root path of the user account on the server
int ftpRootLen; ///< length of ftpRoot
int accRights; ///< access rights of a account
}ftpUserAccount_S;
/**
* @brief Array which holds all registered user accounts
*/
LOCAL ftpUserAccount_S ftpUsers[MAX_USERS];
/**
* @brief Creates a new user account
*
* 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.
* @todo normalize root and check if normalized path really exists
*
* @param name user name
* @param passw account password
* @param root root directory of the account
* @param acc access rights, can be any combination of the following flags:
* - FTP_ACC_RD read access
* - FTP_ACC_WR write access
* - FTP_ACC_LS access to directory listing
* - FTP_ACC_DIR changing of working dir allowed
*
* @return 0 on success; -1 if MAX_USERS is reached
*/
int ftpCreateAccount(const char* name, const char* passw, const char* root, int acc)
{
int n;
n = ftpFindAccount(name); // check if account already exists
if(n > 0)
{
ftpUsers[n - 1].name[0] = '\0'; // delete account
}
for(n = 0; n < MAX_USERS; n++)
{
if(ftpUsers[n].name[0] == '\0')
{
strncpy(ftpUsers[n].name, name, MAXLEN_USERNAME);
strncpy(ftpUsers[n].passw, passw, MAXLEN_PASSWORD);
strncpy(ftpUsers[n].ftpRoot, root, MAX_PATH_LEN);
ftpUsers[n].ftpRootLen = strlen(root);
ftpUsers[n].accRights = acc;
return 0;
}
}
return -1;
}
/**
* @brief Return the account id for a user name
*
* The function searches ftpUsers for the passed user name.
* The returned account id is the index + 1 in ftpUsers.
*
* @param name user name
*
* @return 0 if user is not found; 1 to MAX_USERS+1 if user is found
*/
int ftpFindAccount(const char* name)
{
int n;
if(name[0] != '\0')
for(n = 0; n < MAX_USERS; n++)
if(!strncmp(ftpUsers[n].name, name, MAXLEN_USERNAME))
return n + 1;
return 0;
}
/**
* @brief Checks the password of a user account
*
* Compares the passed password to the saved password in ftpUsers
*
* @param userId user account id
* @param passw password
*
* @return - 0: password is correct
* - -1: invalid user account id
* - else: incorrect password
*/
int ftpCheckPassword(int userId, const char* passw)
{
if(!userId)
return -1;
else if(ftpUsers[userId - 1].passw[0] == '\0')
return 0;
else
return strncmp(ftpUsers[userId - 1].passw, passw, MAXLEN_PASSWORD);
}
/**
* @brief Checks if the account has the needed rights
*
* Compares the passed access rights to the saved rights in ftpUsers
*
* @param userId user account id
* @param accRights needed access rights
*
* @return - 0: the needed access rights are fulfilled
* - -1: invalid user account id
*/
int ftpCheckAccRights(int userId, int accRights)
{
if(!userId)
return -1;
if((ftpUsers[userId - 1].accRights & accRights) == accRights)
return 0;
return -1;
}
/**
* @brief Returns the root directory of a account
*
* @param userId user account id
* @param len length of the returned path
*
* @return root directory name or NULL if the user account id is invalid
*/
const char* ftpGetRoot(int userId, int* len)
{
if(!userId)
return NULL;
if(len)
*len = ftpUsers[userId - 1].ftpRootLen;
return ftpUsers[userId - 1].ftpRoot;
}
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpAccount.c - User account handling
*
* User account management is based on username, password and
* access-rights. An account can be created with the function
* ftpCreateAccount.
*
*
* 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 <string.h>
#include "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
/**
* @brief User account data
*/
typedef struct
{
char name[MAXLEN_USERNAME]; ///< user name
char passw[MAXLEN_PASSWORD]; ///< password of the account
char ftpRoot[MAX_PATH_LEN]; ///< root path of the user account on the server
int ftpRootLen; ///< length of ftpRoot
int accRights; ///< access rights of a account
}ftpUserAccount_S;
/**
* @brief Array which holds all registered user accounts
*/
LOCAL ftpUserAccount_S ftpUsers[MAX_USERS];
/**
* @brief Creates a new user account
*
* 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.
* @todo normalize root and check if normalized path really exists
*
* @param name user name
* @param passw account password
* @param root root directory of the account
* @param acc access rights, can be any combination of the following flags:
* - FTP_ACC_RD read access
* - FTP_ACC_WR write access
* - FTP_ACC_LS access to directory listing
* - FTP_ACC_DIR changing of working dir allowed
*
* @return 0 on success; -1 if MAX_USERS is reached
*/
int ftpCreateAccount(const char* name, const char* passw, const char* root, int acc)
{
int n;
n = ftpFindAccount(name); // check if account already exists
if(n > 0)
{
ftpUsers[n - 1].name[0] = '\0'; // delete account
}
for(n = 0; n < MAX_USERS; n++)
{
if(ftpUsers[n].name[0] == '\0')
{
strncpy(ftpUsers[n].name, name, MAXLEN_USERNAME);
strncpy(ftpUsers[n].passw, passw, MAXLEN_PASSWORD);
strncpy(ftpUsers[n].ftpRoot, root, MAX_PATH_LEN);
ftpUsers[n].ftpRootLen = strlen(root);
ftpUsers[n].accRights = acc;
return 0;
}
}
return -1;
}
/**
* @brief Return the account id for a user name
*
* The function searches ftpUsers for the passed user name.
* The returned account id is the index + 1 in ftpUsers.
*
* @param name user name
*
* @return 0 if user is not found; 1 to MAX_USERS+1 if user is found
*/
int ftpFindAccount(const char* name)
{
int n;
if(name[0] != '\0')
for(n = 0; n < MAX_USERS; n++)
if(!strncmp(ftpUsers[n].name, name, MAXLEN_USERNAME))
return n + 1;
return 0;
}
/**
* @brief Checks the password of a user account
*
* Compares the passed password to the saved password in ftpUsers
*
* @param userId user account id
* @param passw password
*
* @return - 0: password is correct
* - -1: invalid user account id
* - else: incorrect password
*/
int ftpCheckPassword(int userId, const char* passw)
{
if(!userId)
return -1;
else if(ftpUsers[userId - 1].passw[0] == '\0')
return 0;
else
return strncmp(ftpUsers[userId - 1].passw, passw, MAXLEN_PASSWORD);
}
/**
* @brief Checks if the account has the needed rights
*
* Compares the passed access rights to the saved rights in ftpUsers
*
* @param userId user account id
* @param accRights needed access rights
*
* @return - 0: the needed access rights are fulfilled
* - -1: invalid user account id
*/
int ftpCheckAccRights(int userId, int accRights)
{
if(!userId)
return -1;
if((ftpUsers[userId - 1].accRights & accRights) == accRights)
return 0;
return -1;
}
/**
* @brief Returns the root directory of a account
*
* @param userId user account id
* @param len length of the returned path
*
* @return root directory name or NULL if the user account id is invalid
*/
const char* ftpGetRoot(int userId, int* len)
{
if(!userId)
return NULL;
if(len)
*len = ftpUsers[userId - 1].ftpRootLen;
return ftpUsers[userId - 1].ftpRoot;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,171 +1,171 @@
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpLib.c - Global helper functions
*
*
* 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 <string.h>
#include <stdarg.h>
#include "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
#include "ftpIfc.h"
/**
* @brief Removes the trailing slash of a directory path
*
* @param path directory path
*
* @return len of path
*/
int ftpRemoveTrailingSlash(char* path)
{
int len = strlen(path);
if(len > 1)
{
len--;
if(path[len] == '/')
path[len] = '\0';
}
return len;
}
/**
* @brief Removes double slashes in a path
*
* e. g. "//a//b//c" will be converted to "a/b/c"
*
* @param path directory path
*/
void ftpRemoveDoubleSlash(char* path)
{
char *p;
p = path;
while(*p != '\0')
{
if((p[0] == '/') && (p[1] == '/'))
ftpStrcpy(p, &p[1]);
else
p++;
}
}
/**
* @brief Merges multiple path strings
*
* The function catenates all passed strings to a new string and assures that
* the result does not exceed MAX_PATH_LEN. The last parameter has to be
* NULL.
* @todo Not all embedded environments support variadic functions, or they are
* too expensive.
*
* @param dest user name
*
* @return Pointer to dest
*/
char* ftpMergePaths(char* dest, ...)
{
const char* src;
char* dst = dest;
int len = 0;
va_list args;
va_start(args, dest);
while((src = va_arg(args, const char*)))
{
while((*src != '\0') && (len < MAX_PATH_LEN-1))
{
*dst++ = *src++;
len++;
}
}
*dst = '\0';
va_end(args);
return dst;
}
/**
* @brief Determine the unix-time
*
* The function reads the clock from the target-layer and converts it to the
* unix-time. The code is taken from http://de.wikipedia.org/wiki/Unixzeit
*
* @return seconds since 1. Januar 1970 00:00
*/
uint32_t ftpGetUnixTime(void)
{
ftpTime_S t;
uint32_t unixTime = 0;
int j;
ftpGetLocalTime(&t);
for(j=1970;j<t.year;j++) // leap years
{
if(j%4==0 && (j%100!=0 || j%400==0))
unixTime+=(366*24*60*60);
else
unixTime+=(365*24*60*60);
}
for(j=1;j<t.month;j++) // days per month 31/30/29/28
{
if(j==1 || j==3 || j==5 || j==7 || j==8 || j==10 || j==12)
unixTime+=(31*24*60*60); // months with 31 days
if(j==4 || j==6 || j==9 || j==11)
unixTime+=(30*24*60*60); // months with 30 days
if( (j==2) && (t.year%4==0 && (t.year%100!=0 || t.year%400==0)) )
unixTime+=(29*24*60*60);
else
unixTime+=(28*24*60*60);
}
unixTime+=((t.day-1)*24*60*60);
unixTime+=(t.hour*60*60);
unixTime+=t.minute*60;
unixTime+=t.second;
return unixTime;
}
/**
* @brief copy a string
*
* The reason why feathery has its own strcpy is that in some cases src is
* part of dest and src > dest. Because ANSI-C explicitly declares that case
* as undefined our strcpy guarantees to copy from lower to higher
* addresses.
*
* @param dest destination string
* @param src Null-terminated source string
*
* @return destination string
*/
char *ftpStrcpy(char *dest, const char *src)
{
char *d = dest;
const char *s = src;
while (*d++ = *s++);
return dest;
}
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpLib.c - Global helper functions
*
*
* 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 <string.h>
#include <stdarg.h>
#include "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
#include "ftpIfc.h"
/**
* @brief Removes the trailing slash of a directory path
*
* @param path directory path
*
* @return len of path
*/
int ftpRemoveTrailingSlash(char* path)
{
int len = strlen(path);
if(len > 1)
{
len--;
if(path[len] == '/')
path[len] = '\0';
}
return len;
}
/**
* @brief Removes double slashes in a path
*
* e. g. "//a//b//c" will be converted to "a/b/c"
*
* @param path directory path
*/
void ftpRemoveDoubleSlash(char* path)
{
char *p;
p = path;
while(*p != '\0')
{
if((p[0] == '/') && (p[1] == '/'))
ftpStrcpy(p, &p[1]);
else
p++;
}
}
/**
* @brief Merges multiple path strings
*
* The function catenates all passed strings to a new string and assures that
* the result does not exceed MAX_PATH_LEN. The last parameter has to be
* NULL.
* @todo Not all embedded environments support variadic functions, or they are
* too expensive.
*
* @param dest user name
*
* @return Pointer to dest
*/
char* ftpMergePaths(char* dest, ...)
{
const char* src;
char* dst = dest;
int len = 0;
va_list args;
va_start(args, dest);
while((src = va_arg(args, const char*)))
{
while((*src != '\0') && (len < MAX_PATH_LEN-1))
{
*dst++ = *src++;
len++;
}
}
*dst = '\0';
va_end(args);
return dst;
}
/**
* @brief Determine the unix-time
*
* The function reads the clock from the target-layer and converts it to the
* unix-time. The code is taken from http://de.wikipedia.org/wiki/Unixzeit
*
* @return seconds since 1. Januar 1970 00:00
*/
uint32_t ftpGetUnixTime(void)
{
ftpTime_S t;
uint32_t unixTime = 0;
int j;
ftpGetLocalTime(&t);
for(j=1970;j<t.year;j++) // leap years
{
if(j%4==0 && (j%100!=0 || j%400==0))
unixTime+=(366*24*60*60);
else
unixTime+=(365*24*60*60);
}
for(j=1;j<t.month;j++) // days per month 31/30/29/28
{
if(j==1 || j==3 || j==5 || j==7 || j==8 || j==10 || j==12)
unixTime+=(31*24*60*60); // months with 31 days
if(j==4 || j==6 || j==9 || j==11)
unixTime+=(30*24*60*60); // months with 30 days
if( (j==2) && (t.year%4==0 && (t.year%100!=0 || t.year%400==0)) )
unixTime+=(29*24*60*60);
else
unixTime+=(28*24*60*60);
}
unixTime+=((t.day-1)*24*60*60);
unixTime+=(t.hour*60*60);
unixTime+=t.minute*60;
unixTime+=t.second;
return unixTime;
}
/**
* @brief copy a string
*
* The reason why feathery has its own strcpy is that in some cases src is
* part of dest and src > dest. Because ANSI-C explicitly declares that case
* as undefined our strcpy guarantees to copy from lower to higher
* addresses.
*
* @param dest destination string
* @param src Null-terminated source string
*
* @return destination string
*/
char *ftpStrcpy(char *dest, const char *src)
{
char *d = dest;
const char *s = src;
while (*d++ = *s++);
return dest;
}

View File

@@ -1,66 +1,66 @@
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpMessages.c - FTP-Server messages
*
* This Module defines all message-strings the servers sends to
* clients. If someone needs to translate the server user interface
* to a different language this is the only file to be touched.
*
*
* 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/>.
*/
const char ftpMsg000[] = "Data connection error";
const char ftpMsg001[] = "File error";
const char ftpMsg002[] = "File send OK";
const char ftpMsg003[] = "File received OK";
const char ftpMsg004[] = "Please specify the password";
const char ftpMsg005[] = "Login successful";
const char ftpMsg006[] = "Login failed";
const char ftpMsg007[] = "PORT command successful. Consider using PASV.";
const char ftpMsg008[] = "NOOP command successful";
const char ftpMsg009[] = "Goodby";
const char ftpMsg010[] = "Here comes the listing";
const char ftpMsg011[] = "Could not establish data connection.";
const char ftpMsg012[] = "Could not establish passive data connection.";
const char ftpMsg013[] = "Directory send OK";
const char ftpMsg014[] = "Sending file...";
const char ftpMsg015[] = "Could not open file.";
const char ftpMsg016[] = "Receiving file...";
const char ftpMsg018[] = "Could not delete file";
const char ftpMsg019[] = "File deleted";
const char ftpMsg020[] = "Could create directory";
const char ftpMsg021[] = "Directory created";
const char ftpMsg022[] = "Could remove directory";
const char ftpMsg023[] = "Directory removed";
const char ftpMsg024[] = "Directory successfully changed";
const char ftpMsg025[] = "Failed to change directory";
const char ftpMsg026[] = "Switching to binary mode";
const char ftpMsg027[] = "Switching to ascii mode";
const char ftpMsg028[] = "Unknown type-code";
const char ftpMsg029[] = "Entering passive mode";
const char ftpMsg030[] = "Switching to file mode";
const char ftpMsg031[] = "Only file mode supported";
const char ftpMsg032[] = "Invalid path";
const char ftpMsg033[] = "Please login with USER and PASS.";
const char ftpMsg034[] = "Permission denied.";
const char ftpMsg035[] = "Line too long.";
const char ftpMsg036[] = "Timeout.";
const char ftpMsg037[] = "Hi";
const char ftpMsg038[] = "Could not open directory.";
const char ftpMsg039[] = "Could not read directory.";
const char ftpMsg040[] = "Aborted.";
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpMessages.c - FTP-Server messages
*
* This Module defines all message-strings the servers sends to
* clients. If someone needs to translate the server user interface
* to a different language this is the only file to be touched.
*
*
* 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/>.
*/
const char ftpMsg000[] = "Data connection error";
const char ftpMsg001[] = "File error";
const char ftpMsg002[] = "File send OK";
const char ftpMsg003[] = "File received OK";
const char ftpMsg004[] = "Please specify the password";
const char ftpMsg005[] = "Login successful";
const char ftpMsg006[] = "Login failed";
const char ftpMsg007[] = "PORT command successful. Consider using PASV.";
const char ftpMsg008[] = "NOOP command successful";
const char ftpMsg009[] = "Goodby";
const char ftpMsg010[] = "Here comes the listing";
const char ftpMsg011[] = "Could not establish data connection.";
const char ftpMsg012[] = "Could not establish passive data connection.";
const char ftpMsg013[] = "Directory send OK";
const char ftpMsg014[] = "Sending file...";
const char ftpMsg015[] = "Could not open file.";
const char ftpMsg016[] = "Receiving file...";
const char ftpMsg018[] = "Could not delete file";
const char ftpMsg019[] = "File deleted";
const char ftpMsg020[] = "Could create directory";
const char ftpMsg021[] = "Directory created";
const char ftpMsg022[] = "Could remove directory";
const char ftpMsg023[] = "Directory removed";
const char ftpMsg024[] = "Directory successfully changed";
const char ftpMsg025[] = "Failed to change directory";
const char ftpMsg026[] = "Switching to binary mode";
const char ftpMsg027[] = "Switching to ascii mode";
const char ftpMsg028[] = "Unknown type-code";
const char ftpMsg029[] = "Entering passive mode";
const char ftpMsg030[] = "Switching to file mode";
const char ftpMsg031[] = "Only file mode supported";
const char ftpMsg032[] = "Invalid path";
const char ftpMsg033[] = "Please login with USER and PASS.";
const char ftpMsg034[] = "Permission denied.";
const char ftpMsg035[] = "Line too long.";
const char ftpMsg036[] = "Timeout.";
const char ftpMsg037[] = "Hi";
const char ftpMsg038[] = "Could not open directory.";
const char ftpMsg039[] = "Could not read directory.";
const char ftpMsg040[] = "Aborted.";

View File

@@ -1,50 +1,50 @@
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpRuntime.c - ftp-server runtime environment
*
* This is the central module of feathery. It defines all runtime functions
* of feathery. That is startup, state, main-thread an shutdown.
*
*
* 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 "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
#include "ftpMessages.h"
/**
* @brief server-sockets that listens for incoming connections
*/
/**
* Feathery FTP-Server <https://sourceforge.net/projects/feathery>
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
*
* ftpRuntime.c - ftp-server runtime environment
*
* This is the central module of feathery. It defines all runtime functions
* of feathery. That is startup, state, main-thread an shutdown.
*
*
* 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 "ftpTypes.h"
#include "ftpConfig.h"
#include "ftp.h"
#include "ftpMessages.h"
/**
* @brief server-sockets that listens for incoming connections
*/
LOCAL socket_t server;
LOCAL int serverListenPort;
LOCAL int serverPassiveListenPort;
//LOCAL socket_t serverPassivePort;
void ftpInit(ftpFindExternalFTPServerIpType cb1, ftpAddUPNPPortForwardType cb2, ftpRemoveUPNPPortForwardType cb3, ftpIsValidClientType cb4) {
//LOCAL socket_t serverPassivePort;
void ftpInit(ftpFindExternalFTPServerIpType cb1, ftpAddUPNPPortForwardType cb2, ftpRemoveUPNPPortForwardType cb3, ftpIsValidClientType cb4) {
ftpFindExternalFTPServerIp = cb1;
ftpAddUPNPPortForward = cb2;
ftpRemoveUPNPPortForward = cb3;
ftpIsValidClient = cb4;
}
ftpIsValidClient = cb4;
}
int ftpGetListenPort()
{
@@ -60,227 +60,227 @@ int ftpGetPassivePort()
//{
// return serverPassivePort;
//}
/**
* @brief Initializes and starts the server
*
*
* @return - 0: server started successfully
* - -1: could not create server socket
*/
int ftpStart(int portNumber)
/**
* @brief Initializes and starts the server
*
*
* @return - 0: server started successfully
* - -1: could not create server socket
*/
int ftpStart(int portNumber)
{
serverListenPort = portNumber;
serverPassiveListenPort = portNumber + 1;
serverPassiveListenPort = portNumber + 1;
server = -1; // set server socket to invalid value
//serverPassivePort = -1;
if(VERBOSE_MODE_ENABLED) printf("Feathery FTP-Server\n");
ftpArchInit();
if(VERBOSE_MODE_ENABLED) printf("Creating server socket");
server = ftpCreateServerSocket(serverListenPort); // create main listener socket
if(server < 0)
{
if(VERBOSE_MODE_ENABLED) printf("\t\terror\n");
return -1;
}
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server successfully started\n");
//serverPassivePort = -1;
if(VERBOSE_MODE_ENABLED) printf("Feathery FTP-Server\n");
ftpArchInit();
if(VERBOSE_MODE_ENABLED) printf("Creating server socket");
server = ftpCreateServerSocket(serverListenPort); // create main listener socket
if(server < 0)
{
if(VERBOSE_MODE_ENABLED) printf("\t\terror\n");
return -1;
}
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server successfully started\n");
ftpTrackSocket(server); // add socket to "watchlist"
/*
if(VERBOSE_MODE_ENABLED) printf("Creating server PASSIVE socket");
serverPassivePort = ftpCreateServerSocket(serverPassiveListenPort); // create main listener socket
if(serverPassivePort < 0)
{
if(VERBOSE_MODE_ENABLED) printf("\t\tpassive port error\n");
return -1;
}
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server passive port successfully started\n");
*/
return 0;
}
/**
* @brief Checks if the server has something to do
*
* In order of avoid blocking of ftpExecute this function can be used to
* determine if the server has something to do. You can call this function in
* a loop and everytime it returns nonezero its time to call ftpExecute().
* @todo implement me
*
* @return 0 noting to do; else server has received some data
*/
int ftpState(void)
{
return 0;
}
/**
* @brief Main server-thread
*
* Manages all client connections and active transmitions. In addtition
* all received control-strings are dispatched to the command-module.
* Note, the function blocks if there is nothing to do.
*/
int ftpExecute(void)
{
int processedWork=0;
int n=0;
int socksRdy=0;
ftpSession_S *pSession=NULL;
int sessionId=0;
int activeJobs=0;
int len;
int bufLen;
activeJobs = ftpGetActiveTransCnt(); // are there any active transmitions?
//for(n = 0; (activeJobs > 0) && (n < MAX_CONNECTIONS); n++)
for(n = 0; n < MAX_CONNECTIONS; n++)
{
pSession = ftpGetSession(n);
if(pSession->activeTrans.op) // has this session an active transmition?
{
processedWork = 1;
ftpExecTransmission(n); // do the job
activeJobs--;
}
}
if(ftpGetActiveTransCnt()) // don't block if there's still something to do
{
socksRdy = ftpSelect(TRUE);
}
else
{
//if(VERBOSE_MODE_ENABLED) printf("ftpExecute calling blocking select\n");
socksRdy = ftpSelect(FALSE);
}
if(socksRdy > 0)
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute socksRdy = %d\n",socksRdy);
if(VERBOSE_MODE_ENABLED) printf("Creating server PASSIVE socket");
processedWork = 1;
if(ftpTestSocket(server)) // server listner-socket signaled?
{
socket_t clientSocket;
ip_t remoteIP;
port_t remotePort;
socksRdy--;
clientSocket = ftpAcceptServerConnection(server, &remoteIP, &remotePort);
if(clientSocket >= 0)
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute ftpAcceptServerConnection = %d\n",clientSocket);
sessionId = ftpOpenSession(clientSocket, remoteIP, remotePort);
if(sessionId >= 0)
{
ftpTrackSocket(clientSocket);
ftpSendMsg(MSG_NORMAL, sessionId, 220, ftpMsg037);
}
else
{
if(VERBOSE_MODE_ENABLED) printf("ERROR: Connection refused; Session limit reached, about to close socket = %d\n",clientSocket);
ftpUntrackSocket(clientSocket);
ftpCloseSocket(&clientSocket);
}
}
}
//socksRdy = ftpSelect(TRUE);
for(n = 0; (socksRdy > 0) && (n < MAX_CONNECTIONS); n++)
{
pSession = ftpGetSession(n);
if(pSession->open)
{
socket_t ctrlSocket = pSession->ctrlSocket;
if(ftpTestSocket(ctrlSocket))
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute signaled socket = %d, session = %d\n",ctrlSocket,n);
socksRdy--;
bufLen = (LEN_RXBUF - pSession->rxBufWriteIdx);
len = ftpReceive(ctrlSocket,
&pSession->rxBuf[pSession->rxBufWriteIdx],
bufLen);
if(len <= 0) // has client shutdown the connection?
{
int errorNumber = getLastSocketError();
const char *errText = getLastSocketErrorText(&errorNumber);
if(VERBOSE_MODE_ENABLED) printf("In ftpExecute ERROR ON RECEIVE session = %d for socket = %d, data len = %d index = %d, len = %d, error = %d [%s]\n",n,ctrlSocket,bufLen,pSession->rxBufWriteIdx,len,errorNumber,errText);
ftpUntrackSocket(ctrlSocket);
ftpCloseSession(n);
}
else
{
pSession->rxBufWriteIdx += len;
ftpParseCmd(n);
}
}
/// @bug Session-Timeout-Management doesn't work
if((ftpGetUnixTime() - pSession->timeLastCmd) > SESSION_TIMEOUT)
{
if(VERBOSE_MODE_ENABLED) printf("\nIn ftpExecute ERROR: SESSION TIMED OUT for socket = %d\n",ctrlSocket);
ftpSendMsg(MSG_NORMAL, n, 421, ftpMsg036);
ftpUntrackSocket(ctrlSocket);
ftpCloseSession(n);
}
}
}
serverPassivePort = ftpCreateServerSocket(serverPassiveListenPort); // create main listener socket
if(serverPassivePort < 0)
{
if(VERBOSE_MODE_ENABLED) printf("\t\tpassive port error\n");
return -1;
}
return processedWork;
}
/**
* @brief Shut down the server
*
* Cuts all tcp-connections and frees all used resources.
* @return 0
*/
int ftpShutdown(void)
{
int n;
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown Feathery FTP-Server server [%d]\n",server);
ftpUntrackSocket(server);
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server passive port successfully started\n");
*/
return 0;
}
/**
* @brief Checks if the server has something to do
*
* In order of avoid blocking of ftpExecute this function can be used to
* determine if the server has something to do. You can call this function in
* a loop and everytime it returns nonezero its time to call ftpExecute().
* @todo implement me
*
* @return 0 noting to do; else server has received some data
*/
int ftpState(void)
{
return 0;
}
/**
* @brief Main server-thread
*
* Manages all client connections and active transmitions. In addtition
* all received control-strings are dispatched to the command-module.
* Note, the function blocks if there is nothing to do.
*/
int ftpExecute(void)
{
int processedWork=0;
int n=0;
int socksRdy=0;
ftpSession_S *pSession=NULL;
int sessionId=0;
int activeJobs=0;
int len;
int bufLen;
activeJobs = ftpGetActiveTransCnt(); // are there any active transmitions?
//for(n = 0; (activeJobs > 0) && (n < MAX_CONNECTIONS); n++)
for(n = 0; n < MAX_CONNECTIONS; n++)
{
pSession = ftpGetSession(n);
if(pSession->activeTrans.op) // has this session an active transmition?
{
processedWork = 1;
ftpExecTransmission(n); // do the job
activeJobs--;
}
}
if(ftpGetActiveTransCnt()) // don't block if there's still something to do
{
socksRdy = ftpSelect(TRUE);
}
else
{
//if(VERBOSE_MODE_ENABLED) printf("ftpExecute calling blocking select\n");
socksRdy = ftpSelect(FALSE);
}
if(socksRdy > 0)
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute socksRdy = %d\n",socksRdy);
processedWork = 1;
if(ftpTestSocket(server)) // server listner-socket signaled?
{
socket_t clientSocket;
ip_t remoteIP;
port_t remotePort;
socksRdy--;
clientSocket = ftpAcceptServerConnection(server, &remoteIP, &remotePort);
if(clientSocket >= 0)
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute ftpAcceptServerConnection = %d\n",clientSocket);
sessionId = ftpOpenSession(clientSocket, remoteIP, remotePort);
if(sessionId >= 0)
{
ftpTrackSocket(clientSocket);
ftpSendMsg(MSG_NORMAL, sessionId, 220, ftpMsg037);
}
else
{
if(VERBOSE_MODE_ENABLED) printf("ERROR: Connection refused; Session limit reached, about to close socket = %d\n",clientSocket);
ftpUntrackSocket(clientSocket);
ftpCloseSocket(&clientSocket);
}
}
}
//socksRdy = ftpSelect(TRUE);
for(n = 0; (socksRdy > 0) && (n < MAX_CONNECTIONS); n++)
{
pSession = ftpGetSession(n);
if(pSession->open)
{
socket_t ctrlSocket = pSession->ctrlSocket;
if(ftpTestSocket(ctrlSocket))
{
if(VERBOSE_MODE_ENABLED) printf("ftpExecute signaled socket = %d, session = %d\n",ctrlSocket,n);
socksRdy--;
bufLen = (LEN_RXBUF - pSession->rxBufWriteIdx);
len = ftpReceive(ctrlSocket,
&pSession->rxBuf[pSession->rxBufWriteIdx],
bufLen);
if(len <= 0) // has client shutdown the connection?
{
int errorNumber = getLastSocketError();
const char *errText = getLastSocketErrorText(&errorNumber);
if(VERBOSE_MODE_ENABLED) printf("In ftpExecute ERROR ON RECEIVE session = %d for socket = %d, data len = %d index = %d, len = %d, error = %d [%s]\n",n,ctrlSocket,bufLen,pSession->rxBufWriteIdx,len,errorNumber,errText);
ftpUntrackSocket(ctrlSocket);
ftpCloseSession(n);
}
else
{
pSession->rxBufWriteIdx += len;
ftpParseCmd(n);
}
}
/// @bug Session-Timeout-Management doesn't work
if((ftpGetUnixTime() - pSession->timeLastCmd) > SESSION_TIMEOUT)
{
if(VERBOSE_MODE_ENABLED) printf("\nIn ftpExecute ERROR: SESSION TIMED OUT for socket = %d\n",ctrlSocket);
ftpSendMsg(MSG_NORMAL, n, 421, ftpMsg036);
ftpUntrackSocket(ctrlSocket);
ftpCloseSession(n);
}
}
}
}
return processedWork;
}
/**
* @brief Shut down the server
*
* Cuts all tcp-connections and frees all used resources.
* @return 0
*/
int ftpShutdown(void)
{
int n;
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown Feathery FTP-Server server [%d]\n",server);
ftpUntrackSocket(server);
ftpCloseSocket(&server);
//ftpCloseSocket(serverPassivePort);
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown clients\n");
for(n = 0; n < MAX_CONNECTIONS; n++)
{
if(ftpGetSession(n)->open)
{
//ftpCloseSocket(serverPassivePort);
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown clients\n");
for(n = 0; n < MAX_CONNECTIONS; n++)
{
if(ftpGetSession(n)->open)
{
ftpUntrackSocket(ftpGetSession(n)->ctrlSocket);
}
ftpCloseSession(n);
}
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown stack\n");
ftpArchCleanup();
return 0;
}
ftpCloseSession(n);
}
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown stack\n");
ftpArchCleanup();
return 0;
}

View File

@@ -1,38 +1,38 @@
/* FEATHERY FTP-Server
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
* <https://sourceforge.net/projects/feathery>
*
* 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/>.
*/
/* FEATHERY FTP-Server
* Copyright (C) 2005-2010 Andreas Martin (andreas.martin@linuxmail.org)
* <https://sourceforge.net/projects/feathery>
*
* 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/>.
*/
#if 0
#include "ftpIfc.h"
int main(void)
{
ftpCreateAccount("anonymous", "", "./", FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
ftpCreateAccount("nothing", "", "./", 0);
ftpCreateAccount("reader", "", "./", FTP_ACC_RD);
ftpCreateAccount("writer", "", "./", FTP_ACC_WR);
ftpCreateAccount("lister", "", "./", FTP_ACC_LS);
ftpCreateAccount("admin", "xxx", "./", FTP_ACC_RD | FTP_ACC_WR | FTP_ACC_LS | FTP_ACC_DIR);
ftpStart();
while(1)
ftpExecute();
ftpShutdown();
}
#include "ftpIfc.h"
int main(void)
{
ftpCreateAccount("anonymous", "", "./", FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
ftpCreateAccount("nothing", "", "./", 0);
ftpCreateAccount("reader", "", "./", FTP_ACC_RD);
ftpCreateAccount("writer", "", "./", FTP_ACC_WR);
ftpCreateAccount("lister", "", "./", FTP_ACC_LS);
ftpCreateAccount("admin", "xxx", "./", FTP_ACC_RD | FTP_ACC_WR | FTP_ACC_LS | FTP_ACC_DIR);
ftpStart();
while(1)
ftpExecute();
ftpShutdown();
}
#endif

View File

@@ -1,370 +1,370 @@
/**
* 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;
if(VERBOSE_MODE_ENABLED) printf("ftpOpenSession started for ctrlSocket: %d\n",ctrlSocket);
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)
/**
* 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;
if(VERBOSE_MODE_ENABLED) printf("ftpOpenSession started for ctrlSocket: %d\n",ctrlSocket);
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)
{
if(VERBOSE_MODE_ENABLED) printf("In ftpCloseSession sessionId = %d, remote IP = %u, port = %d, ctrlSocket = %d\n",
id, sessions[id].remoteIp, sessions[id].remoteFTPServerPassivePort,sessions[id].ctrlSocket);
id, sessions[id].remoteIp, sessions[id].remoteFTPServerPassivePort,sessions[id].ctrlSocket);
if(ftpFindExternalFTPServerIp != NULL && ftpFindExternalFTPServerIp(sessions[id].remoteIp) != 0)
{
//if(ftpRemoveUPNPPortForward)
//{
//if(VERBOSE_MODE_ENABLED) printf("In ftpCmdPasv sessionId = %d, removing UPNP port forward [%d]\n", id,sessions[id].remoteFTPServerPassivePort);
//if(VERBOSE_MODE_ENABLED) printf("In ftpCmdPasv sessionId = %d, removing UPNP port forward [%d]\n", id,sessions[id].remoteFTPServerPassivePort);
//ftpRemoveUPNPPortForward(sessions[id].remoteFTPServerPassivePort, sessions[id].remoteFTPServerPassivePort);
sessions[id].remoteFTPServerPassivePort = 0;
//}
}
//if(sessions[id].open) {
if(VERBOSE_MODE_ENABLED) printf("In ftpCloseSession about to Close socket = %d, dataSocket = %d, activeDataSocket = %d, for sessionId = %d\n",sessions[id].ctrlSocket,sessions[id].passiveDataSocket,sessions[id].activeTrans.dataSocket,id);
//if(sessions[id].open) {
if(VERBOSE_MODE_ENABLED) printf("In ftpCloseSession about to Close socket = %d, dataSocket = %d, activeDataSocket = %d, for sessionId = %d\n",sessions[id].ctrlSocket,sessions[id].passiveDataSocket,sessions[id].activeTrans.dataSocket,id);
ftpUntrackSocket(sessions[id].ctrlSocket);
ftpCloseSocket(&sessions[id].ctrlSocket);
ftpCloseTransmission(id);
ftpCloseSocket(&sessions[id].ctrlSocket);
ftpCloseTransmission(id);
ftpUntrackSocket(sessions[id].passiveDataSocket);
ftpCloseSocket(&sessions[id].passiveDataSocket);
//}
sessions[id].remoteIp = 0;
sessions[id].ctrlSocket = 0;
sessions[id].passiveDataSocket = 0;
sessions[id].passiveIp = 0;
sessions[id].passivePort = 0;
sessions[id].activeTrans.dataSocket = 0;
sessions[id].activeTrans.op = OP_NOP;
sessions[id].activeTrans.fileSize = 0;
sessions[id].open = FALSE;
if(VERBOSE_MODE_ENABLED) printf("Session %d closed\n", id);
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;
sessions[id].passiveDataSocket = 0;
sessions[id].passiveIp = 0;
sessions[id].passivePort = 0;
sessions[id].activeTrans.dataSocket = 0;
sessions[id].activeTrans.op = OP_NOP;
sessions[id].activeTrans.fileSize = 0;
sessions[id].open = FALSE;
if(VERBOSE_MODE_ENABLED) printf("Session %d closed\n", id);
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(VERBOSE_MODE_ENABLED) printf("#1 ftpGetRealPath id = %d path [%s] ftpRoot [%s] sessions[id].workingDir [%s] normalize = %d\n", id, path, ftpRoot, sessions[id].workingDir,normalize);
if(VERBOSE_MODE_ENABLED) printf("#1 ftpGetRealPath id = %d path [%s] ftpRoot [%s] sessions[id].workingDir [%s] normalize = %d\n", id, path, ftpRoot, sessions[id].workingDir,normalize);
pathScratchBuf[0]='\0';
if(path[0] == '/' || strcmp(path,sessions[id].workingDir) == 0) // absolute path?
pathScratchBuf[0]='\0';
if(path[0] == '/' || strcmp(path,sessions[id].workingDir) == 0) // absolute path?
{
ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
}
else
ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
}
else
{
ftpMergePaths(pathScratchBuf, ftpRoot, sessions[id].workingDir, "/", path, NULL);
//ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
}
//ftpMergePaths(pathScratchBuf, ftpRoot, path, NULL);
}
if(VERBOSE_MODE_ENABLED) printf("#2 ftpGetRealPath path [%s] ftpRoot [%s] pathScratchBuf [%s]\n", path, ftpRoot, pathScratchBuf);
ftpRemoveDoubleSlash(pathScratchBuf);
if(normalize) {
if(VERBOSE_MODE_ENABLED) printf("#2 ftpGetRealPath path [%s] ftpRoot [%s] pathScratchBuf [%s]\n", path, ftpRoot, pathScratchBuf);
ftpRemoveDoubleSlash(pathScratchBuf);
if(normalize) {
normalizePath(pathScratchBuf);
}
ftpRemoveTrailingSlash(pathScratchBuf);
}
ftpRemoveTrailingSlash(pathScratchBuf);
if(VERBOSE_MODE_ENABLED) printf("#2 ftpGetRealPath path [%s] ftpRoot [%s] pathScratchBuf [%s]\n", path, ftpRoot, pathScratchBuf);
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(VERBOSE_MODE_ENABLED) printf("#2 ftpGetRealPath path [%s] ftpRoot [%s] pathScratchBuf [%s]\n", path, ftpRoot, pathScratchBuf);
if(VERBOSE_MODE_ENABLED) printf("ftpChangeDir path [%s] realPath [%s] sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
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, "/");
return pathScratchBuf;
}
if(VERBOSE_MODE_ENABLED) printf("ftpChangeDir path [%s] realPath [%s] NEW sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
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(VERBOSE_MODE_ENABLED) printf("In ftpCloseTransmission about to Close socket = %d, for sessionId = %d, fsHandle [%p] op = %d\n",
sessions[id].activeTrans.dataSocket, id,sessions[id].activeTrans.fsHandle,sessions[id].activeTrans.op);
if(sessions[id].activeTrans.dataSocket > 0)
{
ftpUntrackSocket(sessions[id].activeTrans.dataSocket);
ftpCloseSocket(&sessions[id].activeTrans.dataSocket);
}
if(sessions[id].activeTrans.op != OP_NOP) // is thera an active transmission?
{
if(sessions[id].activeTrans.op == OP_LIST)
{
ftpCloseDir(sessions[id].activeTrans.fsHandle);
}
else
{
ftpCloseFile(sessions[id].activeTrans.fsHandle);
}
sessions[id].activeTrans.fsHandle = NULL;
sessions[id].activeTrans.op = OP_NOP;
sessions[id].activeTrans.dataSocket = 0;
actTransCnt--;
}
}
/**
* @todo documentation
*/
int ftpGetActiveTransCnt(void)
{
return actTransCnt;
}
/**
* @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(VERBOSE_MODE_ENABLED) printf("ftpChangeDir path [%s] realPath [%s] sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
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(VERBOSE_MODE_ENABLED) printf("ftpChangeDir path [%s] realPath [%s] NEW sessions[id].workingDir [%s]\n", path, realPath, sessions[id].workingDir);
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(VERBOSE_MODE_ENABLED) printf("In ftpCloseTransmission about to Close socket = %d, for sessionId = %d, fsHandle [%p] op = %d\n",
sessions[id].activeTrans.dataSocket, id,sessions[id].activeTrans.fsHandle,sessions[id].activeTrans.op);
if(sessions[id].activeTrans.dataSocket > 0)
{
ftpUntrackSocket(sessions[id].activeTrans.dataSocket);
ftpCloseSocket(&sessions[id].activeTrans.dataSocket);
}
if(sessions[id].activeTrans.op != OP_NOP) // is thera an active transmission?
{
if(sessions[id].activeTrans.op == OP_LIST)
{
ftpCloseDir(sessions[id].activeTrans.fsHandle);
}
else
{
ftpCloseFile(sessions[id].activeTrans.fsHandle);
}
sessions[id].activeTrans.fsHandle = NULL;
sessions[id].activeTrans.op = OP_NOP;
sessions[id].activeTrans.dataSocket = 0;
actTransCnt--;
}
}
/**
* @todo documentation
*/
int ftpGetActiveTransCnt(void)
{
return actTransCnt;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff