From: Shane Synan Date: Fri, 19 Feb 2016 08:25:10 +0000 (-0600) Subject: Add support for multi-prefix X-Git-Tag: travis-deploy-test~513^2~1 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=ba1c9e7925671c1393e0ff6b140f68a3dc1fe3cf;ds=sidebyside Add support for multi-prefix Add support for multi-prefix to get a full list of modes in NAMES and WHO replies, updating ircuser objects as appropriate. This enables seeing if an operator (+o) also has voice (+v), etc. In the future, Quassel could show this information in a smart, useful manner. This commit limits synced modes to one for 'NAMES' replies to avoid a warning in older clients. The next commit will address this. See http://ircv3.net/specs/extensions/multi-prefix-3.1.html --- diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index e3ef9457..ae1ebd8e 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -177,6 +177,15 @@ public: */ inline bool useCapUserhostInNames() const { return capEnabled("userhost-in-names"); } + /** + * Gets the status of the multi-prefix capability. + * + * http://ircv3.net/specs/extensions/multi-prefix-3.1.html + * + * @returns True if multi-prefix is enabled, otherwise false + */ + inline bool useCapMultiPrefix() const { return capEnabled("multi-prefix"); } + public slots: virtual void setMyNick(const QString &mynick); diff --git a/src/core/coresessioneventprocessor.cpp b/src/core/coresessioneventprocessor.cpp index ca9b92df..43f44dba 100644 --- a/src/core/coresessioneventprocessor.cpp +++ b/src/core/coresessioneventprocessor.cpp @@ -194,7 +194,8 @@ void CoreSessionEventProcessor::processIrcEventCap(IrcEvent *e) } else if (availableCapPair.at(0).startsWith("away-notify") || availableCapPair.at(0).startsWith("account-notify") || availableCapPair.at(0).startsWith("extended-join") || - availableCapPair.at(0).startsWith("userhost-in-names")) { + availableCapPair.at(0).startsWith("userhost-in-names") || + availableCapPair.at(0).startsWith("multi-prefix")) { // Always request these capabilities if available queueCurrentCap = true; } @@ -918,10 +919,32 @@ 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()) + ircuser->addUserModes(validModes); + } } // Check if channel name has a who in progress. @@ -952,10 +975,27 @@ 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. + // FIXME Only allow one possible mode to avoid a warning in older clients + if (mode.isEmpty()) + mode.append(e->network()->prefixToMode(nick[0])); + //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); }