X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fcoresessioneventprocessor.cpp;h=71619ef1c1767e4e720c22c204c9a59471e4ed09;hp=0cee2444f6ca85c3a0d7939a958f9020d941eb3e;hb=620cd1aa35e05099b3f84400dd33afc207c98244;hpb=9c59843b54202a69f4c01171b28bf79b26c27975 diff --git a/src/core/coresessioneventprocessor.cpp b/src/core/coresessioneventprocessor.cpp index 0cee2444..71619ef1 100644 --- a/src/core/coresessioneventprocessor.cpp +++ b/src/core/coresessioneventprocessor.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 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 * @@ -193,7 +193,9 @@ void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) queueCurrentCap = true; } else if (availableCapPair.at(0).startsWith("away-notify") || availableCapPair.at(0).startsWith("account-notify") || - availableCapPair.at(0).startsWith("extended-join")) { + availableCapPair.at(0).startsWith("extended-join") || + availableCapPair.at(0).startsWith("userhost-in-names") || + availableCapPair.at(0).startsWith("multi-prefix")) { // Always request these capabilities if available queueCurrentCap = true; } @@ -917,10 +919,46 @@ void CoreSessionEventProcessor::processIrcEvent352(IrcEvent *e) ircuser->setUser(e->params()[1]); ircuser->setHost(e->params()[2]); - bool away = e->params()[5].startsWith("G"); + bool away = e->params()[5].contains("G", Qt::CaseInsensitive); ircuser->setAway(away); ircuser->setServer(e->params()[3]); ircuser->setRealName(e->params().last().section(" ", 1)); + + if (coreNetwork(e)->useCapMultiPrefix()) { + // If multi-prefix is enabled, all modes will be sent in WHO replies. + // :kenny.chatspike.net 352 guest #test grawity broken.symlink *.chatspike.net grawity H@%+ :0 Mantas M. + // See: http://ircv3.net/specs/extensions/multi-prefix-3.1.html + QString uncheckedModes = e->params()[5]; + QString validModes = QString(); + while (!uncheckedModes.isEmpty()) { + // Mode found in 1 left-most character, add it to the list + if (e->network()->prefixes().contains(uncheckedModes[0])) { + validModes.append(e->network()->prefixToMode(uncheckedModes[0])); + } + // Remove this mode from the list of unchecked modes + uncheckedModes = uncheckedModes.remove(0, 1); + } + + // Some IRC servers decide to not follow the spec, returning only -some- of the user + // modes in WHO despite listing them all in NAMES. For now, assume it can only add + // and not take away. *sigh* + if (!validModes.isEmpty()) { + if (channel != "*") { + // Channel-specific modes received, apply to given channel only + IrcChannel *ircChan = e->network()->ircChannel(channel); + if (ircChan) { + // Do one mode at a time + // TODO Better way of syncing this without breaking protocol? + for (int i = 0; i < validModes.count(); ++i) { + ircChan->addUserMode(ircuser, validModes.at(i)); + } + } + } else { + // Modes apply to the user everywhere + ircuser->addUserModes(validModes); + } + } + } } // Check if channel name has a who in progress. @@ -951,14 +989,35 @@ void CoreSessionEventProcessor::processIrcEvent353(IrcEvent *e) QStringList nicks; QStringList modes; + // Cache result of multi-prefix to avoid unneeded casts and lookups with each iteration. + bool _useCapMultiPrefix = coreNetwork(e)->useCapMultiPrefix(); + foreach(QString nick, e->params()[2].split(' ', QString::SkipEmptyParts)) { QString mode; - if (e->network()->prefixes().contains(nick[0])) { + if (_useCapMultiPrefix) { + // If multi-prefix is enabled, all modes will be sent in NAMES replies. + // :hades.arpa 353 guest = #tethys :~&@%+aji &@Attila @+alyx +KindOne Argure + // See: http://ircv3.net/specs/extensions/multi-prefix-3.1.html + while (e->network()->prefixes().contains(nick[0])) { + // Mode found in 1 left-most character, add it to the list. + // Note: sending multiple modes may cause a warning in older clients. + // In testing, the clients still seemed to function fine. + mode.append(e->network()->prefixToMode(nick[0])); + // Remove this mode from the nick + nick = nick.remove(0, 1); + } + } else if (e->network()->prefixes().contains(nick[0])) { + // Multi-prefix is disabled and a mode prefix was found. mode = e->network()->prefixToMode(nick[0]); nick = nick.mid(1); } + // If userhost-in-names capability is enabled, the following will be + // in the form "nick!user@host" rather than "nick". This works without + // special handling as the following use nickFromHost() as needed. + // See: http://ircv3.net/specs/extensions/userhost-in-names-3.2.html + nicks << nick; modes << mode; } @@ -1220,7 +1279,7 @@ void CoreSessionEventProcessor::handleCtcpDcc(CtcpEvent *e) } // TODO: check if target is the right thing to use for the partner - CoreTransfer *transfer = new CoreTransfer(Transfer::Receive, e->target(), filename, address, port, size, this); + CoreTransfer *transfer = new CoreTransfer(Transfer::Direction::Receive, e->target(), filename, address, port, size, this); coreSession()->signalProxy()->synchronize(transfer); coreSession()->transferManager()->addTransfer(transfer); } @@ -1247,5 +1306,5 @@ void CoreSessionEventProcessor::handleCtcpTime(CtcpEvent *e) void CoreSessionEventProcessor::handleCtcpVersion(CtcpEvent *e) { e->setReply(QString("Quassel IRC %1 (built on %2) -- http://www.quassel-irc.org") - .arg(Quassel::buildInfo().plainVersionString).arg(Quassel::buildInfo().buildDate)); + .arg(Quassel::buildInfo().plainVersionString).arg(Quassel::buildInfo().commitDate)); }