From 712b7bdfdfe5d77001669dd1d11a860437dc3849 Mon Sep 17 00:00:00 2001
From: Florent Le Coz <louiz@louiz.org>
Date: Wed, 14 May 2014 21:48:38 +0200
Subject: Correctly handle the usage of ! as a IRC user mode indicator
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since “!” is also the separator between the nickname and the user hostname,
having “!” as the user mode (e.g. !nick!~some@host.bla) would cause the nick
to be empty. Now we skip it if it is a valid user mode indicator.
---
 src/irc/irc_user.cpp |  6 +++---
 src/test.cpp         | 17 +++++++++++++++++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/irc/irc_user.cpp b/src/irc/irc_user.cpp
index 0f1b1ee..8785270 100644
--- a/src/irc/irc_user.cpp
+++ b/src/irc/irc_user.cpp
@@ -7,14 +7,14 @@ IrcUser::IrcUser(const std::string& name,
 {
   if (name.empty())
     return ;
-  const std::string::size_type sep = name.find("!");
   const std::map<char, char>::const_iterator prefix = prefix_to_mode.find(name[0]);
-  const size_t name_begin = prefix == prefix_to_mode.end()? 0: 1;
+  const std::string::size_type name_begin = prefix == prefix_to_mode.end()? 0: 1;
+  const std::string::size_type sep = name.find("!", name_begin);
   if (sep == std::string::npos)
     this->nick = name.substr(name_begin);
   else
     {
-      this->nick = name.substr(name_begin, sep);
+      this->nick = name.substr(name_begin, sep-name_begin);
       this->host = name.substr(sep+1);
     }
   if (prefix != prefix_to_mode.end())
diff --git a/src/test.cpp b/src/test.cpp
index 1056926..f624bc2 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -9,6 +9,7 @@
 #include <config/config.hpp>
 #include <bridge/colors.hpp>
 #include <utils/tolower.hpp>
+#include <irc/irc_user.hpp>
 #include <utils/split.hpp>
 #include <xmpp/jid.hpp>
 #include <irc/iid.hpp>
@@ -122,6 +123,22 @@ int main()
   assert(xml_escape(unescaped) == "&apos;coucou&apos;&lt;cc&gt;/&amp;&quot;gaga&quot;");
   assert(xml_unescape(xml_escape(unescaped)) == unescaped);
 
+  /**
+   * Irc user parsing
+   */
+  const std::map<char, char> prefixes{{'!', 'a'}, {'@', 'o'}};
+
+  IrcUser user1("!nick!~some@host.bla", prefixes);
+  assert(user1.nick == "nick");
+  assert(user1.host == "~some@host.bla");
+  assert(user1.modes.size() == 1);
+  assert(user1.modes.find('a') != user1.modes.end());
+  IrcUser user2("coucou!~other@host.bla", prefixes);
+  assert(user2.nick == "coucou");
+  assert(user2.host == "~other@host.bla");
+  assert(user2.modes.size() == 0);
+  assert(user2.modes.find('a') == user2.modes.end());
+
   /**
    * Colors conversion
    */
-- 
cgit v1.2.3