diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 9d562b6f..4547c54c 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -12,7 +12,7 @@ #include "bitcoinrpc.h" #include "db.h" -#include "twister.h" +#include "twister_utils.h" #include #include @@ -252,6 +252,8 @@ static const CRPCCommand vRPCCommands[] = { "unfollow", &unfollow, false, true }, { "getfollowing", &getfollowing, false, true }, { "listusernamespartial", &listusernamespartial, false, true }, + { "getdefaultuser", &getdefaultuser, false, true }, + { "setdefaultuser", &setdefaultuser, false, true }, }; CRPCTable::CRPCTable() @@ -1156,6 +1158,20 @@ void ConvertTo(Value& value, bool fAllowNull=false) } } +void ConvertToValue(Value& value) +{ + if (value.type() == str_type) + { + // reinterpret string as unquoted json value + Value value2; + string strJSON = value.get_str(); + if (!read_string(strJSON, value2)) + throw runtime_error(string("Error parsing JSON:")+strJSON); + value = value2; + } +} + + // Convert strings to command-specific RPC representation Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams) { @@ -1210,6 +1226,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 2) ConvertTo(params[2]); if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); + if (strMethod == "dhtput" && n > 3) ConvertToValue(params[3]); if (strMethod == "dhtput" && n > 5) ConvertTo(params[5]); if (strMethod == "newpostmsg" && n > 1) ConvertTo(params[1]); if (strMethod == "newpostmsg" && n > 4) ConvertTo(params[4]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 4fb81563..d05d1c4d 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -204,5 +204,7 @@ extern json_spirit::Value follow(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value unfollow(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getfollowing(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value listusernamespartial(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getdefaultuser(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value setdefaultuser(const json_spirit::Array& params, bool fHelp); #endif diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 71777902..1116d7f7 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -140,6 +140,53 @@ Value listwalletusers(const Array& params, bool fHelp) return ret; } +Value setdefaultuser(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "setdefaultuser \n" + "Set default user to use (must exist)"); + + EnsureWalletIsUnlocked(); + + string strUsername = params[0].get_str(); + + CKeyID keyID; + if( !pwalletMain->GetKeyIdFromUsername(strUsername, keyID) ) + throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Error: username does not exist in wallet"); + + CPubKey vchPubKey; + if( !pwalletMain->GetPubKey( keyID, vchPubKey) ) + throw JSONRPCError(RPC_WALLET_ERROR, "Error recovering pubkey from wallet"); + + if( !pwalletMain->SetDefaultKey(vchPubKey) ) + throw JSONRPCError(RPC_WALLET_ERROR, "Error setting default key"); + + return Value(); +} + +Value getdefaultuser(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getdefaultuser\n" + "Get default user being used"); + + EnsureWalletIsUnlocked(); + + CPubKey vchPubKey = pwalletMain->vchDefaultKey; + + if( !vchPubKey.IsValid() ) + throw JSONRPCError(RPC_WALLET_ERROR, "Error: default user key is invalid"); + + CKeyID keyID = vchPubKey.GetID(); + std::string username; + if( !pwalletMain->GetUsernameFromKeyId(keyID, username) ) + throw JSONRPCError(RPC_WALLET_ERROR, "Error converting keyID to username"); + + return username; +} + Value signmessage(const Array& params, bool fHelp) { diff --git a/src/twister.cpp b/src/twister.cpp index bf027a6f..7865e3eb 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1,5 +1,7 @@ #include "twister.h" +#include "twister_utils.h" + #include "main.h" #include "init.h" #include "bitcoinrpc.h" @@ -52,68 +54,6 @@ sha1_hash dhtTargetHash(std::string const &username, std::string const &resource return hasher(buf.data(), buf.size()).final(); } -int load_file(std::string const& filename, std::vector& v, int limit) -{ - FILE* f = fopen(filename.c_str(), "rb"); - if (f == NULL) - return -1; - int r = fseek(f, 0, SEEK_END); - if (r != 0) { - fclose(f); - return -1; - } - long s = ftell(f); - if (s < 0) { - fclose(f); - return -1; - } - - if (s > limit) { - fclose(f); - return -2; - } - - r = fseek(f, 0, SEEK_SET); - if (r != 0) { - fclose(f); - return -1; - } - - v.resize(s); - if (s == 0) { - fclose(f); - return 0; - } - - r = fread(&v[0], 1, v.size(), f); - if (r < 0) { - fclose(f); - return -1; - } - - fclose(f); - - if (r != s) return -3; - - return 0; -} - -int save_file(std::string const& filename, std::vector& v) -{ - using namespace libtorrent; - - // TODO: don't use internal file type here. use fopen() - file f; - error_code ec; - if (!f.open(filename, file::write_only, ec)) return -1; - if (ec) return -1; - file::iovec_t b = {&v[0], v.size()}; - size_type written = f.writev(0, &b, 1, ec); - if (written != int(v.size())) return -3; - if (ec) return -3; - return 0; -} - torrent_handle startTorrentUser(std::string const &username) { if( !m_userTorrent.count(username) ) { @@ -775,55 +715,6 @@ int getBestHeight() return nBestHeight; } -Value entryToJson(const entry &e) -{ - Array lst; - Object o; - switch( e.type() ) { - case entry::int_t: - return e.integer(); - case entry::string_t: - return e.string(); - case entry::list_t: - for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) { - lst.push_back( entryToJson(*i) ); - } - return lst; - case entry::dictionary_t: - for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { - o.push_back(Pair(i->first, entryToJson(i->second))); - } - return o; - default: - return string(""); - } -} - -entry jsonToEntry(const Value &v) -{ - entry::list_type lst; - entry::dictionary_type dict; - - switch( v.type() ) { - case int_type: - return v.get_int(); - case str_type: - return v.get_str(); - case array_type: - for (Array::const_iterator i = v.get_array().begin(); i != v.get_array().end(); ++i) { - lst.push_back( jsonToEntry(*i) ); - } - return lst; - case obj_type: - for (Object::const_iterator i = v.get_obj().begin(); i != v.get_obj().end(); ++i) { - dict[ i->name_ ] = jsonToEntry(i->value_); - } - return dict; - default: - return string(""); - } -} - Value dhtput(const Array& params, bool fHelp) { if (fHelp || params.size() < 5 || params.size() > 6) @@ -836,7 +727,7 @@ Value dhtput(const Array& params, bool fHelp) string strUsername = params[0].get_str(); string strResource = params[1].get_str(); string strMulti = params[2].get_str(); - string strValue = params[3].get_str(); + entry value = jsonToEntry(params[3]); string strSigUser = params[4].get_str(); // Test for private key here to avoid going into dht @@ -851,12 +742,13 @@ Value dhtput(const Array& params, bool fHelp) if( !multi && params.size() != 6 ) throw JSONRPCError(RPC_WALLET_ERROR, "Seq parameter required for single"); - int seq = params[5].get_int(); + int seq = -1; + if( params.size() == 6 ) + seq = params[5].get_int(); if( !multi && strUsername != strSigUser ) throw JSONRPCError(RPC_WALLET_ERROR, "Username must be the same as sig_user for single"); - entry value = entry::string_type(strValue); boost::int64_t timeutc = GetAdjustedTime(); ses->dht_putData(strUsername, strResource, multi, value, strSigUser, timeutc, seq); diff --git a/src/twister.h b/src/twister.h index 52bcb9d0..e75cf3f1 100644 --- a/src/twister.h +++ b/src/twister.h @@ -27,7 +27,4 @@ bool validatePostNumberForUser(std::string const &username, int k); int getBestHeight(); -int load_file(std::string const& filename, std::vector& v, int limit = 8000000); - - #endif // TWISTER_H diff --git a/src/twister_utils.cpp b/src/twister_utils.cpp new file mode 100644 index 00000000..9ddc023e --- /dev/null +++ b/src/twister_utils.cpp @@ -0,0 +1,127 @@ +#include "twister_utils.h" + +#include + +#include + +using namespace std; + +twister_utils::twister_utils() +{ +} + +int load_file(std::string const& filename, std::vector& v, int limit) +{ + FILE* f = fopen(filename.c_str(), "rb"); + if (f == NULL) + return -1; + int r = fseek(f, 0, SEEK_END); + if (r != 0) { + fclose(f); + return -1; + } + long s = ftell(f); + if (s < 0) { + fclose(f); + return -1; + } + + if (s > limit) { + fclose(f); + return -2; + } + + r = fseek(f, 0, SEEK_SET); + if (r != 0) { + fclose(f); + return -1; + } + + v.resize(s); + if (s == 0) { + fclose(f); + return 0; + } + + r = fread(&v[0], 1, v.size(), f); + if (r < 0) { + fclose(f); + return -1; + } + + fclose(f); + + if (r != s) return -3; + + return 0; +} + +int save_file(std::string const& filename, std::vector& v) +{ + using namespace libtorrent; + + // TODO: don't use internal file type here. use fopen() + file f; + error_code ec; + if (!f.open(filename, file::write_only, ec)) return -1; + if (ec) return -1; + file::iovec_t b = {&v[0], v.size()}; + size_type written = f.writev(0, &b, 1, ec); + if (written != int(v.size())) return -3; + if (ec) return -3; + return 0; +} + +using namespace json_spirit; +using namespace libtorrent; + +Value entryToJson(const entry &e) +{ + Array lst; + Object o; + switch( e.type() ) { + case entry::int_t: + return e.integer(); + case entry::string_t: + return e.string(); + case entry::list_t: + for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) { + lst.push_back( entryToJson(*i) ); + } + return lst; + case entry::dictionary_t: + for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { + o.push_back(Pair(i->first, entryToJson(i->second))); + } + return o; + default: + return string(""); + } +} + +entry jsonToEntry(const Value &v) +{ + entry::list_type lst; + entry::dictionary_type dict; + + switch( v.type() ) { + case int_type: + return v.get_int(); + case str_type: + return v.get_str(); + case array_type: + for (Array::const_iterator i = v.get_array().begin(); i != v.get_array().end(); ++i) { + lst.push_back( jsonToEntry(*i) ); + } + return lst; + case obj_type: + for (Object::const_iterator i = v.get_obj().begin(); i != v.get_obj().end(); ++i) { + dict[ i->name_ ] = jsonToEntry(i->value_); + } + return dict; + default: + return string(""); + } +} + + diff --git a/src/twister_utils.h b/src/twister_utils.h new file mode 100644 index 00000000..12f04fb8 --- /dev/null +++ b/src/twister_utils.h @@ -0,0 +1,22 @@ +#ifndef TWISTER_UTILS_H +#define TWISTER_UTILS_H + +#include "json_spirit.h" +#include "libtorrent/entry.hpp" + +#include +#include + +class twister_utils +{ +public: + twister_utils(); +}; + +int load_file(std::string const& filename, std::vector& v, int limit = 8000000); +int save_file(std::string const& filename, std::vector& v); + +json_spirit::Value entryToJson(const libtorrent::entry &e); +libtorrent::entry jsonToEntry(const json_spirit::Value &v); + +#endif // TWISTER_UTILS_H diff --git a/src/wallet.cpp b/src/wallet.cpp index 864af444..a3b33726 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -110,6 +110,17 @@ bool CWallet::GetKeyIdFromUsername(std::string username, CKeyID &keyid) return false; } +bool CWallet::GetUsernameFromKeyId(CKeyID keyid, std::string &username) +{ + for (std::map::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) { + if (it->first == keyid) { + username = it->second.username; + return true; + } + } + return false; +} + bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); diff --git a/src/wallet.h b/src/wallet.h index a48dcd4d..1d2388cb 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -133,6 +133,7 @@ public: bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata); // Search metadata for a given username bool GetKeyIdFromUsername(std::string username, CKeyID &keyid); + bool GetUsernameFromKeyId(CKeyID keyid, std::string &username); bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } diff --git a/twister-qt.pro b/twister-qt.pro index a712339a..38f57c1d 100644 --- a/twister-qt.pro +++ b/twister-qt.pro @@ -197,7 +197,8 @@ HEADERS += \ src/leveldb.h \ src/threadsafety.h \ src/limitedmap.h \ - src/twister.h + src/twister.h \ + src/twister_utils.h # src/qt/bitcoingui.h # src/qt/transactiontablemodel.h \ @@ -270,7 +271,8 @@ SOURCES += \ #src/qt/bitcoin.cpp \ src/noui.cpp \ src/leveldb.cpp \ src/txdb.cpp \ - src/twister.cpp + src/twister.cpp \ + src/twister_utils.cpp # src/qt/guiutil.cpp \ # src/qt/bitcoingui.cpp \