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