|
|
@ -31,6 +31,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include <QKeyEvent> |
|
|
|
#include <QKeyEvent> |
|
|
|
#include <QMenu> |
|
|
|
#include <QMenu> |
|
|
|
|
|
|
|
#include <QMessageBox> |
|
|
|
#include <QScrollBar> |
|
|
|
#include <QScrollBar> |
|
|
|
#include <QSettings> |
|
|
|
#include <QSettings> |
|
|
|
#include <QSignalMapper> |
|
|
|
#include <QSignalMapper> |
|
|
@ -74,16 +75,6 @@ const QStringList historyFilter = QStringList() |
|
|
|
<< "walletpassphrasechange" |
|
|
|
<< "walletpassphrasechange" |
|
|
|
<< "encryptwallet"; |
|
|
|
<< "encryptwallet"; |
|
|
|
|
|
|
|
|
|
|
|
QString command_filter_sensitive_data(const QString cmd) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Q_FOREACH(QString unallowedCmd, historyFilter) { |
|
|
|
|
|
|
|
if (cmd.trimmed().startsWith(unallowedCmd)) { |
|
|
|
|
|
|
|
return unallowedCmd; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return cmd; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Object for executing console RPC commands in a separate thread.
|
|
|
|
/* Object for executing console RPC commands in a separate thread.
|
|
|
@ -175,13 +166,32 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
std::string curarg; |
|
|
|
std::string curarg; |
|
|
|
UniValue lastResult; |
|
|
|
UniValue lastResult; |
|
|
|
unsigned nDepthInsideSensitive = 0; |
|
|
|
unsigned nDepthInsideSensitive = 0; |
|
|
|
size_t filter_begin_pos = 0; |
|
|
|
size_t filter_begin_pos = 0, chpos; |
|
|
|
std::vector<std::pair<size_t, size_t>> filter_ranges; |
|
|
|
std::vector<std::pair<size_t, size_t>> filter_ranges; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto add_to_current_stack = [&](const std::string& curarg) { |
|
|
|
|
|
|
|
if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(curarg), Qt::CaseInsensitive)) { |
|
|
|
|
|
|
|
nDepthInsideSensitive = 1; |
|
|
|
|
|
|
|
filter_begin_pos = chpos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stack.back().push_back(curarg); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto close_out_params = [&]() { |
|
|
|
|
|
|
|
if (nDepthInsideSensitive) { |
|
|
|
|
|
|
|
if (!--nDepthInsideSensitive) { |
|
|
|
|
|
|
|
assert(filter_begin_pos); |
|
|
|
|
|
|
|
filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos)); |
|
|
|
|
|
|
|
filter_begin_pos = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stack.pop_back(); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::string strCommandTerminated = strCommand; |
|
|
|
std::string strCommandTerminated = strCommand; |
|
|
|
if (strCommandTerminated.back() != '\n') |
|
|
|
if (strCommandTerminated.back() != '\n') |
|
|
|
strCommandTerminated += "\n"; |
|
|
|
strCommandTerminated += "\n"; |
|
|
|
for (size_t chpos = 0; chpos < strCommandTerminated.size(); ++chpos) |
|
|
|
for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char ch = strCommandTerminated[chpos]; |
|
|
|
char ch = strCommandTerminated[chpos]; |
|
|
|
switch(state) |
|
|
|
switch(state) |
|
|
@ -227,14 +237,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
breakParsing = false; |
|
|
|
breakParsing = false; |
|
|
|
|
|
|
|
|
|
|
|
// pop the stack and return the result to the current command arguments
|
|
|
|
// pop the stack and return the result to the current command arguments
|
|
|
|
if (nDepthInsideSensitive) { |
|
|
|
close_out_params(); |
|
|
|
if (!--nDepthInsideSensitive) { |
|
|
|
|
|
|
|
assert(filter_begin_pos); |
|
|
|
|
|
|
|
filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos)); |
|
|
|
|
|
|
|
filter_begin_pos = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stack.pop_back(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// don't stringify the json in case of a string to avoid doublequotes
|
|
|
|
// don't stringify the json in case of a string to avoid doublequotes
|
|
|
|
if (lastResult.isStr()) |
|
|
|
if (lastResult.isStr()) |
|
|
@ -246,7 +249,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
if (curarg.size()) |
|
|
|
if (curarg.size()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (stack.size()) |
|
|
|
if (stack.size()) |
|
|
|
stack.back().push_back(curarg); |
|
|
|
add_to_current_stack(curarg); |
|
|
|
else |
|
|
|
else |
|
|
|
strResult = curarg; |
|
|
|
strResult = curarg; |
|
|
|
} |
|
|
|
} |
|
|
@ -283,7 +286,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
if (!stack.size()) |
|
|
|
if (!stack.size()) |
|
|
|
throw std::runtime_error("Invalid Syntax"); |
|
|
|
throw std::runtime_error("Invalid Syntax"); |
|
|
|
|
|
|
|
|
|
|
|
stack.back().push_back(curarg); |
|
|
|
add_to_current_stack(curarg); |
|
|
|
curarg.clear(); |
|
|
|
curarg.clear(); |
|
|
|
state = STATE_EATING_SPACES_IN_BRACKETS; |
|
|
|
state = STATE_EATING_SPACES_IN_BRACKETS; |
|
|
|
} |
|
|
|
} |
|
|
@ -308,12 +311,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
|
|
|
|
|
|
|
|
else if(state == STATE_ARGUMENT) // Space ends argument
|
|
|
|
else if(state == STATE_ARGUMENT) // Space ends argument
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// This is the only place where the method name should get pushed (as the first stack item)
|
|
|
|
add_to_current_stack(curarg); |
|
|
|
if ((!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(curarg), Qt::CaseInsensitive)) { |
|
|
|
|
|
|
|
nDepthInsideSensitive = 1; |
|
|
|
|
|
|
|
filter_begin_pos = chpos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
stack.back().push_back(curarg); |
|
|
|
|
|
|
|
curarg.clear(); |
|
|
|
curarg.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',') |
|
|
|
if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',') |
|
|
@ -351,9 +349,13 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (pstrFilteredOut) { |
|
|
|
if (pstrFilteredOut) { |
|
|
|
|
|
|
|
if (STATE_COMMAND_EXECUTED == state) { |
|
|
|
|
|
|
|
assert(!stack.empty()); |
|
|
|
|
|
|
|
close_out_params(); |
|
|
|
|
|
|
|
} |
|
|
|
*pstrFilteredOut = strCommand; |
|
|
|
*pstrFilteredOut = strCommand; |
|
|
|
for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) { |
|
|
|
for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) { |
|
|
|
pstrFilteredOut->replace(i->first, i->second - i->first, "..."); |
|
|
|
pstrFilteredOut->replace(i->first, i->second - i->first, "(…)"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
switch(state) // final state
|
|
|
|
switch(state) // final state
|
|
|
@ -800,16 +802,29 @@ void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) |
|
|
|
void RPCConsole::on_lineEdit_returnPressed() |
|
|
|
void RPCConsole::on_lineEdit_returnPressed() |
|
|
|
{ |
|
|
|
{ |
|
|
|
QString cmd = ui->lineEdit->text(); |
|
|
|
QString cmd = ui->lineEdit->text(); |
|
|
|
ui->lineEdit->clear(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!cmd.isEmpty()) |
|
|
|
if(!cmd.isEmpty()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
std::string strFilteredCmd; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
std::string dummy; |
|
|
|
|
|
|
|
if (!RPCParseCommandLine(dummy, cmd.toStdString(), false, &strFilteredCmd)) { |
|
|
|
|
|
|
|
// Failed to parse command, so we cannot even filter it for the history
|
|
|
|
|
|
|
|
throw std::runtime_error("Invalid command line"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} catch (const std::exception& e) { |
|
|
|
|
|
|
|
QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what())); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ui->lineEdit->clear(); |
|
|
|
|
|
|
|
|
|
|
|
cmdBeforeBrowsing = QString(); |
|
|
|
cmdBeforeBrowsing = QString(); |
|
|
|
|
|
|
|
|
|
|
|
message(CMD_REQUEST, cmd); |
|
|
|
message(CMD_REQUEST, cmd); |
|
|
|
Q_EMIT cmdRequest(cmd); |
|
|
|
Q_EMIT cmdRequest(cmd); |
|
|
|
|
|
|
|
|
|
|
|
cmd = command_filter_sensitive_data(cmd); |
|
|
|
cmd = QString::fromStdString(strFilteredCmd); |
|
|
|
|
|
|
|
|
|
|
|
// Remove command, if already in history
|
|
|
|
// Remove command, if already in history
|
|
|
|
history.removeOne(cmd); |
|
|
|
history.removeOne(cmd); |
|
|
|