1 // ==============================================================
2 //This file is part of Glest Shared Library (www.glest.org)
3 //Copyright (C) 2005 Matthias Braun <matze@braunis.de>
4 
5 //You can redistribute this code and/or modify it under
6 //the terms of the GNU General Public License as published by the Free Software
7 //Foundation; either version 2 of the License, or (at your option) any later
8 //version.
9 
10 #ifdef WIN32
11   #include <winsock2.h>
12   #include <winsock.h>
13 #endif
14 
15 #include "platform_common.h"
16 #include "cache_manager.h"
17 
18 #ifdef WIN32
19 
20 #include <io.h>
21 #include <dbghelp.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <direct.h>
25 
26 #else
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 
32 #endif
33 
34 #if __cplusplus > 199711L
35 #include <chrono>
36 #else
37 #include <time.h>
38 #endif
39 
40 #ifdef WIN32
41  #define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR)
42 #elif defined(__GNUC__)
43 
44 #else
45 #error "Your compiler needs to support S_IFDIR!"
46 #endif
47 
48 #include <iostream>
49 #include <sstream>
50 #include <cassert>
51 
52 #include <glob.h>
53 #include <errno.h>
54 #include <string.h>
55 
56 #include <SDL.h>
57 
58 #include "util.h"
59 #include "conversion.h"
60 #include "leak_dumper.h"
61 #include "sdl_private.h"
62 #include "window.h"
63 #include "noimpl.h"
64 
65 #include "checksum.h"
66 #include "socket.h"
67 #include <algorithm>
68 #include <map>
69 #include "randomgen.h"
70 #include <algorithm>
71 #include "platform_util.h"
72 #include "utf8.h"
73 #include "byte_order.h"
74 
75 #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
76 #include <unistd.h>
77 #include <sys/types.h>
78 #include <pwd.h>
79 #endif
80 
81 #ifdef __APPLE__
82 #include <mach-o/dyld.h>
83 #include <sys/param.h>
84 #endif
85 
86 #include "leak_dumper.h"
87 
88 
89 using namespace Shared::Platform;
90 using namespace Shared::Util;
91 using namespace std;
92 
93 #define _DISABLE_MEMORY_VAULT_CHECKS 1
94 
95 namespace Shared { namespace PlatformCommon {
96 
97 const time_t REFRESH_CRC_DAY_SECONDS = 60 * 60 * 24;
98 static string crcCachePath = "";
99 
100 static string gameVersion = "";
101 static string gameGITVersion = "";
102 
103 namespace Private {
104 
105 bool shouldBeFullscreen = false;
106 int ScreenWidth = 800;
107 int ScreenHeight = 600;
108 
109 }
110 
111 /*
112 	A thread safe localtime proxy
113 */
threadsafe_localtime(const time_t & time)114 tm threadsafe_localtime(const time_t &time) {
115 	tm tm_snapshot;
116 #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
117 	localtime_s(&tm_snapshot, &time);
118 #else
119 	localtime_r(&time, &tm_snapshot); // POSIX
120 #endif
121 	return tm_snapshot;
122 }
123 
124 // extracting std::time_t from std:chrono for "now"
systemtime_now()125 time_t systemtime_now() {
126 #if __cplusplus > 199711L
127 	// typedef std::chrono::time_point<std::chrono::system_clock>  system_time_point;
128 	typedef std::chrono::time_point<std::chrono::system_clock>  system_time_point_x;
129 	system_time_point_x system_now = std::chrono::system_clock::now();
130 	return std::chrono::system_clock::to_time_t(system_now);
131 #else
132 	return time(NULL);
133 #endif
134 }
135 
136 
137 // =====================================
138 //          PerformanceTimer
139 // =====================================
140 
init(float fps,int maxTimes)141 void PerformanceTimer::init(float fps, int maxTimes) {
142 	this->times			= 0;
143 	this->maxTimes		= maxTimes;
144 	this->lastTicks		= SDL_GetTicks();
145 	this->updateTicks	= static_cast<int>(1000.0f / fps);
146 }
147 
isTime()148 bool PerformanceTimer::isTime() {
149 	Uint32 thisTicks = SDL_GetTicks();
150 
151 	if((thisTicks - lastTicks) >= updateTicks &&
152 		times < maxTimes) {
153 
154 		lastTicks += updateTicks;
155 		times++;
156 		return true;
157 	}
158 	times = 0;
159 	return false;
160 }
161 
reset()162 void PerformanceTimer::reset() {
163 	lastTicks = SDL_GetTicks();
164 }
165 
166 // =====================================
167 //         Chrono
168 // =====================================
169 
Chrono(bool autoStart)170 Chrono::Chrono(bool autoStart) {
171 	freq 			= 1000;
172 	stopped			= true;
173 	accumCount		= 0;
174 
175 	lastStartCount 	= 0;
176 	lastTickCount 	= 0;
177 	lastResult 		= 0;
178 	lastMultiplier 	= 0;
179 	lastStopped 	= false;
180 	startCount 		= 0;
181 
182 	if(autoStart == true) {
183 		start();
184 	}
185 }
186 
isStarted() const187 bool Chrono::isStarted() const {
188 	return (stopped == false);
189 }
190 
start()191 void Chrono::start() {
192 	stopped		= false;
193 	startCount 	= SDL_GetTicks();
194 }
195 
stop()196 void Chrono::stop() {
197 	Uint32 endCount	= SDL_GetTicks();
198 	accumCount 		+= endCount - startCount;
199 	stopped			= true;
200 }
201 
reset()202 void Chrono::reset() {
203 	accumCount 		= 0;
204 	lastStartCount 	= 0;
205 	lastTickCount 	= 0;
206 	lastResult 		= 0;
207 	lastMultiplier 	= 0;
208 
209 	startCount 		= SDL_GetTicks();
210 }
211 
getMicros()212 int64 Chrono::getMicros() {
213 	return queryCounter(1000000);
214 }
215 
getMillis()216 int64 Chrono::getMillis()  {
217 	return queryCounter(1000);
218 }
219 
getSeconds()220 int64 Chrono::getSeconds() {
221 	return queryCounter(1);
222 }
223 
queryCounter(int64 multiplier)224 int64 Chrono::queryCounter(int64 multiplier) {
225 
226 	if(	multiplier == lastMultiplier &&
227 		stopped == lastStopped &&
228 		lastStartCount == startCount) {
229 
230 		if(stopped == true) {
231 			return lastResult;
232 		}
233 		else {
234 			Uint32 endCount = SDL_GetTicks();
235 			if(lastTickCount == endCount) {
236 				return lastResult;
237 			}
238 		}
239 	}
240 
241 	int64 result = 0;
242 	if(stopped == true) {
243 		result = multiplier * accumCount / freq;
244 	}
245 	else {
246 		Uint32 endCount = SDL_GetTicks();
247 		result = multiplier * (accumCount + endCount - startCount) / freq;
248 		lastTickCount = endCount;
249 	}
250 
251 	lastStartCount 	= startCount;
252 	lastResult 		= result;
253 	lastMultiplier 	= multiplier;
254 	lastStopped 	= stopped;
255 
256 	return result;
257 }
258 
getCurMillis()259 int64 Chrono::getCurMillis() {
260     return SDL_GetTicks();
261 }
getCurTicks()262 int64 Chrono::getCurTicks() {
263     return SDL_GetTicks();
264 }
265 
266 
267 
268 // =====================================
269 //         Misc
270 // =====================================
271 
Tokenize(const string & str,vector<string> & tokens,const string & delimiters)272 void Tokenize(const string& str,vector<string>& tokens,const string& delimiters) {
273 
274 /*
275     // Skip delimiters at beginning.
276     string::size_type lastPos = str.find_first_not_of(delimiters, 0);
277     // Find first "non-delimiter".
278     string::size_type pos     = str.find_first_of(delimiters, lastPos);
279 
280     while (string::npos != pos || string::npos != lastPos) {
281         // Found a token, add it to the vector.
282         tokens.push_back(str.substr(lastPos, pos - lastPos));
283         // Skip delimiters.  Note the "not_of"
284         lastPos = str.find_first_not_of(delimiters, pos);
285         // Find next "non-delimiter"
286         pos = str.find_first_of(delimiters, lastPos);
287     }
288 */
289 
290 	// Assume textLine contains the line of text to parse.
291 	string textLine = str;
292 
293 	size_t pos = 0;
294 	while( true ) {
295 		size_t nextPos = textLine.find( delimiters, pos );
296 		if( nextPos == textLine.npos ) {
297 			tokens.push_back(textLine.substr(pos, textLine.length( )));
298 			break;
299 		}
300 		tokens.push_back( string( textLine.substr( pos, nextPos - pos ) ) );
301 		pos = nextPos + delimiters.size();
302 	}
303 
304 }
305 
findDirs(string path,vector<string> & results,bool errorOnNotFound,bool keepDuplicates)306 void findDirs(string path, vector<string> &results, bool errorOnNotFound,bool keepDuplicates) {
307     results.clear();
308 	string currentPath = path;
309 	endPathWithSlash(currentPath);
310 
311 	string searchpath = currentPath + "*.";
312 	vector<string> current_results;
313 	findAll(searchpath, current_results, false, errorOnNotFound);
314 	if(current_results.empty() == false) {
315 		for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
316 			const string current_folder = current_results[folder_index];
317 			const string current_folder_path = currentPath + current_folder;
318 
319 			if(isdir(current_folder_path.c_str()) == true) {
320 				if(keepDuplicates == true || std::find(results.begin(),results.end(),current_folder) == results.end()) {
321 					results.push_back(current_folder);
322 				}
323 			}
324 		}
325 	}
326 
327     std::sort(results.begin(),results.end());
328 }
329 
findDirs(const vector<string> & paths,vector<string> & results,bool errorOnNotFound,bool keepDuplicates)330 void findDirs(const vector<string> &paths, vector<string> &results, bool errorOnNotFound,bool keepDuplicates) {
331     results.clear();
332     size_t pathCount = paths.size();
333     for(unsigned int idx = 0; idx < pathCount; idx++) {
334     	string currentPath = paths[idx];
335     	endPathWithSlash(currentPath);
336         string path = currentPath + "*.";
337         vector<string> current_results;
338         findAll(path, current_results, false, errorOnNotFound);
339         if(current_results.empty() == false) {
340             for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
341                 const string current_folder = current_results[folder_index];
342                 const string current_folder_path = currentPath + current_folder;
343 
344                 if(isdir(current_folder_path.c_str()) == true) {
345                     if(keepDuplicates == true || std::find(results.begin(),results.end(),current_folder) == results.end()) {
346                         results.push_back(current_folder);
347                     }
348                 }
349             }
350         }
351     }
352 
353     std::sort(results.begin(),results.end());
354 }
355 
findAll(const vector<string> & paths,const string & fileFilter,vector<string> & results,bool cutExtension,bool errorOnNotFound,bool keepDuplicates)356 void findAll(const vector<string> &paths, const string &fileFilter, vector<string> &results, bool cutExtension, bool errorOnNotFound, bool keepDuplicates) {
357     results.clear();
358     size_t pathCount = paths.size();
359     for(unsigned int idx = 0; idx < pathCount; idx++) {
360     	string currentPath = paths[idx];
361     	endPathWithSlash(currentPath);
362 
363     	string path = currentPath + fileFilter;
364         vector<string> current_results;
365         findAll(path, current_results, cutExtension, errorOnNotFound);
366         if(current_results.empty() == false) {
367             for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
368                 string current_file = current_results[folder_index];
369                 if(keepDuplicates == true || std::find(results.begin(),results.end(),current_file) == results.end()) {
370                     results.push_back(current_file);
371                 }
372             }
373         }
374     }
375 
376     std::sort(results.begin(),results.end());
377 }
378 
379 //finds all filenames like path and stores them in results
findAll(const string & path,vector<string> & results,bool cutExtension,bool errorOnNotFound)380 void findAll(const string &path, vector<string> &results, bool cutExtension, bool errorOnNotFound) {
381 	results.clear();
382 
383 	std::string mypath = path;
384 	/** Stupid win32 is searching for all files without extension when *. is
385 	 * specified as wildcard
386 	 */
387 	if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
388 		mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
389 		mypath += "*";
390 	}
391 
392 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,mypath.c_str());
393 
394 	glob_t globbuf;
395 
396 	int res = glob(mypath.c_str(), 0, 0, &globbuf);
397 	if(res < 0 && errorOnNotFound == true) {
398 		if(errorOnNotFound) {
399 			std::stringstream msg;
400 			msg << "#1 Couldn't scan directory '" << mypath << "': " << strerror(errno);
401 			throw megaglest_runtime_error(msg.str());
402 		}
403 	}
404 	else {
405 		for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
406 			const char* p = globbuf.gl_pathv[i];
407 			const char* begin = p;
408 			for( ; *p != 0; ++p) {
409 				// strip the path component
410 				if(*p == '/')
411 					begin = p+1;
412 			}
413 			if(!(strcmp(".", begin)==0 || strcmp("..", begin)==0 || strcmp(".git", begin)==0)) {
414 				results.push_back(begin);
415 			}
416 			else {
417 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] SKIPPED SPECIAL FILENAME [%s]\n",__FILE__,__FUNCTION__,__LINE__,begin);
418 			}
419 		}
420 
421 		globfree(&globbuf);
422 
423 		if(results.empty() == true && errorOnNotFound == true) {
424 			throw megaglest_runtime_error("No files found in: " + mypath);
425 		}
426 
427 		if(cutExtension) {
428 			for (size_t i=0; i<results.size(); ++i){
429 				results.at(i)=cutLastExt(results.at(i));
430 			}
431 		}
432 	}
433 }
434 
isdir(const char * path)435 bool isdir(const char *path)
436 {
437   string friendly_path = path;
438 
439 #ifdef WIN32
440   replaceAll(friendly_path, "/", "\\");
441   if(EndsWith(friendly_path, "\\") == true) {
442 	  friendly_path.erase(friendly_path.begin() + friendly_path.length() -1);
443   }
444 #endif
445 
446 #ifdef WIN32
447   #if defined(__MINGW32__)
448   struct _stat stats;
449   #else
450   struct _stat64i32 stats;
451   #endif
452   int result = _wstat(utf8_decode(friendly_path).c_str(), &stats);
453 #else
454   struct stat stats;
455   int result = stat(friendly_path.c_str(), &stats);
456 #endif
457   bool ret = (result == 0);
458   if(ret == true) {
459 	  ret = S_ISDIR(stats.st_mode); // #define S_ISDIR(mode) ((mode) & _S_IFDIR)
460 
461 	  if(ret == false) {
462 		//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,friendly_path.c_str(),ret);
463 	  }
464   }
465   else {
466 	  //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] ret = %d, result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,friendly_path.c_str(),ret,result,errno);
467   }
468   //if(ret == false) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] NOT a path [%s]\n",__FILE__,__FUNCTION__,__LINE__,path);
469 
470   return ret;
471 }
472 
fileExists(const string & path)473 bool fileExists(const string &path) {
474 	 if (path.size() == 0) return false;
475 
476 #ifdef WIN32
477 	wstring wstr = utf8_decode(path);
478 	FILE* file= _wfopen(wstr.c_str(), L"rb");
479 #else
480 	FILE* file= fopen(path.c_str(), "rb");
481 #endif
482 	if(file != NULL) {
483 		fclose(file);
484 		return true;
485 	}
486 //	else {
487 		//int fileErrno = errno;
488 //#ifdef WIN32
489         //int fileErrno = errno;
490 		//DWORD error = GetLastError();
491 		//string strError = "[#6] Could not open file, result: " + intToStr(error) + " - " + intToStr(fileErrno) + " " + strerror(fileErrno) + " [" + path + "]";
492 //#endif
493 //	}
494 	return false;
495 }
496 
removeFolder(const string & path)497 void removeFolder(const string &path) {
498 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str());
499 
500     string deletePath = path;
501     endPathWithSlash(deletePath);
502     deletePath += "{,.}*";
503     vector<string> results = getFolderTreeContentsListRecursively(deletePath, "", true);
504     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] results.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),results.size());
505 
506     // First delete files
507     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DELETE FILES\n",__FILE__,__FUNCTION__,__LINE__);
508 
509     for(int i = (int)results.size() -1; i >= 0; --i) {
510         string item = results[i];
511 
512         //if(item.find(".git") != string::npos) {
513         //	printf("!!!!!!!!!!!!!!!!!! FOUND SPECIAL FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
514         //}
515 
516         if(isdir(item.c_str()) == false) {
517         	bool result = removeFile(item);
518         	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(),result);
519         }
520     }
521     // Now delete folders
522     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DELETE FOLDERS\n",__FILE__,__FUNCTION__,__LINE__);
523 
524     for(int i = (int)results.size() -1; i >= 0; --i) {
525         string item = results[i];
526         if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] item [%s] isdir(item.c_str()) = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(), isdir(item.c_str()));
527         if(isdir(item.c_str()) == true) {
528 
529         	//printf("~~~~~ REMOVE FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
530 
531 #ifdef WIN32
532             //int result = _rmdir(item.c_str());
533 			int result = _wrmdir(utf8_decode(item).c_str());
534 #else
535             int result = rmdir(item.c_str());
536 #endif
537             if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] item [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(),result);
538 
539             if(result != 0 && item != path) {
540             	printf("CANNOT REMOVE FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
541             	removeFolder(item);
542             }
543         }
544     }
545 
546 #ifdef WIN32
547     //int result = _rmdir(path.c_str());
548 	int result = _wrmdir(utf8_decode(path).c_str());
549 #else
550     int result = rmdir(path.c_str());
551 #endif
552 
553     if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),result);
554 }
555 
StartsWith(const std::string & str,const std::string & key)556 bool StartsWith(const std::string &str, const std::string &key) {
557   return str.find(key) == 0;
558 }
559 
EndsWith(const string & str,const string & key)560 bool EndsWith(const string &str, const string& key)
561 {
562     bool result = false;
563     if (str.length() >= key.length()) {
564     	result = (0 == str.compare(max((int)0,(int)str.length() - (int)key.length()), key.length(), key));
565     }
566 
567     return result;
568 }
569 
endPathWithSlash(string & path,bool requireOSSlash)570 void endPathWithSlash(string &path,bool requireOSSlash) {
571 	if(EndsWith(path, "/") == false && EndsWith(path, "\\") == false) {
572 		string seperator = "/";
573 		if(requireOSSlash == true) {
574 #if defined(WIN32)
575 			seperator = "\\";
576 #endif
577 		}
578 		path += seperator;
579 	}
580 }
581 
formatPath(string path)582 string formatPath(string path) {
583   replaceAll(path, "\"", "");
584   replaceAll(path, "//", "/");
585 
586   return path;
587 }
588 
trimPathWithStartingSlash(string & path)589 void trimPathWithStartingSlash(string &path) {
590 	if(StartsWith(path, "/") == true || StartsWith(path, "\\") == true) {
591 		path.erase(path.begin(),path.begin()+1);
592 		//printf("************* trimPathWithStartingSlash changed path [%s]\n",path.c_str());
593 	}
594 }
595 
updatePathClimbingParts(string & path,bool processPreviousDirTokenCheck)596 void updatePathClimbingParts(string &path,bool processPreviousDirTokenCheck) {
597 	// Update paths with /./
598 	string::size_type pos = path.find("/./");
599 	if(pos != string::npos && pos != 0) {
600 		string orig = path;
601 		path.erase(pos,2);
602 		//pos--;
603 
604 		//printf("#1 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
605 
606 		pos = path.find("/./");
607 		if(pos != string::npos && pos != 0) {
608 			updatePathClimbingParts(path, processPreviousDirTokenCheck);
609 		}
610 
611 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
612 	}
613 	pos = path.find("\\.\\");
614 	if(pos != string::npos && pos != 0) {
615 		string orig = path;
616 		path.erase(pos,2);
617 		//pos--;
618 		//printf("#w CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
619 
620 		pos = path.find("\\.\\");
621 		if(pos != string::npos && pos != 0) {
622 			updatePathClimbingParts(path, processPreviousDirTokenCheck);
623 		}
624 
625 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
626 	}
627 
628 	// Update paths with ..
629 	if(processPreviousDirTokenCheck) {
630 		pos = path.find("..");
631 		if(pos != string::npos && pos != 0) {
632 
633 			string orig = path;
634 			if(path[pos-1] != ' ' || (path.length() > 2 && path[pos+2] != ' ')) {
635 				path.erase(pos,2);
636 
637 				//printf("#3 [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,orig.c_str(),path.c_str());
638 
639 				pos--;
640 				//pos = pos -1;
641 
642 				//printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #3b [%d]\n",(int)pos);
643 
644 				if(path[pos] == '/' || path[pos] == '\\') {
645 					path.erase(pos,1);
646 
647 					//printf("#4 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
648 				}
649 
650 				for(int x = (int)pos; x >= 0; --x) {
651 					//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
652 
653 					if((path[x] == '/' || path[x] == '\\') && x != (int)pos) {
654 						//string origLoop = path;
655 						path.erase(x,(int)pos-x);
656 
657 						//printf("#5 [%d] [%d] [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,(int)x,(int)origLoop.length(),origLoop.c_str(),path.c_str());
658 						break;
659 					}
660 				}
661 				pos = path.find("..");
662 			}
663 			else {
664 				//printf("#6a [%d]\n",(int)pos);
665 
666 				//pos = path.find("..",pos+1);
667 				pos = string::npos;
668 
669 				//printf("#6b [%d]\n",(int)pos);
670 			}
671 			if(pos != string::npos && pos != 0) {
672 				updatePathClimbingParts(path,processPreviousDirTokenCheck);
673 			}
674 
675 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
676 		}
677 	}
678 
679 /*
680 	string::size_type pos = path.rfind("..");
681 	if(pos != string::npos && pos != 0) {
682 		string orig = path;
683 		path.erase(pos,2);
684 		pos--;
685 		if(path[pos] == '/' || path[pos] == '\\') {
686 			path.erase(pos,1);
687 		}
688 
689 		for(int x = pos; x >= 0; --x) {
690 			//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
691 
692 			if((path[x] == '/' || path[x] == '\\') && x != pos) {
693 				path.erase(x,pos-x);
694 				break;
695 			}
696 		}
697 
698 		printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
699 	}
700 */
701 }
702 
getCRCCacheFilePath()703 string getCRCCacheFilePath() {
704 	return crcCachePath;
705 }
706 
setCRCCacheFilePath(string path)707 void setCRCCacheFilePath(string path) {
708 	crcCachePath = path;
709 }
710 
getGameVersion()711 string getGameVersion() {
712 	return gameVersion;
713 }
getGameGITVersion()714 string getGameGITVersion() {
715 	return gameGITVersion;
716 }
setGameVersion(string version)717 void setGameVersion(string version) {
718 	gameVersion = version;
719 }
setGameGITVersion(string git)720 void setGameGITVersion(string git) {
721 	gameGITVersion = git;
722 }
723 
getCRCCacheFileName(std::pair<string,string> cacheKeys)724 string getCRCCacheFileName(std::pair<string,string> cacheKeys) {
725 	string crcCacheFile = cacheKeys.first + cacheKeys.second;
726 	return crcCacheFile;
727 }
getFormattedCRCCacheFileName(std::pair<string,string> cacheKeys)728 string getFormattedCRCCacheFileName(std::pair<string,string> cacheKeys) {
729 	string crcCacheFile = getCRCCacheFileName(cacheKeys);
730 
731 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] cacheKeys.first = [%s] cacheKeys.second [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,cacheKeys.first.c_str(),cacheKeys.second.c_str());
732 
733 	Checksum checksum;
734 	checksum.addString(crcCacheFile);
735 	string result = getCRCCacheFilePath() + "CRC_CACHE_" + uIntToStr(checksum.getSum());
736 	return result;
737 }
getFolderTreeContentsCheckSumCacheKey(vector<string> paths,string pathSearchString,const string & filterFileExt)738 std::pair<string,string> getFolderTreeContentsCheckSumCacheKey(vector<string> paths, string pathSearchString, const string &filterFileExt) {
739 	string cacheLookupId =  CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1;
740 
741 	string cacheKey = "";
742 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
743 		string path = paths[idx] + pathSearchString;
744 		cacheKey += path + "_" + filterFileExt + "_";
745 	}
746 	return make_pair(cacheLookupId,cacheKey);
747 }
748 
hasCachedFileCRCValue(string crcCacheFile,uint32 & value)749 pair<bool,time_t> hasCachedFileCRCValue(string crcCacheFile, uint32 &value) {
750 	//bool result = false;
751 
752 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
753 		SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str());
754 	}
755 
756 	pair<bool,time_t> result = make_pair(false,0);
757 	if(fileExists(crcCacheFile) == true) {
758 #ifdef WIN32
759 		FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"r");
760 #else
761 		FILE *fp = fopen(crcCacheFile.c_str(),"r");
762 #endif
763 		if(fp != NULL) {
764 			time_t refreshDate = 0;
765 			uint32 crcValue = 0;
766 			time_t lastUpdateDate = 0;
767 
768 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
769 				SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str());
770 			}
771 
772 			char gameVer[500]="";
773 			char gitVer[500]="";
774 			char actualFilePath[8096]="";
775 			int readbytes = fscanf(fp,"%20ld,%20u,%20ld\n%499s\n%499s\n%8095s",
776 					&refreshDate,
777 					&crcValue,
778 					&lastUpdateDate,
779 					&gameVer[0],
780 					&gitVer[0],
781 					&actualFilePath[0]);
782 			refreshDate = Shared::PlatformByteOrder::fromCommonEndian(refreshDate);
783 			crcValue = Shared::PlatformByteOrder::fromCommonEndian(crcValue);
784 			lastUpdateDate = Shared::PlatformByteOrder::fromCommonEndian(lastUpdateDate);
785 			string readGameVer = Shared::PlatformByteOrder::fromCommonEndian(string(gameVer));
786 			string readGitVer = Shared::PlatformByteOrder::fromCommonEndian(string(gitVer));
787 			string readActualFilePath = Shared::PlatformByteOrder::fromCommonEndian(string(actualFilePath));
788 
789 			if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CRC readGameVer [%s] [%s]\n%s\n",readGameVer.c_str(),readGitVer.c_str(),readActualFilePath.c_str());
790 
791 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
792 				SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s] readbytes = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),readbytes);
793 			}
794 
795 			fclose(fp);
796 
797 			struct tm future;       /* as in future date */
798 			future.tm_sec = 0;
799 			future.tm_min = 0;
800 			future.tm_hour = 0;
801 			future.tm_mday = 6;     /* 1st */
802 			future.tm_mon = 6;      /* July */
803 			future.tm_year = 2012 - 1900; /* 2038 in years since 1900 */
804 			future.tm_isdst = 0;          /* Daylight Saving not in affect (UTC) */
805 			#ifdef _BSD_SOURCE
806 			future.tm_zone = "UTC";
807 			#endif
808 
809 			time_t tBadCRCDate = mktime( &future );
810 
811 			result.second = lastUpdateDate;
812 			if(	readGameVer != "" && readGitVer != "" &&
813 					refreshDate > 0 &&
814 				refreshDate > tBadCRCDate &&
815 				time(NULL) < refreshDate) {
816 
817 				result.first = true;
818 				value = crcValue;
819 
820 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
821 			        //struct tm *loctime = localtime (&refreshDate);
822 					struct tm loctime = threadsafe_localtime(refreshDate);
823 			        char szBuf1[100]="";
824 			        strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
825 
826 					SystemFlags::OutputDebug(SystemFlags::debugSystem,
827 							"=-=-=-=- READ CACHE for Cache file [%s] refreshDate = %ld [%s], crcValue = %u\n",
828 							crcCacheFile.c_str(),refreshDate, szBuf1, crcValue);
829 				}
830 			}
831 			else {
832 				//time_t now = time(NULL);
833 		        //struct tm *loctime = localtime (&now);
834 				struct tm loctime = threadsafe_localtime(systemtime_now());
835 		        char szBuf1[100]="";
836 		        strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
837 
838 		        loctime = threadsafe_localtime(refreshDate);
839 		        char szBuf2[100]="";
840 		        strftime(szBuf2,100,"%Y-%m-%d %H:%M:%S",&loctime);
841 
842 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
843 					SystemFlags::OutputDebug(SystemFlags::debugSystem,
844 							"=-=-=-=- NEED TO CALCULATE CRC for Cache file [%s] now = %ld [%s], refreshDate = %ld [%s], crcValue = %u\n",
845 							crcCacheFile.c_str(), systemtime_now(), szBuf1, refreshDate, szBuf2, crcValue);
846 				}
847 			}
848 		}
849 		else {
850 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
851 				SystemFlags::OutputDebug(SystemFlags::debugSystem,"FILE NOT FOUND(1) for Cache file [%s]\n",crcCacheFile.c_str());
852 			}
853 		}
854 	}
855 	else {
856 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
857 			SystemFlags::OutputDebug(SystemFlags::debugSystem,"FILE NOT FOUND(2) for Cache file [%s]\n",crcCacheFile.c_str());
858 		}
859 	}
860 
861 	return result;
862 }
863 
writeCachedFileCRCValue(string crcCacheFile,uint32 & crcValue,string actualFileName)864 void writeCachedFileCRCValue(string crcCacheFile, uint32 &crcValue, string actualFileName) {
865 #ifdef WIN32
866 		FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"w");
867 #else
868 	FILE *fp = fopen(crcCacheFile.c_str(),"w");
869 #endif
870 	if(fp != NULL) {
871 		//RandomGen random;
872 		//int offset = random.randRange(5, 15);
873 	    srand((unsigned int)time(NULL) + (unsigned long)crcCacheFile.length());
874 	    int offset = rand() % 15;
875 	    if(offset == 0) {
876 	    	offset = 3;
877 	    }
878 	    time_t now = time(NULL);
879 		time_t refreshDate = now + (REFRESH_CRC_DAY_SECONDS * offset);
880 
881         //struct tm *loctime = localtime (&refreshDate);
882 		struct tm loctime = threadsafe_localtime(refreshDate);
883         char szBuf1[100]="";
884         strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
885 
886 		string writeGameVer = Shared::PlatformByteOrder::toCommonEndian(gameVersion);
887 		string writeGameGITVersion = Shared::PlatformByteOrder::toCommonEndian(gameGITVersion);
888 		string writeActualFileName = Shared::PlatformByteOrder::toCommonEndian(actualFileName);
889 
890 		fprintf(fp,"%20ld,%20u,%20ld",
891 				Shared::PlatformByteOrder::toCommonEndian(refreshDate),
892 				Shared::PlatformByteOrder::toCommonEndian(crcValue),
893 				Shared::PlatformByteOrder::toCommonEndian(now));
894 
895 		fprintf(fp,"\n%s\n%s\n%s",
896 				writeGameVer.c_str(),
897 				writeGameGITVersion.c_str(),
898 				writeActualFileName.c_str());
899 
900 		fclose(fp);
901 
902 		//if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"========== Writing CRC Cache offset [%d] refreshDate = %ld [%s], crcValue = %u, file [%s]\n",offset,refreshDate,szBuf1,crcValue,crcCacheFile.c_str());
903 	}
904 }
905 
clearFolderTreeContentsCheckSum(vector<string> paths,string pathSearchString,const string & filterFileExt)906 void clearFolderTreeContentsCheckSum(vector<string> paths, string pathSearchString, const string &filterFileExt) {
907 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
908 	string cacheLookupId =  cacheKeys.first;
909 	std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
910 
911 	string cacheKey = cacheKeys.second;
912 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
913 		crcTreeCache.erase(cacheKey);
914 	}
915 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
916 		string path = paths[idx];
917 		clearFolderTreeContentsCheckSum(path, filterFileExt);
918 	}
919 
920 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
921 	if(fileExists(crcCacheFile) == true) {
922 
923 		bool result = removeFile(crcCacheFile);
924 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
925 	}
926 }
927 
getFolderTreeContentsCheckSumRecursivelyLastGenerated(vector<string> paths,string pathSearchString,const string & filterFileExt)928 time_t getFolderTreeContentsCheckSumRecursivelyLastGenerated(vector<string> paths, string pathSearchString, const string &filterFileExt) {
929 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] Calculating CRC for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,pathSearchString.c_str());
930 
931 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
932 	//string cacheLookupId =  cacheKeys.first;
933 	//std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
934 
935 	string cacheKey = cacheKeys.second;
936 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
937 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),pathSearchString.c_str());
938 
939 	uint32 crcValue = 0;
940 	pair<bool,time_t> crcResult = hasCachedFileCRCValue(crcCacheFile, crcValue);
941 	if(crcResult.first == true) {
942         //struct tm *loctime = localtime (&crcResult.second);
943 		struct tm loctime = threadsafe_localtime(crcResult.second);
944         char szBuf1[100]="";
945         strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
946 
947 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE for cacheKey [%s] last updated [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str(),szBuf1);
948 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE for cacheKey [%s] last updated [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str(),szBuf1);
949 
950 		return crcResult.second;
951 	}
952 	else {
953 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,cacheKey.c_str());
954 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,cacheKey.c_str());
955 	}
956 
957 	return 0;
958 }
959 
960 //finds all filenames like path and gets their checksum of all files combined
getFolderTreeContentsCheckSumRecursively(vector<string> paths,string pathSearchString,const string & filterFileExt,Checksum * recursiveChecksum,bool forceNoCache)961 uint32 getFolderTreeContentsCheckSumRecursively(vector<string> paths, string pathSearchString, const string &filterFileExt, Checksum *recursiveChecksum, bool forceNoCache) {
962 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] Calculating CRC for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,pathSearchString.c_str());
963 
964 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
965 	string cacheLookupId =  cacheKeys.first;
966 	std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
967 
968 	string cacheKey = cacheKeys.second;
969 	if(forceNoCache == false && crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
970 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str());
971 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning folders found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str());
972 		return crcTreeCache[cacheKey];
973 	}
974 
975 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
976 	//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for CRC Cache file [%s]\n",crcCacheFile.c_str());
977 
978 	if(recursiveChecksum == NULL) {
979 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] forceNoCache = %d -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),pathSearchString.c_str(),forceNoCache);
980 	}
981 
982 	uint32 crcValue = 0;
983 	if(forceNoCache == false && hasCachedFileCRCValue(crcCacheFile, crcValue).first == true) {
984 		crcTreeCache[cacheKey] = crcValue;
985 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
986 		if(recursiveChecksum == NULL) {
987 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
988 		}
989 
990 		return crcTreeCache[cacheKey];
991 	}
992 	else {
993 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
994 		if(recursiveChecksum == NULL) {
995 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
996 		}
997 	}
998 
999 	Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
1000 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
1001 		string path = paths[idx] + pathSearchString;
1002 
1003 		getFolderTreeContentsCheckSumRecursively(path, filterFileExt, &checksum, forceNoCache);
1004 	}
1005 
1006 	if(recursiveChecksum != NULL) {
1007 		*recursiveChecksum = checksum;
1008 	}
1009 
1010 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Final CRC file count: %d\n",__FILE__,__FUNCTION__,__LINE__,checksum.getFileCount());
1011 
1012 	uint32 result = checksum.getFinalFileListSum();
1013 	//if(forceNoCache == false) {
1014 	crcTreeCache[cacheKey] = result;
1015 	writeCachedFileCRCValue(crcCacheFile, crcTreeCache[cacheKey],getCRCCacheFileName(cacheKeys));
1016 	//}
1017 	return result;
1018 }
1019 
getFolderTreeContentsCheckSumCacheKey(const string & path,const string & filterFileExt)1020 std::pair<string,string> getFolderTreeContentsCheckSumCacheKey(const string &path, const string &filterFileExt) {
1021 	string cacheLookupId =  CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2;
1022 
1023 	string cacheKey = path + "_" + filterFileExt;
1024 	return make_pair(cacheLookupId,cacheKey);
1025 }
1026 
clearFolderTreeContentsCheckSum(const string & path,const string & filterFileExt)1027 void clearFolderTreeContentsCheckSum(const string &path, const string &filterFileExt) {
1028 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(path,filterFileExt);
1029 	string cacheLookupId =  cacheKeys.first;
1030 	std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
1031 
1032 	string cacheKey = cacheKeys.second;
1033 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1034 		crcTreeCache.erase(cacheKey);
1035 	}
1036 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
1037 	if(fileExists(crcCacheFile) == true) {
1038 		bool result = removeFile(crcCacheFile);
1039 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
1040 	}
1041 }
1042 
1043 //finds all filenames like path and gets their checksum of all files combined
getFolderTreeContentsCheckSumRecursively(const string & path,const string & filterFileExt,Checksum * recursiveChecksum,bool forceNoCache)1044 uint32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum, bool forceNoCache) {
1045 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(path, filterFileExt);
1046 
1047 	string cacheLookupId =  cacheKeys.first;
1048 	std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
1049 
1050 	string cacheKey = cacheKeys.second;
1051 	if(forceNoCache == false && crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1052 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str());
1053 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning [%s] found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str());
1054 		return crcTreeCache[cacheKey];
1055 	}
1056 
1057 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
1058 	//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for CRC Cache file [%s]\n",crcCacheFile.c_str());
1059 
1060 	if(recursiveChecksum == NULL) {
1061 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] forceNoCache = %d -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),path.c_str(),forceNoCache);
1062 	}
1063 
1064 	uint32 crcValue = 0;
1065 	if(forceNoCache == false && hasCachedFileCRCValue(crcCacheFile, crcValue).first == true) {
1066 		crcTreeCache[cacheKey] = crcValue;
1067 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
1068 		if(recursiveChecksum == NULL) {
1069 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
1070 		}
1071 
1072 		return crcTreeCache[cacheKey];
1073 	}
1074 	else {
1075 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
1076 		if(recursiveChecksum == NULL) {
1077 			if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
1078 		}
1079 	}
1080 
1081 	bool topLevelCaller = (recursiveChecksum == NULL);
1082     Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
1083 
1084 	std::string mypath = path;
1085 	// Stupid win32 is searching for all files without extension when *. is
1086 	// specified as wildcard
1087 	//
1088 	if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
1089 		mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
1090 		mypath += "*";
1091 	}
1092 
1093 	glob_t globbuf;
1094 
1095 	int res = glob(mypath.c_str(), 0, 0, &globbuf);
1096 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1097 	if(res < 0) {
1098 		std::stringstream msg;
1099 		msg << "#2 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1100 		throw megaglest_runtime_error(msg.str());
1101 	}
1102 #endif
1103 
1104 	int fileLoopCount = 0;
1105 	int fileMatchCount = 0;
1106 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1107 		const char* p = globbuf.gl_pathv[i];
1108 		//printf("Line: %d p [%s]\n",__LINE__,p);
1109 
1110 		if(isdir(p) == false) {
1111             bool addFile = true;
1112             if(EndsWith(p, ".") == true || EndsWith(p, "..") == true || EndsWith(p, ".git") == true) {
1113             	addFile = false;
1114             }
1115             else if(filterFileExt != "") {
1116                 addFile = EndsWith(p, filterFileExt);
1117             }
1118 
1119             if(addFile) {
1120                 checksum.addFile(p);
1121                 fileMatchCount++;
1122             }
1123 		}
1124 		fileLoopCount++;
1125 	}
1126 
1127 	globfree(&globbuf);
1128 
1129     // Look recursively for sub-folders
1130 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1131 	res = glob(mypath.c_str(), 0, 0, &globbuf);
1132 #else
1133 	res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
1134 #endif
1135 
1136 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1137 	if(res < 0) {
1138 		std::stringstream msg;
1139 		msg << "#3 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1140 		throw megaglest_runtime_error(msg.str());
1141 	}
1142 #endif
1143 
1144 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1145 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1146 		struct stat statStruct;
1147 		// only process if dir..
1148 		lstat( globbuf.gl_pathv[i], &statStruct);
1149 		if( S_ISDIR(statStruct.st_mode) == 0)
1150 			continue;
1151 #endif
1152 		const char *p = globbuf.gl_pathv[i];
1153 		//printf("Line: %d p [%s]\n",__LINE__,p);
1154 
1155     	string currentPath = p;
1156     	endPathWithSlash(currentPath);
1157 
1158         getFolderTreeContentsCheckSumRecursively(currentPath + "*", filterFileExt, &checksum, forceNoCache);
1159 	}
1160 
1161 	globfree(&globbuf);
1162 
1163 	if(recursiveChecksum != NULL) {
1164 		*recursiveChecksum = checksum;
1165 	}
1166 
1167 	if(topLevelCaller == true) {
1168 		//printf("In [%s::%s Line: %d] Final CRC file count for [%s]: %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),checksum.getFileCount());
1169 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Final CRC file count for [%s]: %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),checksum.getFileCount());
1170 
1171 		uint32 result = checksum.getFinalFileListSum();
1172 		//if(forceNoCache == false) {
1173 		crcTreeCache[cacheKey] = result;
1174 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] ending checksum = %d for cacheKey [%s] fileMatchCount = %d, fileLoopCount = %d\n",__FILE__,__FUNCTION__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str(),fileMatchCount,fileLoopCount);
1175 		writeCachedFileCRCValue(crcCacheFile, crcTreeCache[cacheKey],getCRCCacheFileName(cacheKeys));
1176 		//}
1177 
1178 		return result;
1179 	}
1180 	else {
1181 		return 0;
1182 	}
1183 }
1184 
1185 
getFolderTreeContentsCheckSumListCacheKey(vector<string> paths,string pathSearchString,const string & filterFileExt)1186 std::pair<string,string> getFolderTreeContentsCheckSumListCacheKey(vector<string> paths, string pathSearchString, const string &filterFileExt) {
1187 	string cacheLookupId =  CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1;
1188 
1189 	string cacheKey = "";
1190 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
1191 		string path = paths[idx] + pathSearchString;
1192 		cacheKey += path + "_" + filterFileExt + "_";
1193 	}
1194 	return make_pair(cacheLookupId,cacheKey);
1195 }
1196 
clearFolderTreeContentsCheckSumList(vector<string> paths,string pathSearchString,const string & filterFileExt)1197 void clearFolderTreeContentsCheckSumList(vector<string> paths, string pathSearchString, const string &filterFileExt) {
1198 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(paths, pathSearchString, filterFileExt);
1199 	string cacheLookupId =  cacheKeys.first;
1200 	std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
1201 
1202 	string cacheKey = cacheKeys.second;
1203 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1204 		crcTreeCache.erase(cacheKey);
1205 	}
1206 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
1207 		string path = paths[idx];
1208 		clearFolderTreeContentsCheckSumList(path, filterFileExt);
1209 	}
1210 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
1211 	if(fileExists(crcCacheFile) == true) {
1212 		bool result = removeFile(crcCacheFile);
1213 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
1214 	}
1215 }
1216 
getFolderTreeContentsCheckSumListRecursively(vector<string> paths,string pathSearchString,const string & filterFileExt,vector<std::pair<string,uint32>> * recursiveMap)1217 vector<std::pair<string,uint32> > getFolderTreeContentsCheckSumListRecursively(vector<string> paths, string pathSearchString, const string &filterFileExt, vector<std::pair<string,uint32> > *recursiveMap) {
1218 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(paths, pathSearchString, filterFileExt);
1219 	string cacheLookupId =  cacheKeys.first;
1220 	std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
1221 
1222 	string cacheKey = cacheKeys.second;
1223 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1224 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED result for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str());
1225 		return crcTreeCache[cacheKey];
1226 	}
1227 	else {
1228 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders, NO CACHE found result for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str());
1229 	}
1230 
1231 	bool topLevelCaller = (recursiveMap == NULL);
1232 
1233 	vector<std::pair<string,uint32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,uint32> >() : *recursiveMap);
1234 	for(unsigned int idx = 0; idx < paths.size(); ++idx) {
1235 		string path = paths[idx] + pathSearchString;
1236 		checksumFiles = getFolderTreeContentsCheckSumListRecursively(path, filterFileExt, &checksumFiles);
1237 	}
1238 
1239 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
1240 
1241 	if(topLevelCaller == true) {
1242 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION, checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
1243 	}
1244 
1245 	crcTreeCache[cacheKey] = checksumFiles;
1246 	return crcTreeCache[cacheKey];
1247 }
1248 
1249 //finds all filenames like path and gets the checksum of each file
getFolderTreeContentsListRecursively(const string & path,const string & filterFileExt,bool includeFolders,vector<string> * recursiveMap)1250 vector<string> getFolderTreeContentsListRecursively(const string &path, const string &filterFileExt, bool includeFolders, vector<string> *recursiveMap) {
1251 	bool topLevelCaller = (recursiveMap == NULL);
1252     vector<string> resultFiles = (recursiveMap == NULL ? vector<string>() : *recursiveMap);
1253 
1254 	std::string mypath = path;
1255 	/** Stupid win32 is searching for all files without extension when *. is
1256 	 * specified as wildcard
1257 	 */
1258 	if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
1259 		mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
1260 		mypath += "*";
1261 	}
1262 
1263 	glob_t globbuf;
1264 
1265 	int globFlags = 0;
1266 	if(EndsWith(mypath,"{,.}*") == true) {
1267 #ifndef WIN32
1268 		globFlags = GLOB_BRACE;
1269 #else
1270 		// Windows glob source cannot handle GLOB_BRACE
1271 		// but that should be ok for win32 platform
1272 		replaceAll(mypath,"{,.}*","*");
1273 #endif
1274 	}
1275 
1276 	int res = glob(mypath.c_str(), globFlags, 0, &globbuf);
1277 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1278 	if(res < 0) {
1279 		std::stringstream msg;
1280 		msg << "#4 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1281 		throw megaglest_runtime_error(msg.str());
1282 	}
1283 #endif
1284 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1285 		const char* p = globbuf.gl_pathv[i];
1286 
1287 		bool skipItem = (EndsWith(p, ".") == true || EndsWith(p, "..") == true);
1288 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"~~~~~~~~~~~ Glob file [%s] skipItem = %d\n",p,skipItem);
1289 
1290 		if(skipItem == false) {
1291 			if(isdir(p) == false) {
1292 				bool addFile = true;
1293 				if(filterFileExt != "") {
1294 					addFile = EndsWith(p, filterFileExt);
1295 				}
1296 
1297 				if(addFile) {
1298 					resultFiles.push_back(p);
1299 				}
1300 			}
1301 			else if(includeFolders == true) {
1302 				resultFiles.push_back(p);
1303 			}
1304 		}
1305 	}
1306 
1307 	globfree(&globbuf);
1308 
1309     // Look recursively for sub-folders
1310 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1311 	res = glob(mypath.c_str(), 0, 0, &globbuf);
1312 #else //APPLE doesn't have the GLOB_ONLYDIR definition..
1313 	globFlags |= GLOB_ONLYDIR;
1314 	res = glob(mypath.c_str(), globFlags, 0, &globbuf);
1315 #endif
1316 
1317 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1318 	if(res < 0) {
1319 		std::stringstream msg;
1320 		msg << "#5 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1321 		throw megaglest_runtime_error(msg.str());
1322 	}
1323 #endif
1324 
1325 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1326 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1327 		struct stat statStruct;
1328 		// only get if dir..
1329 		lstat( globbuf.gl_pathv[ i], &statStruct);
1330 		if( S_ISDIR(statStruct.st_mode) == 0)
1331 			continue;
1332 #endif
1333 		const char* p = globbuf.gl_pathv[i];
1334 
1335 		bool skipItem = (EndsWith(p, ".") == true || EndsWith(p, "..") == true);
1336 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"~~~~~~~~~~~ Glob folder [%s] skipItem = %d\n",p,skipItem);
1337 
1338 		if(skipItem == false) {
1339 			if(includeFolders == true) {
1340 				resultFiles.push_back(p);
1341 			}
1342 
1343 			string currentPath = p;
1344 			endPathWithSlash(currentPath);
1345 
1346 			if(EndsWith(mypath,"{,.}*") == true) {
1347 				currentPath += "{,.}*";
1348 			}
1349 			else {
1350 				currentPath += "*";
1351 			}
1352 			resultFiles = getFolderTreeContentsListRecursively(currentPath, filterFileExt, includeFolders,&resultFiles);
1353 		}
1354 	}
1355 
1356 	globfree(&globbuf);
1357 
1358 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
1359 
1360 	if(topLevelCaller == true) {
1361 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION\n",__FILE__,__FUNCTION__,__LINE__);
1362 	}
1363 
1364     return resultFiles;
1365 }
1366 
getFolderTreeContentsCheckSumListCacheKey(const string & path,const string & filterFileExt)1367 std::pair<string,string> getFolderTreeContentsCheckSumListCacheKey(const string &path, const string &filterFileExt) {
1368 	string cacheLookupId =  CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey2;
1369 
1370 	string cacheKey = path + "_" + filterFileExt;
1371 	return make_pair(cacheLookupId,cacheKey);
1372 }
1373 
clearFolderTreeContentsCheckSumList(const string & path,const string & filterFileExt)1374 void clearFolderTreeContentsCheckSumList(const string &path, const string &filterFileExt) {
1375 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(path,filterFileExt);
1376 	string cacheLookupId =  cacheKeys.first;
1377 	std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
1378 
1379 	string cacheKey = cacheKeys.second;
1380 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1381 		crcTreeCache.erase(cacheKey);
1382 	}
1383 	string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
1384 	if(fileExists(crcCacheFile) == true) {
1385 		bool result = removeFile(crcCacheFile);
1386 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
1387 	}
1388 }
1389 
1390 //finds all filenames like path and gets the checksum of each file
getFolderTreeContentsCheckSumListRecursively(const string & path,const string & filterFileExt,vector<std::pair<string,uint32>> * recursiveMap)1391 vector<std::pair<string,uint32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,uint32> > *recursiveMap) {
1392 	std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(path, filterFileExt);
1393 	string cacheLookupId =  cacheKeys.first;
1394 	std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
1395 
1396 	string cacheKey = cacheKeys.second;
1397 	if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
1398 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] FOUND CACHED result for cacheKey [%s]\n",__FILE__,__FUNCTION__,path.c_str(),cacheKey.c_str());
1399 		return crcTreeCache[cacheKey];
1400 	}
1401 
1402 	bool topLevelCaller = (recursiveMap == NULL);
1403     vector<std::pair<string,uint32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,uint32> >() : *recursiveMap);
1404 
1405 	std::string mypath = path;
1406 	/** Stupid win32 is searching for all files without extension when *. is
1407 	 * specified as wildcard
1408 	 */
1409 	if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
1410 		mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
1411 		mypath += "*";
1412 	}
1413 
1414 	glob_t globbuf;
1415 
1416 	int res = glob(mypath.c_str(), 0, 0, &globbuf);
1417 
1418 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1419 	if(res < 0) {
1420 		std::stringstream msg;
1421 		msg << "#6 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1422 		throw megaglest_runtime_error(msg.str());
1423 	}
1424 #endif
1425 
1426 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1427 		const char* p = globbuf.gl_pathv[i];
1428 
1429 		if(isdir(p) == false) {
1430             bool addFile = true;
1431             if(EndsWith(p, ".") == true || EndsWith(p, "..") == true || EndsWith(p, ".git") == true) {
1432             	addFile = false;
1433             }
1434             else if(filterFileExt != "") {
1435                 addFile = EndsWith(p, filterFileExt);
1436             }
1437 
1438             if(addFile) {
1439                 Checksum checksum;
1440                 checksum.addFile(p);
1441 
1442                 checksumFiles.push_back(std::pair<string,uint32>(p,checksum.getSum()));
1443             }
1444 		}
1445 	}
1446 
1447 	globfree(&globbuf);
1448 
1449     // Look recursively for sub-folders
1450 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1451 	res = glob(mypath.c_str(), 0, 0, &globbuf);
1452 #else //APPLE doesn't have the GLOB_ONLYDIR definition..
1453 	res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
1454 #endif
1455 
1456 #if !defined(__APPLE__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
1457 	if(res < 0) {
1458 		std::stringstream msg;
1459 		msg << "#7 Couldn't scan directory '" << mypath << "': " << strerror(errno);
1460 		throw megaglest_runtime_error(msg.str());
1461 	}
1462 #endif
1463 
1464 	for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
1465 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__OpenBSD__)
1466 		struct stat statStruct;
1467 		// only get if dir..
1468 		lstat( globbuf.gl_pathv[ i], &statStruct);
1469 		if( S_ISDIR(statStruct.st_mode) == 0)
1470 			continue;
1471 #endif
1472 		const char *p = globbuf.gl_pathv[i];
1473 
1474     	string currentPath = p;
1475     	endPathWithSlash(currentPath);
1476 
1477         checksumFiles = getFolderTreeContentsCheckSumListRecursively(currentPath + "*", filterFileExt, &checksumFiles);
1478 	}
1479 
1480 	globfree(&globbuf);
1481 
1482 	crcTreeCache[cacheKey] = checksumFiles;
1483 
1484 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] cacheKey [%s] checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,path.c_str(),cacheKey.c_str(),checksumFiles.size());
1485 
1486 	if(topLevelCaller == true) {
1487 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION, checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
1488 	}
1489 
1490     return crcTreeCache[cacheKey];
1491 }
1492 
extractFileFromDirectoryPath(string filename)1493 string extractFileFromDirectoryPath(string filename) {
1494 	size_t lastDirectory     = filename.find_last_of("/\\");
1495 	if (lastDirectory == string::npos) {
1496 		return filename;
1497 	}
1498 
1499 	return filename.erase( 0, lastDirectory + 1);
1500 }
1501 
extractDirectoryPathFromFile(string filename)1502 string extractDirectoryPathFromFile(string filename) {
1503 	size_t lastDirectory     = filename.find_last_of("/\\");
1504 	string path = "";
1505 	if (lastDirectory != string::npos) {
1506 		path = filename.substr( 0, lastDirectory + 1);
1507 	}
1508 
1509 	return path;
1510 }
1511 
extractLastDirectoryFromPath(string Path)1512 string extractLastDirectoryFromPath(string Path) {
1513 	string result = Path;
1514 	size_t lastDirectory     = Path.find_last_of("/\\");
1515 	if (lastDirectory == string::npos) {
1516 		result = Path;
1517 	}
1518 	else {
1519 		if(Path.length() > lastDirectory + 1) {
1520 			result = Path.erase( 0, lastDirectory + 1);
1521 		}
1522 		else {
1523 			for(int i = (int)lastDirectory-1; i >= 0; --i) {
1524 				if((Path[i] == '/' || Path[i] == '\\') && i > 0) {
1525 					result = Path.erase( 0, i);
1526 					break;
1527 				}
1528 			}
1529 		}
1530 	}
1531 	return result;
1532 }
1533 
extractExtension(const string & filepath)1534 string extractExtension(const string& filepath) {
1535 	size_t lastPoint 		= filepath.find_last_of('.');
1536 	size_t lastDirectory    = filepath.find_last_of("/\\");
1537 
1538 	if (lastPoint == string::npos || (lastDirectory != string::npos && lastDirectory > lastPoint)) {
1539 		return "";
1540 	}
1541 	return filepath.substr(lastPoint+1);
1542 }
1543 
createDirectoryPaths(string Path)1544 void createDirectoryPaths(string Path) {
1545  char DirName[256]="";
1546  const char *path = Path.c_str();
1547  char *dirName = DirName;
1548  while(*path) {
1549    //if (('\\' == *path) || ('/' == *path))
1550    if ('/' == *path) {
1551 	   if(isdir(DirName) == false) {
1552 #ifdef WIN32
1553 		   int result = _wmkdir(utf8_decode(DirName).c_str());
1554 		   //int result = _mkdir(DirName);
1555 #elif defined(__GNUC__)
1556 		   int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG);
1557 #else
1558 		   #error "Your compiler needs to support mkdir!"
1559 #endif
1560         if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DirName [%s] result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,DirName,result,errno);
1561 	   }
1562    }
1563    *dirName++ = *path++;
1564    *dirName = '\0';
1565  }
1566 #ifdef WIN32
1567  //int result = _mkdir(DirName);
1568  int result = _wmkdir(utf8_decode(DirName).c_str());
1569 #elif defined(__GNUC__)
1570  int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG);
1571 #else
1572 	#error "Your compiler needs to support mkdir!"
1573 #endif
1574  if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DirName [%s] result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,DirName,result,errno);
1575 }
1576 
getFullscreenVideoInfo(int & colorBits,int & screenWidth,int & screenHeight,bool isFullscreen)1577 void getFullscreenVideoInfo(int &colorBits,int &screenWidth,int &screenHeight,bool isFullscreen) {
1578 // TTSDL What does this method do ? I have no clue...
1579 //
1580 //    // Get the current video hardware information
1581 //    //const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
1582 //    //colorBits      = vidInfo->vfmt->BitsPerPixel;
1583 //    //screenWidth    = vidInfo->current_w;
1584 //    //screenHeight   = vidInfo->current_h;
1585 //
1586 //	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1587 //
1588 //    /* Get available fullscreen/hardware modes */
1589 //
1590 //    #if defined(WIN32) || defined(__APPLE__)
1591 //
1592 //	int flags = 0;
1593 //
1594 //    #else
1595 //
1596 //    int flags = SDL_WINDOW_RESIZABLE;
1597 //
1598 //    #endif
1599 //    if(isFullscreen) flags = SDL_WINDOW_FULLSCREEN;
1600 //    SDL_Rect**modes = SDL_ListModes(NULL, SDL_OPENGL|flags);
1601 //
1602 //    /* Check if there are any modes available */
1603 //    if (modes == (SDL_Rect**)0) {
1604 //    	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] no hardware modes available.\n",__FILE__,__FUNCTION__,__LINE__);
1605 //
1606 //       const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
1607 //       colorBits      = vidInfo->vfmt->BitsPerPixel;
1608 //       screenWidth    = vidInfo->current_w;
1609 //       screenHeight   = vidInfo->current_h;
1610 //
1611 //       if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
1612 //   }
1613 //   /* Check if our resolution is restricted */
1614 //   else if (modes == (SDL_Rect**)-1) {
1615 //	   if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] all resolutions available.\n",__FILE__,__FUNCTION__,__LINE__);
1616 //
1617 //       const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
1618 //       colorBits      = vidInfo->vfmt->BitsPerPixel;
1619 //       screenWidth    = vidInfo->current_w;
1620 //       screenHeight   = vidInfo->current_h;
1621 //
1622 //       if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
1623 //   }
1624 //   else{
1625 //       /* Print valid modes */
1626 //	   if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] available Modes are:\n",__FILE__,__FUNCTION__,__LINE__);
1627 //
1628 //       int bestW = -1;
1629 //       int bestH = -1;
1630 //       for(int i=0; modes[i]; ++i) {
1631 //    	   if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%d x %d\n",modes[i]->w, modes[i]->h);
1632 //
1633 //           if(bestW < modes[i]->w) {
1634 //               bestW = modes[i]->w;
1635 //               bestH = modes[i]->h;
1636 //           }
1637 //       }
1638 //
1639 //       if(bestW > screenWidth) {
1640 //           screenWidth = bestW;
1641 //           screenHeight = bestH;
1642 //       }
1643 //
1644 //       if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
1645 //  }
1646 }
1647 
1648 
getFullscreenVideoModes(vector<ModeInfo> * modeinfos,bool isFullscreen)1649 void getFullscreenVideoModes(vector<ModeInfo> *modeinfos, bool isFullscreen) {
1650 	// Get the current video hardware information
1651 	//const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
1652 	//colorBits      = vidInfo->vfmt->BitsPerPixel;
1653 	//screenWidth    = vidInfo->current_w;
1654 	//screenHeight   = vidInfo->current_h;
1655 
1656 	if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled)
1657 		SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
1658 
1659 		//SDL_PixelFormat format;
1660 		//SDL_Rect **modes;
1661 		//int loops(0);
1662 		//int bpp(0);
1663 		std::map<std::string,bool> uniqueResList;
1664 
1665 		///////////////////////////
1666 		vector<pair<int,int> > allResoltuions;
1667 		SDL_DisplayMode mode = {SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0};
1668 		int max=SDL_GetNumDisplayModes(0);
1669 		for (int i = 0; i < max; ++i) {
1670 			if(0==SDL_GetDisplayMode(0,i,&mode)) {
1671 				int bpp;
1672 				Uint32 Rmask;
1673 				Uint32 Gmask;
1674 				Uint32 Bmask;
1675 				Uint32 Amask;
1676 				SDL_PixelFormatEnumToMasks(mode.format,&bpp,&Rmask,&Gmask,&Bmask,&Amask);
1677 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%d x %d\n",allResoltuions[i].first, allResoltuions[i].second,bpp);
1678 				string lookupKey = intToStr(mode.w) + "_" + intToStr(mode.h) + "_" + intToStr(bpp);
1679 				if(uniqueResList.find(lookupKey) == uniqueResList.end()) {
1680 					uniqueResList[lookupKey] = true;
1681 					modeinfos->push_back(ModeInfo(mode.w,mode.h,bpp));
1682 				}
1683 			}
1684 		}
1685 		//////////////////////////////////
1686 		std::sort(modeinfos->begin(),modeinfos->end());
1687 	}
1688 
1689 
1690 
changeVideoModeFullScreen(bool value)1691 void changeVideoModeFullScreen(bool value) {
1692 	Private::shouldBeFullscreen = value;
1693 }
1694 
restoreVideoMode(SDL_Window * sdlWindow,bool exitingApp)1695 void restoreVideoMode(SDL_Window *sdlWindow,bool exitingApp) {
1696     //SDL_Quit();
1697 	if(exitingApp == true && SDL_WasInit(SDL_INIT_VIDEO)) {
1698 		SDL_SetRelativeMouseMode(SDL_FALSE);
1699 		SDL_SetWindowBrightness(sdlWindow, 1.0f);
1700 	}
1701 }
1702 
1703 //int getScreenW() {
1704 //	return SDL_GetVideoSurface()->w; //SDL_GetWindowSurface()
1705 //}
1706 //
1707 //int getScreenH() {
1708 //	return SDL_GetVideoSurface()->h;
1709 //}
1710 
sleep(int millis)1711 void sleep(int millis) {
1712 	SDL_Delay(millis);
1713 }
1714 
isCursorShowing()1715 bool isCursorShowing() {
1716 	int state = SDL_ShowCursor(SDL_QUERY);
1717 	return (state == SDL_ENABLE);
1718 }
1719 
showCursor(bool b)1720 void showCursor(bool b) {
1721 	//printf("In showCursor, b: %d, isCursorShowing(): %d\n",b,isCursorShowing());
1722 
1723 
1724 	if(isCursorShowing() == b) {
1725 		return;
1726 	}
1727 	//printf("showCursor(bool b) b=%d\n",b);
1728 	SDL_ShowCursor(b == true ? SDL_ENABLE : SDL_DISABLE);
1729 }
1730 
1731 //bool isKeyDown(SDLKey key) {
1732 //	const Uint8* keystate = SDL_GetKeyboardState(0);
1733 //
1734 //	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = %d\n",__FILE__,__FUNCTION__,__LINE__,key);
1735 //
1736 //	if(key >= 0) {
1737 //		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keystate[key] = %d\n",__FILE__,__FUNCTION__,__LINE__,keystate[key]);
1738 //
1739 //		return (keystate[key] != 0);
1740 //	}
1741 //	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] returning false\n",__FILE__,__FUNCTION__,__LINE__);
1742 //	return false;
1743 //
1744 //}
1745 
isKeyDown(int virtualKey)1746 bool isKeyDown(int virtualKey) {
1747 	char key = static_cast<char> (virtualKey);
1748 	const Uint8* keystate = SDL_GetKeyboardState(0);
1749 
1750 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = %d\n",__FILE__,__FUNCTION__,__LINE__,key);
1751 
1752 	if(key >= 0) {
1753 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keystate[key] = %d\n",__FILE__,__FUNCTION__,__LINE__,keystate[(unsigned char)key]);
1754 
1755 		return (keystate[(unsigned char)key] != 0);
1756 	}
1757 	switch(key) {
1758 //SDLTT		case vkAdd:
1759 //			return (keystate[SDL_SCANCODE_PLUS] != 0 || keystate[SDL_SCANCODE_KP_PLUS] != 0);
1760 		case vkSubtract:
1761 			return (keystate[SDL_SCANCODE_MINUS] != 0 || keystate[SDL_SCANCODE_KP_MINUS] != 0);
1762 		case vkAlt:
1763 			return (keystate[SDL_SCANCODE_LALT] != 0 || keystate[SDL_SCANCODE_RALT] != 0);
1764 		case vkControl:
1765 			return (keystate[SDL_SCANCODE_LCTRL] != 0 || keystate[SDL_SCANCODE_RCTRL] != 0);
1766 		case vkShift:
1767 			return (keystate[SDL_SCANCODE_LSHIFT] != 0 || keystate[SDL_SCANCODE_RSHIFT] != 0);
1768 		case vkEscape:
1769 			return (keystate[SDL_SCANCODE_ESCAPE] != 0);
1770 		case vkUp:
1771 			return (keystate[SDL_SCANCODE_UP] != 0);
1772 		case vkLeft:
1773 			return (keystate[SDL_SCANCODE_LEFT] != 0);
1774 		case vkRight:
1775 			return (keystate[SDL_SCANCODE_RIGHT] != 0);
1776 		case vkDown:
1777 			return (keystate[SDL_SCANCODE_DOWN] != 0);
1778 		case vkReturn:
1779 			return (keystate[SDL_SCANCODE_RETURN] != 0 || keystate[SDL_SCANCODE_KP_ENTER] != 0);
1780 		case vkBack:
1781 			return  (keystate[SDL_SCANCODE_BACKSPACE] != 0);
1782 		case vkDelete:
1783 			return (keystate[SDL_SCANCODE_DELETE] != 0);
1784 		case vkPrint:
1785 			return (keystate[SDL_SCANCODE_PRINTSCREEN] != 0);
1786 		case vkPause:
1787 			return (keystate[SDL_SCANCODE_PAUSE] != 0);
1788 		default:
1789 			std::cerr << "isKeyDown called with unknown key.\n";
1790 			break;
1791 	}
1792 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] returning false\n",__FILE__,__FUNCTION__,__LINE__);
1793 	return false;
1794 }
1795 
replaceAllHTMLEntities(string & context)1796 string replaceAllHTMLEntities(string& context) {
1797 	replaceAll(context,"&quot;","\"");
1798 	replaceAll(context,"&amp;","&");
1799 	replaceAll(context,"&lt;","<");
1800 	replaceAll(context,"&gt;",">");
1801 	//replaceAll(context,"&OElig;","Œ");
1802 	replaceAll(context,"&OElig;","\xC5\x92\0");
1803 	//replaceAll(context,"&oelig;","œ");
1804 	replaceAll(context,"&oelig;","\xC5\x93\0");
1805 	//replaceAll(context,"&Scaron;","Š");
1806 	replaceAll(context,"&Scaron;","\xC5\xA0\0");
1807 	//replaceAll(context,"&scaron;","š");
1808 	replaceAll(context,"&scaron;","\xC5\xA1\0");
1809 	//replaceAll(context,"&Yuml;","Ÿ");
1810 	replaceAll(context,"&Yuml;","\xC5\xB8\0");
1811 	replaceAll(context,"&circ;","ˆ");
1812 	replaceAll(context,"&tilde;","˜");
1813 	replaceAll(context,"&ensp;"," ");
1814 	replaceAll(context,"&emsp;"," ");
1815 	replaceAll(context,"&thinsp;"," ");
1816 	replaceAll(context,"&ndash;","-");
1817 	replaceAll(context,"&mdash;","-");
1818 	//replaceAll(context,"&lsquo;","‘");
1819 	replaceAll(context,"&lsquo;","\xE2\x80\x98\0");
1820 	//replaceAll(context,"&rsquo;","’");
1821 	replaceAll(context,"&rsquo;","\xE2\x80\x99\0");
1822 	//replaceAll(context,"&sbquo;","‚");
1823 	replaceAll(context,"&sbquo;","\xE2\x80\x9A\0");
1824 	//replaceAll(context,"&ldquo;","“");
1825 	replaceAll(context,"&ldquo;","\xE2\x80\x9C\0");
1826 	//replaceAll(context,"&rdquo;","”");
1827 	replaceAll(context,"&rdquo;","\xE2\x80\x9D\0");
1828 	//replaceAll(context,"&bdquo;","„");
1829 	replaceAll(context,"&bdquo;","\xE2\x80\x9E\0");
1830 	//replaceAll(context,"&dagger;","†");
1831 	replaceAll(context,"&dagger;","\xE2\x80\xA0\0");
1832 	//replaceAll(context,"&Dagger;","‡");
1833 	replaceAll(context,"&Dagger;","\xE2\x80\xA1\0");
1834 	//replaceAll(context,"&permil;","‰");
1835 	replaceAll(context,"&permil;","\xE2\x80\xB0\0");
1836 	//replaceAll(context,"&lsaquo;","‹");
1837 	replaceAll(context,"&lsaquo;","\xE2\x80\xB9\0");
1838 	//replaceAll(context,"&rsaquo;","›");
1839 	replaceAll(context,"&rsaquo;","\xE2\x80\xBA\0");
1840 	//replaceAll(context,"&euro;","€");
1841 	replaceAll(context,"&euro;","\xE2\x82\xAC\0");
1842 
1843 	return context;
1844 }
1845 
replaceAll(string & context,const string & from,const string & to)1846 string replaceAll(string& context, const string& from, const string& to) {
1847     size_t lookHere = 0;
1848     size_t foundHere = 0;
1849     if((foundHere = context.find(from, lookHere)) != string::npos) {
1850     	//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Replacing context [%s] from [%s] to [%s]\n",context.c_str(),from.c_str(),to.c_str());
1851 
1852 		while((foundHere = context.find(from, lookHere)) != string::npos) {
1853 			  context.replace(foundHere, from.size(), to);
1854 			  lookHere = foundHere + to.size();
1855 		}
1856 
1857 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("New context [%s]\n",context.c_str());
1858     }
1859     return context;
1860 }
1861 
replaceAllBetweenTokens(vector<char> & context,const string & startToken,const string & endToken,const string & newText,bool removeTokens)1862 vector<char> replaceAllBetweenTokens(vector<char>& context,
1863 		const string &startToken, const string &endToken, const string &newText,
1864 		bool removeTokens) {
1865 	string newValue(context.begin(),context.end());
1866 	replaceAllBetweenTokens(newValue,startToken,endToken,newText,removeTokens);
1867 	context = vector<char>(newValue.begin(),newValue.end());
1868 	return context;
1869 }
1870 
replaceAllBetweenTokens(string & context,const string & startToken,const string & endToken,const string & newText,bool removeTokens)1871 string replaceAllBetweenTokens(string& context, const string &startToken,
1872 		const string &endToken, const string &newText, bool removeTokens) {
1873     size_t lookHere = 0;
1874     size_t foundHere = 0;
1875     if((foundHere = context.find(startToken, lookHere)) != string::npos) {
1876     	//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Replacing context [%s] from [%s] to [%s]\n",context.c_str(),from.c_str(),to.c_str());
1877 
1878 		while((foundHere = context.find(startToken, lookHere)) != string::npos) {
1879 			size_t foundHereEnd = context.find(endToken, foundHere+1);
1880 			if(foundHereEnd == string::npos) {
1881 				break;
1882 			}
1883 			if(removeTokens == true) {
1884 				foundHereEnd += endToken.size();
1885 
1886 				context.replace(foundHere, foundHereEnd-foundHere+1, newText);
1887 				lookHere = foundHere + newText.size();
1888 			}
1889 			else {
1890 				foundHere += startToken.size();
1891 				foundHereEnd -= 1;
1892 
1893 				context.replace(foundHere, foundHereEnd-foundHere+1, newText);
1894 				lookHere = foundHere + newText.size();
1895 			}
1896 		}
1897 
1898 		//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("New context [%s]\n",context.c_str());
1899     }
1900     return context;
1901 }
1902 
getFullFileArchiveExtractCommand(string fileArchiveExtractCommand,string fileArchiveExtractCommandParameters,string outputpath,string archivename)1903 string getFullFileArchiveExtractCommand(string fileArchiveExtractCommand,
1904 		string fileArchiveExtractCommandParameters, string outputpath, string archivename) {
1905 	string parsedOutputpath = outputpath;
1906 	string parsedArchivename = archivename;
1907 
1908 // This is required for execution on win32
1909 #if defined(WIN32)
1910 	replaceAll(parsedOutputpath, "\\\\", "\\");
1911 	replaceAll(parsedOutputpath, "/", "\\");
1912 	replaceAll(parsedArchivename, "\\\\", "\\");
1913 	replaceAll(parsedArchivename, "/", "\\");
1914 #endif
1915 
1916 	string result = fileArchiveExtractCommand;
1917 	result += " ";
1918 	string args = replaceAll(fileArchiveExtractCommandParameters, "{outputpath}", parsedOutputpath);
1919 	args = replaceAll(args, "{archivename}", parsedArchivename);
1920 	result += args;
1921 
1922 	return result;
1923 }
1924 
getFullFileArchiveCompressCommand(string fileArchiveCompressCommand,string fileArchiveCompressCommandParameters,string archivename,string archivefiles)1925 string getFullFileArchiveCompressCommand(string fileArchiveCompressCommand,
1926 		string fileArchiveCompressCommandParameters,
1927 		string archivename, string archivefiles) {
1928 	string parsedArchivename = archivename;
1929 	string parsedArchivefiles = archivefiles;
1930 
1931 // This is required for execution on win32
1932 #if defined(WIN32)
1933 	replaceAll(parsedArchivename, "\\\\", "\\");
1934 	replaceAll(parsedArchivename, "/", "\\");
1935 	replaceAll(parsedArchivefiles, "\\\\", "\\");
1936 	replaceAll(parsedArchivefiles, "/", "\\");
1937 
1938 #endif
1939 
1940 	string result = fileArchiveCompressCommand;
1941 	result += " ";
1942 	string args = replaceAll(fileArchiveCompressCommandParameters, "{archivename}", parsedArchivename);
1943 	args = replaceAll(args, "{archivefiles}", parsedArchivefiles);
1944 	result += args;
1945 
1946 	return result;
1947 }
1948 
executeShellCommand(string cmd,int expectedResult,ShellCommandOutputCallbackInterface * cb)1949 bool executeShellCommand(string cmd, int expectedResult, ShellCommandOutputCallbackInterface *cb) {
1950 	bool result = false;
1951 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"About to run [%s]", cmd.c_str());
1952 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to run [%s]", cmd.c_str());
1953 
1954 #ifdef WIN32
1955 	FILE *file = _wpopen(utf8_decode(cmd).c_str(),L"r");
1956 #else
1957 	FILE *file = popen(cmd.c_str(),"r");
1958 #endif
1959 
1960 	if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"file = [%p]", file);
1961 	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("file = [%p]", file);
1962 
1963 	if(file != NULL) {
1964 		char szBuf[4096]="";
1965 		while(feof(file) == false) {
1966 			if(fgets( szBuf, 4095, file) != NULL) {
1967 				if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s",szBuf);
1968 				if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s",szBuf);
1969 
1970 				if(cb != NULL) {
1971 					cb->ShellCommandOutput_CallbackEvent(cmd,szBuf,cb->getShellCommandOutput_UserData(cmd));
1972 				}
1973 			}
1974 		}
1975 #ifdef WIN32
1976 		int cmdRet = _pclose(file);
1977 #else
1978 		int cmdRet = pclose(file);
1979 #endif
1980 
1981 		/* Close pipe and print return value. */
1982 		if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Process returned %d\n",  cmdRet);
1983 		if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Process returned %d\n",  cmdRet);
1984 		result = (expectedResult == IGNORE_CMD_RESULT_VALUE || expectedResult == cmdRet);
1985 	}
1986 	return result;
1987 }
1988 
removeFile(string file)1989 bool removeFile(string file) {
1990 #ifdef WIN32
1991 	int result = _unlink(file.c_str());
1992 #else
1993     int result = unlink(file.c_str());
1994 #endif
1995 
1996     return (result == 0);
1997 }
1998 
renameFile(string oldFile,string newFile)1999 bool renameFile(string oldFile, string newFile) {
2000 	int result = rename(oldFile.c_str(),newFile.c_str());
2001     return (result == 0);
2002 }
2003 
getFileSize(string filename)2004 off_t getFileSize(string filename) {
2005 #ifdef WIN32
2006   #if defined(__MINGW32__)
2007   struct _stat stbuf;
2008   #else
2009   struct _stat64i32 stbuf;
2010   #endif
2011   if(_wstat(utf8_decode(filename).c_str(), &stbuf) != -1) {
2012 #else
2013   struct stat stbuf;
2014   if(stat(filename.c_str(), &stbuf) != -1) {
2015 #endif
2016 	  return stbuf.st_size;
2017   }
2018   return 0;
2019 }
2020 
2021 string executable_path(string exeName, bool includeExeNameInPath) {
2022 	string value = "";
2023 #ifdef _WIN32
2024 	char path[MAX_PATH]="";
2025 	if( GetModuleFileNameA(NULL,path,MAX_PATH) == 0 ) {
2026 		if(includeExeNameInPath == true) {
2027 			value = exeName;
2028 		}
2029 		else {
2030 			value = extractDirectoryPathFromFile(exeName);
2031 		}
2032 	}
2033 	else {
2034 		if(includeExeNameInPath == true) {
2035 			value = path;
2036 		}
2037 		else {
2038 			value = extractDirectoryPathFromFile(path);
2039 		}
2040 	}
2041 #elif __APPLE__
2042 	char path[MAXPATHLEN+1]="";
2043 	uint32_t path_len = MAXPATHLEN;
2044 	if ( _NSGetExecutablePath(path, &path_len) ) {
2045 		if(includeExeNameInPath == true) {
2046 			value = exeName;
2047 		}
2048 		else {
2049 			value = extractDirectoryPathFromFile(exeName);
2050 		}
2051 	}
2052 	else {
2053 		if(includeExeNameInPath == true) {
2054 			value = path;
2055 		}
2056 		else {
2057 			value = extractDirectoryPathFromFile(path);
2058 		}
2059 	}
2060 #else
2061 	char exe_link_path[200]="";
2062 	int length = readlink("/proc/self/exe", exe_link_path, sizeof(exe_link_path));
2063 	if(length < 0 || length >= 200 ) {
2064 		char *argv0_path = realpath(exeName.c_str(),NULL);
2065 		if(argv0_path != NULL) {
2066 			if(includeExeNameInPath == true) {
2067 				value = argv0_path;
2068 			}
2069 			else {
2070 				value = extractDirectoryPathFromFile(argv0_path);
2071 			}
2072 			free(argv0_path);
2073 			argv0_path = NULL;
2074 		}
2075 		else {
2076 			const char *shell_path = getenv("_");
2077 			if(shell_path != NULL) {
2078 				if(includeExeNameInPath == true) {
2079 					value = shell_path;
2080 				}
2081 				else {
2082 					value = extractDirectoryPathFromFile(shell_path);
2083 				}
2084 			}
2085 			else {
2086 				if(includeExeNameInPath == true) {
2087 					value = exeName;
2088 				}
2089 				else {
2090 					value = extractDirectoryPathFromFile(exeName);
2091 				}
2092 			}
2093 		}
2094 	}
2095 	else {
2096 		exe_link_path[length] = '\0';
2097 		if(includeExeNameInPath == true) {
2098 			value = exe_link_path;
2099 		}
2100 		else {
2101 			value = extractDirectoryPathFromFile(exe_link_path);
2102 		}
2103 	}
2104 #endif
2105     return value;
2106 }
2107 
2108 bool searchAndReplaceTextInFile(string fileName, string findText, string replaceText, bool simulateOnly) {
2109 	bool replacedText = false;
2110 	const int MAX_LEN_SINGLE_LINE = 4096;
2111 	char buffer[MAX_LEN_SINGLE_LINE+2];
2112 	char *buff_ptr, *find_ptr;
2113 	FILE *fp1, *fp2;
2114 	size_t find_len = findText.length();
2115 
2116 	string tempfileName = fileName + "_tmp";
2117 #ifdef WIN32
2118 	fp1 = _wfopen(utf8_decode(fileName).c_str(), L"r");
2119 	fp2 = _wfopen(utf8_decode(tempfileName).c_str(), L"w");
2120 #else
2121 	fp1 = fopen(fileName.c_str(),"r");
2122 	fp2 = fopen(tempfileName.c_str(),"w");
2123 #endif
2124 
2125 	if(fp1 == NULL) {
2126 		if(fp2) fclose(fp2);
2127 
2128 		throw megaglest_runtime_error("cannot open input file [" + fileName + "]");
2129 	}
2130 	if(fp2 == NULL) {
2131 		if(fp1) fclose(fp1);
2132 
2133 		throw megaglest_runtime_error("cannot open output file [" + tempfileName + "]");
2134 	}
2135 
2136 	while(fgets(buffer,MAX_LEN_SINGLE_LINE + 2,fp1)) {
2137 		buff_ptr = buffer;
2138 		if(findText != "") {
2139 			while ((find_ptr = strstr(buff_ptr,findText.c_str()))) {
2140 				//printf("Replacing text [%s] with [%s] in file [%s]\n",findText.c_str(),replaceText.c_str(),fileName.c_str());
2141 
2142 				while(buff_ptr < find_ptr) {
2143 					fputc((int)*buff_ptr++,fp2);
2144 				}
2145 				fputs(replaceText.c_str(),fp2);
2146 
2147 				buff_ptr += find_len;
2148 				replacedText = true;
2149 			}
2150 		}
2151 		fputs(buff_ptr,fp2);
2152 	}
2153 
2154 	fclose(fp2);
2155 	fclose(fp1);
2156 
2157 	if(replacedText == true && simulateOnly == false) {
2158 		removeFile(fileName);
2159 		renameFile(tempfileName,fileName);
2160 	}
2161 	else {
2162 		removeFile(tempfileName);
2163 	}
2164 	//removeFile(tempfileName);
2165 	return replacedText;
2166 }
2167 
2168 void saveDataToFile(string filename, string data) {
2169 	//Open an input and output stream in binary mode
2170 #if defined(WIN32) && !defined(__MINGW32__)
2171 	FILE *fp2 = _wfopen(utf8_decode(filename).c_str(), L"wb");
2172 	ofstream out(fp2);
2173 #else
2174 	ofstream out(filename.c_str(),ios::binary);
2175 #endif
2176 
2177 	if(out.is_open()) {
2178 		out<< data;
2179 	}
2180 	else if(out.is_open() == false) {
2181 		throw megaglest_runtime_error("cannot open input file [" + filename + "]");
2182 	}
2183 
2184 	//Close file
2185 	out.close();
2186 
2187 #if defined(WIN32) && !defined(__MINGW32__)
2188 	if(fp2) {
2189 		fclose(fp2);
2190 	}
2191 #endif
2192 }
2193 
2194 void copyFileTo(string fromFileName, string toFileName) {
2195 	//Open an input and output stream in binary mode
2196 #if defined(WIN32) && !defined(__MINGW32__)
2197 	FILE *fp1 = _wfopen(utf8_decode(fromFileName).c_str(), L"rb");
2198 	ifstream in(fp1);
2199 	FILE *fp2 = _wfopen(utf8_decode(toFileName).c_str(), L"wb");
2200 	ofstream out(fp2);
2201 #else
2202 	ifstream in(fromFileName.c_str(),ios::binary);
2203 	ofstream out(toFileName.c_str(),ios::binary);
2204 #endif
2205 
2206 	if(in.is_open() && out.is_open()) {
2207 		while(in.eof() == false) {
2208 			out.put(in.get());
2209 		}
2210 	}
2211 	else if(in.is_open() == false) {
2212 		throw megaglest_runtime_error("cannot open input file [" + fromFileName + "]");
2213 	}
2214 	else if(out.is_open() == false) {
2215 		throw megaglest_runtime_error("cannot open input file [" + toFileName + "]");
2216 	}
2217 
2218 	//Close both files
2219 	in.close();
2220 	out.close();
2221 
2222 #if defined(WIN32) && !defined(__MINGW32__)
2223 	if(fp1) {
2224 		fclose(fp1);
2225 	}
2226 	if(fp2) {
2227 		fclose(fp2);
2228 	}
2229 #endif
2230 }
2231 
2232 bool valid_utf8_file(const char* file_name) {
2233 #if defined(WIN32) && !defined(__MINGW32__)
2234 	wstring wstr = utf8_decode(file_name);
2235 	FILE *fp = _wfopen(wstr.c_str(), L"r");
2236 	ifstream ifs(fp);
2237 #else
2238     ifstream ifs(file_name);
2239 #endif
2240 
2241     if (!ifs) {
2242         return false; // even better, throw here
2243     }
2244     istreambuf_iterator<char> it(ifs.rdbuf());
2245     istreambuf_iterator<char> eos;
2246 
2247     bool result = utf8::is_valid(it, eos);
2248 
2249 	ifs.close();
2250 #if defined(WIN32) && !defined(__MINGW32__)
2251 	if(fp) {
2252 		fclose(fp);
2253 	}
2254 #endif
2255 
2256 	return result;
2257 }
2258 
2259 string getFileTextContents(string path) {
2260 #if defined(WIN32) && !defined(__MINGW32__)
2261 	FILE *fp = _wfopen(utf8_decode(path).c_str(), L"rb");
2262 	ifstream xmlFile(fp);
2263 #else
2264 	ifstream xmlFile(path.c_str(),ios::binary);
2265 #endif
2266 	if(xmlFile.is_open() == false) {
2267 		throw megaglest_runtime_error("Can not open file: [" + path + "]");
2268 	}
2269 
2270 	xmlFile.unsetf(ios::skipws);
2271 
2272 	// Determine stream size
2273 	xmlFile.seekg(0, ios::end);
2274 	streampos size = xmlFile.tellg();
2275 	xmlFile.seekg(0);
2276 
2277 	// Load data and add terminating 0
2278 	vector<char> buffer;
2279 	buffer.resize((unsigned int)size + 1);
2280 	xmlFile.read(&buffer.front(), static_cast<streamsize>(size));
2281 	buffer[(unsigned int)size] = 0;
2282 
2283 	return &buffer.front();
2284 }
2285 
2286 // =====================================
2287 //         ModeInfo
2288 // =====================================
2289 
2290 ModeInfo::ModeInfo(int w, int h, int d) {
2291 	width=w;
2292 	height=h;
2293 	depth=d;
2294 }
2295 
2296 string ModeInfo::getString() const{
2297 	return intToStr(width)+"x"+intToStr(height)+"-"+intToStr(depth);
2298 }
2299 
2300 void ValueCheckerVault::addItemToVault(const void *ptr,int value) {
2301 #ifndef _DISABLE_MEMORY_VAULT_CHECKS
2302 
2303 	Checksum checksum;
2304 	vaultList[ptr] = checksum.addInt(value);
2305 
2306 #endif
2307 
2308 //	if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] add vault key [%p] value [%s] [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,intToStr(checksum.getSum()).c_str(),value);
2309 }
2310 
2311 void ValueCheckerVault::checkItemInVault(const void *ptr,int value) const {
2312 #ifndef _DISABLE_MEMORY_VAULT_CHECKS
2313 
2314 	map<const void *,uint32>::const_iterator iterFind = vaultList.find(ptr);
2315 	if(iterFind == vaultList.end()) {
2316 //		if(SystemFlags::VERBOSE_MODE_ENABLED) {
2317 //			printf("In [%s::%s Line: %d] check vault key [%p] value [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,value);
2318 //			for(map<const void *,string>::const_iterator iterFind = vaultList.begin();
2319 //					iterFind != vaultList.end(); iterFind++) {
2320 //				printf("In [%s::%s Line: %d] LIST-- check vault key [%p] value [%s]\n",__FILE__,__FUNCTION__,__LINE__,iterFind->first,iterFind->second.c_str());
2321 //			}
2322 //		}
2323 		throw std::runtime_error("memory value has been unexpectedly modified (not found)!");
2324 	}
2325 	Checksum checksum;
2326 	if(iterFind->second != checksum.addInt(value)) {
2327 //		if(SystemFlags::VERBOSE_MODE_ENABLED) {
2328 //			printf("In [%s::%s Line: %d] check vault key [%p] value [%s] [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,intToStr(checksum.getSum()).c_str(),value);
2329 //			for(map<const void *,string>::const_iterator iterFind = vaultList.begin();
2330 //					iterFind != vaultList.end(); iterFind++) {
2331 //				printf("In [%s::%s Line: %d] LIST-- check vault key [%p] value [%s]\n",__FILE__,__FUNCTION__,__LINE__,iterFind->first,iterFind->second.c_str());
2332 //			}
2333 //		}
2334 		throw std::runtime_error("memory value has been unexpectedly modified (changed)!");
2335 	}
2336 
2337 #endif
2338 
2339 }
2340 
2341 string getUserHome() {
2342 	string home_folder;
2343 	home_folder = safeCharPtrCopy(getenv("HOME"),8095);
2344 	if(home_folder == "") {
2345 #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
2346 		struct passwd *pw = getpwuid(getuid());
2347 		home_folder = safeCharPtrCopy(pw->pw_dir,8095);
2348 #endif
2349 	}
2350 	return home_folder;
2351 }
2352 
2353 string safeCharPtrCopy(const char *ptr,int maxLength) {
2354 	string result = "";
2355 	if(ptr == NULL) {
2356 		return result;
2357 	}
2358 	if(maxLength <= 0) {
2359 		maxLength = 8096;
2360 	}
2361 
2362 	int ptrLength = (int)strlen(ptr);
2363 	if(ptrLength >= maxLength) {
2364 		char *pBuffer = new char[maxLength+1];
2365 		memset(pBuffer,0,maxLength+1);
2366 #ifdef WIN32
2367 		memcpy(pBuffer,ptr,min((int)strlen(ptr),maxLength));
2368 #else
2369 		memcpy(pBuffer,ptr,std::min((int)strlen(ptr),maxLength));
2370 #endif
2371 
2372 		result = pBuffer;
2373 		delete [] pBuffer;
2374 	}
2375 	else {
2376 		result = ptr;
2377 	}
2378 	return result;
2379 }
2380 
2381 
2382 }}//end namespace
2383