X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fctcpparser.cpp;h=3c8a9d004f088cd5db9529d4c2e23d630bac4639;hp=b8ac4b356205df2a6a865e8e473adf438b29b80a;hb=5013eef8eb17221e8f5866977f02e970e30ec0ac;hpb=694f9bfbf7f1af19108461c7e00d133e55082bce diff --git a/src/core/ctcpparser.cpp b/src/core/ctcpparser.cpp index b8ac4b35..3c8a9d00 100644 --- a/src/core/ctcpparser.cpp +++ b/src/core/ctcpparser.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2012 by the Quassel Project * + * Copyright (C) 2005-2016 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -15,14 +15,16 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "ctcpparser.h" +#include "corenetworkconfig.h" #include "coresession.h" #include "ctcpevent.h" #include "messageevent.h" +#include "coreuserinputhandler.h" const QByteArray XDELIM = "\001"; @@ -36,14 +38,24 @@ CtcpParser::CtcpParser(CoreSession *coreSession, QObject *parent) _ctcpMDequoteHash[MQUOTE + 'r'] = QByteArray(1, '\r'); _ctcpMDequoteHash[MQUOTE + MQUOTE] = MQUOTE; - QByteArray XQUOTE = QByteArray("\134"); - _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE; - _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM; + setStandardCtcp(_coreSession->networkConfig()->standardCtcp()); + connect(_coreSession->networkConfig(), SIGNAL(standardCtcpSet(bool)), this, SLOT(setStandardCtcp(bool))); connect(this, SIGNAL(newEvent(Event *)), _coreSession->eventManager(), SLOT(postEvent(Event *))); } +void CtcpParser::setStandardCtcp(bool enabled) +{ + QByteArray XQUOTE = QByteArray("\134"); + if (enabled) + _ctcpXDelimDequoteHash[XQUOTE + XQUOTE] = XQUOTE; + else + _ctcpXDelimDequoteHash.remove(XQUOTE + XQUOTE); + _ctcpXDelimDequoteHash[XQUOTE + QByteArray("a")] = XDELIM; +} + + void CtcpParser::displayMsg(NetworkEvent *event, Message::Type msgType, const QString &msg, const QString &sender, const QString &target, Message::Flags msgFlags) { @@ -69,7 +81,7 @@ QByteArray CtcpParser::lowLevelQuote(const QByteArray &message) QHash::const_iterator quoteIter = quoteHash.constBegin(); while (quoteIter != quoteHash.constEnd()) { quotedMessage.replace(quoteIter.value(), quoteIter.key()); - quoteIter++; + ++quoteIter; } return quotedMessage; } @@ -105,7 +117,7 @@ QByteArray CtcpParser::xdelimQuote(const QByteArray &message) QHash::const_iterator quoteIter = _ctcpXDelimDequoteHash.constBegin(); while (quoteIter != _ctcpXDelimDequoteHash.constEnd()) { quotedMessage.replace(quoteIter.value(), quoteIter.key()); - quoteIter++; + ++quoteIter; } return quotedMessage; } @@ -148,8 +160,6 @@ void CtcpParser::processIrcEventRawPrivmsg(IrcEventRawMessage *event) void CtcpParser::parse(IrcEventRawMessage *e, Message::Type messagetype) { - QByteArray ctcp; - //lowlevel message dequote QByteArray dequotedMessage = lowLevelDequote(e->rawMessage()); @@ -161,6 +171,79 @@ 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; + } + + // 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 + parseSimple(e, messagetype, dequotedMessage, ctcptype, flags); +} + + +// only accept CTCPs in their simplest form, i.e. one ctcp, from start to +// end, no text around it; not as per the 'specs', but makes people happier +void CtcpParser::parseSimple(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags) +{ + if (dequotedMessage.count(XDELIM) != 2 || dequotedMessage[0] != '\001' || dequotedMessage[dequotedMessage.count() -1] != '\001') { + displayMsg(e, messagetype, targetDecode(e, dequotedMessage), e->prefix(), e->target(), flags); + } else { + int spacePos; + QString ctcpcmd, ctcpparam; + + QByteArray ctcp = xdelimDequote(dequotedMessage.mid(1, dequotedMessage.count() - 2)); + spacePos = ctcp.indexOf(' '); + if (spacePos != -1) { + ctcpcmd = targetDecode(e, ctcp.left(spacePos)); + ctcpparam = targetDecode(e, ctcp.mid(spacePos + 1)); + } else { + ctcpcmd = targetDecode(e, ctcp); + ctcpparam = QString(); + } + ctcpcmd = ctcpcmd.toUpper(); + + // we don't want to block /me messages by the CTCP ignore list + if (ctcpcmd == QLatin1String("ACTION") || !coreSession()->ignoreListManager()->ctcpMatch(e->prefix(), e->network()->networkName(), ctcpcmd)) { + QUuid uuid = QUuid::createUuid(); + _replies.insert(uuid, CtcpReply(coreNetwork(e), nickFromMask(e->prefix()))); + CtcpEvent *event = new CtcpEvent(EventManager::CtcpEvent, e->network(), e->prefix(), e->target(), + ctcptype, ctcpcmd, ctcpparam, e->timestamp(), uuid); + emit newEvent(event); + CtcpEvent *flushEvent = new CtcpEvent(EventManager::CtcpEventFlush, e->network(), e->prefix(), e->target(), + ctcptype, "INVALID", QString(), e->timestamp(), uuid); + emit newEvent(flushEvent); + } + } +} + + +void CtcpParser::parseStandard(IrcEventRawMessage *e, Message::Type messagetype, QByteArray dequotedMessage, CtcpEvent::CtcpType ctcptype, Message::Flags flags) +{ + QByteArray ctcp; + QList ctcpEvents; QUuid uuid; // needed to group all replies together @@ -255,9 +338,13 @@ QByteArray CtcpParser::pack(const QByteArray &ctcpTag, const QByteArray &message void CtcpParser::query(CoreNetwork *net, const QString &bufname, const QString &ctcpTag, const QString &message) { - QList params; - params << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, message))); - net->putCmd("PRIVMSG", params); + QString cmd("PRIVMSG"); + + std::function(QString &)> cmdGenerator = [&] (QString &splitMsg) -> QList { + return QList() << net->serverEncode(bufname) << lowLevelQuote(pack(net->serverEncode(ctcpTag), net->userEncode(bufname, splitMsg))); + }; + + net->putCmd(cmd, net->splitMessage(cmd, message, cmdGenerator)); }