Split messages on newlines as per IRC protocol
[quassel.git] / src / core / coreuserinputhandler.cpp
index a978fe2..ebbaf91 100644 (file)
 #  include "cipher.h"
 #endif
 
+#if QT_VERSION < 0x050000
+// QChar::LineFeed is Qt 5
+static const QChar QCharLF = QChar('\n');
+#else
+static const QChar QCharLF = QChar::LineFeed;
+#endif
+
 CoreUserInputHandler::CoreUserInputHandler(CoreNetwork *parent)
     : CoreBasicHandler(parent)
 {
@@ -437,8 +444,19 @@ void CoreUserInputHandler::handleMe(const BufferInfo &bufferInfo, const QString
     if (bufferInfo.bufferName().isEmpty() || !bufferInfo.acceptsRegularMessages())
         return;  // server buffer
     // FIXME make this a proper event
-    coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), bufferInfo.bufferName(), "ACTION", msg);
-    emit displayMsg(Message::Action, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self);
+
+    // Split apart messages at line feeds.  The IRC protocol uses those to separate commands, so
+    // they need to be split into multiple messages.
+    QStringList messages = msg.split(QCharLF);
+
+    foreach (auto message, messages) {
+        // Handle each separated message independently, ignoring any carriage returns
+        message = message.trimmed();
+        coreNetwork()->coreSession()->ctcpParser()->query(coreNetwork(), bufferInfo.bufferName(),
+                                                          "ACTION", message);
+        emit displayMsg(Message::Action, bufferInfo.type(), bufferInfo.bufferName(), message,
+                        network()->myNick(), Message::Self);
+    }
 }
 
 
@@ -498,11 +516,20 @@ void CoreUserInputHandler::handleNick(const BufferInfo &bufferInfo, const QStrin
 void CoreUserInputHandler::handleNotice(const BufferInfo &bufferInfo, const QString &msg)
 {
     QString bufferName = msg.section(' ', 0, 0);
-    QString payload = msg.section(' ', 1);
     QList<QByteArray> params;
-    params << serverEncode(bufferName) << channelEncode(bufferInfo.bufferName(), payload);
-    emit putCmd("NOTICE", params);
-    emit displayMsg(Message::Notice, typeByTarget(bufferName), bufferName, payload, network()->myNick(), Message::Self);
+    // Split apart messages at line feeds.  The IRC protocol uses those to separate commands, so
+    // they need to be split into multiple messages.
+    QStringList messages = msg.section(' ', 1).split(QCharLF);
+
+    foreach (auto message, messages) {
+        // Handle each separated message independently, ignoring any carriage returns
+        message = message.trimmed();
+        params.clear();
+        params << serverEncode(bufferName) << channelEncode(bufferInfo.bufferName(), message);
+        emit putCmd("NOTICE", params);
+        emit displayMsg(Message::Notice, typeByTarget(bufferName), bufferName, message,
+                        network()->myNick(), Message::Self);
+    }
 }
 
 
@@ -565,12 +592,25 @@ void CoreUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QStri
 {
     Q_UNUSED(bufferInfo)
     QString target = msg.section(' ', 0, 0);
-    QString message = msg.section(' ', 1);
-    if (message.isEmpty())
-        emit displayMsg(Message::Server, BufferInfo::QueryBuffer, target, tr("Starting query with %1").arg(target), network()->myNick(), Message::Self);
-    else
-        emit displayMsg(Message::Plain, BufferInfo::QueryBuffer, target, message, network()->myNick(), Message::Self);
-    handleMsg(bufferInfo, msg);
+    // Split apart messages at line feeds.  The IRC protocol uses those to separate commands, so
+    // they need to be split into multiple messages.
+    QStringList messages = msg.section(' ', 1).split(QCharLF);
+
+    foreach (auto message, messages) {
+        // Handle each separated message independently, ignoring any carriage returns
+        message = message.trimmed();
+        if (message.isEmpty()) {
+            emit displayMsg(Message::Server, BufferInfo::QueryBuffer, target,
+                            tr("Starting query with %1").arg(target), network()->myNick(),
+                            Message::Self);
+            // handleMsg is a no-op if message is empty
+        } else {
+            emit displayMsg(Message::Plain, BufferInfo::QueryBuffer, target, message,
+                            network()->myNick(), Message::Self);
+            // handleMsg needs the target specified at the beginning of the message
+            handleMsg(bufferInfo, target + " " + message);
+        }
+    }
 }
 
 
@@ -604,12 +644,22 @@ void CoreUserInputHandler::handleSay(const BufferInfo &bufferInfo, const QString
         return channelEncode(target, message);
     };
 
+    // Split apart messages at line feeds.  The IRC protocol uses those to separate commands, so
+    // they need to be split into multiple messages.
+    QStringList messages = msg.split(QCharLF);
+
+    foreach (auto message, messages) {
+        // Handle each separated message independently, ignoring any carriage returns
+        message = message.trimmed();
 #ifdef HAVE_QCA2
-    putPrivmsg(bufferInfo.bufferName(), msg, encodeFunc, network()->cipher(bufferInfo.bufferName()));
+        putPrivmsg(bufferInfo.bufferName(), message, encodeFunc,
+                   network()->cipher(bufferInfo.bufferName()));
 #else
-    putPrivmsg(bufferInfo.bufferName(), msg, encodeFunc);
+        putPrivmsg(bufferInfo.bufferName(), message, encodeFunc);
 #endif
-    emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self);
+        emit displayMsg(Message::Plain, bufferInfo.type(), bufferInfo.bufferName(), message,
+                        network()->myNick(), Message::Self);
+    }
 }