Initial CTCP ignore functionality
authorSebastian Goth <seezer@roath.org>
Mon, 18 Jan 2010 16:08:55 +0000 (17:08 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 18 Jan 2010 17:52:59 +0000 (18:52 +0100)
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
src/common/ignorelistmanager.h
src/core/corenetwork.h
src/core/coresession.h
src/core/ctcphandler.cpp
src/core/ctcphandler.h
src/qtui/settingspages/ignorelisteditdlg.ui
src/qtui/settingspages/ignorelistsettingspage.cpp

index dfd9ae2..81382b2 100644 (file)
@@ -178,3 +178,28 @@ void IgnoreListManager::toggleIgnoreRule(const QString &ignoreRule) {
   _ignoreList[idx].isActive = !_ignoreList[idx].isActive;
   SYNC(ARG(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;
+}
index d6ab6ec..171f8b2 100644 (file)
@@ -37,7 +37,8 @@ public:
 
   enum IgnoreType {
     SenderIgnore,
 
   enum IgnoreType {
     SenderIgnore,
-    MessageIgnore
+    MessageIgnore,
+    CtcpIgnore
   };
 
   enum StrictnessType {
   };
 
   enum StrictnessType {
@@ -93,6 +94,7 @@ public:
     */
   StrictnessType match(const Message &msg, const QString &network = QString());
 
     */
   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);
 
 
 //  virtual void addIgnoreListItem(const IgnoreListItem &item);
 
index bb2a07d..d32734f 100644 (file)
@@ -39,6 +39,7 @@ class CoreIdentity;
 class IrcServerHandler;
 class CoreUserInputHandler;
 class CtcpHandler;
 class IrcServerHandler;
 class CoreUserInputHandler;
 class CtcpHandler;
+class CoreIgnoreListManager;
 
 class CoreNetwork : public Network {
   SYNCABLE_OBJECT
 
 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 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); }
 
   //! Decode a string using the server (network) decoding.
   inline QString serverDecode(const QByteArray &string) const { return decodeServerString(string); }
index 997d1f5..117f690 100644 (file)
@@ -67,6 +67,7 @@ public:
 
   inline CoreIrcListHelper *ircListHelper() const { return _ircListHelper; }
 
 
   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
 //   void attachNetworkConnection(NetworkConnection *conn);
 
   //! Return necessary data for restoring the session after restarting the core
index 5442206..2b606f6 100644 (file)
 #include "network.h"
 #include "quassel.h"
 #include "util.h"
 #include "network.h"
 #include "quassel.h"
 #include "util.h"
+#include "coreignorelistmanager.h"
 
 CtcpHandler::CtcpHandler(CoreNetwork *parent)
   : BasicHandler(parent),
 
 CtcpHandler::CtcpHandler(CoreNetwork *parent)
   : BasicHandler(parent),
-    XDELIM("\001")
+    XDELIM("\001"),
+    _ignoreListManager(parent->ignoreListManager())
 {
 
   QByteArray MQUOTE = QByteArray("\020");
 {
 
   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 &param) {
   Q_UNUSED(target)
   if(ctcptype == CtcpQuery) {
 void CtcpHandler::handlePing(CtcpType ctcptype, const QString &prefix, const QString &target, const QString &param) {
   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();
   } 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 &param) {
   Q_UNUSED(target)
   if(ctcptype == CtcpQuery) {
 void CtcpHandler::handleVersion(CtcpType ctcptype, const QString &prefix, const QString &target, const QString &param) {
   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));
   } 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);
   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));
+  }
 }
 
 
 }
 
 
index 6d3178b..35847c1 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "basichandler.h"
 
 
 #include "basichandler.h"
 
+class CoreListIgnoreListManager;
+
 class CtcpHandler : public BasicHandler {
   Q_OBJECT
 
 class CtcpHandler : public BasicHandler {
   Q_OBJECT
 
@@ -56,6 +58,7 @@ private:
   QByteArray XDELIM;
   QHash<QByteArray, QByteArray> ctcpMDequoteHash;
   QHash<QByteArray, QByteArray> ctcpXDelimDequoteHash;
   QByteArray XDELIM;
   QHash<QByteArray, QByteArray> ctcpMDequoteHash;
   QHash<QByteArray, QByteArray> ctcpXDelimDequoteHash;
+  CoreIgnoreListManager *_ignoreListManager;
 };
 
 
 };
 
 
index 990162a..3c10e8a 100644 (file)
@@ -80,6 +80,13 @@ Whenever you disable/delete the ignore rule, the messages are shown again.&lt;/p
           </property>
          </widget>
         </item>
           </property>
          </widget>
         </item>
+        <item>
+         <widget class="QRadioButton" name="ctcpTypeButton">
+          <property name="text">
+           <string>CTCP</string>
+          </property>
+         </widget>
+        </item>
        </layout>
       </widget>
      </item>
        </layout>
       </widget>
      </item>
index a832e5d..b5a72c2 100644 (file)
@@ -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);
   // 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);
   _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);
 
   if(item.type == IgnoreListManager::MessageIgnore)
     ui.messageTypeButton->setChecked(true);
+  else if(item.type == IgnoreListManager::CtcpIgnore)
+    ui.ctcpTypeButton->setChecked(true);
   else
     ui.senderTypeButton->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;
 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;
 
   else
     _clonedIgnoreListItem.type = IgnoreListManager::SenderIgnore;