aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro16
-rw-r--r--contrib/debian/control3
-rw-r--r--contrib/debian/copyright2
-rwxr-xr-xcontrib/debian/rules2
-rw-r--r--contrib/gitian-descriptors/deps-win32.yml2
-rw-r--r--contrib/gitian-descriptors/gitian.yml10
-rw-r--r--doc/assets-attribution.txt2
-rw-r--r--src/bitcoinrpc.cpp54
-rw-r--r--src/db.cpp16
-rw-r--r--src/init.cpp11
-rw-r--r--src/main.cpp38
-rw-r--r--src/main.h1
-rw-r--r--src/makefile.unix4
-rw-r--r--src/net.cpp119
-rw-r--r--src/net.h22
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/qt/bitcoin.cpp6
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/bitcoingui.cpp22
-rw-r--r--src/qt/bitcoingui.h3
-rw-r--r--src/qt/guiutil.cpp22
-rw-r--r--src/qt/guiutil.h3
-rw-r--r--src/qt/messagepage.cpp12
-rw-r--r--src/qt/qtipcserver.cpp22
-rw-r--r--src/qt/res/icons/filesave.pngbin0 -> 1741 bytes
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.h2
-rw-r--r--src/qt/test/urltests.cpp23
-rw-r--r--src/qt/walletmodel.cpp6
-rw-r--r--src/qt/walletmodel.h2
-rw-r--r--src/util.cpp32
-rw-r--r--src/util.h6
32 files changed, 286 insertions, 182 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index e2097fd4b0..933f4a70da 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -19,14 +19,6 @@ OBJECTS_DIR = build
MOC_DIR = build
UI_DIR = build
-# use: qmake "USE_QRCODE=1"
-# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
-contains(USE_QRCODE, 1) {
- message(Building with QRCode support)
- DEFINES += USE_QRCODE
- LIBS += -lqrencode
-}
-
# use: qmake "RELEASE=1"
contains(RELEASE, 1) {
# Mac: compile for maximum compatibility (10.5, 32-bit)
@@ -38,6 +30,14 @@ contains(RELEASE, 1) {
}
}
+# use: qmake "USE_QRCODE=1"
+# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
+contains(USE_QRCODE, 1) {
+ message(Building with QRCode support)
+ DEFINES += USE_QRCODE
+ LIBS += -lqrencode
+}
+
# use: qmake "USE_UPNP=1" ( enabled by default; default)
# or: qmake "USE_UPNP=0" (disabled by default)
# or: qmake "USE_UPNP=-" (not supported)
diff --git a/contrib/debian/control b/contrib/debian/control
index c41664ca6f..745fd71ea8 100644
--- a/contrib/debian/control
+++ b/contrib/debian/control
@@ -15,7 +15,8 @@ Build-Depends: debhelper,
libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev,
libboost-test-dev (>> 1.35) | libboost-test1.35-dev,
qt4-qmake,
- libqt4-dev
+ libqt4-dev,
+ libqrencode-dev
Standards-Version: 3.9.2
Homepage: http://www.bitcoin.org/
Vcs-Git: git://github.com/bitcoin/bitcoin.git
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
index 5db418df3a..71fa77cf6c 100644
--- a/contrib/debian/copyright
+++ b/contrib/debian/copyright
@@ -37,7 +37,7 @@ Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
src/qt/res/icons/history.png, src/qt/res/icons/key.png,
src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
- src/qt/res/icons/synced.png
+ src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png
Copyright: David Vignoni (david@icon-king.com)
ICON KING - www.icon-king.com
License: LGPL
diff --git a/contrib/debian/rules b/contrib/debian/rules
index a1d65652e3..6d6f119b59 100755
--- a/contrib/debian/rules
+++ b/contrib/debian/rules
@@ -20,7 +20,7 @@ override_dh_auto_clean:
cd src; $(MAKE) -f makefile.unix clean
override_dh_auto_configure:
- qmake bitcoin-qt.pro
+ qmake bitcoin-qt.pro USE_SSL=1 USE_QRCODE=1
override_dh_auto_test:
cd src; $(MAKE) -f makefile.unix test_bitcoin
diff --git a/contrib/gitian-descriptors/deps-win32.yml b/contrib/gitian-descriptors/deps-win32.yml
index 4485f3658f..0107b306ec 100644
--- a/contrib/gitian-descriptors/deps-win32.yml
+++ b/contrib/gitian-descriptors/deps-win32.yml
@@ -59,5 +59,3 @@ script: |
cd ..
#
tar cjvpf "$OUTDIR/bitcoin-deps-0.0.1.tbz2" "$HOME/build"
-
-
diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml
index 8a0ee0e038..086e09743d 100644
--- a/contrib/gitian-descriptors/gitian.yml
+++ b/contrib/gitian-descriptors/gitian.yml
@@ -16,13 +16,15 @@ packages:
- "libssl-dev"
- "git-core"
- "unzip"
-- "libqrencode-dev"
+- "pkg-config"
+- "libpng12-dev"
reference_datetime: "2011-01-30 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
"dir": "bitcoin"
files:
- "miniupnpc-1.6.tar.gz"
+- "qrencode-3.2.0.tar.bz2"
script: |
INSTDIR="$HOME/install"
export LIBRARY_PATH="$INSTDIR/lib"
@@ -32,6 +34,12 @@ script: |
INSTALLPREFIX=$INSTDIR make $MAKEOPTS install
cd ..
#
+ tar xjf qrencode-3.2.0.tar.bz2
+ cd qrencode-3.2.0
+ ./configure --prefix=$INSTDIR --enable-static --disable-shared
+ make $MAKEOPTS install
+ cd ..
+ #
cd bitcoin
mkdir -p $OUTDIR/src
cp -a . $OUTDIR/src
diff --git a/doc/assets-attribution.txt b/doc/assets-attribution.txt
index 5cf0a734bf..fabcdeea76 100644
--- a/doc/assets-attribution.txt
+++ b/doc/assets-attribution.txt
@@ -7,7 +7,7 @@ Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
src/qt/res/icons/history.png, src/qt/res/icons/key.png,
src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
- src/qt/res/icons/synced.png
+ src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png
Icon Pack: NUVOLA ICON THEME for KDE 3.x
Designer: David Vignoni (david@icon-king.com)
ICON KING - www.icon-king.com
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 5d38f042f9..be40e937b8 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -353,7 +353,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
if (pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
+ obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
return obj;
}
@@ -1537,35 +1537,41 @@ void ThreadTopUpKeyPool(void* parg)
void ThreadCleanWalletPassphrase(void* parg)
{
- int64 nMyWakeTime = GetTime() + *((int*)parg);
+ int64 nMyWakeTime = GetTimeMillis() + *((int*)parg) * 1000;
+
+ ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
if (nWalletUnlockTime == 0)
{
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
+ nWalletUnlockTime = nMyWakeTime;
+
+ do
{
- nWalletUnlockTime = nMyWakeTime;
- }
+ if (nWalletUnlockTime==0)
+ break;
+ int64 nToSleep = nWalletUnlockTime - GetTimeMillis();
+ if (nToSleep <= 0)
+ break;
+
+ LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
+ Sleep(nToSleep);
+ ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
- while (GetTime() < nWalletUnlockTime)
- Sleep(GetTime() - nWalletUnlockTime);
+ } while(1);
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
+ if (nWalletUnlockTime)
{
nWalletUnlockTime = 0;
+ pwalletMain->Lock();
}
}
else
{
- CRITICAL_BLOCK(cs_nWalletUnlockTime)
- {
- if (nWalletUnlockTime < nMyWakeTime)
- nWalletUnlockTime = nMyWakeTime;
- }
- delete (int*)parg;
- return;
+ if (nWalletUnlockTime < nMyWakeTime)
+ nWalletUnlockTime = nMyWakeTime;
}
- pwalletMain->Lock();
+ LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
delete (int*)parg;
}
@@ -1655,9 +1661,9 @@ Value walletlock(const Array& params, bool fHelp)
if (!pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an unencrypted wallet, but walletlock was called.");
- pwalletMain->Lock();
CRITICAL_BLOCK(cs_nWalletUnlockTime)
{
+ pwalletMain->Lock();
nWalletUnlockTime = 0;
}
@@ -1810,7 +1816,7 @@ Value getwork(const Array& params, bool fHelp)
}
// Update nTime
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->UpdateTime(pindexPrev);
pblock->nNonce = 0;
// Update nExtraNonce
@@ -1910,7 +1916,7 @@ Value getmemorypool(const Array& params, bool fHelp)
}
// Update nTime
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->UpdateTime(pindexPrev);
pblock->nNonce = 0;
Array transactions;
@@ -2349,15 +2355,15 @@ void ThreadRPCServer(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
try
{
- vnThreadsRunning[4]++;
+ vnThreadsRunning[THREAD_RPCSERVER]++;
ThreadRPCServer2(parg);
- vnThreadsRunning[4]--;
+ vnThreadsRunning[THREAD_RPCSERVER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[4]--;
+ vnThreadsRunning[THREAD_RPCSERVER]--;
PrintException(&e, "ThreadRPCServer()");
} catch (...) {
- vnThreadsRunning[4]--;
+ vnThreadsRunning[THREAD_RPCSERVER]--;
PrintException(NULL, "ThreadRPCServer()");
}
printf("ThreadRPCServer exiting\n");
@@ -2437,7 +2443,7 @@ void ThreadRPCServer2(void* parg)
#endif
ip::tcp::endpoint peer;
- vnThreadsRunning[4]--;
+ vnThreadsRunning[THREAD_RPCSERVER]--;
#ifdef USE_SSL
acceptor.accept(sslStream.lowest_layer(), peer);
#else
diff --git a/src/db.cpp b/src/db.cpp
index 3bdda61569..9a904ec2e0 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -6,6 +6,7 @@
#include "headers.h"
#include "db.h"
#include "net.h"
+#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -1064,14 +1065,19 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
filesystem::path pathDest(strDest);
if (filesystem::is_directory(pathDest))
pathDest = pathDest / wallet.strWalletFile;
+
+ try {
#if BOOST_VERSION >= 104000
- filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
+ filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
#else
- filesystem::copy_file(pathSrc, pathDest);
+ filesystem::copy_file(pathSrc, pathDest);
#endif
- printf("copied wallet.dat to %s\n", pathDest.string().c_str());
-
- return true;
+ printf("copied wallet.dat to %s\n", pathDest.string().c_str());
+ return true;
+ } catch(const filesystem::filesystem_error &e) {
+ printf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what());
+ return false;
+ }
}
}
Sleep(100);
diff --git a/src/init.cpp b/src/init.cpp
index 22f34aa755..2adfed2ebb 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -197,6 +197,9 @@ bool AppInit2(int argc, char* argv[])
" -connect=<ip> \t\t " + _("Connect only to the specified node") + "\n" +
" -irc \t " + _("Find peers using internet relay chat (default: 0)") + "\n" +
" -listen \t " + _("Accept connections from outside (default: 1)") + "\n" +
+#ifdef QT_GUI
+ " -lang=<lang> \t\t " + _("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
+#endif
" -dnsseed \t " + _("Find peers using DNS lookup (default: 1)") + "\n" +
" -banscore=<n> \t " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n" +
" -bantime=<n> \t " + _("Number of seconds to keep misbehaving peers from reconnecting (default: 86400)") + "\n" +
@@ -210,10 +213,10 @@ bool AppInit2(int argc, char* argv[])
#endif
#endif
" -paytxfee=<amt> \t " + _("Fee per KB to add to transactions you send") + "\n" +
-#ifdef GUI
+#ifdef QT_GUI
" -server \t\t " + _("Accept command line and JSON-RPC commands") + "\n" +
#endif
-#ifndef WIN32
+#if !defined(WIN32) && !defined(QT_GUI)
" -daemon \t\t " + _("Run in the background as a daemon and accept commands") + "\n" +
#endif
" -testnet \t\t " + _("Use the test network") + "\n" +
@@ -253,7 +256,7 @@ bool AppInit2(int argc, char* argv[])
fTestNet = GetBoolArg("-testnet");
fDebug = GetBoolArg("-debug");
-#ifndef WIN32
+#if !defined(WIN32) && !defined(QT_GUI)
fDaemon = GetBoolArg("-daemon");
#else
fDaemon = false;
@@ -284,7 +287,7 @@ bool AppInit2(int argc, char* argv[])
}
#endif
-#ifndef WIN32
+#if !defined(WIN32) && !defined(QT_GUI)
if (fDaemon)
{
// Daemonize
diff --git a/src/main.cpp b/src/main.cpp
index e4c6714eae..b73037fb6a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -922,6 +922,15 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
}
+void CBlock::UpdateTime(const CBlockIndex* pindexPrev)
+{
+ nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+
+ // Updating time can change work required on testnet:
+ if (fTestNet)
+ nBits = GetNextWorkRequired(pindexPrev, this);
+}
+
@@ -3168,7 +3177,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->UpdateTime(pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get());
pblock->nNonce = 0;
@@ -3326,6 +3335,7 @@ void static BitcoinMiner(CWallet *pwallet)
FormatHashBuffers(pblock.get(), pmidstate, pdata, phash1);
unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
+ unsigned int& nBlockBits = *(unsigned int*)(pdata + 64 + 8);
unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
@@ -3390,7 +3400,7 @@ void static BitcoinMiner(CWallet *pwallet)
{
nLogTime = GetTime();
printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
- printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[3], dHashesPerSec/1000.0);
+ printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0);
}
}
}
@@ -3401,7 +3411,7 @@ void static BitcoinMiner(CWallet *pwallet)
return;
if (!fGenerateBitcoins)
return;
- if (fLimitProcessors && vnThreadsRunning[3] > nLimitProcessors)
+ if (fLimitProcessors && vnThreadsRunning[THREAD_MINER] > nLimitProcessors)
return;
if (vNodes.empty())
break;
@@ -3413,8 +3423,14 @@ void static BitcoinMiner(CWallet *pwallet)
break;
// Update nTime every few seconds
- pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
+ pblock->UpdateTime(pindexPrev);
nBlockTime = ByteReverse(pblock->nTime);
+ if (fTestNet)
+ {
+ // Changing pblock->nTime can change work required on testnet:
+ nBlockBits = ByteReverse(pblock->nBits);
+ hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+ }
}
}
}
@@ -3424,22 +3440,22 @@ void static ThreadBitcoinMiner(void* parg)
CWallet* pwallet = (CWallet*)parg;
try
{
- vnThreadsRunning[3]++;
+ vnThreadsRunning[THREAD_MINER]++;
BitcoinMiner(pwallet);
- vnThreadsRunning[3]--;
+ vnThreadsRunning[THREAD_MINER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[3]--;
+ vnThreadsRunning[THREAD_MINER]--;
PrintException(&e, "ThreadBitcoinMiner()");
} catch (...) {
- vnThreadsRunning[3]--;
+ vnThreadsRunning[THREAD_MINER]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
nHPSTimerStart = 0;
- if (vnThreadsRunning[3] == 0)
+ if (vnThreadsRunning[THREAD_MINER] == 0)
dHashesPerSec = 0;
- printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
+ printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINER]);
}
@@ -3459,7 +3475,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
nProcessors = 1;
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
- int nAddThreads = nProcessors - vnThreadsRunning[3];
+ int nAddThreads = nProcessors - vnThreadsRunning[THREAD_MINER];
printf("Starting %d BitcoinMiner threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
{
diff --git a/src/main.h b/src/main.h
index 908ada7d4f..d9f976c217 100644
--- a/src/main.h
+++ b/src/main.h
@@ -913,6 +913,7 @@ public:
return (int64)nTime;
}
+ void UpdateTime(const CBlockIndex* pindexPrev);
uint256 BuildMerkleTree() const
diff --git a/src/makefile.unix b/src/makefile.unix
index 41452dec81..80b5bca341 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -7,7 +7,7 @@ USE_UPNP:=0
DEFS=-DNOPCH
DEFS += $(addprefix -I,$(CURDIR) $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH))
-LIBS += $(addprefix -l,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
+LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
LMODE = dynamic
LMODE2 = dynamic
@@ -21,7 +21,7 @@ else
endif
# for boost 1.37, add -mt to the boost libraries
-LIBS= \
+LIBS += \
-Wl,-B$(LMODE) \
-l boost_system$(BOOST_LIB_SUFFIX) \
-l boost_filesystem$(BOOST_LIB_SUFFIX) \
diff --git a/src/net.cpp b/src/net.cpp
index 63829d0e0a..fd488ce671 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -38,8 +38,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect);
-
-
//
// Global state variables
//
@@ -49,7 +47,7 @@ uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
CAddress addrLocalHost(CService("0.0.0.0", 0), nLocalServices);
static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
-array<int, 10> vnThreadsRunning;
+array<int, THREAD_MAX> vnThreadsRunning;
static SOCKET hListenSocket = INVALID_SOCKET;
vector<CNode*> vNodes;
@@ -67,7 +65,6 @@ CCriticalSection cs_setservAddNodeAddresses;
-
unsigned short GetListenPort()
{
return (unsigned short)(GetArg("-port", GetDefaultPort()));
@@ -602,15 +599,15 @@ void ThreadSocketHandler(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
try
{
- vnThreadsRunning[0]++;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]++;
ThreadSocketHandler2(parg);
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
PrintException(&e, "ThreadSocketHandler()");
} catch (...) {
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
throw; // support pthread_cancel()
}
printf("ThreadSocketHandler exiting\n");
@@ -712,9 +709,9 @@ void ThreadSocketHandler2(void* parg)
}
}
- vnThreadsRunning[0]--;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]--;
int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
- vnThreadsRunning[0]++;
+ vnThreadsRunning[THREAD_SOCKETHANDLER]++;
if (fShutdown)
return;
if (nSelect == SOCKET_ERROR)
@@ -740,13 +737,17 @@ void ThreadSocketHandler2(void* parg)
struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr);
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
- CAddress addr(sockaddr);
+ CAddress addr;
int nInbound = 0;
+ if (hSocket != INVALID_SOCKET)
+ addr = CAddress(sockaddr);
+
CRITICAL_BLOCK(cs_vNodes)
BOOST_FOREACH(CNode* pnode, vNodes)
if (pnode->fInbound)
nInbound++;
+
if (hSocket == INVALID_SOCKET)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
@@ -923,15 +924,15 @@ void ThreadMapPort(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
try
{
- vnThreadsRunning[5]++;
+ vnThreadsRunning[THREAD_UPNP]++;
ThreadMapPort2(parg);
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
}
catch (std::exception& e) {
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
PrintException(&e, "ThreadMapPort()");
} catch (...) {
- vnThreadsRunning[5]--;
+ vnThreadsRunning[THREAD_UPNP]--;
PrintException(NULL, "ThreadMapPort()");
}
printf("ThreadMapPort exiting\n");
@@ -1052,7 +1053,7 @@ void MapPort(bool fMapPort)
fUseUPnP = fMapPort;
WriteSetting("fUseUPnP", fUseUPnP);
}
- if (fUseUPnP && vnThreadsRunning[5] < 1)
+ if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
{
if (!CreateThread(ThreadMapPort, NULL))
printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
@@ -1086,15 +1087,15 @@ void ThreadDNSAddressSeed(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg));
try
{
- vnThreadsRunning[6]++;
+ vnThreadsRunning[THREAD_DNSSEED]++;
ThreadDNSAddressSeed2(parg);
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
}
catch (std::exception& e) {
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
PrintException(&e, "ThreadDNSAddressSeed()");
} catch (...) {
- vnThreadsRunning[6]--;
+ vnThreadsRunning[THREAD_DNSSEED]--;
throw; // support pthread_cancel()
}
printf("ThreadDNSAddressSeed exiting\n");
@@ -1232,15 +1233,15 @@ void ThreadOpenConnections(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
try
{
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
ThreadOpenConnections2(parg);
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
}
catch (std::exception& e) {
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
PrintException(&e, "ThreadOpenConnections()");
} catch (...) {
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
PrintException(NULL, "ThreadOpenConnections()");
}
printf("ThreadOpenConnections exiting\n");
@@ -1274,9 +1275,13 @@ void ThreadOpenConnections2(void* parg)
int64 nStart = GetTime();
loop
{
- // Limit outbound connections
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(500);
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
+ if (fShutdown)
+ return;
+
+ // Limit outbound connections
loop
{
int nOutbound = 0;
@@ -1288,13 +1293,12 @@ void ThreadOpenConnections2(void* parg)
nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
if (nOutbound < nMaxOutboundConnections)
break;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
Sleep(2000);
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return;
}
- vnThreadsRunning[1]++;
- if (fShutdown)
- return;
bool fAddSeeds = false;
@@ -1403,15 +1407,15 @@ void ThreadOpenAddedConnections(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg));
try
{
- vnThreadsRunning[7]++;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
ThreadOpenAddedConnections2(parg);
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
}
catch (std::exception& e) {
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
PrintException(&e, "ThreadOpenAddedConnections()");
} catch (...) {
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
PrintException(NULL, "ThreadOpenAddedConnections()");
}
printf("ThreadOpenAddedConnections exiting\n");
@@ -1460,9 +1464,9 @@ void ThreadOpenAddedConnections2(void* parg)
}
if (fShutdown)
return;
- vnThreadsRunning[7]--;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
Sleep(120000); // Retry every 2 minutes
- vnThreadsRunning[7]++;
+ vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
if (fShutdown)
return;
}
@@ -1479,9 +1483,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect))
return false;
- vnThreadsRunning[1]--;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
CNode* pnode = ConnectNode(addrConnect);
- vnThreadsRunning[1]++;
+ vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
if (fShutdown)
return false;
if (!pnode)
@@ -1503,15 +1507,15 @@ void ThreadMessageHandler(void* parg)
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
try
{
- vnThreadsRunning[2]++;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
ThreadMessageHandler2(parg);
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
}
catch (std::exception& e) {
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
PrintException(&e, "ThreadMessageHandler()");
} catch (...) {
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
PrintException(NULL, "ThreadMessageHandler()");
}
printf("ThreadMessageHandler exiting\n");
@@ -1559,11 +1563,11 @@ void ThreadMessageHandler2(void* parg)
// Wait and allow messages to bunch up.
// Reduce vnThreadsRunning so StopNode has permission to exit while
// we're sleeping, but we must always check fShutdown after doing this.
- vnThreadsRunning[2]--;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
Sleep(100);
if (fRequestShutdown)
Shutdown(NULL);
- vnThreadsRunning[2]++;
+ vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
if (fShutdown)
return;
}
@@ -1766,23 +1770,26 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
- while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
- || (fHaveUPnP && vnThreadsRunning[5] > 0) || vnThreadsRunning[6] > 0 || vnThreadsRunning[7] > 0
- )
+ do
{
+ int nThreadsRunning = 0;
+ for (int n = 0; n < THREAD_MAX; n++)
+ nThreadsRunning += vnThreadsRunning[n];
+ if (nThreadsRunning == 0)
+ break;
if (GetTime() - nStart > 20)
break;
Sleep(20);
- }
- if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
- if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
- if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
- if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
- if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
- if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
- if (vnThreadsRunning[6] > 0) printf("ThreadDNSAddressSeed still running\n");
- if (vnThreadsRunning[7] > 0) printf("ThreadOpenAddedConnections still running\n");
- while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
+ } while(true);
+ if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
+ if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
+ if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
+ if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
+ if (vnThreadsRunning[THREAD_RPCSERVER] > 0) printf("ThreadRPCServer still running\n");
+ if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
+ if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
+ if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
+ while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCSERVER] > 0)
Sleep(20);
Sleep(50);
diff --git a/src/net.h b/src/net.h
index 2be9541cd1..0a3cf388ec 100644
--- a/src/net.h
+++ b/src/net.h
@@ -68,14 +68,26 @@ public:
-
+enum threadId
+{
+ THREAD_SOCKETHANDLER,
+ THREAD_OPENCONNECTIONS,
+ THREAD_MESSAGEHANDLER,
+ THREAD_MINER,
+ THREAD_RPCSERVER,
+ THREAD_UPNP,
+ THREAD_DNSSEED,
+ THREAD_ADDEDCONNECTIONS,
+
+ THREAD_MAX
+};
extern bool fClient;
extern bool fAllowDNS;
extern uint64 nLocalServices;
extern CAddress addrLocalHost;
extern uint64 nLocalHostNonce;
-extern boost::array<int, 10> vnThreadsRunning;
+extern boost::array<int, THREAD_MAX> vnThreadsRunning;
extern std::vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;
@@ -279,7 +291,7 @@ public:
void BeginMessage(const char* pszCommand)
{
- cs_vSend.Enter("cs_vSend", __FILE__, __LINE__);
+ ENTER_CRITICAL_SECTION(cs_vSend);
if (nHeaderStart != -1)
AbortMessage();
nHeaderStart = vSend.size();
@@ -298,7 +310,7 @@ public:
vSend.resize(nHeaderStart);
nHeaderStart = -1;
nMessageStart = -1;
- cs_vSend.Leave();
+ LEAVE_CRITICAL_SECTION(cs_vSend);
if (fDebug)
printf("(aborted)\n");
@@ -336,7 +348,7 @@ public:
nHeaderStart = -1;
nMessageStart = -1;
- cs_vSend.Leave();
+ LEAVE_CRITICAL_SECTION(cs_vSend);
}
void EndMessageAbortIfEmpty()
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 54aa933a54..7799a65972 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -402,7 +402,7 @@ bool CNetAddr::IsRFC6145() const
bool CNetAddr::IsRFC4843() const
{
- return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && GetByte(12) & 0xF0 == 0x10);
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
}
bool CNetAddr::IsLocal() const
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 8c4b0e6c10..20c185ed27 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -162,11 +162,13 @@ int main(int argc, char *argv[])
ParseParameters(argc, argv);
- // Load language files for system locale:
+ // Get desired locale ("en_US") from command line or system locale
+ QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
+ // Load language files for configured locale:
// - First load the translator for the base language, without territory
// - Then load the more specific locale translator
- QString lang_territory = QLocale::system().name(); // "en_US"
QString lang = lang_territory;
+
lang.truncate(lang_territory.lastIndexOf('_')); // "en"
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index 5693ae187e..d823752c9c 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -37,6 +37,7 @@
<file alias="lock_closed">res/icons/lock_closed.png</file>
<file alias="lock_open">res/icons/lock_open.png</file>
<file alias="key">res/icons/key.png</file>
+ <file alias="filesave">res/icons/filesave.png</file>
</qresource>
<qresource prefix="/images">
<file alias="about">res/images/about.png</file>
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index b72f128291..c95afdcef3 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -46,6 +46,8 @@
#include <QStackedWidget>
#include <QDateTime>
#include <QMovie>
+#include <QFileDialog>
+#include <QDesktopServices>
#include <QDragEnterEvent>
#include <QUrl>
@@ -243,6 +245,8 @@ void BitcoinGUI::createActions()
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet"), this);
encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet"));
encryptWalletAction->setCheckable(true);
+ backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet"), this);
+ backupWalletAction->setToolTip(tr("Backup wallet to another location"));
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase"), this);
changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption"));
@@ -252,6 +256,7 @@ void BitcoinGUI::createActions()
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
connect(openBitcoinAction, SIGNAL(triggered()), this, SLOT(showNormal()));
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
+ connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
}
@@ -277,6 +282,7 @@ void BitcoinGUI::createMenuBar()
QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
settings->addAction(encryptWalletAction);
settings->addAction(changePassphraseAction);
+ settings->addAction(backupWalletAction);
settings->addSeparator();
settings->addAction(optionsAction);
@@ -723,7 +729,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
QList<QUrl> urls = event->mimeData()->urls();
foreach(const QUrl &url, urls)
{
- sendCoinsPage->handleURL(&url);
+ sendCoinsPage->handleURL(url.toString());
}
}
@@ -733,8 +739,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event)
void BitcoinGUI::handleURL(QString strURL)
{
gotoSendCoinsPage();
- QUrl url = QUrl(strURL);
- sendCoinsPage->handleURL(&url);
+ sendCoinsPage->handleURL(strURL);
}
void BitcoinGUI::setEncryptionStatus(int status)
@@ -778,6 +783,17 @@ void BitcoinGUI::encryptWallet(bool status)
setEncryptionStatus(walletModel->getEncryptionStatus());
}
+void BitcoinGUI::backupWallet()
+{
+ QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+ QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
+ if(!filename.isEmpty()) {
+ if(!walletModel->backupWallet(filename)) {
+ QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."));
+ }
+ }
+}
+
void BitcoinGUI::changePassphrase()
{
AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index 37ab12577c..a522429000 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -86,6 +86,7 @@ private:
QAction *openBitcoinAction;
QAction *exportAction;
QAction *encryptWalletAction;
+ QAction *backupWalletAction;
QAction *changePassphraseAction;
QAction *aboutQtAction;
@@ -162,6 +163,8 @@ private slots:
void incomingTransaction(const QModelIndex & parent, int start, int end);
/** Encrypt the wallet */
void encryptWallet(bool status);
+ /** Backup the wallet */
+ void backupWallet();
/** Change encrypted wallet passphrase */
void changePassphrase();
/** Ask for pass phrase to unlock wallet temporarily */
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 29ef554ac3..02fc3b6700 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -49,15 +49,15 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
}
-bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out)
+bool GUIUtil::parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out)
{
- if(url->scheme() != QString("bitcoin"))
+ if(url.scheme() != QString("bitcoin"))
return false;
SendCoinsRecipient rv;
- rv.address = url->path();
+ rv.address = url.path();
rv.amount = 0;
- QList<QPair<QString, QString> > items = url->queryItems();
+ QList<QPair<QString, QString> > items = url.queryItems();
for (QList<QPair<QString, QString> >::iterator i = items.begin(); i != items.end(); i++)
{
bool fShouldReturnFalse = false;
@@ -94,6 +94,20 @@ bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out)
return true;
}
+bool GUIUtil::parseBitcoinURL(QString url, SendCoinsRecipient *out)
+{
+ // Convert bitcoin:// to bitcoin:
+ //
+ // Cannot handle this later, because bitcoin:// will cause Qt to see the part after // as host,
+ // which will lowercase it (and thus invalidate the address).
+ if(url.startsWith("bitcoin://"))
+ {
+ url.replace(0, 10, "bitcoin:");
+ }
+ QUrl urlInstance(url);
+ return parseBitcoinURL(urlInstance, out);
+}
+
QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
{
QString escaped = Qt::escape(str);
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 3a81bd2f00..0c8b17186f 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -31,7 +31,8 @@ public:
// Parse "bitcoin:" URL into recipient object, return true on succesful parsing
// See Bitcoin URL definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
- static bool parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out);
+ static bool parseBitcoinURL(const QUrl &url, SendCoinsRecipient *out);
+ static bool parseBitcoinURL(QString url, SendCoinsRecipient *out);
// HTML escaping for rich text controls
static QString HtmlEscape(const QString& str, bool fMultiLine=false);
diff --git a/src/qt/messagepage.cpp b/src/qt/messagepage.cpp
index dee1837ed6..46a0cbae24 100644
--- a/src/qt/messagepage.cpp
+++ b/src/qt/messagepage.cpp
@@ -1,6 +1,12 @@
#include <string>
#include <vector>
+#include <QClipboard>
+#include <QInputDialog>
+#include <QList>
+#include <QListWidgetItem>
+#include <QMessageBox>
+
#include "main.h"
#include "wallet.h"
#include "init.h"
@@ -13,12 +19,6 @@
#include "guiutil.h"
#include "walletmodel.h"
-#include <QClipboard>
-#include <QInputDialog>
-#include <QList>
-#include <QListWidgetItem>
-#include <QMessageBox>
-
MessagePage::MessagePage(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessagePage)
diff --git a/src/qt/qtipcserver.cpp b/src/qt/qtipcserver.cpp
index 90d5c14211..018461a9b2 100644
--- a/src/qt/qtipcserver.cpp
+++ b/src/qt/qtipcserver.cpp
@@ -30,16 +30,7 @@ void ipcThread(void* parg)
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(100);
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
{
- strBuf[nSize] = '\0';
- // Convert bitcoin:// URLs to bitcoin: URIs
- if (strBuf[8] == '/' && strBuf[9] == '/')
- {
- for (int i = 8; i < 256; i++)
- {
- strBuf[i] = strBuf[i+2];
- }
- }
- ThreadSafeHandleURL(strBuf);
+ ThreadSafeHandleURL(std::string(strBuf, nSize));
Sleep(1000);
}
if (fShutdown)
@@ -66,16 +57,7 @@ void ipcInit()
ptime d = boost::posix_time::microsec_clock::universal_time() + millisec(1);
if(mq->timed_receive(&strBuf, sizeof(strBuf), nSize, nPriority, d))
{
- strBuf[nSize] = '\0';
- // Convert bitcoin:// URLs to bitcoin: URIs
- if (strBuf[8] == '/' && strBuf[9] == '/')
- {
- for (int i = 8; i < 256; i++)
- {
- strBuf[i] = strBuf[i+2];
- }
- }
- ThreadSafeHandleURL(strBuf);
+ ThreadSafeHandleURL(std::string(strBuf, nSize));
}
else
break;
diff --git a/src/qt/res/icons/filesave.png b/src/qt/res/icons/filesave.png
new file mode 100644
index 0000000000..ae13a151d5
--- /dev/null
+++ b/src/qt/res/icons/filesave.png
Binary files differ
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 0d9a604d3b..964313ea81 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -265,7 +265,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
}
-void SendCoinsDialog::handleURL(const QUrl *url)
+void SendCoinsDialog::handleURL(const QString &url)
{
SendCoinsRecipient rv;
if(!GUIUtil::parseBitcoinURL(url, &rv))
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index 847ee8b697..4dc3f08bc5 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -30,7 +30,7 @@ public:
QWidget *setupTabChain(QWidget *prev);
void pasteEntry(const SendCoinsRecipient &rv);
- void handleURL(const QUrl *url);
+ void handleURL(const QString &url);
public slots:
void clear();
diff --git a/src/qt/test/urltests.cpp b/src/qt/test/urltests.cpp
index 5ecc846203..1f11795a9b 100644
--- a/src/qt/test/urltests.cpp
+++ b/src/qt/test/urltests.cpp
@@ -18,51 +18,54 @@ void URLTests::urlTests()
SendCoinsRecipient rv;
QUrl url;
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
- QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 0);
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString("Wikipedia Example Address"));
QVERIFY(rv.amount == 0);
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 100000);
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
QVERIFY(rv.amount == 100100000);
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.amount == 10000000000);
QVERIFY(rv.label == QString("Wikipedia Example"));
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
- QVERIFY(GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(GUIUtil::parseBitcoinURL(url, &rv));
QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
+
+ QVERIFY(GUIUtil::parseBitcoinURL("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
+ QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
QVERIFY(rv.label == QString());
// We currently dont implement the message paramenter (ok, yea, we break spec...)
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
- QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
- QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
url.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
- QVERIFY(!GUIUtil::parseBitcoinURL(&url, &rv));
+ QVERIFY(!GUIUtil::parseBitcoinURL(url, &rv));
}
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index f028f10f6c..8344a653d5 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -5,6 +5,7 @@
#include "transactiontablemodel.h"
#include "headers.h"
+#include "db.h" // for BackupWallet
#include <QTimer>
#include <QSet>
@@ -239,6 +240,11 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
return retval;
}
+bool WalletModel::backupWallet(const QString &filename)
+{
+ return BackupWallet(*wallet, filename.toLocal8Bit().data());
+}
+
// WalletModel::UnlockContext implementation
WalletModel::UnlockContext WalletModel::requestUnlock()
{
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 89e8cdd2a0..4123240e90 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -77,6 +77,8 @@ public:
// Passphrase only needed when unlocking
bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString());
bool changePassphrase(const SecureString &oldPass, const SecureString &newPass);
+ // Wallet backup
+ bool backupWallet(const QString &filename);
// RAI object for unlocking wallet, returned by requestUnlock()
class UnlockContext
diff --git a/src/util.cpp b/src/util.cpp
index 12ac076f0d..f1af91de27 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -454,6 +454,21 @@ vector<unsigned char> ParseHex(const string& str)
return ParseHex(str.c_str());
}
+static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
+{
+ // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
+ if (name.find("-no") == 0)
+ {
+ std::string positive("-");
+ positive.append(name.begin()+3, name.end());
+ if (mapSettingsRet.count(positive) == 0)
+ {
+ bool value = !GetBoolArg(name);
+ mapSettingsRet[positive] = (value ? "1" : "0");
+ }
+ }
+}
+
void ParseParameters(int argc, const char*const argv[])
{
mapArgs.clear();
@@ -494,17 +509,8 @@ void ParseParameters(int argc, const char*const argv[])
name = singleDash;
}
- // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1, as long as -foo not set)
- if (name.find("-no") == 0)
- {
- std::string positive("-");
- positive.append(name.begin()+3, name.end());
- if (mapArgs.count(positive) == 0)
- {
- bool value = !GetBoolArg(name);
- mapArgs[positive] = (value ? "1" : "0");
- }
- }
+ // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
+ InterpretNegativeSetting(name, mapArgs);
}
}
@@ -920,7 +926,11 @@ void ReadConfigFile(map<string, string>& mapSettingsRet,
// Don't overwrite existing settings so command line settings override bitcoin.conf
string strKey = string("-") + it->string_key;
if (mapSettingsRet.count(strKey) == 0)
+ {
mapSettingsRet[strKey] = it->value[0];
+ // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
+ InterpretNegativeSetting(strKey, mapSettingsRet);
+ }
mapMultiSettingsRet[strKey].push_back(it->value[0]);
}
}
diff --git a/src/util.h b/src/util.h
index 8dcedb147b..ddc8791b38 100644
--- a/src/util.h
+++ b/src/util.h
@@ -218,6 +218,12 @@ public:
#define CRITICAL_BLOCK(cs) \
if (CCriticalBlock criticalblock = CCriticalBlock(cs, #cs, __FILE__, __LINE__))
+#define ENTER_CRITICAL_SECTION(cs) \
+ (cs).Enter(#cs, __FILE__, __LINE__)
+
+#define LEAVE_CRITICAL_SECTION(cs) \
+ (cs).Leave()
+
class CTryCriticalBlock
{
protected: