- All CTCP messages are now using proper charset en/decodings
authorMarcus Eggenberger <egs@quassel-irc.org>
Mon, 18 Feb 2008 18:37:11 +0000 (18:37 +0000)
committerMarcus Eggenberger <egs@quassel-irc.org>
Mon, 18 Feb 2008 18:37:11 +0000 (18:37 +0000)
- For non-Channel NOTICEs and RPL_NOSUCHNICK the redirection flag is
  set. This flag enables the client to show the message in the buffer
  it has been configured for (Status Buffer, Current Buffer, open Query)

The latter one has no effect for the time beeing as Those Settings are
stored in QtUiSettings which cannot be accessed by the Client.

src/core/basichandler.cpp
src/core/basichandler.h
src/core/ctcphandler.cpp
src/core/ctcphandler.h
src/core/ircserverhandler.cpp

index 8288e10..d93a844 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <QMetaMethod>
 
 
 #include <QMetaMethod>
 
+#include "util.h"
 #include "networkconnection.h"
 
 BasicHandler::BasicHandler(NetworkConnection *parent)
 #include "networkconnection.h"
 
 BasicHandler::BasicHandler(NetworkConnection *parent)
@@ -187,3 +188,9 @@ void BasicHandler::putCmd(const QString &cmd, const QList<QByteArray> &params, c
   foreach(QByteArray param, params) list << param;
   emit putCmd(cmd, list, prefix);
 }
   foreach(QByteArray param, params) list << param;
   emit putCmd(cmd, list, prefix);
 }
+
+void BasicHandler::displayMsg(Message::Type msgType, QString target, QString text, QString sender, quint8 flags) {
+  if(target.startsWith('$') || target.startsWith('#'))
+    target = nickFromMask(sender);
+  emit displayMsg(msgType, typeByTarget(target), target, text, sender, flags);
+}
index 7af3894..757af6e 100644 (file)
@@ -60,6 +60,7 @@ signals:
   void putRawLine(const QByteArray &msg);
 
 protected:
   void putRawLine(const QByteArray &msg);
 
 protected:
+  void displayMsg(Message::Type, QString target, QString text, QString sender = "", quint8 flags = Message::None);
   void putCmd(const QString &cmd, const QByteArray &param, const QByteArray &prefix = QByteArray());
   void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
 
   void putCmd(const QString &cmd, const QByteArray &param, const QByteArray &prefix = QByteArray());
   void putCmd(const QString &cmd, const QList<QByteArray> &params, const QByteArray &prefix = QByteArray());
 
index 1e5254d..e6b5344 100644 (file)
 #include "network.h"
 
 CtcpHandler::CtcpHandler(NetworkConnection *parent)
 #include "network.h"
 
 CtcpHandler::CtcpHandler(NetworkConnection *parent)
-  : BasicHandler(parent) {
-
-  QString MQUOTE = QString('\020');
-  ctcpMDequoteHash[MQUOTE + '0'] = QString('\000');
-  ctcpMDequoteHash[MQUOTE + 'n'] = QString('\n');
-  ctcpMDequoteHash[MQUOTE + 'r'] = QString('\r');
+  : BasicHandler(parent),
+    XDELIM("\001")
+{
+
+  QByteArray MQUOTE = QByteArray("\020");
+  ctcpMDequoteHash[MQUOTE + '0'] = QByteArray("\000");
+  ctcpMDequoteHash[MQUOTE + 'n'] = QByteArray("\n");
+  ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray("\r");
   ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
 
   ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE;
 
-  XDELIM = QString('\001');
-  QString XQUOTE = QString('\134');
+  QByteArray XQUOTE = QByteArray("\134");
   ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
   ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE;
-  ctcpXDelimDequoteHash[XQUOTE + QString('a')] = XDELIM;
+  ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM;
 }
 
 }
 
-QString CtcpHandler::dequote(QString message) {
-  QString dequotedMessage;
-  QString messagepart;
-  QHash<QString, QString>::iterator ctcpquote;
+QByteArray CtcpHandler::dequote(const QByteArray &message) {
+  QByteArray dequotedMessage;
+  QByteArray messagepart;
+  QHash<QByteArray, QByteArray>::iterator ctcpquote;
   
   // copy dequote Message
   for(int i = 0; i < message.size(); i++) {
   
   // copy dequote Message
   for(int i = 0; i < message.size(); i++) {
-    messagepart = message[i];
+    messagepart = message.mid(i,1);
     if(i+1 < message.size()) {
       for(ctcpquote = ctcpMDequoteHash.begin(); ctcpquote != ctcpMDequoteHash.end(); ++ctcpquote) {
         if(message.mid(i,2) == ctcpquote.key()) {
     if(i+1 < message.size()) {
       for(ctcpquote = ctcpMDequoteHash.begin(); ctcpquote != ctcpMDequoteHash.end(); ++ctcpquote) {
         if(message.mid(i,2) == ctcpquote.key()) {
@@ -62,13 +63,13 @@ QString CtcpHandler::dequote(QString message) {
 }
 
 
 }
 
 
-QString CtcpHandler::XdelimDequote(QString message) {
-  QString dequotedMessage;
-  QString messagepart;
-  QHash<QString, QString>::iterator xdelimquote;
+QByteArray CtcpHandler::xdelimDequote(const QByteArray &message) {
+  QByteArray dequotedMessage;
+  QByteArray messagepart;
+  QHash<QByteArray, QByteArray>::iterator xdelimquote;
 
   for(int i = 0; i < message.size(); i++) {
 
   for(int i = 0; i < message.size(); i++) {
-    messagepart = message[i];
+    messagepart = message.mid(i,1);
     if(i+1 < message.size()) {
       for(xdelimquote = ctcpXDelimDequoteHash.begin(); xdelimquote != ctcpXDelimDequoteHash.end(); ++xdelimquote) {
         if(message.mid(i,2) == xdelimquote.key()) {
     if(i+1 < message.size()) {
       for(xdelimquote = ctcpXDelimDequoteHash.begin(); xdelimquote != ctcpXDelimDequoteHash.end(); ++xdelimquote) {
         if(message.mid(i,2) == xdelimquote.key()) {
@@ -83,64 +84,71 @@ QString CtcpHandler::XdelimDequote(QString message) {
   return dequotedMessage;
 }
 
   return dequotedMessage;
 }
 
-void CtcpHandler::parse(Message::Type messageType, QString prefix, QString target, QString message) {
-  QString ctcp;
+void CtcpHandler::parse(Message::Type messageType, const QString &prefix, const QString &target, const QByteArray &message) {
+  QByteArray ctcp;
   
   //lowlevel message dequote
   
   //lowlevel message dequote
-  QString dequotedMessage = dequote(message);
+  QByteArray dequotedMessage = dequote(message);
 
 
-  CtcpType ctcptype = (messageType == Message::Notice)
+  CtcpType ctcptype = messageType == Message::Notice
     ? CtcpReply
     : CtcpQuery;
     ? CtcpReply
     : CtcpQuery;
+  
+  quint8 flags = (messageType == Message::Notice && !network()->isChannelName(target))
+    ? Message::Redirected
+    : Message::None;
 
 
-  BufferInfo::Type bufferType = typeByTarget(target);
-     
   // extract tagged / extended data
   // extract tagged / extended data
-  while(dequotedMessage.contains(XDELIM)) {
-    if(dequotedMessage.indexOf(XDELIM) > 0)
-      emit displayMsg(messageType, bufferType, target, dequotedMessage.section(XDELIM,0,0), prefix);
-    // messages << dequotedMessage.section(XDELIM,0,0), prefix);
-    ctcp = XdelimDequote(dequotedMessage.section(XDELIM,1,1));
-    dequotedMessage = dequotedMessage.section(XDELIM,2,2);
+  int xdelimPos = -1;
+  int xdelimEndPos = -1;
+  int spacePos = -1;
+  while((xdelimPos = dequotedMessage.indexOf(XDELIM)) != -1) {
+    if(xdelimPos > 0)
+      displayMsg(messageType, target, userDecode(target, dequotedMessage.left(xdelimPos)), prefix, flags);
+
+    xdelimEndPos = dequotedMessage.indexOf(XDELIM, xdelimPos + 1);
+    
+    ctcp = xdelimDequote(dequotedMessage.mid(xdelimPos + 1, xdelimEndPos - xdelimPos - 1));
+    dequotedMessage = dequotedMessage.mid(xdelimEndPos + 1);
     
     //dispatch the ctcp command
     
     //dispatch the ctcp command
-    QString ctcpcmd = ctcp.section(' ', 0, 0);
-    QString ctcpparam = ctcp.section(' ', 1);
+    spacePos = ctcp.indexOf(' ');
+    QString ctcpcmd = userDecode(target, ctcp.left(spacePos));
+    QString ctcpparam = userDecode(target, ctcp.mid(spacePos + 1));
 
     handle(ctcpcmd, Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam));
   }
   
   if(!dequotedMessage.isEmpty())
 
     handle(ctcpcmd, Q_ARG(CtcpType, ctcptype), Q_ARG(QString, prefix), Q_ARG(QString, target), Q_ARG(QString, ctcpparam));
   }
   
   if(!dequotedMessage.isEmpty())
-    emit displayMsg(messageType, bufferType, target, dequotedMessage, prefix);
-
+    displayMsg(messageType, target, userDecode(target, dequotedMessage), prefix, flags);
 }
 
 }
 
-QString CtcpHandler::pack(QString ctcpTag, QString message) {
+QByteArray CtcpHandler::pack(const QByteArray &ctcpTag, const QByteArray &message) {
   return XDELIM + ctcpTag + ' ' + message + XDELIM;
 }
 
 // TODO handle encodings correctly!
   return XDELIM + ctcpTag + ' ' + message + XDELIM;
 }
 
 // TODO handle encodings correctly!
-void CtcpHandler::query(QString bufname, QString ctcpTag, QString message) {
-  QStringList params;
-  params << bufname << pack(ctcpTag, message);
-  emit putCmd("PRIVMSG", serverEncode(params));
+void CtcpHandler::query(const QString &bufname, const QString &ctcpTag, const QString &message) {
+  QList<QByteArray> params;
+  params << serverEncode(bufname) << pack(serverEncode(ctcpTag), userEncode(bufname, message));
+  emit putCmd("PRIVMSG", params);
 }
 
 }
 
-void CtcpHandler::reply(QString bufname, QString ctcpTag, QString message) {
-  QStringList params;
-  params << bufname << pack(ctcpTag, message);
-  emit putCmd("NOTICE", serverEncode(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));
+  emit putCmd("NOTICE", params);
 }
 
 //******************************/
 // CTCP HANDLER
 //******************************/
 }
 
 //******************************/
 // CTCP HANDLER
 //******************************/
-void CtcpHandler::handleAction(CtcpType ctcptype, QString prefix, QString target, QString param) {
+void CtcpHandler::handleAction(CtcpType ctcptype, const QString &prefix, const QString &target, const QString &param) {
   Q_UNUSED(ctcptype)
   emit displayMsg(Message::Action, typeByTarget(target), target, param, prefix);
 }
 
   Q_UNUSED(ctcptype)
   emit displayMsg(Message::Action, typeByTarget(target), target, param, prefix);
 }
 
-void CtcpHandler::handlePing(CtcpType ctcptype, QString prefix, QString target, QString param) {
+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);
   Q_UNUSED(target)
   if(ctcptype == CtcpQuery) {
     reply(nickFromMask(prefix), "PING", param);
@@ -153,7 +161,7 @@ void CtcpHandler::handlePing(CtcpType ctcptype, QString prefix, QString target,
   }
 }
 
   }
 }
 
-void CtcpHandler::handleVersion(CtcpType ctcptype, QString prefix, QString target, QString param) {
+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 :)
   Q_UNUSED(target)
   if(ctcptype == CtcpQuery) {
     // FIXME use real Info about quassel :)
@@ -166,7 +174,7 @@ void CtcpHandler::handleVersion(CtcpType ctcptype, QString prefix, QString targe
   }
 }
 
   }
 }
 
-void CtcpHandler::defaultHandler(QString cmd, CtcpType ctcptype, QString prefix, QString target, QString param) {
+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);
   Q_UNUSED(ctcptype);
   Q_UNUSED(target);
   Q_UNUSED(param);
index 59db076..aa42bf9 100644 (file)
@@ -34,28 +34,26 @@ public:
 
   enum CtcpType {CtcpQuery, CtcpReply};
 
 
   enum CtcpType {CtcpQuery, CtcpReply};
 
-  void parse(Message::Type, QString prefix, QString target, QString message);
+  void parse(Message::Type, const QString &prefix, const QString &target, const QByteArray &message);
 
 
-  QString dequote(QString);
-  QString XdelimDequote(QString);
+  QByteArray dequote(const QByteArray &);
+  QByteArray xdelimDequote(const QByteArray &);
 
 
-  QString pack(QString ctcpTag, QString message);
-  void query(QString bufname, QString ctcpTag, QString message);
-  void reply(QString bufname, QString ctcpTag, QString message);
+  QByteArray pack(const QByteArray &ctcpTag, const QByteArray &message);
+  void query(const QString &bufname, const QString &ctcpTag, const QString &message);
+  void reply(const QString &bufname, const QString &ctcpTag, const QString &message);
 
 public slots:
 
 public slots:
-  void handleAction(CtcpType, QString prefix, QString target, QString param);
-  void handlePing(CtcpType, QString prefix, QString target, QString param);
-  void handleVersion(CtcpType, QString prefix, QString target, QString param);
+  void handleAction(CtcpType, const QString &prefix, const QString &target, const QString &param);
+  void handlePing(CtcpType, const QString &prefix, const QString &target, const QString &param);
+  void handleVersion(CtcpType, const QString &prefix, const QString &target, const QString &param);
 
 
-  void defaultHandler(QString cmd, CtcpType ctcptype, QString prefix, QString target, QString param);
+  void defaultHandler(const QString &cmd, CtcpType ctcptype, const QString &prefix, const QString &target, const QString &param);
 
 private:
 
 private:
-  QString XDELIM;
-  QHash<QString, QString> ctcpMDequoteHash;
-  QHash<QString, QString> ctcpXDelimDequoteHash;
-
-
+  QByteArray XDELIM;
+  QHash<QByteArray, QByteArray> ctcpMDequoteHash;
+  QHash<QByteArray, QByteArray> ctcpXDelimDequoteHash;
 };
 
 
 };
 
 
index 9318f82..f3e6680 100644 (file)
 
 #include <QDebug>
 
 
 #include <QDebug>
 
-IrcServerHandler::IrcServerHandler(NetworkConnection *parent) : BasicHandler(parent) {
-  _whois = false;
+IrcServerHandler::IrcServerHandler(NetworkConnection *parent)
+  : BasicHandler(parent),
+    _whois(false)
+{
 }
 
 IrcServerHandler::~IrcServerHandler() {
 }
 
 IrcServerHandler::~IrcServerHandler() {
@@ -123,19 +125,13 @@ void IrcServerHandler::defaultHandler(QString cmd, const QString &prefix, const
         emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", params.join(" "), prefix);
         break;
       // Server error messages, display them in red. First param will be appended.
         emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", params.join(" "), prefix);
         break;
       // Server error messages, display them in red. First param will be appended.
-      case 401: 
-      {
-       // FIXME needs proper redirection
+      case 401: {
        QString target = params.takeFirst();
        QString target = params.takeFirst();
-       BufferInfo::Type bufferType = network()->isChannelName(target)
-         ? BufferInfo::ChannelBuffer
-         : BufferInfo::QueryBuffer;
-        emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", params.join(" ") + " " + target, prefix);
-        emit displayMsg(Message::Error, bufferType, target, params.join(" ") + " " + target, prefix);
-        break;
+       displayMsg(Message::Error, target, params.join(" ") + " " + target, prefix, Message::Redirected);
+       break;
       }
       }
-      case 402: case 403: case 404: case 406: case 408: case 415: case 421: case 442:
-      { QString channelName = params.takeFirst();
+      case 402: case 403: case 404: case 406: case 408: case 415: case 421: case 442: {
+       QString channelName = params.takeFirst();
         emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", params.join(" ") + " " + channelName, prefix);
         break;
       }
         emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", params.join(" ") + " " + channelName, prefix);
         break;
       }
@@ -257,13 +253,16 @@ void IrcServerHandler::handleNotice(const QString &prefix, const QList<QByteArra
     return;
   }
 
     return;
   }
 
+  QString target = serverDecode(params[0]);
+
+  
   // check if it's only a Server Message or if it's a regular Notice
   if(network()->currentServer().isEmpty() || network()->currentServer() == prefix) {
     emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", serverDecode(params[1]), prefix);
     return;
   }
 
   // check if it's only a Server Message or if it's a regular Notice
   if(network()->currentServer().isEmpty() || network()->currentServer() == prefix) {
     emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", serverDecode(params[1]), prefix);
     return;
   }
 
-  QString target = serverDecode(params[0]);
+
 
   // kick notices to the server buffer if they are directly addressed to us
   if(network()->isMyNick(target))
 
   // kick notices to the server buffer if they are directly addressed to us
   if(network()->isMyNick(target))
@@ -273,7 +272,7 @@ void IrcServerHandler::handleNotice(const QString &prefix, const QList<QByteArra
     ? nickFromMask(prefix)
     : prefix;
 
     ? nickFromMask(prefix)
     : prefix;
 
-  networkConnection()->ctcpHandler()->parse(Message::Notice, sender, target, userDecode(sender, params[1]));
+  networkConnection()->ctcpHandler()->parse(Message::Notice, sender, target, params[1]);
 }
 
 void IrcServerHandler::handlePart(const QString &prefix, const QList<QByteArray> &params) {
 }
 
 void IrcServerHandler::handlePart(const QString &prefix, const QList<QByteArray> &params) {
@@ -316,7 +315,7 @@ void IrcServerHandler::handlePrivmsg(const QString &prefix, const QList<QByteArr
 
   // it's possible to pack multiple privmsgs into one param using ctcp
   // - > we let the ctcpHandler do the work
 
   // it's possible to pack multiple privmsgs into one param using ctcp
   // - > we let the ctcpHandler do the work
-  networkConnection()->ctcpHandler()->parse(Message::Plain, prefix, target, userDecode(ircuser->nick(), msg));
+  networkConnection()->ctcpHandler()->parse(Message::Plain, prefix, target, msg);
 }
 
 void IrcServerHandler::handleQuit(const QString &prefix, const QList<QByteArray> &params) {
 }
 
 void IrcServerHandler::handleQuit(const QString &prefix, const QList<QByteArray> &params) {