modernize: Use raw string literals instead of escaped strings
[quassel.git] / src / common / aliasmanager.cpp
index cd21f99..356cd32 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
 /***************************************************************************
- *   Copyright (C) 2005-2015 by the Quassel Project                        *
+ *   Copyright (C) 2005-2018 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
@@ -24,7 +24,6 @@
 #include "aliasmanager.h"
 #include "network.h"
 
 #include "aliasmanager.h"
 #include "network.h"
 
-INIT_SYNCABLE_OBJECT(AliasManager)
 AliasManager &AliasManager::operator=(const AliasManager &other)
 {
     if (this == &other)
 AliasManager &AliasManager::operator=(const AliasManager &other)
 {
     if (this == &other)
@@ -128,11 +127,14 @@ void AliasManager::processInput(const BufferInfo &info, const QString &msg_, Com
     QString msg = msg_;
 
     // leading slashes indicate there's a command to call unless there is another one in the first section (like a path /proc/cpuinfo)
     QString msg = msg_;
 
     // leading slashes indicate there's a command to call unless there is another one in the first section (like a path /proc/cpuinfo)
+    // For those habitally tied to irssi, "/ " also makes the rest of the line a literal message
     int secondSlashPos = msg.indexOf('/', 1);
     int firstSpacePos = msg.indexOf(' ');
     int secondSlashPos = msg.indexOf('/', 1);
     int firstSpacePos = msg.indexOf(' ');
-    if (!msg.startsWith('/') || (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) {
+    if (!msg.startsWith('/') || firstSpacePos == 1 || (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) {
         if (msg.startsWith("//"))
         if (msg.startsWith("//"))
-            msg.remove(0, 1);  // //asdf is transformed to /asdf
+            msg.remove(0, 1);  // "//asdf" is transformed to "/asdf"
+        else if (msg.startsWith("/ "))
+            msg.remove(0, 2);  // "/ /asdf" is transformed to "/asdf"
         msg.prepend("/SAY "); // make sure we only send proper commands to the core
     }
     else {
         msg.prepend("/SAY "); // make sure we only send proper commands to the core
     }
     else {
@@ -158,7 +160,7 @@ void AliasManager::expand(const QString &alias, const BufferInfo &bufferInfo, co
         return;
     }
 
         return;
     }
 
-    QRegExp paramRangeR("\\$(\\d+)\\.\\.(\\d*)");
+    QRegExp paramRangeR(R"(\$(\d+)\.\.(\d*))");
     QStringList commands = alias.split(QRegExp("; ?"));
     QStringList params = msg.split(' ');
     QStringList expandedCommands;
     QStringList commands = alias.split(QRegExp("; ?"));
     QStringList params = msg.split(' ');
     QStringList expandedCommands;
@@ -184,8 +186,43 @@ void AliasManager::expand(const QString &alias, const BufferInfo &bufferInfo, co
         }
 
         for (int j = params.count(); j > 0; j--) {
         }
 
         for (int j = params.count(); j > 0; j--) {
+            // Find the referenced IRC user...
             IrcUser *ircUser = net->ircUser(params[j - 1]);
             IrcUser *ircUser = net->ircUser(params[j - 1]);
-            command = command.replace(QString("$%1:hostname").arg(j), ircUser ? ircUser->host() : QString("*"));
+            // ...and replace components, using short-circuit evaluation as ircUser might be null
+
+            // Account, or "*" if blank/nonexistent/logged out
+            command = command.replace(
+                        QString("$%1:account").arg(j),
+                        (ircUser && !ircUser->account().isEmpty()) ? ircUser->account()
+                                                                   : QString("*"));
+
+            // Hostname, or "*" if blank/nonexistent
+            command = command.replace(
+                        QString("$%1:hostname").arg(j),
+                        (ircUser && !ircUser->host().isEmpty()) ? ircUser->host() : QString("*"));
+
+            // Identd
+            // Ident if verified, or "*" if blank/unknown/unverified (prefixed with "~")
+            //
+            // Most IRC daemons have the option to prefix an ident with "~" if it could not be
+            // verified via an identity daemon such as oidentd.  In these cases, it can be handy to
+            // have a way to ban via ident if verified, or all idents if not verified.  If the
+            // server does not verify idents, it usually won't add "~".
+            //
+            // Identd must be replaced before ident to avoid being treated as "$i:ident" + "d"
+            command = command.replace(
+                        QString("$%1:identd").arg(j),
+                        (ircUser && !ircUser->user().isEmpty()
+                         && !ircUser->user().startsWith("~"))
+                        ? ircUser->user() : QString("*"));
+
+            // Ident, or "*" if blank/nonexistent
+            command = command.replace(
+                        QString("$%1:ident").arg(j),
+                        (ircUser && !ircUser->user().isEmpty()) ? ircUser->user() : QString("*"));
+
+            // Nickname
+            // Must be replaced last to avoid interferring with more specific aliases
             command = command.replace(QString("$%1").arg(j), params[j - 1]);
         }
         command = command.replace("$0", msg);
             command = command.replace(QString("$%1").arg(j), params[j - 1]);
         }
         command = command.replace("$0", msg);