You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
konversation/konversation/src/inputfilter.cpp

1986 lines
79 KiB

/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
/*
Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
Copyright (C) 2004 Peter Simonsson <psn@linux.se>
Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
*/
#include "inputfilter.h"
#include "server.h"
#include "replycodes.h"
#include "konversationapplication.h"
#include "commit.h"
#include "version.h"
#include "query.h"
#include "channel.h"
#include "statuspanel.h"
#include "common.h"
#include "notificationhandler.h"
#include <tqdatastream.h>
#include <tqstringlist.h>
#include <tqdatetime.h>
#include <tqregexp.h>
#include <klocale.h>
#include <tdeversion.h>
#include <kstringhandler.h>
#include <config.h>
#include <kdebug.h>
#include <kresolver.h>
InputFilter::InputFilter()
{
m_connecting = false;
}
InputFilter::~InputFilter()
{
}
void InputFilter::setServer(Server* newServer)
{
server=newServer;
}
void InputFilter::parseLine(const TQString& a_newLine)
{
TQString trailing;
TQString newLine(a_newLine);
// Remove white spaces at the end and beginning
newLine = newLine.stripWhiteSpace();
// Find end of middle parameter list
int pos = newLine.find(" :");
// Was there a trailing parameter?
if(pos != -1)
{
// Copy trailing parameter
trailing = newLine.mid(pos + 2);
// Cut trailing parameter from string
newLine = newLine.left(pos);
}
// Remove all unnecessary white spaces to make parsing easier
newLine = newLine.simplifyWhiteSpace();
TQString prefix;
// Do we have a prefix?
if(newLine[0] == ':')
{
// Find end of prefix
pos = newLine.find(' ');
// Copy prefix
prefix = newLine.mid(1, pos - 1);
// Remove prefix from line
newLine = newLine.mid(pos + 1);
}
// Find end of command
pos = newLine.find(' ');
// Copy command (all lowercase to make parsing easier)
TQString command = newLine.left(pos).lower();
// Are there parameters left in the string?
TQStringList parameterList;
if(pos != -1)
{
// Cut out the command
newLine = newLine.mid(pos + 1);
// The rest of the string will be the parameter list
parameterList = TQStringList::split(" ", newLine);
}
Q_ASSERT(server);
// Server command, if no "!" was found in prefix
if((prefix.find('!') == -1) && (prefix != server->getNickname()))
{
parseServerCommand(prefix, command, parameterList, trailing);
}
else
{
parseClientCommand(prefix, command, parameterList, trailing);
}
}
void InputFilter::parseClientCommand(const TQString &prefix, const TQString &command, const TQStringList &parameterList, const TQString &_trailing)
{
KonversationApplication* konv_app = static_cast<KonversationApplication *>(TDEApplication::kApplication());
Q_ASSERT(konv_app);
Q_ASSERT(server);
// Extract nickname from prefix
int pos = prefix.find("!");
TQString sourceNick = prefix.left(pos);
TQString sourceHostmask = prefix.mid(pos + 1);
// remember hostmask for this nick, it could have changed
server->addHostmaskToNick(sourceNick,sourceHostmask);
TQString trailing = _trailing;
if(command=="privmsg")
{
bool isChan = isAChannel(parameterList[0]);
// CTCP message?
if(server->identifyMsg() && (trailing.at(0) == '+' || trailing.at(0) == '-')) {
trailing = trailing.mid(1);
}
if(trailing.at(0)==TQChar(0x01))
{
// cut out the CTCP command
TQString ctcp = trailing.mid(1,trailing.find(1,1)-1);
TQString ctcpCommand=ctcp.left(ctcp.find(" ")).lower();
TQString ctcpArgument=ctcp.mid(ctcp.find(" ")+1);
ctcpArgument=static_cast<KonversationApplication*>(kapp)->doAutoreplace(ctcpArgument,false);
// If it was a ctcp action, build an action string
if(ctcpCommand=="action" && isChan)
{
if(!isIgnore(prefix,Ignore::Channel))
{
Channel* channel = server->getChannelByName( parameterList[0] );
if(!channel) {
kdError() << "Didn't find the channel " << parameterList[0] << endl;
return;
}
channel->appendAction(sourceNick,ctcpArgument);
if(sourceNick != server->getNickname())
{
if(ctcpArgument.lower().find(TQRegExp("(^|[^\\d\\w])"
+ TQRegExp::escape(server->loweredNickname())
+ "([^\\d\\w]|$)")) !=-1 )
{
konv_app->notificationHandler()->nick(channel, sourceNick, ctcpArgument);
}
else
{
konv_app->notificationHandler()->message(channel, sourceNick, ctcpArgument);
}
}
}
}
// If it was a ctcp action, build an action string
else if(ctcpCommand=="action" && !isChan)
{
// Check if we ignore queries from this nick
if(!isIgnore(prefix,Ignore::Query))
{
NickInfoPtr nickinfo = server->obtainNickInfo(sourceNick);
nickinfo->setHostmask(sourceHostmask);
// create new query (server will check for dupes)
query = server->addQuery(nickinfo, false /* we didn't initiate this*/ );
// send action to query
query->appendAction(sourceNick,ctcpArgument);
if(sourceNick != server->getNickname() && query)
{
konv_app->notificationHandler()->queryMessage(query, sourceNick, ctcpArgument);
}
}
}
// Answer ping requests
else if(ctcpCommand=="ping")
{
if(!isIgnore(prefix,Ignore::CTCP))
{
if(isChan)
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-PING request from %1 to channel %2, sending answer.")
.arg(sourceNick).arg(parameterList[0])
);
}
else
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-%1 request from %2, sending answer.")
.arg("PING").arg(sourceNick)
);
}
server->ctcpReply(sourceNick,TQString("PING %1").arg(ctcpArgument));
}
}
// Maybe it was a version request, so act appropriately
else if(ctcpCommand=="version")
{
if(!isIgnore(prefix,Ignore::CTCP))
{
if (isChan)
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received Version request from %1 to channel %2.")
.arg(sourceNick).arg(parameterList[0])
);
}
else
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received Version request from %1.")
.arg(sourceNick)
);
}
TQString reply;
if(Preferences::customVersionReplyEnabled())
{
reply = Preferences::customVersionReply().stripWhiteSpace();
}
else
{
// Do not internationalize the below version string
reply = TQString("Konversation %1 (C) 2002-2008 by the Konversation team")
.arg(TQString(KONVI_VERSION));
}
server->ctcpReply(sourceNick,"VERSION "+reply);
}
}
// DCC request?
else if(ctcpCommand=="dcc" && !isChan)
{
if(!isIgnore(prefix,Ignore::DCC))
{
// Extract DCC type and argument list
TQString dccType=ctcpArgument.lower().section(' ',0,0);
// Support file names with spaces
TQString dccArguments = ctcpArgument.mid(ctcpArgument.find(" ")+1);
TQStringList dccArgumentList;
if ((dccArguments.contains('\"') >= 2) && (dccArguments.startsWith("\""))) {
int lastQuotePos = dccArguments.findRev("\"");
if (dccArguments[lastQuotePos+1] == ' ') {
TQString fileName = dccArguments.mid(1, lastQuotePos-1);
dccArguments = dccArguments.mid(lastQuotePos+2);
dccArgumentList.append(fileName);
}
}
dccArgumentList += TQStringList::split(' ', dccArguments);
if(dccType=="send")
{
if(dccArgumentList.count()==4)
{
// incoming file
konv_app->notificationHandler()->dccIncoming(server->getStatusView(), sourceNick);
emit addDccGet(sourceNick,dccArgumentList);
}
else if(dccArgumentList.count()==5)
{
if(dccArgumentList[2]=="0")
{
// incoming file (Reverse DCC)
konv_app->notificationHandler()->dccIncoming(server->getStatusView(), sourceNick);
emit addDccGet(sourceNick,dccArgumentList);
}
else
{
// the receiver accepted the offer for Reverse DCC
emit startReverseDccSendTransfer(sourceNick,dccArgumentList);
}
}
else
{
server->appendMessageToFrontmost(i18n("DCC"),
i18n("Received invalid DCC SEND request from %1.")
.arg(sourceNick)
);
}
}
else if(dccType=="accept")
{
// resume request was accepted
if(dccArgumentList.count()==3)
{
emit resumeDccGetTransfer(sourceNick,dccArgumentList);
}
else
{
server->appendMessageToFrontmost(i18n("DCC"),
i18n("Received invalid DCC ACCEPT request from %1.")
.arg(sourceNick)
);
}
}
// Remote client wants our sent file resumed
else if(dccType=="resume")
{
if(dccArgumentList.count()==3)
{
emit resumeDccSendTransfer(sourceNick,dccArgumentList);
}
else
{
server->appendMessageToFrontmost(i18n("DCC"),
i18n("Received invalid DCC RESUME request from %1.")
.arg(sourceNick)
);
}
}
else if(dccType=="chat")
{
if(dccArgumentList.count()==3)
{
// will be connected via Server to KonversationMainWindow::addDccChat()
emit addDccChat(server->getNickname(),sourceNick,dccArgumentList,false);
}
else
{
server->appendMessageToFrontmost(i18n("DCC"),
i18n("Received invalid DCC CHAT request from %1.")
.arg(sourceNick)
);
}
}
else
{
server->appendMessageToFrontmost(i18n("DCC"),
i18n("Unknown DCC command %1 received from %2.")
.arg(ctcpArgument).arg(sourceNick)
);
}
}
}
else if (ctcpCommand=="clientinfo" && !isChan)
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-%1 request from %2, sending answer.")
.arg("CLIENTINFO").arg(sourceNick)
);
server->ctcpReply(sourceNick,TQString("CLIENTINFO ACTION CLIENTINFO DCC PING TIME VERSION"));
}
else if(ctcpCommand=="time" && !isChan)
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-%1 request from %2, sending answer.")
.arg("TIME").arg(sourceNick)
);
server->ctcpReply(sourceNick,TQString("TIME ")+TQDateTime::currentDateTime().toString());
}
// No known CTCP request, give a general message
else
{
if(!isIgnore(prefix,Ignore::CTCP))
{
if (isChan)
server->appendServerMessageToChannel(
parameterList[0],
"CTCP",
i18n("Received unknown CTCP-%1 request from %2 to Channel %3.")
.arg(ctcp).arg(sourceNick).arg(parameterList[0])
);
else
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received unknown CTCP-%1 request from %2.")
.arg(ctcp).arg(sourceNick)
);
}
}
}
// No CTCP, so it's an ordinary channel or query message
else
{
parsePrivMsg (prefix, parameterList, trailing);
}
}
else if(command=="notice")
{
if(!isIgnore(prefix,Ignore::Notice))
{
// Channel notice?
if(isAChannel(parameterList[0]))
{
if(server->identifyMsg())
{
trailing = trailing.mid(1);
}
server->appendServerMessageToChannel(parameterList[0], i18n("Notice"),
i18n("-%1 to %2- %3")
.arg(sourceNick).arg(parameterList[0]).arg(trailing)
);
}
// Private notice
else
{
// Was this a CTCP reply?
if(trailing.at(0)==TQChar(0x01))
{
// cut 0x01 bytes from trailing string
TQString ctcp(trailing.mid(1,trailing.length()-2));
TQString replyReason(ctcp.section(' ',0,0));
TQString reply(ctcp.section(' ',1));
// pong reply, calculate turnaround time
if(replyReason.lower()=="ping")
{
int dateArrived=TQDateTime::currentDateTime().toTime_t();
int dateSent=reply.toInt();
int time = dateArrived-dateSent;
TQString unit = "seconds";
if (time==1)
unit = "second";
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-PING reply from %1: %2 %3.")
.arg(sourceNick)
.arg(time)
.arg(unit)
);
}
// all other ctcp replies get a general message
else
{
server->appendMessageToFrontmost(i18n("CTCP"),
i18n("Received CTCP-%1 reply from %2: %3.")
.arg(replyReason).arg(sourceNick).arg(reply)
);
}
}
// No, so it was a normal notice
else
{
// Nickserv
if (trailing.startsWith("If this is your nick"))
{
// Identify command if specified
server->registerWithServices();
}
else if (server->identifyMsg())
trailing = trailing.mid(1);
if(trailing.lower() == "password accepted - you are now recognized"
|| trailing.lower() == "you have already identified")
{
NickInfoPtr nickInfo = server->getNickInfo(server->getNickname());
if(nickInfo)
nickInfo->setIdentified(true);
}
server->appendMessageToFrontmost(i18n("Notice"), i18n("-%1- %2").arg(sourceNick).arg(trailing));
}
}
}
}
else if(command=="join")
{
TQString channelName(trailing);
// Sometimes JOIN comes without ":" in front of the channel name
if(channelName.isEmpty())
channelName=parameterList[parameterList.count()-1];
// Did we join the channel, or was it someone else?
if(server->isNickname(sourceNick))
{
/*
TQString key;
// TODO: Try to remember channel keys for autojoins and manual joins, so
// we can get %k to work
if(channelName.find(' ')!=-1)
{
key=channelName.section(' ',1,1);
channelName=channelName.section(' ',0,0);
}
*/
// Join the channel
server->joinChannel(channelName, sourceHostmask);
server->resetNickList(channelName);
// Upon JOIN we're going to receive some NAMES input from the server which
// we need to be able to tell apart from manual invocations of /names
setAutomaticRequest("NAMES",channelName,true);
server->getChannelByName(channelName)->clearModeList();
// Request modes for the channel
server->queue("MODE "+channelName, Server::LowPriority);
// Initiate channel ban list
server->getChannelByName(channelName)->clearBanList();
setAutomaticRequest("BANLIST",channelName,true);
server->queue("MODE "+channelName+" +b", Server::LowPriority);
}
else
{
Channel* channel = server->nickJoinsChannel(channelName,sourceNick,sourceHostmask);
konv_app->notificationHandler()->join(channel, sourceNick);
}
}
else if(command=="kick")
{
server->nickWasKickedFromChannel(parameterList[0],parameterList[1],sourceNick,trailing);
}
else if(command=="part")
{
/* FIXME: Ugly workaround for a version of the PART line encountered on ircu:
* :Nick!user@host PART :#channel
* Quote: "The final colon is specified as a "last argument" designator, and
* is always valid before the final argument."
*/
TQString channel;
TQString reason;
if (parameterList[0].isEmpty())
{
channel = trailing;
}
else
{
channel = parameterList[0];
reason = trailing;
}
Channel* channelPtr = server->removeNickFromChannel(channel,sourceNick,reason);
if(sourceNick != server->getNickname())
{
konv_app->notificationHandler()->part(channelPtr, sourceNick);
}
}
else if(command=="quit")
{
server->removeNickFromServer(sourceNick,trailing);
if(sourceNick != server->getNickname())
{
konv_app->notificationHandler()->quit(server->getStatusView(), sourceNick);
}
}
else if(command=="nick")
{
TQString newNick(trailing);
// Message may not include ":" in front of the new nickname
if (newNick.isEmpty())
newNick=parameterList[parameterList.count()-1];
server->renameNick(sourceNick,newNick);
if (sourceNick != server->getNickname())
{
konv_app->notificationHandler()->nickChange(server->getStatusView(), sourceNick, newNick);
}
}
else if(command=="topic")
{
server->setChannelTopic(sourceNick,parameterList[0],trailing);
}
else if(command=="mode") // mode #channel -/+ mmm params
{
TQStringList params=parameterList;
if (!trailing.isEmpty())
params << trailing;
parseModes(sourceNick, params);
Channel* channel = server->getChannelByName(parameterList[0]);
if(sourceNick != server->getNickname())
{
konv_app->notificationHandler()->mode(channel, sourceNick);
}
}
else if(command=="invite")
{
TQString channel;
if (parameterList.count() > 1)
channel = parameterList[1];
else
channel = trailing;
server->appendMessageToFrontmost(i18n("Invite"),
i18n("%1 invited you to channel %2.")
.arg(sourceNick).arg(channel)
);
emit invitation(sourceNick,channel);
}
else
{
server->appendMessageToFrontmost(command,parameterList.join(" ")+' '+trailing);
}
}
void InputFilter::parseServerCommand(const TQString &prefix, const TQString &command, const TQStringList &parameterList, const TQString &trailing)
{
bool isNumeric;
int numeric = command.toInt(&isNumeric);
Q_ASSERT(server); if(!server) return;
if(!isNumeric)
{
if(command=="ping")
{
TQString text;
text = (!trailing.isEmpty()) ? trailing : parameterList.join(" ");
if(!trailing.isEmpty())
{
text = prefix + " :" + text;
}
if(!text.startsWith(" "))
{
text.prepend(' ');
}
// queue the reply to send it as soon as possible
server->queue("PONG"+text, Server::HighPriority);
}
else if(command=="error :closing link:")
{
kdDebug() << "link closed" << endl;
}
else if(command=="pong")
{
// double check if we are in lag measuring mode since some servers fail to send
// the LAG cookie back in PONG
if(trailing.startsWith("LAG") || getLagMeasuring())
{
server->pongReceived();
}
}
else if(command=="mode")
{
TQStringList params=parameterList;
if (!trailing.isEmpty())
params << trailing;
parseModes(prefix, params);
}
else if(command=="notice")
{
server->appendStatusMessage(i18n("Notice"),i18n("-%1- %2").arg(prefix).arg(trailing));
}
else if(command=="kick")
{
server->nickWasKickedFromChannel(parameterList[0],parameterList[1],prefix,trailing);
}
else if(command == "privmsg")
{
parsePrivMsg(prefix, parameterList, trailing);
}
// All yet unknown messages go into the frontmost window unaltered
else
{
server->appendMessageToFrontmost(command,parameterList.join(" ")+' '+trailing);
}
}
else
{
switch (numeric)
{
case RPL_WELCOME:
case RPL_YOURHOST:
case RPL_CREATED:
{
if(numeric==RPL_WELCOME)
{
TQString host;
if(trailing.contains("@"))
host = trailing.section("@",1);
// re-set nickname, since the server may have truncated it
if(parameterList[0]!=server->getNickname())
server->renameNick(server->getNickname(), parameterList[0]);
// Send the welcome signal, so the server class knows we are connected properly
emit welcome(host);
m_connecting = true;
}
server->appendStatusMessage(i18n("Welcome"),trailing);
break;
}
case RPL_MYINFO:
{
server->appendStatusMessage(i18n("Welcome"),
i18n("Server %1 (Version %2), User modes: %3, Channel modes: %4")
.arg(parameterList[1])
.arg(parameterList[2])
.arg(parameterList[3])
.arg(parameterList[4])
);
server->setAllowedChannelModes(parameterList[4]);
break;
}
//case RPL_BOUNCE: // RFC 1459 name, now seems to be obsoleted by ...
case RPL_ISUPPORT: // ... DALnet RPL_ISUPPORT
{
server->appendStatusMessage(i18n("Support"),parameterList.join(" "));
// The following behavoiur is neither documented in RFC 1459 nor in 2810-2813
// Nowadays, most ircds send server capabilities out via 005 (BOUNCE).
// refer to http://www.irc.org/tech_docs/005.html for a kind of documentation.
// More on http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
TQStringList::const_iterator it = parameterList.begin();
// don't want the user name
++it;
for (; it != parameterList.end(); ++it )
{
TQString property, value;
int pos;
if ((pos=(*it).find( '=' )) !=-1)
{
property = (*it).left(pos);
value = (*it).mid(pos+1);
}
else
{
property = *it;
}
if (property=="PREFIX")
{
pos = value.find(')',1);
if(pos==-1)
{
server->setPrefixes(TQString(), value);
// XXX if ) isn't in the string, NOTHING should be there. anyone got a server
if (value.length() || property.length())
server->appendStatusMessage("","XXX Server sent bad PREFIX in RPL_ISUPPORT, please report.");
}
else
{
server->setPrefixes (value.mid(1, pos-1), value.mid(pos+1));
}
}
else if (property=="CHANTYPES")
{
server->setChannelTypes(value);
}
else if (property == "CAPAB")
{
// Disable as we don't use this for anything yet
//server->queue("CAPAB IDENTIFY-MSG");
}
else
{
//kdDebug() << "Ignored server-capability: " << property << " with value '" << value << "'" << endl;
}
} // endfor
break;
}
case RPL_UMODEIS:
{
TQString message=TQString("%1 %2").arg(i18n("Your personal modes are:")).arg(parameterList.join(" ").section(' ',1) + ' '+trailing);
server->appendMessageToFrontmost("Info", message);
break;
}
case RPL_CHANNELMODEIS:
{
const TQString modeString=parameterList[2];
// This is the string the user will see
TQString modesAre;
TQString message = i18n("Channel modes: ") + modeString;
for(unsigned int index=0;index<modeString.length();index++)
{
TQString parameter;
int parameterCount=3;
char mode=modeString[index];
if(mode!='+')
{
if(!modesAre.isEmpty())
modesAre+=", ";
if(mode=='t')
modesAre+=i18n("topic protection");
else if(mode=='n')
modesAre+=i18n("no messages from outside");
else if(mode=='s')
modesAre+=i18n("secret");
else if(mode=='i')
modesAre+=i18n("invite only");
else if(mode=='p')
modesAre+=i18n("private");
else if(mode=='m')
modesAre+=i18n("moderated");
else if(mode=='k')
{
parameter=parameterList[parameterCount++];
message += ' ' + parameter;
modesAre+=i18n("password protected");
}
else if(mode=='a')
modesAre+=i18n("anonymous");
else if(mode=='r')
modesAre+=i18n("server reop");
else if(mode=='c')
modesAre+=i18n("no colors allowed");
else if(mode=='l')
{
parameter=parameterList[parameterCount++];
message += ' ' + parameter;
modesAre+=i18n("limited to %n user", "limited to %n users", parameter.toInt());
}
else
{
modesAre+=mode;
}
server->updateChannelModeWidgets(parameterList[1],mode,parameter);
}
} // endfor
if(!modesAre.isEmpty() && Preferences::useLiteralModes())
{
server->appendCommandMessageToChannel(parameterList[1],i18n("Mode"),message);
}
else
{
server->appendCommandMessageToChannel(parameterList[1],i18n("Mode"),
i18n("Channel modes: ") + modesAre
);
}
break;
}
case RPL_CHANNELURLIS:
{// :niven.freenode.net 328 argonel #channel :http://www.buggeroff.com/
server->appendCommandMessageToChannel(parameterList[1], i18n("URL"),
i18n("Channel URL: %1").arg(trailing));
break;
}
case RPL_CHANNELCREATED:
{
TQDateTime when;
when.setTime_t(parameterList[2].toUInt());
server->appendCommandMessageToChannel(parameterList[1],i18n("Created"),
i18n("This channel was created on %1.")
.arg(when.toString(Qt::LocalDate))
);
if(Preferences::autoWhoContinuousEnabled())
{
emit endOfWho(parameterList[1]);
}
break;
}
case RPL_WHOISACCOUNT:
{
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is logged in as %2.").arg(parameterList[1]).arg(parameterList[2]));
}
break;
}
case RPL_NAMREPLY:
{
TQStringList nickList;
if(!trailing.isEmpty())
{
nickList = TQStringList::split(" ", trailing);
}
else if(parameterList.count() > 3)
{
for(uint i = 3; i < parameterList.count(); i++) {
nickList.append(parameterList[i]);
}
}
else
{
kdDebug() << "Hmm seems something is broken... can't get to the names!" << endl;
}
// send list to channel
server->addPendingNickList(parameterList[2], nickList);
// Display message only if this was not an automatic request.
if(!getAutomaticRequest("NAMES",parameterList[2])==1)
{
server->appendMessageToFrontmost(i18n("Names"),trailing);
}
break;
}
case RPL_ENDOFNAMES:
{
if(getAutomaticRequest("NAMES",parameterList[1])==1)
{
// This code path was taken for the automatic NAMES input on JOIN, upcoming
// NAMES input for this channel will be manual invocations of /names
setAutomaticRequest("NAMES",parameterList[1],false);
}
else
{
server->appendMessageToFrontmost(i18n("Names"),i18n("End of NAMES list."));
}
break;
}
// Topic set messages
case RPL_NOTOPIC:
{
server->appendMessageToFrontmost(i18n("TOPIC"),i18n("The channel %1 has no topic set.").arg(parameterList[1]) /*.arg(parameterList[2])*/); //FIXME ok, whats the second parameter supposed to be?
break;
}
case RPL_TOPIC:
{
TQString topic = Konversation::removeIrcMarkup(trailing);
// FIXME: This is an abuse of the automaticRequest system: We're
// using it in an inverted manner, i.e. the automaticRequest is
// set to true by a manual invocation of /topic. Bad bad bad -
// needs rethinking of automaticRequest.
if(getAutomaticRequest("TOPIC",parameterList[1])==0)
{
// Update channel window
server->setChannelTopic(parameterList[1],topic);
}
else
{
server->appendMessageToFrontmost(i18n("Topic"),i18n("The channel topic for %1 is: \"%2\"").arg(parameterList[1]).arg(topic));
}
break;
}
case RPL_TOPICSETBY:
{
// Inform user who set the topic and when
TQDateTime when;
when.setTime_t(parameterList[3].toUInt());
// See FIXME in RPL_TOPIC
if(getAutomaticRequest("TOPIC",parameterList[1])==0)
{
server->appendCommandMessageToChannel(parameterList[1],i18n("Topic"),
i18n("The topic was set by %1 on %2.")
.arg(parameterList[2]).arg(when.toString(Qt::LocalDate)),
false);
}
else
{
server->appendMessageToFrontmost(i18n("Topic"),i18n("The topic for %1 was set by %2 on %3.")
.arg(parameterList[1])
.arg(parameterList[2])
.arg(when.toString(Qt::LocalDate))
);
setAutomaticRequest("TOPIC",parameterList[1],false);
}
emit topicAuthor(parameterList[1], parameterList[2], when);
break;
}
case RPL_WHOISACTUALLY:
{
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is actually using the host %2.").arg(parameterList[1]).arg(parameterList[2]));
}
break;
}
case ERR_NOSUCHNICK:
{
// Display slightly different error message in case we performed a WHOIS for
// IP resolve purposes, and clear it from the automaticRequest list
if(getAutomaticRequest("DNS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Error"),i18n("%1: No such nick/channel.").arg(parameterList[1]));
}
else if(getAutomaticRequest("WHOIS",parameterList[1])==0) //Display message only if this was not an automatic request.
{
server->appendMessageToFrontmost(i18n("Error"),i18n("No such nick: %1.").arg(parameterList[1]));
setAutomaticRequest("DNS", parameterList[1], false);
}
break;
}
case ERR_NOSUCHCHANNEL:
{
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Error"),i18n("%1: No such channel.").arg(parameterList[1]));
}
break;
}
// Nick already on the server, so try another one
case ERR_NICKNAMEINUSE:
{
// if we are already connected, don't try tro find another nick ourselves
if(server->isConnected())
{ // Show message
server->appendMessageToFrontmost(i18n("Nick"),i18n("Nickname already in use, try a different one."));
}
else // not connected yet, so try to find a nick that's not in use
{
// Get the next nick from the list or ask for a new one
TQString newNick = server->getNextNickname();
// The user chose to disconnect
if (newNick.isNull())
{
server->disconnect();
}
else
{
// Update Server window
server->obtainNickInfo(server->getNickname()) ;
server->renameNick(server->getNickname(), newNick);
// Show message
server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname already in use. Trying %1.").arg(newNick));
// Send nickchange request to the server
server->queue("NICK "+newNick);
}
}
break;
}
case ERR_ERRONEUSNICKNAME:
{
if(server->isConnected())
{ // We are already connected. Just print the error message
server->appendMessageToFrontmost(i18n("Nick"), trailing);
}
else // Find a new nick as in ERR_NICKNAMEINUSE
{
TQString newNick = server->getNextNickname();
// The user chose to disconnect
if (newNick.isNull())
{
server->disconnect();
}
else
{
server->obtainNickInfo(server->getNickname()) ;
server->renameNick(server->getNickname(), newNick);
server->appendMessageToFrontmost(i18n("Nick"), i18n("Erroneus nickname. Changing nick to %1." ).arg(newNick)) ;
server->queue("NICK "+newNick);
}
}
break;
}
case ERR_NOTONCHANNEL:
{
server->appendMessageToFrontmost(i18n("Error"),i18n("You are not on %1.").arg(parameterList[1]));
break;
}
case RPL_MOTDSTART:
{
if(!m_connecting || !Preferences::skipMOTD())
server->appendStatusMessage(i18n("MOTD"),i18n("Message of the day:"));
break;
}
case RPL_MOTD:
{
if(!m_connecting || !Preferences::skipMOTD())
server->appendStatusMessage(i18n("MOTD"),trailing);
break;
}
case RPL_ENDOFMOTD:
{
if(!m_connecting || !Preferences::skipMOTD())
server->appendStatusMessage(i18n("MOTD"),i18n("End of message of the day"));
if(m_connecting)
server->autoCommandsAndChannels();
m_connecting = false;
break;
}
case ERR_NOMOTD:
{
if(m_connecting)
server->autoCommandsAndChannels();
m_connecting = false;
break;
}
case RPL_YOUREOPER:
{
server->appendMessageToFrontmost(i18n("Notice"),i18n("You are now an IRC operator on this server."));
break;
}
case RPL_GLOBALUSERS: // Current global users: 589 Max: 845
{
TQString current(trailing.section(' ',3));
//TQString max(trailing.section(' ',5,5));
server->appendStatusMessage(i18n("Users"),i18n("Current users on the network: %1").arg(current));
break;
}
case RPL_LOCALUSERS: // Current local users: 589 Max: 845
{
TQString current(trailing.section(' ',3));
//TQString max(trailing.section(' ',5,5));
server->appendStatusMessage(i18n("Users"),i18n("Current users on %1: %2.").arg(prefix).arg(current));
break;
}
case RPL_ISON:
{
// Tell server to start the next notify timer round
emit notifyResponse(trailing);
break;
}
case RPL_AWAY:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
if(nickInfo)
{
nickInfo->setAway(true);
if( nickInfo->getAwayMessage() == trailing )
break;
nickInfo->setAwayMessage(trailing);
}
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Away"),i18n("%1 is away: %2")
.arg(parameterList[1]).arg(trailing)
);
}
break;
}
case RPL_INVITING:
{
server->appendMessageToFrontmost(i18n("Invite"),
i18n("You invited %1 to channel %2.")
.arg(parameterList[1]).arg(parameterList[2])
);
break;
}
//Sample WHOIS response
//"/WHOIS psn"
//[19:11] :zahn.freenode.net 311 PhantomsDad psn ~psn h106n2fls23o1068.bredband.comhem.se * :Peter Simonsson
//[19:11] :zahn.freenode.net 319 PhantomsDad psn :#kde-devel #koffice
//[19:11] :zahn.freenode.net 312 PhantomsDad psn irc.freenode.net :http://freenode.net/
//[19:11] :zahn.freenode.net 301 PhantomsDad psn :away
//[19:11] :zahn.freenode.net 320 PhantomsDad psn :is an identified user
//[19:11] :zahn.freenode.net 317 PhantomsDad psn 4921 1074973024 :seconds idle, signon time
//[19:11] :zahn.freenode.net 318 PhantomsDad psn :End of /WHOIS list.
case RPL_WHOISUSER:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
if(nickInfo)
{
nickInfo->setHostmask(i18n("%1@%2").arg(parameterList[2]).arg(parameterList[3]));
nickInfo->setRealName(trailing);
}
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
// escape html tags
TQString escapedRealName(trailing);
escapedRealName.replace("<","&lt;").replace(">","&gt;");
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is %2@%3 (%4)")
.arg(parameterList[1])
.arg(parameterList[2])
.arg(parameterList[3])
.arg(escapedRealName), false); // Don't parse any urls
}
else
{
// This WHOIS was requested by Server for DNS resolve purposes; try to resolve the host
if(getAutomaticRequest("DNS",parameterList[1])==1)
{
KNetwork::KResolverResults resolved = KNetwork::KResolver::resolve(parameterList[3],"");
if(resolved.error() == KResolver::NoError && resolved.size() > 0)
{
TQString ip = resolved.first().address().nodeName();
server->appendMessageToFrontmost(i18n("DNS"),
i18n("Resolved %1 (%2) to address: %3")
.arg(parameterList[1])
.arg(parameterList[3])
.arg(ip)
);
}
else
{
server->appendMessageToFrontmost(i18n("Error"),
i18n("Unable to resolve address for %1 (%2)")
.arg(parameterList[1])
.arg(parameterList[3])
);
}
// Clear this from the automaticRequest list so it works repeatedly
setAutomaticRequest("DNS", parameterList[1], false);
}
}
break;
}
// From a WHOIS.
//[19:11] :zahn.freenode.net 320 PhantomsDad psn :is an identified user
case RPL_WHOISIDENTIFY:
case RPL_IDENTIFIED:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
if(nickInfo)
{
nickInfo->setIdentified(true);
}
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
// Prints "psn is an identified user"
//server->appendStatusMessage(i18n("Whois"),parameterList.join(" ").section(' ',1)+' '+trailing);
// The above line works fine, but can't be i18n'ised. So use the below instead.. I hope this is okay.
server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an identified user.").arg(parameterList[1]));
}
break;
}
// Sample WHO response
//"/WHO #lounge"
//[21:39] [352] #lounge jasmine bots.worldforge.org irc.worldforge.org jasmine H 0 jasmine
//[21:39] [352] #lounge ~Nottingha worldforge.org irc.worldforge.org SherwoodSpirit H 0 Arboreal Entity
case RPL_WHOREPLY:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[5]);
// G=away G@=away,op G+=away,voice
bool bAway = parameterList[6].upper().startsWith("G");
if(nickInfo)
{
nickInfo->setHostmask(i18n("%1@%2").arg(parameterList[2]).arg(parameterList[3]));
//Strip off the "0 "
nickInfo->setRealName(trailing.section(" ", 1));
nickInfo->setAway(bAway);
if(!bAway)
{
nickInfo->setAwayMessage(TQString());
}
}
// Display message only if this was not an automatic request.
if(!whoRequestList.isEmpty()) // for safe
{
if(getAutomaticRequest("WHO",whoRequestList.front())==0)
{
server->appendMessageToFrontmost(i18n("Who"),
i18n("%1 is %2@%3 (%4)%5").arg(parameterList[5])
.arg(parameterList[2])
.arg(parameterList[3])
.arg(trailing.section(" ", 1))
.arg(bAway?i18n(" (Away)"):TQString())
, false); // Don't parse as url
}
}
break;
}
case RPL_ENDOFWHO:
{
if(!whoRequestList.isEmpty())
{ // for safety
TQStringList::iterator it = whoRequestList.find(parameterList[1].lower());
if(it != whoRequestList.end())
{
if(getAutomaticRequest("WHO", *it) == 0)
{
server->appendMessageToFrontmost(i18n("Who"),
i18n("End of /WHO list for %1")
.arg(parameterList[1]));
}
else
{
setAutomaticRequest("WHO", *it, false);
}
whoRequestList.remove(it);
}
else
{
// whoReauestList seems to be broken.
kdDebug() << "InputFilter::parseServerCommand(): RPL_ENDOFWHO: malformed ENDOFWHO. retrieved: "
<< parameterList[1] << " expected: " << whoRequestList.front()
<< endl;
whoRequestList.clear();
}
}
else
{
kdDebug() << "InputFilter::parseServerCommand(): RPL_ENDOFWHO: unexpected ENDOFWHO. retrieved: "
<< parameterList[1]
<< endl;
}
emit endOfWho(parameterList[1]);
break;
}
case RPL_WHOISCHANNELS:
{
TQStringList userChannels,voiceChannels,opChannels,halfopChannels,ownerChannels,adminChannels;
// get a list of all channels the user is in
TQStringList channelList=TQStringList::split(' ',trailing);
channelList.sort();
// split up the list in channels where they are operator / user / voice
for(unsigned int index=0; index < channelList.count(); index++)
{
TQString lookChannel=channelList[index];
if(lookChannel.startsWith("*") || lookChannel.startsWith("&"))
{
adminChannels.append(lookChannel.mid(1));
server->setChannelNick(lookChannel.mid(1), parameterList[1], 16);
}
// See bug #97354 part 2
else if((lookChannel.startsWith("!") || lookChannel.startsWith("~")) && server->isAChannel(lookChannel.mid(1)))
{
ownerChannels.append(lookChannel.mid(1));
server->setChannelNick(lookChannel.mid(1), parameterList[1], 8);
}
// See bug #97354 part 1
else if(lookChannel.startsWith("@+"))
{
opChannels.append(lookChannel.mid(2));
server->setChannelNick(lookChannel.mid(2), parameterList[1], 4);
}
else if(lookChannel.startsWith("@"))
{
opChannels.append(lookChannel.mid(1));
server->setChannelNick(lookChannel.mid(1), parameterList[1], 4);
}
else if(lookChannel.startsWith("%"))
{
halfopChannels.append(lookChannel.mid(1));
server->setChannelNick(lookChannel.mid(1), parameterList[1], 2);
}
else if(lookChannel.startsWith("+"))
{
voiceChannels.append(lookChannel.mid(1));
server->setChannelNick(lookChannel.mid(1), parameterList[1], 1);
}
else
{
userChannels.append(lookChannel);
server->setChannelNick(lookChannel, parameterList[1], 0);
}
} // endfor
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
if(userChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is a user on channels: %2")
.arg(parameterList[1])
.arg(userChannels.join(" "))
);
}
if(voiceChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 has voice on channels: %2")
.arg(parameterList[1]).arg(voiceChannels.join(" "))
);
}
if(halfopChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is a halfop on channels: %2")
.arg(parameterList[1]).arg(halfopChannels.join(" "))
);
}
if(opChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is an operator on channels: %2")
.arg(parameterList[1]).arg(opChannels.join(" "))
);
}
if(ownerChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is owner of channels: %2")
.arg(parameterList[1]).arg(ownerChannels.join(" "))
);
}
if(adminChannels.count())
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is admin on channels: %2")
.arg(parameterList[1]).arg(adminChannels.join(" "))
);
}
}
break;
}
case RPL_WHOISSERVER:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
if(nickInfo)
{
nickInfo->setNetServer(parameterList[2]);
nickInfo->setNetServerInfo(trailing);
// Clear the away state on assumption that if nick is away, this message will be followed
// by a 301 RPL_AWAY message. Not necessary a invalid assumption, but what can we do?
nickInfo->setAway(false);
nickInfo->setAwayMessage(TQString());
}
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is online via %2 (%3).").arg(parameterList[1])
.arg(parameterList[2]).arg(trailing)
);
}
break;
}
case RPL_WHOISHELPER:
{
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 is available for help.")
.arg(parameterList[1])
);
}
break;
}
case RPL_WHOISOPERATOR:
{
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
if (trailing.lower().simplifyWhiteSpace().startsWith("is an irc operator"))
server->appendMessageToFrontmost(i18n("Whois"),i18n("%1 is an IRC Operator.").arg(parameterList[1]));
else
server->appendMessageToFrontmost(i18n("Whois"),TQString("%1 %2").arg(parameterList[1]).arg(trailing));
}
break;
}
case RPL_WHOISIDLE:
{
// get idle time in seconds
long seconds=parameterList[2].toLong();
long minutes=seconds/60;
long hours =minutes/60;
long days =hours/24;
// if idle time is longer than a day
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
if(days)
{
const TQString daysString = i18n("1 day", "%n days", days);
const TQString hoursString = i18n("1 hour", "%n hours", (hours % 24));
const TQString minutesString = i18n("1 minute", "%n minutes", (minutes % 60));
const TQString secondsString = i18n("1 second", "%n seconds", (seconds % 60));
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 = name of person, %2 = (x days), %3 = (x hours), %4 = (x minutes), %5 = (x seconds)",
"%1 has been idle for %2, %3, %4, and %5.")
.arg(parameterList[1])
.arg(daysString).arg(hoursString).arg(minutesString).arg(secondsString)
);
// or longer than an hour
}
else if(hours)
{
const TQString hoursString = i18n("1 hour", "%n hours", hours);
const TQString minutesString = i18n("1 minute", "%n minutes", (minutes % 60));
const TQString secondsString = i18n("1 second", "%n seconds", (seconds % 60));
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 = name of person, %2 = (x hours), %3 = (x minutes), %4 = (x seconds)",
"%1 has been idle for %2, %3, and %4.")
.arg(parameterList[1])
.arg(hoursString).arg(minutesString).arg(secondsString)
);
// or longer than a minute
}
else if(minutes)
{
const TQString minutesString = i18n("1 minute", "%n minutes", minutes);
const TQString secondsString = i18n("1 second", "%n seconds", (seconds % 60));
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 = name of person, %2 = (x minutes), %3 = (x seconds)",
"%1 has been idle for %2 and %3.")
.arg(parameterList[1])
.arg(minutesString).arg(secondsString)
);
// or just some seconds
}
else
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 has been idle for 1 second.", "%1 has been idle for %n seconds.", seconds)
.arg(parameterList[1])
);
}
}
if(parameterList.count()==4)
{
TQDateTime when;
when.setTime_t(parameterList[3].toUInt());
NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
if(nickInfo)
{
nickInfo->setOnlineSince(when);
}
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),
i18n("%1 has been online since %2.")
.arg(parameterList[1]).arg(when.toString(Qt::LocalDate))
);
}
}
break;
}
case RPL_ENDOFWHOIS:
{
//NickInfo* nickInfo = server->getNickInfo(parameterList[1]);
// Display message only if this was not an automatic request.
if(getAutomaticRequest("WHOIS",parameterList[1])==0)
{
server->appendMessageToFrontmost(i18n("Whois"),i18n("End of WHOIS list."));
}
// was this an automatic request?
if(getAutomaticRequest("WHOIS",parameterList[1])!=0)
{
setAutomaticRequest("WHOIS",parameterList[1],false);
}
break;
}
case RPL_USERHOST:
{
// iterate over all nick/masks in reply
TQStringList uhosts=TQStringList::split(" ",trailing);
for(unsigned int index=0;index<uhosts.count();index++)
{
// extract nickname and hostmask from reply
TQString nick(uhosts[index].section('=',0,0));
TQString mask(uhosts[index].section('=',1));
// get away and IRC operator flags
bool away=(mask[0]=='-');
bool ircOp=(nick[nick.length()-1]=='*');
// cut flags from nick/hostmask
mask=mask.mid(1);
if(ircOp)
{
nick=nick.left(nick.length()-1);
}
// inform server of this user's data
emit userhost(nick,mask,away,ircOp);
// display message only if this was no automatic request
if(getAutomaticRequest("USERHOST",nick)==0)
{
server->appendMessageToFrontmost(i18n("Userhost"),
i18n("%1 = nick, %2 = shows if nick is op, %3 = hostmask, %4 = shows away", "%1%2 is %3%4.")
.arg(nick)
.arg((ircOp) ? i18n(" (IRC Operator)") : TQString())
.arg(mask)
.arg((away) ? i18n(" (away)") : TQString()));
}
// was this an automatic request?
if(getAutomaticRequest("USERHOST",nick)!=0)
{
setAutomaticRequest("USERHOST",nick,false);
}
} // for
break;
}
case RPL_LISTSTART: //FIXME This reply is obsolete!!!
{
if(getAutomaticRequest("LIST",TQString())==0)
{
server->appendMessageToFrontmost(i18n("List"),i18n("List of channels:"));
}
break;
}
case RPL_LIST:
{
if(getAutomaticRequest("LIST",TQString())==0)
{
TQString message;
message=i18n("%1 (%n user): %2", "%1 (%n users): %2", parameterList[2].toInt());
server->appendMessageToFrontmost(i18n("List"),message.arg(parameterList[1]).arg(trailing));
}
else // send them to /LIST window
{
emit addToChannelList(parameterList[1],parameterList[2].toInt(),trailing);
}
break;
}
case RPL_LISTEND:
{
// was this an automatic request?
if(getAutomaticRequest("LIST",TQString())==0)
{
server->appendMessageToFrontmost(i18n("List"),i18n("End of channel list."));
}
else
{
setAutomaticRequest("LIST",TQString(),false);
}
break;
}
case RPL_NOWAWAY:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[0]);
if (nickInfo) nickInfo->setAway(true);
server->setAway(true);
break;
}
case RPL_UNAWAY:
{
NickInfo* nickInfo = server->getNickInfo(parameterList[0]);
if (nickInfo)
{
nickInfo->setAway(false);
nickInfo->setAwayMessage(TQString());
}
server->setAway(false);
break;
}
case RPL_BANLIST:
{
if (getAutomaticRequest("BANLIST", parameterList[1]))
{
server->addBan(parameterList[1], parameterList.join(" ").section(' ', 2, 4));
} else {
TQDateTime when;
when.setTime_t(parameterList[4].toUInt());
server->appendMessageToFrontmost(i18n("BanList:%1").arg(parameterList[1]), i18n("BanList message: e.g. *!*@aol.com set by MrGrim on <date>", "%1 set by %2 on %3").arg(parameterList[2]).arg(parameterList[3].section('!', 0, 0)).arg(when.toString(Qt::LocalDate)));
}
break;
}
case RPL_ENDOFBANLIST:
{
if (getAutomaticRequest("BANLIST", parameterList[1]))
{
setAutomaticRequest("BANLIST", parameterList[1], false);
} else {
server->appendMessageToFrontmost(i18n("BanList:%1").arg(parameterList[1]), i18n("End of Ban List."));
}
break;
}
case ERR_NOCHANMODES:
{
ChatWindow *chatwindow = server->getChannelByName(parameterList[1]);
if(chatwindow)
{
chatwindow->appendServerMessage(i18n("Channel"), trailing);
}
else // We couldn't join the channel , so print the error. with [#channel] : <Error Message>
{
server->appendMessageToFrontmost(i18n("Channel"), trailing);
}
break;
}
case ERR_NOSUCHSERVER:
{
//Some servers don't know their name, so they return an error instead of the PING data
if (getLagMeasuring() && trailing.startsWith(prefix))
{
server->pongReceived();
}
break;
}
case ERR_UNAVAILRESOURCE:
{
server->appendMessageToFrontmost(i18n("Error"),i18n("%1 is currently unavailable.").arg(parameterList[1]));
break;
}
case RPL_HIGHCONNECTCOUNT:
case RPL_LUSERCLIENT:
case RPL_LUSEROP:
case RPL_LUSERUNKNOWN:
case RPL_LUSERCHANNELS:
case RPL_LUSERME:
{
server->appendStatusMessage(i18n("Users"), parameterList.join(" ").section(' ',1) + ' '+trailing);
break;
}
case ERR_UNKNOWNCOMMAND:
{
server->appendMessageToFrontmost(i18n("Error"),i18n("%1: Unknown command.").arg(parameterList[1]));
break;
}
case ERR_NOTREGISTERED:
{
server->appendMessageToFrontmost(i18n("Error"),i18n("Not registered."));
break;
}
case ERR_NEEDMOREPARAMS:
{
server->appendMessageToFrontmost(i18n("Error"),i18n("%1: This command requires more parameters.").arg(parameterList[1]));
break;
}
case RPL_CAPAB: // Special freenode reply afaik
{
// Disable as we don't use this for anything yet
if(trailing.contains("IDENTIFY-MSG"))
{
server->enableIdentifyMsg(true);
break;
}
/* don't break; - this is also used as RPL_DATASTR on ircu and some others */
}
// FALLTHROUGH to default to let the error display otherwise
default:
{
// All yet unknown messages go into the frontmost window without the
// preceding nickname
server->appendMessageToFrontmost(command, parameterList.join(" ").section(' ',1) + ' '+trailing);
}
} // end of numeric switch
}
}
void InputFilter::parseModes(const TQString &sourceNick, const TQStringList &parameterList)
{
const TQString modestring=parameterList[1];
if (!isAChannel(parameterList[0]))
{
TQString message;
if (parameterList[0] == server->getNickname())
{
if (sourceNick == server->getNickname())
{
//XXX someone might care about the potentially unnecessary plural here
message = i18n("You have set personal modes: ") + modestring;
}
else
{ //XXX someone might care about the potentially unnecessary plural here
message = TQString("%1 %2 %3").arg(sourceNick).arg(i18n("has changed your personal modes:")).arg(modestring);
}
}
if (!message.isEmpty())
server->appendStatusMessage(i18n("Mode"), message);
return;
}
bool plus=false;
int parameterIndex=0;
// List of modes that need a parameter (note exception with -k and -l)
// Mode q is quiet on freenode and acts like b... if this is a channel mode on other
// networks then more logic is needed here. --MrGrim
TQString parameterModes="aAoOvhkbleIq";
TQString message = sourceNick + i18n(" sets mode: ") + modestring;
for(unsigned int index=0;index<modestring.length();index++)
{
unsigned char mode=modestring[index];
TQString parameter;
// Check if this is a mode or a +/- qualifier
if(mode=='+' || mode=='-')
{
plus=(mode=='+');
}
else
{
// Check if this was a parameter mode
if(parameterModes.find(mode)!=-1)
{
// Check if the mode actually wants a parameter. -k and -l do not!
if(plus || (!plus && (mode!='k') && (mode!='l')))
{
// Remember the mode parameter
parameter=parameterList[2+parameterIndex];
message += ' ' + parameter;
// Switch to next parameter
++parameterIndex;
}
}
// Let the channel update its modes
if(parameter.isEmpty()) // XXX Check this to ensure the braces are in the correct place
{
kdDebug() << "in updateChannelMode. sourceNick: '" << sourceNick << "' parameterlist: '"
<< parameterList.join(", ") << "'"
<< endl;
}
server->updateChannelMode(sourceNick,parameterList[0],mode,plus,parameter);
}
} // endfor
if (Preferences::useLiteralModes())
{
server->appendCommandMessageToChannel(parameterList[0],i18n("Mode"),message);
}
}
// # & + and ! are *often*, but not necessarily, Channel identifiers. + and ! are non-RFC,
// so if a server doesn't offer 005 and supports + and ! channels, I think thats broken behaviour
// on their part - not ours. --Argonel
bool InputFilter::isAChannel(const TQString &check)
{
Q_ASSERT(server);
// if we ever see the assert, we need the ternary
return server? server->isAChannel(check) : TQString("#&").contains(check.at(0));
}
bool InputFilter::isIgnore(const TQString &sender, Ignore::Type type)
{
bool doIgnore = false;
TQPtrList<Ignore> list = Preferences::ignoreList();
for(unsigned int index =0; index<list.count(); index++)
{
Ignore* item = list.at(index);
TQRegExp ignoreItem(TQString(TQRegExp::escape(item->getName())).replace("\\*", "(.*)"),false);
if (ignoreItem.exactMatch(sender) && (item->getFlags() & type))
doIgnore = true;
if (ignoreItem.exactMatch(sender) && (item->getFlags() & Ignore::Exception))
return false;
}
return doIgnore;
}
void InputFilter::reset()
{
automaticRequest.clear();
whoRequestList.clear();
}
void InputFilter::setAutomaticRequest(const TQString& command, const TQString& name, bool yes)
{
automaticRequest[command][name.lower()] += (yes) ? 1 : -1;
if(automaticRequest[command][name.lower()]<0)
{
kdDebug() << "InputFilter::automaticRequest( " << command << ", " << name
<< " ) was negative! Resetting!"
<< endl;
automaticRequest[command][name.lower()]=0;
}
}
int InputFilter::getAutomaticRequest(const TQString& command, const TQString& name)
{
return automaticRequest[command][name.lower()];
}
void InputFilter::addWhoRequest(const TQString& name) { whoRequestList << name.lower(); }
bool InputFilter::isWhoRequestUnderProcess(const TQString& name) { return (whoRequestList.contains(name.lower())>0); }
void InputFilter::setLagMeasuring(bool state) { lagMeasuring=state; }
bool InputFilter::getLagMeasuring() { return lagMeasuring; }
void InputFilter::parsePrivMsg(const TQString& prefix,
const TQStringList& parameterList,
const TQString& trailing)
{
int pos = prefix.find("!");
TQString source;
TQString sourceHostmask;
TQString message(trailing);
if(pos > 0)
{
source = prefix.left(pos);
sourceHostmask = prefix.mid(pos + 1);
}
else
{
source = prefix;
}
KonversationApplication* konv_app = static_cast<KonversationApplication*>(kapp);
message = konv_app->doAutoreplace(message, false);
if(isAChannel(parameterList[0]))
{
if(!isIgnore(prefix, Ignore::Channel))
{
Channel* channel = server->getChannelByName(parameterList[0]);
if(channel)
{
channel->append(source, message);
if(source != server->getNickname())
{
TQRegExp regexp("(^|[^\\d\\w])" +
TQRegExp::escape(server->loweredNickname()) +
"([^\\d\\w]|$)");
regexp.setCaseSensitive(false);
if(message.find(regexp) !=-1 )
{
konv_app->notificationHandler()->nick(channel,
source, message);
}
else
{
konv_app->notificationHandler()->message(channel,
source, message);
}
}
}
}
}
else
{
if(!isIgnore(prefix,Ignore::Query))
{
NickInfoPtr nickinfo = server->obtainNickInfo(source);
nickinfo->setHostmask(sourceHostmask);
// Create a new query (server will check for dupes)
query = server->addQuery(nickinfo, false /*we didn't initiate this*/ );
// send action to query
query->appendQuery(source, message);
if(source != server->getNickname() && query)
{
TQRegExp regexp("(^|[^\\d\\w])" +
TQRegExp::escape(server->loweredNickname()) +
"([^\\d\\w]|$)");
regexp.setCaseSensitive(false);
if(message.find(regexp) !=-1 )
{
konv_app->notificationHandler()->nick(query,
source, message);
}
else
{
konv_app->notificationHandler()->queryMessage(query,
source, message);
}
}
}
}
}
#include "inputfilter.moc"
// kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on;
// vim: set et sw=4 ts=4 cino=l1,cs,U1: