From ac374ec32612798c230d54665f6bce7faf416602 Mon Sep 17 00:00:00 2001 From: Sebastian Goth Date: Mon, 18 Jan 2010 17:08:55 +0100 Subject: [PATCH] Initial CTCP ignore functionality Kind of hacky solution to not break protocol. Introduces new "type" in settingspage that causes the "Rule" line to be interpreted as: hostmask [CTCPCMD CTCPCMD] for example: * VERSION blocks any version _request_ globally or on any configured network. If no CTCPCMD is given, all CTCP requests will be ignored. --- src/common/ignorelistmanager.cpp | 25 +++++++++++++++++++ src/common/ignorelistmanager.h | 4 ++- src/core/corenetwork.h | 2 ++ src/core/coresession.h | 1 + src/core/ctcphandler.cpp | 24 ++++++++++++------ src/core/ctcphandler.h | 3 +++ src/qtui/settingspages/ignorelisteditdlg.ui | 7 ++++++ .../settingspages/ignorelistsettingspage.cpp | 5 ++++ 8 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/common/ignorelistmanager.cpp b/src/common/ignorelistmanager.cpp index dfd9ae2d..81382b26 100644 --- a/src/common/ignorelistmanager.cpp +++ b/src/common/ignorelistmanager.cpp @@ -178,3 +178,28 @@ void IgnoreListManager::toggleIgnoreRule(const QString &ignoreRule) { _ignoreList[idx].isActive = !_ignoreList[idx].isActive; SYNC(ARG(ignoreRule)) } + +bool IgnoreListManager::ctcpMatch(const QString sender, const QString &network, const QString &type) { + foreach(IgnoreListItem item, _ignoreList) { + if(!item.isActive) + continue; + if(item.scope == GlobalScope || (item.scope == NetworkScope && scopeMatch(item.scopeRule, network))) { + QString sender_; + QStringList types = item.ignoreRule.split(QRegExp("\\s+"), QString::SkipEmptyParts); + + sender_ = types.takeAt(0); + + QRegExp ruleRx = QRegExp(sender_); + ruleRx.setCaseSensitivity(Qt::CaseInsensitive); + if(!item.isRegEx) + ruleRx.setPatternSyntax(QRegExp::Wildcard); + if((!item.isRegEx && ruleRx.exactMatch(sender)) || + (item.isRegEx && ruleRx.indexIn(sender) != -1)) { + + if(types.isEmpty() || types.contains(type, Qt::CaseInsensitive)) + return true; + } + } + } + return false; +} diff --git a/src/common/ignorelistmanager.h b/src/common/ignorelistmanager.h index d6ab6eca..171f8b23 100644 --- a/src/common/ignorelistmanager.h +++ b/src/common/ignorelistmanager.h @@ -37,7 +37,8 @@ public: enum IgnoreType { SenderIgnore, - MessageIgnore + MessageIgnore, + CtcpIgnore }; enum StrictnessType { @@ -93,6 +94,7 @@ public: */ StrictnessType match(const Message &msg, const QString &network = QString()); + bool ctcpMatch(const QString sender, const QString &network, const QString &type = QString()); // virtual void addIgnoreListItem(const IgnoreListItem &item); diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index bb2a07d3..d32734f4 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -39,6 +39,7 @@ class CoreIdentity; class IrcServerHandler; class CoreUserInputHandler; class CtcpHandler; +class CoreIgnoreListManager; class CoreNetwork : public Network { SYNCABLE_OBJECT @@ -56,6 +57,7 @@ public: inline IrcServerHandler *ircServerHandler() const { return _ircServerHandler; } inline CoreUserInputHandler *userInputHandler() const { return _userInputHandler; } inline CtcpHandler *ctcpHandler() const { return _ctcpHandler; } + inline CoreIgnoreListManager *ignoreListManager() { return coreSession()->ignoreListManager(); } //! Decode a string using the server (network) decoding. inline QString serverDecode(const QByteArray &string) const { return decodeServerString(string); } diff --git a/src/core/coresession.h b/src/core/coresession.h index 997d1f53..117f690e 100644 --- a/src/core/coresession.h +++ b/src/core/coresession.h @@ -67,6 +67,7 @@ public: inline CoreIrcListHelper *ircListHelper() const { return _ircListHelper; } + inline CoreIgnoreListManager *ignoreListManager() { return &_ignoreListManager; } // void attachNetworkConnection(NetworkConnection *conn); //! Return necessary data for restoring the session after restarting the core diff --git a/src/core/ctcphandler.cpp b/src/core/ctcphandler.cpp index 5442206b..2b606f6b 100644 --- a/src/core/ctcphandler.cpp +++ b/src/core/ctcphandler.cpp @@ -23,10 +23,12 @@ #include "network.h" #include "quassel.h" #include "util.h" +#include "coreignorelistmanager.h" CtcpHandler::CtcpHandler(CoreNetwork *parent) : BasicHandler(parent), - XDELIM("\001") + XDELIM("\001"), + _ignoreListManager(parent->ignoreListManager()) { QByteArray MQUOTE = QByteArray("\020"); @@ -186,8 +188,10 @@ void CtcpHandler::handleAction(CtcpType ctcptype, const QString &prefix, const Q void CtcpHandler::handlePing(CtcpType ctcptype, const QString &prefix, const QString &target, const QString ¶m) { Q_UNUSED(target) if(ctcptype == CtcpQuery) { - reply(nickFromMask(prefix), "PING", param); - emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP PING request from %1").arg(prefix)); + if(!_ignoreListManager->ctcpMatch(prefix, network()->networkName(), "PING")) { + reply(nickFromMask(prefix), "PING", param); + emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP PING request from %1").arg(prefix)); + } } else { // display ping answer uint now = QDateTime::currentDateTime().toTime_t(); @@ -199,10 +203,12 @@ void CtcpHandler::handlePing(CtcpType ctcptype, const QString &prefix, const QSt void CtcpHandler::handleVersion(CtcpType ctcptype, const QString &prefix, const QString &target, const QString ¶m) { Q_UNUSED(target) if(ctcptype == CtcpQuery) { - reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org") - .arg(Quassel::buildInfo().plainVersionString) - .arg(Quassel::buildInfo().buildDate)); - emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP VERSION request by %1").arg(prefix)); + if(!_ignoreListManager->ctcpMatch(prefix, network()->networkName(), "VERSION")) { + reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org") + .arg(Quassel::buildInfo().plainVersionString) + .arg(Quassel::buildInfo().buildDate)); + emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP VERSION request by %1").arg(prefix)); + } } else { // display Version answer emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Received CTCP VERSION answer from %1: %2").arg(prefix).arg(param)); @@ -213,7 +219,9 @@ void CtcpHandler::defaultHandler(const QString &cmd, CtcpType ctcptype, const QS Q_UNUSED(ctcptype); Q_UNUSED(target); Q_UNUSED(param); - emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Received unknown CTCP %1 by %2").arg(cmd).arg(prefix)); + if(!_ignoreListManager->ctcpMatch(prefix, network()->networkName())) { + emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Received unknown CTCP %1 by %2").arg(cmd).arg(prefix)); + } } diff --git a/src/core/ctcphandler.h b/src/core/ctcphandler.h index 6d3178ba..35847c1f 100644 --- a/src/core/ctcphandler.h +++ b/src/core/ctcphandler.h @@ -26,6 +26,8 @@ #include "basichandler.h" +class CoreListIgnoreListManager; + class CtcpHandler : public BasicHandler { Q_OBJECT @@ -56,6 +58,7 @@ private: QByteArray XDELIM; QHash ctcpMDequoteHash; QHash ctcpXDelimDequoteHash; + CoreIgnoreListManager *_ignoreListManager; }; diff --git a/src/qtui/settingspages/ignorelisteditdlg.ui b/src/qtui/settingspages/ignorelisteditdlg.ui index 014604f3..8938b8e1 100644 --- a/src/qtui/settingspages/ignorelisteditdlg.ui +++ b/src/qtui/settingspages/ignorelisteditdlg.ui @@ -80,6 +80,13 @@ Whenever you disable/delete the ignore rule, the messages are shown again.</p + + + + CTCP + + + diff --git a/src/qtui/settingspages/ignorelistsettingspage.cpp b/src/qtui/settingspages/ignorelistsettingspage.cpp index aa73396b..a49b46ef 100644 --- a/src/qtui/settingspages/ignorelistsettingspage.cpp +++ b/src/qtui/settingspages/ignorelistsettingspage.cpp @@ -214,6 +214,7 @@ IgnoreListEditDlg::IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &it // this could be moved to .ui file with qt4.5 _typeButtonGroup.addButton(ui.senderTypeButton, 0); _typeButtonGroup.addButton(ui.messageTypeButton, 1); + _typeButtonGroup.addButton(ui.ctcpTypeButton, 2); _strictnessButtonGroup.addButton(ui.dynamicStrictnessButton, 0); _strictnessButtonGroup.addButton(ui.permanentStrictnessButton, 1); _scopeButtonGroup.addButton(ui.globalScopeButton, 0); @@ -226,6 +227,8 @@ IgnoreListEditDlg::IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &it if(item.type == IgnoreListManager::MessageIgnore) ui.messageTypeButton->setChecked(true); + else if(item.type == IgnoreListManager::CtcpIgnore) + ui.ctcpTypeButton->setChecked(true); else ui.senderTypeButton->setChecked(true); @@ -271,6 +274,8 @@ IgnoreListEditDlg::IgnoreListEditDlg(const IgnoreListManager::IgnoreListItem &it void IgnoreListEditDlg::widgetHasChanged() { if(ui.messageTypeButton->isChecked()) _clonedIgnoreListItem.type = IgnoreListManager::MessageIgnore; + else if(ui.ctcpTypeButton->isChecked()) + _clonedIgnoreListItem.type = IgnoreListManager::CtcpIgnore; else _clonedIgnoreListItem.type = IgnoreListManager::SenderIgnore; -- 2.20.1