Check correct number of params for handle353(), thanks to coekie for noticing
[quassel.git] / src / core / ircserverhandler.cpp
index 9bdb3c6..f466065 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "ircuser.h"
 #include "ircchannel.h"
+#include "logger.h"
 
 #include <QDebug>
 
@@ -47,7 +48,7 @@ IrcServerHandler::~IrcServerHandler() {
 void IrcServerHandler::handleServerMsg(QByteArray msg) {
   try {
     if(msg.isEmpty()) {
-      qWarning() << "Received empty string from server!";
+      quWarning() << "Received empty string from server!";
       return;
     }
 
@@ -67,7 +68,7 @@ void IrcServerHandler::handleServerMsg(QByteArray msg) {
     QList<QByteArray> params = msg.split(' ');
     if(!trailing.isEmpty()) params << trailing;
     if(params.count() < 1) {
-      qWarning() << "Received invalid string from server!";
+      quWarning() << "Received invalid string from server!";
       return;
     }
 
@@ -78,7 +79,7 @@ void IrcServerHandler::handleServerMsg(QByteArray msg) {
       foo.remove(0, 1);
       prefix = foo;
       if(params.count() < 1) {
-        qWarning() << "Received invalid string from server!";
+        quWarning() << "Received invalid string from server!";
         return;
       }
       foo = serverDecode(params.takeFirst());
@@ -91,7 +92,7 @@ void IrcServerHandler::handleServerMsg(QByteArray msg) {
     uint num = cmd.toUInt();
     if(num > 0) {
       if(params.count() == 0) {
-        qWarning() << "Message received from server violates RFC and is ignored!";
+        quWarning() << "Message received from server violates RFC and is ignored!";
         return;
       }
       params.removeFirst();
@@ -108,8 +109,7 @@ void IrcServerHandler::handleServerMsg(QByteArray msg) {
 
 void IrcServerHandler::defaultHandler(QString cmd, const QString &prefix, const QList<QByteArray> &rawparams) {
   // we assume that all this happens in server encoding
-  QStringList params;
-  foreach(QByteArray r, rawparams) params << serverDecode(r);
+  QStringList params = serverDecode(rawparams);
   uint num = cmd.toUInt();
   if(num) {
     // A lot of server messages don't really need their own handler because they don't do much.
@@ -150,7 +150,15 @@ void IrcServerHandler::defaultHandler(QString cmd, const QString &prefix, const
 
       // Everything else will be marked in red, so we can add them somewhere.
       default:
-        emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", cmd + " " + params.join(" "), prefix);
+       if(_whois) {
+         // many nets define their own WHOIS fields. we fetch those not in need of special attention here:
+         emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", "[Whois] " + params.join(" "), prefix);
+       } else {
+         if(networkConnection()->coreSession()->ircListHelper()->requestInProgress(network()->networkId()))
+           networkConnection()->coreSession()->ircListHelper()->reportError(params.join(" "));
+         else
+           emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", cmd + " " + params.join(" "), prefix);
+       }
     }
     //qDebug() << prefix <<":"<<cmd<<params;
   } else {
@@ -208,6 +216,12 @@ void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray>
     emit displayMsg(Message::Mode, BufferInfo::ChannelBuffer, serverDecode(params[0]), serverDecode(params).join(" "), prefix);
 
     IrcChannel *channel = network()->ircChannel(params[0]);
+    if(!channel) {
+      // we received mode information for a channel we're not in. that means probably we've just been kicked out or something like that
+      // anyways: we don't have a place to store the data --> discard the info.
+      return;
+    }
+
     QString modes = params[1];
     bool add = true;
     int paramOffset = 2;
@@ -230,7 +244,7 @@ void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray>
          else
            channel->removeUserMode(ircUser, QString(modes[c]));
        } else {
-         qWarning() << "Received MODE with too few parameters:" << serverDecode(params);
+         quWarning() << "Received MODE with too few parameters:" << serverDecode(params);
        }
        paramOffset++;
       } else {
@@ -241,7 +255,7 @@ void IrcServerHandler::handleMode(const QString &prefix, const QList<QByteArray>
            if(paramOffset < params.count()) {
              value = params[paramOffset];
            } else {
-             qWarning() << "Received MODE with too few parameters:" << serverDecode(params);
+             quWarning() << "Received MODE with too few parameters:" << serverDecode(params);
            }
            paramOffset++;
        }
@@ -290,7 +304,7 @@ void IrcServerHandler::handleNick(const QString &prefix, const QList<QByteArray>
 
   IrcUser *ircuser = network()->updateNickFromMask(prefix);
   if(!ircuser) {
-    qWarning() << "IrcServerHandler::handleNick(): Unknown IrcUser!";
+    quWarning() << "IrcServerHandler::handleNick(): Unknown IrcUser!";
     return;
   }
   QString newnick = serverDecode(params[0]);
@@ -327,7 +341,7 @@ void IrcServerHandler::handlePart(const QString &prefix, const QList<QByteArray>
   IrcUser *ircuser = network()->updateNickFromMask(prefix);
   QString channel = serverDecode(params[0]);
   if(!ircuser) {
-    qWarning() << "IrcServerHandler::handlePart(): Unknown IrcUser!";
+    quWarning() << "IrcServerHandler::handlePart(): Unknown IrcUser!";
     return;
   }
 
@@ -346,18 +360,35 @@ void IrcServerHandler::handlePing(const QString &prefix, const QList<QByteArray>
   putCmd("PONG", params);
 }
 
+void IrcServerHandler::handlePong(const QString &prefix, const QList<QByteArray> &params) {
+  Q_UNUSED(prefix);
+  // the server is supposed to send back what we passed as param. and we send a timestamp
+  // but using quote and whatnought one can send arbitrary pings, so we have to do some sanity checks
+  if(params.count() < 2)
+    return;
+
+  QString timestamp = serverDecode(params[1]);
+  QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz");
+  if(!sendTime.isValid()) {
+    emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", "PONG " + serverDecode(params).join(" "), prefix);
+    return;
+  }
+
+  network()->setLatency(sendTime.msecsTo(QTime::currentTime()) / 2);
+}
+
 void IrcServerHandler::handlePrivmsg(const QString &prefix, const QList<QByteArray> &params) {
   if(!checkParamCount("IrcServerHandler::handlePrivmsg()", params, 1))
     return;
 
   IrcUser *ircuser = network()->updateNickFromMask(prefix);
   if(!ircuser) {
-    qWarning() << "IrcServerHandler::handlePrivmsg(): Unknown IrcUser!";
+    quWarning() << "IrcServerHandler::handlePrivmsg(): Unknown IrcUser!";
     return;
   }
 
   if(params.isEmpty()) {
-    qWarning() << "IrcServerHandler::handlePrivmsg(): received PRIVMSG without target or message from:" << prefix;
+    quWarning() << "IrcServerHandler::handlePrivmsg(): received PRIVMSG without target or message from:" << prefix;
     return;
   }
      
@@ -432,14 +463,16 @@ void IrcServerHandler::handle001(const QString &prefix, const QList<QByteArray>
 void IrcServerHandler::handle005(const QString &prefix, const QList<QByteArray> &params) {
   Q_UNUSED(prefix);
   const int numParams = params.size();
-  if(numParams < 1) {
-    qWarning() << "IrcServerHandler::handle005(): received RPL_ISUPPORT (005) with too few parameters:" << serverDecode(params);
+  if(numParams == 0) {
+    emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Received RPL_ISUPPORT (005) without parameters!"), prefix);
+    return;
   }
 
+  emit displayMsg(Message::Server, BufferInfo::StatusBuffer, "", serverDecode(params).join(" "), prefix);
+
   QString rpl_isupport_suffix = serverDecode(params.last());
-  if(!rpl_isupport_suffix.toLower().contains("supported")) {
-    qWarning() << "Received invalid RPL_ISUPPORT! Suffix is:" << rpl_isupport_suffix << "Excpected: are supported by this server";
-    return;
+  if(!rpl_isupport_suffix.toLower().contains("are supported by this server")) {
+    emit displayMsg(Message::Error, BufferInfo::StatusBuffer, "", tr("Received non RFC compliant RPL_ISUPPORT: this can lead to unexpected behavior!"), prefix);
   }
 
   QString rawSupport;
@@ -763,6 +796,10 @@ void IrcServerHandler::handle324(const QString &prefix, const QList<QByteArray>
 /* RPL_??? - "<channel> <creation time (unix)>" */
 void IrcServerHandler::handle329(const QString &prefix, const QList<QByteArray> &params) {
   Q_UNUSED(prefix);
+  Q_UNUSED(params)
+#ifdef __GNUC__
+#  warning "Implement handle329 (Channel creation time)"
+#endif
   // FIXME implement this... 
 }
 
@@ -773,7 +810,10 @@ void IrcServerHandler::handle331(const QString &prefix, const QList<QByteArray>
     return;
 
   QString channel = serverDecode(params[0]);
-  network()->ircChannel(channel)->setTopic(QString());
+  IrcChannel *chan = network()->ircChannel(channel);
+  if(chan)
+    chan->setTopic(QString());
+
   emit displayMsg(Message::Server, BufferInfo::ChannelBuffer, channel, tr("No topic is set for %1.").arg(channel));
 }
 
@@ -785,7 +825,10 @@ void IrcServerHandler::handle332(const QString &prefix, const QList<QByteArray>
 
   QString channel = serverDecode(params[0]);
   QString topic = channelDecode(channel, params[1]);
-  network()->ircChannel(channel)->setTopic(topic);
+  IrcChannel *chan = network()->ircChannel(channel);
+  if(chan)
+    chan->setTopic(topic);
+
   emit displayMsg(Message::Server, BufferInfo::ChannelBuffer, channel, tr("Topic for %1 is \"%2\"").arg(channel, topic));
 }
 
@@ -827,7 +870,7 @@ void IrcServerHandler::handle352(const QString &prefix, const QList<QByteArray>
 /* RPL_NAMREPLY */
 void IrcServerHandler::handle353(const QString &prefix, const QList<QByteArray> &params) {
   Q_UNUSED(prefix);
-  if(!checkParamCount("IrcServerHandler::handle353()", params, 2))
+  if(!checkParamCount("IrcServerHandler::handle353()", params, 3))
     return;
     
   // param[0] is either "=", "*" or "@" indicating a public, private or secret channel
@@ -836,7 +879,7 @@ void IrcServerHandler::handle353(const QString &prefix, const QList<QByteArray>
 
   IrcChannel *channel = network()->ircChannel(channelname);
   if(!channel) {
-    qWarning() << "IrcServerHandler::handle353(): received unknown target channel:" << channelname;
+    quWarning() << "IrcServerHandler::handle353(): received unknown target channel:" << channelname;
     return;
   }
 
@@ -920,7 +963,7 @@ void IrcServerHandler::tryNextNick(const QString &errnick) {
 
 bool IrcServerHandler::checkParamCount(const QString &methodName, const QList<QByteArray> &params, int minParams) {
   if(params.count() < minParams) {
-    qWarning() << qPrintable(methodName) << "requieres" << minParams << "parameters but received only" << params.count() << serverDecode(params);
+    quWarning() << qPrintable(methodName) << "requires" << minParams << "parameters but received only" << params.count() << serverDecode(params);
     return false;
   } else {
     return true;