a05a7a516283b17dd96d88669053882ac2a890a8
[novacoin.git] / src / util.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Copyright (c) 2011-2012 The PPCoin developers
4 // Copyright (c) 2012-2013 The NovaCoin developers
5 // Distributed under the MIT/X11 software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7
8 #include "util.h"
9 #include "strlcpy.h"
10 #include "version.h"
11 #include "ui_interface.h"
12 #include <boost/algorithm/string/join.hpp>
13
14 // Work around clang compilation problem in Boost 1.46:
15 // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
16 // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
17 //           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
18 namespace boost {
19     namespace program_options {
20         std::string to_internal(const std::string&);
21     }
22 }
23
24 #include <boost/program_options/detail/config_file.hpp>
25 #include <boost/program_options/parsers.hpp>
26 #include <boost/filesystem.hpp>
27 #include <boost/filesystem/fstream.hpp>
28 #include <boost/interprocess/sync/interprocess_mutex.hpp>
29 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
30 #include <boost/foreach.hpp>
31 #include <boost/thread.hpp>
32 #include <openssl/crypto.h>
33 #include <openssl/rand.h>
34
35 #ifdef WIN32
36 #ifdef _MSC_VER
37 #pragma warning(disable:4786)
38 #pragma warning(disable:4804)
39 #pragma warning(disable:4805)
40 #pragma warning(disable:4717)
41 #endif
42 #ifdef _WIN32_WINNT
43 #undef _WIN32_WINNT
44 #endif
45 #define _WIN32_WINNT 0x0501
46 #ifdef _WIN32_IE
47 #undef _WIN32_IE
48 #endif
49 #define _WIN32_IE 0x0400
50 #define WIN32_LEAN_AND_MEAN 1
51 #ifndef NOMINMAX
52 #define NOMINMAX
53 #endif
54 #include "shlobj.h"
55 #include "shlwapi.h"
56 #endif
57
58 #ifndef WIN32
59 #include <execinfo.h>
60 #endif
61
62 using namespace std;
63 using namespace boost;
64
65 map<string, string> mapArgs;
66 map<string, vector<string> > mapMultiArgs;
67 bool fDebug = false;
68 bool fPrintToConsole = false;
69 bool fPrintToDebugger = false;
70 bool fRequestShutdown = false;
71 bool fShutdown = false;
72 bool fDaemon = false;
73 bool fServer = false;
74 bool fCommandLine = false;
75 string strMiscWarning;
76 bool fTestNet = false;
77 bool fNoListen = false;
78 bool fLogTimestamps = false;
79 CMedianFilter<int64> vTimeOffsets(200,0);
80
81 // Init openssl library multithreading support
82 static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
83 void locking_callback(int mode, int i, const char* file, int line)
84 {
85     if (mode & CRYPTO_LOCK)
86         ppmutexOpenSSL[i]->lock();
87     else
88         ppmutexOpenSSL[i]->unlock();
89 }
90
91 // Init
92 class CInit
93 {
94 public:
95     CInit()
96     {
97         // Init openssl library multithreading support
98         ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
99         for (int i = 0; i < CRYPTO_num_locks(); i++)
100             ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
101         CRYPTO_set_locking_callback(locking_callback);
102
103 #ifdef WIN32
104         // Seed random number generator with screen scrape and other hardware sources
105         RAND_screen();
106 #endif
107
108         // Seed random number generator with performance counter
109         RandAddSeed();
110     }
111     ~CInit()
112     {
113         // Shutdown openssl library multithreading support
114         CRYPTO_set_locking_callback(NULL);
115         for (int i = 0; i < CRYPTO_num_locks(); i++)
116             delete ppmutexOpenSSL[i];
117         OPENSSL_free(ppmutexOpenSSL);
118     }
119 }
120 instance_of_cinit;
121
122
123
124
125
126
127
128
129 void RandAddSeed()
130 {
131     // Seed with CPU performance counter
132     int64 nCounter = GetPerformanceCounter();
133     RAND_add(&nCounter, sizeof(nCounter), 1.5);
134     memset(&nCounter, 0, sizeof(nCounter));
135 }
136
137 void RandAddSeedPerfmon()
138 {
139     RandAddSeed();
140
141     // This can take up to 2 seconds, so only do it every 10 minutes
142     static int64 nLastPerfmon;
143     if (GetTime() < nLastPerfmon + 10 * 60)
144         return;
145     nLastPerfmon = GetTime();
146
147 #ifdef WIN32
148     // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
149     // Seed with the entire set of perfmon data
150     unsigned char pdata[250000];
151     memset(pdata, 0, sizeof(pdata));
152     unsigned long nSize = sizeof(pdata);
153     long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
154     RegCloseKey(HKEY_PERFORMANCE_DATA);
155     if (ret == ERROR_SUCCESS)
156     {
157         RAND_add(pdata, nSize, nSize/100.0);
158         memset(pdata, 0, nSize);
159         printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat(GetTime()).c_str(), nSize);
160     }
161 #endif
162 }
163
164 uint64 GetRand(uint64 nMax)
165 {
166     if (nMax == 0)
167         return 0;
168
169     // The range of the random source must be a multiple of the modulus
170     // to give every possible output value an equal possibility
171     uint64 nRange = (std::numeric_limits<uint64>::max() / nMax) * nMax;
172     uint64 nRand = 0;
173     do
174         RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
175     while (nRand >= nRange);
176     return (nRand % nMax);
177 }
178
179 int GetRandInt(int nMax)
180 {
181     return GetRand(nMax);
182 }
183
184 uint256 GetRandHash()
185 {
186     uint256 hash;
187     RAND_bytes((unsigned char*)&hash, sizeof(hash));
188     return hash;
189 }
190
191
192
193
194
195
196
197
198 static FILE* fileout = NULL;
199
200 inline int OutputDebugStringF(const char* pszFormat, ...)
201 {
202     int ret = 0;
203     if (fPrintToConsole)
204     {
205         // print to console
206         va_list arg_ptr;
207         va_start(arg_ptr, pszFormat);
208         ret = vprintf(pszFormat, arg_ptr);
209         va_end(arg_ptr);
210     }
211     else
212     {
213         // print to debug.log
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             static boost::mutex mutexDebugLog;
224             boost::mutex::scoped_lock scoped_lock(mutexDebugLog);
225
226             // Debug print useful for profiling
227             if (fLogTimestamps && fStartedNewLine)
228                 fprintf(fileout, "%s ", DateTimeStrFormat(GetTime()).c_str());
229             if (pszFormat[strlen(pszFormat) - 1] == '\n')
230                 fStartedNewLine = true;
231             else
232                 fStartedNewLine = false;
233
234             va_list arg_ptr;
235             va_start(arg_ptr, pszFormat);
236             ret = vfprintf(fileout, pszFormat, arg_ptr);
237             va_end(arg_ptr);
238         }
239     }
240
241 #ifdef WIN32
242     if (fPrintToDebugger)
243     {
244         static CCriticalSection cs_OutputDebugStringF;
245
246         // accumulate a line at a time
247         {
248             LOCK(cs_OutputDebugStringF);
249             static char pszBuffer[50000];
250             static char* pend;
251             if (pend == NULL)
252                 pend = pszBuffer;
253             va_list arg_ptr;
254             va_start(arg_ptr, pszFormat);
255             int limit = END(pszBuffer) - pend - 2;
256             int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
257             va_end(arg_ptr);
258             if (ret < 0 || ret >= limit)
259             {
260                 pend = END(pszBuffer) - 2;
261                 *pend++ = '\n';
262             }
263             else
264                 pend += ret;
265             *pend = '\0';
266             char* p1 = pszBuffer;
267             char* p2;
268             while ((p2 = strchr(p1, '\n')))
269             {
270                 p2++;
271                 char c = *p2;
272                 *p2 = '\0';
273                 OutputDebugStringA(p1);
274                 *p2 = c;
275                 p1 = p2;
276             }
277             if (p1 != pszBuffer)
278                 memmove(pszBuffer, p1, pend - p1 + 1);
279             pend -= (p1 - pszBuffer);
280         }
281     }
282 #endif
283     return ret;
284 }
285
286
287 // Safer snprintf
288 //  - prints up to limit-1 characters
289 //  - output string is always null terminated even if limit reached
290 //  - return value is the number of characters actually printed
291 int my_snprintf(char* buffer, size_t limit, const char* format, ...)
292 {
293     if (limit == 0)
294         return 0;
295     va_list arg_ptr;
296     va_start(arg_ptr, format);
297     int ret = _vsnprintf(buffer, limit, format, arg_ptr);
298     va_end(arg_ptr);
299     if (ret < 0 || ret >= (int)limit)
300     {
301         ret = limit - 1;
302         buffer[limit-1] = 0;
303     }
304     return ret;
305 }
306
307 string real_strprintf(const std::string &format, int dummy, ...)
308 {
309     char buffer[50000];
310     char* p = buffer;
311     int limit = sizeof(buffer);
312     int ret;
313     loop
314     {
315         va_list arg_ptr;
316         va_start(arg_ptr, dummy);
317         ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
318         va_end(arg_ptr);
319         if (ret >= 0 && ret < limit)
320             break;
321         if (p != buffer)
322             delete[] p;
323         limit *= 2;
324         p = new char[limit];
325         if (p == NULL)
326             throw std::bad_alloc();
327     }
328     string str(p, p+ret);
329     if (p != buffer)
330         delete[] p;
331     return str;
332 }
333
334 bool error(const char *format, ...)
335 {
336     char buffer[50000];
337     int limit = sizeof(buffer);
338     va_list arg_ptr;
339     va_start(arg_ptr, format);
340     int ret = _vsnprintf(buffer, limit, format, arg_ptr);
341     va_end(arg_ptr);
342     if (ret < 0 || ret >= limit)
343     {
344         buffer[limit-1] = 0;
345     }
346     printf("ERROR: %s\n", buffer);
347     return false;
348 }
349
350
351 void ParseString(const string& str, char c, vector<string>& v)
352 {
353     if (str.empty())
354         return;
355     string::size_type i1 = 0;
356     string::size_type i2;
357     loop
358     {
359         i2 = str.find(c, i1);
360         if (i2 == str.npos)
361         {
362             v.push_back(str.substr(i1));
363             return;
364         }
365         v.push_back(str.substr(i1, i2-i1));
366         i1 = i2+1;
367     }
368 }
369
370
371 string FormatMoney(int64 n, bool fPlus)
372 {
373     // Note: not using straight sprintf here because we do NOT want
374     // localized number formatting.
375     int64 n_abs = (n > 0 ? n : -n);
376     int64 quotient = n_abs/COIN;
377     int64 remainder = n_abs%COIN;
378     string str = strprintf("%"PRI64d".%06"PRI64d, quotient, remainder);
379
380     // Right-trim excess 0's before the decimal point:
381     int nTrim = 0;
382     for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
383         ++nTrim;
384     if (nTrim)
385         str.erase(str.size()-nTrim, nTrim);
386
387     if (n < 0)
388         str.insert((unsigned int)0, 1, '-');
389     else if (fPlus && n > 0)
390         str.insert((unsigned int)0, 1, '+');
391     return str;
392 }
393
394
395 bool ParseMoney(const string& str, int64& nRet)
396 {
397     return ParseMoney(str.c_str(), nRet);
398 }
399
400 bool ParseMoney(const char* pszIn, int64& nRet)
401 {
402     string strWhole;
403     int64 nUnits = 0;
404     const char* p = pszIn;
405     while (isspace(*p))
406         p++;
407     for (; *p; p++)
408     {
409         if (*p == '.')
410         {
411             p++;
412             int64 nMult = CENT*10;
413             while (isdigit(*p) && (nMult > 0))
414             {
415                 nUnits += nMult * (*p++ - '0');
416                 nMult /= 10;
417             }
418             break;
419         }
420         if (isspace(*p))
421             break;
422         if (!isdigit(*p))
423             return false;
424         strWhole.insert(strWhole.end(), *p);
425     }
426     for (; *p; p++)
427         if (!isspace(*p))
428             return false;
429     if (strWhole.size() > 10) // guard against 63 bit overflow
430         return false;
431     if (nUnits < 0 || nUnits > COIN)
432         return false;
433     int64 nWhole = atoi64(strWhole);
434     int64 nValue = nWhole*COIN + nUnits;
435
436     nRet = nValue;
437     return true;
438 }
439
440
441 static signed char phexdigit[256] =
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   0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
446   -1,0xa,0xb,0xc,0xd,0xe,0xf,-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,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
449   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
450   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
451   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
452   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
453   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
454   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
455   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
456   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
457   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
458
459 bool IsHex(const string& str)
460 {
461     BOOST_FOREACH(unsigned char c, str)
462     {
463         if (phexdigit[c] < 0)
464             return false;
465     }
466     return (str.size() > 0) && (str.size()%2 == 0);
467 }
468
469 vector<unsigned char> ParseHex(const char* psz)
470 {
471     // convert hex dump to vector
472     vector<unsigned char> vch;
473     loop
474     {
475         while (isspace(*psz))
476             psz++;
477         signed char c = phexdigit[(unsigned char)*psz++];
478         if (c == (signed char)-1)
479             break;
480         unsigned char n = (c << 4);
481         c = phexdigit[(unsigned char)*psz++];
482         if (c == (signed char)-1)
483             break;
484         n |= c;
485         vch.push_back(n);
486     }
487     return vch;
488 }
489
490 vector<unsigned char> ParseHex(const string& str)
491 {
492     return ParseHex(str.c_str());
493 }
494
495 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
496 {
497     // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
498     if (name.find("-no") == 0)
499     {
500         std::string positive("-");
501         positive.append(name.begin()+3, name.end());
502         if (mapSettingsRet.count(positive) == 0)
503         {
504             bool value = !GetBoolArg(name);
505             mapSettingsRet[positive] = (value ? "1" : "0");
506         }
507     }
508 }
509
510 void ParseParameters(int argc, const char*const argv[])
511 {
512     mapArgs.clear();
513     mapMultiArgs.clear();
514     for (int i = 1; i < argc; i++)
515     {
516         char psz[10000];
517         strlcpy(psz, argv[i], sizeof(psz));
518         char* pszValue = (char*)"";
519         if (strchr(psz, '='))
520         {
521             pszValue = strchr(psz, '=');
522             *pszValue++ = '\0';
523         }
524         #ifdef WIN32
525         _strlwr(psz);
526         if (psz[0] == '/')
527             psz[0] = '-';
528         #endif
529         if (psz[0] != '-')
530             break;
531
532         mapArgs[psz] = pszValue;
533         mapMultiArgs[psz].push_back(pszValue);
534     }
535
536     // New 0.6 features:
537     BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
538     {
539         string name = entry.first;
540
541         //  interpret --foo as -foo (as long as both are not set)
542         if (name.find("--") == 0)
543         {
544             std::string singleDash(name.begin()+1, name.end());
545             if (mapArgs.count(singleDash) == 0)
546                 mapArgs[singleDash] = entry.second;
547             name = singleDash;
548         }
549
550         // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
551         InterpretNegativeSetting(name, mapArgs);
552     }
553 }
554
555 std::string GetArg(const std::string& strArg, const std::string& strDefault)
556 {
557     if (mapArgs.count(strArg))
558         return mapArgs[strArg];
559     return strDefault;
560 }
561
562 int64 GetArg(const std::string& strArg, int64 nDefault)
563 {
564     if (mapArgs.count(strArg))
565         return atoi64(mapArgs[strArg]);
566     return nDefault;
567 }
568
569 bool GetBoolArg(const std::string& strArg, bool fDefault)
570 {
571     if (mapArgs.count(strArg))
572     {
573         if (mapArgs[strArg].empty())
574             return true;
575         return (atoi(mapArgs[strArg]) != 0);
576     }
577     return fDefault;
578 }
579
580 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
581 {
582     if (mapArgs.count(strArg))
583         return false;
584     mapArgs[strArg] = strValue;
585     return true;
586 }
587
588 bool SoftSetBoolArg(const std::string& strArg, bool fValue)
589 {
590     if (fValue)
591         return SoftSetArg(strArg, std::string("1"));
592     else
593         return SoftSetArg(strArg, std::string("0"));
594 }
595
596
597 string EncodeBase64(const unsigned char* pch, size_t len)
598 {
599     static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
600
601     string strRet="";
602     strRet.reserve((len+2)/3*4);
603
604     int mode=0, left=0;
605     const unsigned char *pchEnd = pch+len;
606
607     while (pch<pchEnd)
608     {
609         int enc = *(pch++);
610         switch (mode)
611         {
612             case 0: // we have no bits
613                 strRet += pbase64[enc >> 2];
614                 left = (enc & 3) << 4;
615                 mode = 1;
616                 break;
617
618             case 1: // we have two bits
619                 strRet += pbase64[left | (enc >> 4)];
620                 left = (enc & 15) << 2;
621                 mode = 2;
622                 break;
623
624             case 2: // we have four bits
625                 strRet += pbase64[left | (enc >> 6)];
626                 strRet += pbase64[enc & 63];
627                 mode = 0;
628                 break;
629         }
630     }
631
632     if (mode)
633     {
634         strRet += pbase64[left];
635         strRet += '=';
636         if (mode == 1)
637             strRet += '=';
638     }
639
640     return strRet;
641 }
642
643 string EncodeBase64(const string& str)
644 {
645     return EncodeBase64((const unsigned char*)str.c_str(), str.size());
646 }
647
648 vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
649 {
650     static const int decode64_table[256] =
651     {
652         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
653         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
654         -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
655         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
656         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
657         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
658         49, 50, 51, -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, -1, -1, -1, -1,
661         -1, -1, -1, -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
665     };
666
667     if (pfInvalid)
668         *pfInvalid = false;
669
670     vector<unsigned char> vchRet;
671     vchRet.reserve(strlen(p)*3/4);
672
673     int mode = 0;
674     int left = 0;
675
676     while (1)
677     {
678          int dec = decode64_table[(unsigned char)*p];
679          if (dec == -1) break;
680          p++;
681          switch (mode)
682          {
683              case 0: // we have no bits and get 6
684                  left = dec;
685                  mode = 1;
686                  break;
687
688               case 1: // we have 6 bits and keep 4
689                   vchRet.push_back((left<<2) | (dec>>4));
690                   left = dec & 15;
691                   mode = 2;
692                   break;
693
694              case 2: // we have 4 bits and get 6, we keep 2
695                  vchRet.push_back((left<<4) | (dec>>2));
696                  left = dec & 3;
697                  mode = 3;
698                  break;
699
700              case 3: // we have 2 bits and get 6
701                  vchRet.push_back((left<<6) | dec);
702                  mode = 0;
703                  break;
704          }
705     }
706
707     if (pfInvalid)
708         switch (mode)
709         {
710             case 0: // 4n base64 characters processed: ok
711                 break;
712
713             case 1: // 4n+1 base64 character processed: impossible
714                 *pfInvalid = true;
715                 break;
716
717             case 2: // 4n+2 base64 characters processed: require '=='
718                 if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
719                     *pfInvalid = true;
720                 break;
721
722             case 3: // 4n+3 base64 characters processed: require '='
723                 if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
724                     *pfInvalid = true;
725                 break;
726         }
727
728     return vchRet;
729 }
730
731 string DecodeBase64(const string& str)
732 {
733     vector<unsigned char> vchRet = DecodeBase64(str.c_str());
734     return string((const char*)&vchRet[0], vchRet.size());
735 }
736
737
738 bool WildcardMatch(const char* psz, const char* mask)
739 {
740     loop
741     {
742         switch (*mask)
743         {
744         case '\0':
745             return (*psz == '\0');
746         case '*':
747             return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
748         case '?':
749             if (*psz == '\0')
750                 return false;
751             break;
752         default:
753             if (*psz != *mask)
754                 return false;
755             break;
756         }
757         psz++;
758         mask++;
759     }
760 }
761
762 bool WildcardMatch(const string& str, const string& mask)
763 {
764     return WildcardMatch(str.c_str(), mask.c_str());
765 }
766
767
768
769
770
771
772
773
774 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
775 {
776 #ifdef WIN32
777     char pszModule[MAX_PATH];
778     pszModule[0] = '\0';
779     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
780 #else
781     const char* pszModule = "novacoin";
782 #endif
783     if (pex)
784         snprintf(pszMessage, 1000,
785             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
786     else
787         snprintf(pszMessage, 1000,
788             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
789 }
790
791 void LogException(std::exception* pex, const char* pszThread)
792 {
793     char pszMessage[10000];
794     FormatException(pszMessage, pex, pszThread);
795     printf("\n%s", pszMessage);
796 }
797
798 void PrintException(std::exception* pex, const char* pszThread)
799 {
800     char pszMessage[10000];
801     FormatException(pszMessage, pex, pszThread);
802     printf("\n\n************************\n%s\n", pszMessage);
803     fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
804     strMiscWarning = pszMessage;
805     throw;
806 }
807
808 void LogStackTrace() {
809     printf("\n\n******* exception encountered *******\n");
810     if (fileout)
811     {
812 #ifndef WIN32
813         void* pszBuffer[32];
814         size_t size;
815         size = backtrace(pszBuffer, 32);
816         backtrace_symbols_fd(pszBuffer, size, fileno(fileout));
817 #endif
818     }
819 }
820
821 void PrintExceptionContinue(std::exception* pex, const char* pszThread)
822 {
823     char pszMessage[10000];
824     FormatException(pszMessage, pex, pszThread);
825     printf("\n\n************************\n%s\n", pszMessage);
826     fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
827     strMiscWarning = pszMessage;
828 }
829
830 #ifdef WIN32
831 boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate)
832 {
833     namespace fs = boost::filesystem;
834
835     char pszPath[MAX_PATH] = "";
836     if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
837     {
838         return fs::path(pszPath);
839     }
840     else if (nFolder == CSIDL_STARTUP)
841     {
842         return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup";
843     }
844     else if (nFolder == CSIDL_APPDATA)
845     {
846         return fs::path(getenv("APPDATA"));
847     }
848     return fs::path("");
849 }
850 #endif
851
852 boost::filesystem::path GetDefaultDataDir()
853 {
854     namespace fs = boost::filesystem;
855
856     // Windows: C:\Documents and Settings\username\Application Data\NovaCoin
857     // Mac: ~/Library/Application Support/NovaCoin
858     // Unix: ~/.novacoin
859 #ifdef WIN32
860     // Windows
861     return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "NovaCoin";
862 #else
863     fs::path pathRet;
864     char* pszHome = getenv("HOME");
865     if (pszHome == NULL || strlen(pszHome) == 0)
866         pathRet = fs::path("/");
867     else
868         pathRet = fs::path(pszHome);
869 #ifdef MAC_OSX
870     // Mac
871     pathRet /= "Library/Application Support";
872     fs::create_directory(pathRet);
873     return pathRet / "NovaCoin";
874 #else
875     // Unix
876     return pathRet / ".novacoin";
877 #endif
878 #endif
879 }
880
881 const boost::filesystem::path &GetDataDir(bool fNetSpecific)
882 {
883     namespace fs = boost::filesystem;
884
885     static fs::path pathCached[2];
886     static CCriticalSection csPathCached;
887     static bool cachedPath[2] = {false, false};
888
889     fs::path &path = pathCached[fNetSpecific];
890
891     // This can be called during exceptions by printf, so we cache the
892     // value so we don't have to do memory allocations after that.
893     if (cachedPath[fNetSpecific])
894         return path;
895
896     LOCK(csPathCached);
897
898     if (mapArgs.count("-datadir")) {
899         path = fs::system_complete(mapArgs["-datadir"]);
900         if (!fs::is_directory(path)) {
901             path = "";
902             return path;
903         }
904     } else {
905         path = GetDefaultDataDir();
906     }
907     if (fNetSpecific && GetBoolArg("-testnet", false))
908         path /= "testnet";
909
910     fs::create_directory(path);
911
912     cachedPath[fNetSpecific]=true;
913     return path;
914 }
915
916 boost::filesystem::path GetConfigFile()
917 {
918     namespace fs = boost::filesystem;
919
920     fs::path pathConfigFile(GetArg("-conf", "novacoin.conf"));
921     if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
922     return pathConfigFile;
923 }
924
925 void ReadConfigFile(map<string, string>& mapSettingsRet,
926                     map<string, vector<string> >& mapMultiSettingsRet)
927 {
928     namespace fs = boost::filesystem;
929     namespace pod = boost::program_options::detail;
930
931     fs::ifstream streamConfig(GetConfigFile());
932     if (!streamConfig.good())
933         return; // No bitcoin.conf file is OK
934
935     set<string> setOptions;
936     setOptions.insert("*");
937
938     for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
939     {
940         // Don't overwrite existing settings so command line settings override bitcoin.conf
941         string strKey = string("-") + it->string_key;
942         if (mapSettingsRet.count(strKey) == 0)
943         {
944             mapSettingsRet[strKey] = it->value[0];
945             //  interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
946             InterpretNegativeSetting(strKey, mapSettingsRet);
947         }
948         mapMultiSettingsRet[strKey].push_back(it->value[0]);
949     }
950 }
951
952 boost::filesystem::path GetPidFile()
953 {
954     namespace fs = boost::filesystem;
955
956     fs::path pathPidFile(GetArg("-pid", "novacoind.pid"));
957     if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
958     return pathPidFile;
959 }
960
961 void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
962 {
963     FILE* file = fopen(path.string().c_str(), "w");
964     if (file)
965     {
966         fprintf(file, "%d\n", pid);
967         fclose(file);
968     }
969 }
970
971 int GetFilesize(FILE* file)
972 {
973     int nSavePos = ftell(file);
974     int nFilesize = -1;
975     if (fseek(file, 0, SEEK_END) == 0)
976         nFilesize = ftell(file);
977     fseek(file, nSavePos, SEEK_SET);
978     return nFilesize;
979 }
980
981 void ShrinkDebugFile()
982 {
983     // Scroll debug.log if it's getting too big
984     boost::filesystem::path pathLog = GetDataDir() / "debug.log";
985     FILE* file = fopen(pathLog.string().c_str(), "r");
986     if (file && GetFilesize(file) > 10 * 1000000)
987     {
988         // Restart the file with some of the end
989         char pch[200000];
990         fseek(file, -sizeof(pch), SEEK_END);
991         int nBytes = fread(pch, 1, sizeof(pch), file);
992         fclose(file);
993
994         file = fopen(pathLog.string().c_str(), "w");
995         if (file)
996         {
997             fwrite(pch, 1, nBytes, file);
998             fclose(file);
999         }
1000     }
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010 //
1011 // "Never go to sea with two chronometers; take one or three."
1012 // Our three time sources are:
1013 //  - System clock
1014 //  - Median of other nodes's clocks
1015 //  - The user (asking the user to fix the system clock if the first two disagree)
1016 //
1017 static int64 nMockTime = 0;  // For unit testing
1018
1019 int64 GetTime()
1020 {
1021     if (nMockTime) return nMockTime;
1022
1023     return time(NULL);
1024 }
1025
1026 void SetMockTime(int64 nMockTimeIn)
1027 {
1028     nMockTime = nMockTimeIn;
1029 }
1030
1031 static int64 nTimeOffset = 0;
1032
1033 int64 GetAdjustedTime()
1034 {
1035     return GetTime() + nTimeOffset;
1036 }
1037
1038 void AddTimeData(const CNetAddr& ip, int64 nTime)
1039 {
1040     int64 nOffsetSample = nTime - GetTime();
1041
1042     // Ignore duplicates
1043     static set<CNetAddr> setKnown;
1044     if (!setKnown.insert(ip).second)
1045         return;
1046
1047     // Add data
1048     vTimeOffsets.input(nOffsetSample);
1049     printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
1050     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
1051     {
1052         int64 nMedian = vTimeOffsets.median();
1053         std::vector<int64> vSorted = vTimeOffsets.sorted();
1054         // Only let other nodes change our time by so much
1055         if (abs64(nMedian) < 70 * 60)
1056         {
1057             nTimeOffset = nMedian;
1058         }
1059         else
1060         {
1061             nTimeOffset = 0;
1062
1063             static bool fDone;
1064             if (!fDone)
1065             {
1066                 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
1067                 bool fMatch = false;
1068                 BOOST_FOREACH(int64 nOffset, vSorted)
1069                     if (nOffset != 0 && abs64(nOffset) < 5 * 60)
1070                         fMatch = true;
1071
1072                 if (!fMatch)
1073                 {
1074                     fDone = true;
1075                     string strMessage = _("Warning: Please check that your computer's date and time are correct.  If your clock is wrong NovaCoin will not work properly.");
1076                     strMiscWarning = strMessage;
1077                     printf("*** %s\n", strMessage.c_str());
1078                     ThreadSafeMessageBox(strMessage+" ", string("NovaCoin"), wxOK | wxICON_EXCLAMATION);
1079                 }
1080             }
1081         }
1082         if (fDebug) {
1083             BOOST_FOREACH(int64 n, vSorted)
1084                 printf("%+"PRI64d"  ", n);
1085             printf("|  ");
1086         }
1087         printf("nTimeOffset = %+"PRI64d"  (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
1088     }
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098 string FormatVersion(int nVersion)
1099 {
1100     if (nVersion%100 == 0)
1101         return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
1102     else
1103         return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
1104 }
1105
1106 string FormatFullVersion()
1107 {
1108     return CLIENT_BUILD;
1109 }
1110
1111 // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
1112 std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
1113 {
1114     std::ostringstream ss;
1115     ss << "/";
1116     ss << name << ":" << FormatVersion(nClientVersion);
1117     if (!comments.empty())
1118         ss << "(" << boost::algorithm::join(comments, "; ") << ")";
1119     ss << "/";
1120     return ss.str();
1121 }
1122
1123 #ifdef WIN32
1124 boost::filesystem::path static StartupShortcutPath()
1125 {
1126     return MyGetSpecialFolderPath(CSIDL_STARTUP, true) / "NovaCoin.lnk";
1127 }
1128
1129 bool GetStartOnSystemStartup()
1130 {
1131     return filesystem::exists(StartupShortcutPath());
1132 }
1133
1134 bool SetStartOnSystemStartup(bool fAutoStart)
1135 {
1136     // If the shortcut exists already, remove it for updating
1137     boost::filesystem::remove(StartupShortcutPath());
1138
1139     if (fAutoStart)
1140     {
1141         CoInitialize(NULL);
1142
1143         // Get a pointer to the IShellLink interface.
1144         IShellLink* psl = NULL;
1145         HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
1146                                 CLSCTX_INPROC_SERVER, IID_IShellLink,
1147                                 reinterpret_cast<void**>(&psl));
1148
1149         if (SUCCEEDED(hres))
1150         {
1151             // Get the current executable path
1152             TCHAR pszExePath[MAX_PATH];
1153             GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
1154
1155             TCHAR pszArgs[5] = TEXT("-min");
1156
1157             // Set the path to the shortcut target
1158             psl->SetPath(pszExePath);
1159             PathRemoveFileSpec(pszExePath);
1160             psl->SetWorkingDirectory(pszExePath);
1161             psl->SetShowCmd(SW_SHOWMINNOACTIVE);
1162             psl->SetArguments(pszArgs);
1163
1164             // Query IShellLink for the IPersistFile interface for
1165             // saving the shortcut in persistent storage.
1166             IPersistFile* ppf = NULL;
1167             hres = psl->QueryInterface(IID_IPersistFile,
1168                                        reinterpret_cast<void**>(&ppf));
1169             if (SUCCEEDED(hres))
1170             {
1171                 WCHAR pwsz[MAX_PATH];
1172                 // Ensure that the string is ANSI.
1173                 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
1174                 // Save the link by calling IPersistFile::Save.
1175                 hres = ppf->Save(pwsz, TRUE);
1176                 ppf->Release();
1177                 psl->Release();
1178                 CoUninitialize();
1179                 return true;
1180             }
1181             psl->Release();
1182         }
1183         CoUninitialize();
1184         return false;
1185     }
1186     return true;
1187 }
1188
1189 #elif defined(LINUX)
1190
1191 // Follow the Desktop Application Autostart Spec:
1192 //  http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
1193
1194 boost::filesystem::path static GetAutostartDir()
1195 {
1196     namespace fs = boost::filesystem;
1197
1198     char* pszConfigHome = getenv("XDG_CONFIG_HOME");
1199     if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
1200     char* pszHome = getenv("HOME");
1201     if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
1202     return fs::path();
1203 }
1204
1205 boost::filesystem::path static GetAutostartFilePath()
1206 {
1207     return GetAutostartDir() / "novacoin.desktop";
1208 }
1209
1210 bool GetStartOnSystemStartup()
1211 {
1212     boost::filesystem::ifstream optionFile(GetAutostartFilePath());
1213     if (!optionFile.good())
1214         return false;
1215     // Scan through file for "Hidden=true":
1216     string line;
1217     while (!optionFile.eof())
1218     {
1219         getline(optionFile, line);
1220         if (line.find("Hidden") != string::npos &&
1221             line.find("true") != string::npos)
1222             return false;
1223     }
1224     optionFile.close();
1225
1226     return true;
1227 }
1228
1229 bool SetStartOnSystemStartup(bool fAutoStart)
1230 {
1231     if (!fAutoStart)
1232         boost::filesystem::remove(GetAutostartFilePath());
1233     else
1234     {
1235         char pszExePath[MAX_PATH+1];
1236         memset(pszExePath, 0, sizeof(pszExePath));
1237         if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
1238             return false;
1239
1240         boost::filesystem::create_directories(GetAutostartDir());
1241
1242         boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
1243         if (!optionFile.good())
1244             return false;
1245         // Write a bitcoin.desktop file to the autostart directory:
1246         optionFile << "[Desktop Entry]\n";
1247         optionFile << "Type=Application\n";
1248         optionFile << "Name=NovaCoin\n";
1249         optionFile << "Exec=" << pszExePath << " -min\n";
1250         optionFile << "Terminal=false\n";
1251         optionFile << "Hidden=false\n";
1252         optionFile.close();
1253     }
1254     return true;
1255 }
1256 #else
1257
1258 // TODO: OSX startup stuff; see:
1259 // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
1260
1261 bool GetStartOnSystemStartup() { return false; }
1262 bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
1263
1264 #endif
1265
1266
1267
1268 #ifdef DEBUG_LOCKORDER
1269 //
1270 // Early deadlock detection.
1271 // Problem being solved:
1272 //    Thread 1 locks  A, then B, then C
1273 //    Thread 2 locks  D, then C, then A
1274 //     --> may result in deadlock between the two threads, depending on when they run.
1275 // Solution implemented here:
1276 // Keep track of pairs of locks: (A before B), (A before C), etc.
1277 // Complain if any thread trys to lock in a different order.
1278 //
1279
1280 struct CLockLocation
1281 {
1282     CLockLocation(const char* pszName, const char* pszFile, int nLine)
1283     {
1284         mutexName = pszName;
1285         sourceFile = pszFile;
1286         sourceLine = nLine;
1287     }
1288
1289     std::string ToString() const
1290     {
1291         return mutexName+"  "+sourceFile+":"+itostr(sourceLine);
1292     }
1293
1294 private:
1295     std::string mutexName;
1296     std::string sourceFile;
1297     int sourceLine;
1298 };
1299
1300 typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
1301
1302 static boost::interprocess::interprocess_mutex dd_mutex;
1303 static std::map<std::pair<void*, void*>, LockStack> lockorders;
1304 static boost::thread_specific_ptr<LockStack> lockstack;
1305
1306
1307 static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
1308 {
1309     printf("POTENTIAL DEADLOCK DETECTED\n");
1310     printf("Previous lock order was:\n");
1311     BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
1312     {
1313         if (i.first == mismatch.first) printf(" (1)");
1314         if (i.first == mismatch.second) printf(" (2)");
1315         printf(" %s\n", i.second.ToString().c_str());
1316     }
1317     printf("Current lock order is:\n");
1318     BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
1319     {
1320         if (i.first == mismatch.first) printf(" (1)");
1321         if (i.first == mismatch.second) printf(" (2)");
1322         printf(" %s\n", i.second.ToString().c_str());
1323     }
1324 }
1325
1326 static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
1327 {
1328     bool fOrderOK = true;
1329     if (lockstack.get() == NULL)
1330         lockstack.reset(new LockStack);
1331
1332     if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
1333     dd_mutex.lock();
1334
1335     (*lockstack).push_back(std::make_pair(c, locklocation));
1336
1337     if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
1338     {
1339         if (i.first == c) break;
1340
1341         std::pair<void*, void*> p1 = std::make_pair(i.first, c);
1342         if (lockorders.count(p1))
1343             continue;
1344         lockorders[p1] = (*lockstack);
1345
1346         std::pair<void*, void*> p2 = std::make_pair(c, i.first);
1347         if (lockorders.count(p2))
1348         {
1349             potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
1350             break;
1351         }
1352     }
1353     dd_mutex.unlock();
1354 }
1355
1356 static void pop_lock()
1357 {
1358     if (fDebug) 
1359     {
1360         const CLockLocation& locklocation = (*lockstack).rbegin()->second;
1361         printf("Unlocked: %s\n", locklocation.ToString().c_str());
1362     }
1363     dd_mutex.lock();
1364     (*lockstack).pop_back();
1365     dd_mutex.unlock();
1366 }
1367
1368 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
1369 {
1370     push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
1371 }
1372
1373 void LeaveCritical()
1374 {
1375     pop_lock();
1376 }
1377
1378 #endif /* DEBUG_LOCKORDER */