From fa2e185ecffa83feca93577a2f8348d554e61f96 Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Sat, 27 Aug 2016 17:28:36 -0500 Subject: [PATCH] Add support for self messages Check if the incoming message sender is our own nick. If so, treat as if sent by the core itself. Message decryption is still tried in case the user manually set up identical keys on different clients, but key negotiation isn't allowed with self-messages (for it wouldn't make sense). Carry over the "Self" flag from EventManager to Message, so incoming self-messages can be processed and stored as if sent by the client. This lays some of the groundwork for IRCv3 'echo-message'. For example, if the core's nick is 'quasseluser': :quasseluser!ex@example.com PRIVMSG dcircuit :hi ...is handled as if 'quasseluser' had sent 'hi' to nick 'dcircuit'. See http://ircv3.net/specs/extensions/echo-message-3.2.html --- src/core/ctcpparser.cpp | 5 +++++ src/core/ircparser.cpp | 43 +++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/core/ctcpparser.cpp b/src/core/ctcpparser.cpp index 2231df6d..3c8a9d00 100644 --- a/src/core/ctcpparser.cpp +++ b/src/core/ctcpparser.cpp @@ -192,6 +192,11 @@ void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype) flags |= Message::StatusMsg; } + // For self-messages, pass the flag on to the message, too + if (e->testFlag(EventManager::Self)) { + flags |= Message::Self; + } + if (coreSession()->networkConfig()->standardCtcp()) parseStandard(e, messagetype, dequotedMessage, ctcptype, flags); else diff --git a/src/core/ircparser.cpp b/src/core/ircparser.cpp index 44b4b523..bb77ad1c 100644 --- a/src/core/ircparser.cpp +++ b/src/core/ircparser.cpp @@ -181,16 +181,29 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent *e) if (checkParamCount(cmd, params, 1)) { QString senderNick = nickFromMask(prefix); net->updateNickFromMask(prefix); + // Check if the sender is our own nick. If so, treat message as if sent by ourself. + // See http://ircv3.net/specs/extensions/echo-message-3.2.html + // Cache the result to avoid multiple redundant comparisons + bool isSelfMessage = net->isMyNick(senderNick); + QByteArray msg = params.count() < 2 ? QByteArray() : params.at(1); 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) || net->isStatusMsg(*targetIter) ? *targetIter : senderNick; + // For self-messages, keep the target, don't set it to the senderNick + QString target = net->isChannelName(*targetIter) || net->isStatusMsg(*targetIter) || isSelfMessage ? *targetIter : senderNick; + // Note: self-messages could be encrypted with a different key. If issues arise, + // consider including this within an if (!isSelfMessage) block msg = decrypt(net, target, msg); - events << new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg, net, msg, prefix, target, e->timestamp()); + IrcEventRawMessage *rawMessage = new IrcEventRawMessage(EventManager::IrcEventRawPrivmsg, net, msg, prefix, target, e->timestamp()); + if (isSelfMessage) { + // Self-messages need processed differently, tag as such via flag. + rawMessage->setFlag(EventManager::Self); + } + events << rawMessage; } } break; @@ -199,6 +212,11 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent *e) defaultHandling = false; if (checkParamCount(cmd, params, 2)) { + // Check if the sender is our own nick. If so, treat message as if sent by ourself. + // See http://ircv3.net/specs/extensions/echo-message-3.2.html + // Cache the result to avoid multiple redundant comparisons + bool isSelfMessage = net->isMyNick(nickFromMask(prefix)); + QStringList targets = net->serverDecode(params.at(0)).split(',', QString::SkipEmptyParts); QStringList::const_iterator targetIter; for (targetIter = targets.constBegin(); targetIter != targets.constEnd(); ++targetIter) { @@ -227,21 +245,34 @@ void IrcParser::processNetworkIncoming(NetworkDataEvent *e) else { if (!target.isEmpty() && net->prefixes().contains(target.at(0))) target = target.mid(1); + if (!net->isChannelName(target)) { - target = nickFromMask(prefix); + // For self-messages, keep the target, don't set it to the sender prefix + if (!isSelfMessage) { + target = nickFromMask(prefix); + } net->updateNickFromMask(prefix); } } #ifdef HAVE_QCA2 // Handle DH1080 key exchange - if (params[1].startsWith("DH1080_INIT") && !net->isChannelName(target)) { + // Don't allow key exchange in channels, and don't allow it for self-messages. + bool keyExchangeAllowed = (!net->isChannelName(target) && !isSelfMessage); + if (params[1].startsWith("DH1080_INIT") && keyExchangeAllowed) { events << new KeyEvent(EventManager::KeyEvent, net, prefix, target, KeyEvent::Init, params[1].mid(12)); - } else if (params[1].startsWith("DH1080_FINISH") && !net->isChannelName(target)) { + } else if (params[1].startsWith("DH1080_FINISH") && keyExchangeAllowed) { events << new KeyEvent(EventManager::KeyEvent, net, prefix, target, KeyEvent::Finish, params[1].mid(14)); } else #endif - events << new IrcEventRawMessage(EventManager::IrcEventRawNotice, net, params[1], prefix, target, e->timestamp()); + { + IrcEventRawMessage *rawMessage = new IrcEventRawMessage(EventManager::IrcEventRawNotice, net, params[1], prefix, target, e->timestamp()); + if (isSelfMessage) { + // Self-messages need processed differently, tag as such via flag. + rawMessage->setFlag(EventManager::Self); + } + events << rawMessage; + } } } break; -- 2.20.1