- initial work for tileset ftp transfers, needs some testing

This commit is contained in:
Mark Vejvoda
2011-01-01 00:50:10 +00:00
parent 798c88e991
commit 2cdb8dd354
7 changed files with 327 additions and 55 deletions

View File

@@ -54,9 +54,13 @@ MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainM
currentTechName_factionPreview=""; currentTechName_factionPreview="";
currentFactionName_factionPreview=""; currentFactionName_factionPreview="";
ftpClientThread = NULL; ftpClientThread = NULL;
ftpMissingDataType = ftpmsg_MissingNone;
getMissingMapFromFTPServer = ""; getMissingMapFromFTPServer = "";
getMissingMapFromFTPServerInProgress = false; getMissingMapFromFTPServerInProgress = false;
getMissingTilesetFromFTPServer = "";
getMissingTilesetFromFTPServerInProgress = false;
currentFactionLogo = ""; currentFactionLogo = "";
factionTexture=NULL; factionTexture=NULL;
@@ -389,8 +393,16 @@ MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainM
if(mapPathList.size() > 1) { if(mapPathList.size() > 1) {
mapsPath.second = mapPathList[1]; mapsPath.second = mapPathList[1];
} }
std::pair<string,string> tilesetsPath;
vector<string> tilesetsList = Config::getInstance().getPathListForType(ptTilesets);
if(tilesetsList.size() > 0) {
tilesetsPath.first = tilesetsList[0];
if(tilesetsList.size() > 1) {
tilesetsPath.second = tilesetsList[1];
}
}
ftpClientThread = new FTPClientThread(portNumber,serverUrl,mapsPath, this); ftpClientThread = new FTPClientThread(portNumber,serverUrl,mapsPath,tilesetsPath,this);
ftpClientThread->start(); ftpClientThread->start();
} }
@@ -432,6 +444,7 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){
soundRenderer.playFx(coreData.getClickSoundA()); soundRenderer.playFx(coreData.getClickSoundA());
ftpMessageBox.setEnabled(false); ftpMessageBox.setEnabled(false);
if(button == 1) { if(button == 1) {
if(ftpMissingDataType == ftpmsg_MissingMap) {
getMissingMapFromFTPServerInProgress = true; getMissingMapFromFTPServerInProgress = true;
char szMsg[1024]=""; char szMsg[1024]="";
@@ -442,6 +455,18 @@ void MenuStateConnectedGame::mouseClick(int x, int y, MouseButton mouseButton){
ftpClientThread->addMapToRequests(getMissingMapFromFTPServer); ftpClientThread->addMapToRequests(getMissingMapFromFTPServer);
} }
} }
else if(ftpMissingDataType == ftpmsg_MissingTileset) {
getMissingTilesetFromFTPServerInProgress = true;
char szMsg[1024]="";
sprintf(szMsg,"Player: %s is attempting to download the tileset: %s",getHumanPlayerName().c_str(),getMissingTilesetFromFTPServer.c_str());
clientInterface->sendTextMessage(szMsg,-1, true);
if(ftpClientThread != NULL) {
ftpClientThread->addTilesetToRequests(getMissingTilesetFromFTPServer);
}
}
}
} }
} }
else if(buttonDisconnect.mouseClick(x,y)){ else if(buttonDisconnect.mouseClick(x,y)){
@@ -951,6 +976,8 @@ void MenuStateConnectedGame::update() {
if(gameSettings == NULL) { if(gameSettings == NULL) {
throw runtime_error("gameSettings == NULL"); throw runtime_error("gameSettings == NULL");
} }
if(getMissingTilesetFromFTPServerInProgress == false) {
// tileset // tileset
if(std::find(this->tileSets.begin(),this->tileSets.end(),gameSettings->getTileset()) != this->tileSets.end()) { if(std::find(this->tileSets.begin(),this->tileSets.end(),gameSettings->getTileset()) != this->tileSets.end()) {
lastMissingTileSet = ""; lastMissingTileSet = "";
@@ -958,6 +985,20 @@ void MenuStateConnectedGame::update() {
tilesets.push_back(formatString(gameSettings->getTileset())); tilesets.push_back(formatString(gameSettings->getTileset()));
} }
else { else {
// try to get the map via ftp
if(ftpClientThread != NULL && getMissingTilesetFromFTPServer != gameSettings->getTileset()) {
if(ftpMessageBox.getEnabled() == false) {
getMissingTilesetFromFTPServer = gameSettings->getTileset();
Lang &lang= Lang::getInstance();
char szBuf[1024]="";
sprintf(szBuf,"%s %s ?",lang.get("DownloadMissingTilesetQuestion").c_str(),gameSettings->getTileset().c_str());
ftpMissingDataType = ftpmsg_MissingTileset;
showFTPMessageBox(szBuf, lang.get("Question"), false);
}
}
tilesets.push_back("***missing***"); tilesets.push_back("***missing***");
NetworkManager &networkManager= NetworkManager::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance();
@@ -975,6 +1016,7 @@ void MenuStateConnectedGame::update() {
} }
} }
listBoxTileset.setItems(tilesets); listBoxTileset.setItems(tilesets);
}
// techtree // techtree
techtree.push_back(formatString(gameSettings->getTech())); techtree.push_back(formatString(gameSettings->getTech()));
@@ -1015,6 +1057,7 @@ void MenuStateConnectedGame::update() {
char szBuf[1024]=""; char szBuf[1024]="";
sprintf(szBuf,"%s %s ?",lang.get("DownloadMissingMapQuestion").c_str(),currentMap.c_str()); sprintf(szBuf,"%s %s ?",lang.get("DownloadMissingMapQuestion").c_str(),currentMap.c_str());
ftpMissingDataType = ftpmsg_MissingMap;
showFTPMessageBox(szBuf, lang.get("Question"), false); showFTPMessageBox(szBuf, lang.get("Question"), false);
} }
} }
@@ -1631,11 +1674,12 @@ void MenuStateConnectedGame::showFTPMessageBox(const string &text, const string
} }
} }
void MenuStateConnectedGame::FTPClient_CallbackEvent(string mapFilename, FTP_Client_ResultType result) { void MenuStateConnectedGame::FTPClient_CallbackEvent(string itemName, FTP_Client_ResultType result) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(ftpMissingDataType == ftpmsg_MissingMap) {
getMissingMapFromFTPServerInProgress = false; getMissingMapFromFTPServerInProgress = false;
printf("Got FTP Callback for [%s] result = %d\n",mapFilename.c_str(),result); printf("Got FTP Callback for [%s] result = %d\n",itemName.c_str(),result);
NetworkManager &networkManager= NetworkManager::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance();
ClientInterface* clientInterface= networkManager.getClientInterface(); ClientInterface* clientInterface= networkManager.getClientInterface();
@@ -1651,6 +1695,26 @@ void MenuStateConnectedGame::FTPClient_CallbackEvent(string mapFilename, FTP_Cli
sprintf(szMsg,"Player: %s FAILED to download the map: %s",getHumanPlayerName().c_str(),gameSettings->getMap().c_str()); sprintf(szMsg,"Player: %s FAILED to download the map: %s",getHumanPlayerName().c_str(),gameSettings->getMap().c_str());
clientInterface->sendTextMessage(szMsg,-1, true); clientInterface->sendTextMessage(szMsg,-1, true);
} }
}
else if(ftpMissingDataType == ftpmsg_MissingTileset) {
getMissingTilesetFromFTPServerInProgress = false;
printf("Got FTP Callback for [%s] result = %d\n",itemName.c_str(),result);
NetworkManager &networkManager= NetworkManager::getInstance();
ClientInterface* clientInterface= networkManager.getClientInterface();
const GameSettings *gameSettings = clientInterface->getGameSettings();
if(result == ftp_crt_SUCCESS) {
char szMsg[1024]="";
sprintf(szMsg,"Player: %s SUCCESSFULLY downloaded the tileset: %s",getHumanPlayerName().c_str(),gameSettings->getTileset().c_str());
clientInterface->sendTextMessage(szMsg,-1, true);
}
else {
char szMsg[1024]="";
sprintf(szMsg,"Player: %s FAILED to download the tileset: %s",getHumanPlayerName().c_str(),gameSettings->getTileset().c_str());
clientInterface->sendTextMessage(szMsg,-1, true);
}
}
} }
}}//end namespace }}//end namespace

View File

@@ -27,6 +27,11 @@ enum JoinMenu {
jmCount jmCount
}; };
enum FTPMessageType {
ftpmsg_MissingNone,
ftpmsg_MissingMap,
ftpmsg_MissingTileset
};
// =============================== // ===============================
// class MenuStateConnectedGame // class MenuStateConnectedGame
@@ -138,9 +143,14 @@ private:
GraphicMessageBox ftpMessageBox; GraphicMessageBox ftpMessageBox;
FTPClientThread *ftpClientThread; FTPClientThread *ftpClientThread;
FTPMessageType ftpMissingDataType;
string getMissingMapFromFTPServer; string getMissingMapFromFTPServer;
bool getMissingMapFromFTPServerInProgress; bool getMissingMapFromFTPServerInProgress;
string getMissingTilesetFromFTPServer;
bool getMissingTilesetFromFTPServerInProgress;
public: public:
MenuStateConnectedGame(Program *program, MainMenu *mainMenu, JoinMenu joinMenuInfo=jmSimple, bool openNetworkSlots= false); MenuStateConnectedGame(Program *program, MainMenu *mainMenu, JoinMenu joinMenuInfo=jmSimple, bool openNetworkSlots= false);
@@ -171,7 +181,7 @@ private:
void showMessageBox(const string &text, const string &header, bool toggle); void showMessageBox(const string &text, const string &header, bool toggle);
void showFTPMessageBox(const string &text, const string &header, bool toggle); void showFTPMessageBox(const string &text, const string &header, bool toggle);
virtual void FTPClient_CallbackEvent(string mapFilename, FTP_Client_ResultType result); virtual void FTPClient_CallbackEvent(string itemName, FTP_Client_ResultType result);
}; };
}}//end namespace }}//end namespace

View File

@@ -96,9 +96,18 @@ ServerInterface::ServerInterface() {
} }
} }
std::pair<string,string> tilesetsPath;
vector<string> tilesetsList = Config::getInstance().getPathListForType(ptTilesets);
if(tilesetsList.size() > 0) {
tilesetsPath.first = tilesetsList[0];
if(tilesetsList.size() > 1) {
tilesetsPath.second = tilesetsList[1];
}
}
int portNumber = Config::getInstance().getInt("FTPServerPort",intToStr(ServerSocket::getFTPServerPort()).c_str()); int portNumber = Config::getInstance().getInt("FTPServerPort",intToStr(ServerSocket::getFTPServerPort()).c_str());
ServerSocket::setFTPServerPort(portNumber); ServerSocket::setFTPServerPort(portNumber);
ftpServer = new FTPServerThread(mapsPath,portNumber); ftpServer = new FTPServerThread(mapsPath,tilesetsPath,portNumber);
ftpServer->start(); ftpServer->start();
} }
} }

View File

@@ -44,20 +44,29 @@ protected:
string serverUrl; string serverUrl;
FTPClientCallbackInterface *pCBObject; FTPClientCallbackInterface *pCBObject;
std::pair<string,string> mapsPath; std::pair<string,string> mapsPath;
std::pair<string,string> tilesetsPath;
Mutex mutexMapFileList; Mutex mutexMapFileList;
vector<string> mapFileList; vector<string> mapFileList;
Mutex mutexTilesetList;
vector<string> tilesetList;
void getMapFromServer(string mapFilename); void getMapFromServer(string mapFilename);
FTP_Client_ResultType getMapFromServer(string mapFileName, string ftpUser, string ftpUserPassword); FTP_Client_ResultType getMapFromServer(string mapFileName, string ftpUser, string ftpUserPassword);
void getTilesetFromServer(string tileSetName);
FTP_Client_ResultType getTilesetFromServer(string tileSetName, string tileSetNameSubfolder, string ftpUser, string ftpUserPassword);
public: public:
FTPClientThread(int portNumber,string serverUrl, std::pair<string,string> mapsPath, FTPClientCallbackInterface *pCBObject); FTPClientThread(int portNumber,string serverUrl, std::pair<string,string> mapsPath, std::pair<string,string> tilesetsPath, FTPClientCallbackInterface *pCBObject);
virtual void execute(); virtual void execute();
virtual void signalQuit(); virtual void signalQuit();
virtual bool shutdownAndWait(); virtual bool shutdownAndWait();
void addMapToRequests(string mapFilename); void addMapToRequests(string mapFilename);
void addTilesetToRequests(string tileSetName);
}; };
}}//end namespace }}//end namespace

View File

@@ -31,12 +31,12 @@ class FTPServerThread : public BaseThread
{ {
protected: protected:
std::pair<string,string> mapsPath; std::pair<string,string> mapsPath;
std::pair<string,string> tilesetsPath;
int portNumber; int portNumber;
//uint32 externalIp;
public: public:
FTPServerThread(std::pair<string,string> mapsPath, int portNumber); FTPServerThread(std::pair<string,string> mapsPath, std::pair<string,string> tilesetsPath, int portNumber);
~FTPServerThread(); ~FTPServerThread();
virtual void execute(); virtual void execute();
virtual void signalQuit(); virtual void signalQuit();

View File

@@ -56,7 +56,7 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread opening file for writing [%s]\n",out->filename); if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread opening file for writing [%s]\n",out->filename);
/* open file for writing */ /* open file for writing */
out->stream=fopen(out->filename, "wb"); out->stream = fopen(out->filename, "wb");
if(out->stream == NULL) { if(out->stream == NULL) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread FAILED to open file for writing [%s]\n",out->filename); if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread FAILED to open file for writing [%s]\n",out->filename);
@@ -66,10 +66,57 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) {
return fwrite(buffer, size, nmemb, out->stream); return fwrite(buffer, size, nmemb, out->stream);
} }
FTPClientThread::FTPClientThread(int portNumber, string serverUrl, std::pair<string,string> mapsPath, FTPClientCallbackInterface *pCBObject) : BaseThread() {
static long file_is_comming(struct curl_fileinfo *finfo,void *data,int remains)
{
printf("%3d %40s %10luB ", remains, finfo->filename,(unsigned long)finfo->size);
switch(finfo->filetype) {
case CURLFILETYPE_DIRECTORY:
printf(" DIR\n");
break;
case CURLFILETYPE_FILE:
printf("FILE ");
break;
default:
printf("OTHER\n");
break;
}
if(finfo->filetype == CURLFILETYPE_FILE) {
// do not transfer files >= 50B
//if(finfo->size > 50) {
// printf("SKIPPED\n");
// return CURL_CHUNK_BGN_FUNC_SKIP;
//}
struct FtpFile *out=(struct FtpFile *)data;
out->stream = fopen(finfo->filename, "w");
if(!out->stream) {
return CURL_CHUNK_BGN_FUNC_FAIL;
}
}
return CURL_CHUNK_BGN_FUNC_OK;
}
static long file_is_downloaded(void *data)
{
struct FtpFile *out=(struct FtpFile *)data;
if(out->stream) {
printf("DOWNLOADED\n");
fclose(out->stream);
out->stream = 0x0;
}
return CURL_CHUNK_END_FUNC_OK;
}
FTPClientThread::FTPClientThread(int portNumber, string serverUrl, std::pair<string,string> mapsPath, std::pair<string,string> tilesetsPath, FTPClientCallbackInterface *pCBObject) : BaseThread() {
this->portNumber = portNumber; this->portNumber = portNumber;
this->serverUrl = serverUrl; this->serverUrl = serverUrl;
this->mapsPath = mapsPath; this->mapsPath = mapsPath;
this->tilesetsPath = tilesetsPath;
this->pCBObject = pCBObject; this->pCBObject = pCBObject;
} }
@@ -175,6 +222,127 @@ void FTPClientThread::addMapToRequests(string mapFilename) {
} }
} }
void FTPClientThread::addTilesetToRequests(string tileSetName) {
MutexSafeWrapper safeMutex(&mutexTilesetList);
if(std::find(tilesetList.begin(),tilesetList.end(),tileSetName) == tilesetList.end()) {
tilesetList.push_back(tileSetName);
}
}
void FTPClientThread::getTilesetFromServer(string tileSetName) {
FTP_Client_ResultType result = getTilesetFromServer(tileSetName, "", "tilsets_custom", "mg_ftp_server");
if(result != ftp_crt_SUCCESS && this->getQuitStatus() == false) {
result = getTilesetFromServer(tileSetName, "tilesets", "", "mg_ftp_server");
}
if(this->pCBObject != NULL) {
this->pCBObject->FTPClient_CallbackEvent(tileSetName,result);
}
}
FTP_Client_ResultType FTPClientThread::getTilesetFromServer(string tileSetName, string tileSetNameSubfolder, string ftpUser, string ftpUserPassword) {
CURLcode res;
FTP_Client_ResultType result = ftp_crt_FAIL;
string destFile = this->mapsPath.second;
if(EndsWith(destFile,"/") == false && EndsWith(destFile,"\\") == false) {
destFile += "/";
}
destFile += tileSetName;
if(tileSetNameSubfolder != "") {
destFile += tileSetNameSubfolder;
if(EndsWith(destFile,"/") == false && EndsWith(destFile,"\\") == false) {
destFile += "/";
}
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str());
struct FtpFile ftpfile = {
destFile.c_str(), /* name to store the file as if succesful */
NULL,
this
};
//curl_global_init(CURL_GLOBAL_DEFAULT);
CURL *curl = curl_easy_init();
if(curl) {
ftpfile.stream = NULL;
char szBuf[1024]="";
sprintf(szBuf,"ftp://%s:%s@%s:%d/%s*",ftpUser.c_str(),ftpUserPassword.c_str(),serverUrl.c_str(),portNumber,tileSetName.c_str());
curl_easy_setopt(curl, CURLOPT_URL,szBuf);
// turn on wildcard matching
curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
// callback is called before download of concrete file started
curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_comming);
// callback is called after data from the file have been transferred
curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
// put transfer data into callbacks
// helper data
//struct callback_data data = { 0 };
curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &ftpfile);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
// Define our callback to get called when there's data to be written
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
// Set a pointer to our struct to pass to the callback
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
// Switch on full protocol/debug output
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(CURLE_OK != res) {
// we failed
fprintf(stderr, "curl told us %d\n", res);
}
else {
result = ftp_crt_SUCCESS;
bool requireMoreFolders = false;
if(tileSetNameSubfolder == "") {
tileSetNameSubfolder = "models";
requireMoreFolders = true;
}
else if(tileSetNameSubfolder == "models") {
tileSetNameSubfolder = "sounds";
requireMoreFolders = true;
}
else if(tileSetNameSubfolder == "sounds") {
tileSetNameSubfolder = "textures";
requireMoreFolders = true;
}
else if(tileSetNameSubfolder == "textures") {
tileSetNameSubfolder = "textures";
requireMoreFolders = true;
}
if(requireMoreFolders == true) {
FTP_Client_ResultType result2 = getTilesetFromServer(tileSetName, tileSetNameSubfolder, ftpUser, ftpUserPassword);
}
}
curl_easy_cleanup(curl);
}
if(ftpfile.stream) {
fclose(ftpfile.stream);
ftpfile.stream = NULL;
}
return result;
}
void FTPClientThread::execute() { void FTPClientThread::execute() {
{ {

View File

@@ -36,8 +36,9 @@ ip_t FindExternalFTPServerIp(ip_t clientIp) {
return result; return result;
} }
FTPServerThread::FTPServerThread(std::pair<string,string> mapsPath,int portNumber) : BaseThread() { FTPServerThread::FTPServerThread(std::pair<string,string> mapsPath,std::pair<string,string> tilesetsPath, int portNumber) : BaseThread() {
this->mapsPath = mapsPath; this->mapsPath = mapsPath;
this->tilesetsPath = tilesetsPath;
this->portNumber = portNumber; this->portNumber = portNumber;
ftpInit(&FindExternalFTPServerIp,&UPNP_Tools::AddUPNPPortForward,&UPNP_Tools::RemoveUPNPPortForward); ftpInit(&FindExternalFTPServerIp,&UPNP_Tools::AddUPNPPortForward,&UPNP_Tools::RemoveUPNPPortForward);
@@ -82,6 +83,7 @@ void FTPServerThread::execute() {
try { try {
//ftpCreateAccount("anonymous", "", mapsPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); //ftpCreateAccount("anonymous", "", mapsPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
// Setup FTP Users and permissions for maps
if(mapsPath.first != "") { if(mapsPath.first != "") {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] mapsPath #1 [%s]\n",__FILE__,__FUNCTION__,__LINE__,mapsPath.first.c_str()); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] mapsPath #1 [%s]\n",__FILE__,__FUNCTION__,__LINE__,mapsPath.first.c_str());
ftpCreateAccount("maps", "mg_ftp_server", mapsPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); ftpCreateAccount("maps", "mg_ftp_server", mapsPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
@@ -91,6 +93,16 @@ void FTPServerThread::execute() {
ftpCreateAccount("maps_custom", "mg_ftp_server", mapsPath.second.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); ftpCreateAccount("maps_custom", "mg_ftp_server", mapsPath.second.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
} }
// Setup FTP Users and permissions for tilesets
if(tilesetsPath.first != "") {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] tilesetsPath #1 [%s]\n",__FILE__,__FUNCTION__,__LINE__,tilesetsPath.first.c_str());
ftpCreateAccount("tilsets", "mg_ftp_server", tilesetsPath.first.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
}
if(tilesetsPath.second != "") {
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] tilesetsPath #2 [%s]\n",__FILE__,__FUNCTION__,__LINE__,tilesetsPath.second.c_str());
ftpCreateAccount("tilsets_custom", "mg_ftp_server", tilesetsPath.second.c_str(), FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
}
/* /*
ftpCreateAccount("anonymous", "", "./", FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR); ftpCreateAccount("anonymous", "", "./", FTP_ACC_RD | FTP_ACC_LS | FTP_ACC_DIR);
ftpCreateAccount("nothing", "", "./", 0); ftpCreateAccount("nothing", "", "./", 0);