aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2015-06-01 09:15:10 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2015-06-01 09:48:17 +0200
commit42746b0476ba4d8419227809a0001ad276b7ce51 (patch)
treefb121a8167d87776004278f9f522b02f31afd4c5 /src
parent921ea89bc3be5ac47d22580bd657212915cda1d5 (diff)
parent6e71efa9f020ee0a2b8050e8643deb03022b0b38 (diff)
downloadbitcoin-42746b0476ba4d8419227809a0001ad276b7ce51.tar.xz
Merge pull request #6193
6e71efa [REST] remove json input for getutxos, limit to query max. 15 outpoints (Jonas Schnelli) 64b8027 rest.cpp: strip whitespace (Jonas Schnelli)
Diffstat (limited to 'src')
-rw-r--r--src/rest.cpp94
1 files changed, 55 insertions, 39 deletions
diff --git a/src/rest.cpp b/src/rest.cpp
index 1b7954bbf6..7c238d506d 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -19,7 +19,7 @@
using namespace std;
using namespace json_spirit;
-static const int MAX_GETUTXOS_OUTPOINTS = 100; //allow a max of 100 outpoints to be queried at once
+static const int MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once
enum RetFormat {
RF_UNDEF,
@@ -262,12 +262,12 @@ static bool rest_chaininfo(AcceptedConnection* conn,
{
vector<string> params;
const RetFormat rf = ParseDataFormat(params, strURIPart);
-
+
switch (rf) {
case RF_JSON: {
Array rpcParams;
Value chainInfoObject = getblockchaininfo(rpcParams, false);
-
+
string strJSON = write_string(chainInfoObject, false) + "\n";
conn->stream() << HTTPReply(HTTP_OK, strJSON, fRun) << std::flush;
return true;
@@ -276,7 +276,7 @@ static bool rest_chaininfo(AcceptedConnection* conn,
throw RESTERR(HTTP_NOT_FOUND, "output format not found (available: json)");
}
}
-
+
// not reached
return true; // continue to process further HTTP reqs on this cxn
}
@@ -342,18 +342,53 @@ static bool rest_getutxos(AcceptedConnection* conn,
vector<string> params;
enum RetFormat rf = ParseDataFormat(params, strURIPart);
+ vector<string> uriParts;
+ if (params.size() > 0 && params[0].length() > 1)
+ {
+ std::string strUriParams = params[0].substr(1);
+ boost::split(uriParts, strUriParams, boost::is_any_of("/"));
+ }
+
// throw exception in case of a empty request
- if (strRequest.length() == 0)
+ if (strRequest.length() == 0 && uriParts.size() == 0)
throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
+ bool fInputParsed = false;
bool fCheckMemPool = false;
vector<COutPoint> vOutPoints;
// parse/deserialize input
// input-format = output-format, rest/getutxos/bin requires binary input, gives binary output, ...
-
+
+ if (uriParts.size() > 0)
+ {
+
+ //inputs is sent over URI scheme (/rest/getutxos/checkmempool/txid1-n/txid2-n/...)
+ if (uriParts.size() > 0 && uriParts[0] == "checkmempool")
+ fCheckMemPool = true;
+
+ for (size_t i = (fCheckMemPool) ? 1 : 0; i < uriParts.size(); i++)
+ {
+ uint256 txid;
+ int32_t nOutput;
+ std::string strTxid = uriParts[i].substr(0, uriParts[i].find("-"));
+ std::string strOutput = uriParts[i].substr(uriParts[i].find("-")+1);
+
+ if (!ParseInt32(strOutput, &nOutput) || !IsHex(strTxid))
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
+
+ txid.SetHex(strTxid);
+ vOutPoints.push_back(COutPoint(txid, (uint32_t)nOutput));
+ }
+
+ if (vOutPoints.size() > 0)
+ fInputParsed = true;
+ else
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
+ }
+
string strRequestMutable = strRequest; //convert const string to string for allowing hex to bin converting
-
+
switch (rf) {
case RF_HEX: {
// convert hex to bin, continue then with bin part
@@ -363,11 +398,17 @@ static bool rest_getutxos(AcceptedConnection* conn,
case RF_BINARY: {
try {
- //deserialize
- CDataStream oss(SER_NETWORK, PROTOCOL_VERSION);
- oss << strRequestMutable;
- oss >> fCheckMemPool;
- oss >> vOutPoints;
+ //deserialize only if user sent a request
+ if (strRequestMutable.size() > 0)
+ {
+ if (fInputParsed) //don't allow sending input over URI and HTTP RAW DATA
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Combination of URI scheme inputs and raw post data is not allowed");
+
+ CDataStream oss(SER_NETWORK, PROTOCOL_VERSION);
+ oss << strRequestMutable;
+ oss >> fCheckMemPool;
+ oss >> vOutPoints;
+ }
} catch (const std::ios_base::failure& e) {
// abort in case of unreadable binary data
throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
@@ -376,33 +417,8 @@ static bool rest_getutxos(AcceptedConnection* conn,
}
case RF_JSON: {
- try {
- // parse json request
- Value valRequest;
- if (!read_string(strRequest, valRequest))
- throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
-
- Object jsonObject = valRequest.get_obj();
- const Value& checkMempoolValue = find_value(jsonObject, "checkmempool");
-
- if (!checkMempoolValue.is_null()) {
- fCheckMemPool = checkMempoolValue.get_bool();
- }
- const Value& outpointsValue = find_value(jsonObject, "outpoints");
- if (!outpointsValue.is_null()) {
- Array outPoints = outpointsValue.get_array();
- BOOST_FOREACH (const Value& outPoint, outPoints) {
- Object outpointObject = outPoint.get_obj();
- uint256 txid = ParseHashO(outpointObject, "txid");
- Value nValue = find_value(outpointObject, "n");
- int nOutput = nValue.get_int();
- vOutPoints.push_back(COutPoint(txid, nOutput));
- }
- }
- } catch (...) {
- // return HTTP 500 if there was a json parsing error
- throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Parse error");
- }
+ if (!fInputParsed)
+ throw RESTERR(HTTP_INTERNAL_SERVER_ERROR, "Error: empty request");
break;
}
default: {