From f0228d3664cd96cbfcc800593308a0155f8c9381 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 9 Dec 2015 14:37:46 -0700 Subject: [PATCH 01/51] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7557ba990016..b486dc631553 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +pay-core-team.sh *.sublime-project *.sublime-workspace todo.txt From 432e0c0586ab938f2435c70e379d17a9f35adfa0 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 15 Dec 2015 08:13:35 -0700 Subject: [PATCH 02/51] json serializing --- dash-docs/function-layout.txt | 22 +++++ src/Makefile.am | 11 ++- src/evo/dapi.cpp | 166 ++++++++++++++++++++++++++++++++++ src/evo/dapi.h | 45 +++++++++ src/evo/enduser.cpp | 26 ++++++ src/evo/enduser.h | 40 ++++++++ src/evo/file.cpp | 85 +++++++++++++++++ src/evo/file.h | 110 ++++++++++++++++++++++ src/init.cpp | 13 ++- src/init.h | 1 + src/rpcclient.cpp | 1 + src/rpcdapi.cpp | 65 +++++++++++++ src/rpcserver.cpp | 2 + src/rpcserver.h | 1 + 14 files changed, 585 insertions(+), 3 deletions(-) create mode 100644 dash-docs/function-layout.txt create mode 100644 src/evo/dapi.cpp create mode 100644 src/evo/dapi.h create mode 100644 src/evo/enduser.cpp create mode 100644 src/evo/enduser.h create mode 100644 src/evo/file.cpp create mode 100644 src/evo/file.h create mode 100644 src/rpcdapi.cpp diff --git a/dash-docs/function-layout.txt b/dash-docs/function-layout.txt new file mode 100644 index 000000000000..cd7d6e4616a8 --- /dev/null +++ b/dash-docs/function-layout.txt @@ -0,0 +1,22 @@ + +Dash2T + -- Websockets / ZeroMQ daemon + + Listens on port 10014 for websocks + Listens for ZeroMQ commands (relays them locally to DashD.rpcdapi) + +DashD + -- + + rpcdapi + dapi: Execute json command on behalf of a user (delivered locally from Dash2T) + + CDapi + ValidateCommand + ExecuteCommand + + EndUser + Load + Save + UpdateField + diff --git a/src/Makefile.am b/src/Makefile.am index 92eaca819a13..744f1c4773e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -97,6 +97,8 @@ BITCOIN_CORE_H = \ db.h \ eccryptoverify.h \ ecwrapper.h \ + evo/file.h \ + evo/dapi.h \ hash.h \ init.h \ instantx.h \ @@ -178,6 +180,8 @@ libbitcoin_server_a_SOURCES = \ bloom.cpp \ chain.cpp \ checkpoints.cpp \ + evo/file.cpp \ + evo/dapi.cpp \ init.cpp \ leveldbwrapper.cpp \ main.cpp \ @@ -188,6 +192,7 @@ libbitcoin_server_a_SOURCES = \ pow.cpp \ rest.cpp \ rpcblockchain.cpp \ + rpcdapi.cpp \ rpcmasternode.cpp \ rpcmasternode-budget.cpp \ rpcmining.cpp \ @@ -207,10 +212,12 @@ libbitcoin_server_a_SOURCES = \ libbitcoin_wallet_a_CPPFLAGS = $(BITCOIN_INCLUDES) libbitcoin_wallet_a_SOURCES = \ activemasternode.cpp \ - darksend.cpp \ - darksend-relay.cpp \ db.cpp \ crypter.cpp \ + darksend.cpp \ + darksend-relay.cpp \ + evo/file.cpp \ + evo/dapi.cpp \ instantx.cpp \ masternode.cpp \ masternode-budget.cpp \ diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp new file mode 100644 index 000000000000..1e740eb65259 --- /dev/null +++ b/src/evo/dapi.cpp @@ -0,0 +1,166 @@ + + +// Copyright (c) 2014-2015 The Dash developers + +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +#include "main.h" +#include "db.h" +#include "init.h" +#include "dapi.h" +#include "file.h" + +/* + +{ + "object" : "dash_budget_items", + "data" : [ + { "object" : "dash_budget", + "name" : "ds-liquidity", + ... + }, + { "object" : "dash_budget", + "name" : "christmas-lottery", + ... + }, + ... + ] +} +*/ + +bool CDAPI::Execute(Object& obj) +{ + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + if(strObject != "dapi_command") return false; + + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strCommand = json_spirit::find_value(objData, "command").get_str(); + + printf("%s\n", strCommand.c_str()); + + if(strCommand == "get-profile") { + GetProfile(obj); + return true; + } + + return true; +} + +bool CDAPI::ValidateSignature(Object& obj) +{ + /* + lookup pubkey for user + remove signature + hash object + check signature against hash + */ + + return true; +} + +bool CDAPI::GetProfile(Object& obj) +{ + /* + { + "command" : "get-profile", + "my_uid" : 0, + "target_uid" : 0, + "signature" : "SIGNATURE", + } + */ + + + EventNotify("{\"name\":\"value\"}"); + return true; +} + +bool CDAPI::SetProfile(Object& obj) +{ + /* + { + "command" : "set-profile", + "my_uid" : 0, + "target_uid" : 0, + "signature" : "SIGNATURE", + "fields" : ["fname", "lname"] + } + */ + + return true; +} + +bool CDAPI::GetProfileData(Object& obj) +{ + /* + REQUIRED JSON + { + "command" : "get-private-data", + "my_uid" : 0, + "target_uid" : 0, + "signature" : "SIGNATURE", + "slot" : 1 + } + */ + + return true; +} + +bool CDAPI::SetProfileData(Object& obj) +{ + /* + REQUIRED JSON + { + "command" : "set-profile-data", + "my_uid" : 0, + "target_uid" : 0, + "signature" : "SIGNATURE" + "update" : { + "email" : "evan@dash.org" + } + } + */ + + return true; + +} + +// send message from one user to another through T2 +bool CDAPI::SendMessage(Object& obj) +{ + /* + REQUIRED JSON + { + "command" : "send-message", + "my_uid" : 0, + "target_uid" : 0, + "signature" : "SIGNATURE" + "update" : { + "email" : "evan@dash.org" + } + } + */ + + return true; +} + +// broadcast any message on the network from T3 +bool CDAPI::SendBroadcast(Object& obj) +{ + /* + REQUIRED JSON + { + 'command' : 'set-profile-data', + 'my_uid' : 0, + 'target_uid' : 0, + 'signature' : "SIGNATURE" + 'update' : { + "email" : "evan@dash.org" + } + } + */ + + return true; +} + diff --git a/src/evo/dapi.h b/src/evo/dapi.h new file mode 100644 index 000000000000..42dcdd113bf3 --- /dev/null +++ b/src/evo/dapi.h @@ -0,0 +1,45 @@ + + +// Copyright (c) 2014-2015 The Dash developers + +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +#ifndef DAPI_H +#define DAPI_H + +#include "main.h" +#include "db.h" +#include "init.h" +#include "rpcserver.h" + +#include "util.h" + +#include + +#include "json/json_spirit_value.h" +#include "univalue/univalue.h" + +using namespace std; +using namespace json_spirit; + +class CDAPI +{ +private: + CDAPI(); + +public: + + static bool Execute(Object& obj); + static bool ValidateSignature(Object& obj); + static bool GetProfile(Object& obj); + static bool SetProfile(Object& obj); + static bool GetProfileData(Object& obj); + static bool SetProfileData(Object& obj); + static bool SendMessage(Object& obj); + static bool SendBroadcast(Object& obj); + +}; + +#endif \ No newline at end of file diff --git a/src/evo/enduser.cpp b/src/evo/enduser.cpp new file mode 100644 index 000000000000..29f0e0772ce7 --- /dev/null +++ b/src/evo/enduser.cpp @@ -0,0 +1,26 @@ + + +#include "enduser.h" + +#include "main.h" +#include "db.h" +#include "init.h" +#include "rpcserver.h" +#include "utilmoneystr.h" + +#include "util.h" + +#include + +#include "univalue/univalue.h" + +#include +using namespace json_spirit; +using namespace std; + +bool CEndUser::Load() +{ + obj.clear(); + obj.push_back(Pair("name", "evan")); + return true; +} \ No newline at end of file diff --git a/src/evo/enduser.h b/src/evo/enduser.h new file mode 100644 index 000000000000..aeba1c18b17f --- /dev/null +++ b/src/evo/enduser.h @@ -0,0 +1,40 @@ + + +// Copyright (c) 2014-2015 The Dash developers + +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + + +#ifndef DASHDRIVE_USER_H +#define DASHDRIVE_USER_H + +#include "main.h" +#include "db.h" +#include "init.h" +#include "rpcserver.h" + +#include "util.h" + +#include + +#include "json/json_spirit_value.h" +#include "univalue/univalue.h" + +using namespace std; +using namespace json_spirit; + +class CEndUser +{ +private: + Object obj; + std::string strPath; + CEndUser(std::string strPathIn) {strPath = strPathIn;} + +public: + + bool Load(); + bool Save() {return true;}; +}; + +#endif \ No newline at end of file diff --git a/src/evo/file.cpp b/src/evo/file.cpp new file mode 100644 index 000000000000..584a09f64f8b --- /dev/null +++ b/src/evo/file.cpp @@ -0,0 +1,85 @@ + +#include "util.h" +#include "init.h" + +#include "addrman.h" +#include "amount.h" +#include "checkpoints.h" +#include "compat/sanity.h" +#include "key.h" +#include "main.h" +#include "file.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "main.h" +#include "base58.h" + +#include +#include "json/json_spirit.h" +#include "json/json_spirit_value.h" + +#include +#include + + +using namespace boost; +using namespace std; +using namespace json_spirit; + + +// CDriveFile --- + +CDriveFile::CDriveFile() +{ + LOCK(cs); + strMagicMessage = "CDriveFile"; + fDirty = false; +} + +CDriveFile::CDriveFile(const std::string strPathIn) +{ + LOCK(cs); + strPath = strPathIn; + Read(); + fDirty = false; +} + + +CDriveFile::ReadResult CDriveFile::Read() +{ + std::ifstream t(strPath); + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + json_spirit::Value val; + + bool fSuccess = json_spirit::read(str, val); + if (fSuccess) { + obj = val.get_obj(); + return Ok; + } + + return FileError; +} + +bool CDriveFile::Write() +{ + LOCK(cs); + + ofstream os( strPath ); + write( obj, os ); + os.close(); + + + return false; +} diff --git a/src/evo/file.h b/src/evo/file.h new file mode 100644 index 000000000000..6e6a732d00a0 --- /dev/null +++ b/src/evo/file.h @@ -0,0 +1,110 @@ + + +#ifndef DASHDRIVE_FILE_H +#define DASHDRIVE_FILE_H + +#include "init.h" + +#include "addrman.h" +#include "amount.h" +#include "checkpoints.h" +#include "compat/sanity.h" +#include "key.h" +#include "main.h" +#include "file.h" + +#include +#include + + +#include "sync.h" +#include "net.h" +#include "util.h" +#include "base58.h" + + +#include +#include +#include +#include +#include +#include + +#include "json/json_spirit_value.h" +#include "univalue/univalue.h" + +using namespace json_spirit; +using namespace std; + + +// TODO: What include is required for this? +#define CLIENT_VERSION 1 + +boost::filesystem::path GetDataDirectory() +{ + string strDataDir2 = GetArg("-datadir2", ""); + if(strDataDir2 != "") return strDataDir2; + + namespace fs = boost::filesystem; + // Windows < Vista: C:\Documents and Settings\Username\Application Data\Dash + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Dash + // Mac: ~/Library/Application Support/Dash + // Unix: ~/.dash +#ifdef WIN32 + // Windows + return GetSpecialFolderPath(CSIDL_APPDATA) / "Dash"; +#else + fs::path pathRet; + char* pszHome = getenv("HOME"); + if (pszHome == NULL || strlen(pszHome) == 0) + pathRet = fs::path("/"); + else + pathRet = fs::path(pszHome); +#ifdef MAC_OSX + // Mac + pathRet /= "Library/Application Support"; + TryCreateDirectory(pathRet); + return pathRet / "DashData"; +#else + // Unix + return pathRet / ".dash-data"; +#endif +#endif +} + +class CDriveFile +{ +private: + // critical section to protect the inner data structures + mutable CCriticalSection cs; + string strMagicMessage; + string strPath; + Object obj; + bool fDirty; + +public: + + enum ReadResult { + Ok, + FileError, + HashReadError, + IncorrectHash, + IncorrectMagicMessage, + IncorrectMagicNumber, + IncorrectFormat + }; + + CDriveFile(); + CDriveFile(const string strPathIn); + + static CDriveFile GetNextIncrementalFileInFolder(const string strFolderIn); + + bool Exists(); + ReadResult Read(); + bool Write(); + +}; + + +#endif + diff --git a/src/init.cpp b/src/init.cpp index db615b4088ef..8071d5244302 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -409,7 +409,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += " -testnet " + _("Use the test network") + "\n"; strUsage += " -litemode= " + strprintf(_("Disable all Dash specific functionality (Masternodes, Darksend, InstantX, Budgeting) (0-1, default: %u)"), 0) + "\n"; - strUsage += "\n" + _("Masternode options:") + "\n"; + strUsage += "\n" + _("Masternode options:") + "\n"; + + strUsage += " -eventnotify= " + _("Send event to dash-2t to allow propagation to endusers (%s in cmd is replaced by event data)") + "\n"; strUsage += " -masternode= " + strprintf(_("Enable the client to act as a masternode (0-1, default: %u)"), 0) + "\n"; strUsage += " -mnconf= " + strprintf(_("Specify masternode configuration file (default: %s)"), "masternode.conf") + "\n"; strUsage += " -mnconflock= " + strprintf(_("Lock masternodes from masternode configuration file (default: %u)"), 1) + "\n"; @@ -478,6 +480,15 @@ static void BlockNotifyCallback(const uint256& hashNewTip) boost::thread t(runCommand, strCmd); // thread runs free } +void EventNotify(const std::string& strEvent) +{ + std::string strCmd = GetArg("-eventnotify", ""); + + boost::replace_all(strCmd, "%s", strEvent); + boost::thread t(runCommand, strCmd); // thread runs free +} + + struct CImportingNow { CImportingNow() { diff --git a/src/init.h b/src/init.h index 36300eadefb4..12a871f00d2e 100644 --- a/src/init.h +++ b/src/init.h @@ -22,6 +22,7 @@ bool ShutdownRequested(); void Shutdown(); void PrepareShutdown(); bool AppInit2(boost::thread_group& threadGroup); +void EventNotify(const std::string& strEvent); /** The help message mode determines what help message to show */ enum HelpMessageMode { diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 4844f6567373..343524b660ad 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -99,6 +99,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "mnbudget", 8 }, { "mnbudgetvoteraw", 1 }, { "mnbudgetvoteraw", 4 }, + //{ "dapi", 0 }, }; class CRPCConvertTable diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp new file mode 100644 index 000000000000..3940f7587710 --- /dev/null +++ b/src/rpcdapi.cpp @@ -0,0 +1,65 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Dash developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "main.h" +#include "db.h" +#include "init.h" +#include "rpcserver.h" +#include "utilmoneystr.h" +#include "evo/dapi.h" +#include "evo/file.h" + +#include "util.h" + +#include + +#include "json/json_spirit_value.h" +#include "univalue/univalue.h" + +#include +using namespace json_spirit; +using namespace std; + +/* + More Information About DAPI + + This uses a simple json interface to execute commands on the network through DAPI. + To run a daemon and take commands from the network, you will also need to run the server in + the dash-t2 package. + +*/ + + +Value dapi(const Array& params, bool fHelp) +{ + + if (fHelp || params.size() < 1) + throw runtime_error( + "dapi \"json_command\"\n" + "Execute a command via DAPI\n" + ); + + /* + + + Executing web events: + + dashd --datadir=example --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" --daemon + dash-cli dapi "{\"txid\":\"myid\",\"aeou\":\"123\",\"vout\":\"0\"}" "{\"address\":0.01}" + + dash_t2 --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=% + */ + + std::string strCommand = params[0].get_str(); + json_spirit::Value val; + + bool fSuccess = json_spirit::read_string(strCommand, val); + if (fSuccess) { + Object obj = val.get_obj(); + CDAPI::Execute(obj); + } + + return "ok"; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d5eb1efd3346..f08c3b0f1cb6 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -316,6 +316,8 @@ static const CRPCCommand vRPCCommands[] = { "dash", "mnfinalbudget", &mnfinalbudget, true, true, false }, { "dash", "mnsync", &mnsync, true, true, false }, { "dash", "spork", &spork, true, true, false }, + { "dash", "dapi", &dapi, true, true, false }, + #ifdef ENABLE_WALLET { "dash", "darksend", &darksend, false, false, true }, /* not threadSafe because of SendMoney */ diff --git a/src/rpcserver.h b/src/rpcserver.h index ff8d556173f6..64f004244305 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -235,6 +235,7 @@ extern json_spirit::Value mnbudget(const json_spirit::Array& params, bool fHelp) extern json_spirit::Value mnbudgetvoteraw(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value mnfinalbudget(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value mnsync(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dapi(const json_spirit::Array& params, bool fHelp); // in rest.cpp extern bool HTTPReq_REST(AcceptedConnection *conn, From 1b8279e1f32d9fc69baba9862a5ad5cd7e2862a0 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 15 Dec 2015 09:51:10 -0700 Subject: [PATCH 03/51] added dapif for files --- src/rpcclient.cpp | 1 - src/rpcdapi.cpp | 34 ++++++++++++++++++++++++++++++++++ src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 343524b660ad..4844f6567373 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -99,7 +99,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "mnbudget", 8 }, { "mnbudgetvoteraw", 1 }, { "mnbudgetvoteraw", 4 }, - //{ "dapi", 0 }, }; class CRPCConvertTable diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 3940f7587710..b41df29a9b5a 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -63,3 +63,37 @@ Value dapi(const Array& params, bool fHelp) return "ok"; } + +Value dapif(const Array& params, bool fHelp) +{ + + if (fHelp || params.size() < 1) + throw runtime_error( + "dapif \"json_file\"\n" + "Execute a command via DAPI\n" + ); + + /* + Executing web events: + + dashd --datadir=example --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" --daemon + dash-cli dapi "{\"txid\":\"myid\",\"aeou\":\"123\",\"vout\":\"0\"}" "{\"address\":0.01}" + + dash_t2 --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=% + */ + + std::string strPath = params[0].get_str(); + std::ifstream t(strPath); + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + json_spirit::Value val; + + bool fSuccess = json_spirit::read_string(str, val); + if (fSuccess) { + Object obj = val.get_obj(); + CDAPI::Execute(obj); + } + + return "ok"; +} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f08c3b0f1cb6..902719097b99 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -317,6 +317,7 @@ static const CRPCCommand vRPCCommands[] = { "dash", "mnsync", &mnsync, true, true, false }, { "dash", "spork", &spork, true, true, false }, { "dash", "dapi", &dapi, true, true, false }, + { "dash", "dapif", &dapif, true, true, false }, #ifdef ENABLE_WALLET { "dash", "darksend", &darksend, false, false, true }, /* not threadSafe because of SendMoney */ diff --git a/src/rpcserver.h b/src/rpcserver.h index 64f004244305..bb5dafb95cac 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -236,6 +236,7 @@ extern json_spirit::Value mnbudgetvoteraw(const json_spirit::Array& params, bool extern json_spirit::Value mnfinalbudget(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value mnsync(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dapi(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value dapif(const json_spirit::Array& params, bool fHelp); // in rest.cpp extern bool HTTPReq_REST(AcceptedConnection *conn, From 29acb53a230f6ec1aec6735aa607621c79848691 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 15 Dec 2015 13:28:51 -0700 Subject: [PATCH 04/51] fixed dep problems --- src/Makefile.am | 3 +++ src/evo/dapi.cpp | 5 ++++ src/evo/dapi.h | 2 ++ src/evo/file.cpp | 38 +++++--------------------- src/evo/file.h | 45 +++++++++++++++++-------------- src/rpcdapi.cpp | 12 ++++++--- src/test/data/dapi-get-profile.js | 1 + 7 files changed, 51 insertions(+), 55 deletions(-) create mode 100644 src/test/data/dapi-get-profile.js diff --git a/src/Makefile.am b/src/Makefile.am index 744f1c4773e7..61313c5792a0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,6 +182,7 @@ libbitcoin_server_a_SOURCES = \ checkpoints.cpp \ evo/file.cpp \ evo/dapi.cpp \ + json/json_spirit_writer.cpp \ init.cpp \ leveldbwrapper.cpp \ main.cpp \ @@ -294,6 +295,8 @@ libbitcoin_common_a_SOURCES = \ chainparams.cpp \ coins.cpp \ compressor.cpp \ + evo/file.cpp \ + evo/dapi.cpp \ primitives/block.cpp \ primitives/transaction.cpp \ core_read.cpp \ diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 1e740eb65259..f14f29d59b22 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -11,6 +11,8 @@ #include "init.h" #include "dapi.h" #include "file.h" +#include "json/json_spirit.h" +#include "json/json_spirit_value.h" /* @@ -71,6 +73,9 @@ bool CDAPI::GetProfile(Object& obj) } */ + CDriveFile file("/Users/evan/Desktop/dash/src/test/data/dapi-get-profile.js"); + file.obj = obj; + file.WriteContents(); EventNotify("{\"name\":\"value\"}"); return true; diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 42dcdd113bf3..ac77d76bd8bb 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -15,6 +15,8 @@ #include "rpcserver.h" #include "util.h" +#include "file.h" +#include "json/json_spirit.h" #include diff --git a/src/evo/file.cpp b/src/evo/file.cpp index 584a09f64f8b..02c3ffcb86d3 100644 --- a/src/evo/file.cpp +++ b/src/evo/file.cpp @@ -1,35 +1,22 @@ -#include "util.h" -#include "init.h" - -#include "addrman.h" -#include "amount.h" -#include "checkpoints.h" -#include "compat/sanity.h" -#include "key.h" #include "main.h" #include "file.h" +#include "util.h" +#include "init.h" +#include "base58.h" #include #include #include -#include -#include -#include -#include -#include -#include - -#include "main.h" -#include "base58.h" - -#include #include "json/json_spirit.h" #include "json/json_spirit_value.h" +#include "json/json_spirit_writer.h" +#include #include #include +#include using namespace boost; @@ -50,7 +37,6 @@ CDriveFile::CDriveFile(const std::string strPathIn) { LOCK(cs); strPath = strPathIn; - Read(); fDirty = false; } @@ -71,15 +57,3 @@ CDriveFile::ReadResult CDriveFile::Read() return FileError; } - -bool CDriveFile::Write() -{ - LOCK(cs); - - ofstream os( strPath ); - write( obj, os ); - os.close(); - - - return false; -} diff --git a/src/evo/file.h b/src/evo/file.h index 6e6a732d00a0..ce30a900b029 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -4,7 +4,7 @@ #define DASHDRIVE_FILE_H #include "init.h" - +#include "base58.h" #include "addrman.h" #include "amount.h" #include "checkpoints.h" @@ -13,26 +13,21 @@ #include "main.h" #include "file.h" -#include -#include - - -#include "sync.h" -#include "net.h" -#include "util.h" -#include "base58.h" - - -#include -#include #include -#include -#include -#include +#include "json/json_spirit.h" #include "json/json_spirit_value.h" +#include "json/json_spirit_writer.h" + #include "univalue/univalue.h" +#include +#include +#include +#include +#include + + using namespace json_spirit; using namespace std; @@ -79,10 +74,10 @@ class CDriveFile mutable CCriticalSection cs; string strMagicMessage; string strPath; - Object obj; bool fDirty; public: + Object obj; enum ReadResult { Ok, @@ -97,11 +92,21 @@ class CDriveFile CDriveFile(); CDriveFile(const string strPathIn); - static CDriveFile GetNextIncrementalFileInFolder(const string strFolderIn); - bool Exists(); ReadResult Read(); - bool Write(); + + bool WriteContents() + { + LOCK(cs); + + ofstream os( strPath ); + json_spirit::write( obj, os ); + os.close(); + + + return false; + } + }; diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index b41df29a9b5a..f0bae2b1999f 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -54,14 +54,17 @@ Value dapi(const Array& params, bool fHelp) std::string strCommand = params[0].get_str(); json_spirit::Value val; - + + printf("%s\n", strCommand.c_str()); + bool fSuccess = json_spirit::read_string(strCommand, val); if (fSuccess) { Object obj = val.get_obj(); CDAPI::Execute(obj); + return "ok"; } - return "ok"; + return "error"; } Value dapif(const Array& params, bool fHelp) @@ -87,13 +90,16 @@ Value dapif(const Array& params, bool fHelp) std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); + printf("%s\n", str.c_str()); + json_spirit::Value val; bool fSuccess = json_spirit::read_string(str, val); if (fSuccess) { Object obj = val.get_obj(); CDAPI::Execute(obj); + return "ok"; } - return "ok"; + return "error"; } diff --git a/src/test/data/dapi-get-profile.js b/src/test/data/dapi-get-profile.js new file mode 100644 index 000000000000..ea5f588e006b --- /dev/null +++ b/src/test/data/dapi-get-profile.js @@ -0,0 +1 @@ +"{\"object\":\"dapi_command\",\"data\":{\"command\":\"get-profile\"}} \ No newline at end of file From 24d755b81369c1d483ab87bf7eddcd9c523a6c32 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 15 Dec 2015 13:33:35 -0700 Subject: [PATCH 05/51] fixed js file --- src/rpcdapi.cpp | 6 ++++-- src/test/data/dapi-get-profile.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index f0bae2b1999f..20aaa1f1d745 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -64,7 +64,8 @@ Value dapi(const Array& params, bool fHelp) return "ok"; } - return "error"; + //TODO: add better errors + return "parse error"; } Value dapif(const Array& params, bool fHelp) @@ -101,5 +102,6 @@ Value dapif(const Array& params, bool fHelp) return "ok"; } - return "error"; + //TODO: add better errors + return "parse error"; } diff --git a/src/test/data/dapi-get-profile.js b/src/test/data/dapi-get-profile.js index ea5f588e006b..ef92244880d0 100644 --- a/src/test/data/dapi-get-profile.js +++ b/src/test/data/dapi-get-profile.js @@ -1 +1 @@ -"{\"object\":\"dapi_command\",\"data\":{\"command\":\"get-profile\"}} \ No newline at end of file +{"object":"dapi_command","data":{"command":"get-profile"}} \ No newline at end of file From 2a3ec03ccd462600a94241db209b7ad852be15af Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 15 Dec 2015 14:31:49 -0700 Subject: [PATCH 06/51] fixed dep issue --- src/Makefile.am | 1 + src/evo/dapi.cpp | 136 +++++++++++++++++++++++++++++------------------ src/evo/dapi.h | 10 +++- src/evo/file.cpp | 18 ------- src/evo/file.h | 21 +++++++- 5 files changed, 114 insertions(+), 72 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 61313c5792a0..8577a9b8b7c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -182,6 +182,7 @@ libbitcoin_server_a_SOURCES = \ checkpoints.cpp \ evo/file.cpp \ evo/dapi.cpp \ + json/json_spirit_reader.cpp \ json/json_spirit_writer.cpp \ init.cpp \ leveldbwrapper.cpp \ diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index f14f29d59b22..4dc7d41b3687 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -32,6 +32,9 @@ } */ + + + bool CDAPI::Execute(Object& obj) { std::string strObject = json_spirit::find_value(obj, "object").get_str(); @@ -65,66 +68,95 @@ bool CDAPI::ValidateSignature(Object& obj) bool CDAPI::GetProfile(Object& obj) { /* - { - "command" : "get-profile", - "my_uid" : 0, - "target_uid" : 0, - "signature" : "SIGNATURE", + { + "object" : "dapi_command", + "data" : { + “command” : ”get-profile”, + “my_uid” : INT64, + “target_uid” : INT64, + “signature” : ‘’, + “fields” : [“fname”, “lname”] + } } */ - CDriveFile file("/Users/evan/Desktop/dash/src/test/data/dapi-get-profile.js"); - file.obj = obj; - file.WriteContents(); + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + if(strObject != "dapi_command") return false; + + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + + CDriveFile file(GetProfileFile(strUID)); + //if(!file.Exists()) return false; + file.Read(); - EventNotify("{\"name\":\"value\"}"); + // Object ret; + // ret.PushKV("object", "dapi_result"); + // ret.PushKV("data", "result"); + + // string sret; + // json_spirit::write( obj, sret ); + + // EventNotify(sret); return true; } bool CDAPI::SetProfile(Object& obj) { /* - { - "command" : "set-profile", - "my_uid" : 0, - "target_uid" : 0, - "signature" : "SIGNATURE", - "fields" : ["fname", "lname"] + { + "object" : "dapi_command", + "data" : { + "command" = "set-profile", + "my_uid" = INT64, + "target_uid" = INT64, + "signature" = "" } + } + */ + + CDriveFile file("/Users/evan/Desktop/dash/src/test/data/dapi-get-profile.js"); + file.obj = obj; + file.WriteContents(); + + return true; } -bool CDAPI::GetProfileData(Object& obj) +bool CDAPI::GetPrivateData(Object& obj) { /* - REQUIRED JSON - { - "command" : "get-private-data", - "my_uid" : 0, - "target_uid" : 0, - "signature" : "SIGNATURE", - "slot" : 1 + { + "object" : "dapi_command", + "data" : { + "command" = "get-private-data", + "my_uid" = UID, + "target_uid" = UID, + "signature" = ‘’, + "slot" = 1 } + } */ return true; } -bool CDAPI::SetProfileData(Object& obj) +bool CDAPI::SetPrivateData(Object& obj) { /* - REQUIRED JSON - { - "command" : "set-profile-data", - "my_uid" : 0, - "target_uid" : 0, - "signature" : "SIGNATURE" - "update" : { - "email" : "evan@dash.org" - } + { + "object" : "dapi_command", + "data" : { + "command" : "set-private-data", + "my_uid" : INT64, + "target_uid" : INT64, + "signature" : "SIGNATURE", + "slot" : 1, + "payload" : JSON_WEB_ENCRYPTION } + } */ return true; @@ -135,16 +167,17 @@ bool CDAPI::SetProfileData(Object& obj) bool CDAPI::SendMessage(Object& obj) { /* - REQUIRED JSON - { - "command" : "send-message", - "my_uid" : 0, - "target_uid" : 0, - "signature" : "SIGNATURE" - "update" : { - "email" : "evan@dash.org" - } + { + "object" : "dapi_command", + "data" : { + "command" = "message", + "subcommand" = "(available subcommands)", + "my_uid" = UID, + "target_uid" = UID, + "signature" = ‘’, + "payload" = ENCRYPTED } + } */ return true; @@ -154,16 +187,17 @@ bool CDAPI::SendMessage(Object& obj) bool CDAPI::SendBroadcast(Object& obj) { /* - REQUIRED JSON - { - 'command' : 'set-profile-data', - 'my_uid' : 0, - 'target_uid' : 0, - 'signature' : "SIGNATURE" - 'update' : { - "email" : "evan@dash.org" - } + { + "object" : "dapi_command", + "data" : { + "command" = "broadcast", + "subcommand" = "tx", //can support multiple message commands + "my_uid" = UID, + "target_uid" = UID, + "signature" = ‘’, + "payload" = SERIALIZED_BASE64_ENCODED } + } */ return true; diff --git a/src/evo/dapi.h b/src/evo/dapi.h index ac77d76bd8bb..92ea0fb9cc67 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -26,6 +26,12 @@ using namespace std; using namespace json_spirit; +std::string GetProfileFile(std::string strUID) +{ + boost::filesystem::path filename = GetDataDirectory() / strUID; + return filename.c_str(); +} + class CDAPI { private: @@ -37,8 +43,8 @@ class CDAPI static bool ValidateSignature(Object& obj); static bool GetProfile(Object& obj); static bool SetProfile(Object& obj); - static bool GetProfileData(Object& obj); - static bool SetProfileData(Object& obj); + static bool GetPrivateData(Object& obj); + static bool SetPrivateData(Object& obj); static bool SendMessage(Object& obj); static bool SendBroadcast(Object& obj); diff --git a/src/evo/file.cpp b/src/evo/file.cpp index 02c3ffcb86d3..73538468c6be 100644 --- a/src/evo/file.cpp +++ b/src/evo/file.cpp @@ -39,21 +39,3 @@ CDriveFile::CDriveFile(const std::string strPathIn) strPath = strPathIn; fDirty = false; } - - -CDriveFile::ReadResult CDriveFile::Read() -{ - std::ifstream t(strPath); - std::string str((std::istreambuf_iterator(t)), - std::istreambuf_iterator()); - - json_spirit::Value val; - - bool fSuccess = json_spirit::read(str, val); - if (fSuccess) { - obj = val.get_obj(); - return Ok; - } - - return FileError; -} diff --git a/src/evo/file.h b/src/evo/file.h index ce30a900b029..bd655e94f78e 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -13,6 +13,10 @@ #include "main.h" #include "file.h" + + + + #include #include "json/json_spirit.h" @@ -93,7 +97,22 @@ class CDriveFile CDriveFile(const string strPathIn); bool Exists(); - ReadResult Read(); + ReadResult Read() + { + std::ifstream t(strPath); + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + + json_spirit::Value val; + + bool fSuccess = json_spirit::read(str, val); + if (fSuccess) { + obj = val.get_obj(); + return Ok; + } + + return FileError; + } bool WriteContents() { From 6738486c0214ccb155ddf020770a778029bdff45 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 16 Dec 2015 09:41:07 -0700 Subject: [PATCH 07/51] reading and writing user profiles --- src/evo/dapi.cpp | 104 +++++++++++++++++++++++++----- src/evo/dapi.h | 24 ++++++- src/evo/file.h | 30 +++++---- src/rpcdapi.cpp | 2 +- src/test/data/dapi-get-profile.js | 11 +++- 5 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 4dc7d41b3687..31bcabd1692e 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -43,14 +43,21 @@ bool CDAPI::Execute(Object& obj) Object objData = json_spirit::find_value(obj, "data").get_obj(); string strCommand = json_spirit::find_value(objData, "command").get_str(); - printf("%s\n", strCommand.c_str()); + printf("1 %s\n", strCommand.c_str()); if(strCommand == "get-profile") { GetProfile(obj); return true; } - return true; + printf("2 %d\n", strCommand == "set-profile"); + if (strCommand == "set-profile") { + printf("here\n"); + SetProfile(obj); + return true; + } + + return false; } bool CDAPI::ValidateSignature(Object& obj) @@ -83,21 +90,39 @@ bool CDAPI::GetProfile(Object& obj) std::string strObject = json_spirit::find_value(obj, "object").get_str(); if(strObject != "dapi_command") return false; + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + + printf("4 %s\n", strUID.c_str()); + + // open the file and read it CDriveFile file(GetProfileFile(strUID)); - //if(!file.Exists()) return false; + printf("5 %s\n", GetProfileFile(strUID).c_str()); + + if(!file.Exists()) return false; file.Read(); - // Object ret; - // ret.PushKV("object", "dapi_result"); - // ret.PushKV("data", "result"); + printf("6 %s\n", GetProfileFile(strUID).c_str()); - // string sret; - // json_spirit::write( obj, sret ); + // send the user back the results of the query + Object ret; + ret.push_back(Pair("object", "dapi_result")); + ret.push_back(Pair("data", file.obj)); - // EventNotify(sret); + //TODO: this is terrible, we need to correctly clean and escape the json :) + std::stringstream ss; + json_spirit::write( ret, ss ); + std::string strJson = escapeJsonString("'" + ss.str() + "'"); + strJson.replace(0,1,"\""); + strJson.replace(strJson.size()-1,1,"\""); + + printf("7 %s\n", strJson.c_str()); + + EventNotify(strJson); return true; } @@ -107,20 +132,67 @@ bool CDAPI::SetProfile(Object& obj) { "object" : "dapi_command", "data" : { - "command" = "set-profile", - "my_uid" = INT64, - "target_uid" = INT64, - "signature" = "" + "command": "set-profile", + "my_uid": INT64, + "target_uid": INT64, + "signature": "", + "update" : [ + {"field":"name","value":"newvalue"} + ] } } */ + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + if(strObject != "dapi_command") return false; + + printf("2 %s\n", strObject.c_str()); + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + const Array& arrDataUpdate = json_spirit::find_value(objData, "update").get_array(); + string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + + printf("3 %s\n", strUID.c_str()); + + // open the file and read it + CDriveFile file(GetProfileFile(strUID)); + if(!file.Exists()) return false; + file.Read(); + + std::map mapObj; + json_spirit::obj_to_map(file.obj, mapObj); + + printf("4 %s\n", GetProfileFile(strUID).c_str()); + + for( unsigned int i = 0; i < arrDataUpdate.size(); ++i ) + { + Object tmp = arrDataUpdate[i].get_obj(); + string strField = json_spirit::find_value(tmp, "field").get_str(); + string strValue = json_spirit::find_value(tmp, "value").get_str(); + + printf("5 %s %s\n", strField.c_str(), strValue.c_str()); + + // string& strUpdate = json_spirit::find_value(obj, strField).get_str(); + // strUpdate = strValue; + + //update the users file, NOTE: this is completely insecure for the prototype (see the paper for security model!) + //file.obj[strField] = strValue; + mapObj[strField] = strValue; + } + + json_spirit::map_to_obj(mapObj, file.obj); + file.Write(); + + // send the user back the results of the query + Object ret; + ret.push_back(Pair("object", "dapi_result")); + ret.push_back(Pair("data", file.obj)); - CDriveFile file("/Users/evan/Desktop/dash/src/test/data/dapi-get-profile.js"); - file.obj = obj; - file.WriteContents(); + std::stringstream ss; + json_spirit::write( obj, ss ); + EventNotify(ss.str()); return true; } diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 92ea0fb9cc67..64b733b530bc 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -22,16 +22,38 @@ #include "json/json_spirit_value.h" #include "univalue/univalue.h" +#include +#include using namespace std; using namespace json_spirit; std::string GetProfileFile(std::string strUID) { - boost::filesystem::path filename = GetDataDirectory() / strUID; + boost::filesystem::path filename = GetDataDirectory() / "users" / strUID; return filename.c_str(); } +std::string escapeJsonString(const std::string& input) { + std::ostringstream ss; + for (auto iter = input.cbegin(); iter != input.cend(); iter++) { + //C++98/03: + //for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { + switch (*iter) { + case '\\': ss << "\\\\"; break; + case '"': ss << "\\\""; break; + case '/': ss << "\\/"; break; + case '\b': ss << "\\b"; break; + case '\f': ss << "\\f"; break; + case '\n': ss << "\\n"; break; + case '\r': ss << "\\r"; break; + case '\t': ss << "\\t"; break; + default: ss << *iter; break; + } + } + return ss.str(); +} + class CDAPI { private: diff --git a/src/evo/file.h b/src/evo/file.h index bd655e94f78e..3f9002511964 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -13,24 +13,19 @@ #include "main.h" #include "file.h" - - - - -#include +#include +#include +#include +#include +#include #include "json/json_spirit.h" #include "json/json_spirit_value.h" #include "json/json_spirit_writer.h" +#include #include "univalue/univalue.h" -#include -#include -#include -#include -#include - using namespace json_spirit; using namespace std; @@ -96,7 +91,16 @@ class CDriveFile CDriveFile(); CDriveFile(const string strPathIn); - bool Exists(); + bool Exists() + { + if ( boost::filesystem::exists( strPath ) ) + { + return true; + } + + return false; + } + ReadResult Read() { std::ifstream t(strPath); @@ -114,7 +118,7 @@ class CDriveFile return FileError; } - bool WriteContents() + bool Write() { LOCK(cs); diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 20aaa1f1d745..997b876139ed 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -83,7 +83,7 @@ Value dapif(const Array& params, bool fHelp) dashd --datadir=example --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" --daemon dash-cli dapi "{\"txid\":\"myid\",\"aeou\":\"123\",\"vout\":\"0\"}" "{\"address\":0.01}" - dash_t2 --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=% + dash_t2 --datadir2=/Users/evan/.dash-data/ --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" */ std::string strPath = params[0].get_str(); diff --git a/src/test/data/dapi-get-profile.js b/src/test/data/dapi-get-profile.js index ef92244880d0..15bd01f7ba5a 100644 --- a/src/test/data/dapi-get-profile.js +++ b/src/test/data/dapi-get-profile.js @@ -1 +1,10 @@ -{"object":"dapi_command","data":{"command":"get-profile"}} \ No newline at end of file +{ + "object" : "dapi_command", + "data" : { + "command" : "get-profile", + "my_uid" : "1337", + "target_uid" : "1337", + "signature" : "SIG", + "fields" : ["fname", "lname"] + } +} \ No newline at end of file From f8f8a945a12b5b4948438b6c9096062b805f7d97 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 16 Dec 2015 09:41:38 -0700 Subject: [PATCH 08/51] set-profile-js --- src/test/data/dapi-set-profile.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/data/dapi-set-profile.js diff --git a/src/test/data/dapi-set-profile.js b/src/test/data/dapi-set-profile.js new file mode 100644 index 000000000000..e0bb9b81bcee --- /dev/null +++ b/src/test/data/dapi-set-profile.js @@ -0,0 +1,12 @@ +{ + "object" : "dapi_command", + "data" : { + "command": "set-profile", + "my_uid": "1337", + "target_uid": "1337", + "signature": "", + "update" : [ + {"field":"name","value":"uberevan"} + ] + } +} From 2fe79b2547af0f7d601838838882738668a8580f Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 16 Dec 2015 10:40:02 -0700 Subject: [PATCH 09/51] get and set private data --- src/evo/dapi.cpp | 143 +++++++++++++++++++++++++++++++++++++++-------- src/evo/dapi.h | 10 ++++ 2 files changed, 131 insertions(+), 22 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 31bcabd1692e..6b06b85e3e25 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -32,6 +32,31 @@ } */ +Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile, bool fSuccess) +{ + Object retData; + retData.push_back(Pair("id", nCommandID)); + retData.push_back(Pair("command", strCommand)); + retData.push_back(Pair("success", fSuccess)); + retData.push_back(Pair("data", objFile)); + + Object ret; + ret.push_back(Pair("object", "dapi_result")); + ret.push_back(Pair("data", retData)); + + return ret; +} + +std::string SerializeJsonFromObject(Object objToSerialize) +{ + //TODO: this is terrible, we need to correctly clean and escape the json :) + std::stringstream ss; + json_spirit::write( objToSerialize, ss ); + std::string strJson = escapeJsonString("'" + ss.str() + "'"); + strJson.replace(0,1,"\""); + strJson.replace(strJson.size()-1,1,"\""); + return strJson; +} @@ -48,13 +73,21 @@ bool CDAPI::Execute(Object& obj) if(strCommand == "get-profile") { GetProfile(obj); return true; - } - - printf("2 %d\n", strCommand == "set-profile"); - if (strCommand == "set-profile") { - printf("here\n"); + } else if (strCommand == "set-profile") { SetProfile(obj); return true; + } else if (strCommand == "set-private-data") { + SetPrivateData(obj); + return true; + } else if (strCommand == "get-private-data") { + GetPrivateData(obj); + return true; + } else if (strCommand == "send-message") { + SendMessage(obj); + return true; + } else if (strCommand == "send-broadcast") { + SendBroadcast(obj); + return true; } return false; @@ -109,16 +142,8 @@ bool CDAPI::GetProfile(Object& obj) printf("6 %s\n", GetProfileFile(strUID).c_str()); // send the user back the results of the query - Object ret; - ret.push_back(Pair("object", "dapi_result")); - ret.push_back(Pair("data", file.obj)); - - //TODO: this is terrible, we need to correctly clean and escape the json :) - std::stringstream ss; - json_spirit::write( ret, ss ); - std::string strJson = escapeJsonString("'" + ss.str() + "'"); - strJson.replace(0,1,"\""); - strJson.replace(strJson.size()-1,1,"\""); + Object ret = GetResultObject(1000, "get-profile", file.obj, true); + std::string strJson = SerializeJsonFromObject(ret); printf("7 %s\n", strJson.c_str()); @@ -184,15 +209,12 @@ bool CDAPI::SetProfile(Object& obj) json_spirit::map_to_obj(mapObj, file.obj); file.Write(); - // send the user back the results of the query - Object ret; - ret.push_back(Pair("object", "dapi_result")); - ret.push_back(Pair("data", file.obj)); + Object ret = GetResultObject(1000, "set-profile", file.obj, true); + std::string strJson = SerializeJsonFromObject(ret); - std::stringstream ss; - json_spirit::write( obj, ss ); + printf("7 %s\n", strJson.c_str()); - EventNotify(ss.str()); + EventNotify(strJson); return true; } @@ -212,6 +234,34 @@ bool CDAPI::GetPrivateData(Object& obj) } */ + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + if(strObject != "dapi_command") return false; + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + int nSlot = json_spirit::find_value(objData, "slot").get_int(); + if(nSlot < 1 || nSlot > 10) return false; + + printf("4 %s\n", strUID.c_str()); + + // open the file and read it + CDriveFile file(GetPrivateDataFile(strUID, nSlot)); + printf("5 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); + + if(!file.Exists()) return false; + file.Read(); + + // send the user back the results of the query + Object ret = GetResultObject(1000, "get-private-data", file.obj, true); + std::string strJson = SerializeJsonFromObject(ret); + + printf("7 %s\n", strJson.c_str()); + + EventNotify(strJson); + return true; } @@ -231,6 +281,55 @@ bool CDAPI::SetPrivateData(Object& obj) } */ + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + if(strObject != "dapi_command") return false; + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + int nSlot = json_spirit::find_value(objData, "slot").get_int(); + if(nSlot < 1 || nSlot > 10) return false; + + printf("4 %s\n", strUID.c_str()); + + // open the file and read it + CDriveFile file(GetPrivateDataFile(strUID, nSlot)); + printf("5 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); + + if(!file.Exists()) + { + printf("new %s\n"); + Object newObj; + newObj.push_back(Pair("access_times", 0)); + newObj.push_back(Pair("last_access", 0)); + newObj.push_back(Pair("payload", "")); + file.obj = newObj; + } + file.Read(); + + //update from new payload + std::map mapObj; + json_spirit::obj_to_map(file.obj, mapObj); + + string strPayload = json_spirit::find_value(objData, "payload").get_str(); + mapObj["payload"] = strPayload; + + json_spirit::map_to_obj(mapObj, file.obj); + file.Write(); + + + printf("6 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); + + // send the user back the results of the query + Object ret = GetResultObject(1000, "set-private-data", file.obj, true); + std::string strJson = SerializeJsonFromObject(ret); + + printf("7 %s\n", strJson.c_str()); + + EventNotify(strJson); + return true; } diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 64b733b530bc..cee2cc30145f 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -25,6 +25,8 @@ #include #include +#include + using namespace std; using namespace json_spirit; @@ -34,6 +36,14 @@ std::string GetProfileFile(std::string strUID) return filename.c_str(); } +std::string GetPrivateDataFile(std::string strUID, int nSlot) +{ + std::string strFilename = strUID + "." + boost::lexical_cast(nSlot); + boost::filesystem::path filename = GetDataDirectory() / "users" / strFilename; + return filename.c_str(); +} + + std::string escapeJsonString(const std::string& input) { std::ostringstream ss; for (auto iter = input.cbegin(); iter != input.cend(); iter++) { From 272c1acd1e9f8fc4f0281c7b8aac98ea5a59956d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 16 Dec 2015 10:40:20 -0700 Subject: [PATCH 10/51] get and set private data js --- src/test/data/dapi-get-private-data.js | 10 ++++++++++ src/test/data/dapi-set-private-data.js | 11 +++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/data/dapi-get-private-data.js create mode 100644 src/test/data/dapi-set-private-data.js diff --git a/src/test/data/dapi-get-private-data.js b/src/test/data/dapi-get-private-data.js new file mode 100644 index 000000000000..0b90d4cfbfc5 --- /dev/null +++ b/src/test/data/dapi-get-private-data.js @@ -0,0 +1,10 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "get-private-data", + "my_uid" : "1337", + "target_uid" : "1337", + "signature" : "SIG", + "slot" : 1 + } +} \ No newline at end of file diff --git a/src/test/data/dapi-set-private-data.js b/src/test/data/dapi-set-private-data.js new file mode 100644 index 000000000000..2c65ca1cc76c --- /dev/null +++ b/src/test/data/dapi-set-private-data.js @@ -0,0 +1,11 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "set-private-data", + "my_uid" : "1337", + "target_uid" : "1337", + "signature" : "SIG", + "slot" : 1, + "payload" : "AOEU" + } +} \ No newline at end of file From 0ee1650bf7f87e69084c95c104085eeb8fb77c52 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 16 Dec 2015 11:52:44 -0700 Subject: [PATCH 11/51] - Get/Set private data is working - Proper error handling - Broadcast transaction support --- src/evo/dapi.cpp | 172 +++++++++++++++++++------ src/evo/dapi.h | 3 +- src/test/data/dapi-broadcast-tx.js | 10 ++ src/test/data/dapi-get-private-data.js | 2 +- src/test/data/dapi-get-profile.js | 2 +- src/test/data/dapi-set-private-data.js | 2 +- src/test/data/dapi-set-profile.js | 2 +- 7 files changed, 147 insertions(+), 46 deletions(-) create mode 100644 src/test/data/dapi-broadcast-tx.js diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 6b06b85e3e25..8659cc15806f 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -7,6 +7,7 @@ #include "main.h" +#include "core_io.h" #include "db.h" #include "init.h" #include "dapi.h" @@ -14,13 +15,21 @@ #include "json/json_spirit.h" #include "json/json_spirit_value.h" + +int nError; +std::string strErrorMessage; +// error reporting + +void ResetErrorStatus() {nError = 0; strErrorMessage = "";} +void SetError(int nErrorIn, std::string strMessageIn) {nError = nErrorIn; strErrorMessage = strMessageIn;} + /* { "object" : "dash_budget_items", "data" : [ { "object" : "dash_budget", - "name" : "ds-liquidity", + "name" : "ds_liquidity", ... }, { "object" : "dash_budget", @@ -32,12 +41,13 @@ } */ -Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile, bool fSuccess) +Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile) { Object retData; retData.push_back(Pair("id", nCommandID)); retData.push_back(Pair("command", strCommand)); - retData.push_back(Pair("success", fSuccess)); + retData.push_back(Pair("error-id", nError)); + retData.push_back(Pair("error-message", strErrorMessage)); retData.push_back(Pair("data", objFile)); Object ret; @@ -47,6 +57,24 @@ Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile, return ret; } +Object GetMessageObject(int nCommandID, std::string strUserID, std::string strSubCommand, std::string strMessage) +{ + Object retData; + retData.push_back(Pair("id", nCommandID)); + retData.push_back(Pair("command", "send_message")); + retData.push_back(Pair("error-id", nError)); + retData.push_back(Pair("error-message", strErrorMessage)); + retData.push_back(Pair("target_uid", strUserID)); + retData.push_back(Pair("sub_command", strSubCommand)); + retData.push_back(Pair("payload", strMessage)); + + Object ret; + ret.push_back(Pair("object", "dapi_message")); + ret.push_back(Pair("data", retData)); + + return ret; +} + std::string SerializeJsonFromObject(Object objToSerialize) { //TODO: this is terrible, we need to correctly clean and escape the json :) @@ -62,6 +90,8 @@ std::string SerializeJsonFromObject(Object objToSerialize) bool CDAPI::Execute(Object& obj) { + ResetErrorStatus(); + std::string strObject = json_spirit::find_value(obj, "object").get_str(); if(strObject != "dapi_command") return false; @@ -70,26 +100,30 @@ bool CDAPI::Execute(Object& obj) printf("1 %s\n", strCommand.c_str()); - if(strCommand == "get-profile") { - GetProfile(obj); - return true; - } else if (strCommand == "set-profile") { - SetProfile(obj); - return true; - } else if (strCommand == "set-private-data") { - SetPrivateData(obj); - return true; - } else if (strCommand == "get-private-data") { - GetPrivateData(obj); - return true; - } else if (strCommand == "send-message") { - SendMessage(obj); - return true; - } else if (strCommand == "send-broadcast") { - SendBroadcast(obj); - return true; + if(strCommand == "get_profile") { + if(GetProfile(obj)) return true; + } else if (strCommand == "set_profile") { + if(SetProfile(obj)) return true; + } else if (strCommand == "set_private_data") { + if(SetPrivateData(obj)) return true; + } else if (strCommand == "get_private_data") { + if(GetPrivateData(obj)) return true; + } else if (strCommand == "send_message") { + if(SendMessage(obj)) return true; + } else if (strCommand == "broadcast_message") { + if(BroadcastMessage(obj)) return true; } + // unknown command + + // send the user back the results of the query + if(nError == 0) SetError(1000, "Unknown Command : " + strCommand); + Object result; + Object ret = GetResultObject(1000, strCommand, result); + std::string strJson = SerializeJsonFromObject(ret); + + EventNotify(strJson); + return false; } @@ -111,7 +145,7 @@ bool CDAPI::GetProfile(Object& obj) { "object" : "dapi_command", "data" : { - “command” : ”get-profile”, + “command” : ”get_profile”, “my_uid” : INT64, “target_uid” : INT64, “signature” : ‘’, @@ -121,7 +155,6 @@ bool CDAPI::GetProfile(Object& obj) */ std::string strObject = json_spirit::find_value(obj, "object").get_str(); - if(strObject != "dapi_command") return false; printf("3 %s\n", strObject.c_str()); @@ -136,13 +169,17 @@ bool CDAPI::GetProfile(Object& obj) CDriveFile file(GetProfileFile(strUID)); printf("5 %s\n", GetProfileFile(strUID).c_str()); - if(!file.Exists()) return false; + if(!file.Exists()) + { + SetError(1001, "File doesn't exist : " + strUID); + return false; + } file.Read(); printf("6 %s\n", GetProfileFile(strUID).c_str()); // send the user back the results of the query - Object ret = GetResultObject(1000, "get-profile", file.obj, true); + Object ret = GetResultObject(1000, "get_profile", file.obj); std::string strJson = SerializeJsonFromObject(ret); printf("7 %s\n", strJson.c_str()); @@ -157,7 +194,7 @@ bool CDAPI::SetProfile(Object& obj) { "object" : "dapi_command", "data" : { - "command": "set-profile", + "command": "set_profile", "my_uid": INT64, "target_uid": INT64, "signature": "", @@ -170,7 +207,6 @@ bool CDAPI::SetProfile(Object& obj) */ std::string strObject = json_spirit::find_value(obj, "object").get_str(); - if(strObject != "dapi_command") return false; printf("2 %s\n", strObject.c_str()); // get the user we want to open @@ -182,7 +218,11 @@ bool CDAPI::SetProfile(Object& obj) // open the file and read it CDriveFile file(GetProfileFile(strUID)); - if(!file.Exists()) return false; + if(!file.Exists()) + { + SetError(1002, "File doesn't exist : " + strUID); + return false; + } file.Read(); std::map mapObj; @@ -209,7 +249,7 @@ bool CDAPI::SetProfile(Object& obj) json_spirit::map_to_obj(mapObj, file.obj); file.Write(); - Object ret = GetResultObject(1000, "set-profile", file.obj, true); + Object ret = GetResultObject(1000, "set_profile", file.obj); std::string strJson = SerializeJsonFromObject(ret); printf("7 %s\n", strJson.c_str()); @@ -225,7 +265,7 @@ bool CDAPI::GetPrivateData(Object& obj) { "object" : "dapi_command", "data" : { - "command" = "get-private-data", + "command" = "get_private_data", "my_uid" = UID, "target_uid" = UID, "signature" = ‘’, @@ -235,7 +275,6 @@ bool CDAPI::GetPrivateData(Object& obj) */ std::string strObject = json_spirit::find_value(obj, "object").get_str(); - if(strObject != "dapi_command") return false; printf("3 %s\n", strObject.c_str()); @@ -243,7 +282,11 @@ bool CDAPI::GetPrivateData(Object& obj) Object objData = json_spirit::find_value(obj, "data").get_obj(); string strUID = json_spirit::find_value(objData, "target_uid").get_str(); int nSlot = json_spirit::find_value(objData, "slot").get_int(); - if(nSlot < 1 || nSlot > 10) return false; + if(nSlot < 1 || nSlot > 10) + { + SetError(1002, "Slot out of range"); + return false; + } printf("4 %s\n", strUID.c_str()); @@ -255,7 +298,7 @@ bool CDAPI::GetPrivateData(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(1000, "get-private-data", file.obj, true); + Object ret = GetResultObject(1000, "get_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); printf("7 %s\n", strJson.c_str()); @@ -271,7 +314,7 @@ bool CDAPI::SetPrivateData(Object& obj) { "object" : "dapi_command", "data" : { - "command" : "set-private-data", + "command" : "set_private_data", "my_uid" : INT64, "target_uid" : INT64, "signature" : "SIGNATURE", @@ -282,7 +325,6 @@ bool CDAPI::SetPrivateData(Object& obj) */ std::string strObject = json_spirit::find_value(obj, "object").get_str(); - if(strObject != "dapi_command") return false; printf("3 %s\n", strObject.c_str()); @@ -290,7 +332,11 @@ bool CDAPI::SetPrivateData(Object& obj) Object objData = json_spirit::find_value(obj, "data").get_obj(); string strUID = json_spirit::find_value(objData, "target_uid").get_str(); int nSlot = json_spirit::find_value(objData, "slot").get_int(); - if(nSlot < 1 || nSlot > 10) return false; + if(nSlot < 1 || nSlot > 10) + { + SetError(1002, "Slot out of range"); + return false; + } printf("4 %s\n", strUID.c_str()); @@ -300,7 +346,6 @@ bool CDAPI::SetPrivateData(Object& obj) if(!file.Exists()) { - printf("new %s\n"); Object newObj; newObj.push_back(Pair("access_times", 0)); newObj.push_back(Pair("last_access", 0)); @@ -323,7 +368,7 @@ bool CDAPI::SetPrivateData(Object& obj) printf("6 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); // send the user back the results of the query - Object ret = GetResultObject(1000, "set-private-data", file.obj, true); + Object ret = GetResultObject(1000, "set_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); printf("7 %s\n", strJson.c_str()); @@ -351,11 +396,26 @@ bool CDAPI::SendMessage(Object& obj) } */ + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); + string strPayload = json_spirit::find_value(objData, "payload").get_str(); + + //TODO: this is presently sending the message to all users on the server + Object ret = GetMessageObject(1000, strUID, strSubCommand, strPayload); + std::string strJson = SerializeJsonFromObject(ret); + EventNotify(strJson); + return true; } // broadcast any message on the network from T3 -bool CDAPI::SendBroadcast(Object& obj) +bool CDAPI::BroadcastMessage(Object& obj) { /* { @@ -371,6 +431,38 @@ bool CDAPI::SendBroadcast(Object& obj) } */ - return true; + + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strSubCommand = json_spirit::find_value(objData, "subcommand").get_str(); + string strPayload = json_spirit::find_value(objData, "payload").get_str(); + + if(strSubCommand == "tx") + { + CTransaction tx; + if (!DecodeHexTx(tx, strPayload)) + { + SetError(1003, "TX Decoding Failed"); + return false; + } + RelayTransaction(tx); + + Object retTx; + retTx.push_back(Pair("tx-id", tx.GetHash().ToString())); + //should probably figure out if it was broadcasted successfully + + // send the user back the results of the query + Object ret = GetResultObject(1000, "broadcast_message", retTx); + std::string strJson = SerializeJsonFromObject(ret); + + } else { + return false; + } + + return false; } diff --git a/src/evo/dapi.h b/src/evo/dapi.h index cee2cc30145f..d9762a6c8d6b 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -70,7 +70,6 @@ class CDAPI CDAPI(); public: - static bool Execute(Object& obj); static bool ValidateSignature(Object& obj); static bool GetProfile(Object& obj); @@ -78,7 +77,7 @@ class CDAPI static bool GetPrivateData(Object& obj); static bool SetPrivateData(Object& obj); static bool SendMessage(Object& obj); - static bool SendBroadcast(Object& obj); + static bool BroadcastMessage(Object& obj); }; diff --git a/src/test/data/dapi-broadcast-tx.js b/src/test/data/dapi-broadcast-tx.js new file mode 100644 index 000000000000..bcf7b861d8c0 --- /dev/null +++ b/src/test/data/dapi-broadcast-tx.js @@ -0,0 +1,10 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "broadcast_message", + "subcommand" : "tx", + "my_uid" : "1337", + "target_uid" : "1337", + "payload" : "SIG" + } +} \ No newline at end of file diff --git a/src/test/data/dapi-get-private-data.js b/src/test/data/dapi-get-private-data.js index 0b90d4cfbfc5..01dc3fcca7b5 100644 --- a/src/test/data/dapi-get-private-data.js +++ b/src/test/data/dapi-get-private-data.js @@ -1,7 +1,7 @@ { "object" : "dapi_command", "data" : { - "command" : "get-private-data", + "command" : "get_private_data", "my_uid" : "1337", "target_uid" : "1337", "signature" : "SIG", diff --git a/src/test/data/dapi-get-profile.js b/src/test/data/dapi-get-profile.js index 15bd01f7ba5a..76e35ae04e84 100644 --- a/src/test/data/dapi-get-profile.js +++ b/src/test/data/dapi-get-profile.js @@ -1,7 +1,7 @@ { "object" : "dapi_command", "data" : { - "command" : "get-profile", + "command" : "get_profile", "my_uid" : "1337", "target_uid" : "1337", "signature" : "SIG", diff --git a/src/test/data/dapi-set-private-data.js b/src/test/data/dapi-set-private-data.js index 2c65ca1cc76c..99e6ab1d4481 100644 --- a/src/test/data/dapi-set-private-data.js +++ b/src/test/data/dapi-set-private-data.js @@ -1,7 +1,7 @@ { "object" : "dapi_command", "data" : { - "command" : "set-private-data", + "command" : "set_private_data", "my_uid" : "1337", "target_uid" : "1337", "signature" : "SIG", diff --git a/src/test/data/dapi-set-profile.js b/src/test/data/dapi-set-profile.js index e0bb9b81bcee..f326950c28ec 100644 --- a/src/test/data/dapi-set-profile.js +++ b/src/test/data/dapi-set-profile.js @@ -1,7 +1,7 @@ { "object" : "dapi_command", "data" : { - "command": "set-profile", + "command": "set_profile", "my_uid": "1337", "target_uid": "1337", "signature": "", From cfe13b189cd56c3438af33d04ed11016103b276b Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 23 Dec 2015 16:36:05 -0700 Subject: [PATCH 12/51] send pm --- src/evo/dapi.cpp | 8 +++++--- src/rpcdapi.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 8659cc15806f..c80ce9e1896d 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -386,8 +386,8 @@ bool CDAPI::SendMessage(Object& obj) { "object" : "dapi_command", "data" : { - "command" = "message", - "subcommand" = "(available subcommands)", + "command" = "send_message", + "subcommand" = "(addr,cmd2,cmd3)", "my_uid" = UID, "target_uid" = UID, "signature" = ‘’, @@ -403,12 +403,14 @@ bool CDAPI::SendMessage(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); string strUID = json_spirit::find_value(objData, "target_uid").get_str(); - string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); + string strSubCommand = json_spirit::find_value(objData, "subcommand").get_str(); string strPayload = json_spirit::find_value(objData, "payload").get_str(); //TODO: this is presently sending the message to all users on the server Object ret = GetMessageObject(1000, strUID, strSubCommand, strPayload); std::string strJson = SerializeJsonFromObject(ret); + + printf("4 %s\n", strJson.c_str()); EventNotify(strJson); return true; diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 997b876139ed..deb9b88f09af 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -49,7 +49,7 @@ Value dapi(const Array& params, bool fHelp) dashd --datadir=example --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" --daemon dash-cli dapi "{\"txid\":\"myid\",\"aeou\":\"123\",\"vout\":\"0\"}" "{\"address\":0.01}" - dash_t2 --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=% + dash_t2 --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%" */ std::string strCommand = params[0].get_str(); From 5f97a3fc6eee6cb4daf479637534d1d64998c271 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 28 Dec 2015 22:51:36 -0700 Subject: [PATCH 13/51] messaging fixes --- src/evo/dapi.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index c80ce9e1896d..97b8fceba907 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -57,14 +57,15 @@ Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile) return ret; } -Object GetMessageObject(int nCommandID, std::string strUserID, std::string strSubCommand, std::string strMessage) +Object GetMessageObject(int nCommandID, std::string strFromUserID, std::string strToUserID, std::string strSubCommand, std::string strMessage) { Object retData; retData.push_back(Pair("id", nCommandID)); retData.push_back(Pair("command", "send_message")); retData.push_back(Pair("error-id", nError)); retData.push_back(Pair("error-message", strErrorMessage)); - retData.push_back(Pair("target_uid", strUserID)); + retData.push_back(Pair("from_uid", strFromUserID)); + retData.push_back(Pair("to_uid", strToUserID)); retData.push_back(Pair("sub_command", strSubCommand)); retData.push_back(Pair("payload", strMessage)); @@ -180,9 +181,14 @@ bool CDAPI::GetProfile(Object& obj) // send the user back the results of the query Object ret = GetResultObject(1000, "get_profile", file.obj); + + std::string strJson2 = SerializeJsonFromObject(file.obj); + + printf("7 %s\n", strJson2.c_str()); + std::string strJson = SerializeJsonFromObject(ret); - printf("7 %s\n", strJson.c_str()); + printf("8 %s\n", strJson.c_str()); EventNotify(strJson); return true; @@ -402,12 +408,13 @@ bool CDAPI::SendMessage(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + string strUID1 = json_spirit::find_value(objData, "my_uid").get_str(); + string strUID2 = json_spirit::find_value(objData, "target_uid").get_str(); string strSubCommand = json_spirit::find_value(objData, "subcommand").get_str(); string strPayload = json_spirit::find_value(objData, "payload").get_str(); //TODO: this is presently sending the message to all users on the server - Object ret = GetMessageObject(1000, strUID, strSubCommand, strPayload); + Object ret = GetMessageObject(1000, strUID1, strUID2, strSubCommand, strPayload); std::string strJson = SerializeJsonFromObject(ret); printf("4 %s\n", strJson.c_str()); From f83f71c57c070d39bdf0485752b2d4ceb5f4b910 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 5 Jan 2016 11:49:46 -0700 Subject: [PATCH 14/51] draft --- src/evo/dapi.cpp | 209 +++++++++++++++++++++++++++++++++++++++++------ src/evo/dapi.h | 2 +- 2 files changed, 187 insertions(+), 24 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 97b8fceba907..edb6ed74a54e 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -147,8 +147,8 @@ bool CDAPI::GetProfile(Object& obj) "object" : "dapi_command", "data" : { “command” : ”get_profile”, - “my_uid” : INT64, - “target_uid” : INT64, + “from_uid” : INT64, + “to_uid” : INT64, “signature” : ‘’, “fields” : [“fname”, “lname”] } @@ -161,8 +161,7 @@ bool CDAPI::GetProfile(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "target_uid").get_str(); - + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); printf("4 %s\n", strUID.c_str()); @@ -201,8 +200,8 @@ bool CDAPI::SetProfile(Object& obj) "object" : "dapi_command", "data" : { "command": "set_profile", - "my_uid": INT64, - "target_uid": INT64, + "from_uid": INT64, + "to_uid": INT64, "signature": "", "update" : [ {"field":"name","value":"newvalue"} @@ -218,7 +217,7 @@ bool CDAPI::SetProfile(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); const Array& arrDataUpdate = json_spirit::find_value(objData, "update").get_array(); - string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); printf("3 %s\n", strUID.c_str()); @@ -272,8 +271,8 @@ bool CDAPI::GetPrivateData(Object& obj) "object" : "dapi_command", "data" : { "command" = "get_private_data", - "my_uid" = UID, - "target_uid" = UID, + "from_uid" = UID, + "to_uid" = UID, "signature" = ‘’, "slot" = 1 } @@ -286,7 +285,7 @@ bool CDAPI::GetPrivateData(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); int nSlot = json_spirit::find_value(objData, "slot").get_int(); if(nSlot < 1 || nSlot > 10) { @@ -321,8 +320,8 @@ bool CDAPI::SetPrivateData(Object& obj) "object" : "dapi_command", "data" : { "command" : "set_private_data", - "my_uid" : INT64, - "target_uid" : INT64, + "from_uid" : INT64, + "to_uid" : INT64, "signature" : "SIGNATURE", "slot" : 1, "payload" : JSON_WEB_ENCRYPTION @@ -336,7 +335,7 @@ bool CDAPI::SetPrivateData(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "target_uid").get_str(); + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); int nSlot = json_spirit::find_value(objData, "slot").get_int(); if(nSlot < 1 || nSlot > 10) { @@ -393,9 +392,9 @@ bool CDAPI::SendMessage(Object& obj) "object" : "dapi_command", "data" : { "command" = "send_message", - "subcommand" = "(addr,cmd2,cmd3)", - "my_uid" = UID, - "target_uid" = UID, + "sub_command" = "(addr,cmd2,cmd3)", + "from_uid" = UID, + "to_uid" = UID, "signature" = ‘’, "payload" = ENCRYPTED } @@ -408,9 +407,9 @@ bool CDAPI::SendMessage(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID1 = json_spirit::find_value(objData, "my_uid").get_str(); - string strUID2 = json_spirit::find_value(objData, "target_uid").get_str(); - string strSubCommand = json_spirit::find_value(objData, "subcommand").get_str(); + string strUID1 = json_spirit::find_value(objData, "from_uid").get_str(); + string strUID2 = json_spirit::find_value(objData, "to_uid").get_str(); + string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); string strPayload = json_spirit::find_value(objData, "payload").get_str(); //TODO: this is presently sending the message to all users on the server @@ -431,9 +430,9 @@ bool CDAPI::BroadcastMessage(Object& obj) "object" : "dapi_command", "data" : { "command" = "broadcast", - "subcommand" = "tx", //can support multiple message commands - "my_uid" = UID, - "target_uid" = UID, + "sub_command" = "tx", //can support multiple message commands + "from_uid" = UID, + "to_uid" = UID, "signature" = ‘’, "payload" = SERIALIZED_BASE64_ENCODED } @@ -447,7 +446,7 @@ bool CDAPI::BroadcastMessage(Object& obj) // get the user we want to open Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strSubCommand = json_spirit::find_value(objData, "subcommand").get_str(); + string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); string strPayload = json_spirit::find_value(objData, "payload").get_str(); if(strSubCommand == "tx") @@ -475,3 +474,167 @@ bool CDAPI::BroadcastMessage(Object& obj) return false; } +// Create new user account +bool CDAPI::InviteUser(Object& obj) +{ + // //SEND FRIEND REQUEST + // { + // "object" : "dapi_command", + // "data" : { + // "command" : “invite_user”, + // "from_uid" : UID, + // "to_uid" : ENTERED_USERNAME, + // "to_email" : ENTERED_EMAIL, + // "to_pubkey" : ENTERED_PUBKEY, + // "signature" = “” + // } + // } + + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); + + printf("4 %s\n", strUID.c_str()); + + // open the file and read it + CDriveFile file(GetProfileFile(strUID)); + printf("5 %s\n", GetProfileFile(strUID).c_str()); + + if(file.Exists()) + { + SetError(1004, "User already exists : " + strUID); + return false; + } + + string strName = json_spirit::find_value(objData, "to_name").get_str(); + string strEmail = json_spirit::find_value(objData, "to_email").get_str(); + string strPubkey = json_spirit::find_value(objData, "to_pubkey").get_str(); + + CBitcoinAddress address(strPubkey); + bool isValid = address.IsValid(); + + if(!isValid) + { + SetError(1005, "Invalid pubkey: " + strPubkey); + return false; + } + + Object newObj; + newObj.push_back(Pair("status", 1)); + newObj.push_back(Pair("name", strName)); + newObj.push_back(Pair("email", strEmail)); + newObj.push_back(Pair("pubkey", strPubkey)); + newObj.push_back(Pair("challenge_code", GetRand(999999))); + file.obj = newObj; + + file.Write(); + + // //RESULTING JSON + // { + // "object" : "dapi_result", + // "data" : { + // "command" : “invite_user”, + // "from_uid" : UID, + // "to_uid" : ENTERED_USERNAME, + // "to_email" : ENTERED_EMAIL, + // "to_pubkey" : ENTERED_PUBKEY, + // "to_challenge_code" : RANDOMLY_GENERATED, + // "signature" : “” + // } + // } + + // send the user back the results of the query + Object ret = GetResultObject(1000, "invite_user", file.obj); + std::string strJson = SerializeJsonFromObject(ret); + + printf("7 %s\n", strJson.c_str()); + + EventNotify(strJson); +} + +bool CDAPI::ValidateAccount(Object& obj) +{ + /* + //VALIDATE ACCOUNT + { + "object" : "dapi_command", + "data" : { + "command" : “validate_account”, + "from_uid" : UID, + "to_uid" : ENTERED_USERNAME, + "to_challenge_code" : RANDOMLY_GENERATED, + "signature" : “” + } + } + */ + + std::string strObject = json_spirit::find_value(obj, "object").get_str(); + + printf("3 %s\n", strObject.c_str()); + + // get the user we want to open + Object objData = json_spirit::find_value(obj, "data").get_obj(); + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); + string strChallengeCode = json_spirit::find_value(objData, "to_challenge_code").get_str(); + + printf("4 %s\n", strUID.c_str()); + + // open the file and read it + CDriveFile file(GetProfileFile(strUID)); + printf("5 %s\n", GetProfileFile(strUID).c_str()); + + // open the file and read it + CDriveFile file(GetProfileFile(strUID)); + printf("5 %s\n", GetProfileFile(strUID).c_str()); + + if(!file.Exists()) + { + SetError(1001, "File doesn't exist : " + strUID); + return false; + } + file.Read(); + + std::map mapObj; + json_spirit::obj_to_map(file.obj, mapObj); + + string strUID = json_spirit::find_value(objData, "to_uid").get_str(); + if(mapObj["challenge_code"] == strChallengeCode) + { + mapObj["challenge_code"] = ""; + mapObj["status"] = 2; + } else { + SetError(1006, "Invalid challenge_code : " + strChallengeCode); + return false; + } + + json_spirit::map_to_obj(mapObj, file.obj); + file.Write(); + + /* + //RESULTING JSON + { + "object" : "dapi_result", + "data" : { + "command" : “validate_account”, + "from_uid" : UID, + "to_uid" : ENTERED_USERNAME, + "signature" : “”, + “error_id” : 1000, + “error_description” : “none” + } + } + */ + + // send the user back the results of the query + Object ret = GetResultObject(1000, "“validate_account”", file.obj); + std::string strJson = SerializeJsonFromObject(ret); + + printf("7 %s\n", strJson.c_str()); + + EventNotify(strJson); +} + diff --git a/src/evo/dapi.h b/src/evo/dapi.h index d9762a6c8d6b..8d3ae8891f5f 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -78,7 +78,7 @@ class CDAPI static bool SetPrivateData(Object& obj); static bool SendMessage(Object& obj); static bool BroadcastMessage(Object& obj); - + static bool InviteUser(Object& obj);] }; #endif \ No newline at end of file From 4b79afb5eed4cd5d0b71e9f5933393270035d6e9 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 5 Jan 2016 14:58:00 -0700 Subject: [PATCH 15/51] prototype setup --- dash-docs/prototype-setup.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 dash-docs/prototype-setup.txt diff --git a/dash-docs/prototype-setup.txt b/dash-docs/prototype-setup.txt new file mode 100644 index 000000000000..4a9c91b217df --- /dev/null +++ b/dash-docs/prototype-setup.txt @@ -0,0 +1,13 @@ +Setting up the prototype (using mainnet atm): + + +1. Download and install dash (https://github.com/dashpay/dash) +2. Setup a data directory in ~/.dash-data +3. Create your user files. For example to create the user evan, write this file to ~/.dash-data/users/evan +file contents: {"name":"Evan Duffield","username":"evan","stars":5} +4. Download dash-2t, the tier-2 websockets proxy +5. Run the client with a command like this: +dash_t2 --datadir2="/Users/evan/.dash-data" --eventnotify="/Users/evan/Desktop/dash-2t/serve/event.py --event=%s" +6. Start dash-2t, "python app.py" +7. Download and run the electrum client at: https://github.com/evan82/electrum-dash +8. Start 2x versions of client with 2 different users : ./electrum-dash -w ~/.test-electrum2 --electrum_path=~/.electrum-test-2 \ No newline at end of file From 7683339cf0d090304cbc1e0684f2407d00e3975a Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 5 Jan 2016 17:49:28 -0700 Subject: [PATCH 16/51] added invite user and verify account commands --- src/evo/dapi.cpp | 6 +----- src/evo/dapi.h | 3 ++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index edb6ed74a54e..1bd64ca3c679 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -474,6 +474,7 @@ bool CDAPI::BroadcastMessage(Object& obj) return false; } + // Create new user account bool CDAPI::InviteUser(Object& obj) { @@ -587,10 +588,6 @@ bool CDAPI::ValidateAccount(Object& obj) CDriveFile file(GetProfileFile(strUID)); printf("5 %s\n", GetProfileFile(strUID).c_str()); - // open the file and read it - CDriveFile file(GetProfileFile(strUID)); - printf("5 %s\n", GetProfileFile(strUID).c_str()); - if(!file.Exists()) { SetError(1001, "File doesn't exist : " + strUID); @@ -601,7 +598,6 @@ bool CDAPI::ValidateAccount(Object& obj) std::map mapObj; json_spirit::obj_to_map(file.obj, mapObj); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); if(mapObj["challenge_code"] == strChallengeCode) { mapObj["challenge_code"] = ""; diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 8d3ae8891f5f..805320e42277 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -78,7 +78,8 @@ class CDAPI static bool SetPrivateData(Object& obj); static bool SendMessage(Object& obj); static bool BroadcastMessage(Object& obj); - static bool InviteUser(Object& obj);] + static bool InviteUser(Object& obj); + static bool ValidateAccount(Object& obj); }; #endif \ No newline at end of file From 347a884b204b9e45a23d562931c6fb9f1ea5f547 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 7 Jan 2016 10:19:52 -0700 Subject: [PATCH 17/51] vastly improved error feedback for dapi --- src/evo/dapi.cpp | 354 +++++++++++++++---------- src/evo/dapi.h | 9 + src/test/data/dapi-invite-user.js | 11 + src/test/data/dapi-search-users.js | 9 + src/test/data/dapi-validate-account.js | 9 + 5 files changed, 255 insertions(+), 137 deletions(-) create mode 100644 src/test/data/dapi-invite-user.js create mode 100644 src/test/data/dapi-search-users.js create mode 100644 src/test/data/dapi-validate-account.js diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 1bd64ca3c679..5fa928e05867 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -87,38 +87,119 @@ std::string SerializeJsonFromObject(Object objToSerialize) return strJson; } +// GET OBJECT AND CONVERT TO VARIABLE +bool FindValueAsString(Object obj, std::string strName, std::string& strOut) +{ + const Value& result = json_spirit::find_value(obj, strName); + if (result.type() == null_type) + { + SetError(1008, "Missing required field : " + strName); + return false; + } + + strOut = result.get_str(); + return true; +} + +bool FindValueAsObject(Object obj, std::string strName, Object& objOut) +{ + const Value& result = json_spirit::find_value(obj, strName); + if (result.type() == null_type) + { + SetError(1008, "Missing required field : " + strName); + return false; + } + + objOut = result.get_obj(); + return true; +} + +bool FindValueAsArray(Object obj, std::string strName, Array& arrOut) +{ + const Value& result = json_spirit::find_value(obj, strName); + if (result.type() == null_type) + { + SetError(1008, "Missing required field : " + strName); + return false; + } + + arrOut = result.get_array(); + return true; +} + +bool FindValueAsInt(Object obj, std::string strName, int& nOut) +{ + const Value& result = json_spirit::find_value(obj, strName); + if (result.type() == null_type) + { + SetError(1008, "Missing required field : " + strName); + return false; + } + + nOut = result.get_int(); + return true; +} + +// DAPI FUNCTIONALITY bool CDAPI::Execute(Object& obj) { ResetErrorStatus(); - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - if(strObject != "dapi_command") return false; - - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strCommand = json_spirit::find_value(objData, "command").get_str(); - - printf("1 %s\n", strCommand.c_str()); - - if(strCommand == "get_profile") { - if(GetProfile(obj)) return true; - } else if (strCommand == "set_profile") { - if(SetProfile(obj)) return true; - } else if (strCommand == "set_private_data") { - if(SetPrivateData(obj)) return true; - } else if (strCommand == "get_private_data") { - if(GetPrivateData(obj)) return true; - } else if (strCommand == "send_message") { - if(SendMessage(obj)) return true; - } else if (strCommand == "broadcast_message") { - if(BroadcastMessage(obj)) return true; + // dapi command only + std::string strObject; + if(!FindValueAsString(obj, "object", strObject)) + { + SetError(1009, "[\"object\"] is required in data structure"); + } + + if(strObject != "dapi_command") + { + SetError(1010, "[\"object\"] type of \"dapi_command\" is only supported in data structure"); + } + + // required for all DAPI messages + Object objData; + string strCommand = ""; + if(!FindValueAsObject(obj, "data", objData)) + { + SetError(1011, "[\"data\"] is required in data structure"); + } + if(!FindValueAsString(objData, "command", strCommand)) + { + SetError(1012, "[\"data\"][\"command\"] is required in data structure"); + } + + // SUPPORTED COMMANDS + + if(nError == 0) + { + if(strCommand == "get_profile") { + if(GetProfile(obj)) return true; + } else if (strCommand == "set_profile") { + if(SetProfile(obj)) return true; + } else if (strCommand == "set_private_data") { + if(SetPrivateData(obj)) return true; + } else if (strCommand == "get_private_data") { + if(GetPrivateData(obj)) return true; + } else if (strCommand == "send_message") { + if(SendMessage(obj)) return true; + } else if (strCommand == "broadcast_message") { + if(BroadcastMessage(obj)) return true; + } else if (strCommand == "invite_user") { + if(InviteUser(obj)) return true; + } else if (strCommand == "validate_account") { + if(ValidateAccount(obj)) return true; + } else if (strCommand == "search_users") { + if(SearchUsers(obj)) return true; + } } - // unknown command + // UNKNOWN COMMANDS // send the user back the results of the query - if(nError == 0) SetError(1000, "Unknown Command : " + strCommand); + if(nError == 0) SetError(1007, "Unknown Command : " + strCommand); Object result; Object ret = GetResultObject(1000, strCommand, result); std::string strJson = SerializeJsonFromObject(ret); @@ -155,20 +236,14 @@ bool CDAPI::GetProfile(Object& obj) } */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - - printf("4 %s\n", strUID.c_str()); + Object objData; + string strUID = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(obj, "to_uid", strUID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); - printf("5 %s\n", GetProfileFile(strUID).c_str()); - if(!file.Exists()) { SetError(1001, "File doesn't exist : " + strUID); @@ -176,20 +251,12 @@ bool CDAPI::GetProfile(Object& obj) } file.Read(); - printf("6 %s\n", GetProfileFile(strUID).c_str()); - // send the user back the results of the query Object ret = GetResultObject(1000, "get_profile", file.obj); - - std::string strJson2 = SerializeJsonFromObject(file.obj); - - printf("7 %s\n", strJson2.c_str()); - + std::string strJson2 = SerializeJsonFromObject(file.obj); std::string strJson = SerializeJsonFromObject(ret); - - printf("8 %s\n", strJson.c_str()); - EventNotify(strJson); + return true; } @@ -211,15 +278,16 @@ bool CDAPI::SetProfile(Object& obj) */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); + std::string strObject = ""; + if(!FindValueAsString(obj, "object", strObject)) return false; - printf("2 %s\n", strObject.c_str()); // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - const Array& arrDataUpdate = json_spirit::find_value(objData, "update").get_array(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - - printf("3 %s\n", strUID.c_str()); + Object objData; + Array arrDataUpdate; + string strUID = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsArray(objData, "update", arrDataUpdate)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); @@ -233,15 +301,11 @@ bool CDAPI::SetProfile(Object& obj) std::map mapObj; json_spirit::obj_to_map(file.obj, mapObj); - printf("4 %s\n", GetProfileFile(strUID).c_str()); - for( unsigned int i = 0; i < arrDataUpdate.size(); ++i ) { Object tmp = arrDataUpdate[i].get_obj(); - string strField = json_spirit::find_value(tmp, "field").get_str(); - string strValue = json_spirit::find_value(tmp, "value").get_str(); - - printf("5 %s %s\n", strField.c_str(), strValue.c_str()); + string strField = ""; if(!FindValueAsString(tmp, "field", strField)) return false; + string strValue = ""; if(!FindValueAsString(tmp, "value", strValue)) return false; // string& strUpdate = json_spirit::find_value(obj, strField).get_str(); // strUpdate = strValue; @@ -257,8 +321,6 @@ bool CDAPI::SetProfile(Object& obj) Object ret = GetResultObject(1000, "set_profile", file.obj); std::string strJson = SerializeJsonFromObject(ret); - printf("7 %s\n", strJson.c_str()); - EventNotify(strJson); return true; @@ -279,35 +341,27 @@ bool CDAPI::GetPrivateData(Object& obj) } */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - int nSlot = json_spirit::find_value(objData, "slot").get_int(); + Object objData; + string strUID = ""; + int nSlot = -1; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; + if(!FindValueAsInt(objData, "slot", nSlot)) return false; if(nSlot < 1 || nSlot > 10) { SetError(1002, "Slot out of range"); return false; } - printf("4 %s\n", strUID.c_str()); - // open the file and read it CDriveFile file(GetPrivateDataFile(strUID, nSlot)); - printf("5 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); - if(!file.Exists()) return false; file.Read(); // send the user back the results of the query Object ret = GetResultObject(1000, "get_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); - - printf("7 %s\n", strJson.c_str()); - EventNotify(strJson); return true; @@ -329,26 +383,21 @@ bool CDAPI::SetPrivateData(Object& obj) } */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - int nSlot = json_spirit::find_value(objData, "slot").get_int(); + Object objData; + string strUID = ""; + int nSlot = -1; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; + if(!FindValueAsInt(objData, "slot", nSlot)) return false; if(nSlot < 1 || nSlot > 10) { SetError(1002, "Slot out of range"); return false; } - printf("4 %s\n", strUID.c_str()); - // open the file and read it CDriveFile file(GetPrivateDataFile(strUID, nSlot)); - printf("5 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); - if(!file.Exists()) { Object newObj; @@ -363,21 +412,17 @@ bool CDAPI::SetPrivateData(Object& obj) std::map mapObj; json_spirit::obj_to_map(file.obj, mapObj); - string strPayload = json_spirit::find_value(objData, "payload").get_str(); + string strPayload = ""; + if(!FindValueAsString(objData, "payload", strPayload)) return false; mapObj["payload"] = strPayload; json_spirit::map_to_obj(mapObj, file.obj); file.Write(); - - printf("6 %s\n", GetPrivateDataFile(strUID, nSlot).c_str()); - // send the user back the results of the query Object ret = GetResultObject(1000, "set_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); - printf("7 %s\n", strJson.c_str()); - EventNotify(strJson); return true; @@ -401,24 +446,23 @@ bool CDAPI::SendMessage(Object& obj) } */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID1 = json_spirit::find_value(objData, "from_uid").get_str(); - string strUID2 = json_spirit::find_value(objData, "to_uid").get_str(); - string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); - string strPayload = json_spirit::find_value(objData, "payload").get_str(); + Object objData; + string strUID1 = ""; + string strUID2 = ""; + string strSubCommand = ""; + string strPayload = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "from_uid", strUID1)) return false; + if(!FindValueAsString(objData, "to_uid", strUID2)) return false; + if(!FindValueAsString(objData, "sub_command", strSubCommand)) return false; + if(!FindValueAsString(objData, "payload", strPayload)) return false; //TODO: this is presently sending the message to all users on the server Object ret = GetMessageObject(1000, strUID1, strUID2, strSubCommand, strPayload); std::string strJson = SerializeJsonFromObject(ret); - printf("4 %s\n", strJson.c_str()); EventNotify(strJson); - return true; } @@ -439,15 +483,13 @@ bool CDAPI::BroadcastMessage(Object& obj) } */ - - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strSubCommand = json_spirit::find_value(objData, "sub_command").get_str(); - string strPayload = json_spirit::find_value(objData, "payload").get_str(); + Object objData; + string strSubCommand = ""; + string strPayload = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "sub_command", strSubCommand)) return false; + if(!FindValueAsString(objData, "payload", strPayload)) return false; if(strSubCommand == "tx") { @@ -467,6 +509,8 @@ bool CDAPI::BroadcastMessage(Object& obj) Object ret = GetResultObject(1000, "broadcast_message", retTx); std::string strJson = SerializeJsonFromObject(ret); + return true; + } else { return false; } @@ -485,35 +529,33 @@ bool CDAPI::InviteUser(Object& obj) // "command" : “invite_user”, // "from_uid" : UID, // "to_uid" : ENTERED_USERNAME, + // "to_name" : ENTERED_NAME, // "to_email" : ENTERED_EMAIL, // "to_pubkey" : ENTERED_PUBKEY, // "signature" = “” // } // } - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); - // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - - printf("4 %s\n", strUID.c_str()); + Object objData; + string strUID = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); - printf("5 %s\n", GetProfileFile(strUID).c_str()); - if(file.Exists()) { SetError(1004, "User already exists : " + strUID); return false; } - string strName = json_spirit::find_value(objData, "to_name").get_str(); - string strEmail = json_spirit::find_value(objData, "to_email").get_str(); - string strPubkey = json_spirit::find_value(objData, "to_pubkey").get_str(); + string strName = ""; + string strEmail = ""; + string strPubkey = ""; + if(!FindValueAsString(objData, "to_name", strName)) return false; + if(!FindValueAsString(objData, "to_email", strEmail)) return false; + if(!FindValueAsString(objData, "to_pubkey", strPubkey)) return false; CBitcoinAddress address(strPubkey); bool isValid = address.IsValid(); @@ -526,10 +568,11 @@ bool CDAPI::InviteUser(Object& obj) Object newObj; newObj.push_back(Pair("status", 1)); + newObj.push_back(Pair("username", strUID)); newObj.push_back(Pair("name", strName)); newObj.push_back(Pair("email", strEmail)); newObj.push_back(Pair("pubkey", strPubkey)); - newObj.push_back(Pair("challenge_code", GetRand(999999))); + newObj.push_back(Pair("challenge_code", std::to_string(GetRand(999999)))); file.obj = newObj; file.Write(); @@ -551,10 +594,9 @@ bool CDAPI::InviteUser(Object& obj) // send the user back the results of the query Object ret = GetResultObject(1000, "invite_user", file.obj); std::string strJson = SerializeJsonFromObject(ret); - - printf("7 %s\n", strJson.c_str()); - EventNotify(strJson); + + return true; } bool CDAPI::ValidateAccount(Object& obj) @@ -573,21 +615,19 @@ bool CDAPI::ValidateAccount(Object& obj) } */ - std::string strObject = json_spirit::find_value(obj, "object").get_str(); - - printf("3 %s\n", strObject.c_str()); + std::string strObject = ""; + Object objData; + string strUID = ""; + string strChallengeCode = ""; + if(!FindValueAsString(obj, "object", strObject)) return false; // get the user we want to open - Object objData = json_spirit::find_value(obj, "data").get_obj(); - string strUID = json_spirit::find_value(objData, "to_uid").get_str(); - string strChallengeCode = json_spirit::find_value(objData, "to_challenge_code").get_str(); - - printf("4 %s\n", strUID.c_str()); + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; + if(!FindValueAsString(objData, "to_challenge_code", strChallengeCode)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); - printf("5 %s\n", GetProfileFile(strUID).c_str()); - if(!file.Exists()) { SetError(1001, "File doesn't exist : " + strUID); @@ -598,7 +638,13 @@ bool CDAPI::ValidateAccount(Object& obj) std::map mapObj; json_spirit::obj_to_map(file.obj, mapObj); - if(mapObj["challenge_code"] == strChallengeCode) + if(mapObj["status"].get_int() != 1) + { + SetError(1008, "Account in wrong state to be validated"); + return false; + } + + if(mapObj["challenge_code"].get_str() == strChallengeCode) { mapObj["challenge_code"] = ""; mapObj["status"] = 2; @@ -611,7 +657,7 @@ bool CDAPI::ValidateAccount(Object& obj) file.Write(); /* - //RESULTING JSON + //VALIDATE_ACCOUNT { "object" : "dapi_result", "data" : { @@ -628,9 +674,43 @@ bool CDAPI::ValidateAccount(Object& obj) // send the user back the results of the query Object ret = GetResultObject(1000, "“validate_account”", file.obj); std::string strJson = SerializeJsonFromObject(ret); + EventNotify(strJson); + + return true; +} + + +bool CDAPI::SearchUsers(Object& obj) +{ + /* + //SEARCH USERS + { + "object" : "dapi_command", + "data" : { + "command" : "search_users", + "match_fields" : ["fiat_converter" : 1], + "start" : 0, + "limit" : 10 + } + } + */ - printf("7 %s\n", strJson.c_str()); + // open the file and read it + CDriveFile file(GetIndexFile("fiat_converters.js")); + + if(!file.Exists()) + { + SetError(1003, "File doesn't exist : " + GetIndexFile("fiat_converters.js")); + return false; + } + file.Read(); + + // send the user back the results of the query + Object ret = GetResultObject(1000, "search_users", file.obj); + std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); + + return true; } diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 805320e42277..cf91961217f3 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -30,6 +30,12 @@ using namespace std; using namespace json_spirit; +std::string GetIndexFile(std::string strFilename) +{ + boost::filesystem::path filename = GetDataDirectory() / "index" / strFilename; + return filename.c_str(); +} + std::string GetProfileFile(std::string strUID) { boost::filesystem::path filename = GetDataDirectory() / "users" / strUID; @@ -45,6 +51,8 @@ std::string GetPrivateDataFile(std::string strUID, int nSlot) std::string escapeJsonString(const std::string& input) { + // NOTE: Any ideas on replacing this with something more portable? + std::ostringstream ss; for (auto iter = input.cbegin(); iter != input.cend(); iter++) { //C++98/03: @@ -80,6 +88,7 @@ class CDAPI static bool BroadcastMessage(Object& obj); static bool InviteUser(Object& obj); static bool ValidateAccount(Object& obj); + static bool SearchUsers(Object& obj); }; #endif \ No newline at end of file diff --git a/src/test/data/dapi-invite-user.js b/src/test/data/dapi-invite-user.js new file mode 100644 index 000000000000..0bfff9470727 --- /dev/null +++ b/src/test/data/dapi-invite-user.js @@ -0,0 +1,11 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "invite_user", + "from_uid" : "evan", + "to_uid" : "cryptofish82", + "to_name" : "Evan Duffield", + "to_email" : "cryptofish82@gmail.com", + "to_pubkey" : "Xf4qeg8A7efL6pfZyxKwnH6dbvydnpJ4Cn" + } +} \ No newline at end of file diff --git a/src/test/data/dapi-search-users.js b/src/test/data/dapi-search-users.js new file mode 100644 index 000000000000..a191550678b1 --- /dev/null +++ b/src/test/data/dapi-search-users.js @@ -0,0 +1,9 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "search_users", + "match_fields" : {"fiat_converter" : 1}, + "start" : 0, + "limit" : 10 + } +} \ No newline at end of file diff --git a/src/test/data/dapi-validate-account.js b/src/test/data/dapi-validate-account.js new file mode 100644 index 000000000000..8a819bca797d --- /dev/null +++ b/src/test/data/dapi-validate-account.js @@ -0,0 +1,9 @@ +{ + "object" : "dapi_command", + "data" : { + "command" : "validate_account", + "from_uid" : "evan", + "to_uid" : "cryptofish82", + "to_challenge_code" : "321017" + } +} \ No newline at end of file From 5a1f2d99045a70cf448148e2f4105e5ad9065ea1 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:02:24 -0700 Subject: [PATCH 18/51] change error-id to error_id and error-message to error_message --- src/evo/dapi.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 5fa928e05867..b6f3318b4848 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -46,8 +46,8 @@ Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile) Object retData; retData.push_back(Pair("id", nCommandID)); retData.push_back(Pair("command", strCommand)); - retData.push_back(Pair("error-id", nError)); - retData.push_back(Pair("error-message", strErrorMessage)); + retData.push_back(Pair("error_id", nError)); + retData.push_back(Pair("error_message", strErrorMessage)); retData.push_back(Pair("data", objFile)); Object ret; @@ -62,8 +62,8 @@ Object GetMessageObject(int nCommandID, std::string strFromUserID, std::string s Object retData; retData.push_back(Pair("id", nCommandID)); retData.push_back(Pair("command", "send_message")); - retData.push_back(Pair("error-id", nError)); - retData.push_back(Pair("error-message", strErrorMessage)); + retData.push_back(Pair("error_id", nError)); + retData.push_back(Pair("error_message", strErrorMessage)); retData.push_back(Pair("from_uid", strFromUserID)); retData.push_back(Pair("to_uid", strToUserID)); retData.push_back(Pair("sub_command", strSubCommand)); From de6d0f02dc8d63edf2dd2f9db9001fcab6c919c8 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:16:25 -0700 Subject: [PATCH 19/51] fix file reading issues --- src/evo/file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/file.h b/src/evo/file.h index 3f9002511964..626b472a8bc1 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -103,7 +103,7 @@ class CDriveFile ReadResult Read() { - std::ifstream t(strPath); + std::ifstream t(strPath.c_str()); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); From d2c70d8a1916d13496cf51a2d0dfe5592d0994e9 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:17:32 -0700 Subject: [PATCH 20/51] fix file reading issues --- src/evo/file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/file.h b/src/evo/file.h index 626b472a8bc1..a6b1b830ff6b 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -122,7 +122,7 @@ class CDriveFile { LOCK(cs); - ofstream os( strPath ); + ofstream os( strPath.c_str() ); json_spirit::write( obj, os ); os.close(); From e2598f713bdb0187530a737d1d1e4b9e00ecc44d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:23:49 -0700 Subject: [PATCH 21/51] changed dapi iterator to c++98 compatible (thx crowning) --- src/evo/dapi.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/evo/dapi.h b/src/evo/dapi.h index cf91961217f3..0de31fe16f61 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -54,9 +54,7 @@ std::string escapeJsonString(const std::string& input) { // NOTE: Any ideas on replacing this with something more portable? std::ostringstream ss; - for (auto iter = input.cbegin(); iter != input.cend(); iter++) { - //C++98/03: - //for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { + for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { switch (*iter) { case '\\': ss << "\\\\"; break; case '"': ss << "\\\""; break; From 6c7eca0c2687b89275fe73f515e0b1872329f849 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:26:00 -0700 Subject: [PATCH 22/51] fix file reading issues --- src/rpcdapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index deb9b88f09af..1cba96e0ffa7 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -87,7 +87,7 @@ Value dapif(const Array& params, bool fHelp) */ std::string strPath = params[0].get_str(); - std::ifstream t(strPath); + std::ifstream t(strPath.c_str()); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); From b835eea4d576c961899698b3f7b81737681e43c5 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:32:25 -0700 Subject: [PATCH 23/51] fixed compile issue --- src/evo/dapi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index b6f3318b4848..52c0dba14aeb 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -14,6 +14,7 @@ #include "file.h" #include "json/json_spirit.h" #include "json/json_spirit_value.h" +#include int nError; @@ -572,7 +573,7 @@ bool CDAPI::InviteUser(Object& obj) newObj.push_back(Pair("name", strName)); newObj.push_back(Pair("email", strEmail)); newObj.push_back(Pair("pubkey", strPubkey)); - newObj.push_back(Pair("challenge_code", std::to_string(GetRand(999999)))); + newObj.push_back(Pair("challenge_code", boost::lexical_cast(GetRand(999999)))); file.obj = newObj; file.Write(); From ec59b00b2c83872b075a90160214b51429e44f0b Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:45:50 -0700 Subject: [PATCH 24/51] moved around declarations --- src/evo/dapi.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/evo/dapi.h | 43 ++++--------------------------------------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 52c0dba14aeb..a8948cc62fc7 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -21,6 +21,47 @@ int nError; std::string strErrorMessage; // error reporting +std::string GetIndexFile(std::string strFilename) +{ + boost::filesystem::path filename = GetDataDirectory() / "index" / strFilename; + return filename.c_str(); +} + +std::string GetProfileFile(std::string strUID) +{ + boost::filesystem::path filename = GetDataDirectory() / "users" / strUID; + return filename.c_str(); +} + +std::string GetPrivateDataFile(std::string strUID, int nSlot) +{ + std::string strFilename = strUID + "." + boost::lexical_cast(nSlot); + boost::filesystem::path filename = GetDataDirectory() / "users" / strFilename; + return filename.c_str(); +} + + +std::string escapeJsonString(const std::string& input) { + // NOTE: Any ideas on replacing this with something more portable? + + std::ostringstream ss; + for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { + switch (*iter) { + case '\\': ss << "\\\\"; break; + case '"': ss << "\\\""; break; + case '/': ss << "\\/"; break; + case '\b': ss << "\\b"; break; + case '\f': ss << "\\f"; break; + case '\n': ss << "\\n"; break; + case '\r': ss << "\\r"; break; + case '\t': ss << "\\t"; break; + default: ss << *iter; break; + } + } + return ss.str(); +} + + void ResetErrorStatus() {nError = 0; strErrorMessage = "";} void SetError(int nErrorIn, std::string strMessageIn) {nError = nErrorIn; strErrorMessage = strMessageIn;} diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 0de31fe16f61..fda2cc88328a 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -30,45 +30,10 @@ using namespace std; using namespace json_spirit; -std::string GetIndexFile(std::string strFilename) -{ - boost::filesystem::path filename = GetDataDirectory() / "index" / strFilename; - return filename.c_str(); -} - -std::string GetProfileFile(std::string strUID) -{ - boost::filesystem::path filename = GetDataDirectory() / "users" / strUID; - return filename.c_str(); -} - -std::string GetPrivateDataFile(std::string strUID, int nSlot) -{ - std::string strFilename = strUID + "." + boost::lexical_cast(nSlot); - boost::filesystem::path filename = GetDataDirectory() / "users" / strFilename; - return filename.c_str(); -} - - -std::string escapeJsonString(const std::string& input) { - // NOTE: Any ideas on replacing this with something more portable? - - std::ostringstream ss; - for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { - switch (*iter) { - case '\\': ss << "\\\\"; break; - case '"': ss << "\\\""; break; - case '/': ss << "\\/"; break; - case '\b': ss << "\\b"; break; - case '\f': ss << "\\f"; break; - case '\n': ss << "\\n"; break; - case '\r': ss << "\\r"; break; - case '\t': ss << "\\t"; break; - default: ss << *iter; break; - } - } - return ss.str(); -} +std::string GetIndexFile(std::string strFilename); +std::string GetProfileFile(std::string strUID); +std::string GetPrivateDataFile(std::string strUID, int nSlot); +std::string escapeJsonString(const std::string& input); class CDAPI { From 90af7865cde7d17e7c26331222fabbd8264c76f6 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 13:48:29 -0700 Subject: [PATCH 25/51] moved around declarations --- src/evo/file.cpp | 32 ++++++++++++++++++++++++++++++++ src/evo/file.h | 32 +------------------------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/evo/file.cpp b/src/evo/file.cpp index 73538468c6be..1c8b97c8fcee 100644 --- a/src/evo/file.cpp +++ b/src/evo/file.cpp @@ -23,6 +23,38 @@ using namespace boost; using namespace std; using namespace json_spirit; +boost::filesystem::path GetDataDirectory() +{ + string strDataDir2 = GetArg("-datadir2", ""); + if(strDataDir2 != "") return strDataDir2; + + namespace fs = boost::filesystem; + // Windows < Vista: C:\Documents and Settings\Username\Application Data\Dash + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Dash + // Mac: ~/Library/Application Support/Dash + // Unix: ~/.dash +#ifdef WIN32 + // Windows + return GetSpecialFolderPath(CSIDL_APPDATA) / "Dash"; +#else + fs::path pathRet; + char* pszHome = getenv("HOME"); + if (pszHome == NULL || strlen(pszHome) == 0) + pathRet = fs::path("/"); + else + pathRet = fs::path(pszHome); +#ifdef MAC_OSX + // Mac + pathRet /= "Library/Application Support"; + TryCreateDirectory(pathRet); + return pathRet / "DashData"; +#else + // Unix + return pathRet / ".dash-data"; +#endif +#endif +} + // CDriveFile --- diff --git a/src/evo/file.h b/src/evo/file.h index a6b1b830ff6b..7697dd3dc11e 100644 --- a/src/evo/file.h +++ b/src/evo/file.h @@ -34,37 +34,7 @@ using namespace std; // TODO: What include is required for this? #define CLIENT_VERSION 1 -boost::filesystem::path GetDataDirectory() -{ - string strDataDir2 = GetArg("-datadir2", ""); - if(strDataDir2 != "") return strDataDir2; - - namespace fs = boost::filesystem; - // Windows < Vista: C:\Documents and Settings\Username\Application Data\Dash - // Windows >= Vista: C:\Users\Username\AppData\Roaming\Dash - // Mac: ~/Library/Application Support/Dash - // Unix: ~/.dash -#ifdef WIN32 - // Windows - return GetSpecialFolderPath(CSIDL_APPDATA) / "Dash"; -#else - fs::path pathRet; - char* pszHome = getenv("HOME"); - if (pszHome == NULL || strlen(pszHome) == 0) - pathRet = fs::path("/"); - else - pathRet = fs::path(pszHome); -#ifdef MAC_OSX - // Mac - pathRet /= "Library/Application Support"; - TryCreateDirectory(pathRet); - return pathRet / "DashData"; -#else - // Unix - return pathRet / ".dash-data"; -#endif -#endif -} +boost::filesystem::path GetDataDirectory(); class CDriveFile { From 0ca38f98444532892e99e1c9db93656a604c4fbd Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sat, 9 Jan 2016 23:40:56 -0700 Subject: [PATCH 26/51] commit include of init --- src/evo/dapi.cpp | 2 +- src/rpcdapi.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index a8948cc62fc7..8e9c49c20abf 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -9,7 +9,7 @@ #include "main.h" #include "core_io.h" #include "db.h" -#include "init.h" +//#include "init.h" #include "dapi.h" #include "file.h" #include "json/json_spirit.h" diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 1cba96e0ffa7..71443f9a73df 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -5,7 +5,7 @@ #include "main.h" #include "db.h" -#include "init.h" +//#include "init.h" #include "rpcserver.h" #include "utilmoneystr.h" #include "evo/dapi.h" From 4dd0100c31254066a3ade62f85bd39c95d64d33f Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sun, 10 Jan 2016 08:18:05 -0700 Subject: [PATCH 27/51] moved eventnotify from init --- src/evo/dapi.cpp | 9 +++++++++ src/evo/dapi.h | 10 +++++++++- src/init.cpp | 9 --------- src/init.h | 1 - 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 8e9c49c20abf..aaf7de9a51bf 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -15,6 +15,8 @@ #include "json/json_spirit.h" #include "json/json_spirit_value.h" #include +#include +#include int nError; @@ -40,6 +42,13 @@ std::string GetPrivateDataFile(std::string strUID, int nSlot) return filename.c_str(); } +void EventNotify(const std::string& strEvent) +{ + std::string strCmd = GetArg("-eventnotify", ""); + + boost::replace_all(strCmd, "%s", strEvent); + boost::thread t(runCommand, strCmd); // thread runs free +} std::string escapeJsonString(const std::string& input) { // NOTE: Any ideas on replacing this with something more portable? diff --git a/src/evo/dapi.h b/src/evo/dapi.h index fda2cc88328a..86320b0b64dc 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -9,9 +9,15 @@ #ifndef DAPI_H #define DAPI_H +namespace boost +{ +class thread_group; +} // namespace boost + + #include "main.h" #include "db.h" -#include "init.h" +//ø#include "init.h" #include "rpcserver.h" #include "util.h" @@ -35,6 +41,8 @@ std::string GetProfileFile(std::string strUID); std::string GetPrivateDataFile(std::string strUID, int nSlot); std::string escapeJsonString(const std::string& input); +void EventNotify(const std::string& strEvent); + class CDAPI { private: diff --git a/src/init.cpp b/src/init.cpp index 8071d5244302..89f1497b29ec 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -480,15 +480,6 @@ static void BlockNotifyCallback(const uint256& hashNewTip) boost::thread t(runCommand, strCmd); // thread runs free } -void EventNotify(const std::string& strEvent) -{ - std::string strCmd = GetArg("-eventnotify", ""); - - boost::replace_all(strCmd, "%s", strEvent); - boost::thread t(runCommand, strCmd); // thread runs free -} - - struct CImportingNow { CImportingNow() { diff --git a/src/init.h b/src/init.h index 12a871f00d2e..36300eadefb4 100644 --- a/src/init.h +++ b/src/init.h @@ -22,7 +22,6 @@ bool ShutdownRequested(); void Shutdown(); void PrepareShutdown(); bool AppInit2(boost::thread_group& threadGroup); -void EventNotify(const std::string& strEvent); /** The help message mode determines what help message to show */ enum HelpMessageMode { From ae857aba0d6812adc95e5321ee156561063af05b Mon Sep 17 00:00:00 2001 From: Holger Schinzel Date: Sun, 10 Jan 2016 17:14:58 +0100 Subject: [PATCH 28/51] v13.0.0 --- src/clientversion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clientversion.h b/src/clientversion.h index 9c51d8405cfe..94057848e46d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -15,9 +15,9 @@ //! These need to be macros, as clientversion.cpp's and dash*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 -#define CLIENT_VERSION_MINOR 12 +#define CLIENT_VERSION_MINOR 13 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 55 +#define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true From af3fc8d9ffa96f713ab80222579f25fee9220c4c Mon Sep 17 00:00:00 2001 From: Holger Schinzel Date: Sun, 10 Jan 2016 17:16:25 +0100 Subject: [PATCH 29/51] v0.13.0.0 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index b5893eedaa73..da6bdf4b7b25 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,9 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) -define(_CLIENT_VERSION_MINOR, 12) +define(_CLIENT_VERSION_MINOR, 13) define(_CLIENT_VERSION_REVISION, 0) -define(_CLIENT_VERSION_BUILD, 55) +define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2015) AC_INIT([Dash Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[info@dashpay.io],[dash]) From 9b9500cfb6670395624b64b1f6b8af668723ac3d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 13:22:38 -0700 Subject: [PATCH 30/51] validate usernames --- src/evo/dapi.cpp | 39 +++++++++++++++++++++++++++++++++++++-- src/evo/dapi.h | 1 + 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index aaf7de9a51bf..2615aaf47d77 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -17,7 +17,7 @@ #include #include #include - +#include int nError; std::string strErrorMessage; @@ -198,6 +198,11 @@ bool CDAPI::Execute(Object& obj) { ResetErrorStatus(); + if(obj.size() > 2000) + { + SetError(1013, "[\"object\"] is too large"); + } + // dapi command only std::string strObject; if(!FindValueAsString(obj, "object", strObject)) @@ -222,8 +227,12 @@ bool CDAPI::Execute(Object& obj) SetError(1012, "[\"data\"][\"command\"] is required in data structure"); } - // SUPPORTED COMMANDS + // check and make sure the usernames are OK + ValidateUsernames(obj); + + printf("%d\n", nError); + // SUPPORTED COMMANDS if(nError == 0) { if(strCommand == "get_profile") { @@ -272,6 +281,32 @@ bool CDAPI::ValidateSignature(Object& obj) return true; } + +bool CDAPI::ValidateUsernames(Object& obj) +{ + + // get the user we want to open + Object objData; + string strUID = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(FindValueAsString(objData, "to_uid", strUID)) + { + if (!std::regex_match (strUID, std::regex("^[a-zA-Z0-9]+$") )) + { + SetError(1011, "Invalid to_uid - must be alphanumeric: " + strUID); + } + } + if(FindValueAsString(objData, "from_uid", strUID)) + { + if (!std::regex_match (strUID, std::regex("^[a-zA-Z0-9]+$") )) + { + SetError(1011, "Invalid from_uid - must be alphanumeric: " + strUID); + } + } + + return true; +} + bool CDAPI::GetProfile(Object& obj) { /* diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 86320b0b64dc..0698cf715519 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -49,6 +49,7 @@ class CDAPI CDAPI(); public: + static bool ValidateUsernames(Object& obj); static bool Execute(Object& obj); static bool ValidateSignature(Object& obj); static bool GetProfile(Object& obj); From 9e469e144a8dc6c82af7ea8bbd5f795540227e88 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 13:52:02 -0700 Subject: [PATCH 31/51] removed regex for compatibility --- src/evo/dapi.cpp | 14 +++++++++++--- src/evo/dapi.h | 1 - 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 2615aaf47d77..c4cccedd7dfd 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -17,7 +17,6 @@ #include #include #include -#include int nError; std::string strErrorMessage; @@ -42,6 +41,14 @@ std::string GetPrivateDataFile(std::string strUID, int nSlot) return filename.c_str(); } +bool IsValidUsername(std::string strUsername) +{ + for(std::string::size_type i = 0; i < strUsername.size(); ++i) { + if(!std::isalpha(strUsername[i]) && !std::isdigit(strUsername[i]) ) return false; + } + return true; +} + void EventNotify(const std::string& strEvent) { std::string strCmd = GetArg("-eventnotify", ""); @@ -289,16 +296,17 @@ bool CDAPI::ValidateUsernames(Object& obj) Object objData; string strUID = ""; if(!FindValueAsObject(obj, "data", objData)) return false; + if(FindValueAsString(objData, "to_uid", strUID)) { - if (!std::regex_match (strUID, std::regex("^[a-zA-Z0-9]+$") )) + if (!IsValidUsername(strUID)) { SetError(1011, "Invalid to_uid - must be alphanumeric: " + strUID); } } if(FindValueAsString(objData, "from_uid", strUID)) { - if (!std::regex_match (strUID, std::regex("^[a-zA-Z0-9]+$") )) + if (!IsValidUsername(strUID)) { SetError(1011, "Invalid from_uid - must be alphanumeric: " + strUID); } diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 0698cf715519..376e413b4d39 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -30,7 +30,6 @@ class thread_group; #include "univalue/univalue.h" #include #include - #include using namespace std; From 9d996d17054e562d78b2a8c2d271171bfe763edc Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 14:16:49 -0700 Subject: [PATCH 32/51] debug evo vars --- src/init.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 89f1497b29ec..37c74e0bfd65 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1416,6 +1416,14 @@ bool AppInit2(boost::thread_group& threadGroup) // ********************************************************* Step 10: setup DarkSend + LogPrintf("Dash Evolution Variables...\n"); + + std::string datadir = GetArg("-datadir", "none"); + std::string eventnotify = GetArg("-eventnotify", "none"); + + LogPrintf("datadir2 = %s\n", datadir); + LogPrintf("eventnotify command = %s\n", eventnotify); + uiInterface.InitMessage(_("Loading masternode cache...")); CMasternodeDB mndb; From 99d082b310eb7782ccda2a7becbf56a965478c53 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 17:14:30 -0700 Subject: [PATCH 33/51] add debuging vars --- src/rpcdapi.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 71443f9a73df..0d589c4e1525 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -87,11 +87,14 @@ Value dapif(const Array& params, bool fHelp) */ std::string strPath = params[0].get_str(); + + printf("path %s\n", strPath.c_str()); + std::ifstream t(strPath.c_str()); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); - printf("%s\n", str.c_str()); + printf("json %s\n", str.c_str()); json_spirit::Value val; From 22a4bcfc92c178cb0d4385a6c04a29a68ad9e43a Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 18:56:18 -0700 Subject: [PATCH 34/51] moved around eventnotify --- src/evo/dapi.cpp | 19 ++++++++++++++++++- src/evo/dapi.h | 6 ------ src/init.cpp | 8 ++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index c4cccedd7dfd..2bb81eb2fc94 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -9,7 +9,7 @@ #include "main.h" #include "core_io.h" #include "db.h" -//#include "init.h" +#include "init.h" #include "dapi.h" #include "file.h" #include "json/json_spirit.h" @@ -18,6 +18,11 @@ #include #include +#include +#include +#include +#include + int nError; std::string strErrorMessage; // error reporting @@ -49,6 +54,18 @@ bool IsValidUsername(std::string strUsername) return true; } +// std::string exec(const char* cmd) { +// std::shared_ptr pipe(popen(cmd, "r"), pclose); +// if (!pipe) return "ERROR"; +// char buffer[128]; +// std::string result = ""; +// while (!feof(pipe.get())) { +// if (fgets(buffer, 128, pipe.get()) != NULL) +// result += buffer; +// } +// return result; +// } + void EventNotify(const std::string& strEvent) { std::string strCmd = GetArg("-eventnotify", ""); diff --git a/src/evo/dapi.h b/src/evo/dapi.h index 376e413b4d39..c2dad3e8212e 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -9,12 +9,6 @@ #ifndef DAPI_H #define DAPI_H -namespace boost -{ -class thread_group; -} // namespace boost - - #include "main.h" #include "db.h" //ø#include "init.h" diff --git a/src/init.cpp b/src/init.cpp index 37c74e0bfd65..ac5339c2c845 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -472,6 +472,14 @@ std::string LicenseInfo() "\n"; } +void EventNotify(const std::string& strEvent) +{ + std::string strCmd = GetArg("-eventnotify", ""); + + boost::replace_all(strCmd, "%s", strEvent); + boost::thread t(runCommand, strCmd); // thread runs free +} + static void BlockNotifyCallback(const uint256& hashNewTip) { std::string strCmd = GetArg("-blocknotify", ""); From c131290dcf50f59c559777bf473af9a096095f53 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 19:06:34 -0700 Subject: [PATCH 35/51] removed eventnotify declaration --- src/evo/dapi.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/evo/dapi.h b/src/evo/dapi.h index c2dad3e8212e..836b05c743bb 100644 --- a/src/evo/dapi.h +++ b/src/evo/dapi.h @@ -34,8 +34,6 @@ std::string GetProfileFile(std::string strUID); std::string GetPrivateDataFile(std::string strUID, int nSlot); std::string escapeJsonString(const std::string& input); -void EventNotify(const std::string& strEvent); - class CDAPI { private: From dc73fe20a5f3bf64efed33166e983377911e0f8c Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 20:45:02 -0700 Subject: [PATCH 36/51] added websockets client --- src/Makefile.am | 2 + src/easywsclient.cpp | 527 +++++++++++++++++++++++++++++++++++++++++++ src/easywsclient.h | 72 ++++++ src/evo/dapi.cpp | 26 ++- src/init.cpp | 8 - 5 files changed, 621 insertions(+), 14 deletions(-) create mode 100644 src/easywsclient.cpp create mode 100644 src/easywsclient.h diff --git a/src/Makefile.am b/src/Makefile.am index 8577a9b8b7c8..209c7c808cba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -94,6 +94,7 @@ BITCOIN_CORE_H = \ crypter.h \ darksend.h \ darksend-relay.h \ + easywsclient.h \ db.h \ eccryptoverify.h \ ecwrapper.h \ @@ -180,6 +181,7 @@ libbitcoin_server_a_SOURCES = \ bloom.cpp \ chain.cpp \ checkpoints.cpp \ + easywsclient.cpp \ evo/file.cpp \ evo/dapi.cpp \ json/json_spirit_reader.cpp \ diff --git a/src/easywsclient.cpp b/src/easywsclient.cpp new file mode 100644 index 000000000000..49230f2429e5 --- /dev/null +++ b/src/easywsclient.cpp @@ -0,0 +1,527 @@ + +#ifdef _WIN32 + #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) + #define _CRT_SECURE_NO_WARNINGS // _CRT_SECURE_NO_WARNINGS for sscanf errors in MSVC2013 Express + #endif + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include + #include + #include + #pragma comment( lib, "ws2_32" ) + #include + #include + #include + #include + #include + #ifndef _SSIZE_T_DEFINED + typedef int ssize_t; + #define _SSIZE_T_DEFINED + #endif + #ifndef _SOCKET_T_DEFINED + typedef SOCKET socket_t; + #define _SOCKET_T_DEFINED + #endif + #ifndef snprintf + #define snprintf _snprintf_s + #endif + #if _MSC_VER >=1600 + // vs2010 or later + #include + #else + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + #endif + #define socketerrno WSAGetLastError() + #define SOCKET_EAGAIN_EINPROGRESS WSAEINPROGRESS + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifndef _SOCKET_T_DEFINED + typedef int socket_t; + #define _SOCKET_T_DEFINED + #endif + #ifndef INVALID_SOCKET + #define INVALID_SOCKET (-1) + #endif + #ifndef SOCKET_ERROR + #define SOCKET_ERROR (-1) + #endif + #define closesocket(s) ::close(s) + #include + #define socketerrno errno + #define SOCKET_EAGAIN_EINPROGRESS EAGAIN + #define SOCKET_EWOULDBLOCK EWOULDBLOCK +#endif + +#include +#include + +#include "easywsclient.h" + +using easywsclient::Callback_Imp; +using easywsclient::BytesCallback_Imp; + +namespace { // private module-only namespace + +socket_t hostname_connect(const std::string& hostname, int port) { + struct addrinfo hints; + struct addrinfo *result; + struct addrinfo *p; + int ret; + socket_t sockfd = INVALID_SOCKET; + char sport[16]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + snprintf(sport, 16, "%d", port); + if ((ret = getaddrinfo(hostname.c_str(), sport, &hints, &result)) != 0) + { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); + return 1; + } + for(p = result; p != NULL; p = p->ai_next) + { + sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (sockfd == INVALID_SOCKET) { continue; } + if (connect(sockfd, p->ai_addr, p->ai_addrlen) != SOCKET_ERROR) { + break; + } + closesocket(sockfd); + sockfd = INVALID_SOCKET; + } + freeaddrinfo(result); + return sockfd; +} + + +class _DummyWebSocket : public easywsclient::WebSocket +{ + public: + void poll(int timeout) { } + void send(const std::string& message) { } + void sendBinary(const std::string& message) { } + void sendBinary(const std::vector& message) { } + void sendPing() { } + void close() { } + readyStateValues getReadyState() const { return CLOSED; } + void _dispatch(Callback_Imp & callable) { } + void _dispatchBinary(BytesCallback_Imp& callable) { } +}; + + +class _RealWebSocket : public easywsclient::WebSocket +{ + public: + // http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol + // + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-------+-+-------------+-------------------------------+ + // |F|R|R|R| opcode|M| Payload len | Extended payload length | + // |I|S|S|S| (4) |A| (7) | (16/64) | + // |N|V|V|V| |S| | (if payload len==126/127) | + // | |1|2|3| |K| | | + // +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + // | Extended payload length continued, if payload len == 127 | + // + - - - - - - - - - - - - - - - +-------------------------------+ + // | |Masking-key, if MASK set to 1 | + // +-------------------------------+-------------------------------+ + // | Masking-key (continued) | Payload Data | + // +-------------------------------- - - - - - - - - - - - - - - - + + // : Payload Data continued ... : + // + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + // | Payload Data continued ... | + // +---------------------------------------------------------------+ + struct wsheader_type { + unsigned header_size; + bool fin; + bool mask; + enum opcode_type { + CONTINUATION = 0x0, + TEXT_FRAME = 0x1, + BINARY_FRAME = 0x2, + CLOSE = 8, + PING = 9, + PONG = 0xa, + } opcode; + int N0; + uint64_t N; + uint8_t masking_key[4]; + }; + + std::vector rxbuf; + std::vector txbuf; + std::vector receivedData; + + socket_t sockfd; + readyStateValues readyState; + bool useMask; + + _RealWebSocket(socket_t sockfd, bool useMask) : sockfd(sockfd), readyState(OPEN), useMask(useMask) { + } + + readyStateValues getReadyState() const { + return readyState; + } + + void poll(int timeout) { // timeout in milliseconds + if (readyState == CLOSED) { + if (timeout > 0) { + timeval tv = { timeout/1000, (timeout%1000) * 1000 }; + select(0, NULL, NULL, NULL, &tv); + } + return; + } + if (timeout != 0) { + fd_set rfds; + fd_set wfds; + timeval tv = { timeout/1000, (timeout%1000) * 1000 }; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_SET(sockfd, &rfds); + if (txbuf.size()) { FD_SET(sockfd, &wfds); } + select(sockfd + 1, &rfds, &wfds, 0, timeout > 0 ? &tv : 0); + } + while (true) { + // FD_ISSET(0, &rfds) will be true + int N = rxbuf.size(); + ssize_t ret; + rxbuf.resize(N + 1500); + ret = recv(sockfd, (char*)&rxbuf[0] + N, 1500, 0); + if (false) { } + else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS)) { + rxbuf.resize(N); + break; + } + else if (ret <= 0) { + rxbuf.resize(N); + closesocket(sockfd); + readyState = CLOSED; + fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr); + break; + } + else { + rxbuf.resize(N + ret); + } + } + while (txbuf.size()) { + int ret = ::send(sockfd, (char*)&txbuf[0], txbuf.size(), 0); + if (false) { } // ?? + else if (ret < 0 && (socketerrno == SOCKET_EWOULDBLOCK || socketerrno == SOCKET_EAGAIN_EINPROGRESS)) { + break; + } + else if (ret <= 0) { + closesocket(sockfd); + readyState = CLOSED; + fputs(ret < 0 ? "Connection error!\n" : "Connection closed!\n", stderr); + break; + } + else { + txbuf.erase(txbuf.begin(), txbuf.begin() + ret); + } + } + if (!txbuf.size() && readyState == CLOSING) { + closesocket(sockfd); + readyState = CLOSED; + } + } + + // Callable must have signature: void(const std::string & message). + // Should work with C functions, C++ functors, and C++11 std::function and + // lambda: + //template + //void dispatch(Callable callable) + virtual void _dispatch(Callback_Imp & callable) { + struct CallbackAdapter : public BytesCallback_Imp + // Adapt void(const std::string&) to void(const std::string&) + { + Callback_Imp& callable; + CallbackAdapter(Callback_Imp& callable) : callable(callable) { } + void operator()(const std::vector& message) { + std::string stringMessage(message.begin(), message.end()); + callable(stringMessage); + } + }; + CallbackAdapter bytesCallback(callable); + _dispatchBinary(bytesCallback); + } + + virtual void _dispatchBinary(BytesCallback_Imp & callable) { + // TODO: consider acquiring a lock on rxbuf... + while (true) { + wsheader_type ws; + if (rxbuf.size() < 2) { return; /* Need at least 2 */ } + const uint8_t * data = (uint8_t *) &rxbuf[0]; // peek, but don't consume + ws.fin = (data[0] & 0x80) == 0x80; + ws.opcode = (wsheader_type::opcode_type) (data[0] & 0x0f); + ws.mask = (data[1] & 0x80) == 0x80; + ws.N0 = (data[1] & 0x7f); + ws.header_size = 2 + (ws.N0 == 126? 2 : 0) + (ws.N0 == 127? 8 : 0) + (ws.mask? 4 : 0); + if (rxbuf.size() < ws.header_size) { return; /* Need: ws.header_size - rxbuf.size() */ } + int i = 0; + if (ws.N0 < 126) { + ws.N = ws.N0; + i = 2; + } + else if (ws.N0 == 126) { + ws.N = 0; + ws.N |= ((uint64_t) data[2]) << 8; + ws.N |= ((uint64_t) data[3]) << 0; + i = 4; + } + else if (ws.N0 == 127) { + ws.N = 0; + ws.N |= ((uint64_t) data[2]) << 56; + ws.N |= ((uint64_t) data[3]) << 48; + ws.N |= ((uint64_t) data[4]) << 40; + ws.N |= ((uint64_t) data[5]) << 32; + ws.N |= ((uint64_t) data[6]) << 24; + ws.N |= ((uint64_t) data[7]) << 16; + ws.N |= ((uint64_t) data[8]) << 8; + ws.N |= ((uint64_t) data[9]) << 0; + i = 10; + } + if (ws.mask) { + ws.masking_key[0] = ((uint8_t) data[i+0]) << 0; + ws.masking_key[1] = ((uint8_t) data[i+1]) << 0; + ws.masking_key[2] = ((uint8_t) data[i+2]) << 0; + ws.masking_key[3] = ((uint8_t) data[i+3]) << 0; + } + else { + ws.masking_key[0] = 0; + ws.masking_key[1] = 0; + ws.masking_key[2] = 0; + ws.masking_key[3] = 0; + } + if (rxbuf.size() < ws.header_size+ws.N) { return; /* Need: ws.header_size+ws.N - rxbuf.size() */ } + + // We got a whole message, now do something with it: + if (false) { } + else if ( + ws.opcode == wsheader_type::TEXT_FRAME + || ws.opcode == wsheader_type::BINARY_FRAME + || ws.opcode == wsheader_type::CONTINUATION + ) { + if (ws.mask) { for (size_t i = 0; i != ws.N; ++i) { rxbuf[i+ws.header_size] ^= ws.masking_key[i&0x3]; } } + receivedData.insert(receivedData.end(), rxbuf.begin()+ws.header_size, rxbuf.begin()+ws.header_size+(size_t)ws.N);// just feed + if (ws.fin) { + callable((const std::vector) receivedData); + receivedData.erase(receivedData.begin(), receivedData.end()); + std::vector ().swap(receivedData);// free memory + } + } + else if (ws.opcode == wsheader_type::PING) { + if (ws.mask) { for (size_t i = 0; i != ws.N; ++i) { rxbuf[i+ws.header_size] ^= ws.masking_key[i&0x3]; } } + std::string data(rxbuf.begin()+ws.header_size, rxbuf.begin()+ws.header_size+(size_t)ws.N); + sendData(wsheader_type::PONG, data.size(), data.begin(), data.end()); + } + else if (ws.opcode == wsheader_type::PONG) { } + else if (ws.opcode == wsheader_type::CLOSE) { close(); } + else { fprintf(stderr, "ERROR: Got unexpected WebSocket message.\n"); close(); } + + rxbuf.erase(rxbuf.begin(), rxbuf.begin() + ws.header_size+(size_t)ws.N); + } + } + + void sendPing() { + std::string empty; + sendData(wsheader_type::PING, empty.size(), empty.begin(), empty.end()); + } + + void send(const std::string& message) { + sendData(wsheader_type::TEXT_FRAME, message.size(), message.begin(), message.end()); + } + + void sendBinary(const std::string& message) { + sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end()); + } + + void sendBinary(const std::vector& message) { + sendData(wsheader_type::BINARY_FRAME, message.size(), message.begin(), message.end()); + } + + template + void sendData(wsheader_type::opcode_type type, uint64_t message_size, Iterator message_begin, Iterator message_end) { + // TODO: + // Masking key should (must) be derived from a high quality random + // number generator, to mitigate attacks on non-WebSocket friendly + // middleware: + const uint8_t masking_key[4] = { 0x12, 0x34, 0x56, 0x78 }; + // TODO: consider acquiring a lock on txbuf... + if (readyState == CLOSING || readyState == CLOSED) { printf("closed\n"); return; } + std::vector header; + header.assign(2 + (message_size >= 126 ? 2 : 0) + (message_size >= 65536 ? 6 : 0) + (useMask ? 4 : 0), 0); + header[0] = 0x80 | type; + if (false) { } + else if (message_size < 126) { + header[1] = (message_size & 0xff) | (useMask ? 0x80 : 0); + if (useMask) { + header[2] = masking_key[0]; + header[3] = masking_key[1]; + header[4] = masking_key[2]; + header[5] = masking_key[3]; + } + } + else if (message_size < 65536) { + header[1] = 126 | (useMask ? 0x80 : 0); + header[2] = (message_size >> 8) & 0xff; + header[3] = (message_size >> 0) & 0xff; + if (useMask) { + header[4] = masking_key[0]; + header[5] = masking_key[1]; + header[6] = masking_key[2]; + header[7] = masking_key[3]; + } + } + else { // TODO: run coverage testing here + header[1] = 127 | (useMask ? 0x80 : 0); + header[2] = (message_size >> 56) & 0xff; + header[3] = (message_size >> 48) & 0xff; + header[4] = (message_size >> 40) & 0xff; + header[5] = (message_size >> 32) & 0xff; + header[6] = (message_size >> 24) & 0xff; + header[7] = (message_size >> 16) & 0xff; + header[8] = (message_size >> 8) & 0xff; + header[9] = (message_size >> 0) & 0xff; + if (useMask) { + header[10] = masking_key[0]; + header[11] = masking_key[1]; + header[12] = masking_key[2]; + header[13] = masking_key[3]; + } + } + printf("added to buffer\n"); + // N.B. - txbuf will keep growing until it can be transmitted over the socket: + txbuf.insert(txbuf.end(), header.begin(), header.end()); + txbuf.insert(txbuf.end(), message_begin, message_end); + if (useMask) { + for (size_t i = 0; i != message_size; ++i) { *(txbuf.end() - message_size + i) ^= masking_key[i&0x3]; } + } + } + + void close() { + if(readyState == CLOSING || readyState == CLOSED) { return; } + readyState = CLOSING; + uint8_t closeFrame[6] = {0x88, 0x80, 0x00, 0x00, 0x00, 0x00}; // last 4 bytes are a masking key + std::vector header(closeFrame, closeFrame+6); + txbuf.insert(txbuf.end(), header.begin(), header.end()); + } + +}; + + +easywsclient::WebSocket::pointer from_url(const std::string& url, bool useMask, const std::string& origin) { + char host[128]; + int port; + char path[128]; + if (url.size() >= 128) { + fprintf(stderr, "ERROR: url size limit exceeded: %s\n", url.c_str()); + return NULL; + } + if (origin.size() >= 200) { + fprintf(stderr, "ERROR: origin size limit exceeded: %s\n", origin.c_str()); + return NULL; + } + if (false) { } + else if (sscanf(url.c_str(), "ws://%[^:/]:%d/%s", host, &port, path) == 3) { + } + else if (sscanf(url.c_str(), "ws://%[^:/]/%s", host, path) == 2) { + port = 80; + } + else if (sscanf(url.c_str(), "ws://%[^:/]:%d", host, &port) == 2) { + path[0] = '\0'; + } + else if (sscanf(url.c_str(), "ws://%[^:/]", host) == 1) { + port = 80; + path[0] = '\0'; + } + else { + fprintf(stderr, "ERROR: Could not parse WebSocket url: %s\n", url.c_str()); + return NULL; + } + fprintf(stderr, "easywsclient: connecting: host=%s port=%d path=/%s\n", host, port, path); + socket_t sockfd = hostname_connect(host, port); + if (sockfd == INVALID_SOCKET) { + fprintf(stderr, "Unable to connect to %s:%d\n", host, port); + return NULL; + } + { + // XXX: this should be done non-blocking, + char line[256]; + int status; + int i; + snprintf(line, 256, "GET /%s HTTP/1.1\r\n", path); ::send(sockfd, line, strlen(line), 0); + if (port == 80) { + snprintf(line, 256, "Host: %s\r\n", host); ::send(sockfd, line, strlen(line), 0); + } + else { + snprintf(line, 256, "Host: %s:%d\r\n", host, port); ::send(sockfd, line, strlen(line), 0); + } + snprintf(line, 256, "Upgrade: websocket\r\n"); ::send(sockfd, line, strlen(line), 0); + snprintf(line, 256, "Connection: Upgrade\r\n"); ::send(sockfd, line, strlen(line), 0); + if (!origin.empty()) { + snprintf(line, 256, "Origin: %s\r\n", origin.c_str()); ::send(sockfd, line, strlen(line), 0); + } + snprintf(line, 256, "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"); ::send(sockfd, line, strlen(line), 0); + snprintf(line, 256, "Sec-WebSocket-Version: 13\r\n"); ::send(sockfd, line, strlen(line), 0); + snprintf(line, 256, "\r\n"); ::send(sockfd, line, strlen(line), 0); + for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } } + line[i] = 0; + if (i == 255) { fprintf(stderr, "ERROR: Got invalid status line connecting to: %s\n", url.c_str()); return NULL; } + if (sscanf(line, "HTTP/1.1 %d", &status) != 1 || status != 101) { fprintf(stderr, "ERROR: Got bad status connecting to %s: %s", url.c_str(), line); return NULL; } + // TODO: verify response headers, + while (true) { + for (i = 0; i < 2 || (i < 255 && line[i-2] != '\r' && line[i-1] != '\n'); ++i) { if (recv(sockfd, line+i, 1, 0) == 0) { return NULL; } } + if (line[0] == '\r' && line[1] == '\n') { break; } + } + } + int flag = 1; + setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(flag)); // Disable Nagle's algorithm +#ifdef _WIN32 + u_long on = 1; + ioctlsocket(sockfd, FIONBIO, &on); +#else + fcntl(sockfd, F_SETFL, O_NONBLOCK); +#endif + fprintf(stderr, "Connected to: %s\n", url.c_str()); + return easywsclient::WebSocket::pointer(new _RealWebSocket(sockfd, useMask)); +} + +} // end of module-only namespace + + + +namespace easywsclient { + +WebSocket::pointer WebSocket::create_dummy() { + static pointer dummy = pointer(new _DummyWebSocket); + return dummy; +} + + +WebSocket::pointer WebSocket::from_url(const std::string& url, const std::string& origin) { + return ::from_url(url, true, origin); +} + +WebSocket::pointer WebSocket::from_url_no_mask(const std::string& url, const std::string& origin) { + return ::from_url(url, false, origin); +} + + +} // namespace easywsclient \ No newline at end of file diff --git a/src/easywsclient.h b/src/easywsclient.h new file mode 100644 index 000000000000..5a7148b12f33 --- /dev/null +++ b/src/easywsclient.h @@ -0,0 +1,72 @@ +#ifndef EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD +#define EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD + +// This code comes from: +// https://github.com/dhbaird/easywsclient +// +// To get the latest version: +// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.hpp +// wget https://raw.github.com/dhbaird/easywsclient/master/easywsclient.cpp + +#include +#include + +namespace easywsclient { + +struct Callback_Imp { virtual void operator()(const std::string& message) = 0; }; +struct BytesCallback_Imp { virtual void operator()(const std::vector& message) = 0; }; + +class WebSocket { + public: + typedef WebSocket * pointer; + typedef enum readyStateValues { CLOSING, CLOSED, CONNECTING, OPEN } readyStateValues; + + // Factories: + static pointer create_dummy(); + static pointer from_url(const std::string& url, const std::string& origin = std::string()); + static pointer from_url_no_mask(const std::string& url, const std::string& origin = std::string()); + + // Interfaces: + virtual ~WebSocket() { } + virtual void poll(int timeout = 0) = 0; // timeout in milliseconds + virtual void send(const std::string& message) = 0; + virtual void sendBinary(const std::string& message) = 0; + virtual void sendBinary(const std::vector& message) = 0; + virtual void sendPing() = 0; + virtual void close() = 0; + virtual readyStateValues getReadyState() const = 0; + + template + void dispatch(Callable callable) + // For callbacks that accept a string argument. + { // N.B. this is compatible with both C++11 lambdas, functors and C function pointers + struct _Callback : public Callback_Imp { + Callable& callable; + _Callback(Callable& callable) : callable(callable) { } + void operator()(const std::string& message) { callable(message); } + }; + _Callback callback(callable); + _dispatch(callback); + } + + template + void dispatchBinary(Callable callable) + // For callbacks that accept a std::vector argument. + { // N.B. this is compatible with both C++11 lambdas, functors and C function pointers + struct _Callback : public BytesCallback_Imp { + Callable& callable; + _Callback(Callable& callable) : callable(callable) { } + void operator()(const std::vector& message) { callable(message); } + }; + _Callback callback(callable); + _dispatchBinary(callback); + } + + protected: + virtual void _dispatch(Callback_Imp& callable) = 0; + virtual void _dispatchBinary(BytesCallback_Imp& callable) = 0; +}; + +} // namespace easywsclient + +#endif /* EASYWSCLIENT_HPP_20120819_MIOFVASDTNUASZDQPLFD */ \ No newline at end of file diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 2bb81eb2fc94..dea0ec3321a0 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -9,11 +9,11 @@ #include "main.h" #include "core_io.h" #include "db.h" -#include "init.h" #include "dapi.h" #include "file.h" #include "json/json_spirit.h" #include "json/json_spirit_value.h" +#include "easywsclient.h" #include #include #include @@ -27,6 +27,9 @@ int nError; std::string strErrorMessage; // error reporting +using easywsclient::WebSocket; +WebSocket::pointer ws_client; + std::string GetIndexFile(std::string strFilename) { boost::filesystem::path filename = GetDataDirectory() / "index" / strFilename; @@ -70,8 +73,19 @@ void EventNotify(const std::string& strEvent) { std::string strCmd = GetArg("-eventnotify", ""); - boost::replace_all(strCmd, "%s", strEvent); - boost::thread t(runCommand, strCmd); // thread runs free + //boost::replace_all(strCmd, "%s", strEvent); + //boost::thread t(runCommand, strCmd); // thread runs free + + if(!ws_client) + { + ws_client = WebSocket::from_url("ws://localhost:5000/"); + } + + assert(ws_client); + ws_client->send(strEvent); + ws_client->poll(); + + printf("%s\n", strEvent.c_str()); } std::string escapeJsonString(const std::string& input) { @@ -156,9 +170,9 @@ std::string SerializeJsonFromObject(Object objToSerialize) //TODO: this is terrible, we need to correctly clean and escape the json :) std::stringstream ss; json_spirit::write( objToSerialize, ss ); - std::string strJson = escapeJsonString("'" + ss.str() + "'"); - strJson.replace(0,1,"\""); - strJson.replace(strJson.size()-1,1,"\""); + std::string strJson = ss.str(); // escapeJsonString("'" + ss.str() + "'"); + // strJson.replace(0,1,"\""); + // strJson.replace(strJson.size()-1,1,"\""); return strJson; } diff --git a/src/init.cpp b/src/init.cpp index ac5339c2c845..37c74e0bfd65 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -472,14 +472,6 @@ std::string LicenseInfo() "\n"; } -void EventNotify(const std::string& strEvent) -{ - std::string strCmd = GetArg("-eventnotify", ""); - - boost::replace_all(strCmd, "%s", strEvent); - boost::thread t(runCommand, strCmd); // thread runs free -} - static void BlockNotifyCallback(const uint256& hashNewTip) { std::string strCmd = GetArg("-blocknotify", ""); From 49df096b4531c4030f95524b67444515dc3f526b Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 21:01:21 -0700 Subject: [PATCH 37/51] fixed bug with getprofile --- src/evo/dapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index dea0ec3321a0..7c84679f620f 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -365,7 +365,7 @@ bool CDAPI::GetProfile(Object& obj) Object objData; string strUID = ""; if(!FindValueAsObject(obj, "data", objData)) return false; - if(!FindValueAsString(obj, "to_uid", strUID)) return false; + if(!FindValueAsString(objData, "to_uid", strUID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); From 9a4e419215cb33b6309d61e9c46db49a428ae5ec Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 11 Jan 2016 21:13:05 -0700 Subject: [PATCH 38/51] data test bugs and fixed username tests --- src/evo/dapi.cpp | 8 ++++---- src/test/data/dapi-broadcast-tx.js | 4 ++-- src/test/data/dapi-get-private-data.js | 4 ++-- src/test/data/dapi-get-profile.js | 4 ++-- src/test/data/dapi-set-private-data.js | 4 ++-- src/test/data/dapi-set-profile.js | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 7c84679f620f..8f9827d17263 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -178,12 +178,12 @@ std::string SerializeJsonFromObject(Object objToSerialize) // GET OBJECT AND CONVERT TO VARIABLE -bool FindValueAsString(Object obj, std::string strName, std::string& strOut) +bool FindValueAsString(Object obj, std::string strName, std::string& strOut, bool fRequired=true) { const Value& result = json_spirit::find_value(obj, strName); if (result.type() == null_type) { - SetError(1008, "Missing required field : " + strName); + if(fRequired) SetError(1008, "Missing required field : " + strName); return false; } @@ -328,14 +328,14 @@ bool CDAPI::ValidateUsernames(Object& obj) string strUID = ""; if(!FindValueAsObject(obj, "data", objData)) return false; - if(FindValueAsString(objData, "to_uid", strUID)) + if(FindValueAsString(objData, "to_uid", strUID, false)) { if (!IsValidUsername(strUID)) { SetError(1011, "Invalid to_uid - must be alphanumeric: " + strUID); } } - if(FindValueAsString(objData, "from_uid", strUID)) + if(FindValueAsString(objData, "from_uid", strUID, false)) { if (!IsValidUsername(strUID)) { diff --git a/src/test/data/dapi-broadcast-tx.js b/src/test/data/dapi-broadcast-tx.js index bcf7b861d8c0..d4c9f66d8e4d 100644 --- a/src/test/data/dapi-broadcast-tx.js +++ b/src/test/data/dapi-broadcast-tx.js @@ -3,8 +3,8 @@ "data" : { "command" : "broadcast_message", "subcommand" : "tx", - "my_uid" : "1337", - "target_uid" : "1337", + "from_uid" : "1337", + "to_uid" : "1337", "payload" : "SIG" } } \ No newline at end of file diff --git a/src/test/data/dapi-get-private-data.js b/src/test/data/dapi-get-private-data.js index 01dc3fcca7b5..0ed159865d36 100644 --- a/src/test/data/dapi-get-private-data.js +++ b/src/test/data/dapi-get-private-data.js @@ -2,8 +2,8 @@ "object" : "dapi_command", "data" : { "command" : "get_private_data", - "my_uid" : "1337", - "target_uid" : "1337", + "from_uid" : "1337", + "to_uid" : "1337", "signature" : "SIG", "slot" : 1 } diff --git a/src/test/data/dapi-get-profile.js b/src/test/data/dapi-get-profile.js index 76e35ae04e84..3841b7a119ae 100644 --- a/src/test/data/dapi-get-profile.js +++ b/src/test/data/dapi-get-profile.js @@ -2,8 +2,8 @@ "object" : "dapi_command", "data" : { "command" : "get_profile", - "my_uid" : "1337", - "target_uid" : "1337", + "from_uid" : "1337", + "to_uid" : "1337", "signature" : "SIG", "fields" : ["fname", "lname"] } diff --git a/src/test/data/dapi-set-private-data.js b/src/test/data/dapi-set-private-data.js index 99e6ab1d4481..4c577769396b 100644 --- a/src/test/data/dapi-set-private-data.js +++ b/src/test/data/dapi-set-private-data.js @@ -2,8 +2,8 @@ "object" : "dapi_command", "data" : { "command" : "set_private_data", - "my_uid" : "1337", - "target_uid" : "1337", + "from_uid" : "1337", + "to_uid" : "1337", "signature" : "SIG", "slot" : 1, "payload" : "AOEU" diff --git a/src/test/data/dapi-set-profile.js b/src/test/data/dapi-set-profile.js index f326950c28ec..633793e8bdf2 100644 --- a/src/test/data/dapi-set-profile.js +++ b/src/test/data/dapi-set-profile.js @@ -2,8 +2,8 @@ "object" : "dapi_command", "data" : { "command": "set_profile", - "my_uid": "1337", - "target_uid": "1337", + "from_uid": "1337", + "to_uid": "1337", "signature": "", "update" : [ {"field":"name","value":"uberevan"} From ac930df2d1be51726db1af65cd860a8757ccf648 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 05:46:57 -0700 Subject: [PATCH 39/51] changed id to time --- src/evo/dapi.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 8f9827d17263..bd6ec94d5e28 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -85,7 +85,7 @@ void EventNotify(const std::string& strEvent) ws_client->send(strEvent); ws_client->poll(); - printf("%s\n", strEvent.c_str()); + printf("sending out: %s\n", strEvent.c_str()); } std::string escapeJsonString(const std::string& input) { @@ -299,7 +299,7 @@ bool CDAPI::Execute(Object& obj) // send the user back the results of the query if(nError == 0) SetError(1007, "Unknown Command : " + strCommand); Object result; - Object ret = GetResultObject(1000, strCommand, result); + Object ret = GetResultObject(GetTime(), strCommand, result); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -377,7 +377,7 @@ bool CDAPI::GetProfile(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(1000, "get_profile", file.obj); + Object ret = GetResultObject(GetTime(), "get_profile", file.obj); std::string strJson2 = SerializeJsonFromObject(file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -443,7 +443,7 @@ bool CDAPI::SetProfile(Object& obj) json_spirit::map_to_obj(mapObj, file.obj); file.Write(); - Object ret = GetResultObject(1000, "set_profile", file.obj); + Object ret = GetResultObject(GetTime(), "set_profile", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -485,7 +485,7 @@ bool CDAPI::GetPrivateData(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(1000, "get_private_data", file.obj); + Object ret = GetResultObject(GetTime(), "get_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -545,7 +545,7 @@ bool CDAPI::SetPrivateData(Object& obj) file.Write(); // send the user back the results of the query - Object ret = GetResultObject(1000, "set_private_data", file.obj); + Object ret = GetResultObject(GetTime(), "set_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -631,7 +631,7 @@ bool CDAPI::BroadcastMessage(Object& obj) //should probably figure out if it was broadcasted successfully // send the user back the results of the query - Object ret = GetResultObject(1000, "broadcast_message", retTx); + Object ret = GetResultObject(GetTime(), "broadcast_message", retTx); std::string strJson = SerializeJsonFromObject(ret); return true; @@ -717,7 +717,7 @@ bool CDAPI::InviteUser(Object& obj) // } // send the user back the results of the query - Object ret = GetResultObject(1000, "invite_user", file.obj); + Object ret = GetResultObject(GetTime(), "invite_user", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -797,7 +797,7 @@ bool CDAPI::ValidateAccount(Object& obj) */ // send the user back the results of the query - Object ret = GetResultObject(1000, "“validate_account”", file.obj); + Object ret = GetResultObject(GetTime(), "“validate_account”", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -831,7 +831,7 @@ bool CDAPI::SearchUsers(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(1000, "search_users", file.obj); + Object ret = GetResultObject(GetTime(), "search_users", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); From 54c3dad7bc007cc71db19644c02fca29d54ae696 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 06:03:15 -0700 Subject: [PATCH 40/51] better websocket closed detection --- src/evo/dapi.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index bd6ec94d5e28..91a3f8d428f4 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -79,6 +79,8 @@ void EventNotify(const std::string& strEvent) if(!ws_client) { ws_client = WebSocket::from_url("ws://localhost:5000/"); + } else if(ws_client->getReadyState() == WebSocket::CLOSED) { + ws_client = WebSocket::from_url("ws://localhost:5000/"); } assert(ws_client); From 8ecc77a9f8cb616ad45bea156e5fc0d1846f57de Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 06:05:19 -0700 Subject: [PATCH 41/51] message id --- src/evo/dapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 91a3f8d428f4..eddf4a842a52 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -586,7 +586,7 @@ bool CDAPI::SendMessage(Object& obj) if(!FindValueAsString(objData, "payload", strPayload)) return false; //TODO: this is presently sending the message to all users on the server - Object ret = GetMessageObject(1000, strUID1, strUID2, strSubCommand, strPayload); + Object ret = GetMessageObject(GetTime(), strUID1, strUID2, strSubCommand, strPayload); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); From 9e98fefe9256cba6a9d18c4476f58d3a87b5ecee Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 06:37:17 -0700 Subject: [PATCH 42/51] autoclose websockets after use --- src/evo/dapi.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index eddf4a842a52..6236e8de0e80 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -76,18 +76,15 @@ void EventNotify(const std::string& strEvent) //boost::replace_all(strCmd, "%s", strEvent); //boost::thread t(runCommand, strCmd); // thread runs free - if(!ws_client) - { - ws_client = WebSocket::from_url("ws://localhost:5000/"); - } else if(ws_client->getReadyState() == WebSocket::CLOSED) { - ws_client = WebSocket::from_url("ws://localhost:5000/"); - } - + ws_client = WebSocket::from_url("ws://localhost:5000/"); + assert(ws_client); ws_client->send(strEvent); ws_client->poll(); printf("sending out: %s\n", strEvent.c_str()); + + ws_client->close(); } std::string escapeJsonString(const std::string& input) { From ec7048094277aaf505cd33f2148c43c7e5743f90 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 08:34:08 -0700 Subject: [PATCH 43/51] allow underscores in usernames --- src/evo/dapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 6236e8de0e80..356f5ba78c9d 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -52,7 +52,7 @@ std::string GetPrivateDataFile(std::string strUID, int nSlot) bool IsValidUsername(std::string strUsername) { for(std::string::size_type i = 0; i < strUsername.size(); ++i) { - if(!std::isalpha(strUsername[i]) && !std::isdigit(strUsername[i]) ) return false; + if(!std::isalpha(strUsername[i]) && !std::isdigit(strUsername[i] && strUsername[i] != '_') ) return false; } return true; } From 08c36041fb609b1d5ffa7a91ab7b1311937dcd8e Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 12:06:38 -0700 Subject: [PATCH 44/51] validate usernames --- src/evo/dapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 356f5ba78c9d..e20e61a46098 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -52,7 +52,7 @@ std::string GetPrivateDataFile(std::string strUID, int nSlot) bool IsValidUsername(std::string strUsername) { for(std::string::size_type i = 0; i < strUsername.size(); ++i) { - if(!std::isalpha(strUsername[i]) && !std::isdigit(strUsername[i] && strUsername[i] != '_') ) return false; + if(!std::isalpha(strUsername[i]) && !std::isdigit(strUsername[i]) && strUsername[i] != '_') return false; } return true; } From c5c095ed7ef1a2721df55944fb10b78c2c123584 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 12:23:43 -0700 Subject: [PATCH 45/51] remove pubkey requirement --- src/evo/dapi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index e20e61a46098..802d9f9272d8 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -679,7 +679,7 @@ bool CDAPI::InviteUser(Object& obj) string strPubkey = ""; if(!FindValueAsString(objData, "to_name", strName)) return false; if(!FindValueAsString(objData, "to_email", strEmail)) return false; - if(!FindValueAsString(objData, "to_pubkey", strPubkey)) return false; + //if(!FindValueAsString(objData, "to_pubkey", strPubkey)) return false; CBitcoinAddress address(strPubkey); bool isValid = address.IsValid(); @@ -695,7 +695,7 @@ bool CDAPI::InviteUser(Object& obj) newObj.push_back(Pair("username", strUID)); newObj.push_back(Pair("name", strName)); newObj.push_back(Pair("email", strEmail)); - newObj.push_back(Pair("pubkey", strPubkey)); + //newObj.push_back(Pair("pubkey", strPubkey)); newObj.push_back(Pair("challenge_code", boost::lexical_cast(GetRand(999999)))); file.obj = newObj; From 319e1bc2fbba77b4e2e2f9d9b79e5cf5f3d406ab Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 12 Jan 2016 12:37:46 -0700 Subject: [PATCH 46/51] removed pubkey check for invite --- src/evo/dapi.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 802d9f9272d8..0bbaddea9b25 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -681,14 +681,14 @@ bool CDAPI::InviteUser(Object& obj) if(!FindValueAsString(objData, "to_email", strEmail)) return false; //if(!FindValueAsString(objData, "to_pubkey", strPubkey)) return false; - CBitcoinAddress address(strPubkey); - bool isValid = address.IsValid(); + // CBitcoinAddress address(strPubkey); + // bool isValid = address.IsValid(); - if(!isValid) - { - SetError(1005, "Invalid pubkey: " + strPubkey); - return false; - } + // if(!isValid) + // { + // SetError(1005, "Invalid pubkey: " + strPubkey); + // return false; + // } Object newObj; newObj.push_back(Pair("status", 1)); From 0e0c3a261def23749dea31050a9e4640b9b97a84 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 13 Jan 2016 09:22:36 -0700 Subject: [PATCH 47/51] fixed id usage --- src/evo/dapi.cpp | 55 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 0bbaddea9b25..914e14989d85 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -129,10 +129,10 @@ void SetError(int nErrorIn, std::string strMessageIn) {nError = nErrorIn; strErr } */ -Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile) +Object GetResultObject(std::string strID, std::string strCommand, Object& objFile) { Object retData; - retData.push_back(Pair("id", nCommandID)); + retData.push_back(Pair("id", strID)); retData.push_back(Pair("command", strCommand)); retData.push_back(Pair("error_id", nError)); retData.push_back(Pair("error_message", strErrorMessage)); @@ -145,10 +145,10 @@ Object GetResultObject(int nCommandID, std::string strCommand, Object& objFile) return ret; } -Object GetMessageObject(int nCommandID, std::string strFromUserID, std::string strToUserID, std::string strSubCommand, std::string strMessage) +Object GetMessageObject(std::string strID, std::string strFromUserID, std::string strToUserID, std::string strSubCommand, std::string strMessage) { Object retData; - retData.push_back(Pair("id", nCommandID)); + retData.push_back(Pair("id", strID)); retData.push_back(Pair("command", "send_message")); retData.push_back(Pair("error_id", nError)); retData.push_back(Pair("error_message", strErrorMessage)); @@ -294,11 +294,13 @@ bool CDAPI::Execute(Object& obj) } // UNKNOWN COMMANDS + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; // send the user back the results of the query if(nError == 0) SetError(1007, "Unknown Command : " + strCommand); Object result; - Object ret = GetResultObject(GetTime(), strCommand, result); + Object ret = GetResultObject(strID, strCommand, result); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -365,6 +367,8 @@ bool CDAPI::GetProfile(Object& obj) string strUID = ""; if(!FindValueAsObject(obj, "data", objData)) return false; if(!FindValueAsString(objData, "to_uid", strUID)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); @@ -376,7 +380,7 @@ bool CDAPI::GetProfile(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "get_profile", file.obj); + Object ret = GetResultObject(strID, "get_profile", file.obj); std::string strJson2 = SerializeJsonFromObject(file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -412,6 +416,8 @@ bool CDAPI::SetProfile(Object& obj) if(!FindValueAsObject(obj, "data", objData)) return false; if(!FindValueAsArray(objData, "update", arrDataUpdate)) return false; if(!FindValueAsString(objData, "to_uid", strUID)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; // open the file and read it CDriveFile file(GetProfileFile(strUID)); @@ -442,7 +448,7 @@ bool CDAPI::SetProfile(Object& obj) json_spirit::map_to_obj(mapObj, file.obj); file.Write(); - Object ret = GetResultObject(GetTime(), "set_profile", file.obj); + Object ret = GetResultObject(strID, "set_profile", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -477,6 +483,8 @@ bool CDAPI::GetPrivateData(Object& obj) SetError(1002, "Slot out of range"); return false; } + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; // open the file and read it CDriveFile file(GetPrivateDataFile(strUID, nSlot)); @@ -484,7 +492,7 @@ bool CDAPI::GetPrivateData(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "get_private_data", file.obj); + Object ret = GetResultObject(strID, "get_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -519,6 +527,8 @@ bool CDAPI::SetPrivateData(Object& obj) SetError(1002, "Slot out of range"); return false; } + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; // open the file and read it CDriveFile file(GetPrivateDataFile(strUID, nSlot)); @@ -544,7 +554,7 @@ bool CDAPI::SetPrivateData(Object& obj) file.Write(); // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "set_private_data", file.obj); + Object ret = GetResultObject(strID, "set_private_data", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -581,9 +591,11 @@ bool CDAPI::SendMessage(Object& obj) if(!FindValueAsString(objData, "to_uid", strUID2)) return false; if(!FindValueAsString(objData, "sub_command", strSubCommand)) return false; if(!FindValueAsString(objData, "payload", strPayload)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; //TODO: this is presently sending the message to all users on the server - Object ret = GetMessageObject(GetTime(), strUID1, strUID2, strSubCommand, strPayload); + Object ret = GetMessageObject(strID, strUID1, strUID2, strSubCommand, strPayload); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -615,6 +627,9 @@ bool CDAPI::BroadcastMessage(Object& obj) if(!FindValueAsString(objData, "sub_command", strSubCommand)) return false; if(!FindValueAsString(objData, "payload", strPayload)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; + if(strSubCommand == "tx") { CTransaction tx; @@ -630,7 +645,7 @@ bool CDAPI::BroadcastMessage(Object& obj) //should probably figure out if it was broadcasted successfully // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "broadcast_message", retTx); + Object ret = GetResultObject(strID, "broadcast_message", retTx); std::string strJson = SerializeJsonFromObject(ret); return true; @@ -666,6 +681,9 @@ bool CDAPI::InviteUser(Object& obj) if(!FindValueAsObject(obj, "data", objData)) return false; if(!FindValueAsString(objData, "to_uid", strUID)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; + // open the file and read it CDriveFile file(GetProfileFile(strUID)); if(file.Exists()) @@ -716,7 +734,7 @@ bool CDAPI::InviteUser(Object& obj) // } // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "invite_user", file.obj); + Object ret = GetResultObject(strID, "invite_user", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -750,6 +768,9 @@ bool CDAPI::ValidateAccount(Object& obj) if(!FindValueAsString(objData, "to_uid", strUID)) return false; if(!FindValueAsString(objData, "to_challenge_code", strChallengeCode)) return false; + string strID = ""; + if(!FindValueAsString(objData, "id", strID)) return false; + // open the file and read it CDriveFile file(GetProfileFile(strUID)); if(!file.Exists()) @@ -796,7 +817,7 @@ bool CDAPI::ValidateAccount(Object& obj) */ // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "“validate_account”", file.obj); + Object ret = GetResultObject(strID, "“validate_account”", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); @@ -819,6 +840,12 @@ bool CDAPI::SearchUsers(Object& obj) } */ + Object objData; + string strID = ""; + if(!FindValueAsObject(obj, "data", objData)) return false; + if(!FindValueAsString(objData, "id", strID)) return false; + + // open the file and read it CDriveFile file(GetIndexFile("fiat_converters.js")); @@ -830,7 +857,7 @@ bool CDAPI::SearchUsers(Object& obj) file.Read(); // send the user back the results of the query - Object ret = GetResultObject(GetTime(), "search_users", file.obj); + Object ret = GetResultObject(strID, "search_users", file.obj); std::string strJson = SerializeJsonFromObject(ret); EventNotify(strJson); From c5be1f87a4bd9bc9a8efe85c9d4b422f2c80c529 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Fri, 15 Jan 2016 21:37:23 -0700 Subject: [PATCH 48/51] missing ids --- src/test/data/dapi-invite-user.js | 1 + src/test/data/dapi-validate-account.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/data/dapi-invite-user.js b/src/test/data/dapi-invite-user.js index 0bfff9470727..631d2ae819c1 100644 --- a/src/test/data/dapi-invite-user.js +++ b/src/test/data/dapi-invite-user.js @@ -1,6 +1,7 @@ { "object" : "dapi_command", "data" : { + "id" : "1111", "command" : "invite_user", "from_uid" : "evan", "to_uid" : "cryptofish82", diff --git a/src/test/data/dapi-validate-account.js b/src/test/data/dapi-validate-account.js index 8a819bca797d..294ab17cc419 100644 --- a/src/test/data/dapi-validate-account.js +++ b/src/test/data/dapi-validate-account.js @@ -1,6 +1,7 @@ { "object" : "dapi_command", "data" : { + "id" : "1111", "command" : "validate_account", "from_uid" : "evan", "to_uid" : "cryptofish82", From adf5ba36db947014c22c505c9dfb09265788a185 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sun, 17 Jan 2016 09:29:21 -0700 Subject: [PATCH 49/51] added missing required profile fields --- src/evo/dapi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 914e14989d85..7adb86da3c13 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -713,6 +713,9 @@ bool CDAPI::InviteUser(Object& obj) newObj.push_back(Pair("username", strUID)); newObj.push_back(Pair("name", strName)); newObj.push_back(Pair("email", strEmail)); + newObj.push_back(Pair("stars", 5)); + Object addresses; + newObj.push_back(Pair("addresses", addresses)); //newObj.push_back(Pair("pubkey", strPubkey)); newObj.push_back(Pair("challenge_code", boost::lexical_cast(GetRand(999999)))); file.obj = newObj; From bfe0a6be85fc540548a51d40799c91680323f3b8 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Sun, 17 Jan 2016 10:04:55 -0700 Subject: [PATCH 50/51] use array obj for addresses --- src/evo/dapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/dapi.cpp b/src/evo/dapi.cpp index 7adb86da3c13..38f56d38886b 100644 --- a/src/evo/dapi.cpp +++ b/src/evo/dapi.cpp @@ -714,7 +714,7 @@ bool CDAPI::InviteUser(Object& obj) newObj.push_back(Pair("name", strName)); newObj.push_back(Pair("email", strEmail)); newObj.push_back(Pair("stars", 5)); - Object addresses; + Array addresses; newObj.push_back(Pair("addresses", addresses)); //newObj.push_back(Pair("pubkey", strPubkey)); newObj.push_back(Pair("challenge_code", boost::lexical_cast(GetRand(999999)))); From 3d28dba43c8e4a34c6e99131956a3e501a3351e3 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 1 Feb 2016 23:28:27 -0700 Subject: [PATCH 51/51] log dapi commands --- src/rpcdapi.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rpcdapi.cpp b/src/rpcdapi.cpp index 0d589c4e1525..60de290cbc86 100644 --- a/src/rpcdapi.cpp +++ b/src/rpcdapi.cpp @@ -55,7 +55,7 @@ Value dapi(const Array& params, bool fHelp) std::string strCommand = params[0].get_str(); json_spirit::Value val; - printf("%s\n", strCommand.c_str()); + LogPrintf("dapi - new command : %s\n", strCommand.c_str()); bool fSuccess = json_spirit::read_string(strCommand, val); if (fSuccess) { @@ -87,14 +87,13 @@ Value dapif(const Array& params, bool fHelp) */ std::string strPath = params[0].get_str(); - - printf("path %s\n", strPath.c_str()); + LogPrintf("dapi - path: %s\n", strPath.c_str()); std::ifstream t(strPath.c_str()); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); - printf("json %s\n", str.c_str()); + LogPrintf("dapi - json: %s\n", str.c_str()); json_spirit::Value val;