79de9db5625303b7f2828ca7cd176d9851fcbc2a
[novacoin.git] / src / util.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "util.h"
7 #include "interface.h"
8 #include "sync.h"
9 #include "version.h"
10
11 #include <boost/program_options/detail/config_file.hpp>
12 #include <boost/program_options/parsers.hpp>
13 #include <boost/filesystem.hpp>
14 #include <boost/filesystem/fstream.hpp>
15 #include <boost/date_time/posix_time/posix_time.hpp>
16 #include <boost/thread.hpp>
17 #include <openssl/crypto.h>
18 #include <openssl/rand.h>
19
20 #ifdef WIN32
21 #include <io.h> /* for _commit */
22 #include "shlobj.h"
23 #elif defined(__linux__)
24 #include <sys/prctl.h>
25 #endif
26
27 #if !defined(WIN32) && !defined(ANDROID)
28 #include <execinfo.h>
29 #endif
30
31
32 using namespace std;
33 namespace bt = boost::posix_time;
34
35 map<string, string> mapArgs;
36 map<string, vector<string> > mapMultiArgs;
37 bool fDebug = false;
38 bool fDebugNet = false;
39 bool fPrintToConsole = false;
40 bool fPrintToDebugger = false;
41 bool fRequestShutdown = false;
42 bool fShutdown = false;
43 bool fDaemon = false;
44 bool fServer = false;
45 bool fCommandLine = false;
46 string strMiscWarning;
47 bool fTestNet = false;
48 bool fNoListen = false;
49 bool fLogTimestamps = false;
50 CMedianFilter<int64_t> vTimeOffsets(200,0);
51 bool fReopenDebugLog = false;
52
53 // Extended DecodeDumpTime implementation, see this page for details:
54 // http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
55 const std::locale formats[] = {
56     std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
57     std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
58     std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
59     std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
60     std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
61 };
62
63 const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
64
65 std::time_t pt_to_time_t(const bt::ptime& pt)
66 {
67     bt::ptime timet_start(boost::gregorian::date(1970,1,1));
68     bt::time_duration diff = pt - timet_start;
69     return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
70 }
71
72 // Init OpenSSL library multithreading support
73 static CCriticalSection** ppmutexOpenSSL;
74 void locking_callback(int mode, int i, const char* file, int line)
75 {
76     if (mode & CRYPTO_LOCK) {
77         ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
78     } else {
79         LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
80     }
81 }
82
83 LockedPageManager LockedPageManager::instance;
84
85 // Init
86 class CInit
87 {
88 public:
89     CInit()
90     {
91         // Init OpenSSL library multithreading support
92         ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
93         for (int i = 0; i < CRYPTO_num_locks(); i++)
94             ppmutexOpenSSL[i] = new CCriticalSection();
95         CRYPTO_set_locking_callback(locking_callback);
96
97 #ifdef WIN32
98         // Seed random number generator with screen scrape and other hardware sources
99         RAND_screen();
100 #endif
101
102         // Seed random number generator with performance counter
103         RandAddSeed();
104     }
105     ~CInit()
106     {
107         // Shutdown OpenSSL library multithreading support
108         CRYPTO_set_locking_callback(NULL);
109         for (int i = 0; i < CRYPTO_num_locks(); i++)
110             delete ppmutexOpenSSL[i];
111         OPENSSL_free(ppmutexOpenSSL);
112     }
113 }
114 instance_of_cinit;
115
116
117
118
119
120
121
122
123 void RandAddSeed()
124 {
125     // Seed with CPU performance counter
126     int64_t nCounter = GetPerformanceCounter();
127     RAND_add(&nCounter, sizeof(nCounter), 1.5);
128     memset(&nCounter, 0, sizeof(nCounter));
129 }
130
131 void RandAddSeedPerfmon()
132 {
133     RandAddSeed();
134
135     // This can take up to 2 seconds, so only do it every 10 minutes
136     static int64_t nLastPerfmon;
137     if (GetTime() < nLastPerfmon + 10 * 60)
138         return;
139     nLastPerfmon = GetTime();
140
141 #ifdef WIN32
142     // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
143     // Seed with the entire set of perfmon data
144     unsigned char pdata[250000];
145     memset(pdata, 0, sizeof(pdata));
146     unsigned long nSize = sizeof(pdata);
147     long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
148     RegCloseKey(HKEY_PERFORMANCE_DATA);
149     if (ret == ERROR_SUCCESS)
150     {
151         RAND_add(pdata, nSize, nSize/100.0);
152         OPENSSL_cleanse(pdata, nSize);
153         printf("RandAddSeed() %lu bytes\n", nSize);
154     }
155 #endif
156 }
157
158 uint64_t GetRand(uint64_t nMax)
159 {
160     if (nMax == 0)
161         return 0;
162
163     // The range of the random source must be a multiple of the modulus
164     // to give every possible output value an equal possibility
165     uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
166     uint64_t nRand = 0;
167     do
168         RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
169     while (nRand >= nRange);
170     return (nRand % nMax);
171 }
172
173 int GetRandInt(int nMax)
174 {
175     return static_cast<int>(GetRand(nMax));
176 }
177
178 static FILE* fileout = NULL;
179
180 inline int OutputDebugStringF(const char* pszFormat, ...)
181 {
182     int ret = 0;
183     if (fPrintToConsole)
184     {
185         // print to console
186         va_list arg_ptr;
187         va_start(arg_ptr, pszFormat);
188         ret = vprintf(pszFormat, arg_ptr);
189         va_end(arg_ptr);
190     }
191     else if (!fPrintToDebugger)
192     {
193         // print to debug.log
194
195         if (!fileout)
196         {
197             boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
198             fileout = fopen(pathDebug.string().c_str(), "a");
199             if (fileout) setbuf(fileout, NULL); // unbuffered
200         }
201         if (fileout)
202         {
203             static bool fStartedNewLine = true;
204
205             // This routine may be called by global destructors during shutdown.
206             // Since the order of destruction of static/global objects is undefined,
207             // allocate mutexDebugLog on the heap the first time this routine
208             // is called to avoid crashes during shutdown.
209             static std::mutex* mutexDebugLog = nullptr;
210             if (mutexDebugLog == nullptr) mutexDebugLog = new std::mutex();
211             std::scoped_lock scoped_lock(*mutexDebugLog);
212
213             // reopen the log file, if requested
214             if (fReopenDebugLog) {
215                 fReopenDebugLog = false;
216                 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
217                 if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
218                     setbuf(fileout, NULL); // unbuffered
219             }
220
221             // Debug print useful for profiling
222             if (fLogTimestamps && fStartedNewLine)
223                 fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
224             if (pszFormat[strlen(pszFormat) - 1] == '\n')
225                 fStartedNewLine = true;
226             else
227                 fStartedNewLine = false;
228
229             va_list arg_ptr;
230             va_start(arg_ptr, pszFormat);
231             ret = vfprintf(fileout, pszFormat, arg_ptr);
232             va_end(arg_ptr);
233         }
234     }
235
236 #ifdef WIN32
237     if (fPrintToDebugger)
238     {
239         static CCriticalSection cs_OutputDebugStringF;
240
241         // accumulate and output a line at a time
242         {
243             LOCK(cs_OutputDebugStringF);
244             static std::string buffer;
245
246             va_list arg_ptr;
247             va_start(arg_ptr, pszFormat);
248             buffer += vstrprintf(pszFormat, arg_ptr);
249             va_end(arg_ptr);
250
251             size_t line_start = 0, line_end;
252             while((line_end = buffer.find('\n', line_start)) != -1)
253             {
254                 OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str());
255                 line_start = line_end + 1;
256             }
257             buffer.erase(0, line_start);
258         }
259     }
260 #endif
261     return ret;
262 }
263
264 string vstrprintf(const char *format, va_list ap)
265 {
266     char buffer[50000];
267     char* p = buffer;
268     int limit = sizeof(buffer);
269     int ret;
270     for ( ; ; )
271     {
272 #ifndef _MSC_VER
273         va_list arg_ptr;
274         va_copy(arg_ptr, ap);
275 #else
276         va_list arg_ptr = ap;
277 #endif
278 #ifdef WIN32
279         ret = _vsnprintf(p, limit, format, arg_ptr);
280 #else
281         ret = vsnprintf(p, limit, format, arg_ptr);
282 #endif
283         va_end(arg_ptr);
284         if (ret >= 0 && ret < limit)
285             break;
286         if (p != buffer)
287             delete[] p;
288         limit *= 2;
289         p = new(nothrow) char[limit];
290         if (p == NULL)
291             throw std::bad_alloc();
292     }
293     string str(p, p+ret);
294     if (p != buffer)
295         delete[] p;
296     return str;
297 }
298
299 string real_strprintf(const char *format, int dummy, ...)
300 {
301     va_list arg_ptr;
302     va_start(arg_ptr, dummy);
303     string str = vstrprintf(format, arg_ptr);
304     va_end(arg_ptr);
305     return str;
306 }
307
308 string real_strprintf(const std::string &format, int dummy, ...)
309 {
310     va_list arg_ptr;
311     va_start(arg_ptr, dummy);
312     string str = vstrprintf(format.c_str(), arg_ptr);
313     va_end(arg_ptr);
314     return str;
315 }
316
317 bool error(const char *format, ...)
318 {
319     va_list arg_ptr;
320     va_start(arg_ptr, format);
321     std::string str = vstrprintf(format, arg_ptr);
322     va_end(arg_ptr);
323     printf("ERROR: %s\n", str.c_str());
324     return false;
325 }
326
327
328 void ParseString(const string& str, char c, vector<string>& v)
329 {
330     if (str.empty())
331         return;
332     string::size_type i1 = 0;
333     string::size_type i2;
334     for ( ; ; )
335     {
336         i2 = str.find(c, i1);
337         if (i2 == str.npos)
338         {
339             v.push_back(str.substr(i1));
340             return;
341         }
342         v.push_back(str.substr(i1, i2-i1));
343         i1 = i2+1;
344     }
345 }
346
347
348 string FormatMoney(int64_t n, bool fPlus)
349 {
350     // Note: not using straight sprintf here because we do NOT want
351     // localized number formatting.
352     int64_t n_abs = (n > 0 ? n : -n);
353     int64_t quotient = n_abs/COIN;
354     int64_t remainder = n_abs%COIN;
355     string str = strprintf("%" PRId64 ".%06" PRId64, quotient, remainder);
356
357     // Right-trim excess zeros before the decimal point:
358     size_t nTrim = 0;
359     for (size_t i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
360         ++nTrim;
361     if (nTrim)
362         str.erase(str.size()-nTrim, nTrim);
363
364     if (n < 0)
365         str.insert(0u, 1, '-');
366     else if (fPlus && n > 0)
367         str.insert(0u, 1, '+');
368     return str;
369 }
370
371
372 bool ParseMoney(const string& str, int64_t& nRet)
373 {
374     return ParseMoney(str.c_str(), nRet);
375 }
376
377 bool ParseMoney(const char* pszIn, int64_t& nRet)
378 {
379     string strWhole;
380     int64_t nUnits = 0;
381     const char* p = pszIn;
382     while (isspace(*p))
383         p++;
384     for (; *p; p++)
385     {
386         if (*p == '.')
387         {
388             p++;
389             int64_t nMult = CENT*10;
390             while (isdigit(*p) && (nMult > 0))
391             {
392                 nUnits += nMult * (*p++ - '0');
393                 nMult /= 10;
394             }
395             break;
396         }
397         if (isspace(*p))
398             break;
399         if (!isdigit(*p))
400             return false;
401         strWhole.insert(strWhole.end(), *p);
402     }
403     for (; *p; p++)
404         if (!isspace(*p))
405             return false;
406     if (strWhole.size() > 10) // guard against 63 bit overflow
407         return false;
408     if (nUnits < 0 || nUnits > COIN)
409         return false;
410     int64_t nWhole = atoi64(strWhole);
411     int64_t nValue = nWhole*COIN + nUnits;
412
413     nRet = nValue;
414     return true;
415 }
416
417
418 static const signed char phexdigit[256] =
419 { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
420   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
421   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
422   0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
423   -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
424   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
425   -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
426   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
427   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
428   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
429   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
430   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
431   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
432   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
433   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
434   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
435
436 bool IsHex(const string& str)
437 {
438     for (unsigned char c : str)
439     {
440         if (phexdigit[c] < 0)
441             return false;
442     }
443     return (str.size() > 0) && (str.size()%2 == 0);
444 }
445
446 vector<unsigned char> ParseHex(const char* psz)
447 {
448     // convert hex dump to vector
449     vector<unsigned char> vch;
450     for ( ; ; )
451     {
452         while (isspace(*psz))
453             psz++;
454         signed char c = phexdigit[(unsigned char)*psz++];
455         if (c == (signed char)-1)
456             break;
457         unsigned char n = (c << 4);
458         c = phexdigit[(unsigned char)*psz++];
459         if (c == (signed char)-1)
460             break;
461         n |= c;
462         vch.push_back(n);
463     }
464     return vch;
465 }
466
467 vector<unsigned char> ParseHex(const string& str)
468 {
469     return ParseHex(str.c_str());
470 }
471
472 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
473 {
474     // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
475     if (name.find("-no") == 0)
476     {
477         std::string positive("-");
478         positive.append(name.begin()+3, name.end());
479         if (mapSettingsRet.count(positive) == 0)
480         {
481             bool value = !GetBoolArg(name);
482             mapSettingsRet[positive] = (value ? "1" : "0");
483         }
484     }
485 }
486
487 void ParseParameters(int argc, const char* const argv[])
488 {
489     mapArgs.clear();
490     mapMultiArgs.clear();
491     for (int i = 1; i < argc; i++)
492     {
493         std::string str(argv[i]);
494         std::string strValue;
495         size_t is_index = str.find('=');
496         if (is_index != std::string::npos)
497         {
498             strValue = str.substr(is_index+1);
499             str = str.substr(0, is_index);
500         }
501 #ifdef WIN32
502         std::transform(str.begin(), str.end(), str.begin(), ::tolower);
503         if (str.compare(0,1, "/") == 0)
504             str = "-" + str.substr(1);
505 #endif
506         if (str[0] != '-')
507             break;
508
509         mapArgs[str] = strValue;
510         mapMultiArgs[str].push_back(strValue);
511     }
512
513     // New 0.6 features:
514     for (const auto& entry : mapArgs)
515     {
516         string name = entry.first;
517
518         //  interpret --foo as -foo (as long as both are not set)
519         if (name.find("--") == 0)
520         {
521             std::string singleDash(name.begin()+1, name.end());
522             if (mapArgs.count(singleDash) == 0)
523                 mapArgs[singleDash] = entry.second;
524             name = singleDash;
525         }
526
527         // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
528         InterpretNegativeSetting(name, mapArgs);
529     }
530 }
531
532 std::string GetArg(const std::string& strArg, const std::string& strDefault)
533 {
534     if (mapArgs.count(strArg))
535         return mapArgs[strArg];
536     return strDefault;
537 }
538
539 int64_t GetArg(const std::string& strArg, int64_t nDefault)
540 {
541     if (mapArgs.count(strArg))
542         return atoi64(mapArgs[strArg]);
543     return nDefault;
544 }
545
546 int32_t GetArgInt(const std::string& strArg, int32_t nDefault)
547 {
548     if (mapArgs.count(strArg))
549         return strtol(mapArgs[strArg]);
550     return nDefault;
551 }
552
553 uint32_t GetArgUInt(const std::string& strArg, uint32_t nDefault)
554 {
555     if (mapArgs.count(strArg))
556         return strtoul(mapArgs[strArg]);
557     return nDefault;
558 }
559
560 bool GetBoolArg(const std::string& strArg, bool fDefault)
561 {
562     if (mapArgs.count(strArg))
563     {
564         if (mapArgs[strArg].empty())
565             return true;
566         return (atoi(mapArgs[strArg]) != 0);
567     }
568     return fDefault;
569 }
570
571 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
572 {
573     if (mapArgs.count(strArg) || mapMultiArgs.count(strArg))
574         return false;
575     mapArgs[strArg] = strValue;
576     mapMultiArgs[strArg].push_back(strValue);
577
578     return true;
579 }
580
581 bool SoftSetBoolArg(const std::string& strArg, bool fValue)
582 {
583     if (fValue)
584         return SoftSetArg(strArg, std::string("1"));
585     else
586         return SoftSetArg(strArg, std::string("0"));
587 }
588
589
590 string EncodeBase64(const unsigned char* pch, size_t len)
591 {
592     static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
593
594     string strRet="";
595     strRet.reserve((len+2)/3*4);
596
597     int mode=0, left=0;
598     const unsigned char *pchEnd = pch+len;
599
600     while (pch<pchEnd)
601     {
602         int enc = *(pch++);
603         switch (mode)
604         {
605             case 0: // we have no bits
606                 strRet += pbase64[enc >> 2];
607                 left = (enc & 3) << 4;
608                 mode = 1;
609                 break;
610
611             case 1: // we have two bits
612                 strRet += pbase64[left | (enc >> 4)];
613                 left = (enc & 15) << 2;
614                 mode = 2;
615                 break;
616
617             case 2: // we have four bits
618                 strRet += pbase64[left | (enc >> 6)];
619                 strRet += pbase64[enc & 63];
620                 mode = 0;
621                 break;
622         }
623     }
624
625     if (mode)
626     {
627         strRet += pbase64[left];
628         strRet += '=';
629         if (mode == 1)
630             strRet += '=';
631     }
632
633     return strRet;
634 }
635
636 string EncodeBase64(const string& str)
637 {
638     return EncodeBase64((const unsigned char*)str.c_str(), str.size());
639 }
640
641 vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
642 {
643     static const int decode64_table[256] =
644     {
645         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
646         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
647         -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
648         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
649         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
650         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
651         49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
652         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
653         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
654         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
655         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
656         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
657         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
658     };
659
660     if (pfInvalid)
661         *pfInvalid = false;
662
663     vector<unsigned char> vchRet;
664     vchRet.reserve(strlen(p)*3/4);
665
666     int mode = 0;
667     int left = 0;
668
669     for ( ; ; )
670     {
671          int dec = decode64_table[(unsigned char)*p];
672          if (dec == -1) break;
673          p++;
674          switch (mode)
675          {
676              case 0: // we have no bits and get 6
677                  left = dec;
678                  mode = 1;
679                  break;
680
681               case 1: // we have 6 bits and keep 4
682                   vchRet.push_back((left<<2) | (dec>>4));
683                   left = dec & 15;
684                   mode = 2;
685                   break;
686
687              case 2: // we have 4 bits and get 6, we keep 2
688                  vchRet.push_back((left<<4) | (dec>>2));
689                  left = dec & 3;
690                  mode = 3;
691                  break;
692
693              case 3: // we have 2 bits and get 6
694                  vchRet.push_back((left<<6) | dec);
695                  mode = 0;
696                  break;
697          }
698     }
699
700     if (pfInvalid)
701         switch (mode)
702         {
703             case 0: // 4n base64 characters processed: ok
704                 break;
705
706             case 1: // 4n+1 base64 character processed: impossible
707                 *pfInvalid = true;
708                 break;
709
710             case 2: // 4n+2 base64 characters processed: require '=='
711                 if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
712                     *pfInvalid = true;
713                 break;
714
715             case 3: // 4n+3 base64 characters processed: require '='
716                 if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
717                     *pfInvalid = true;
718                 break;
719         }
720
721     return vchRet;
722 }
723
724 string DecodeBase64(const string& str)
725 {
726     vector<unsigned char> vchRet = DecodeBase64(str.c_str());
727     return string((const char*)&vchRet[0], vchRet.size());
728 }
729
730 string EncodeBase32(const unsigned char* pch, size_t len)
731 {
732     static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
733
734     string strRet="";
735     strRet.reserve((len+4)/5*8);
736
737     int mode=0, left=0;
738     const unsigned char *pchEnd = pch+len;
739
740     while (pch<pchEnd)
741     {
742         int enc = *(pch++);
743         switch (mode)
744         {
745             case 0: // we have no bits
746                 strRet += pbase32[enc >> 3];
747                 left = (enc & 7) << 2;
748                 mode = 1;
749                 break;
750
751             case 1: // we have three bits
752                 strRet += pbase32[left | (enc >> 6)];
753                 strRet += pbase32[(enc >> 1) & 31];
754                 left = (enc & 1) << 4;
755                 mode = 2;
756                 break;
757
758             case 2: // we have one bit
759                 strRet += pbase32[left | (enc >> 4)];
760                 left = (enc & 15) << 1;
761                 mode = 3;
762                 break;
763
764             case 3: // we have four bits
765                 strRet += pbase32[left | (enc >> 7)];
766                 strRet += pbase32[(enc >> 2) & 31];
767                 left = (enc & 3) << 3;
768                 mode = 4;
769                 break;
770
771             case 4: // we have two bits
772                 strRet += pbase32[left | (enc >> 5)];
773                 strRet += pbase32[enc & 31];
774                 mode = 0;
775         }
776     }
777
778     static const int nPadding[5] = {0, 6, 4, 3, 1};
779     if (mode)
780     {
781         strRet += pbase32[left];
782         for (int n=0; n<nPadding[mode]; n++)
783              strRet += '=';
784     }
785
786     return strRet;
787 }
788
789 string EncodeBase32(const string& str)
790 {
791     return EncodeBase32((const unsigned char*)str.c_str(), str.size());
792 }
793
794 vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
795 {
796     static const int decode32_table[256] =
797     {
798         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
799         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
800         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
801         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
802         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1,  0,  1,  2,
803          3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
804         23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
805         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
806         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
807         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
808         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
809         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
810         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
811     };
812
813     if (pfInvalid)
814         *pfInvalid = false;
815
816     vector<unsigned char> vchRet;
817     vchRet.reserve((strlen(p))*5/8);
818
819     int mode = 0;
820     int left = 0;
821
822     for ( ; ; )
823     {
824          int dec = decode32_table[(unsigned char)*p];
825          if (dec == -1) break;
826          p++;
827          switch (mode)
828          {
829              case 0: // we have no bits and get 5
830                  left = dec;
831                  mode = 1;
832                  break;
833
834               case 1: // we have 5 bits and keep 2
835                   vchRet.push_back((left<<3) | (dec>>2));
836                   left = dec & 3;
837                   mode = 2;
838                   break;
839
840              case 2: // we have 2 bits and keep 7
841                  left = left << 5 | dec;
842                  mode = 3;
843                  break;
844
845              case 3: // we have 7 bits and keep 4
846                  vchRet.push_back((left<<1) | (dec>>4));
847                  left = dec & 15;
848                  mode = 4;
849                  break;
850
851              case 4: // we have 4 bits, and keep 1
852                  vchRet.push_back((left<<4) | (dec>>1));
853                  left = dec & 1;
854                  mode = 5;
855                  break;
856
857              case 5: // we have 1 bit, and keep 6
858                  left = left << 5 | dec;
859                  mode = 6;
860                  break;
861
862              case 6: // we have 6 bits, and keep 3
863                  vchRet.push_back((left<<2) | (dec>>3));
864                  left = dec & 7;
865                  mode = 7;
866                  break;
867
868              case 7: // we have 3 bits, and keep 0
869                  vchRet.push_back((left<<5) | dec);
870                  mode = 0;
871                  break;
872          }
873     }
874
875     if (pfInvalid)
876         switch (mode)
877         {
878             case 0: // 8n base32 characters processed: ok
879                 break;
880
881             case 1: // 8n+1 base32 characters processed: impossible
882             case 3: //   +3
883             case 6: //   +6
884                 *pfInvalid = true;
885                 break;
886
887             case 2: // 8n+2 base32 characters processed: require '======'
888                 if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1)
889                     *pfInvalid = true;
890                 break;
891
892             case 4: // 8n+4 base32 characters processed: require '===='
893                 if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1)
894                     *pfInvalid = true;
895                 break;
896
897             case 5: // 8n+5 base32 characters processed: require '==='
898                 if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1)
899                     *pfInvalid = true;
900                 break;
901
902             case 7: // 8n+7 base32 characters processed: require '='
903                 if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1)
904                     *pfInvalid = true;
905                 break;
906         }
907
908     return vchRet;
909 }
910
911 string DecodeBase32(const string& str)
912 {
913     vector<unsigned char> vchRet = DecodeBase32(str.c_str());
914     return string((const char*)&vchRet[0], vchRet.size());
915 }
916
917
918 int64_t DecodeDumpTime(const std::string& s)
919 {
920     bt::ptime pt;
921
922     for(size_t i=0; i<formats_n; ++i)
923     {
924         std::istringstream is(s);
925         is.imbue(formats[i]);
926         is >> pt;
927         if(pt != bt::ptime()) break;
928     }
929
930     return pt_to_time_t(pt);
931 }
932
933 std::string EncodeDumpTime(int64_t nTime) {
934     return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
935 }
936
937 std::string EncodeDumpString(const std::string &str) {
938     std::stringstream ret;
939     for (unsigned char c : str) {
940         if (c <= 32 || c >= 128 || c == '%') {
941             ret << '%' << HexStr(&c, &c + 1);
942         } else {
943             ret << c;
944         }
945     }
946     return ret.str();
947 }
948
949 std::string DecodeDumpString(const std::string &str) {
950     std::stringstream ret;
951     for (unsigned int pos = 0; pos < str.length(); pos++) {
952         unsigned char c = str[pos];
953         if (c == '%' && pos+2 < str.length()) {
954             c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) | 
955                 ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
956             pos += 2;
957         }
958         ret << c;
959     }
960     return ret.str();
961 }
962
963 bool WildcardMatch(const char* psz, const char* mask)
964 {
965     for ( ; ; )
966     {
967         switch (*mask)
968         {
969         case '\0':
970             return (*psz == '\0');
971         case '*':
972             return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
973         case '?':
974             if (*psz == '\0')
975                 return false;
976             break;
977         default:
978             if (*psz != *mask)
979                 return false;
980             break;
981         }
982         psz++;
983         mask++;
984     }
985 }
986
987 bool WildcardMatch(const string& str, const string& mask)
988 {
989     return WildcardMatch(str.c_str(), mask.c_str());
990 }
991
992
993
994
995
996
997
998
999 static std::string FormatException(std::exception* pex, const char* pszThread)
1000 {
1001 #ifdef WIN32
1002     char pszModule[MAX_PATH] = "";
1003     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
1004 #else
1005     const char* pszModule = "novacoin";
1006 #endif
1007     if (pex)
1008         return strprintf(
1009             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
1010     else
1011         return strprintf(
1012             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
1013 }
1014
1015 void LogException(std::exception* pex, const char* pszThread)
1016 {
1017     std::string message = FormatException(pex, pszThread);
1018     printf("\n%s", message.c_str());
1019 }
1020
1021 void PrintException(std::exception* pex, const char* pszThread)
1022 {
1023     std::string message = FormatException(pex, pszThread);
1024     printf("\n\n************************\n%s\n", message.c_str());
1025     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
1026     strMiscWarning = message;
1027     throw;
1028 }
1029
1030 void LogStackTrace() {
1031     printf("\n\n******* exception encountered *******\n");
1032     if (fileout)
1033     {
1034 #if !defined(WIN32) && !defined(ANDROID)
1035         void* pszBuffer[32];
1036         size_t size;
1037         size = backtrace(pszBuffer, 32);
1038         backtrace_symbols_fd(pszBuffer, size, fileno(fileout));
1039 #endif
1040     }
1041 }
1042
1043 void PrintExceptionContinue(std::exception* pex, const char* pszThread)
1044 {
1045     std::string message = FormatException(pex, pszThread);
1046     printf("\n\n************************\n%s\n", message.c_str());
1047     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
1048     strMiscWarning = message;
1049 }
1050
1051 boost::filesystem::path GetDefaultDataDir()
1052 {
1053     namespace fs = boost::filesystem;
1054     // Windows < Vista: C:\Documents and Settings\Username\Application Data\NovaCoin
1055     // Windows >= Vista: C:\Users\Username\AppData\Roaming\NovaCoin
1056     // Mac: ~/Library/Application Support/NovaCoin
1057     // Unix: ~/.novacoin
1058 #ifdef WIN32
1059     // Windows
1060     return GetSpecialFolderPath(CSIDL_APPDATA) / "NovaCoin";
1061 #else
1062     fs::path pathRet;
1063     char* pszHome = getenv("HOME");
1064     if (pszHome == NULL || strlen(pszHome) == 0)
1065         pathRet = fs::path("/");
1066     else
1067         pathRet = fs::path(pszHome);
1068 #ifdef __APPLE__
1069     // Mac
1070     pathRet /= "Library/Application Support";
1071     fs::create_directory(pathRet);
1072     return pathRet / "NovaCoin";
1073 #else
1074     // Unix
1075     return pathRet / ".novacoin";
1076 #endif
1077 #endif
1078 }
1079
1080 const boost::filesystem::path &GetDataDir(bool fNetSpecific)
1081 {
1082     namespace fs = boost::filesystem;
1083
1084     static fs::path pathCached[2];
1085     static CCriticalSection csPathCached;
1086     static bool cachedPath[2] = {false, false};
1087
1088     fs::path &path = pathCached[fNetSpecific];
1089
1090     // This can be called during exceptions by printf, so we cache the
1091     // value so we don't have to do memory allocations after that.
1092     if (cachedPath[fNetSpecific])
1093         return path;
1094
1095     LOCK(csPathCached);
1096
1097     if (mapArgs.count("-datadir")) {
1098         path = fs::system_complete(mapArgs["-datadir"]);
1099         if (!fs::is_directory(path)) {
1100             path = "";
1101             return path;
1102         }
1103     } else {
1104         path = GetDefaultDataDir();
1105     }
1106     if (fNetSpecific && GetBoolArg("-testnet", false))
1107         path /= "testnet2";
1108
1109     fs::create_directory(path);
1110
1111     cachedPath[fNetSpecific]=true;
1112     return path;
1113 }
1114
1115 string randomStrGen(int length) {
1116     static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1117     string result;
1118     result.resize(length);
1119     for (int32_t i = 0; i < length; i++)
1120         result[i] = charset[rand() % charset.length()];
1121
1122     return result;
1123 }
1124
1125 void createConf()
1126 {
1127     srand(static_cast<unsigned int>(time(NULL)));
1128
1129     ofstream pConf;
1130 #if BOOST_FILESYSTEM_VERSION >= 3
1131     pConf.open(GetConfigFile().generic_string().c_str());
1132 #else
1133     pConf.open(GetConfigFile().string().c_str());
1134 #endif
1135     pConf << "rpcuser=user\nrpcpassword="
1136             + randomStrGen(15)
1137             + "\nrpcport=8344"
1138             + "\n#(0=off, 1=on) daemon - run in the background as a daemon and accept commands"
1139             + "\ndaemon=0"
1140             + "\n#(0=off, 1=on) server - accept command line and JSON-RPC commands"
1141             + "\nserver=0"
1142             + "\nrpcallowip=127.0.0.1";
1143     pConf.close();
1144 }
1145
1146 boost::filesystem::path GetConfigFile()
1147 {
1148     boost::filesystem::path pathConfigFile(GetArg("-conf", "novacoin.conf"));
1149     if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
1150     return pathConfigFile;
1151 }
1152
1153 void ReadConfigFile(map<string, string>& mapSettingsRet,
1154                     map<string, vector<string> >& mapMultiSettingsRet)
1155 {
1156     boost::filesystem::ifstream streamConfig(GetConfigFile());
1157     if (!streamConfig.good())
1158     {
1159         createConf();
1160         new(&streamConfig) boost::filesystem::ifstream(GetConfigFile());
1161         if(!streamConfig.good())
1162             return;
1163     }
1164
1165     set<string> setOptions;
1166     setOptions.insert("*");
1167
1168     for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
1169     {
1170         // Don't overwrite existing settings so command line settings override bitcoin.conf
1171         string strKey = string("-") + it->string_key;
1172         if (mapSettingsRet.count(strKey) == 0)
1173         {
1174             mapSettingsRet[strKey] = it->value[0];
1175             // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
1176             InterpretNegativeSetting(strKey, mapSettingsRet);
1177         }
1178         mapMultiSettingsRet[strKey].push_back(it->value[0]);
1179     }
1180 }
1181
1182 boost::filesystem::path GetPidFile()
1183 {
1184     boost::filesystem::path pathPidFile(GetArg("-pid", "novacoind.pid"));
1185     if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
1186     return pathPidFile;
1187 }
1188
1189 #ifndef WIN32
1190 void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
1191 {
1192     FILE* file = fopen(path.string().c_str(), "w");
1193     if (file)
1194     {
1195         fprintf(file, "%d\n", pid);
1196         fclose(file);
1197     }
1198 }
1199 #endif
1200
1201 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
1202 {
1203 #ifdef WIN32
1204     return MoveFileExA(src.string().c_str(), dest.string().c_str(),
1205                        MOVEFILE_REPLACE_EXISTING) != 0;
1206 #else
1207     int rc = std::rename(src.string().c_str(), dest.string().c_str());
1208     return (rc == 0);
1209 #endif /* WIN32 */
1210 }
1211
1212 void FileCommit(FILE *fileout)
1213 {
1214     fflush(fileout);                // harmless if redundantly called
1215 #ifdef WIN32
1216     _commit(_fileno(fileout));
1217 #else
1218     fsync(fileno(fileout));
1219 #endif
1220 }
1221
1222 int GetFilesize(FILE* file)
1223 {
1224     int nSavePos = ftell(file);
1225     int nFilesize = -1;
1226     if (fseek(file, 0, SEEK_END) == 0)
1227         nFilesize = ftell(file);
1228     fseek(file, nSavePos, SEEK_SET);
1229     return nFilesize;
1230 }
1231
1232 void ShrinkDebugFile()
1233 {
1234     // Scroll debug.log if it's getting too big
1235     boost::filesystem::path pathLog = GetDataDir() / "debug.log";
1236     FILE* file = fopen(pathLog.string().c_str(), "r");
1237     if (file && GetFilesize(file) > 10 * 1000000)
1238     {
1239         // Restart the file with some of the end
1240         try {
1241             vector<char>* vBuf = new vector <char>(200000, 0);
1242             fseek(file, -((long)(vBuf->size())), SEEK_END);
1243             size_t nBytes = fread(&vBuf->operator[](0), 1, vBuf->size(), file);
1244             fclose(file);
1245             file = fopen(pathLog.string().c_str(), "w");
1246             if (file)
1247             {
1248                 fwrite(&vBuf->operator[](0), 1, nBytes, file);
1249                 fclose(file);
1250             }
1251             delete vBuf;
1252         }
1253         catch (const bad_alloc& e) {
1254             // Bad things happen - no free memory in heap at program startup
1255             fclose(file);
1256             printf("Warning: %s in %s:%d\n ShrinkDebugFile failed - debug.log expands further", e.what(), __FILE__, __LINE__);
1257         }
1258     }
1259 }
1260
1261
1262
1263
1264
1265
1266
1267
1268 //
1269 // "Never go to sea with two chronometers; take one or three."
1270 // Our three time sources are:
1271 //  - System clock
1272 //  - Median of other nodes clocks
1273 //  - The user (asking the user to fix the system clock if the first two disagree)
1274 //
1275
1276 // System clock
1277 int64_t GetTime()
1278 {
1279     int64_t now = time(NULL);
1280     assert(now > 0);
1281     return now;
1282 }
1283
1284 // Trusted NTP offset or median of NTP samples.
1285 extern int64_t nNtpOffset;
1286
1287 // Median of time samples given by other nodes.
1288 static int64_t nNodesOffset = INT64_MAX;
1289
1290 // Select time offset:
1291 int64_t GetTimeOffset()
1292 {
1293     // If NTP and system clock are in agreement within 40 minutes, then use NTP.
1294     if (abs64(nNtpOffset) < 40 * 60)
1295         return nNtpOffset;
1296
1297     // If not, then choose between median peer time and system clock.
1298     if (abs64(nNodesOffset) < 70 * 60)
1299         return nNodesOffset;
1300
1301     return 0;
1302 }
1303
1304 int64_t GetNodesOffset()
1305 {
1306         return nNodesOffset;
1307 }
1308
1309 int64_t GetAdjustedTime()
1310 {
1311     return GetTime() + GetTimeOffset();
1312 }
1313
1314 void AddTimeData(const CNetAddr& ip, int64_t nTime)
1315 {
1316     int64_t nOffsetSample = nTime - GetTime();
1317
1318     // Ignore duplicates
1319     static set<CNetAddr> setKnown;
1320     if (!setKnown.insert(ip).second)
1321         return;
1322
1323     // Add data
1324     vTimeOffsets.input(nOffsetSample);
1325     printf("Added time data, samples %d, offset %+" PRId64 " (%+" PRId64 " minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
1326     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
1327     {
1328         int64_t nMedian = vTimeOffsets.median();
1329         std::vector<int64_t> vSorted = vTimeOffsets.sorted();
1330         // Only let other nodes change our time by so much
1331         if (abs64(nMedian) < 70 * 60)
1332         {
1333             nNodesOffset = nMedian;
1334         }
1335         else
1336         {
1337             nNodesOffset = INT64_MAX;
1338
1339             static bool fDone;
1340             if (!fDone)
1341             {
1342                 bool fMatch = false;
1343
1344                 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
1345                 for (int64_t nOffset : vSorted)
1346                     if (nOffset != 0 && abs64(nOffset) < 5 * 60)
1347                         fMatch = true;
1348
1349                 if (!fMatch)
1350                 {
1351                     fDone = true;
1352                     string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong NovaCoin will not work properly.");
1353                     strMiscWarning = strMessage;
1354                     printf("*** %s\n", strMessage.c_str());
1355                     uiInterface.ThreadSafeMessageBox(strMessage+" ", string("NovaCoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION);
1356                 }
1357             }
1358         }
1359         if (fDebug) {
1360             for (int64_t n : vSorted)
1361                 printf("%+" PRId64 "  ", n);
1362             printf("|  ");
1363         }
1364         if (nNodesOffset != INT64_MAX)
1365             printf("nNodesOffset = %+" PRId64 "  (%+" PRId64 " minutes)\n", nNodesOffset, nNodesOffset/60);
1366     }
1367 }
1368
1369 string FormatVersion(int nVersion)
1370 {
1371     if (nVersion%100 == 0)
1372         return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
1373     else
1374         return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
1375 }
1376
1377 string FormatFullVersion()
1378 {
1379     return CLIENT_BUILD;
1380 }
1381
1382 // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
1383 std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
1384 {
1385     std::ostringstream ss;
1386     ss << "/";
1387     ss << name << ":" << FormatVersion(nClientVersion);
1388     if (!comments.empty())
1389     {
1390         ss << "(";
1391         for (const auto& st : comments)
1392         {
1393             ss << st;
1394             if (st == comments.back()) break;
1395             ss << "; ";
1396         }
1397         ss << ")";
1398     }
1399     ss << "/";
1400     return ss.str();
1401 }
1402
1403 #ifdef WIN32
1404 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
1405 {
1406     namespace fs = boost::filesystem;
1407
1408     char pszPath[MAX_PATH] = "";
1409
1410     if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
1411     {
1412         return fs::path(pszPath);
1413     }
1414
1415     printf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
1416     return fs::path("");
1417 }
1418 #endif
1419
1420 void runCommand(std::string strCommand)
1421 {
1422     int nErr = ::system(strCommand.c_str());
1423     if (nErr)
1424         printf("runCommand error: system(%s) returned %d\n", strCommand.c_str(), nErr);
1425 }
1426
1427 void RenameThread(const char* name)
1428 {
1429 #if defined(PR_SET_NAME)
1430     // Only the first 15 characters are used (16 - NUL terminator)
1431     ::prctl(PR_SET_NAME, name, 0, 0, 0);
1432 #elif (defined(__FreeBSD__) || defined(__OpenBSD__))
1433     pthread_set_name_np(pthread_self(), name);
1434 #elif defined(__APPLE__)
1435     pthread_setname_np(name);
1436 #else
1437     // Prevent warnings for unused parameters...
1438     (void)name;
1439 #endif
1440 }
1441
1442 bool NewThread(void(*pfn)(void*), void* parg)
1443 {
1444     try
1445     {
1446         boost::thread(pfn, parg); // thread detaches when out of scope
1447     } catch(boost::thread_resource_error &e) {
1448         printf("Error creating thread: %s\n", e.what());
1449         return false;
1450     }
1451     return true;
1452 }
1453
1454 std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
1455 {
1456     // std::locale takes ownership of the pointer
1457     std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
1458     std::stringstream ss;
1459     ss.imbue(loc);
1460     ss << boost::posix_time::from_time_t(nTime);
1461     return ss.str();
1462 }