From adeeb152130c3c80cccd7d12684e6768f8f5b227 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sat, 28 Sep 2013 07:47:07 -0300 Subject: [PATCH] implement very very simple html server to fix cross-domain problems executing json-rpc from browser --- src/bitcoinrpc.cpp | 41 +++++++++++++++++++++++++++++++++-------- src/twister.cpp | 33 +++++++++------------------------ src/twister.h | 3 +++ 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 66fce69a..9d562b6f 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -12,6 +12,8 @@ #include "bitcoinrpc.h" #include "db.h" +#include "twister.h" + #include #include #include @@ -25,6 +27,9 @@ #include #include #include +#include +#include +#include using namespace std; using namespace boost; @@ -306,7 +311,7 @@ string rfc1123Time() return string(buffer); } -static string HTTPReply(int nStatus, const string& strMsg, bool keepalive) +static string HTTPReply(int nStatus, const string& strMsg, bool keepalive, const char *contentType = "application/json") { if (nStatus == HTTP_UNAUTHORIZED) return strprintf("HTTP/1.0 401 Authorization Required\r\n" @@ -332,22 +337,23 @@ static string HTTPReply(int nStatus, const string& strMsg, bool keepalive) else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; else cStatus = ""; - return strprintf( + + string strReply = strprintf( "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" "Connection: %s\r\n" "Content-Length: %"PRIszu"\r\n" - "Content-Type: application/json\r\n" + "Content-Type: %s\r\n" "Server: bitcoin-json-rpc/%s\r\n" - "\r\n" - "%s", + "\r\n", nStatus, cStatus, rfc1123Time().c_str(), keepalive ? "keep-alive" : "close", strMsg.size(), - FormatFullVersion().c_str(), - strMsg.c_str()); + contentType, + FormatFullVersion().c_str()); + return strReply + strMsg; } bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, @@ -364,6 +370,19 @@ bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, // HTTP methods permitted: GET, POST http_method = vWords[0]; + if (http_method == "OPTIONS") { + string replyOptions= strprintf( + "HTTP/1.1 %d %s\r\n" + "Date: %s\r\n" + "Connection: close\r\n" + "Allow: GET,POST,OPTIONS\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" + "Access-Control-Allow-Headers: origin, x-csrf-token, content-type, accept, authorization\r\n" + "Server: bitcoin-json-rpc/%s\r\n" + "\r\n", HTTP_OK, "OK", rfc1123Time().c_str(), FormatFullVersion().c_str()); + (*static_cast(&stream)) << replyOptions << std::flush; + } if (http_method != "GET" && http_method != "POST") return false; @@ -952,7 +971,13 @@ void ServiceConnection(AcceptedConnection *conn) ReadHTTPMessage(conn->stream(), mapHeaders, strRequest, nProto); if (strURI != "/") { - conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; + std::vector file_data; + if( load_file(strURI.c_str(), file_data) == 0 ) { + std::string str(file_data.data(), file_data.size()); + conn->stream() << HTTPReply(HTTP_OK, str, false, "text/html") << std::flush; + } else { + conn->stream() << HTTPReply(HTTP_NOT_FOUND, "", false) << std::flush; + } break; } diff --git a/src/twister.cpp b/src/twister.cpp index aa4f42fc..bf027a6f 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -52,56 +52,41 @@ 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, libtorrent::error_code& ec, int limit = 8000000) +int load_file(std::string const& filename, std::vector& v, int limit) { - ec.clear(); FILE* f = fopen(filename.c_str(), "rb"); if (f == NULL) - { - ec.assign(errno, boost::system::get_generic_category()); return -1; - } - int r = fseek(f, 0, SEEK_END); - if (r != 0) - { - ec.assign(errno, boost::system::get_generic_category()); + if (r != 0) { fclose(f); return -1; } long s = ftell(f); - if (s < 0) - { - ec.assign(errno, boost::system::get_generic_category()); + if (s < 0) { fclose(f); return -1; } - if (s > limit) - { + if (s > limit) { fclose(f); return -2; } r = fseek(f, 0, SEEK_SET); - if (r != 0) - { - ec.assign(errno, boost::system::get_generic_category()); + if (r != 0) { fclose(f); return -1; } v.resize(s); - if (s == 0) - { + if (s == 0) { fclose(f); return 0; } r = fread(&v[0], 1, v.size(), f); - if (r < 0) - { - ec.assign(errno, boost::system::get_generic_category()); + if (r < 0) { fclose(f); return -1; } @@ -145,7 +130,7 @@ torrent_handle startTorrentUser(std::string const &username) create_directory(tparams.save_path, ec); std::string filename = combine_path(tparams.save_path, to_hex(ih.to_string()) + ".resume"); - load_file(filename.c_str(), tparams.resume_data, ec); + load_file(filename.c_str(), tparams.resume_data); m_userTorrent[username] = ses->add_torrent(tparams); m_userTorrent[username].force_dht_announce(); @@ -194,7 +179,7 @@ void ThreadWaitExtIP() std::vector in; boost::filesystem::path sesStatePath = GetDataDir() / "ses_state"; - if (load_file(sesStatePath.string(), in, ec) == 0) + if (load_file(sesStatePath.string(), in) == 0) { lazy_entry e; if (lazy_bdecode(&in[0], &in[0] + in.size(), e, ec) == 0) diff --git a/src/twister.h b/src/twister.h index e75cf3f1..52bcb9d0 100644 --- a/src/twister.h +++ b/src/twister.h @@ -27,4 +27,7 @@ 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