5 #if defined(HAVE_CONFIG_H) 23 #include <openssl/crypto.h> 32 #include <QDesktopWidget> 35 #include <QMessageBox> 38 #include <QSignalMapper> 42 #include <QStringList> 43 #include <QStyledItemDelegate> 45 #if QT_VERSION < 0x050000 73 const QStringList historyFilter = QStringList()
76 <<
"signmessagewithprivkey" 77 <<
"signrawtransaction" 79 <<
"walletpassphrasechange" 91 void request(
const QString &command);
94 void reply(
int category,
const QString &command);
107 timer.setSingleShot(
true);
108 connect(&timer, SIGNAL(timeout()),
this, SLOT(timeout()));
116 std::function<void(void)>
func;
123 const char *
Name() {
return "Qt"; }
131 #include <rpcconsole.moc> 154 std::vector< std::vector<std::string> > stack;
155 stack.push_back(std::vector<std::string>());
160 STATE_EATING_SPACES_IN_ARG,
161 STATE_EATING_SPACES_IN_BRACKETS,
166 STATE_ESCAPE_DOUBLEQUOTED,
167 STATE_COMMAND_EXECUTED,
168 STATE_COMMAND_EXECUTED_INNER
169 } state = STATE_EATING_SPACES;
172 unsigned nDepthInsideSensitive = 0;
173 size_t filter_begin_pos = 0, chpos;
174 std::vector<std::pair<size_t, size_t>> filter_ranges;
176 auto add_to_current_stack = [&](
const std::string& strArg) {
177 if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {
178 nDepthInsideSensitive = 1;
179 filter_begin_pos = chpos;
183 stack.
push_back(std::vector<std::string>());
185 stack.back().push_back(strArg);
188 auto close_out_params = [&]() {
189 if (nDepthInsideSensitive) {
190 if (!--nDepthInsideSensitive) {
192 filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
193 filter_begin_pos = 0;
199 std::string strCommandTerminated = strCommand;
200 if (strCommandTerminated.back() !=
'\n')
201 strCommandTerminated +=
"\n";
202 for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)
204 char ch = strCommandTerminated[chpos];
207 case STATE_COMMAND_EXECUTED_INNER:
208 case STATE_COMMAND_EXECUTED:
210 bool breakParsing =
true;
213 case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER;
break;
215 if (state == STATE_COMMAND_EXECUTED_INNER)
223 if (curarg.size() && fExecute)
229 for(
char argch: curarg)
230 if (!std::isdigit(argch))
231 throw std::runtime_error(
"Invalid result query");
232 subelement = lastResult[
atoi(curarg.c_str())];
237 throw std::runtime_error(
"Invalid result query");
238 lastResult = subelement;
241 state = STATE_COMMAND_EXECUTED;
245 breakParsing =
false;
251 if (lastResult.
isStr())
254 curarg = lastResult.
write(2);
260 add_to_current_stack(curarg);
266 state = STATE_EATING_SPACES;
272 case STATE_EATING_SPACES_IN_ARG:
273 case STATE_EATING_SPACES_IN_BRACKETS:
274 case STATE_EATING_SPACES:
277 case '"': state = STATE_DOUBLEQUOTED;
break;
278 case '\'': state = STATE_SINGLEQUOTED;
break;
279 case '\\': state = STATE_ESCAPE_OUTER;
break;
280 case '(':
case ')':
case '\n':
281 if (state == STATE_EATING_SPACES_IN_ARG)
282 throw std::runtime_error(
"Invalid Syntax");
283 if (state == STATE_ARGUMENT)
285 if (ch ==
'(' && stack.size() && stack.back().size() > 0)
287 if (nDepthInsideSensitive) {
288 ++nDepthInsideSensitive;
290 stack.push_back(std::vector<std::string>());
295 throw std::runtime_error(
"Invalid Syntax");
297 add_to_current_stack(curarg);
299 state = STATE_EATING_SPACES_IN_BRACKETS;
301 if ((ch ==
')' || ch ==
'\n') && stack.size() > 0)
307 req.
params =
RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
313 QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(
vpwallets[0]->GetName()));
314 req.
URI =
"/wallet/"+std::string(encodedName.constData(), encodedName.length());
320 state = STATE_COMMAND_EXECUTED;
324 case ' ':
case ',':
case '\t':
325 if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch ==
',')
326 throw std::runtime_error(
"Invalid Syntax");
328 else if(state == STATE_ARGUMENT)
330 add_to_current_stack(curarg);
333 if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch ==
',')
335 state = STATE_EATING_SPACES_IN_ARG;
338 state = STATE_EATING_SPACES;
340 default: curarg +=
ch; state = STATE_ARGUMENT;
343 case STATE_SINGLEQUOTED:
346 case '\'': state = STATE_ARGUMENT;
break;
347 default: curarg +=
ch;
350 case STATE_DOUBLEQUOTED:
353 case '"': state = STATE_ARGUMENT;
break;
354 case '\\': state = STATE_ESCAPE_DOUBLEQUOTED;
break;
355 default: curarg +=
ch;
358 case STATE_ESCAPE_OUTER:
359 curarg +=
ch; state = STATE_ARGUMENT;
361 case STATE_ESCAPE_DOUBLEQUOTED:
362 if(ch !=
'"' && ch !=
'\\') curarg +=
'\\';
363 curarg +=
ch; state = STATE_DOUBLEQUOTED;
367 if (pstrFilteredOut) {
368 if (STATE_COMMAND_EXECUTED == state) {
372 *pstrFilteredOut = strCommand;
373 for (
auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
374 pstrFilteredOut->replace(i->first, i->second - i->first,
"(…)");
379 case STATE_COMMAND_EXECUTED:
380 if (lastResult.
isStr())
381 strResult = lastResult.
get_str();
383 strResult = lastResult.
write(2);
385 case STATE_EATING_SPACES:
397 std::string executableCommand = command.toStdString() +
"\n";
410 std::string message =
find_value(objError,
"message").get_str();
413 catch (
const std::runtime_error&)
418 catch (
const std::exception&
e)
429 platformStyle(_platformStyle),
430 peersTableContextMenu(0),
431 banTableContextMenu(0),
436 if (!restoreGeometry(settings.value(
"RPCConsoleWindowGeometry").toByteArray())) {
438 move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
486 ui->
peerHeading->setText(tr(
"Select a peer to view detailed information."));
495 settings.setValue(
"RPCConsoleWindowGeometry", saveGeometry());
503 if(event->type() == QEvent::KeyPress)
505 QKeyEvent *keyevt =
static_cast<QKeyEvent*
>(event);
506 int key = keyevt->key();
507 Qt::KeyboardModifiers mod = keyevt->modifiers();
513 case Qt::Key_PageDown:
524 QApplication::postEvent(
ui->
lineEdit,
new QKeyEvent(*keyevt));
532 (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
533 ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
534 ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
537 QApplication::postEvent(
ui->
lineEdit,
new QKeyEvent(*keyevt));
542 return QWidget::eventFilter(obj, event);
552 connect(model, SIGNAL(numConnectionsChanged(
int)),
this, SLOT(
setNumConnections(
int)));
555 connect(model, SIGNAL(numBlocksChanged(
int,QDateTime,
double,
bool)),
this, SLOT(
setNumBlocks(
int,QDateTime,
double,
bool)));
558 connect(model, SIGNAL(networkActiveChanged(
bool)),
this, SLOT(
setNetworkActive(
bool)));
561 connect(model, SIGNAL(bytesChanged(quint64,quint64)),
this, SLOT(
updateTrafficStats(quint64, quint64)));
563 connect(model, SIGNAL(mempoolSizeChanged(
long,
size_t)),
this, SLOT(
setMempoolSize(
long,
size_t)));
568 ui->
peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
569 ui->
peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
570 ui->
peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
571 ui->
peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
575 ui->
peerWidget->horizontalHeader()->setStretchLastSection(
true);
578 QAction* disconnectAction =
new QAction(tr(
"&Disconnect"),
this);
579 QAction* banAction1h =
new QAction(tr(
"Ban for") +
" " + tr(
"1 &hour"),
this);
580 QAction* banAction24h =
new QAction(tr(
"Ban for") +
" " + tr(
"1 &day"),
this);
581 QAction* banAction7d =
new QAction(tr(
"Ban for") +
" " + tr(
"1 &week"),
this);
582 QAction* banAction365d =
new QAction(tr(
"Ban for") +
" " + tr(
"1 &year"),
this);
595 QSignalMapper* signalMapper =
new QSignalMapper(
this);
596 signalMapper->setMapping(banAction1h, 60*60);
597 signalMapper->setMapping(banAction24h, 60*60*24);
598 signalMapper->setMapping(banAction7d, 60*60*24*7);
599 signalMapper->setMapping(banAction365d, 60*60*24*365);
600 connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map()));
601 connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map()));
602 connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map()));
603 connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map()));
604 connect(signalMapper, SIGNAL(mapped(
int)),
this, SLOT(
banSelectedNode(
int)));
611 connect(
ui->
peerWidget->selectionModel(), SIGNAL(selectionChanged(
const QItemSelection &,
const QItemSelection &)),
612 this, SLOT(
peerSelected(
const QItemSelection &,
const QItemSelection &)));
622 ui->
banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
623 ui->
banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
630 QAction* unbanAction =
new QAction(tr(
"&Unban"),
this);
654 QStringList wordList;
656 for (
size_t i = 0; i < commandList.size(); ++i)
658 wordList << commandList[i].c_str();
659 wordList << (
"help " + commandList[i]).c_str();
664 autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
667 autoCompleter->popup()->setItemDelegate(
new QStyledItemDelegate(
this));
681 static QString categoryClass(
int category)
688 default:
return "misc";
714 str.replace(QString(
"font-size:%1pt").arg(
consoleFontSize), QString(
"font-size:%1pt").arg(newSize));
743 QTextDocument::ImageResource,
753 "td.time { color: #808080; font-size: %2; padding-top: 3px; } " 754 "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } " 755 "td.cmd-request { color: #006060; } " 756 "td.cmd-error { color: red; } " 757 ".secwarning { color: red; }" 758 "b { color: #006060; } " 763 QString clsKey =
"(⌘)-L";
765 QString clsKey =
"Ctrl-L";
769 tr(
"Use up and down arrows to navigate history, and %1 to clear screen.").arg(
"<b>"+clsKey+
"</b>") +
"<br>" +
770 tr(
"Type <b>help</b> for an overview of available commands.")) +
771 "<br><span class=\"secwarning\">" +
772 tr(
"WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") +
779 if(windowType() != Qt::Widget && event->key() == Qt::Key_Escape)
787 QTime time = QTime::currentTime();
788 QString timeString = time.toString();
790 out +=
"<table><tr><td class=\"time\" width=\"65\">" + timeString +
"</td>";
791 out +=
"<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) +
"\"></td>";
792 out +=
"<td class=\"message " + categoryClass(category) +
"\" valign=\"middle\">";
797 out +=
"</td></tr></table>";
808 connections +=
" (" + tr(
"Network activity disabled") +
")";
839 if (dynUsage < 1000000)
840 ui->
mempoolSize->setText(QString::number(dynUsage/1000.0,
'f', 2) +
" KB");
842 ui->
mempoolSize->setText(QString::number(dynUsage/1000000.0,
'f', 2) +
" MB");
851 std::string strFilteredCmd;
856 throw std::runtime_error(
"Invalid command line");
858 }
catch (
const std::exception&
e) {
859 QMessageBox::critical(
this,
"Error", QString(
"Error: ") + QString::fromStdString(e.what()));
870 cmd = QString::fromStdString(strFilteredCmd);
911 executor->moveToThread(&
thread);
914 connect(executor, SIGNAL(reply(
int,QString)),
this, SLOT(
message(
int,QString)));
916 connect(
this, SIGNAL(
cmdRequest(QString)), executor, SLOT(request(QString)));
922 connect(&
thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
945 scrollbar->setValue(scrollbar->maximum());
950 const int multiplier = 5;
951 int mins = value * multiplier;
958 return QString(tr(
"%1 B")).arg(bytes);
959 if(bytes < 1024 * 1024)
960 return QString(tr(
"%1 KB")).arg(bytes / 1024);
961 if(bytes < 1024 * 1024 * 1024)
962 return QString(tr(
"%1 MB")).arg(bytes / 1024 / 1024);
964 return QString(tr(
"%1 GB")).arg(bytes / 1024 / 1024 / 1024);
981 Q_UNUSED(deselected);
993 QModelIndexList selected =
ui->
peerWidget->selectionModel()->selectedIndexes();
995 for(
int i = 0; i < selected.size(); i++)
1008 bool fUnselect =
false;
1009 bool fReselect =
false;
1015 int selectedRow = -1;
1016 QModelIndexList selectedModelIndex =
ui->
peerWidget->selectionModel()->selectedIndexes();
1017 if (!selectedModelIndex.isEmpty()) {
1018 selectedRow = selectedModelIndex.first().row();
1025 if (detailNodeRow < 0)
1032 if (detailNodeRow != selectedRow)
1043 if (fUnselect && selectedRow >= 0) {
1062 QString peerAddrDetails(QString::fromStdString(stats->
nodeStats.
addrName) +
" ");
1063 peerAddrDetails += tr(
"(node id: %1)").arg(QString::number(stats->
nodeStats.
nodeid));
1065 peerAddrDetails +=
"<br />" + tr(
"via %1").arg(QString::fromStdString(stats->
nodeStats.
addrLocal));
1107 QWidget::resizeEvent(event);
1112 QWidget::showEvent(event);
1123 QWidget::hideEvent(event);
1135 if (index.isValid())
1142 if (index.isValid())
1153 for(
int i = 0; i < nodes.count(); i++)
1156 NodeId id = nodes.at(i).data().toLongLong();
1170 for(
int i = 0; i < nodes.count(); i++)
1173 NodeId id = nodes.at(i).data().toLongLong();
1177 if(detailNodeRow < 0)
1197 for(
int i = 0; i < nodes.count(); i++)
1200 QString strNode = nodes.at(i).data().toString();
1203 LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
1217 ui->
peerHeading->setText(tr(
"Select a peer to view detailed information."));
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
QTableView * banlistWidget
int getRowByNodeId(NodeId nodeid)
const char * Name()
Implementation name.
RPCTimerBase * NewTimer(std::function< void(void)> &func, int64_t millis)
Factory function for timers.
const std::string & get_str() const
#define SetObjectStyleSheet(object, name)
Local Fabcoin RPC console.
QLabel * berkeleyDBVersion
#define function(a, b, c, d, k, s)
std::vector< std::string > listCommands() const
Returns a list of registered commands.
void keyPressEvent(QKeyEvent *)
std::vector< CWalletRef > vpwallets
QString cmdBeforeBrowsing
CNodeStateStats nodeStateStats
QList< QModelIndex > getEntryData(QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
static QString FormatBytes(quint64 bytes)
void showEvent(QShowEvent *event)
QPushButton * openDebugLogfileButton
void on_lineEdit_returnPressed()
QLabel * numberOfConnections
double getVerificationProgress(const CBlockIndex *tip) const
void message(int category, const QString &message, bool html=false)
Append the message to the message widget.
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string *const pstrFilteredOut=nullptr)
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
RPCConsole(const PlatformStyle *platformStyle, QWidget *parent)
QLabel * peerCommonHeight
quint64 getTotalBytesRecv() const
QTextEdit * messagesWidget
bool getNetworkActive() const
Return true if network activity in core is enabled.
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
void scrollToEnd()
Scroll console view to end.
QString formatTimeOffset(int64_t nTimeOffset)
void clearSelectedNode()
clear the selected node
assert(len-trim+(2 *lenIndices)<=WIDTH)
QString HtmlEscape(const QString &str, bool fMultiLine)
QString formatClientStartupTime() const
PeerTableModel * getPeerTableModel()
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
void on_tabWidget_currentChanged(int index)
void setupUi(QWidget *RPCConsole)
QLabel * mempoolNumberTxs
void updateNodeDetail(const CNodeCombinedStats *stats)
show detailed information on ui about selected node
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
QPushButton * btnClearTrafficGraph
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
void setClientModel(ClientModel *model)
void resizeEvent(QResizeEvent *event)
void reply(int category, const QString &command)
QPushButton * fontSmallerButton
QMenu * peersTableContextMenu
void browseHistory(int offset)
Go forward or back in history.
bool fNodeStateStatsAvailable
bool push_back(const UniValue &val)
int64_t GetSystemTimeInSeconds()
Class for handling RPC timers (used for e.g.
QString formatDurationStr(int secs)
std::function< void(void)> func
const int CONSOLE_HISTORY
QDateTime getLastBlockDate() const
QPushButton * clearButton
const Object_type::value_type::Value_type & find_value(const Object_type &obj, const String_type &name)
QtRPCTimerBase(std::function< void(void)> &_func, int64_t millis)
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
void request(const QString &command)
QString formatSubVersion() const
std::vector< byte > bytes
BanTableModel * getBanTableModel()
const struct @57 ICON_MAPPING[]
void peerLayoutChanged()
Handle updated peer information.
RPCTimerInterface * rpcTimerInterface
static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string *const pstrFilteredOut=nullptr)
Split shell command line into a list of arguments and optionally execute the command(s).
void updateNetworkState()
Update UI with latest network info from model.
const CNodeCombinedStats * getNodeStats(int idx)
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Model for Fabcoin network client.
void unbanSelectedNode()
Unban a selected node on the Bans tab.
QLabel * label_berkeleyDBVersion
void hideEvent(QHideEvent *event)
ClientModel * clientModel
TrafficGraphWidget * trafficGraph
QString formatPingTime(double dPingTime)
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
virtual bool eventFilter(QObject *obj, QEvent *event)
QMenu * banTableContextMenu
bool LookupSubNet(const char *pszName, CSubNet &ret)
void setTrafficGraphRange(int mins)
void clear(bool clearHistory=true)
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
quint64 getTotalBytesSent() const
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
QList< NodeId > cachedNodeids
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
void setFontSize(int newSize)
void setNumConnections(int count)
Set number of connections shown in the UI.
PlatformStyle::TableColorType type
const CChainParams & Params()
Return the currently selected parameters.
void peerLayoutAboutToChange()
Handle selection caching before update.
QString formatServicesStr(quint64 mask)
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
Opaque base class for timers returned by NewTimerFunc.
const int INITIAL_TRAFFIC_GRAPH_MINS
std::unique_ptr< CConnman > g_connman
const char fontSizeSettingsKey[]
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
Handle selection of peer in peers list.
const QSize FONT_RANGE(4, 40)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
uint32_t ch(uint32_t x, uint32_t y, uint32_t z)
QPushButton * fontBiggerButton
QCompleter * autoCompleter
QString formatFullVersion() const
void cmdRequest(const QString &command)
const PlatformStyle * platformStyle
void setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, bool headers)
Set number of blocks and last block date shown in the UI.
int atoi(const std::string &str)
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.