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