mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
Configuration file, HTTP Basic authentication
This commit is contained in:
parent
e96cd730d1
commit
fe98cf8dc5
@ -26,6 +26,7 @@
|
|||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
#include <wx/taskbar.h>
|
#include <wx/taskbar.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <openssl/buffer.h>
|
||||||
#include <openssl/ecdsa.h>
|
#include <openssl/ecdsa.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
@ -64,6 +65,9 @@
|
|||||||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
||||||
#include <boost/date_time/gregorian/gregorian_types.hpp>
|
#include <boost/date_time/gregorian/gregorian_types.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/program_options/detail/config_file.hpp>
|
||||||
|
#include <boost/program_options/parsers.hpp>
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
49
init.cpp
49
init.cpp
@ -240,12 +240,13 @@ IMPLEMENT_APP(CMyApp)
|
|||||||
|
|
||||||
bool CMyApp::Initialize(int& argc, wxChar** argv)
|
bool CMyApp::Initialize(int& argc, wxChar** argv)
|
||||||
{
|
{
|
||||||
if (argc > 1 && argv[1][0] != '-' && (!fWindows || argv[1][0] != '/') &&
|
for (int i = 1; i < argc; i++)
|
||||||
wxString(argv[1]) != "start")
|
if (!IsSwitchChar(argv[i][0]))
|
||||||
{
|
|
||||||
fCommandLine = true;
|
fCommandLine = true;
|
||||||
}
|
|
||||||
else if (!fGUI)
|
if (!fCommandLine)
|
||||||
|
{
|
||||||
|
if (!fGUI)
|
||||||
{
|
{
|
||||||
fDaemon = true;
|
fDaemon = true;
|
||||||
}
|
}
|
||||||
@ -264,11 +265,11 @@ bool CMyApp::Initialize(int& argc, wxChar** argv)
|
|||||||
strlwr(pszLower);
|
strlwr(pszLower);
|
||||||
str = pszLower;
|
str = pszLower;
|
||||||
#endif
|
#endif
|
||||||
// haven't decided which argument to use for this yet
|
if (str == "-daemon")
|
||||||
if (str == "-daemon" || str == "-d" || str == "start")
|
|
||||||
fDaemon = true;
|
fDaemon = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
if (fDaemon || fCommandLine)
|
if (fDaemon || fCommandLine)
|
||||||
@ -375,22 +376,23 @@ bool CMyApp::OnInit2()
|
|||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
//
|
//
|
||||||
if (fCommandLine)
|
|
||||||
{
|
|
||||||
int ret = CommandLineRPC(argc, argv);
|
|
||||||
exit(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParseParameters(argc, argv);
|
ParseParameters(argc, argv);
|
||||||
|
|
||||||
|
if (mapArgs.count("-datadir"))
|
||||||
|
strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
|
||||||
|
|
||||||
|
ReadConfigFile(mapArgs, mapMultiArgs); // Must be done after processing datadir
|
||||||
|
|
||||||
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
if (mapArgs.count("-?") || mapArgs.count("--help"))
|
||||||
{
|
{
|
||||||
wxString strUsage = string() +
|
wxString strUsage = string() +
|
||||||
_("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
|
_("Usage:") + "\t\t\t\t\t\t\t\t\t\t\n" +
|
||||||
" bitcoin [options] \t" + "\n" +
|
" bitcoin [options] \t " + "\n" +
|
||||||
" bitcoin [command] \t" + _("Send command to bitcoin running with -server or -daemon\n") +
|
" bitcoin [options] <command> [params]\t " + _("Send command to -server or bitcoind\n") +
|
||||||
" bitcoin [command] -? \t" + _("Get help for a command\n") +
|
" bitcoin [options] <command> -? \t\t " + _("Get help for a command\n") +
|
||||||
" bitcoin help <pw> \t" + _("List commands\n") +
|
" bitcoin help \t\t\t " + _("List commands\n") +
|
||||||
_("Options:\n") +
|
_("Options:\n") +
|
||||||
|
" -conf=<file> \t " + _("Specify configuration file (default: bitcoin.conf)\n") +
|
||||||
" -gen \t " + _("Generate coins\n") +
|
" -gen \t " + _("Generate coins\n") +
|
||||||
" -gen=0 \t " + _("Don't generate coins\n") +
|
" -gen=0 \t " + _("Don't generate coins\n") +
|
||||||
" -min \t " + _("Start minimized\n") +
|
" -min \t " + _("Start minimized\n") +
|
||||||
@ -398,7 +400,7 @@ bool CMyApp::OnInit2()
|
|||||||
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
|
" -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
|
||||||
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
|
" -addnode=<ip> \t " + _("Add a node to connect to\n") +
|
||||||
" -connect=<ip> \t " + _("Connect only to the specified node\n") +
|
" -connect=<ip> \t " + _("Connect only to the specified node\n") +
|
||||||
" -rpcpw=<pw> \t " + _("Accept command line and JSON-RPC commands with the given password\n") +
|
" -server \t " + _("Accept command line and JSON-RPC commands\n") +
|
||||||
" -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
|
" -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
|
||||||
" -? \t " + _("This help message\n");
|
" -? \t " + _("This help message\n");
|
||||||
|
|
||||||
@ -413,15 +415,18 @@ bool CMyApp::OnInit2()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapArgs.count("-datadir"))
|
|
||||||
strlcpy(pszSetDataDir, mapArgs["-datadir"].c_str(), sizeof(pszSetDataDir));
|
|
||||||
|
|
||||||
if (mapArgs.count("-debug"))
|
if (mapArgs.count("-debug"))
|
||||||
fDebug = true;
|
fDebug = true;
|
||||||
|
|
||||||
if (mapArgs.count("-printtodebugger"))
|
if (mapArgs.count("-printtodebugger"))
|
||||||
fPrintToDebugger = true;
|
fPrintToDebugger = true;
|
||||||
|
|
||||||
|
if (fCommandLine)
|
||||||
|
{
|
||||||
|
int ret = CommandLineRPC(argc, argv);
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fDebug && !pszSetDataDir[0])
|
if (!fDebug && !pszSetDataDir[0])
|
||||||
ShrinkDebugFile();
|
ShrinkDebugFile();
|
||||||
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||||
@ -611,7 +616,7 @@ bool CMyApp::OnInit2()
|
|||||||
if (!CreateThread(StartNode, NULL))
|
if (!CreateThread(StartNode, NULL))
|
||||||
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
|
wxMessageBox("Error: CreateThread(StartNode) failed", "Bitcoin");
|
||||||
|
|
||||||
if (mapArgs.count("-server") || mapArgs.count("-rpcpw") || fDaemon)
|
if (mapArgs.count("-server") || fDaemon)
|
||||||
CreateThread(ThreadRPCServer, NULL);
|
CreateThread(ThreadRPCServer, NULL);
|
||||||
|
|
||||||
if (fFirstRun)
|
if (fFirstRun)
|
||||||
|
@ -22,7 +22,7 @@ WXLIBS= \
|
|||||||
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd
|
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd
|
||||||
|
|
||||||
LIBS= \
|
LIBS= \
|
||||||
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
|
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d -l libboost_program_options-mgw34-mt-d \
|
||||||
-l db_cxx \
|
-l db_cxx \
|
||||||
-l eay32 \
|
-l eay32 \
|
||||||
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
|
||||||
|
@ -19,6 +19,7 @@ LIBS= -dead_strip \
|
|||||||
$(DEPSDIR)/lib/libdb_cxx-4.8.a \
|
$(DEPSDIR)/lib/libdb_cxx-4.8.a \
|
||||||
$(DEPSDIR)/lib/libboost_system.a \
|
$(DEPSDIR)/lib/libboost_system.a \
|
||||||
$(DEPSDIR)/lib/libboost_filesystem.a \
|
$(DEPSDIR)/lib/libboost_filesystem.a \
|
||||||
|
$(DEPSDIR)/lib/libboost_program_options.a \
|
||||||
$(DEPSDIR)/lib/libcrypto.a
|
$(DEPSDIR)/lib/libcrypto.a
|
||||||
|
|
||||||
WXDEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -DNOPCH -DMSG_NOSIGNAL=0
|
WXDEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -DNOPCH -DMSG_NOSIGNAL=0
|
||||||
|
@ -21,7 +21,7 @@ WXLIBS= \
|
|||||||
|
|
||||||
LIBS= \
|
LIBS= \
|
||||||
-Wl,-Bstatic \
|
-Wl,-Bstatic \
|
||||||
-l boost_system -l boost_filesystem \
|
-l boost_system -l boost_filesystem -l boost_program_options \
|
||||||
-l db_cxx \
|
-l db_cxx \
|
||||||
-l crypto \
|
-l crypto \
|
||||||
-Wl,-Bdynamic \
|
-Wl,-Bdynamic \
|
||||||
|
@ -19,7 +19,7 @@ LIBPATHS= \
|
|||||||
/LIBPATH:"/wxwidgets/lib/vc_lib"
|
/LIBPATH:"/wxwidgets/lib/vc_lib"
|
||||||
|
|
||||||
LIBS= \
|
LIBS= \
|
||||||
libboost_system-vc80-mt-gd.lib libboost_filesystem-vc80-mt-gd.lib \
|
libboost_system-vc80-mt-gd.lib libboost_filesystem-vc80-mt-gd.lib libboost_program_options-vc80-mt-gd.lib \
|
||||||
libdb47sd.lib \
|
libdb47sd.lib \
|
||||||
libeay32.lib \
|
libeay32.lib \
|
||||||
wxmsw29ud_html.lib wxmsw29ud_core.lib wxmsw29ud_adv.lib wxbase29ud.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib \
|
wxmsw29ud_html.lib wxmsw29ud_core.lib wxmsw29ud_adv.lib wxbase29ud.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib \
|
||||||
|
284
rpc.cpp
284
rpc.cpp
@ -21,7 +21,27 @@ void ThreadRPCServer2(void* parg);
|
|||||||
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
|
||||||
extern map<string, rpcfn_type> mapCallTable;
|
extern map<string, rpcfn_type> mapCallTable;
|
||||||
|
|
||||||
static string strRPCPassword;
|
|
||||||
|
|
||||||
|
void PrintConsole(const char* format, ...)
|
||||||
|
{
|
||||||
|
char buffer[50000];
|
||||||
|
int limit = sizeof(buffer);
|
||||||
|
va_list arg_ptr;
|
||||||
|
va_start(arg_ptr, format);
|
||||||
|
int ret = _vsnprintf(buffer, limit, format, arg_ptr);
|
||||||
|
va_end(arg_ptr);
|
||||||
|
if (ret < 0 || ret >= limit)
|
||||||
|
{
|
||||||
|
ret = limit - 1;
|
||||||
|
buffer[limit-1] = 0;
|
||||||
|
}
|
||||||
|
#if defined(__WXMSW__) && wxUSE_GUI
|
||||||
|
MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
||||||
|
#else
|
||||||
|
fprintf(stdout, buffer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -34,12 +54,11 @@ static string strRPCPassword;
|
|||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Value help(const Array& params, bool fHelp)
|
Value help(const Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"help <pw>\n"
|
"help\n"
|
||||||
"List commands.");
|
"List commands.");
|
||||||
|
|
||||||
string strRet;
|
string strRet;
|
||||||
@ -76,7 +95,7 @@ Value stop(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"stop <pw>\n"
|
"stop\n"
|
||||||
"Stop bitcoin server.");
|
"Stop bitcoin server.");
|
||||||
|
|
||||||
// Shutdown will take long enough that the response should get back
|
// Shutdown will take long enough that the response should get back
|
||||||
@ -89,7 +108,7 @@ Value getblockcount(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getblockcount <pw>\n"
|
"getblockcount\n"
|
||||||
"Returns the number of blocks in the longest block chain.");
|
"Returns the number of blocks in the longest block chain.");
|
||||||
|
|
||||||
return nBestHeight + 1;
|
return nBestHeight + 1;
|
||||||
@ -100,7 +119,7 @@ Value getblocknumber(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getblocknumber <pw>\n"
|
"getblocknumber\n"
|
||||||
"Returns the block number of the latest block in the longest block chain.");
|
"Returns the block number of the latest block in the longest block chain.");
|
||||||
|
|
||||||
return nBestHeight;
|
return nBestHeight;
|
||||||
@ -111,7 +130,7 @@ Value getconnectioncount(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getconnectioncount <pw>\n"
|
"getconnectioncount\n"
|
||||||
"Returns the number of connections to other nodes.");
|
"Returns the number of connections to other nodes.");
|
||||||
|
|
||||||
return (int)vNodes.size();
|
return (int)vNodes.size();
|
||||||
@ -134,7 +153,7 @@ Value getdifficulty(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getdifficulty <pw>\n"
|
"getdifficulty\n"
|
||||||
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
|
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
|
||||||
|
|
||||||
return GetDifficulty();
|
return GetDifficulty();
|
||||||
@ -145,7 +164,7 @@ Value getbalance(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getbalance <pw>\n"
|
"getbalance\n"
|
||||||
"Returns the server's available balance.");
|
"Returns the server's available balance.");
|
||||||
|
|
||||||
return ((double)GetBalance() / (double)COIN);
|
return ((double)GetBalance() / (double)COIN);
|
||||||
@ -156,7 +175,7 @@ Value getgenerate(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getgenerate <pw>\n"
|
"getgenerate\n"
|
||||||
"Returns true or false.");
|
"Returns true or false.");
|
||||||
|
|
||||||
return (bool)fGenerateBitcoins;
|
return (bool)fGenerateBitcoins;
|
||||||
@ -167,7 +186,7 @@ Value setgenerate(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"setgenerate <pw> <generate> [genproclimit]\n"
|
"setgenerate <generate> [genproclimit]\n"
|
||||||
"<generate> is true or false to turn generation on or off.\n"
|
"<generate> is true or false to turn generation on or off.\n"
|
||||||
"Generation is limited to [genproclimit] processors, -1 is unlimited.");
|
"Generation is limited to [genproclimit] processors, -1 is unlimited.");
|
||||||
|
|
||||||
@ -193,7 +212,7 @@ Value getinfo(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getinfo <pw>");
|
"getinfo");
|
||||||
|
|
||||||
Object obj;
|
Object obj;
|
||||||
obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
|
obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
|
||||||
@ -211,7 +230,7 @@ Value getnewaddress(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() > 1)
|
if (fHelp || params.size() > 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getnewaddress <pw> [label]\n"
|
"getnewaddress [label]\n"
|
||||||
"Returns a new bitcoin address for receiving payments. "
|
"Returns a new bitcoin address for receiving payments. "
|
||||||
"If [label] is specified (recommended), it is added to the address book "
|
"If [label] is specified (recommended), it is added to the address book "
|
||||||
"so payments received with the address will be labeled.");
|
"so payments received with the address will be labeled.");
|
||||||
@ -233,7 +252,7 @@ Value setlabel(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"setlabel <pw> <bitcoinaddress> <label>\n"
|
"setlabel <bitcoinaddress> <label>\n"
|
||||||
"Sets the label associated with the given address.");
|
"Sets the label associated with the given address.");
|
||||||
|
|
||||||
string strAddress = params[0].get_str();
|
string strAddress = params[0].get_str();
|
||||||
@ -250,7 +269,7 @@ Value getlabel(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() != 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getlabel <pw> <bitcoinaddress>\n"
|
"getlabel <bitcoinaddress>\n"
|
||||||
"Returns the label associated with the given address.");
|
"Returns the label associated with the given address.");
|
||||||
|
|
||||||
string strAddress = params[0].get_str();
|
string strAddress = params[0].get_str();
|
||||||
@ -270,7 +289,7 @@ Value getaddressesbylabel(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() != 1)
|
if (fHelp || params.size() != 1)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getaddressesbylabel <pw> <label>\n"
|
"getaddressesbylabel <label>\n"
|
||||||
"Returns the list of addresses with the given label.");
|
"Returns the list of addresses with the given label.");
|
||||||
|
|
||||||
string strLabel = params[0].get_str();
|
string strLabel = params[0].get_str();
|
||||||
@ -300,7 +319,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() < 2 || params.size() > 4)
|
if (fHelp || params.size() < 2 || params.size() > 4)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"sendtoaddress <pw> <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
|
||||||
"<amount> is a real and is rounded to the nearest 0.01");
|
"<amount> is a real and is rounded to the nearest 0.01");
|
||||||
|
|
||||||
string strAddress = params[0].get_str();
|
string strAddress = params[0].get_str();
|
||||||
@ -328,7 +347,7 @@ Value listtransactions(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() > 2)
|
if (fHelp || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"listtransactions <pw> [count=10] [includegenerated=false]\n"
|
"listtransactions [count=10] [includegenerated=false]\n"
|
||||||
"Returns up to [count] most recent transactions.");
|
"Returns up to [count] most recent transactions.");
|
||||||
|
|
||||||
int64 nCount = 10;
|
int64 nCount = 10;
|
||||||
@ -349,7 +368,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getreceivedbyaddress <pw> <bitcoinaddress> [minconf=1]\n"
|
"getreceivedbyaddress <bitcoinaddress> [minconf=1]\n"
|
||||||
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
|
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
|
||||||
|
|
||||||
// Bitcoin address
|
// Bitcoin address
|
||||||
@ -390,7 +409,7 @@ Value getreceivedbylabel(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() < 1 || params.size() > 2)
|
if (fHelp || params.size() < 1 || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"getreceivedbylabel <pw> <label> [minconf=1]\n"
|
"getreceivedbylabel <label> [minconf=1]\n"
|
||||||
"Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.");
|
"Returns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.");
|
||||||
|
|
||||||
// Get the set of pub keys that have the label
|
// Get the set of pub keys that have the label
|
||||||
@ -553,7 +572,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() > 2)
|
if (fHelp || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"listreceivedbyaddress <pw> [minconf=1] [includeempty=false]\n"
|
"listreceivedbyaddress [minconf=1] [includeempty=false]\n"
|
||||||
"[minconf] is the minimum number of confirmations before payments are included.\n"
|
"[minconf] is the minimum number of confirmations before payments are included.\n"
|
||||||
"[includeempty] whether to include addresses that haven't received any payments.\n"
|
"[includeempty] whether to include addresses that haven't received any payments.\n"
|
||||||
"Returns an array of objects containing:\n"
|
"Returns an array of objects containing:\n"
|
||||||
@ -569,7 +588,7 @@ Value listreceivedbylabel(const Array& params, bool fHelp)
|
|||||||
{
|
{
|
||||||
if (fHelp || params.size() > 2)
|
if (fHelp || params.size() > 2)
|
||||||
throw runtime_error(
|
throw runtime_error(
|
||||||
"listreceivedbylabel <pw> [minconf=1] [includeempty=false]\n"
|
"listreceivedbylabel [minconf=1] [includeempty=false]\n"
|
||||||
"[minconf] is the minimum number of confirmations before payments are included.\n"
|
"[minconf] is the minimum number of confirmations before payments are included.\n"
|
||||||
"[includeempty] whether to include labels that haven't received any payments.\n"
|
"[includeempty] whether to include labels that haven't received any payments.\n"
|
||||||
"Returns an array of objects containing:\n"
|
"Returns an array of objects containing:\n"
|
||||||
@ -632,23 +651,41 @@ map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)
|
|||||||
// and to be compatible with other JSON-RPC implementations.
|
// and to be compatible with other JSON-RPC implementations.
|
||||||
//
|
//
|
||||||
|
|
||||||
string HTTPPost(const string& strMsg)
|
string HTTPPost(const string& strMsg, const map<string,string>& mapRequestHeaders)
|
||||||
{
|
{
|
||||||
return strprintf(
|
ostringstream s;
|
||||||
"POST / HTTP/1.1\r\n"
|
s << "POST / HTTP/1.1\r\n"
|
||||||
"User-Agent: json-rpc/1.0\r\n"
|
<< "User-Agent: json-rpc/1.0\r\n"
|
||||||
"Host: 127.0.0.1\r\n"
|
<< "Host: 127.0.0.1\r\n"
|
||||||
"Content-Type: application/json\r\n"
|
<< "Content-Type: application/json\r\n"
|
||||||
"Content-Length: %d\r\n"
|
<< "Content-Length: " << strMsg.size() << "\r\n"
|
||||||
"Accept: application/json\r\n"
|
<< "Accept: application/json\r\n";
|
||||||
"\r\n"
|
for (map<string,string>::const_iterator it = mapRequestHeaders.begin(); it != mapRequestHeaders.end(); ++it)
|
||||||
"%s",
|
s << it->first << ": " << it->second << "\r\n";
|
||||||
strMsg.size(),
|
s << "\r\n" << strMsg;
|
||||||
strMsg.c_str());
|
|
||||||
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
string HTTPReply(const string& strMsg, int nStatus=200)
|
string HTTPReply(const string& strMsg, int nStatus=200)
|
||||||
{
|
{
|
||||||
|
if (nStatus == 401)
|
||||||
|
return "HTTP/1.0 401 Authorization Required\r\n"
|
||||||
|
"Server: HTTPd/1.0\r\n"
|
||||||
|
"Date: Sat, 08 Jul 2006 12:04:08 GMT\r\n"
|
||||||
|
"WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n"
|
||||||
|
"Content-Type: text/html\r\n"
|
||||||
|
"Content-Length: 311\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
|
||||||
|
"\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n"
|
||||||
|
"<HTML>\r\n"
|
||||||
|
"<HEAD>\r\n"
|
||||||
|
"<TITLE>Error</TITLE>\r\n"
|
||||||
|
"<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=ISO-8859-1'>\r\n"
|
||||||
|
"</HEAD>\r\n"
|
||||||
|
"<BODY><H1>401 Unauthorized.</H1></BODY>\r\n"
|
||||||
|
"</HTML>\r\n";
|
||||||
string strStatus;
|
string strStatus;
|
||||||
if (nStatus == 200) strStatus = "OK";
|
if (nStatus == 200) strStatus = "OK";
|
||||||
if (nStatus == 500) strStatus = "Internal Server Error";
|
if (nStatus == 500) strStatus = "Internal Server Error";
|
||||||
@ -667,7 +704,17 @@ string HTTPReply(const string& strMsg, int nStatus=200)
|
|||||||
strMsg.c_str());
|
strMsg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadHTTPHeader(tcp::iostream& stream)
|
int ReadHTTPStatus(tcp::iostream& stream)
|
||||||
|
{
|
||||||
|
string str;
|
||||||
|
getline(stream, str);
|
||||||
|
vector<string> vWords;
|
||||||
|
boost::split(vWords, str, boost::is_any_of(" "));
|
||||||
|
int nStatus = atoi(vWords[1].c_str());
|
||||||
|
return nStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadHTTPHeader(tcp::iostream& stream, map<string, string>& mapHeadersRet)
|
||||||
{
|
{
|
||||||
int nLen = 0;
|
int nLen = 0;
|
||||||
loop
|
loop
|
||||||
@ -676,26 +723,92 @@ int ReadHTTPHeader(tcp::iostream& stream)
|
|||||||
std::getline(stream, str);
|
std::getline(stream, str);
|
||||||
if (str.empty() || str == "\r")
|
if (str.empty() || str == "\r")
|
||||||
break;
|
break;
|
||||||
if (str.substr(0,15) == "Content-Length:")
|
string::size_type nColon = str.find(":");
|
||||||
nLen = atoi(str.substr(15));
|
if (nColon != string::npos)
|
||||||
|
{
|
||||||
|
string strHeader = str.substr(0, nColon);
|
||||||
|
boost::trim(strHeader);
|
||||||
|
string strValue = str.substr(nColon+1);
|
||||||
|
boost::trim(strValue);
|
||||||
|
mapHeadersRet[strHeader] = strValue;
|
||||||
|
if (strHeader == "Content-Length")
|
||||||
|
nLen = atoi(strValue.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nLen;
|
return nLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline string ReadHTTP(tcp::iostream& stream)
|
int ReadHTTP(tcp::iostream& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
|
||||||
{
|
{
|
||||||
|
mapHeadersRet.clear();
|
||||||
|
strMessageRet = "";
|
||||||
|
|
||||||
|
// Read status
|
||||||
|
int nStatus = ReadHTTPStatus(stream);
|
||||||
|
|
||||||
// Read header
|
// Read header
|
||||||
int nLen = ReadHTTPHeader(stream);
|
int nLen = ReadHTTPHeader(stream, mapHeadersRet);
|
||||||
if (nLen <= 0)
|
if (nLen <= 0)
|
||||||
return string();
|
return 500;
|
||||||
|
|
||||||
// Read message
|
// Read message
|
||||||
vector<char> vch(nLen);
|
vector<char> vch(nLen);
|
||||||
stream.read(&vch[0], nLen);
|
stream.read(&vch[0], nLen);
|
||||||
return string(vch.begin(), vch.end());
|
strMessageRet = string(vch.begin(), vch.end());
|
||||||
|
|
||||||
|
return nStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string EncodeBase64(string s)
|
||||||
|
{
|
||||||
|
BIO *b64, *bmem;
|
||||||
|
BUF_MEM *bptr;
|
||||||
|
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
bmem = BIO_new(BIO_s_mem());
|
||||||
|
b64 = BIO_push(b64, bmem);
|
||||||
|
BIO_write(b64, s.c_str(), s.size());
|
||||||
|
BIO_flush(b64);
|
||||||
|
BIO_get_mem_ptr(b64, &bptr);
|
||||||
|
|
||||||
|
string result(bptr->data, bptr->length-1);
|
||||||
|
BIO_free_all(b64);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string DecodeBase64(string s)
|
||||||
|
{
|
||||||
|
BIO *b64, *bmem;
|
||||||
|
|
||||||
|
char* buffer = static_cast<char*>(calloc(s.size(), sizeof(char)));
|
||||||
|
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
bmem = BIO_new_mem_buf(const_cast<char*>(s.c_str()), s.size());
|
||||||
|
bmem = BIO_push(b64, bmem);
|
||||||
|
BIO_read(bmem, buffer, s.size());
|
||||||
|
BIO_free_all(bmem);
|
||||||
|
|
||||||
|
string result(buffer);
|
||||||
|
free(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTTPAuthorized(map<string, string>& mapHeaders)
|
||||||
|
{
|
||||||
|
string strAuth = mapHeaders["Authorization"];
|
||||||
|
if (strAuth.substr(0,6) != "Basic ")
|
||||||
|
return false;
|
||||||
|
string strUserPass64 = strAuth.substr(6); boost::trim(strUserPass64);
|
||||||
|
string strUserPass = DecodeBase64(strUserPass64);
|
||||||
|
string::size_type nColon = strUserPass.find(":");
|
||||||
|
if (nColon == string::npos)
|
||||||
|
return false;
|
||||||
|
string strUser = strUserPass.substr(0, nColon);
|
||||||
|
string strPassword = strUserPass.substr(nColon+1);
|
||||||
|
return (strUser == mapArgs["-rpcuser"] && strPassword == mapArgs["-rpcpassword"]);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// JSON-RPC protocol
|
// JSON-RPC protocol
|
||||||
@ -751,15 +864,20 @@ void ThreadRPCServer2(void* parg)
|
|||||||
{
|
{
|
||||||
printf("ThreadRPCServer started\n");
|
printf("ThreadRPCServer started\n");
|
||||||
|
|
||||||
if (mapArgs.count("-rpcpw"))
|
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
|
||||||
strRPCPassword = mapArgs["-rpcpw"];
|
|
||||||
if (strRPCPassword == "")
|
|
||||||
{
|
{
|
||||||
#if defined(__WXMSW__) && wxUSE_GUI
|
string strWhatAmI = "To use bitcoind";
|
||||||
MyMessageBox("Warning: rpc password is blank, use -rpcpw=<password>\n", "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
if (mapArgs.count("-server"))
|
||||||
#else
|
strWhatAmI = strprintf(_("To use the %s option"), "\"-server\"");
|
||||||
fprintf(stdout, "Warning: rpc password is blank, use -rpcpw=<password>\n");
|
else if (mapArgs.count("-daemon"))
|
||||||
#endif
|
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
|
||||||
|
PrintConsole(
|
||||||
|
_("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
|
||||||
|
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
|
||||||
|
strWhatAmI.c_str(),
|
||||||
|
GetConfigFile().c_str());
|
||||||
|
CreateThread(Shutdown, NULL);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind to loopback 127.0.0.1 so the socket can only be accessed locally
|
// Bind to loopback 127.0.0.1 so the socket can only be accessed locally
|
||||||
@ -783,7 +901,26 @@ void ThreadRPCServer2(void* parg)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Receive request
|
// Receive request
|
||||||
string strRequest = ReadHTTP(stream);
|
map<string, string> mapHeaders;
|
||||||
|
string strRequest;
|
||||||
|
ReadHTTP(stream, mapHeaders, strRequest);
|
||||||
|
|
||||||
|
// Check authorization
|
||||||
|
if (mapHeaders.count("Authorization") == 0)
|
||||||
|
{
|
||||||
|
stream << HTTPReply("", 401) << std::flush;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!HTTPAuthorized(mapHeaders))
|
||||||
|
{
|
||||||
|
// Deter brute-forcing short passwords
|
||||||
|
if (mapArgs["-rpcpassword"].size() < 15)
|
||||||
|
Sleep(50);
|
||||||
|
|
||||||
|
stream << HTTPReply("", 401) << std::flush;
|
||||||
|
printf("ThreadRPCServer incorrect password attempt\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle multiple invocations per request
|
// Handle multiple invocations per request
|
||||||
string::iterator begin = strRequest.begin();
|
string::iterator begin = strRequest.begin();
|
||||||
@ -808,23 +945,11 @@ void ThreadRPCServer2(void* parg)
|
|||||||
|
|
||||||
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
||||||
|
|
||||||
// Check password
|
|
||||||
if (params.size() < 1 || params[0].type() != str_type)
|
|
||||||
throw runtime_error("First parameter must be the password.");
|
|
||||||
if (params[0].get_str() != strRPCPassword)
|
|
||||||
{
|
|
||||||
if (strRPCPassword.size() < 15)
|
|
||||||
Sleep(50);
|
|
||||||
begin = strRequest.end();
|
|
||||||
printf("ThreadRPCServer incorrect password attempt\n");
|
|
||||||
throw runtime_error("Incorrect password.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
|
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
|
||||||
if (mi == mapCallTable.end())
|
if (mi == mapCallTable.end())
|
||||||
throw runtime_error("Method not found.");
|
throw runtime_error("Method not found.");
|
||||||
Value result = (*(*mi).second)(Array(params.begin()+1, params.end()), false);
|
Value result = (*(*mi).second)(params, false);
|
||||||
|
|
||||||
// Send reply
|
// Send reply
|
||||||
string strReply = JSONRPCReply(result, Value::null, id);
|
string strReply = JSONRPCReply(result, Value::null, id);
|
||||||
@ -847,18 +972,36 @@ void ThreadRPCServer2(void* parg)
|
|||||||
|
|
||||||
Value CallRPC(const string& strMethod, const Array& params)
|
Value CallRPC(const string& strMethod, const Array& params)
|
||||||
{
|
{
|
||||||
|
if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
|
||||||
|
throw runtime_error(strprintf(
|
||||||
|
_("You must set rpcpassword=<password> in the configuration file:\n%s\n"
|
||||||
|
"If the file does not exist, create it with owner-readable-only file permissions."),
|
||||||
|
GetConfigFile().c_str()));
|
||||||
|
|
||||||
// Connect to localhost
|
// Connect to localhost
|
||||||
tcp::iostream stream("127.0.0.1", "8332");
|
tcp::iostream stream("127.0.0.1", "8332");
|
||||||
if (stream.fail())
|
if (stream.fail())
|
||||||
throw runtime_error("couldn't connect to server");
|
throw runtime_error("couldn't connect to server");
|
||||||
|
|
||||||
|
// HTTP basic authentication
|
||||||
|
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
|
||||||
|
map<string, string> mapRequestHeaders;
|
||||||
|
mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;
|
||||||
|
|
||||||
// Send request
|
// Send request
|
||||||
string strRequest = JSONRPCRequest(strMethod, params, 1);
|
string strRequest = JSONRPCRequest(strMethod, params, 1);
|
||||||
stream << HTTPPost(strRequest) << std::flush;
|
string strPost = HTTPPost(strRequest, mapRequestHeaders);
|
||||||
|
stream << strPost << std::flush;
|
||||||
|
|
||||||
// Receive reply
|
// Receive reply
|
||||||
string strReply = ReadHTTP(stream);
|
map<string, string> mapHeaders;
|
||||||
if (strReply.empty())
|
string strReply;
|
||||||
|
int nStatus = ReadHTTP(stream, mapHeaders, strReply);
|
||||||
|
if (nStatus == 401)
|
||||||
|
throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
|
||||||
|
else if (nStatus >= 400 && nStatus != 500)
|
||||||
|
throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
|
||||||
|
else if (strReply.empty())
|
||||||
throw runtime_error("no response from server");
|
throw runtime_error("no response from server");
|
||||||
|
|
||||||
// Parse reply
|
// Parse reply
|
||||||
@ -904,7 +1047,14 @@ int CommandLineRPC(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Check that method exists
|
// Skip switches
|
||||||
|
while (argc > 1 && IsSwitchChar(argv[1][0]))
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the method exists
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
throw runtime_error("too few parameters");
|
throw runtime_error("too few parameters");
|
||||||
string strMethod = argv[1];
|
string strMethod = argv[1];
|
||||||
|
39
util.cpp
39
util.cpp
@ -416,7 +416,7 @@ void ParseParameters(int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
mapArgs.clear();
|
mapArgs.clear();
|
||||||
mapMultiArgs.clear();
|
mapMultiArgs.clear();
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
char psz[10000];
|
char psz[10000];
|
||||||
strlcpy(psz, argv[i], sizeof(psz));
|
strlcpy(psz, argv[i], sizeof(psz));
|
||||||
@ -431,6 +431,8 @@ void ParseParameters(int argc, char* argv[])
|
|||||||
if (psz[0] == '/')
|
if (psz[0] == '/')
|
||||||
psz[0] = '-';
|
psz[0] = '-';
|
||||||
#endif
|
#endif
|
||||||
|
if (psz[0] != '-')
|
||||||
|
break;
|
||||||
mapArgs[psz] = pszValue;
|
mapArgs[psz] = pszValue;
|
||||||
mapMultiArgs[psz].push_back(pszValue);
|
mapMultiArgs[psz].push_back(pszValue);
|
||||||
}
|
}
|
||||||
@ -619,6 +621,38 @@ string GetDataDir()
|
|||||||
return pszDir;
|
return pszDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string GetConfigFile()
|
||||||
|
{
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
fs::path pathConfig(mapArgs.count("-conf") ? mapArgs["-conf"] : string("bitcoin.conf"));
|
||||||
|
if (!pathConfig.is_complete())
|
||||||
|
pathConfig = fs::path(GetDataDir()) / pathConfig;
|
||||||
|
return pathConfig.string();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadConfigFile(map<string, string>& mapSettingsRet,
|
||||||
|
map<string, vector<string> >& mapMultiSettingsRet)
|
||||||
|
{
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
namespace pod = boost::program_options::detail;
|
||||||
|
|
||||||
|
fs::ifstream streamConfig(GetConfigFile());
|
||||||
|
if (!streamConfig.good())
|
||||||
|
return;
|
||||||
|
|
||||||
|
set<string> setOptions;
|
||||||
|
setOptions.insert("*");
|
||||||
|
|
||||||
|
for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
|
||||||
|
{
|
||||||
|
// 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];
|
||||||
|
mapMultiSettingsRet[strKey].push_back(it->value[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int GetFilesize(FILE* file)
|
int GetFilesize(FILE* file)
|
||||||
{
|
{
|
||||||
int nSavePos = ftell(file);
|
int nSavePos = ftell(file);
|
||||||
@ -656,9 +690,6 @@ void ShrinkDebugFile()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// "Never go to sea with two chronometers; take one or three."
|
// "Never go to sea with two chronometers; take one or three."
|
||||||
// Our three chronometers are:
|
// Our three chronometers are:
|
||||||
|
11
util.h
11
util.h
@ -141,6 +141,8 @@ void ParseParameters(int argc, char* argv[]);
|
|||||||
const char* wxGetTranslation(const char* psz);
|
const char* wxGetTranslation(const char* psz);
|
||||||
int GetFilesize(FILE* file);
|
int GetFilesize(FILE* file);
|
||||||
void GetDataDir(char* pszDirRet);
|
void GetDataDir(char* pszDirRet);
|
||||||
|
string GetConfigFile();
|
||||||
|
void ReadConfigFile(map<string, string>& mapSettingsRet, map<string, vector<string> >& mapMultiSettingsRet);
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
string MyGetSpecialFolderPath(int nFolder, bool fCreate);
|
string MyGetSpecialFolderPath(int nFolder, bool fCreate);
|
||||||
#endif
|
#endif
|
||||||
@ -348,7 +350,14 @@ void skipspaces(T& it)
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsSwitchChar(char c)
|
||||||
|
{
|
||||||
|
#ifdef __WXMSW__
|
||||||
|
return c == '-' || c == '/';
|
||||||
|
#else
|
||||||
|
return c == '-';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user