Merge pull request #193 from mamarley/statusmsg
authorDaniel Albers <daniel@lbe.rs>
Fri, 1 Apr 2016 01:49:49 +0000 (03:49 +0200)
committerDaniel Albers <daniel@lbe.rs>
Fri, 1 Apr 2016 01:51:40 +0000 (03:51 +0200)
Handle STATUSMSG messages

src/common/message.h
src/common/network.cpp
src/common/network.h
src/core/ctcpparser.cpp
src/core/ircparser.cpp

index 402faea..a7fb493 100644 (file)
@@ -61,6 +61,7 @@ public:
         Highlight = 0x02,
         Redirected = 0x04,
         ServerMsg = 0x08,
+        StatusMsg = 0x10,
         Backlog = 0x80
     };
     Q_DECLARE_FLAGS(Flags, Flag)
index 24ce125..54d0366 100644 (file)
@@ -77,6 +77,18 @@ bool Network::isChannelName(const QString &channelname) const
 }
 
 
+bool Network::isStatusMsg(const QString &target) const
+{
+    if (target.isEmpty())
+        return false;
+
+    if (supports("STATUSMSG"))
+        return support("STATUSMSG").contains(target[0]);
+    else
+        return QString("@+").contains(target[0]);
+}
+
+
 NetworkInfo Network::networkInfo() const
 {
     NetworkInfo info;
index 190c62c..e425701 100644 (file)
@@ -132,6 +132,18 @@ public :
 
     bool isChannelName(const QString &channelname) const;
 
+    /**
+     * Checks if the target counts as a STATUSMSG
+     *
+     * Status messages are prefixed with one or more characters from the server-provided STATUSMSG
+     * if available, otherwise "@" and "+" are assumed.  Generally, status messages sent to a
+     * channel are only visible to those with the same or higher permissions, e.g. voiced.
+     *
+     * @param[in] target Name of destination, e.g. a channel or query
+     * @returns True if a STATUSMSG, otherwise false
+     */
+    bool isStatusMsg(const QString &target) const;
+
     inline bool isConnected() const { return _connected; }
     //Network::ConnectionState connectionState() const;
     inline int connectionState() const { return _connectionState; }
index d2da841..f5257bb 100644 (file)
@@ -171,6 +171,27 @@ void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype)
                            ? Message::Redirected
                            : Message::None;
 
+    bool isStatusMsg = false;
+
+    // First remove all statusmsg prefix characters that are not also channel prefix characters.
+    while (e->network()->isStatusMsg(e->target()) && !e->network()->isChannelName(e->target())) {
+        isStatusMsg = true;
+        e->setTarget(e->target().remove(0, 1));
+    }
+
+    // Then continue removing statusmsg characters as long as removing the character will still result in a
+    // valid channel name.  This prevents removing the channel prefix character if said character is in the
+    // overlap between the statusmsg characters and the channel prefix characters.
+    while (e->network()->isStatusMsg(e->target()) && e->network()->isChannelName(e->target().remove(0, 1))) {
+        isStatusMsg = true;
+        e->setTarget(e->target().remove(0, 1));
+    }
+
+    // If any statusmsg characters were removed, Flag the message as a StatusMsg.
+    if (isStatusMsg) {
+        flags |= Message::StatusMsg;
+    }
+
     if (coreSession()->networkConfig()->standardCtcp())
         parseStandard(e, messagetype, dequotedMessage, ctcptype, flags);
     else
index 681346c..dec7b78 100644 (file)
@@ -186,7 +186,7 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent *e)
             QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts);
             QStringList::const_iterator targetIter;
             for (targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) {
-                QString target = net->isChannelName(*targetIter) ? *targetIter : senderNick;
+                QString target = net->isChannelName(*targetIter) || net->isStatusMsg(*targetIter) ? *targetIter : senderNick;
 
                 msg = decrypt(net, target, msg);