@@ -151,9 +151,10 @@ class QtRPCTimerInterface: public RPCTimerInterface
151151 * @param[out] result stringified Result from the executed command(chain)
152152 * @param[in] strCommand Command line to split
153153 * @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
154155 */
155156
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 )
157158{
158159 std::vector< std::vector<std::string> > stack;
159160 stack.push_back (std::vector<std::string>());
@@ -173,12 +174,16 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
173174 } state = STATE_EATING_SPACES;
174175 std::string curarg;
175176 UniValue lastResult;
177+ unsigned nDepthInsideSensitive = 0 ;
178+ size_t filter_begin_pos = 0 ;
179+ std::vector<std::pair<size_t , size_t >> filter_ranges;
176180
177181 std::string strCommandTerminated = strCommand;
178182 if (strCommandTerminated.back () != ' \n ' )
179183 strCommandTerminated += " \n " ;
180- for ( char ch: strCommandTerminated)
184+ for ( size_t chpos = 0 ; chpos < strCommandTerminated. size (); ++chpos )
181185 {
186+ char ch = strCommandTerminated[chpos];
182187 switch (state)
183188 {
184189 case STATE_COMMAND_EXECUTED_INNER:
@@ -222,6 +227,13 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
222227 breakParsing = false ;
223228
224229 // 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+ }
225237 stack.pop_back ();
226238
227239 // 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 &
260272 if (state == STATE_ARGUMENT)
261273 {
262274 if (ch == ' (' && stack.size () && stack.back ().size () > 0 )
275+ {
276+ if (nDepthInsideSensitive) {
277+ ++nDepthInsideSensitive;
278+ }
263279 stack.push_back (std::vector<std::string>());
280+ }
264281
265282 // don't allow commands after executed commands on baselevel
266283 if (!stack.size ())
@@ -291,6 +308,11 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
291308
292309 else if (state == STATE_ARGUMENT) // Space ends argument
293310 {
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+ }
294316 stack.back ().push_back (curarg);
295317 curarg.clear ();
296318 }
@@ -328,6 +350,12 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &
328350 break ;
329351 }
330352 }
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+ }
331359 switch (state) // final state
332360 {
333361 case STATE_COMMAND_EXECUTED:
0 commit comments