Refactoring of BasicHandler
[quassel.git] / src / core / ctcphandler.cpp
index 8493088..aab7cd1 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-08 by the Quassel Project                          *
+ *   Copyright (C) 2005-10 by the Quassel Project                          *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  ***************************************************************************/
 #include "ctcphandler.h"
 
-#include "global.h"
-#include "util.h"
 #include "message.h"
 #include "network.h"
+#include "quassel.h"
+#include "util.h"
+#include "coreignorelistmanager.h"
 
-CtcpHandler::CtcpHandler(NetworkConnection *parent)
-  : BasicHandler(parent),
-    XDELIM("\001")
+CtcpHandler::CtcpHandler(CoreNetwork *parent)
+  : CoreBasicHandler(parent),
+    XDELIM("\001"),
+    _ignoreListManager(parent->ignoreListManager())
 {
 
   QByteArray MQUOTE = QByteArray("\020");
-  ctcpMDequoteHash[MQUOTE + '0'] = QByteArray("\000");
-  ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray("\n");
-  ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray("\r");
+  ctcpMDequoteHash[MQUOTE + '0'] = QByteArray(1, '\000');
+  ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray(1, '\n');
+  ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r');
   ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
 
   QByteArray XQUOTE = QByteArray("\134");
@@ -40,11 +42,27 @@ CtcpHandler::CtcpHandler(NetworkConnection *parent)
   ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
 }
 
-QByteArray CtcpHandler::dequote(const QByteArray &message) {
+QByteArray CtcpHandler::lowLevelQuote(const QByteArray &message) {
+  QByteArray quotedMessage = message;
+
+  QHash<QByteArray, QByteArray> quoteHash = ctcpMDequoteHash;
+  QByteArray MQUOTE = QByteArray("\020");
+  quoteHash.remove(MQUOTE + MQUOTE);
+  quotedMessage.replace(MQUOTE, MQUOTE + MQUOTE);
+
+  QHash<QByteArray, QByteArray>::const_iterator quoteIter = quoteHash.constBegin();
+  while(quoteIter != quoteHash.constEnd()) {
+    quotedMessage.replace(quoteIter.value(), quoteIter.key());
+    quoteIter++;
+  }
+  return quotedMessage;
+}
+
+QByteArray CtcpHandler::lowLevelDequote(const QByteArray &message) {
   QByteArray dequotedMessage;
   QByteArray messagepart;
   QHash<QByteArray, QByteArray>::iterator ctcpquote;
-  
+
   // copy dequote Message
   for(int i = 0; i < message.size(); i++) {
     messagepart = message.mid(i,1);
@@ -62,6 +80,15 @@ QByteArray CtcpHandler::dequote(const QByteArray &message) {
   return dequotedMessage;
 }
 
+QByteArray CtcpHandler::xdelimQuote(const QByteArray &message) {
+  QByteArray quotedMessage = message;
+  QHash<QByteArray, QByteArray>::const_iterator quoteIter = ctcpXDelimDequoteHash.constBegin();
+  while(quoteIter != ctcpXDelimDequoteHash.constEnd()) {
+    quotedMessage.replace(quoteIter.value(), quoteIter.key());
+    quoteIter++;
+  }
+  return quotedMessage;
+}
 
 QByteArray CtcpHandler::xdelimDequote(const QByteArray &message) {
   QByteArray dequotedMessage;
@@ -86,15 +113,15 @@ QByteArray CtcpHandler::xdelimDequote(const QByteArray &message) {
 
 void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const QString &target, const QByteArray &message) {
   QByteArray ctcp;
-  
+
   //lowlevel message dequote
-  QByteArray dequotedMessage = dequote(message);
+  QByteArray dequotedMessage = lowLevelDequote(message);
 
   CtcpType ctcptype = messageType == Message::Notice
     ? CtcpReply
     : CtcpQuery;
-  
-  quint8 flags = (messageType == Message::Notice && !network()->isChannelName(target))
+
+  Message::Flags flags = (messageType == Message::Notice && !network()->isChannelName(target))
     ? Message::Redirected
     : Message::None;
 
@@ -107,7 +134,10 @@ void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const
       displayMsg(messageType, target, userDecode(target, dequotedMessage.left(xdelimPos)), prefix, flags);
 
     xdelimEndPos = dequotedMessage.indexOf(XDELIM, xdelimPos + 1);
-    
+    if(xdelimEndPos == -1) {
+      // no matching end delimiter found... treat rest of the message as ctcp
+      xdelimEndPos = dequotedMessage.count();
+    }
     ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1));
     dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1);
 
@@ -126,25 +156,24 @@ void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const
 
     handle(ctcpcmd, Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam));
   }
-  
+
   if(!dequotedMessage.isEmpty())
     displayMsg(messageType, target, userDecode(target, dequotedMessage), prefix, flags);
 }
 
 QByteArray CtcpHandler::pack(const QByteArray &ctcpTag, const QByteArray &message) {
-  return XDELIM + ctcpTag + ' ' + message + XDELIM;
+  return XDELIM + ctcpTag + ' ' + xdelimQuote(message) + XDELIM;
 }
 
-// TODO handle encodings correctly!
 void CtcpHandler::query(const QString &bufname, const QString &ctcpTag, const QString &message) {
   QList<QByteArray> params;
-  params << serverEncode(bufname) << pack(serverEncode(ctcpTag), userEncode(bufname, message));
+  params << serverEncode(bufname) << lowLevelQuote(pack(serverEncode(ctcpTag), userEncode(bufname, message)));
   emit putCmd("PRIVMSG", params);
 }
 
 void CtcpHandler::reply(const QString &bufname, const QString &ctcpTag, const QString &message) {
   QList<QByteArray> params;
-  params << serverEncode(bufname) << pack(serverEncode(ctcpTag), userEncode(bufname, message));
+  params << serverEncode(bufname) << lowLevelQuote(pack(serverEncode(ctcpTag), userEncode(bufname, message)));
   emit putCmd("NOTICE", params);
 }
 
@@ -159,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) {
-    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();
@@ -172,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) {
-    // FIXME use real Info about quassel :)
-    reply(nickFromMask(prefix), "VERSION", QString("Quassel IRC (v%1 build >= %2) -- http://www.quassel-irc.org")
-        .arg(Global::quasselVersion).arg(Global::quasselBuild));
-    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));
@@ -185,8 +218,12 @@ void CtcpHandler::handleVersion(CtcpType ctcptype, const QString &prefix, const
 void CtcpHandler::defaultHandler(const QString &cmd, CtcpType ctcptype, const QString &prefix, const QString &target, const QString &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())) {
+    QString str = tr("Received unknown CTCP %1 by %2").arg(cmd).arg(prefix);
+    if(!param.isEmpty())
+      str.append(tr(" with arguments: %1").arg(param));
+    emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", str);
+  }
 }