31
31
32
32
#include < QKeyEvent>
33
33
#include < QMenu>
34
+ #include < QMessageBox>
34
35
#include < QScrollBar>
35
36
#include < QSettings>
36
37
#include < QSignalMapper>
@@ -74,16 +75,6 @@ const QStringList historyFilter = QStringList()
74
75
<< " walletpassphrasechange"
75
76
<< " encryptwallet" ;
76
77
77
- QString command_filter_sensitive_data (const QString cmd)
78
- {
79
- Q_FOREACH (QString unallowedCmd, historyFilter) {
80
- if (cmd.trimmed ().startsWith (unallowedCmd)) {
81
- return unallowedCmd;
82
- }
83
- }
84
- return cmd;
85
- }
86
-
87
78
}
88
79
89
80
/* Object for executing console RPC commands in a separate thread.
@@ -175,13 +166,32 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
175
166
std::string curarg;
176
167
UniValue lastResult;
177
168
unsigned nDepthInsideSensitive = 0 ;
178
- size_t filter_begin_pos = 0 ;
169
+ size_t filter_begin_pos = 0 , chpos ;
179
170
std::vector<std::pair<size_t , size_t >> filter_ranges;
180
171
172
+ auto add_to_current_stack = [&](const std::string& curarg) {
173
+ if (stack.back ().empty () && (!nDepthInsideSensitive) && historyFilter.contains (QString::fromStdString (curarg), Qt::CaseInsensitive)) {
174
+ nDepthInsideSensitive = 1 ;
175
+ filter_begin_pos = chpos;
176
+ }
177
+ stack.back ().push_back (curarg);
178
+ };
179
+
180
+ auto close_out_params = [&]() {
181
+ if (nDepthInsideSensitive) {
182
+ if (!--nDepthInsideSensitive) {
183
+ assert (filter_begin_pos);
184
+ filter_ranges.push_back (std::make_pair (filter_begin_pos, chpos));
185
+ filter_begin_pos = 0 ;
186
+ }
187
+ }
188
+ stack.pop_back ();
189
+ };
190
+
181
191
std::string strCommandTerminated = strCommand;
182
192
if (strCommandTerminated.back () != ' \n ' )
183
193
strCommandTerminated += " \n " ;
184
- for (size_t chpos = 0 ; chpos < strCommandTerminated.size (); ++chpos)
194
+ for (chpos = 0 ; chpos < strCommandTerminated.size (); ++chpos)
185
195
{
186
196
char ch = strCommandTerminated[chpos];
187
197
switch (state)
@@ -227,14 +237,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
227
237
breakParsing = false ;
228
238
229
239
// pop the stack and return the result to the current command arguments
230
- if (nDepthInsideSensitive) {
231
- if (!--nDepthInsideSensitive) {
232
- assert (filter_begin_pos);
233
- filter_ranges.push_back (std::make_pair (filter_begin_pos, chpos));
234
- filter_begin_pos = 0 ;
235
- }
236
- }
237
- stack.pop_back ();
240
+ close_out_params ();
238
241
239
242
// don't stringify the json in case of a string to avoid doublequotes
240
243
if (lastResult.isStr ())
@@ -246,7 +249,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
246
249
if (curarg.size ())
247
250
{
248
251
if (stack.size ())
249
- stack. back (). push_back (curarg);
252
+ add_to_current_stack (curarg);
250
253
else
251
254
strResult = curarg;
252
255
}
@@ -283,7 +286,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
283
286
if (!stack.size ())
284
287
throw std::runtime_error (" Invalid Syntax" );
285
288
286
- stack. back (). push_back (curarg);
289
+ add_to_current_stack (curarg);
287
290
curarg.clear ();
288
291
state = STATE_EATING_SPACES_IN_BRACKETS;
289
292
}
@@ -308,12 +311,7 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
308
311
309
312
else if (state == STATE_ARGUMENT) // Space ends argument
310
313
{
311
- // This is the only place where the method name should get pushed (as the first stack item)
312
- if ((!nDepthInsideSensitive) && historyFilter.contains (QString::fromStdString (curarg), Qt::CaseInsensitive)) {
313
- nDepthInsideSensitive = 1 ;
314
- filter_begin_pos = chpos;
315
- }
316
- stack.back ().push_back (curarg);
314
+ add_to_current_stack (curarg);
317
315
curarg.clear ();
318
316
}
319
317
if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ' ,' )
@@ -351,9 +349,13 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
351
349
}
352
350
}
353
351
if (pstrFilteredOut) {
352
+ if (STATE_COMMAND_EXECUTED == state) {
353
+ assert (!stack.empty ());
354
+ close_out_params ();
355
+ }
354
356
*pstrFilteredOut = strCommand;
355
357
for (auto i = filter_ranges.rbegin (); i != filter_ranges.rend (); ++i) {
356
- pstrFilteredOut->replace (i->first , i->second - i->first , " ... " );
358
+ pstrFilteredOut->replace (i->first , i->second - i->first , " (…) " );
357
359
}
358
360
}
359
361
switch (state) // final state
@@ -800,16 +802,29 @@ void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
800
802
void RPCConsole::on_lineEdit_returnPressed ()
801
803
{
802
804
QString cmd = ui->lineEdit ->text ();
803
- ui->lineEdit ->clear ();
804
805
805
806
if (!cmd.isEmpty ())
806
807
{
808
+ std::string strFilteredCmd;
809
+ try {
810
+ std::string dummy;
811
+ if (!RPCParseCommandLine (dummy, cmd.toStdString (), false , &strFilteredCmd)) {
812
+ // Failed to parse command, so we cannot even filter it for the history
813
+ throw std::runtime_error (" Invalid command line" );
814
+ }
815
+ } catch (const std::exception& e) {
816
+ QMessageBox::critical (this , " Error" , QString (" Error: " ) + QString::fromStdString (e.what ()));
817
+ return ;
818
+ }
819
+
820
+ ui->lineEdit ->clear ();
821
+
807
822
cmdBeforeBrowsing = QString ();
808
823
809
824
message (CMD_REQUEST, cmd);
810
825
Q_EMIT cmdRequest (cmd);
811
826
812
- cmd = command_filter_sensitive_data (cmd );
827
+ cmd = QString::fromStdString (strFilteredCmd );
813
828
814
829
// Remove command, if already in history
815
830
history.removeOne (cmd);
0 commit comments