diff --git a/Makefile.am b/Makefile.am index 161c7f0e..4802e0b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -166,19 +166,18 @@ endif twisterd_SOURCES = $(LIBTORRENT_SOURCES) $(BITCOIN_TWISTER_SOURCES) -twisterd_LDFLAGS = +twisterd_LDFLAGS = @OPENSSL_LDFLAGS@ @DB_CXX_LDFLAGS@ twisterd_DEPENDENCIES = $(LEVELDB_LIB) twisterd_LDADD = $(LEVELDB_LIB) $(UPNP_LIB) \ - @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_THREAD_LIB@ @BOOST_LOCALE_LIB@ \ + @BOOST_SYSTEM_LIB@ @BOOST_FILESYSTEM_LIB@ @BOOST_PROGRAM_OPTIONS_LIB@ @BOOST_THREAD_LIB@ @BOOST_CHRONO_LIB@ @BOOST_LOCALE_LIB@ \ @DB_CXX_LIBS@ @OPENSSL_LIBS@ AM_CPPFLAGS = -ftemplate-depth-100 -DBOOST_SPIRIT_THREADSAFE -D_FILE_OFFSET_BITS=64 \ -I$(top_srcdir)/libtorrent/include \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/leveldb/include -I$(top_srcdir)/src/leveldb/helpers \ - @DEBUGFLAGS@ @OPENSSL_INCLUDES@ + @DEBUGFLAGS@ @OPENSSL_INCLUDES@ @DB_CXX_CPPFLAGS@ AM_LDFLAGS = @OPENSSL_LDFLAGS@ - diff --git a/README.md b/README.md index 66341d18..eabba547 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ not interoperate with existing networks (on purpose). Compiling ---------------- -You can build you own twister with this docs: +You can build twister using these docs: [Ubuntu/Debian](https://github.com/miguelfreitas/twister-core/blob/master/doc/building-on-ubuntu-debian.md) @@ -175,3 +175,12 @@ them: Visit [http://localhost:28332/index.html](http://localhost:28332/index.html) in your web browser and you should see a page asking you to choose between the Desktop and Mobile interfaces. + +Different themes +------------------------- + +If you prefer new modern look of twister with new untested things, you can try twister-calm theme +But be careful, it is in beta stage. + + cd ~/.twister/ + git clone https://github.com/iHedgehog/twister-calm.git ./html diff --git a/TODO b/TODO.md similarity index 96% rename from TODO rename to TODO.md index 637dada8..775e4cf1 100644 --- a/TODO +++ b/TODO.md @@ -1,28 +1,38 @@ +Security +================ + - Encrypt user_data (which contains all DMs) - Test wallet encrypt to see if it still works from original bitcoin implementation and what are the implications to our code. -- Rescan directmessages after importing a privatekey (importprivkey) +- Move all crypto to javascript, store only encrypted version of the privatekey (which would be +decrypted only in browser memory). getposts may obtain all DMs encrypted to browser, another +newpostmsg needs to be provided to receive posts with signature field added. -- Check libtorrent's limitation on the number of pieces (max_pieces in piece_picker.hpp = 1<<19) -Since post number is constrained by max of 288 posts per day in average, that means we have 5 years -to think about it (for the really heavy users). +Features +================ - Besides increasing the maximum number of pieces, a more pressing issue to save bandwidth and torrent download time would be to define the first piece to download/store locally. People don't need to maintain the entire post history for everybody they follow, they could just keep the last ones. This has to be implemented. -- Move all crypto to javascript, store only encrypted version of the privatekey (which would be -decrypted only in browser memory). getposts may obtain all DMs encrypted to browser, another -newpostmsg needs to be provided to receive posts with signature field added. - - Store a dht resource "publickey" containing not only the public key itself but also information needed to validate it by a lightweight client. That includes: block hash, block height and partial merkle tree inside that block. This resource propagation cannot be sent right after user registration for obvious reasons (no block yet, other nodes wouldn't accept the signed dht put). +- Share images + +Kill bugs +================ +- Rescan directmessages after importing a privatekey (importprivkey) + +- Check libtorrent's limitation on the number of pieces (max_pieces in piece_picker.hpp = 1<<19) +Since post number is constrained by max of 288 posts per day in average, that means we have 5 years +to think about it (for the really heavy users). + - Implement the mention forwarding mechanism discussed in the paper so user don't need to do polling and can also be sure to receive all mentions. @@ -39,8 +49,6 @@ of his own torrent) - Estimate number of online followers by quering the "tracker" resource (implement a value within this resource to report the number of torrent peers) -- Define and enforce html directory to serve from. Do installation scripts. - - Don't accept dht "post"+k if k violates the validatePostNumberForUser() rule. - Implement -secdatadir= parameter to store sensitive data (wallet, dm) in a separated dir. diff --git a/configure.ac b/configure.ac index 5f651b1e..ecff0dfd 100644 --- a/configure.ac +++ b/configure.ac @@ -83,27 +83,23 @@ AC_CACHE_CHECK([for __attribute__((visibility("hidden")))], AS_ECHO AS_ECHO "Checking for boost libraries:" -AX_BOOST_BASE([1.44]) +AX_BOOST_BASE([1.44], [], + [AC_MSG_ERROR(Boost library not found. Try using --with-boost=)]) AX_BOOST_SYSTEM() -AS_IF([test -z "$BOOST_SYSTEM_LIB"], - [AC_MSG_ERROR(Boost.System library not found. Try using --with-boost-libdir=)]) AX_BOOST_FILESYSTEM() AX_BOOST_PROGRAM_OPTIONS() AX_BOOST_THREAD() AX_BOOST_CHRONO() AX_BOOST_LOCALE() -CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS" -LDFLAGS="$BOOST_LDFLAGS $LDFLAGS $BOOST_CHRONO_LIB" - - ############################################################################### # Checking for Berkeley DB C++ ############################################################################### AC_LANG([C++]) -AX_BERKELEY_DB_CXX(4.8) +AX_BERKELEY_DB_CXX(4.8, [], + [AC_MSG_ERROR(Berkeley DB C++ library not found. Try using --with-libdb=)]) ############################################################################### # Checking for functions and other stuffs @@ -773,6 +769,15 @@ Boost libraries: CPPFlags: ${BOOST_CPPFLAGS} LDFlags: ${BOOST_LDFLAGS} boost.system: ${BOOST_SYSTEM_LIB} + boost.filesystem: ${BOOST_FILESYSTEM_LIB} + boost.program_opts: ${BOOST_PROGRAM_OPTIONS_LIB} + boost.thread: ${BOOST_THREAD_LIB} + +Berkeley DB C++ library: + header: ${DB_CXX_HEADER} + libraries: ${DB_CXX_LIBS} + LDFlags: ${DB_CXX_LDFLAGS} + CPPFlags: ${DB_CXX_CPPFLAGS} END AS_IF([test "x$ARG_ENABLE_PYTHON_BINDING" = "xyes"], [ @@ -831,7 +836,7 @@ OpenSSL library: OpenSSL Libs: ${OPENSSL_LIBS} OpenSSL LDFlags: ${OPENSSL_LDFLAGS} OpenSSL Includes: ${OPENSSL_INCLUDES} -END +END ]) cat config.report diff --git a/doc/build-osx.md b/doc/build-osx.md index 8add73bb..e59b5d75 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -43,18 +43,6 @@ Instructions: HomeBrew brew install boost miniupnpc openssl berkeley-db4 autoconf automake libtool -Note: After you have installed the dependencies, you should check that the Brew-installed -version of OpenSSL is the one available for compilation. You can check this by typing - - openssl version - -into Terminal. You should see OpenSSL 1.0.1e 11 Feb 2013. - -If that's not the case, you *could* `brew link --force openssl` but it's a bad idea. -Instead, it's enough to make sure the right openssl binary is on your $PATH: - - export PATH=/usr/local/opt/openssl/bin:$PATH - ### Building `twisterd` 1. Clone the github tree to get the source code and go into the directory. @@ -63,29 +51,14 @@ Instead, it's enough to make sure the right openssl binary is on your $PATH: git clone https://github.com/miguelfreitas/twister-core.git cd twister-core -2. Set system variables to match your environment. THIS IS IMPORTANT! - - - export OPENSSL_INCLUDE_PATH=/usr/local/opt/openssl/include - export OPENSSL_LIB_PATH=/usr/local/opt/openssl/lib - export BDB_INCLUDE_PATH=/usr/local/opt/berkeley-db4/include - export BDB_LIB_PATH=/usr/local/opt/berkeley-db4/lib - export BOOST_INCLUDE_PATH=/usr/local/opt/boost/include - export BOOST_LIB_PATH=/usr/local/opt/boost/lib - export BOOST_LIB_SUFFIX=-mt - export LDFLAGS="-L$OPENSSL_LIB_PATH -L$BDB_LIB_PATH -L$BOOST_LIB_PATH" - export CPPFLAGS="-I$OPENSSL_INCLUDE_PATH -I$BDB_INCLUDE_PATH -I$BOOST_INCLUDE_PATH" - export PATH=${BDB_INCLUDE_PATH}:${PATH} - -3. Build twister using autotool - +2. Build twister using autotool ./autotool.sh - ./configure --enable-logging + ./configure --enable-logging --with-openssl=/usr/local/opt/openssl --with-libdb=/usr/local/opt/berkeley-db4 make (If you have multi core CPU, use "make -j N" where N = number of your cores) -4. If things go south, before trying again, make sure you clean it up: +3. If things go south, before trying again, make sure you clean it up: make clean diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp index 6ca43c7d..5906b1ca 100644 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ b/libtorrent/include/libtorrent/kademlia/node.hpp @@ -118,12 +118,16 @@ struct torrent_entry struct dht_storage_item { // FIXME: optimize so bdecode is not needed all the time - dht_storage_item() : p(), sig_p(), sig_user() {} - dht_storage_item(std::string &_p, lazy_entry const *_sig_p, lazy_entry const *_sig_user) - : p(_p), sig_p(_sig_p->string_value()), sig_user(_sig_user->string_value()) {} + dht_storage_item() : p(), sig_p(), sig_user(), local_add_time(0) {} + dht_storage_item(std::string const &_p, lazy_entry const *_sig_p, lazy_entry const *_sig_user) + : p(_p), sig_p(_sig_p->string_value()), sig_user(_sig_user->string_value()), + local_add_time(0) {} + dht_storage_item(std::string const &_p, std::string const &_sig_p, std::string const &_sig_user) + : p(_p), sig_p(_sig_p), sig_user(_sig_user), local_add_time(0) {} std::string p; std::string sig_p; std::string sig_user; + boost::int64_t local_add_time; // the last time we heard about this //ptime last_seen; }; @@ -282,6 +286,8 @@ private: std::set m_running_requests; void incoming_request(msg const& h, entry& e); + void store_dht_item(dht_storage_item &item, big_number const &target, + bool multi, int seq, int height, std::pair &bufv); node_id m_id; diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 9511fb65..1f92bb8c 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -444,11 +444,13 @@ void node_impl::putData(std::string const &username, std::string const &resource if (seq >= 0 && !multi) p["seq"] = seq; p["v"] = value; p["time"] = timeutc; - p["height"] = getBestHeight()-1; // be conservative + int height = getBestHeight()-1; // be conservative + p["height"] = height; std::vector pbuf; bencode(std::back_inserter(pbuf), p); - std::string sig_p = createSignature(std::string(pbuf.data(),pbuf.size()), sig_user); + std::string str_p = std::string(pbuf.data(),pbuf.size()); + std::string sig_p = createSignature(str_p, sig_user); if( !sig_p.size() ) { printf("putData: createSignature error (this should have been caught earlier)\n"); return; @@ -459,7 +461,17 @@ void node_impl::putData(std::string const &username, std::string const &resource boost::intrusive_ptr ta(new dht_get(*this, username, resource, multi, boost::bind(&nop), boost::bind(&putData_fun, _1, boost::ref(*this), p, sig_p, sig_user), true)); - ta->start(); + + // store it locally so it will be automatically refreshed with the rest + dht_storage_item item(str_p, sig_p, sig_user); + item.local_add_time = time(NULL); + std::vector vbuf; + bencode(std::back_inserter(vbuf), value); + std::pair bufv = std::make_pair(vbuf.data(), vbuf.size()); + store_dht_item(item, ta->target(), multi, seq, height, bufv); + + // now send it to the network (start transversal algorithm) + ta->start(); } void node_impl::getData(std::string const &username, std::string const &resource, bool multi, @@ -555,7 +567,8 @@ bool node_impl::refresh_storage() { bool multi = (target->dict_find_string_value("t") == "m"); // refresh only signed single posts and mentions - if( !multi || (multi && resource == "mention") ) { + if( !multi || (multi && resource == "mention") || + (multi && item.local_add_time && item.local_add_time + 60*60*24*2 > time(NULL)) ) { num_refreshable++; if( refresh_next_item ) { @@ -678,6 +691,8 @@ bool node_impl::save_storage(entry &save) const { entry_item["p"] = item.p; entry_item["sig_p"] = item.sig_p; entry_item["sig_user"] = item.sig_user; + if( item.local_add_time ) + entry_item["local_add_time"] = item.local_add_time; save_list.list().push_back(entry_item); } } @@ -709,6 +724,9 @@ void node_impl::load_storage(entry const* e) { item.p = j->find_key("p")->string(); item.sig_p = j->find_key("sig_p")->string(); item.sig_user = j->find_key("sig_user")->string(); + entry const *local_add_time( j->find_key("local_add_time") ); + if(local_add_time) + item.local_add_time = local_add_time->integer(); // just for printf for now bool expired = has_expired(item); @@ -1327,71 +1345,13 @@ void node_impl::incoming_request(msg const& m, entry& e) // attack this resource by storing value into non-final nodes. if( !possiblyNeighbor ) { printf("putData with possiblyNeighbor=false, ignoring request.\n"); + return; } dht_storage_item item(str_p, msg_keys[mk_sig_p], msg_keys[mk_sig_user]); - dht_storage_table_t::iterator i = m_storage_table.find(target); - if (i == m_storage_table.end()) { - // make sure we don't add too many items - if (int(m_storage_table.size()) >= m_settings.max_dht_items) - { - // FIXME: erase one? preferably a multi - } - - dht_storage_list_t to_add; - to_add.push_back(item); - - boost::tie(i, boost::tuples::ignore) = m_storage_table.insert( - std::make_pair(target, to_add)); - } else { - dht_storage_list_t & lsto = i->second; - - dht_storage_list_t::reverse_iterator j, rend(lsto.rend()); - dht_storage_list_t::iterator insert_pos = lsto.end(); - for( j = lsto.rbegin(); j != rend; ++j) { - dht_storage_item &olditem = *j; - - lazy_entry p; - int pos; - error_code err; - // FIXME: optimize to avoid bdecode (store seq separated, etc) - int ret = lazy_bdecode(olditem.p.data(), olditem.p.data() + olditem.p.size(), p, err, &pos, 10, 500); - - if( !multi ) { - if( msg_keys[mk_seq]->int_value() > p.dict_find_int("seq")->int_value() ) { - olditem = item; - } else { - // don't report this error (because of refresh storage) - //incoming_error(e, "old sequence number"); - return; - } - } else { - std::pair bufv = msg_keys[mk_v]->data_section(); - - // compare contents before adding to the list - std::pair bufoldv = p.dict_find("v")->data_section(); - if( bufv.second == bufoldv.second && !memcmp(bufv.first, bufoldv.first,bufv.second) ) { - // break so it wont be inserted - break; - } - - // if new entry is newer than existing one, it will be inserted before - if( msg_keys[mk_height]->int_value() >= p.dict_find_int_value("height") ) { - insert_pos = j.base(); - insert_pos--; - } - } - } - if(multi && j == rend) { - // new entry - lsto.insert(insert_pos, item); - } - - if(lsto.size() > m_settings.max_entries_per_multi) { - lsto.resize(m_settings.max_entries_per_multi); - } - - } + std::pair bufv = msg_keys[mk_v]->data_section(); + store_dht_item(item, target, multi, !multi ? msg_keys[mk_seq]->int_value() : 0, + msg_keys[mk_height]->int_value(), bufv); } else if (strcmp(query, "getData") == 0) { @@ -1517,6 +1477,69 @@ void node_impl::incoming_request(msg const& m, entry& e) } } +void node_impl::store_dht_item(dht_storage_item &item, const big_number &target, + bool multi, int seq, int height, std::pair &bufv) +{ + dht_storage_table_t::iterator i = m_storage_table.find(target); + if (i == m_storage_table.end()) { + // make sure we don't add too many items + if (int(m_storage_table.size()) >= m_settings.max_dht_items) + { + // FIXME: erase one? preferably a multi + } + + dht_storage_list_t to_add; + to_add.push_back(item); + + boost::tie(i, boost::tuples::ignore) = m_storage_table.insert( + std::make_pair(target, to_add)); + } else { + dht_storage_list_t & lsto = i->second; + + dht_storage_list_t::reverse_iterator j, rend(lsto.rend()); + dht_storage_list_t::iterator insert_pos = lsto.end(); + for( j = lsto.rbegin(); j != rend; ++j) { + dht_storage_item &olditem = *j; + + lazy_entry p; + int pos; + error_code err; + // FIXME: optimize to avoid bdecode (store seq separated, etc) + int ret = lazy_bdecode(olditem.p.data(), olditem.p.data() + olditem.p.size(), p, err, &pos, 10, 500); + + if( !multi ) { + if( seq > p.dict_find_int("seq")->int_value() ) { + olditem = item; + } else { + // don't report this error (because of refresh storage) + //incoming_error(e, "old sequence number"); + return; + } + } else { + // compare contents before adding to the list + std::pair bufoldv = p.dict_find("v")->data_section(); + if( bufv.second == bufoldv.second && !memcmp(bufv.first, bufoldv.first,bufv.second) ) { + // break so it wont be inserted + break; + } + + // if new entry is newer than existing one, it will be inserted before + if( height >= p.dict_find_int_value("height") ) { + insert_pos = j.base(); + insert_pos--; + } + } + } + if(multi && j == rend) { + // new entry + lsto.insert(insert_pos, item); + } + + if(lsto.size() > m_settings.max_entries_per_multi) { + lsto.resize(m_settings.max_entries_per_multi); + } + } +} } } // namespace libtorrent::dht diff --git a/m4/ax_berkeley_db_cxx.m4 b/m4/ax_berkeley_db_cxx.m4 index f35e5e89..42b47223 100644 --- a/m4/ax_berkeley_db_cxx.m4 +++ b/m4/ax_berkeley_db_cxx.m4 @@ -21,28 +21,52 @@ # in your C/C++ code. DB_CXX_LIBS is set to linker flags needed to link # against the library (e.g. -ldb3.1_cxx) and AC_SUBST is called on it. # +# when specified user-selected spot (via --with-libdb) also sets +# +# DB_CXX_CPPFLAGS to the include directives required +# DB_CXX_LDFLAGS to the -L flags required +# # LICENSE # # Copyright (c) 2008 Vaclav Slavik # Copyright (c) 2011 Stephan Suerken +# Copyright (c) 2014 Kirill A. Korinskiy # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 3 +#serial 4 AC_DEFUN([AX_BERKELEY_DB_CXX], [ AC_LANG_ASSERT(C++) old_LIBS="$LIBS" + old_LDFLAGS="$LDFLAGS" + old_CPPFLAGS="$CPPFLAGS" + + libdbdir="" + AC_ARG_WITH(libdb, + AS_HELP_STRING([--with-libdb=DIR], + [root of the Berkeley DB directory]), + [ + case "$withval" in + "" | y | ye | yes | n | no) + AC_MSG_ERROR([Invalid --with-libdb value]) + ;; + *) libdbdir="$withval" + ;; + esac + ], []) minversion=ifelse([$1], ,,$1) DB_CXX_HEADER="" DB_CXX_LIBS="" + DB_CXX_LDFLAGS="" + DB_CXX_CPPFLAGS="" if test -z $minversion ; then minvermajor=0 @@ -59,13 +83,20 @@ AC_DEFUN([AX_BERKELEY_DB_CXX], AC_MSG_CHECKING([for Berkeley DB (C++) >= $minversion]) fi + if test x$libdbdir != x""; then + DB_CXX_CPPFLAGS="-I${libdbdir}/include" + DB_CXX_LDFLAGS="-L${libdbdir}/lib" + LDFLAGS="$DB_CXX_LDFLAGS $old_LDFLAGS" + CPPFLAGS="$DB_CXX_CPPFLAGS $old_CPPFLAGS" + fi + for version in "" 5.0 4.9 4.8 4.7 4.6 4.5 4.4 4.3 4.2 4.1 4.0 3.6 3.5 3.4 3.3 3.2 3.1 ; do if test -z $version ; then db_cxx_lib="-ldb_cxx -ldb" try_headers="db_cxx.h" else - db_cxx_lib="-ldb_cxx-$version -ldb-$version" + db_cxx_lib="$libdbdir -ldb_cxx-$version -ldb-$version" try_headers="db$version/db_cxx.h db`echo $version | sed -e 's,\..*,,g'`/db_cxx.h" fi @@ -102,13 +133,19 @@ AC_DEFUN([AX_BERKELEY_DB_CXX], done LIBS="$old_LIBS" + LDFLAGS="$old_LDFLAGS" + CPPFLAGS="$old_CPPFLAGS" if test -z $DB_CXX_HEADER ; then AC_MSG_RESULT([not found]) + DB_CXX_LDFLAGS="" + DB_CXX_CPPFLAGS="" ifelse([$3], , :, [$3]) else AC_DEFINE_UNQUOTED(DB_CXX_HEADER, ["$DB_CXX_HEADER"], ["Berkeley DB C++ Header File"]) AC_SUBST(DB_CXX_LIBS) + AC_SUBST(DB_CXX_LDFLAGS) + AC_SUBST(DB_CXX_CPPFLAGS) ifelse([$2], , :, [$2]) fi ]) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index e709321c..66c103b0 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -195,74 +195,74 @@ Value stop(const Array& params, bool fHelp) static const CRPCCommand vRPCCommands[] = -{ // name actor (function) okSafeMode threadSafe - // ------------------------ ----------------------- ---------- ---------- - { "help", &help, true, true }, - { "stop", &stop, true, true }, - { "getblockcount", &getblockcount, true, false }, - { "getbestblockhash", &getbestblockhash, true, false }, - { "getconnectioncount", &getconnectioncount, true, false }, - { "getpeerinfo", &getpeerinfo, true, false }, - { "addnode", &addnode, true, true }, - { "adddnsseed", &adddnsseed, true, true }, - { "getaddednodeinfo", &getaddednodeinfo, true, true }, - { "getdifficulty", &getdifficulty, true, false }, - { "getgenerate", &getgenerate, true, false }, - { "setgenerate", &setgenerate, true, false }, - { "gethashespersec", &gethashespersec, true, false }, - { "getinfo", &getinfo, true, true }, - { "getmininginfo", &getmininginfo, true, false }, - { "createwalletuser", &createwalletuser, true, false }, - { "listwalletusers", &listwalletusers, true, false }, - { "backupwallet", &backupwallet, true, false }, - { "walletpassphrase", &walletpassphrase, true, false }, - { "walletpassphrasechange", &walletpassphrasechange, false, false }, - { "walletlock", &walletlock, true, false }, - { "encryptwallet", &encryptwallet, false, false }, - { "getrawmempool", &getrawmempool, true, false }, - { "getblock", &getblock, false, false }, - { "getblockhash", &getblockhash, false, false }, - { "gettransaction", &gettransaction, false, false }, - { "listtransactions", &listtransactions, false, false }, - { "signmessage", &signmessage, false, false }, - { "verifymessage", &verifymessage, false, false }, - { "getwork", &getwork, true, false }, - { "getblocktemplate", &getblocktemplate, true, false }, - { "submitblock", &submitblock, false, false }, - { "listsinceblock", &listsinceblock, false, false }, - { "dumpprivkey", &dumpprivkey, true, false }, - { "dumppubkey", &dumppubkey, false, false }, - { "dumpwallet", &dumpwallet, true, false }, - { "importprivkey", &importprivkey, false, false }, - { "importwallet", &importwallet, false, false }, - { "getrawtransaction", &getrawtransaction, false, false }, - { "createrawtransaction", &createrawtransaction, false, false }, - { "decoderawtransaction", &decoderawtransaction, false, false }, - { "sendrawtransaction", &sendrawtransaction, false, false }, - { "sendnewusertransaction", &sendnewusertransaction, false, false }, - { "verifychain", &verifychain, true, false }, - { "getlastsoftcheckpoint", &getlastsoftcheckpoint, true, false }, +{ // name actor (function) okSafeMode threadSafe allowOnPublicServer + // ------------------------ ----------------------- ---------- ---------- ------------------- + { "help", &help, true, true, true }, + { "stop", &stop, true, true, false }, + { "getblockcount", &getblockcount, true, false, false }, + { "getbestblockhash", &getbestblockhash, true, false, true }, + { "getconnectioncount", &getconnectioncount, true, false, false }, + { "getpeerinfo", &getpeerinfo, true, false, false }, + { "addnode", &addnode, true, true, false }, + { "adddnsseed", &adddnsseed, true, true, false }, + { "getaddednodeinfo", &getaddednodeinfo, true, true, false }, + { "getdifficulty", &getdifficulty, true, false, false }, + { "getgenerate", &getgenerate, true, false, false }, + { "setgenerate", &setgenerate, true, false, false }, + { "gethashespersec", &gethashespersec, true, false, false }, + { "getinfo", &getinfo, true, true, true }, + { "getmininginfo", &getmininginfo, true, false, false }, + { "createwalletuser", &createwalletuser, true, false, false }, + { "listwalletusers", &listwalletusers, true, false, true }, + { "backupwallet", &backupwallet, true, false, false }, + { "walletpassphrase", &walletpassphrase, true, false, false }, + { "walletpassphrasechange", &walletpassphrasechange, false, false, false }, + { "walletlock", &walletlock, true, false, false }, + { "encryptwallet", &encryptwallet, false, false, false }, + { "getrawmempool", &getrawmempool, true, false, false }, + { "getblock", &getblock, false, false, true }, + { "getblockhash", &getblockhash, false, false, false }, + { "gettransaction", &gettransaction, false, false, false }, + { "listtransactions", &listtransactions, false, false, false }, + { "signmessage", &signmessage, false, false, false }, + { "verifymessage", &verifymessage, false, false, false }, + { "getwork", &getwork, true, false, false }, + { "getblocktemplate", &getblocktemplate, true, false, false }, + { "submitblock", &submitblock, false, false, false }, + { "listsinceblock", &listsinceblock, false, false, false }, + { "dumpprivkey", &dumpprivkey, true, false, false }, + { "dumppubkey", &dumppubkey, false, false, false }, + { "dumpwallet", &dumpwallet, true, false, false }, + { "importprivkey", &importprivkey, false, false, false }, + { "importwallet", &importwallet, false, false, false }, + { "getrawtransaction", &getrawtransaction, false, false, false }, + { "createrawtransaction", &createrawtransaction, false, false, false }, + { "decoderawtransaction", &decoderawtransaction, false, false, false }, + { "sendrawtransaction", &sendrawtransaction, false, false, false }, + { "sendnewusertransaction", &sendnewusertransaction, false, false, false }, + { "verifychain", &verifychain, true, false, false }, + { "getlastsoftcheckpoint", &getlastsoftcheckpoint, true, false, false }, // twister dht network - { "dhtput", &dhtput, false, true }, - { "dhtget", &dhtget, false, true }, - { "newpostmsg", &newpostmsg, false, true }, - { "newdirectmsg", &newdirectmsg, false, true }, - { "newrtmsg", &newrtmsg, false, true }, - { "getposts", &getposts, false, true }, - { "getdirectmsgs", &getdirectmsgs, false, true }, - { "setspammsg", &setspammsg, false, false }, - { "getspammsg", &getspammsg, false, false }, - { "follow", &follow, false, true }, - { "unfollow", &unfollow, false, true }, - { "getfollowing", &getfollowing, false, true }, - { "getlasthave", &getlasthave, false, true }, - { "getnumpieces", &getnumpieces, false, true }, - { "listusernamespartial", &listusernamespartial, false, true }, - { "rescandirectmsgs", &rescandirectmsgs, false, true }, - { "recheckusertorrent", &recheckusertorrent, false, true }, - { "gettrendinghashtags", &gettrendinghashtags, false, true }, - { "getspamposts", &getspamposts, false, true }, - { "torrentstatus", &torrentstatus, false, true }, + { "dhtput", &dhtput, false, true, false }, + { "dhtget", &dhtget, false, true, true }, + { "newpostmsg", &newpostmsg, false, true, false }, + { "newdirectmsg", &newdirectmsg, false, true, false }, + { "newrtmsg", &newrtmsg, false, true, false }, + { "getposts", &getposts, false, true, false }, + { "getdirectmsgs", &getdirectmsgs, false, true, false }, + { "setspammsg", &setspammsg, false, false, false }, + { "getspammsg", &getspammsg, false, false, false }, + { "follow", &follow, false, true, false }, + { "unfollow", &unfollow, false, true, false }, + { "getfollowing", &getfollowing, false, true, false }, + { "getlasthave", &getlasthave, false, true, false }, + { "getnumpieces", &getnumpieces, false, true, false }, + { "listusernamespartial", &listusernamespartial, false, true, true }, + { "rescandirectmsgs", &rescandirectmsgs, false, true, false }, + { "recheckusertorrent", &recheckusertorrent, false, true, false }, + { "gettrendinghashtags", &gettrendinghashtags, false, true, true }, + { "getspamposts", &getspamposts, false, true, false }, + { "torrentstatus", &torrentstatus, false, true, false }, }; CRPCTable::CRPCTable() @@ -989,6 +989,9 @@ void ServiceConnection(AcceptedConnection *conn) // Read HTTP message headers and body ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto); + if(strMethod == "GET" && strURI == "/") + strURI="/home.html"; + if (strURI != "/" && strURI.find("..") == std::string::npos ) { filesystem::path pathFile = filesystem::path(GetHTMLDir()) / strURI; std::string fname = pathFile.string(); @@ -1093,6 +1096,9 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s const CRPCCommand *pcmd = tableRPC[strMethod]; if (!pcmd) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); + + if(!pcmd->allowOnPublicServer && GetBoolArg("-public_server_mode",false)) + throw JSONRPCError(RPC_FORBIDDEN_ON_PUBLIC_SERVER, "Forbidden: accessing this method is not allowed on a public server"); // Observe safe mode string strWarning = GetWarnings("rpc"); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 7d25e219..b0822e06 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -48,6 +48,7 @@ enum RPCErrorCode RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, // Database error RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format + RPC_FORBIDDEN_ON_PUBLIC_SERVER = -23, // public server mode is activated, this method is not allowed // P2P client errors RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected @@ -103,6 +104,7 @@ public: rpcfn_type actor; bool okSafeMode; bool threadSafe; + bool allowOnPublicServer; }; /** diff --git a/src/clientversion.h b/src/clientversion.h index 33f62e91..d2292c0d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,7 +8,7 @@ // These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 19 +#define CLIENT_VERSION_REVISION 20 #define CLIENT_VERSION_BUILD 0 // Set to true for release, false for prerelease or test build diff --git a/src/db.h b/src/db.h index b3f269f3..d550c80d 100644 --- a/src/db.h +++ b/src/db.h @@ -13,7 +13,11 @@ #include #include -#include +#ifdef DB_CXX_HEADER + #include DB_CXX_HEADER +#else + #include +#endif class CAddrMan; class CBlockLocator; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 12de4bd9..31311139 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -96,6 +96,7 @@ Value getinfo(const Array& params, bool fHelp) if (pwalletMain->IsCrypted()) obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); } + obj.push_back(Pair("public_server_mode", GetBoolArg("-public_server_mode",false))); obj.push_back(Pair("errors", GetWarnings("statusbar"))); } return obj; @@ -155,6 +156,11 @@ Value listwalletusers(const Array& params, bool fHelp) // Find all addresses that have the given account Array ret; + + // Always return an empty array on a public server + if(GetBoolArg("-public_server_mode",false)) + return ret; + LOCK(pwalletMain->cs_wallet); BOOST_FOREACH(const PAIRTYPE(CKeyID, CKeyMetadata)& item, pwalletMain->mapKeyMetadata) { diff --git a/src/twister.cpp b/src/twister.cpp index 3da01c60..f0762638 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -1691,7 +1691,7 @@ Value getposts(const Array& params, bool fHelp) Value getdirectmsgs(const Array& params, bool fHelp) { - if (fHelp || params.size() < 2 || params.size() > 3) + if (fHelp || params.size() != 3) throw runtime_error( "getdirectmsgs '[{\"username\":username,\"max_id\":max_id,\"since_id\":since_id},...]'\n" "get (locally stored) decrypted direct messages sent/received by user \n" diff --git a/src/twister_utils.cpp b/src/twister_utils.cpp index 5abe5fc0..5260510b 100644 --- a/src/twister_utils.cpp +++ b/src/twister_utils.cpp @@ -71,6 +71,7 @@ int save_file(std::string const& filename, std::vector& v) libtorrent::error_code ec; if (!f.open(filename, file::write_only, ec)) return -1; if (ec) return -1; + f.set_size(0, ec); file::iovec_t b = {&v[0], v.size()}; size_type written = f.writev(0, &b, 1, ec); if (written != int(v.size())) return -3;