@@ -151,9 +151,10 @@ class QtRPCTimerInterface: public RPCTimerInterface
151
151
* @param[out] result stringified Result from the executed command(chain)
152
152
* @param[in] strCommand Command line to split
153
153
* @param[in] fExecute set true if you want the command to be executed
154
+ * @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data
154
155
*/
155
156
156
- bool RPCConsole::RPCParseCommandLine (std::string &strResult, const std::string &strCommand, const bool fExecute )
157
+ bool RPCConsole::RPCParseCommandLine (std::string &strResult, const std::string &strCommand, const bool fExecute , std::string * const pstrFilteredOut )
157
158
{
158
159
std::vector< std::vector<std::string> > stack;
159
160
stack.push_back (std::vector<std::string>());
@@ -173,12 +174,16 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
173
174
} state = STATE_EATING_SPACES;
174
175
std::string curarg;
175
176
UniValue lastResult;
177
+ unsigned nDepthInsideSensitive = 0 ;
178
+ size_t filter_begin_pos = 0 ;
179
+ std::vector<std::pair<size_t , size_t >> filter_ranges;
176
180
177
181
std::string strCommandTerminated = strCommand;
178
182
if (strCommandTerminated.back () != ' \n ' )
179
183
strCommandTerminated += " \n " ;
180
- for ( char ch: strCommandTerminated)
184
+ for ( size_t chpos = 0 ; chpos < strCommandTerminated. size (); ++chpos )
181
185
{
186
+ char ch = strCommandTerminated[chpos];
182
187
switch (state)
183
188
{
184
189
case STATE_COMMAND_EXECUTED_INNER:
@@ -222,6 +227,13 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
222
227
breakParsing = false ;
223
228
224
229
// 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
+ }
225
237
stack.pop_back ();
226
238
227
239
// don't stringify the json in case of a string to avoid doublequotes
@@ -260,7 +272,12 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
260
272
if (state == STATE_ARGUMENT)
261
273
{
262
274
if (ch == ' (' && stack.size () && stack.back ().size () > 0 )
275
+ {
276
+ if (nDepthInsideSensitive) {
277
+ ++nDepthInsideSensitive;
278
+ }
263
279
stack.push_back (std::vector<std::string>());
280
+ }
264
281
265
282
// don't allow commands after executed commands on baselevel
266
283
if (!stack.size ())
@@ -291,6 +308,11 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
291
308
292
309
else if (state == STATE_ARGUMENT) // Space ends argument
293
310
{
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
+ }
294
316
stack.back ().push_back (curarg);
295
317
curarg.clear ();
296
318
}
@@ -328,6 +350,12 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
328
350
break ;
329
351
}
330
352
}
353
+ if (pstrFilteredOut) {
354
+ *pstrFilteredOut = strCommand;
355
+ for (auto i = filter_ranges.rbegin (); i != filter_ranges.rend (); ++i) {
356
+ pstrFilteredOut->replace (i->first , i->second - i->first , " ..." );
357
+ }
358
+ }
331
359
switch (state) // final state
332
360
{
333
361
case STATE_COMMAND_EXECUTED:
0 commit comments