1 // ==============================================================
2 // This file is part of MegaGlest Shared Library (www.glest.org)
3 //
4 // Copyright (C) 2009-2010 Titus Tscharntke (info@titusgames.de) and
5 // Mark Vejvoda (mark_vejvoda@hotmail.com)
6 //
7 // You can redistribute this code and/or modify it under
8 // the terms of the GNU General Public License as published
9 // by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version
11 // ==============================================================
12
13 #include "miniftpclient.h"
14 #include "util.h"
15 #include "platform_common.h"
16
17 #include <curl/curl.h>
18 #include <curl/easy.h>
19 #include <algorithm>
20 #include "conversion.h"
21 #include "platform_util.h"
22
23 using namespace Shared::Util;
24 using namespace Shared::PlatformCommon;
25
26 namespace Shared { namespace PlatformCommon {
27
28 static const char *FTP_MAPS_CUSTOM_USERNAME = "maps_custom";
29 static const char *FTP_MAPS_USERNAME = "maps";
30 static const char *FTP_TILESETS_CUSTOM_USERNAME = "tilesets_custom";
31 static const char *FTP_TILESETS_USERNAME = "tilesets";
32 static const char *FTP_TECHTREES_CUSTOM_USERNAME = "techtrees_custom";
33 static const char *FTP_TECHTREES_USERNAME = "techtrees";
34
35 static const char *FTP_TEMPFILES_USERNAME = "temp";
36
37 static const char *FTP_COMMON_PASSWORD = "mg_ftp_server";
38
39 /*
40 * This is an example showing how to get a single file from an FTP server.
41 * It delays the actual destination file creation until the first write
42 * callback so that it won't create an empty file in case the remote file
43 * doesn't exist or something else fails.
44 */
45
46 struct FtpFile {
47 const char *itemName;
48 const char *filename;
49 const char *filepath;
50 FILE *stream;
51 FTPClientThread *ftpServer;
52 string currentFilename;
53 bool isValidXfer;
54 FTP_Client_CallbackType downloadType;
55 };
56
my_fwrite(void * buffer,size_t size,size_t nmemb,void * stream)57 static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) {
58 struct FtpFile *out=(struct FtpFile *)stream;
59
60 string fullFilePath = "";
61 if(out != NULL && out->filepath != NULL) {
62 fullFilePath = out->filepath;
63 }
64 if(out != NULL && out->filename != NULL) {
65 fullFilePath += out->filename;
66 }
67
68 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread writing to file [%s]\n",fullFilePath.c_str());
69 //printf ("===> FTP Client thread writing to file [%s]\n",fullFilePath.c_str());
70
71 // Abort file xfer and delete partial file
72 if(out && out->ftpServer && out->ftpServer->getQuitStatus() == true) {
73 if(out->stream) {
74 fclose(out->stream);
75 out->stream = NULL;
76 }
77
78 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread CANCELLED, deleting file for writing [%s]\n",fullFilePath.c_str());
79 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread CANCELLED, deleting file for writing [%s]\n",fullFilePath.c_str());
80
81
82 removeFile(fullFilePath);
83 return 0;
84 }
85
86 if(out && out->stream == NULL) {
87 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread opening file for writing [%s]\n",fullFilePath.c_str());
88 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread opening file for writing [%s]\n",fullFilePath.c_str());
89
90 /* open file for writing */
91 #ifdef WIN32
92 out->stream= _wfopen(utf8_decode(fullFilePath).c_str(), L"wb");
93 #else
94 out->stream = fopen(fullFilePath.c_str(), "wb");
95 #endif
96 if(out->stream == NULL) {
97 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
98 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
99 SystemFlags::OutputDebug(SystemFlags::debugError,"===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
100 return 0; /* failure, can't open file to write */
101 }
102
103 out->isValidXfer = true;
104 }
105 else if(out == NULL) {
106 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> #2 FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
107 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> #2 FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
108 SystemFlags::OutputDebug(SystemFlags::debugError,"===> #2 FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
109 return 0; /* failure, can't open file to write */
110 }
111
112 size_t result = fwrite(buffer, size, nmemb, out->stream);
113 if(result != nmemb) {
114 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("===> FTP Client thread FAILED to write data chunk to file [%s] nmemb = " MG_SIZE_T_SPECIFIER ", result = " MG_SIZE_T_SPECIFIER "\n",fullFilePath.c_str(),nmemb,result);
115 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread FAILED to write data chunk to file [%s] nmemb = " MG_SIZE_T_SPECIFIER ", result = " MG_SIZE_T_SPECIFIER "\n",fullFilePath.c_str(),nmemb,result);
116 SystemFlags::OutputDebug(SystemFlags::debugError,"===> FTP Client thread FAILED to write data chunk to file [%s] nmemb = " MG_SIZE_T_SPECIFIER ", result = " MG_SIZE_T_SPECIFIER "\n",fullFilePath.c_str(),nmemb,result);
117 //return -1; /* failure, can't open file to write */
118 }
119 return result;
120 }
121
122 /*
123 static long file_is_comming(struct curl_fileinfo *finfo,void *data,int remains) {
124 struct FtpFile *out=(struct FtpFile *)data;
125
126 string rootFilePath = "";
127 string fullFilePath = "";
128 if(out != NULL && out->filepath != NULL) {
129 rootFilePath = out->filepath;
130 }
131 if(out != NULL && out->filename != NULL) {
132 fullFilePath = rootFilePath + finfo->filename;
133 }
134
135 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n===> FTP Client thread file_is_comming: remains: [%3d] filename: [%s] size: [%10luB] ", remains, finfo->filename,(unsigned long)finfo->size);
136 SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread file_is_comming: remains: [%3d] filename: [%s] size: [%10luB] ", remains, finfo->filename,(unsigned long)finfo->size);
137
138 if(out != NULL) {
139 //out->currentFilename = finfo->filename;
140 out->currentFilename = fullFilePath;
141
142 if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" current filename: [%s] ", fullFilePath.c_str());
143 SystemFlags::OutputDebug(SystemFlags::debugNetwork,"current filename: [%s] ", fullFilePath.c_str());
144 }
145
146 switch(finfo->filetype) {
147 case CURLFILETYPE_DIRECTORY:
148 if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" DIR (creating [%s%s])\n",rootFilePath.c_str(),finfo->filename);
149 SystemFlags::OutputDebug(SystemFlags::debugNetwork," DIR (creating [%s%s])\n",rootFilePath.c_str(),finfo->filename);
150
151 rootFilePath += finfo->filename;
152 createDirectoryPaths(rootFilePath.c_str());
153 break;
154 case CURLFILETYPE_FILE:
155 if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" FILE ");
156 SystemFlags::OutputDebug(SystemFlags::debugNetwork," FILE ");
157 break;
158 default:
159 if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" OTHER\n");
160 SystemFlags::OutputDebug(SystemFlags::debugNetwork," OTHER\n");
161 break;
162 }
163
164 if(finfo->filetype == CURLFILETYPE_FILE) {
165 // do not transfer files >= 50B
166 //if(finfo->size > 50) {
167 // printf("SKIPPED\n");
168 // return CURL_CHUNK_BGN_FUNC_SKIP;
169 //}
170
171 if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" opening file [%s] ", fullFilePath.c_str());
172 SystemFlags::OutputDebug(SystemFlags::debugNetwork," opening file [%s] ", fullFilePath.c_str());
173
174 out->stream = fopen(fullFilePath.c_str(), "wb");
175 if(out->stream == NULL) {
176 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
177 SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread FAILED to open file for writing [%s]\n",fullFilePath.c_str());
178
179 return CURL_CHUNK_BGN_FUNC_FAIL;
180 }
181 }
182
183 out->isValidXfer = true;
184 return CURL_CHUNK_BGN_FUNC_OK;
185 }
186
187 static long file_is_downloaded(void *data) {
188 struct FtpFile *out=(struct FtpFile *)data;
189 if(out->stream) {
190 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("DOWNLOAD COMPLETE!\n");
191 SystemFlags::OutputDebug(SystemFlags::debugNetwork,"DOWNLOAD COMPLETE!\n");
192
193 fclose(out->stream);
194 out->stream = NULL;
195 }
196 return CURL_CHUNK_END_FUNC_OK;
197 }
198 */
199
file_progress(struct FtpFile * out,double download_total,double download_now,double upload_total,double upload_now)200 int file_progress(struct FtpFile *out,double download_total, double download_now, double upload_total,double upload_now) {
201 //if(SystemFlags::VERBOSE_MODE_ENABLED) printf(" download progress [%f][%f][%f][%f] ",download_total,download_now,upload_total,upload_now);
202 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork," download progress [%f][%f][%f][%f] ",download_total,download_now,upload_total,upload_now);
203
204 if(out != NULL &&
205 out->ftpServer != NULL &&
206 out->ftpServer->getCallBackObject() != NULL) {
207 if(out->ftpServer->getQuitStatus() == true) {
208 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread CANCELLED\n");
209 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread CANCELLED\n");
210
211 return -1;
212 }
213 FTPClientCallbackInterface::FtpProgressStats stats;
214 stats.download_total = download_total;
215 stats.download_now = download_now;
216 stats.upload_total = upload_total;
217 stats.upload_now = upload_now;
218 stats.currentFilename = out->currentFilename;
219 stats.downloadType = out->downloadType;
220
221 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
222 MutexSafeWrapper safeMutex(out->ftpServer->getProgressMutex(),mutexOwnerId);
223 out->ftpServer->getProgressMutex()->setOwnerId(mutexOwnerId);
224 out->ftpServer->getCallBackObject()->FTPClient_CallbackEvent(
225 out->itemName,
226 ftp_cct_DownloadProgress,
227 make_pair(ftp_crt_SUCCESS,""),
228 &stats);
229 }
230
231 return 0;
232 }
233
FTPClientThread(int portNumber,string serverUrl,std::pair<string,string> mapsPath,std::pair<string,string> tilesetsPath,std::pair<string,string> techtreesPath,std::pair<string,string> scenariosPath,FTPClientCallbackInterface * pCBObject,string fileArchiveExtension,string fileArchiveExtractCommand,string fileArchiveExtractCommandParameters,int fileArchiveExtractCommandSuccessResult,string tempFilesPath)234 FTPClientThread::FTPClientThread(int portNumber, string serverUrl,
235 std::pair<string,string> mapsPath,
236 std::pair<string,string> tilesetsPath,
237 std::pair<string,string> techtreesPath,
238 std::pair<string,string> scenariosPath,
239 FTPClientCallbackInterface *pCBObject,
240 string fileArchiveExtension,
241 string fileArchiveExtractCommand,
242 string fileArchiveExtractCommandParameters,
243 int fileArchiveExtractCommandSuccessResult,
244 string tempFilesPath) : BaseThread() {
245
246 uniqueID = "FTPClientThread";
247 this->portNumber = portNumber;
248 this->serverUrl = serverUrl;
249 this->mapsPath = mapsPath;
250 this->tilesetsPath = tilesetsPath;
251 this->techtreesPath = techtreesPath;
252 this->scenariosPath = scenariosPath;
253 this->pCBObject = pCBObject;
254 this->shellCommandCallbackUserData = "";
255
256 this->fileArchiveExtension = fileArchiveExtension;
257 this->fileArchiveExtractCommand = fileArchiveExtractCommand;
258 this->fileArchiveExtractCommandParameters = fileArchiveExtractCommandParameters;
259 this->fileArchiveExtractCommandSuccessResult = fileArchiveExtractCommandSuccessResult;
260 this->tempFilesPath = tempFilesPath;
261
262 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line %d] Using FTP port #: %d, serverUrl [%s]\n",__FILE__,__FUNCTION__,__LINE__,portNumber,serverUrl.c_str());
263 }
264
signalQuit()265 void FTPClientThread::signalQuit() {
266 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("===> FTP Client: signalQuit\n");
267 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client: signalQuit\n");
268 BaseThread::signalQuit();
269 }
270
shutdownAndWait()271 bool FTPClientThread::shutdownAndWait() {
272 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("===> FTP Client: shutdownAndWait\n");
273 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client: shutdownAndWait\n");
274
275 signalQuit();
276 return BaseThread::shutdownAndWait();
277 }
278
279
getMapFromServer(pair<string,string> mapFileName,string ftpUser,string ftpUserPassword)280 pair<FTP_Client_ResultType,string> FTPClientThread::getMapFromServer(pair<string,string> mapFileName, string ftpUser, string ftpUserPassword) {
281 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
282
283 string destFileExt = "";
284 string destFile = this->mapsPath.second;
285
286 endPathWithSlash(destFile);
287 destFile += mapFileName.first;
288
289 if(mapFileName.second == "") {
290 if(EndsWith(destFile,".mgm") == false && EndsWith(destFile,".gbm") == false) {
291 destFileExt = ".mgm";
292 destFile += destFileExt;
293 }
294 }
295
296 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str());
297 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread about to try to RETR into [%s]\n",destFile.c_str());
298
299 struct FtpFile ftpfile = {
300 NULL,
301 destFile.c_str(), /* name to store the file as if succesful */
302 NULL,
303 NULL,
304 this,
305 "",
306 false,
307 ftp_cct_Map
308 };
309
310 CURL *curl = SystemFlags::initHTTP();
311 if(curl) {
312 ftpfile.stream = NULL;
313
314 char szBuf[8096]="";
315 if(mapFileName.second != "") {
316 snprintf(szBuf,8096,"%s",mapFileName.second.c_str());
317 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
318 }
319 else {
320 snprintf(szBuf,8096,"ftp://%s:%s@%s:%d/%s%s",ftpUser.c_str(),ftpUserPassword.c_str(),serverUrl.c_str(),portNumber,mapFileName.first.c_str(),destFileExt.c_str());
321 }
322
323 curl_easy_setopt(curl, CURLOPT_URL,szBuf);
324 curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
325
326 /* Define our callback to get called when there's data to be written */
327 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
328 /* Set a pointer to our struct to pass to the callback */
329 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
330
331
332 // Max 10 minutes to transfer
333 //curl_easy_setopt(curl, CURLOPT_TIMEOUT, 600);
334 // Max 60 minutes to transfer
335 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3600L);
336 curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, 120L);
337
338 /* Switch on full protocol/debug output */
339 if(SystemFlags::VERBOSE_MODE_ENABLED) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
340
341 CURLcode res = curl_easy_perform(curl);
342 if(res != CURLE_OK) {
343 result.second = curl_easy_strerror(res);
344 // we failed
345 printf("curl FAILED with: %d [%s] szBuf [%s]\n", res,curl_easy_strerror(res),szBuf);
346 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"curl FAILED with: %d [%s] szBuf [%s]\n", res,curl_easy_strerror(res),szBuf);
347
348 if(res == CURLE_PARTIAL_FILE) {
349 result.first = ftp_crt_PARTIALFAIL;
350 }
351 else if(res == CURLE_COULDNT_CONNECT) {
352 result.first = ftp_crt_HOST_NOT_ACCEPTING;
353 }
354 }
355 else {
356 result.first = ftp_crt_SUCCESS;
357 }
358
359 SystemFlags::cleanupHTTP(&curl);
360 }
361
362 if(ftpfile.stream) {
363 fclose(ftpfile.stream);
364 ftpfile.stream = NULL;
365 }
366 if(result.first != ftp_crt_SUCCESS) {
367 removeFile(destFile);
368 }
369
370 return result;
371 }
372
getMapFromServer(pair<string,string> mapFileName)373 void FTPClientThread::getMapFromServer(pair<string,string> mapFileName) {
374 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
375 if(mapFileName.second != "") {
376 result = getMapFromServer(mapFileName, "", "");
377 }
378 else {
379 pair<string,string> findMapFileName = mapFileName;
380 findMapFileName.first += + ".mgm";
381
382 result = getMapFromServer(findMapFileName, FTP_MAPS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD);
383 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
384 findMapFileName = mapFileName;
385 findMapFileName.first += + ".gbm";
386 result = getMapFromServer(findMapFileName, FTP_MAPS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD);
387 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
388 findMapFileName = mapFileName;
389 findMapFileName.first += + ".mgm";
390 result = getMapFromServer(findMapFileName, FTP_MAPS_USERNAME, FTP_COMMON_PASSWORD);
391 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
392 findMapFileName = mapFileName;
393 findMapFileName.first += + ".gbm";
394 result = getMapFromServer(findMapFileName, FTP_MAPS_USERNAME, FTP_COMMON_PASSWORD);
395 }
396 }
397 }
398 }
399
400 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
401 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
402 this->getProgressMutex()->setOwnerId(mutexOwnerId);
403 if(this->pCBObject != NULL) {
404 this->pCBObject->FTPClient_CallbackEvent(
405 mapFileName.first,
406 ftp_cct_Map,
407 result,
408 NULL);
409 }
410 }
411
addMapToRequests(string mapFilename,string URL)412 void FTPClientThread::addMapToRequests(string mapFilename,string URL) {
413 std::pair<string,string> item = make_pair(mapFilename,URL);
414 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
415 MutexSafeWrapper safeMutex(&mutexMapFileList,mutexOwnerId);
416 mutexMapFileList.setOwnerId(mutexOwnerId);
417 if(std::find(mapFileList.begin(),mapFileList.end(),item) == mapFileList.end()) {
418 mapFileList.push_back(item);
419 }
420 }
421
addTilesetToRequests(string tileSetName,string URL)422 void FTPClientThread::addTilesetToRequests(string tileSetName,string URL) {
423 std::pair<string,string> item = make_pair(tileSetName,URL);
424 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
425 MutexSafeWrapper safeMutex(&mutexTilesetList,mutexOwnerId);
426 mutexTilesetList.setOwnerId(mutexOwnerId);
427 if(std::find(tilesetList.begin(),tilesetList.end(),item) == tilesetList.end()) {
428 tilesetList.push_back(item);
429 }
430 }
431
addTechtreeToRequests(string techtreeName,string URL)432 void FTPClientThread::addTechtreeToRequests(string techtreeName,string URL) {
433 std::pair<string,string> item = make_pair(techtreeName,URL);
434 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
435 MutexSafeWrapper safeMutex(&mutexTechtreeList,mutexOwnerId);
436 mutexTechtreeList.setOwnerId(mutexOwnerId);
437 if(std::find(techtreeList.begin(),techtreeList.end(),item) == techtreeList.end()) {
438 techtreeList.push_back(item);
439 }
440 }
441
addScenarioToRequests(string fileName,string URL)442 void FTPClientThread::addScenarioToRequests(string fileName,string URL) {
443 std::pair<string,string> item = make_pair(fileName,URL);
444 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
445 MutexSafeWrapper safeMutex(&mutexScenarioList,mutexOwnerId);
446 mutexScenarioList.setOwnerId(mutexOwnerId);
447 if(std::find(scenarioList.begin(),scenarioList.end(),item) == scenarioList.end()) {
448 scenarioList.push_back(item);
449 }
450 }
451
addFileToRequests(string fileName,string URL)452 void FTPClientThread::addFileToRequests(string fileName,string URL) {
453 std::pair<string,string> item = make_pair(fileName,URL);
454 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
455 MutexSafeWrapper safeMutex(&mutexFileList,mutexOwnerId);
456 mutexFileList.setOwnerId(mutexOwnerId);
457 if(std::find(fileList.begin(),fileList.end(),item) == fileList.end()) {
458 fileList.push_back(item);
459 }
460 }
461
addTempFileToRequests(string fileName,string URL)462 void FTPClientThread::addTempFileToRequests(string fileName,string URL) {
463 std::pair<string,string> item = make_pair(fileName,URL);
464 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
465 MutexSafeWrapper safeMutex(&mutexTempFileList,mutexOwnerId);
466 mutexTempFileList.setOwnerId(mutexOwnerId);
467 if(std::find(tempFileList.begin(),tempFileList.end(),item) == tempFileList.end()) {
468 tempFileList.push_back(item);
469 }
470 }
471
getTilesetFromServer(pair<string,string> tileSetName)472 void FTPClientThread::getTilesetFromServer(pair<string,string> tileSetName) {
473 bool findArchive = executeShellCommand(
474 this->fileArchiveExtractCommand,
475 this->fileArchiveExtractCommandSuccessResult);
476
477 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
478 if(findArchive == true) {
479 if(tileSetName.second != "") {
480 //result = getTilesetFromServer(tileSetName, "", "", "", findArchive);
481 result = getTilesetFromServer(tileSetName, "", "", "", true);
482 }
483 else {
484 //result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD, findArchive);
485 result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD, true);
486 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
487 //if(findArchive == true) {
488 //result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD, false);
489 result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_CUSTOM_USERNAME, FTP_COMMON_PASSWORD, true);
490 //}
491 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
492 // result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_USERNAME, FTP_COMMON_PASSWORD, findArchive);
493 result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_USERNAME, FTP_COMMON_PASSWORD, true);
494
495 // if(findArchive == true) {
496 // result = getTilesetFromServer(tileSetName, "", FTP_TILESETS_USERNAME, FTP_COMMON_PASSWORD, false);
497 // }
498 }
499 }
500 }
501 }
502
503 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
504 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
505 this->getProgressMutex()->setOwnerId(mutexOwnerId);
506 if(this->pCBObject != NULL) {
507 this->pCBObject->FTPClient_CallbackEvent(
508 tileSetName.first,
509 ftp_cct_Tileset,
510 result,
511 NULL);
512 }
513 }
514
getTilesetFromServer(pair<string,string> tileSetName,string tileSetNameSubfolder,string ftpUser,string ftpUserPassword,bool findArchive)515 pair<FTP_Client_ResultType,string> FTPClientThread::getTilesetFromServer(
516 pair<string,string> tileSetName,
517 string tileSetNameSubfolder,
518 string ftpUser,
519 string ftpUserPassword,
520 bool findArchive) {
521
522 string destFileSaveAsNewFile = "";
523 string destFileSaveAs = "";
524 string remotePath = "";
525 bool getFolderContents = false;
526 vector<string> wantDirListOnly;
527
528 if(tileSetNameSubfolder == "") {
529 if(findArchive == true) {
530 destFileSaveAs = this->tilesetsPath.second;
531 endPathWithSlash(destFileSaveAs);
532 destFileSaveAs += tileSetName.first + this->fileArchiveExtension;
533
534 if(tileSetName.second != "") {
535 remotePath = tileSetName.second;
536 }
537 else {
538 remotePath = tileSetName.first + this->fileArchiveExtension;
539 }
540 }
541 else {
542 getFolderContents = true;
543 remotePath = tileSetName.first + "/";
544 destFileSaveAs = this->tilesetsPath.second;
545 endPathWithSlash(destFileSaveAs);
546 destFileSaveAs += tileSetName.first;
547 destFileSaveAsNewFile = destFileSaveAs;
548 endPathWithSlash(destFileSaveAsNewFile);
549 destFileSaveAs += ".tmp";
550 }
551 }
552 else {
553 getFolderContents = true;
554 remotePath = tileSetName.first + "/" + tileSetNameSubfolder + "/";
555 destFileSaveAs = this->tilesetsPath.second;
556 endPathWithSlash(destFileSaveAs);
557 destFileSaveAs += tileSetName.first;
558 endPathWithSlash(destFileSaveAs);
559
560 destFileSaveAs += tileSetNameSubfolder;
561 destFileSaveAsNewFile = destFileSaveAs;
562 endPathWithSlash(destFileSaveAsNewFile);
563 destFileSaveAs += ".tmp";
564 }
565
566 vector <string> *pWantDirListOnly = NULL;
567 if(getFolderContents == true) {
568 pWantDirListOnly = &wantDirListOnly;
569 }
570
571 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("FTPClientThread::getTilesetFromServer [%s] remotePath [%s] destFileSaveAs [%s] getFolderContents = %d findArchive = %d\n",tileSetName.first.c_str(),remotePath.c_str(),destFileSaveAs.c_str(),getFolderContents,findArchive);
572
573 pair<FTP_Client_ResultType,string> result = getFileFromServer(
574 ftp_cct_Tileset,
575 tileSetName,
576 remotePath,
577 destFileSaveAs,
578 ftpUser,
579 ftpUserPassword,
580 pWantDirListOnly);
581
582 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("FTPClientThread::getTilesetFromServer [%s] remotePath [%s] destFileSaveAs [%s] getFolderContents = %d result.first = %d [%s] findArchive = %d\n",tileSetName.first.c_str(),remotePath.c_str(),destFileSaveAs.c_str(),getFolderContents,result.first,result.second.c_str(),findArchive);
583
584 // Extract the archive
585 if(result.first == ftp_crt_SUCCESS) {
586 if(findArchive == true) {
587 string destRootArchiveFolder = this->tilesetsPath.second;
588 endPathWithSlash(destRootArchiveFolder);
589
590 string extractCmd = getFullFileArchiveExtractCommand(
591 this->fileArchiveExtractCommand,
592 this->fileArchiveExtractCommandParameters,
593 destRootArchiveFolder,
594 destRootArchiveFolder + tileSetName.first + this->fileArchiveExtension);
595
596 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
597 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
598 this->getProgressMutex()->setOwnerId(mutexOwnerId);
599
600 if(this->pCBObject != NULL) {
601 this->shellCommandCallbackUserData = tileSetName.first;
602 this->pCBObject->FTPClient_CallbackEvent(
603 tileSetName.first,
604 ftp_cct_ExtractProgress,
605 make_pair(ftp_crt_SUCCESS,"extracting"),NULL);
606 }
607 safeMutex.ReleaseLock();
608
609 if(executeShellCommand(extractCmd,this->fileArchiveExtractCommandSuccessResult,this) == false) {
610 result.first = ftp_crt_FAIL;
611 result.second = "failed to extract archive!";
612 }
613
614 return result;
615 }
616 else {
617 if(getFolderContents == true) {
618 removeFile(destFileSaveAs);
619
620 for(unsigned int i = 0; i < wantDirListOnly.size(); ++i) {
621 string fileFromList = wantDirListOnly[i];
622
623 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("fileFromList [%s] i [%u]\n",fileFromList.c_str(),i);
624
625 if( fileFromList != "models" && fileFromList != "textures" &&
626 fileFromList != "sounds") {
627 result = getFileFromServer(ftp_cct_Tileset,
628 tileSetName,
629 remotePath + fileFromList,
630 destFileSaveAsNewFile + fileFromList,
631 ftpUser, ftpUserPassword);
632 if(result.first != ftp_crt_SUCCESS) {
633 break;
634 }
635 }
636 else {
637 result = getTilesetFromServer(tileSetName,
638 fileFromList, ftpUser, ftpUserPassword,
639 findArchive);
640 if(result.first != ftp_crt_SUCCESS) {
641 break;
642 }
643 }
644 }
645 }
646 }
647 }
648
649 if(result.first != ftp_crt_SUCCESS && findArchive == false) {
650 string destRootFolder = this->tilesetsPath.second;
651 endPathWithSlash(destRootFolder);
652 destRootFolder += tileSetName.first;
653 endPathWithSlash(destRootFolder);
654
655 removeFolder(destRootFolder);
656 }
657
658 return result;
659 }
660
getTechtreeFromServer(pair<string,string> techtreeName)661 void FTPClientThread::getTechtreeFromServer(pair<string,string> techtreeName) {
662 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
663 bool findArchive = executeShellCommand(
664 this->fileArchiveExtractCommand,
665 this->fileArchiveExtractCommandSuccessResult);
666 if(findArchive == true) {
667 if(techtreeName.second != "") {
668 result = getTechtreeFromServer(techtreeName, "", "");
669 }
670 else {
671 result = getTechtreeFromServer(techtreeName, FTP_TECHTREES_CUSTOM_USERNAME, FTP_COMMON_PASSWORD);
672 if(result.first == ftp_crt_FAIL && this->getQuitStatus() == false) {
673 result = getTechtreeFromServer(techtreeName, FTP_TECHTREES_USERNAME, FTP_COMMON_PASSWORD);
674 }
675 }
676 }
677
678 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
679 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
680 this->getProgressMutex()->setOwnerId(mutexOwnerId);
681 if(this->pCBObject != NULL) {
682 this->pCBObject->FTPClient_CallbackEvent(
683 techtreeName.first,
684 ftp_cct_Techtree,
685 result,
686 NULL);
687 }
688 }
689
getTechtreeFromServer(pair<string,string> techtreeName,string ftpUser,string ftpUserPassword)690 pair<FTP_Client_ResultType,string> FTPClientThread::getTechtreeFromServer(pair<string,string> techtreeName,
691 string ftpUser, string ftpUserPassword) {
692
693 // Root folder for the techtree
694 string destRootFolder = this->techtreesPath.second;
695 endPathWithSlash(destRootFolder);
696 string destRootArchiveFolder = destRootFolder;
697 destRootFolder += techtreeName.first;
698 endPathWithSlash(destRootFolder);
699
700 string destFile = this->techtreesPath.second;
701 endPathWithSlash(destFile);
702 destFile += techtreeName.first;
703 string destFileSaveAs = destFile + this->fileArchiveExtension;
704 endPathWithSlash(destFile);
705
706 string remotePath = techtreeName.first + this->fileArchiveExtension;
707 if(techtreeName.second != "") {
708 remotePath = techtreeName.second;
709 }
710
711 pair<FTP_Client_ResultType,string> result = getFileFromServer(ftp_cct_Techtree,
712 techtreeName, remotePath, destFileSaveAs, ftpUser, ftpUserPassword);
713
714 // Extract the archive
715 if(result.first == ftp_crt_SUCCESS) {
716 string extractCmd = getFullFileArchiveExtractCommand(
717 this->fileArchiveExtractCommand,
718 this->fileArchiveExtractCommandParameters,
719 destRootArchiveFolder,
720 destRootArchiveFolder + techtreeName.first + this->fileArchiveExtension);
721
722 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
723 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
724 this->getProgressMutex()->setOwnerId(mutexOwnerId);
725 if(this->pCBObject != NULL) {
726 this->shellCommandCallbackUserData = techtreeName.first;
727 this->pCBObject->FTPClient_CallbackEvent(
728 techtreeName.first,
729 ftp_cct_ExtractProgress,
730 make_pair(ftp_crt_SUCCESS,"extracting"),NULL);
731 }
732 safeMutex.ReleaseLock();
733
734 if(executeShellCommand(extractCmd,this->fileArchiveExtractCommandSuccessResult,this) == false) {
735 result.first = ftp_crt_FAIL;
736 result.second = "failed to extract archive!";
737 }
738 }
739
740 return result;
741
742 }
743
getScenarioFromServer(pair<string,string> fileName)744 void FTPClientThread::getScenarioFromServer(pair<string,string> fileName) {
745 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
746 bool findArchive = executeShellCommand(
747 this->fileArchiveExtractCommand,
748 this->fileArchiveExtractCommandSuccessResult);
749 if(findArchive == true) {
750 result = getScenarioInternalFromServer(fileName);
751 }
752
753 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
754 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
755 this->getProgressMutex()->setOwnerId(mutexOwnerId);
756 if(this->pCBObject != NULL) {
757 this->pCBObject->FTPClient_CallbackEvent(
758 fileName.first,
759 ftp_cct_Scenario,
760 result,
761 NULL);
762 }
763 }
764
getScenarioInternalFromServer(pair<string,string> fileName)765 pair<FTP_Client_ResultType,string> FTPClientThread::getScenarioInternalFromServer(pair<string,string> fileName) {
766 // Root folder for the techtree
767 string destRootFolder = this->scenariosPath.second;
768 endPathWithSlash(destRootFolder);
769 string destRootArchiveFolder = destRootFolder;
770 destRootFolder += fileName.first;
771 endPathWithSlash(destRootFolder);
772
773 string destFile = this->scenariosPath.second;
774 endPathWithSlash(destFile);
775 destFile += fileName.first;
776 string destFileSaveAs = destFile + this->fileArchiveExtension;
777 endPathWithSlash(destFile);
778
779 string remotePath = fileName.first + this->fileArchiveExtension;
780 if(fileName.second != "") {
781 remotePath = fileName.second;
782 }
783
784 pair<FTP_Client_ResultType,string> result = getFileFromServer(ftp_cct_Scenario,
785 fileName, remotePath, destFileSaveAs, "", "");
786
787 // Extract the archive
788 if(result.first == ftp_crt_SUCCESS) {
789 string extractCmd = getFullFileArchiveExtractCommand(
790 this->fileArchiveExtractCommand,
791 this->fileArchiveExtractCommandParameters,
792 destRootArchiveFolder,
793 destRootArchiveFolder + fileName.first + this->fileArchiveExtension);
794
795 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
796 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
797 this->getProgressMutex()->setOwnerId(mutexOwnerId);
798 if(this->pCBObject != NULL) {
799 this->shellCommandCallbackUserData = fileName.first;
800 this->pCBObject->FTPClient_CallbackEvent(
801 fileName.first,
802 ftp_cct_ExtractProgress,
803 make_pair(ftp_crt_SUCCESS,"extracting"),NULL);
804 }
805 safeMutex.ReleaseLock();
806
807 if(executeShellCommand(extractCmd,this->fileArchiveExtractCommandSuccessResult,this) == false) {
808 result.first = ftp_crt_FAIL;
809 result.second = "failed to extract archive!";
810 }
811 }
812
813 return result;
814
815 }
816
getFileFromServer(pair<string,string> fileName)817 void FTPClientThread::getFileFromServer(pair<string,string> fileName) {
818 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
819
820 bool findArchive = true;
821 string ext = extractExtension(fileName.first);
822 if(("." + ext) == this->fileArchiveExtension) {
823 findArchive = executeShellCommand(
824 this->fileArchiveExtractCommand,
825 this->fileArchiveExtractCommandSuccessResult);
826 }
827 if(findArchive == true) {
828 result = getFileInternalFromServer(fileName);
829 }
830
831 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
832 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
833 this->getProgressMutex()->setOwnerId(mutexOwnerId);
834 if(this->pCBObject != NULL) {
835 this->pCBObject->FTPClient_CallbackEvent(fileName.first,ftp_cct_File,result,NULL);
836 }
837 }
838
getFileInternalFromServer(pair<string,string> fileName)839 pair<FTP_Client_ResultType,string> FTPClientThread::getFileInternalFromServer(pair<string,string> fileName) {
840 string destFile = fileName.first;
841 string destFileSaveAs = fileName.first;
842
843 string remotePath = fileName.second;
844
845 pair<FTP_Client_ResultType,string> result = getFileFromServer(ftp_cct_File,
846 fileName,remotePath, destFileSaveAs, "", "");
847
848 //printf("Got file [%s] result.first = %d\n",destFileSaveAs.c_str(),result.first);
849
850 // Extract the archive
851 if(result.first == ftp_crt_SUCCESS) {
852 string ext = extractExtension(destFileSaveAs);
853 if(("." + ext) == fileArchiveExtension) {
854 string destRootArchiveFolder = extractDirectoryPathFromFile(destFileSaveAs);
855 string extractCmd = getFullFileArchiveExtractCommand(
856 this->fileArchiveExtractCommand,
857 this->fileArchiveExtractCommandParameters,
858 destRootArchiveFolder,
859 destFileSaveAs);
860
861 if(executeShellCommand(extractCmd,this->fileArchiveExtractCommandSuccessResult) == false) {
862 result.first = ftp_crt_FAIL;
863 result.second = "failed to extract archive!";
864 }
865 }
866 }
867
868 return result;
869 }
870
getTempFileFromServer(pair<string,string> fileName)871 void FTPClientThread::getTempFileFromServer(pair<string,string> fileName) {
872 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
873
874 bool findArchive = true;
875 string ext = extractExtension(fileName.first);
876 if(("." + ext) == this->fileArchiveExtension) {
877 findArchive = executeShellCommand(
878 this->fileArchiveExtractCommand,
879 this->fileArchiveExtractCommandSuccessResult);
880 }
881 if(findArchive == true) {
882 result = getTempFileInternalFromServer(fileName);
883 }
884
885 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
886 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
887 this->getProgressMutex()->setOwnerId(mutexOwnerId);
888 if(this->pCBObject != NULL) {
889 this->pCBObject->FTPClient_CallbackEvent(fileName.first,ftp_cct_TempFile,result,NULL);
890 }
891 }
892
getTempFileInternalFromServer(pair<string,string> fileName)893 pair<FTP_Client_ResultType,string> FTPClientThread::getTempFileInternalFromServer(pair<string,string> fileName) {
894 string destFile = fileName.first;
895 //string destFileSaveAs = fileName.first;
896 string destFileSaveAs = tempFilesPath;
897
898 endPathWithSlash(destFileSaveAs);
899 destFileSaveAs += fileName.first;
900
901 string remotePath = fileName.second;
902
903 //printf("First [%s] Second [%s]\n",fileName.first.c_str(),fileName.second.c_str());
904 pair<FTP_Client_ResultType,string> result;
905 if(StartsWith(remotePath,"http://")) {
906 result = getFileFromServer(ftp_cct_TempFile, fileName,remotePath, destFileSaveAs, "", "");
907 }
908 else {
909 fileName.second = "";
910 result = getFileFromServer(ftp_cct_TempFile,fileName,remotePath, destFileSaveAs, FTP_TEMPFILES_USERNAME, FTP_COMMON_PASSWORD);
911 }
912
913 //printf("Got temp file [%s] result.first = %d\n",destFileSaveAs.c_str(),result.first);
914
915 // Extract the archive
916 if(result.first == ftp_crt_SUCCESS) {
917 string ext = extractExtension(destFileSaveAs);
918 if(("." + ext) == fileArchiveExtension) {
919 string destRootArchiveFolder = extractDirectoryPathFromFile(destFileSaveAs);
920 string extractCmd = getFullFileArchiveExtractCommand(
921 this->fileArchiveExtractCommand,
922 this->fileArchiveExtractCommandParameters,
923 destRootArchiveFolder,
924 destFileSaveAs);
925
926 if(executeShellCommand(extractCmd,this->fileArchiveExtractCommandSuccessResult) == false) {
927 result.first = ftp_crt_FAIL;
928 result.second = "failed to extract archive!";
929 }
930 }
931 }
932
933 return result;
934 }
935
getFileFromServer(FTP_Client_CallbackType downloadType,pair<string,string> fileNameTitle,string remotePath,string destFileSaveAs,string ftpUser,string ftpUserPassword,vector<string> * wantDirListOnly)936 pair<FTP_Client_ResultType,string> FTPClientThread::getFileFromServer(FTP_Client_CallbackType downloadType,
937 pair<string,string> fileNameTitle,
938 string remotePath, string destFileSaveAs,
939 string ftpUser, string ftpUserPassword, vector <string> *wantDirListOnly) {
940 pair<FTP_Client_ResultType,string> result = make_pair(ftp_crt_FAIL,"");
941 if(wantDirListOnly) {
942 (*wantDirListOnly).clear();
943 }
944 string destRootFolder = extractDirectoryPathFromFile(destFileSaveAs);
945 bool pathCreated = false;
946 if(isdir(destRootFolder.c_str()) == false) {
947 createDirectoryPaths(destRootFolder);
948 pathCreated = true;
949 }
950
951 bool wantDirList = (wantDirListOnly != NULL);
952
953 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread about to try to RETR into [%s] wantDirList = %d\n",destFileSaveAs.c_str(),wantDirList);
954 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client thread about to try to RETR into [%s] wantDirList = %d\n",destFileSaveAs.c_str(),wantDirList);
955
956 struct FtpFile ftpfile = {
957 fileNameTitle.first.c_str(),
958 destFileSaveAs.c_str(), // name to store the file as if successful
959 NULL,
960 NULL,
961 this,
962 "",
963 false,
964 downloadType
965 };
966
967 CURL *curl = SystemFlags::initHTTP();
968 if(curl) {
969 ftpfile.stream = NULL;
970
971 char szBuf[8096]="";
972 if(fileNameTitle.second != "") {
973 snprintf(szBuf,8096,"%s",fileNameTitle.second.c_str());
974 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
975 }
976 else {
977 snprintf(szBuf,8096,"ftp://%s:%s@%s:%d/%s",ftpUser.c_str(),ftpUserPassword.c_str(),serverUrl.c_str(),portNumber,remotePath.c_str());
978 }
979
980 //printf("===> Getting ftp file: %s\n",szBuf);
981
982 curl_easy_setopt(curl, CURLOPT_URL,szBuf);
983 curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L);
984
985 // turn on wildcard matching
986 //curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L);
987
988 // callback is called before download of concrete file started
989 //curl_easy_setopt(curl, CURLOPT_CHUNK_BGN_FUNCTION, file_is_comming);
990 // callback is called after data from the file have been transferred
991 //curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded);
992
993 //curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &ftpfile);
994 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
995
996 // Define our callback to get called when there's data to be written
997 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
998 // Set a pointer to our struct to pass to the callback
999 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
1000
1001 if(wantDirListOnly) {
1002 curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1);
1003 }
1004 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
1005 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, file_progress);
1006 curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &ftpfile);
1007
1008 // Max 10 minutes to transfer
1009 //curl_easy_setopt(curl, CURLOPT_TIMEOUT, 600);
1010 // Max 60 minutes to transfer
1011 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3600L);
1012 curl_easy_setopt(curl, CURLOPT_FTP_RESPONSE_TIMEOUT, 120L);
1013
1014 // Switch on full protocol/debug output
1015 if(SystemFlags::VERBOSE_MODE_ENABLED) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
1016
1017 CURLcode res = curl_easy_perform(curl);
1018
1019 if(res != CURLE_OK) {
1020 result.second = curl_easy_strerror(res);
1021 // we failed
1022 printf("curl FAILED with: %d [%s] attempting to remove folder contents [%s] szBuf [%s] ftpfile.isValidXfer = %d, pathCreated = %d\n", res,curl_easy_strerror(res),destRootFolder.c_str(),szBuf,ftpfile.isValidXfer,pathCreated);
1023 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"curl FAILED with: %d [%s] attempting to remove folder contents [%s] szBuf [%s] ftpfile.isValidXfer = %d, pathCreated = %d\n", res,curl_easy_strerror(res),destRootFolder.c_str(),szBuf,ftpfile.isValidXfer,pathCreated);
1024
1025 if(res == CURLE_PARTIAL_FILE || ftpfile.isValidXfer == true) {
1026 result.first = ftp_crt_PARTIALFAIL;
1027 }
1028 else if(res == CURLE_COULDNT_CONNECT) {
1029 result.first = ftp_crt_HOST_NOT_ACCEPTING;
1030 }
1031
1032
1033 if(destRootFolder != "") {
1034 if(pathCreated == true) {
1035 removeFolder(destRootFolder);
1036 }
1037 else {
1038 removeFile(destFileSaveAs);
1039 }
1040 }
1041 }
1042 else {
1043 result.first = ftp_crt_SUCCESS;
1044
1045 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] result.first = %d wantDirListOnly = %p\n",__FILE__,__FUNCTION__,__LINE__,result.first,wantDirListOnly);
1046
1047 if(wantDirListOnly) {
1048 if(ftpfile.stream) {
1049 fclose(ftpfile.stream);
1050 ftpfile.stream = NULL;
1051 }
1052
1053 #ifdef WIN32
1054 FILE *fp = _wfopen(utf8_decode(destFileSaveAs).c_str(), L"rt");
1055 #else
1056 FILE *fp = fopen(destFileSaveAs.c_str(), "rt");
1057 #endif
1058 if(fp != NULL) {
1059 char szBuf[4096]="";
1060 while(feof(fp) == false) {
1061 if(fgets( szBuf, 4095, fp) != NULL) {
1062 string item = szBuf;
1063 replaceAll(item,"\n","");
1064 replaceAll(item,"\r","");
1065 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Got [%s]\n",item.c_str());
1066 (*wantDirListOnly).push_back(item);
1067 }
1068 }
1069 fclose(fp);
1070 }
1071 }
1072 }
1073
1074 SystemFlags::cleanupHTTP(&curl);
1075 }
1076
1077 if(ftpfile.stream) {
1078 fclose(ftpfile.stream);
1079 ftpfile.stream = NULL;
1080 }
1081
1082 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] result.first = %d\n",__FILE__,__FUNCTION__,__LINE__,result.first);
1083
1084 return result;
1085 }
1086
getCallBackObject()1087 FTPClientCallbackInterface * FTPClientThread::getCallBackObject() {
1088 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1089 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
1090 this->getProgressMutex()->setOwnerId(mutexOwnerId);
1091 return pCBObject;
1092 }
1093
setCallBackObject(FTPClientCallbackInterface * value)1094 void FTPClientThread::setCallBackObject(FTPClientCallbackInterface *value) {
1095 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1096 MutexSafeWrapper safeMutex(this->getProgressMutex(),mutexOwnerId);
1097 this->getProgressMutex()->setOwnerId(mutexOwnerId);
1098 pCBObject = value;
1099 }
1100
ShellCommandOutput_CallbackEvent(string cmd,char * output,void * userdata)1101 void FTPClientThread::ShellCommandOutput_CallbackEvent(string cmd,char *output,void *userdata) {
1102 if(this->pCBObject != NULL) {
1103
1104 string &itemName = *static_cast<string *>(userdata);
1105 this->pCBObject->FTPClient_CallbackEvent(
1106 itemName,
1107 ftp_cct_ExtractProgress,
1108 make_pair(ftp_crt_SUCCESS,"extracting"),
1109 output);
1110 }
1111 }
1112
getShellCommandOutput_UserData(string cmd)1113 void * FTPClientThread::getShellCommandOutput_UserData(string cmd) {
1114 return &shellCommandCallbackUserData;
1115 }
1116
execute()1117 void FTPClientThread::execute() {
1118 {
1119 RunningStatusSafeWrapper runningStatus(this);
1120 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1121
1122 if(getQuitStatus() == true) {
1123 return;
1124 }
1125
1126 if(SystemFlags::VERBOSE_MODE_ENABLED) printf ("===> FTP Client thread is running\n");
1127 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"FTP Client thread is running\n");
1128
1129 try {
1130 while(this->getQuitStatus() == false) {
1131 static string mutexOwnerId = string(__FILE__) + string("_") + intToStr(__LINE__);
1132 MutexSafeWrapper safeMutex(&mutexMapFileList,mutexOwnerId);
1133 mutexMapFileList.setOwnerId(mutexOwnerId);
1134 if(mapFileList.size() > 0) {
1135 pair<string,string> mapFilename = mapFileList[0];
1136 mapFileList.erase(mapFileList.begin() + 0);
1137 safeMutex.ReleaseLock();
1138
1139 getMapFromServer(mapFilename);
1140 }
1141 else {
1142 safeMutex.ReleaseLock();
1143 }
1144
1145 if(this->getQuitStatus() == true) {
1146 break;
1147 }
1148
1149 static string mutexOwnerId2 = string(__FILE__) + string("_") + intToStr(__LINE__);
1150 MutexSafeWrapper safeMutex2(&mutexTilesetList,mutexOwnerId2);
1151 mutexTilesetList.setOwnerId(mutexOwnerId2);
1152 if(tilesetList.size() > 0) {
1153 pair<string,string> tileset = tilesetList[0];
1154 tilesetList.erase(tilesetList.begin() + 0);
1155 safeMutex2.ReleaseLock();
1156
1157 getTilesetFromServer(tileset);
1158 }
1159 else {
1160 safeMutex2.ReleaseLock();
1161 }
1162
1163 static string mutexOwnerId3 = string(__FILE__) + string("_") + intToStr(__LINE__);
1164 MutexSafeWrapper safeMutex3(&mutexTechtreeList,mutexOwnerId3);
1165 mutexTechtreeList.setOwnerId(mutexOwnerId3);
1166 if(techtreeList.size() > 0) {
1167 pair<string,string> techtree = techtreeList[0];
1168 techtreeList.erase(techtreeList.begin() + 0);
1169 safeMutex3.ReleaseLock();
1170
1171 getTechtreeFromServer(techtree);
1172 }
1173 else {
1174 safeMutex3.ReleaseLock();
1175 }
1176
1177 static string mutexOwnerId4 = string(__FILE__) + string("_") + intToStr(__LINE__);
1178 MutexSafeWrapper safeMutex4(&mutexScenarioList,mutexOwnerId4);
1179 mutexScenarioList.setOwnerId(mutexOwnerId4);
1180 if(scenarioList.size() > 0) {
1181 pair<string,string> file = scenarioList[0];
1182 scenarioList.erase(scenarioList.begin() + 0);
1183 safeMutex4.ReleaseLock();
1184
1185 getScenarioFromServer(file);
1186 }
1187 else {
1188 safeMutex4.ReleaseLock();
1189 }
1190
1191 static string mutexOwnerId5 = string(__FILE__) + string("_") + intToStr(__LINE__);
1192 MutexSafeWrapper safeMutex5(&mutexFileList,mutexOwnerId5);
1193 mutexFileList.setOwnerId(mutexOwnerId5);
1194 if(fileList.size() > 0) {
1195 pair<string,string> file = fileList[0];
1196 fileList.erase(fileList.begin() + 0);
1197 safeMutex5.ReleaseLock();
1198
1199 getFileFromServer(file);
1200 }
1201 else {
1202 safeMutex5.ReleaseLock();
1203 }
1204
1205 static string mutexOwnerId6 = string(__FILE__) + string("_") + intToStr(__LINE__);
1206 MutexSafeWrapper safeMutex6(&mutexTempFileList,mutexOwnerId6);
1207 mutexTempFileList.setOwnerId(mutexOwnerId6);
1208 if(tempFileList.size() > 0) {
1209 pair<string,string> file = tempFileList[0];
1210 tempFileList.erase(tempFileList.begin() + 0);
1211 safeMutex6.ReleaseLock();
1212
1213 getTempFileFromServer(file);
1214 }
1215 else {
1216 safeMutex6.ReleaseLock();
1217 }
1218
1219 if(this->getQuitStatus() == false) {
1220 sleep(25);
1221 }
1222 }
1223
1224 if(SystemFlags::VERBOSE_MODE_ENABLED) printf("===> FTP Client exiting!\n");
1225 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"===> FTP Client exiting!\n");
1226 }
1227 catch(const exception &ex) {
1228 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
1229 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what());
1230 }
1231 catch(...) {
1232 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] UNKNOWN Error\n",__FILE__,__FUNCTION__,__LINE__);
1233 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] unknown error\n",__FILE__,__FUNCTION__,__LINE__);
1234 }
1235
1236 if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] FTP Client thread is exiting\n",__FILE__,__FUNCTION__,__LINE__);
1237 }
1238
1239 // Delete ourself when the thread is done (no other actions can happen after this
1240 // such as the mutex which modifies the running status of this method
1241 deleteSelfIfRequired();
1242 }
1243
1244 }}//end namespace
1245