From fd718b6209f1ad2bcd199c44c2dae3b0cb0f633b Mon Sep 17 00:00:00 2001 From: Marcus Eggenberger Date: Mon, 14 May 2007 14:43:40 +0000 Subject: [PATCH 1/1] - Bug #20 (RPL_NICKNAMEINUSER) - Fixed Bug in Message Parsing - Added Missing Destructor in ChatWidgetLine - Added userHandlerList to Server (providesUserHandlers()) --- core/server.cpp | 69 +++++++++++++++++++++++++++++--------- core/server.h | 2 ++ gui/channelwidgetinput.cpp | 8 +++-- gui/channelwidgetinput.h | 3 +- 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/core/server.cpp b/core/server.cpp index 89fb0aa9..cc97fde0 100644 --- a/core/server.cpp +++ b/core/server.cpp @@ -28,6 +28,7 @@ Server::Server(QString net) : network(net) { + } Server::~Server() { @@ -161,34 +162,36 @@ void Server::handleServerMsg(QString msg) { QString prefix; QString cmd; QStringList params; + + // check for prefix by checking for a colon as the first char if(msg[0] == ':') { msg.remove(0,1); prefix = msg.section(' ', 0, 0); msg = msg.section(' ', 1); } + + // next string without a whitespace is the command cmd = msg.section(' ', 0, 0).toUpper(); msg = msg.section(' ', 1); + + // get the parameters QString left, trailing; - // RPL_ISUPPORT (005) can contain colons, so don't treat it like the rest of the commands - if(cmd.toUInt() == 5) { - left = msg.remove(QString(":are supported by this server")); - } else { - left = msg.section(':', 0, 0); - trailing = msg.section(':', 1); - } + left = msg.section(" :", 0, 0); + trailing = msg.section(" :", -1, -1); if(!left.isEmpty()) { params << left.split(' ', QString::SkipEmptyParts); } if(!trailing.isEmpty()) { params << trailing; } - // numeric replies usually have our own nick as first param. Remove this! - // BTW, this behavior is not in the RFC. + + // numeric replies have the target as first param (RFC 2812 - 2.4). this is usually our own nick. Remove this! uint num = cmd.toUInt(); - if(num > 1 && params.count() > 0) { // 001 sets our nick, so we shouldn't remove anything - if(params[0] == ownNick) params.removeFirst(); - else qWarning((QString("First param NOT nick: %1:%2 %3").arg(prefix).arg(cmd).arg(params.join(" "))).toAscii()); + if(num > 0) { + Q_ASSERT(params.count() > 0); // Violation to RFC + params.removeFirst(); } + // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-) QString hname = cmd.toLower(); hname[0] = hname[0].toUpper(); @@ -224,7 +227,7 @@ void Server::defaultServerHandler(QString cmd, QString prefix, QStringList param break; } // Server error messages which will be displayed with a colon between the first param and the rest - case 413: case 414: case 423: case 433: case 436: case 441: case 444: case 461: + case 413: case 414: case 423: case 436: case 441: case 444: case 461: case 467: case 471: case 473: case 474: case 475: case 476: case 477: case 478: case 482: { QString p = params.takeFirst(); emit displayMsg(Message::error("", p + ": " + params.join(" "))); @@ -273,6 +276,20 @@ void Server::defaultUserHandler(QString bufname, QString cmd, QString msg) { } +QStringList Server::providesUserHandlers() { + QStringList userHandlers; + for(int i=0; i < metaObject()->methodCount(); i++) { + QString methodSignature(metaObject()->method(i).signature()); + if (methodSignature.startsWith("handleUser")) { + methodSignature = methodSignature.section('(',0,0); // chop the attribute list + methodSignature = methodSignature.mid(10); // strip "handleUser" + userHandlers << methodSignature; + } + } + return userHandlers; +} + + /**********************************************************************************/ /* @@ -507,7 +524,7 @@ void Server::handleServerNick(QString prefix, QStringList params) { void Server::handleServerNotice(QString prefix, QStringList params) { //Message msg(Message::Notice, params[1], prefix); - if(prefix == currentServer) emit displayMsg(Message::server("", params[1], prefix)); + if(currentServer.isEmpty() || prefix == currentServer) emit displayMsg(Message::server("", params[1], prefix)); else emit displayMsg(Message::notice("", params[1], prefix)); } @@ -574,14 +591,15 @@ void Server::handleServerTopic(QString prefix, QStringList params) { /* RPL_WELCOME */ void Server::handleServer001(QString prefix, QStringList params) { + // there should be only one param: "Welcome to the Internet Relay Network !@" currentServer = prefix; - ownNick = params[0]; + ownNick = params[0].section(' ', -1, -1).section('!', 0, 0); VarMap n; n["Channels"] = VarMap(); nicks[ownNick] = n; emit ownNickSet(network, ownNick); emit nickAdded(network, ownNick, VarMap()); - emit displayMsg(Message::server("", params[1], prefix)); + emit displayMsg(Message::server("", params[0], prefix)); // send performlist QStringList performList = networkSettings["Perform"].toString().split( "\n" ); int count = performList.count(); @@ -595,6 +613,7 @@ void Server::handleServer001(QString prefix, QStringList params) { /* RPL_ISUPPORT */ // TODO Complete 005 handling, also use sensible defaults for non-sent stuff void Server::handleServer005(QString prefix, QStringList params) { + params.removeLast(); foreach(QString p, params) { QString key = p.section("=", 0, 0); QString val = p.section("=", 1); @@ -669,6 +688,24 @@ void Server::handleServer353(QString prefix, QStringList params) { } } } + +/* RPL_NICKNAMEINUSER */ +void Server::handleServer433(QString prefix, QStringList params) { + QString errnick = params[0]; + emit displayMsg(Message::error("", tr("Nick %1 is already taken").arg(errnick))); + // if there is a problem while connecting to the server -> we handle it + // TODO rely on another source... + if(currentServer.isEmpty()) { + QStringList desiredNicks = identity["NickList"].toStringList(); + int nextNick = desiredNicks.indexOf(errnick) + 1; + if (desiredNicks.size() > nextNick) { + putCmd("NICK", QStringList(desiredNicks[nextNick])); + } else { + emit displayMsg(Message::error("", "All nicks in nicklist taken... use: /nick to continue")); + } + } +} + /***********************************************************************************/ /* Exception classes for message handling */ diff --git a/core/server.h b/core/server.h index 90763ac7..b2fb2304 100644 --- a/core/server.h +++ b/core/server.h @@ -47,6 +47,7 @@ class Server : public QThread { // serverState state(); bool isConnected() { return socket.state() == QAbstractSocket::ConnectedState; } QString getNetwork() { return network; } + QStringList providesUserHandlers(); public slots: // void setServerOptions(); @@ -127,6 +128,7 @@ class Server : public QThread { void handleServer332(QString, QStringList); // RPL_TOPIC void handleServer333(QString, QStringList); // Topic set by... void handleServer353(QString, QStringList); // RPL_NAMREPLY + void handleServer433(QString, QStringList); // RPL_NICKNAMEINUSER void defaultServerHandler(QString cmd, QString prefix, QStringList params); void defaultUserHandler(QString buf, QString cmd, QString msg); diff --git a/gui/channelwidgetinput.cpp b/gui/channelwidgetinput.cpp index 37ec8f77..813d1c8c 100644 --- a/gui/channelwidgetinput.cpp +++ b/gui/channelwidgetinput.cpp @@ -22,13 +22,15 @@ ChannelWidgetInput::ChannelWidgetInput(QWidget *parent) : QLineEdit(parent) { idx = 0; - //tabMode = false; connect(this, SIGNAL(returnPressed()), this, SLOT(enter())); - TabCompleter *tc = new TabCompleter(this); - tabComplete = tc; + tabComplete = new TabCompleter(this); connect(this, SIGNAL(nickListUpdated(QStringList)), tabComplete, SLOT(updateNickList(QStringList))); } +ChannelWidgetInput::~ChannelWidgetInput() { + delete tabComplete; +} + void ChannelWidgetInput::keyPressEvent(QKeyEvent * event) { if(event->key() == Qt::Key_Tab) { // Tabcomplete diff --git a/gui/channelwidgetinput.h b/gui/channelwidgetinput.h index a901a95f..eb9a9de9 100644 --- a/gui/channelwidgetinput.h +++ b/gui/channelwidgetinput.h @@ -30,7 +30,8 @@ class ChannelWidgetInput : public QLineEdit { public: ChannelWidgetInput(QWidget *parent = 0); - + ~ChannelWidgetInput(); + protected: virtual bool event(QEvent *); virtual void keyPressEvent(QKeyEvent * event); -- 2.20.1