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.
kvirc/src/kvirc/sparser/kvi_sp_numeric.cpp

2004 lines
66 KiB

//=============================================================================
//
// File : kvi_sp_numeric.cpp
// Creation date : Thu Aug 3 2000 01:30:45 by Szymon Stefanek
//
// This file is part of the KVirc irc client distribution
// Copyright (C) 1999-2007 Szymon Stefanek (pragma at kvirc dot net)
//
// 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 opinion) any later version.
//
// This program is distributed in the HOPE that it will be USEFUL,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, write to the Free Software Foundation,
// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
#define __KVIRC__
#include "kvi_sparser.h"
#include "kvi_window.h"
#include "kvi_query.h"
#include "kvi_out.h"
#include "kvi_locale.h"
#include "kvi_ircsocket.h"
#include "kvi_options.h"
#include "kvi_channel.h"
#include "kvi_topicw.h"
#include "kvi_ircuserdb.h"
#include "kvi_defaults.h"
#include "kvi_mirccntrl.h"
#include "kvi_frame.h"
#include "kvi_parameterlist.h"
#include "kvi_app.h"
#include "kvi_notifylist.h"
#include "kvi_numeric.h"
#include "kvi_ircconnection.h"
#include "kvi_ircconnectionstatedata.h"
#include "kvi_ircconnectionuserinfo.h"
#include "kvi_ircconnectionserverinfo.h"
#include "kvi_ircconnectionasyncwhoisdata.h"
#include "kvi_ircconnectiontarget.h"
#include "kvi_time.h"
#include "kvi_lagmeter.h"
#include "kvi_qcstring.h"
#include <tqpixmap.h>
#include <tqdatetime.h>
#include <tqtextcodec.h>
#include <tqregexp.h>
#include "kvi_kvs_eventtriggers.h"
#include "kvi_kvs_script.h"
#include "kvi_kvs_variantlist.h"
// #define IS_CHANNEL_TYPE_FLAG(_str) ((*(_str) == '#') || (*(_str) == '&') || (*(_str) == '!'))
#define IS_CHANNEL_TYPE_FLAG(_qchar) (msg->connection()->serverInfo()->supportedChannelTypes().find(_qchar) != -1)
#define IS_USER_MODE_PREFIX(_qchar) (msg->connection()->serverInfo()->supportedModePrefixes().find(_qchar) != -1)
// Numeric message handlers
// FIXME: #warning "IN ALL OUTPUT ADD ESCAPE SEQUENCES!!!!"
// FIXME: #warning "parseErrorUnknownModeChar() for modes e and I , parseErrorUnknownCommand for WATCH"
void KviServerParser::parseNumeric001(KviIrcMessage *msg)
{
// 001: RPL_WELCOME
// :prefix 001 target :Welcome to the Internet Relay Network <usermask>
// FIXME: #warning "SET THE USERMASK FROM SERVER"
TQString szText = msg->connection()->decodeText(msg->safeTrailing());
TQRegExp rx( " ([^ ]+)!([^ ]+)@([^ ]+)$" );
if( rx.search(szText) != -1)
{
msg->connection()->userInfo()->setUnmaskedHostName(rx.cap(3));
msg->connection()->userInfo()->setNickName(rx.cap(1));
msg->connection()->userInfoReceived(rx.cap(2),rx.cap(3));
}
if(msg->connection()->context()->state() != KviIrcContext::Connected)
msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
if(!msg->haltOutput())
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,szText);
}
void KviServerParser::parseNumeric002(KviIrcMessage *msg)
{
// 002: RPL_YOURHOST [I,E,U,D]
// :prefix 002 target :Your host is <server name>, running version <server version>
if(msg->connection()->context()->state() != KviIrcContext::Connected)
msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()));
}
void KviServerParser::parseNumeric003(KviIrcMessage *msg)
{
// 003: RPL_CREATED [I,E,U,D]
// :prefix 003 target :This server was created <date>
if(msg->connection()->context()->state() != KviIrcContext::Connected)
msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()));
}
void KviServerParser::parseNumeric004(KviIrcMessage *msg)
{
// 004: RPL_MYINFO [I,E,U,D]
// :prefix 004 target <server_name> <srv_version> <u_modes> <ch_modes>
if(msg->connection()->context()->state() != KviIrcContext::Connected)
msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
int uParams = msg->paramCount();
int uModeParam = 3;
if(uParams < 2)uParams = 2;
KviStr version = msg->safeParam(2);
msg->connection()->serverInfo()->setServerVersion(msg->safeParam(2));
KviStr umodes;
// skip version number (great, thanks WEBMASTER INCORPORATED -_-)
do
{
umodes = msg->safeParam(uModeParam);
} while (((umodes.contains('.')) || (umodes.contains('-'))) && uModeParam++ < uParams);
KviStr chanmodes = msg->safeParam(uModeParam+1);
if(uModeParam > 3)
{
version.append(' ');
version.append(msg->safeParam(3));
}
if((umodes.occurences('o') != 1) || (chanmodes.occurences('o') != 1) ||
(chanmodes.occurences('b') != 1) || (chanmodes.occurences('v') != 1) ||
(chanmodes.occurences('t') != 1) || (chanmodes.occurences('n') != 1) ||
(chanmodes.contains('.')) || (chanmodes.contains('-')) || (chanmodes.contains('(')))
{
if(!_OUTPUT_QUIET)
{
msg->console()->output(KVI_OUT_SYSTEMWARNING,__tr2qs(
"One or more standard mode flags are missing in the server available modes.\n" \
"This is caused either by a non RFC1459-compliant IRC daemon or a broken server reply.\n" \
"Server umodes seem to be '%s' and channel modes seem to be '%s'.\n" \
"Ignoring this reply and assuming that the basic set of modes is available.\n" \
"If you have strange problems, try changing the server."),umodes.ptr(),chanmodes.ptr());
}
umodes = "oiws"; // standard support
chanmodes = "obtkmlvsn"; // standard support
}
if(KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo) && (!msg->haltOutput()))
{
if(umodes.hasData())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("Available user modes:"));
const char * aux = umodes.ptr();
TQString tmp;
while(*aux)
{
tmp = msg->connection()->serverInfo()->getUserModeDescription(*aux);
if(tmp.isEmpty())
{
TQString tmp2 = __tr2qs(": Unknown user mode");
KviTQString::sprintf(tmp,"%c: %Q",*aux,&tmp2);
}
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,tmp);
aux++;
}
if(chanmodes.hasData())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("Available channel modes:"));
aux = chanmodes.ptr();
while(*aux)
{
KviTQString::sprintf(tmp,"%c: %Q",*aux,&(msg->connection()->serverInfo()->getChannelModeDescription(*aux)));
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,tmp);
aux++;
}
}
TQString szServer = msg->connection()->decodeText(msg->safeParam(1));
msg->connection()->serverInfoReceived(szServer,umodes.ptr(),chanmodes.ptr());
// FIXME: #warning "TO ACTIVE ? OR TO CONSOLE ?"
if(!_OUTPUT_MUTE)
{
if(!msg->haltOutput())msg->console()->output(KVI_OUT_SERVERINFO,
__tr2qs("Server %Q version %S supporting user modes '%S' and channel modes '%S'"),
&szServer,&version,&umodes,&chanmodes);
}
}
void KviServerParser::parseNumeric005(KviIrcMessage *msg)
{
// 005: RPL_PROTOCTL [D]
// :prefix 005 target <proto> <proto> .... :are available/supported on this server
// 005: RPL_BOUNCE [?]
// :prefix 005 target :Try server <server>, port <port>
// 005: RPL_ISUPPORT
if(msg->connection()->context()->state() != KviIrcContext::Connected)
msg->connection()->loginComplete(msg->connection()->decodeText(msg->param(0)));
bool bUhNames = false;
bool bNamesx = false;
unsigned int count = msg->paramCount();
if(count > 2)
{
count--;
for(unsigned int i = 1;i < count;i++)
{
const char * p = msg->param(i);
if(kvi_strEqualCIN("PREFIX=(",p,8))
{
p+=8;
const char * pModes = p;
while(*p && (*p != ')'))p++;
KviStr szModeFlags(pModes,p-pModes);
if(*p)p++;
KviStr szModePrefixes = p;
if(szModePrefixes.hasData() && (szModePrefixes.len() == szModeFlags.len()))
{
msg->connection()->serverInfo()->setSupportedModePrefixes(szModePrefixes.ptr(),szModeFlags.ptr());
}
} else if(kvi_strEqualCIN("CHANTYPES=",p,10))
{
p+=10;
KviStr tmp = p;
if(tmp.hasData())msg->connection()->serverInfo()->setSupportedChannelTypes(tmp.ptr());
} else if(kvi_strEqualCI("WATCH",p) || kvi_strEqualCIN("WATCH=",p,6))
{
msg->connection()->serverInfo()->setSupportsWatchList(true);
if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
{
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the WATCH notify list method, it will be used"));
}
} else if(kvi_strEqualCIN("TOPICLEN=",p,9))
{
p += 9;
TQString tmp = p;
if(!tmp.isEmpty()) {
bool ok;
int len = tmp.toInt( &ok );
if(ok) msg->connection()->serverInfo()->setMaxTopicLen(len);
}
} else if(kvi_strEqualCIN("NETWORK=",p,8))
{
p += 8;
TQString tmp = p;
if(!tmp.isEmpty())msg->console()->connection()->target()->setNetworkName(tmp);
if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
{
msg->console()->output(KVI_OUT_SERVERINFO,__tr2qs("The current network is %Q"),&tmp);
}
} else if(kvi_strEqualCI("CODEPAGES",p))
{
msg->connection()->serverInfo()->setSupportsCodePages(true);
if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
{
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the CODEPAGE command, it will be used"));
}
//msg->connection()->sendFmtData("CODEPAGE %s",msg->console()->textCodec()->name());
} else if(kvi_strEqualCIN("CHANMODES=",p,10))
{
p+=10;
TQString tmp = p;
msg->connection()->serverInfo()->setSupportedChannelModes(tmp);
}else if(kvi_strEqualCIN("MODES=",p,6))
{
p+=6;
TQString tmp = p;
bool bok;
int num=tmp.toUInt(&bok);
if(bok)
msg->connection()->serverInfo()->setMaxModeChanges(num);
} else if(kvi_strEqualCIN("NAMESX",p,6))
{
p+=6;
bNamesx=true;
} else if(kvi_strEqualCIN("UHNAMES",p,7))
{
p+=7;
bUhNames=true;
}else if(kvi_strEqualCIN("CHARSET=",p,8))
{
p+=8;
TQString tmp = p;
msg->connection()->serverInfo()->setSupportsCodePages(true);
if((!_OUTPUT_MUTE) && (!msg->haltOutput()) && KVI_OPTION_BOOL(KviOption_boolShowExtendedServerInfo))
{
msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,__tr2qs("This server supports the CODEPAGE command, it will be used"));
}
/*if( tmp.contains(msg->console()->textCodec()->name(),false) || tmp.contains("*",false) )
{
msg->connection()->sendFmtData("CODEPAGE %s",msg->console()->textCodec()->name());
}*/
}
}
if((!_OUTPUT_MUTE) && (!msg->haltOutput()))
{
const char * aux = msg->allParams();
while(*aux == ' ')aux++;
while(*aux && (*aux != ' '))aux++;
while(*aux == ' ')aux++;
if(*aux == ':')aux++;
if(!msg->haltOutput())msg->console()->output(KVI_OUT_SERVERINFO,__tr2qs("This server supports: %s"),msg->connection()->decodeText(aux).utf8().data());
if(bNamesx || bUhNames) {
msg->connection()->sendFmtData("PROTOCTL %s %s",bNamesx ? "NAMESX" : "", bUhNames ? "UHNAMES" : "");
}
}
} else {
TQString inf = msg->connection()->decodeText(msg->safeTrailing());
if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,inf);
}
// } else {
// // RPL_BOUNCE prolly
// if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_SERVERINFO,msg->safeTrailing());
// }
}
void KviServerParser::parseNumericMotd(KviIrcMessage *msg)
{
// 372: RPL_MOTD [I,E,U,D]
// :prefix 372 target : - <motd>
// 377: RPL_MOTD2 [?]
// :prefix 377 target : - <motd>
// 378: RPL_MOTD3 [Austnet]
// :prefix 377 target : - <motd>
// 375: RPL_MOTDSTART [I,E,U,D]
// :prefix 375 target : - <server> Message of the Day -
// 372: RPL_ENDOFMOTD [I,E,U,D]
// :prefix 376 target :End of /MOTD command.
// FIXME: #warning "SKIP MOTD , MOTD IN A SEPARATE WINDOW , SILENT ENDOFMOTD , MOTD IN ACTIVE WINDOW"
if(!msg->haltOutput())msg->console()->outputNoFmt(KVI_OUT_MOTD,msg->connection()->decodeText(msg->safeTrailing()));
if(msg->numeric() == RPL_ENDOFMOTD)
{
msg->connection()->endOfMotdReceived();
}
}
void KviServerParser::parseNumericEndOfNames(KviIrcMessage *msg)
{
// 366: RPL_ENDOFNAMES [I,E,U,D]
// :prefix 366 target <channel> :End of /NAMES list.
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
if(!chan->hasAllNames())
{
chan->setHasAllNames();
return;
}
}
if(!msg->haltOutput() && !_OUTPUT_MUTE)
{
// FIXME: #warning "KVI_OUT_NAMES missing"
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_UNHANDLED,__tr2qs("End of NAMES for \r!c\r%Q\r"),&szChan);
}
}
void KviServerParser::parseNumeric020(KviIrcMessage *msg)
{
// 020: RPL_CONNECTING
//:irc.dotsrc.org 020 * :Please wait while we process your connection.
TQString szServer;
if(!msg->haltOutput())
{
TQString szWText = msg->console()->decodeText(msg->safeTrailing());
msg->console()->output(
KVI_OUT_CONNECTION,"%c\r!s\r%s\r%c: %Q",KVI_TEXT_BOLD,
msg->safePrefix(),KVI_TEXT_BOLD,&szWText);
}
}
void KviServerParser::parseNumericNames(KviIrcMessage *msg)
{
// 353: RPL_NAMREPLY [I,E,U,D]
// :prefix 353 target [=|*|@] <channel> :<space_separated_list_of_nicks>
// [=|*|@] is the type of the channel:
// = --> public * --> private @ --> secret
// ...but we ignore it
//TQString szChan = msg->connection()->decodeText(msg->cSafeParam(2)->data()); // <-- KviTQCString::data() is implicitly unsafe: it CAN return 0
TQString szChan = msg->connection()->decodeText(msg->safeParam(2));
KviChannel * chan = msg->connection()->findChannel(szChan);
// and run to the first nickname
char * aux = msg->safeTrailingString().ptr();
while((*aux) && (*aux == ' '))aux++;
// now check if we have that channel
char * trailing = aux;
bool bHalt = msg->haltOutput();
if(chan)
{
bHalt = bHalt || (!chan->hasAllNames());
// K...time to parse a lot of data
chan->enableUserListUpdates(false);
int iPrevFlags = chan->myFlags();
KviIrcConnectionServerInfo * pServerInfo = msg->connection()->serverInfo();
while(*aux)
{
int iFlags = 0;
// @ = op (+o), + = voiced (+v), % = halfop (+h), - = userop (+u), ^ = protected (+a?), * = chan owner (+q), !, & = channel admin (+a?)
// ^ +a is a weird mode: it also breaks nicknames on some networks!
// not a valid first char(s) of nickname, must be a mode prefix
bool bContinue = true;
while(pServerInfo->isSupportedModePrefix((unsigned char)(*aux)))
{
// leading umode flag(s)
iFlags |= pServerInfo->modeFlagFromPrefixChar(*aux);
aux++;
}
char * begin = aux;
while(*aux && (*aux != ' '))aux++;
char save = *aux;
*aux = 0;
// NAMESX + UHNAMES support
KviIrcMask mask(msg->connection()->decodeText(begin));
// and make it join
if(!mask.nick().isEmpty())chan->join(mask.nick(),
mask.hasUser() ? mask.user() : TQString(),
mask.hasHost() ? mask.host() : TQString(),
iFlags);
*aux = ' ';
*aux = save;
// run to the next nick (or the end)
while((*aux) && (*aux == ' '))aux++;
}
if(iPrevFlags != chan->myFlags())chan->updateCaption();
chan->enableUserListUpdates(true);
// finished a block
}
// So it is a result of a /NAMES command or a local desync
// We handle it in a cool way.
if(!bHalt)
{
// FIXME: #warning "KVI_OUT_NAMES missing"
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szTrailing = trailing ? msg->connection()->decodeText(trailing) : TQString("");
pOut->output(KVI_OUT_UNHANDLED,__tr2qs("Names for \r!c\r%Q\r: %Q"),&szChan,&szTrailing);
}
}
void KviServerParser::parseNumericTopic(KviIrcMessage *msg)
{
// 332: RPL_TOPIC [I,E,U,D]
// :prefix 332 target <channel> :<topic>
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
TQString szTopic = chan->decodeText(msg->safeTrailing());
chan->topicWidget()->setTopic(szTopic);
chan->topicWidget()->setTopicSetBy(__tr2qs("(unknown)"));
if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
{
if(!msg->haltOutput())
chan->output(KVI_OUT_TOPIC,__tr2qs("Channel topic is: %Q"),&szTopic);
}
} else {
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szTopic = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r is: %Q"),
&szChan,&szTopic);
}
}
void KviServerParser::parseNumericNoTopic(KviIrcMessage *msg)
{
// 331: RPL_NOTOPIC [I,E,U,D]
// :prefix 331 target <channel> :No topic is set
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
chan->topicWidget()->setTopic("");
if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
{
if(!msg->haltOutput())
chan->outputNoFmt(KVI_OUT_TOPIC,__tr2qs("No channel topic is set"));
}
} else {
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_TOPIC,__tr2qs("No topic is set for channel \r!c\r%Q\r"),
&szChan);
}
}
void KviServerParser::parseNumericTopicWhoTime(KviIrcMessage *msg)
{
// 333: RPL_TOPICWHOTIME [e,U,D]
// :prefix 333 target <channel> <whoset> <time>
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
KviStr tmp = msg->safeParam(3);
bool bOk = false;
unsigned long t = 0;
if(tmp.hasData())t = tmp.toUInt(&bOk);
TQDateTime dt;
dt.setTime_t(t);
TQString szDate = dt.toString();
TQString szWho = msg->connection()->decodeText(msg->safeParam(2));
KviIrcMask who(szWho);
TQString szDisplayableWho;
if( !(who.hasUser() && who.hasHost()) )
{
szDisplayableWho="\r!n\r"+szWho+"\r";
} else {
KviTQString::sprintf(szDisplayableWho,"\r!n\r%Q\r!%Q@\r!h\r%Q\r",&(who.nick()),&(who.user()),&(who.host()));
}
if(chan)
{
chan->topicWidget()->setTopicSetBy(szWho);
if(bOk)chan->topicWidget()->setTopicSetAt(szDate);
if(KVI_OPTION_BOOL(KviOption_boolEchoNumericTopic))
{
if(!msg->haltOutput())
{
if(bOk)chan->output(KVI_OUT_TOPIC,__tr2qs("Topic was set by %Q on %Q"),&szDisplayableWho,&szDate);
else chan->output(KVI_OUT_TOPIC,__tr2qs("Topic was set by %Q"),&szDisplayableWho);
}
}
} else {
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
if(bOk)
{
pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r was set by %Q on %Q"),
&szChan,&szDisplayableWho,&szDate);
} else {
pOut->output(KVI_OUT_TOPIC,__tr2qs("Topic for \r!c\r%Q\r was set by %Q"),
&szChan,&szDisplayableWho);
}
}
}
void KviServerParser::parseNumericChannelModeIs(KviIrcMessage *msg)
{
// 324: RPL_CHANNELMODEIS [I,E,U,D]
// :prefix 324 target <channel> +<chanmode>
TQString szSource = msg->connection()->decodeText(msg->safePrefix());
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
KviStr modefl = msg->safeParam(2);
if(chan)parseChannelMode(szSource,"*","*",chan,modefl,msg,3);
else {
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
if((!szChan.isEmpty()) && IS_CHANNEL_TYPE_FLAG(szChan[0]))
{
pOut->output(KVI_OUT_CHANMODE,__tr2qs("Channel mode for \r!c\r%Q\r is %s"),
&szChan,msg->safeParam(2));
} else {
pOut->output(KVI_OUT_MODE,__tr2qs("User mode for \r!n\r%Q\r is %s"),
&szChan,msg->safeParam(2));
}
}
}
void getDateTimeStringFromCharTimeT(TQString &buffer,const char *time_t_string)
{
KviStr tmp=time_t_string;
bool bOk=false;
unsigned int uTime = tmp.toUInt(&bOk);
if(bOk){
TQDateTime dt;
dt.setTime_t(uTime);
buffer = dt.toString();
} else buffer = __tr2qs("(Unknown)");
}
#define PARSE_NUMERIC_ENDOFLIST(__funcname,__setGotIt,__didSendRequest,__setDone,__daicon,__szWhatTQString) \
void KviServerParser::__funcname(KviIrcMessage *msg) \
{ \
TQString szChan = msg->connection()->decodeText(msg->safeParam(1)); \
KviChannel * chan = msg->connection()->findChannel(szChan); \
if(chan) \
{ \
chan->__setGotIt(); \
if(chan->__didSendRequest()) \
{ \
chan->__setDone(); \
return; \
} \
} \
if(!msg->haltOutput()) \
{ \
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ? \
msg->console()->activeWindow() : (KviWindow *)(msg->console()); \
pOut->output(__daicon,__tr2qs("End of channel %Q for \r!c\r%Q\r"),&(__szWhatTQString),&szChan); \
} \
}
PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfBanList,setHasBanList,sentBanListRequest,setBanListDone,KVI_OUT_BAN,__tr2qs("ban list"))
PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfInviteList,setHasInviteList,sentInviteListRequest,setInviteListDone,KVI_OUT_INVITEEXCEPT,__tr2qs("invite list"))
PARSE_NUMERIC_ENDOFLIST(parseNumericEndOfExceptList,setHasBanExceptionList,sentBanExceptionListRequest,setBanExceptionListDone,KVI_OUT_BANEXCEPT,__tr2qs("ban exception list"))
#define PARSE_NUMERIC_LIST(__funcname,__modechar,__sentRequest,__ico,__szWhatTQString) \
void KviServerParser::__funcname(KviIrcMessage *msg) \
{ \
TQString szChan = msg->connection()->decodeText(msg->safeParam(1)); \
TQString banmask = msg->connection()->decodeText(msg->safeParam(2)); \
TQString bansetby = msg->connection()->decodeText(msg->safeParam(3)); \
TQString bansetat; \
getDateTimeStringFromCharTimeT(bansetat,msg->safeParam(4)); \
if(bansetby.isEmpty())bansetby = __tr2qs("(Unknown)"); \
KviChannel * chan = msg->connection()->findChannel(szChan); \
if(chan) \
{ \
chan->setMask(__modechar,banmask,true,bansetby,TQString(msg->safeParam(4)).toUInt()); \
if(chan->__sentRequest())return; \
} \
if(!msg->haltOutput()) \
{ \
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ? \
msg->console()->activeWindow() : (KviWindow *)(msg->console()); \
pOut->output(__ico,__tr2qs("%Q for \r!c\r%Q\r: \r!m-%c\r%Q\r (set by %Q on %Q)"), \
&(__szWhatTQString),&szChan,__modechar,&banmask,&bansetby,&bansetat); \
} \
}
// 367: RPL_BANLIST [I,E,U,D]
// :prefix 367 target <channel> <banmask> [bansetby] [bansetat]
PARSE_NUMERIC_LIST(parseNumericBanList,'b',sentBanListRequest,KVI_OUT_BAN,__tr2qs("Ban listing"))
// 346: RPL_INVITELIST [I,E,U,D]
// :prefix 346 target <channel> <invitemask> [invitesetby] [invitesetat]
PARSE_NUMERIC_LIST(parseNumericInviteList,'I',sentInviteListRequest,KVI_OUT_INVITEEXCEPT,__tr2qs("Invite listing"))
// 346: RPL_EXCEPTLIST [I,E,U,D]
// :prefix 346 target <channel> <banmask> [bansetby] [bansetat]
PARSE_NUMERIC_LIST(parseNumericExceptList,'e',sentBanExceptionListRequest,KVI_OUT_BANEXCEPT,__tr2qs("Ban exception listing"));
void KviServerParser::parseNumericWhoReply(KviIrcMessage *msg)
{
// 352: RPL_WHOREPLY [I,E,U,D]
// :prefix 352 target <chan> <usr> <hst> <srv> <nck> <stat> :<hops> <real>
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
TQString szUser = msg->connection()->decodeText(msg->safeParam(2));
TQString szHost = msg->connection()->decodeText(msg->safeParam(3));
TQString szServ = msg->connection()->decodeText(msg->safeParam(4));
TQString szNick = msg->connection()->decodeText(msg->safeParam(5));
TQString szFlag = msg->connection()->decodeText(msg->safeParam(6));
bool bAway = szFlag.find('G') != -1;
KviStr trailing = msg->safeTrailing();
KviStr hops = trailing.getToken(' ');
bool bHopsOk = false;
int iHops = hops.toInt(&bHopsOk);
TQString szReal = msg->connection()->decodeText(trailing.ptr());
// Update the user entry
KviIrcUserDataBase * db = msg->connection()->userDataBase();
KviIrcUserEntry * e = db->find(szNick);
if(e)
{
if(bHopsOk)e->setHops(iHops);
e->setUser(szUser);
e->setHost(szHost);
e->setServer(szServ);
e->setRealName(szReal);
e->setAway(bAway);
KviQuery * q = msg->connection()->findQuery(szNick);
if(q) q->updateLabelText();
if(!e->avatar())
{
// FIXME: #warning "THE AVATAR SHOULD BE RESIZED TO MATCH THE MAX WIDTH/HEIGHT"
// maybe now we can match this user ?
msg->console()->checkDefaultAvatar(e,szNick,szUser,szHost);
}
}
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
if(!chan->hasWhoList())
{
// FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
return;
}
if(chan->sentSyncWhoRequest())
{
// FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
return;
}
}
// FIXME: #warning "SYNC OP/VOICE on channel!!!"
if(!msg->haltOutput())
{
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szAway = bAway ? __tr2qs("Yes") : __tr2qs("No");
pOut->output(KVI_OUT_WHO,
__tr2qs("WHO entry for %c\r!n\r%Q\r%c [%Q@\r!h\r%Q\r]: %cChannel%c: \r!c\r%Q\r, %cServer%c: \r!s\r%Q\r, %cHops%c: %d, %cFlags%c: %Q, %cAway%c: %Q, %cReal name%c: %Q"),
KVI_TEXT_BOLD,&szNick, KVI_TEXT_BOLD,
&szUser,&szHost,KVI_TEXT_UNDERLINE,
KVI_TEXT_UNDERLINE,&szChan,KVI_TEXT_UNDERLINE,
KVI_TEXT_UNDERLINE,&szServ,KVI_TEXT_UNDERLINE,
KVI_TEXT_UNDERLINE,iHops, KVI_TEXT_UNDERLINE, KVI_TEXT_UNDERLINE,
&szFlag, KVI_TEXT_UNDERLINE, KVI_TEXT_UNDERLINE,
&szAway, KVI_TEXT_UNDERLINE,
KVI_TEXT_UNDERLINE, &szReal);
}
}
void KviServerParser::parseNumericEndOfWho(KviIrcMessage *msg)
{
// 315: RPL_ENDOFWHO [I,E,U,D]
// :prefix 315 target <channel/nick> :End of /WHO List.
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
chan->userListView()->updateArea();
kvi_time_t tNow = kvi_unixTime();
msg->connection()->stateData()->setLastReceivedChannelWhoReply(tNow);
chan->setLastReceivedWhoReply(tNow);
if(msg->connection()->lagMeter())
{
KviStr tmp(KviStr::Format,"WHO %s",msg->safeParam(1));
msg->connection()->lagMeter()->lagCheckComplete(tmp.ptr());
}
if(!chan->hasWhoList())
{
// FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
chan->setHasWhoList();
return;
}
if(chan->sentSyncWhoRequest())
{
// FIXME: #warning "IF VERBOSE && SHOW INTERNAL WHO REPLIES...."
chan->clearSentSyncWhoRequest();
return;
}
}
if(!msg->haltOutput())
{
KviWindow * pOut = chan ? chan : KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString whoTarget = msg->connection()->decodeText(msg->safeParam(1));
if(IS_CHANNEL_TYPE_FLAG(whoTarget[0]))
whoTarget.prepend("\r!c\r");
else
whoTarget.prepend("\r!n\r");
whoTarget.append("\r");
pOut->output(KVI_OUT_WHO,__tr2qs("End of WHO list for %Q"),&whoTarget);
}
}
void KviServerParser::parseLoginNicknameProblem(KviIrcMessage *msg)
{
// ops...not logged in yet...
TQString nextNick;
unsigned int uNickCnt;
switch(msg->connection()->stateData()->loginNickIndex())
{
case 0:
// used a server specific nickname
KVI_OPTION_STRING(KviOption_stringNickname1).stripWhiteSpace();
if(KVI_OPTION_STRING(KviOption_stringNickname1).isEmpty())
KVI_OPTION_STRING(KviOption_stringNickname1) = KVI_DEFAULT_NICKNAME1;
nextNick = KVI_OPTION_STRING(KviOption_stringNickname1);
uNickCnt = 1;
case 1:
// used the first nickname of the identity
KVI_OPTION_STRING(KviOption_stringNickname2).stripWhiteSpace();
if(KVI_OPTION_STRING(KviOption_stringNickname2).isEmpty())
KVI_OPTION_STRING(KviOption_stringNickname2) = KVI_DEFAULT_NICKNAME2;
nextNick = KVI_OPTION_STRING(KviOption_stringNickname2);
uNickCnt = 2;
break;
case 2:
// used the second nickname of the identity
KVI_OPTION_STRING(KviOption_stringNickname3).stripWhiteSpace();
if(KVI_OPTION_STRING(KviOption_stringNickname3).isEmpty())
KVI_OPTION_STRING(KviOption_stringNickname3) = KVI_DEFAULT_NICKNAME3;
nextNick = KVI_OPTION_STRING(KviOption_stringNickname3);
uNickCnt = 3;
break;
default:
{
// used all the nicknames of the identity
// fall back to a random string...
nextNick = msg->safeParam(1);
nextNick.stripWhiteSpace();
if(nextNick.isEmpty())nextNick = KVI_DEFAULT_NICKNAME1;
nextNick = nextNick.left(7);
TQString num;
num.setNum(msg->connection()->stateData()->loginNickIndex());
nextNick.append(num);
uNickCnt = msg->connection()->stateData()->loginNickIndex() + 1;
}
break;
}
TQString szOldNick = msg->connection()->userInfo()->nickName();
msg->console()->notifyListView()->nickChange(szOldNick,nextNick);
msg->connection()->userInfo()->setNickName(nextNick);
msg->connection()->stateData()->setLoginNickIndex(uNickCnt);
if(uNickCnt > 7)
{
msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
__tr2qs("Something really weird is happening: the server is refusing all the login nicknames..."));
if(msg->connection()->stateData()->loginNickIndex() > 10)
{
msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
__tr2qs("The server is refusing all the login nicknames: giving up, you must send the nickname manually"));
return;
}
}
if(!msg->haltOutput())
{
TQString szActual = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
__tr2qs("No way to login as '\r!n\r%Q\r' (%d: %Q), trying '%Q'..."),
&szActual,msg->numeric(),&szWText,&nextNick);
}
KviTQCString d = msg->connection()->encodeText(nextNick);
msg->connection()->sendFmtData("NICK %s",d.data());
}
void KviServerParser::parseNumericUnavailResource(KviIrcMessage *msg)
{
// 437: ERR_UNAVAILRESOURCE [I]
// :prefix 437 <target> <nick/channel> :Nick/Channel is temporairly unavailable
if(!(msg->console()->isConnected()))
{
parseLoginNicknameProblem(msg);
} else {
// already connected... just say that we have problems
if(!msg->haltOutput())
{
TQString szNk = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
"\r!n\r%Q\r: %Q",&szNk,&szWText);
}
}
}
void KviServerParser::parseNumericCantJoinChannel(KviIrcMessage *msg)
{
// 471: ERR_CHANNELISFULL [I,E,U,D]
// 473: ERR_INVITEONLYCHAN [I,E,U,D]
// 474: ERR_BANNEDFROMCHAN [I,E,U,D]
// 475: ERR_BADCHANNELKEY [I,E,U,D]
// :prefix 47* <target> <channel> :Can't join channel (+l/i/b/k)
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->connection()->findChannel(msg->safeParam(1)));
if(!pOut)pOut = (KviWindow *)(msg->console());
TQString szChannel = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_JOINERROR,
"\r!c\r%Q\r: %Q",&szChannel,&szWText);
}
}
// Keep the source ordered: this should be named "parseOtherChannelError"
void KviServerParser::otherChannelError(KviIrcMessage *msg)
{
// 482: ERR_CHANOPRIVSNEEDED
// 467: ERR_KEYSET
// 472: ERR_UNKNOWNMODE
// :prefix 4?? <target> <channel> :error text
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->connection()->findChannel(msg->safeParam(1)));
if(!pOut)pOut = (KviWindow *)(msg->console());
TQString szChannel = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_GENERICERROR,
"\r!c\r%Q\r: %Q",&szChannel,&szWText);
}
}
void KviServerParser::parseCommandSyntaxHelp(KviIrcMessage *msg)
{
// 704 RPL_COMMANDSYNTAX
// :prefix 704 <target> <command> :text
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szCommand = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_HELP,
__tr2qs("Command syntax %Q: %Q"),&szCommand,&szWText); // Pragma: wheee..... that should be in english :D
}
}
void KviServerParser::parseCommandHelp(KviIrcMessage *msg)
{
// 705 RPL_COMMANDHELP
// :prefix 705 <target> <command> :text
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szCommand = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
pOut->outputNoFmt(KVI_OUT_HELP,szWText);
}
}
void KviServerParser::parseChannelHelp(KviIrcMessage *msg)
{
// 477 RPL_CHANNELHELP (freenode)
// :prefix 477 <target> <channel> :text
if(!msg->haltOutput())
{
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
TQString szText = msg->connection()->decodeText(msg->safeTrailing());
KviWindow * pOut = msg->connection()->findChannel(szChan);
if(pOut)
{
pOut->output(KVI_OUT_HELP,__tr2qs("Tip: %Q"),&szText);
} else {
pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_HELP,__tr2qs("Tip for %Q: %Q"),&szChan,&szText);
}
}
}
void KviServerParser::parseCommandEndOfHelp(KviIrcMessage *msg)
{
// 704 RPL_COMMANDSYNTAX
// 705 RPL_COMMANDHELP
// :prefix 706 <target> <command> :End of /HELP.
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szCommand = msg->connection()->decodeText(msg->safeParam(1));
pOut->output(KVI_OUT_HELP,
__tr2qs("End of help about %Q"),&szCommand);
}
}
void KviServerParser::parseNumericNicknameProblem(KviIrcMessage *msg)
{
// 433: ERR_NICKNAMEINUSE [I,E,U,D]
// :prefix 433 <target> <nick> :Nickname is already in use.
// 432: ERR_ERRONEUSNICKNAME [I,E,U,D]
// :prefix 433 <target> <nick> :Erroneous nickname
if(!(msg->console()->isConnected()))
{
parseLoginNicknameProblem(msg);
} else {
// already connected... just say that we have problems
if(!msg->haltOutput())
{
TQString szNk = msg->connection()->decodeText(msg->safeParam(1));
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
msg->console()->output(KVI_OUT_NICKNAMEPROBLEM,
"\r!n\r%Q\r: %Q",&szNk,&szWText);
}
}
}
void KviServerParser::parseNumericWhoisAway(KviIrcMessage * msg)
{
// FIXME: #warning "Need an icon here too: sth like KVI_OUT_WHOISSERVER, but with 'A' letter"
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNk = msg->connection()->decodeText(msg->safeParam(1));
KviIrcUserDataBase * db = msg->connection()->userDataBase();
KviIrcUserEntry * e = db->find(szNk);
if(e)e->setAway(true);
KviQuery * q = msg->connection()->findQuery(szNk);
if(q) q->updateLabelText();
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->connection()->findQuery(szNk));
TQString szWText = pOut ? pOut->decodeText(msg->safeTrailing()) : msg->connection()->decodeText(msg->safeTrailing());
if(!pOut)pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c is away: %Q"),
KVI_TEXT_BOLD,&szNk,KVI_TEXT_BOLD,&szWText);
}
}
void KviServerParser::parseNumericWhoisUser(KviIrcMessage *msg)
{
// 311: RPL_WHOISUSER [I,E,U,D]
// :prefix 311 <target> <nick> <user> <host> * :<real_name>
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szUser = msg->connection()->decodeText(msg->safeParam(2));
TQString szHost = msg->connection()->decodeText(msg->safeParam(3));
TQString szReal = msg->connection()->decodeText(msg->safeTrailing());
KviIrcUserDataBase * db = msg->connection()->userDataBase();
KviIrcUserEntry * e = db->find(szNick);
if(e)
{
e->setUser(szUser);
e->setHost(szHost);
e->setRealName(szReal);
if(e->gender()!=KviIrcUserEntry::Unknown) {
if(KviTQString::equalCS(g_pActiveWindow->className(),TQString("KviChannel")))
{
((KviChannel*)g_pActiveWindow)->userListView()->updateArea();
}
}
KviQuery * q = msg->connection()->findQuery(szNick);
if(q) q->updateLabelText();
if(!e->avatar())
{
// FIXME: #warning "THE AVATAR SHOULD BE RESIZED TO MATCH THE MAX WIDTH/HEIGHT"
// maybe now we can match this user ?
msg->console()->checkDefaultAvatar(e,szNick,szUser,szHost);
}
}
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
i->szNick = szNick;
i->szUser = szUser;
i->szHost = szHost;
i->szReal = szReal;
return;
}
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(
KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c is %c\r!n\r%Q\r!%Q@\r!h\r%Q\r%c"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,KVI_TEXT_UNDERLINE,&szNick,
&szUser,&szHost,KVI_TEXT_UNDERLINE);
pOut->output(
KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c's real name: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szReal);
}
}
void KviServerParser::parseNumericWhowasUser(KviIrcMessage * msg)
{
// 314: RPL_WHOWASUSER [I,E,U,D]
// :prefix 314 <target> <nick> <user> <host> * :<real_name>
if(!msg->haltOutput())
{
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szUser = msg->connection()->decodeText(msg->safeParam(2));
TQString szHost = msg->connection()->decodeText(msg->safeParam(3));
TQString szReal = msg->connection()->decodeText(msg->safeTrailing());
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(
KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c was %c\r!n\r%Q\r!%Q@\r!h\r%Q\r%c"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,KVI_TEXT_UNDERLINE,&szNick,
&szUser,&szHost,KVI_TEXT_UNDERLINE);
pOut->output(
KVI_OUT_WHOISUSER,__tr2qs("%c\r!n\r%Q\r%c's real name was: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szReal);
}
}
void KviServerParser::parseNumericWhoisChannels(KviIrcMessage *msg)
{
// 319: RPL_WHOISCHANNELS [I,E,U,D]
// :prefix 319 <target> <nick> :<channel list>
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szChans = msg->connection()->decodeText(msg->safeTrailing());
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
i->szChannels = szChans;
return;
}
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQStringList sl = TQStringList::split(" ",szChans);
TQString szChanList;
for(TQStringList::Iterator it = sl.begin();it != sl.end();++it)
{
TQString szCur = *it;
// deals with <flag>[#channel] and [##channel]
int len = szCur.length();
int i =0;
while(i < len)
{
if(IS_CHANNEL_TYPE_FLAG(szCur[i]) && (!IS_USER_MODE_PREFIX(szCur[i])))break;
i++;
}
if(i < len)
{
if(i > 0)
{
len = szCur.length() - i;
if(szChanList.length() > 0)szChanList.append(", ");
szChanList += szCur.left(i);
TQString szR = szCur.right(len);
KviTQString::appendFormatted(szChanList,"\r!c\r%Q\r",&szR);
} else {
if(szChanList.length() > 0)szChanList.append(", ");
KviTQString::appendFormatted(szChanList,"\r!c\r%Q\r",&szCur);
}
} else {
// we dunno what is this.. just append
if(szChanList.length() > 0)szChanList.append(", ");
szChanList.append(szCur);
}
}
pOut->output(
KVI_OUT_WHOISCHANNELS,__tr2qs("%c\r!n\r%Q\r%c's channels: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szChanList);
}
}
void KviServerParser::parseNumericWhoisIdle(KviIrcMessage *msg)
{
// 317: RPL_WHOISIDLE [I,E,U,D]
// :prefix 317 <target> <nick> <number> <number> :seconds idle, signon time
// FIXME: #warning "and NICK LINKS"
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
i->szIdle = msg->safeParam(2);
i->szSignon = msg->safeParam(3);
bool bOk = false;
i->szSignon.toUInt(&bOk);
if(!bOk)i->szSignon = "";
return;
}
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
KviStr idle = msg->safeParam(2); // shouldn't be encoded
KviStr sign = msg->safeParam(3); // shouldn't be encoded
bool bOk;
unsigned int uTime = idle.toUInt(&bOk);
if(!bOk)
{
UNRECOGNIZED_MESSAGE(msg,__tr2qs("Received a broken RPL_WHOISIDLE, can't evaluate the idle time"));
return;
}
unsigned int uDays = uTime / 86400;
uTime = uTime % 86400;
unsigned int uHours = uTime / 3600;
uTime = uTime % 3600;
unsigned int uMins = uTime / 60;
uTime = uTime % 60;
pOut->output(
KVI_OUT_WHOISIDLE,__tr2qs("%c\r!n\r%Q\r%c's idle time: %ud %uh %um %us"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,uDays,uHours,uMins,uTime);
uTime = sign.toUInt(&bOk);
if(bOk)
{
TQDateTime dt;
dt.setTime_t((time_t)uTime);
TQString tmp = dt.toString();
pOut->output(
KVI_OUT_WHOISIDLE,__tr2qs("%c\r!n\r%Q\r%c's signon time: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&tmp);
}
}
}
void KviServerParser::parseNumericWhoisServer(KviIrcMessage *msg)
{
// 312: RPL_WHOISSERVER [I,E,U,D] (sent also in response to WHOWAS)
// :prefix 312 <target> <nick> <server> :<server description / last whowas date>
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szServ = msg->connection()->decodeText(msg->safeParam(2));
KviIrcUserDataBase * db = msg->connection()->userDataBase();
KviIrcUserEntry * e = db->find(szNick);
if(e)e->setServer(szServ);
KviQuery * q = msg->connection()->findQuery(szNick);
if(q) q->updateLabelText();
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(msg->safeParam(1));
if(i)
{
i->szServer = szServ;
return;
}
// FIXME: #warning "AWHOIS HERE.... and NICK LINKS"
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szWText = pOut->decodeText(msg->safeTrailing());
pOut->output(
KVI_OUT_WHOISSERVER,__tr2qs("%c\r!n\r%Q\r%c's server: \r!s\r%Q\r - %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szServ,&szWText);
}
}
void KviServerParser::parseNumericWhoisAuth(KviIrcMessage *msg)
{
// :prefix RPL_WHOISAUTH <target> <nick> :is authed as
// actually seen only on Quakenet
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szAuth = msg->connection()->decodeText(msg->safeParam(2));
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(
KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c is authenticated as %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szAuth);
}
}
void KviServerParser::parseNumericWhoisOther(KviIrcMessage *msg)
{
// *: RPL_WHOIS* [?]
// :prefix * <target> <nick> :<description>
// used for RPL_WHOISCHANOP,RPL_WHOISADMIN,
// RPL_WHOISSADMIN,RPL_WHOISOPERATOR,RPL_WHOISREGNICK,RPL_WHOISSSL
// and all the other unrecognized codes that look really like a RPL_WHOIS*
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szOth = msg->connection()->decodeText(msg->safeTrailing());
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
if(!(i->szServer.isEmpty()))i->szServer.append(',');
i->szServer.append(szOth);
return;
}
// FIXME: #warning "NICK LINKS"
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(
KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c's info: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szOth);
}
}
// FIXME: #warning "WHOWAS MISSING"
void KviServerParser::parseNumericEndOfWhois(KviIrcMessage *msg)
{
// 318: RPL_ENDOFWHOIS [I,E,U,D]
// :prefix 318 <target> <nick> :End of /WHOIS list
msg->connection()->stateData()->setLastReceivedWhoisReply(0);
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
if(!g_pApp->windowExists(i->pWindow))i->pWindow = msg->console();
// that's the new KVS engine!
KviKvsVariantList vl;
vl.setAutoDelete(true);
vl.append(new KviKvsVariant(i->szNick));
vl.append(new KviKvsVariant(i->szUser));
vl.append(new KviKvsVariant(i->szHost));
vl.append(new KviKvsVariant(i->szReal));
vl.append(new KviKvsVariant(i->szServer));
vl.append(new KviKvsVariant(i->szIdle));
vl.append(new KviKvsVariant(i->szSignon));
vl.append(new KviKvsVariant(i->szChannels));
vl.append(new KviKvsVariant(TQString(msg->safePrefix())));
vl.append(new KviKvsVariant(i->szSpecial));
vl.append(new KviKvsVariant(*(i->pMagic)));
i->pCallback->run(i->pWindow,&vl,0,KviKvsScript::PreserveParams);
msg->connection()->asyncWhoisData()->remove(i);
return;
}
// FIXME: #warning "NICK LINKS"
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString pref = msg->connection()->decodeText(msg->safePrefix());
pOut->output(
KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c WHOIS info from \r!s\r%Q\r"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&pref);
}
}
void KviServerParser::parseNumericEndOfWhowas(KviIrcMessage *msg)
{
// 369: RPL_ENDOFWHOWAS [I,E,U,D]
// :prefix 369 <target> <nick> :End of /WHOWAS list
if(!msg->haltOutput())
{
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString pref = msg->connection()->decodeText(msg->safePrefix());
pOut->output(
KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c WHOWAS info from \r!s\r%Q\r"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&pref);
}
}
void KviServerParser::parseNumericNoSuchNick(KviIrcMessage *msg)
{
// 401: ERR_NOSUCHNICK [I,E,U,D]
// 406: ERR_WASNOSUCHNICK [I,E,U,D]
// :prefix 401 <target> <nick> :No such nick/channel
// :prefix 406 <target> <nick> :There was no such nickname
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
if(msg->numeric() == ERR_NOSUCHNICK)
{
KviAsyncWhoisInfo * i = msg->connection()->asyncWhoisData()->lookup(szNick);
if(i)
{
if(!g_pApp->windowExists(i->pWindow))i->pWindow = msg->console();
// that's the new KVS engine!
KviKvsVariantList vl;
vl.setAutoDelete(true);
vl.append(new KviKvsVariant(i->szNick));
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant());
vl.append(new KviKvsVariant(*(i->pMagic)));
i->pCallback->run(i->pWindow,&vl,0,KviKvsScript::PreserveParams);
msg->connection()->asyncWhoisData()->remove(i);
return;
}
}
// FIXME: #warning "KVI_OUT_NOSUCHNICKCHANNEL ?"
// FIXME: #warning "QUERIES SHOULD REPORT NO TARGET HERE! (?)"
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->connection()->findQuery(szNick));
if(!pOut)
{
pOut = (KviWindow *)(msg->console()->activeWindow());
}
//} else {
// ((KviQuery *)pOut)->removeTarget(msg->safeParam(1));
//}
TQString szWText = pOut->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_NICKNAMEPROBLEM,"\r!n\r%Q\r: %Q",
&szNick,&szWText);
}
}
void KviServerParser::parseNumericCreationTime(KviIrcMessage *msg)
{
// 329: RPL_CREATIONTIME
// :prefix 329 <target> <channel> <creation_time>
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
KviChannel * chan = msg->connection()->findChannel(szChan);
KviStr tmstr = msg->safeParam(2);
TQDateTime dt;
dt.setTime_t((time_t)tmstr.toUInt());
if(!tmstr.isUnsignedNum())
{
UNRECOGNIZED_MESSAGE(msg,__tr2qs("Can't evaluate creation time"));
return;
}
TQString szDate = dt.toString();
if(chan)
{
if(!msg->haltOutput())
{
chan->output(KVI_OUT_CREATIONTIME,__tr2qs("Channel was created at %Q"),&szDate);
}
} else {
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_CREATIONTIME,__tr2qs("Channel \r!c\r%Q\r was created at %Q"),
&szChan,&szDate);
}
}
void KviServerParser::parseNumericIsOn(KviIrcMessage *msg)
{
// 303: RPL_ISON
// :prefix 303 <target> :<ison replies>
if(msg->connection()->notifyListManager())
{
if(msg->connection()->notifyListManager()->handleIsOn(msg))return;
}
// not handled...output it
// FIXME: #warning "OUTPUT IT! (In a suitable way)"
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szPrefix = msg->connection()->decodeText(msg->safePrefix());
TQString szAllParms = msg->connection()->decodeText(msg->allParams());
pOut->output(KVI_OUT_UNHANDLED,
"[%Q][%s] %Q",&szPrefix,msg->command(),&szAllParms);
}
}
void KviServerParser::parseNumericUserhost(KviIrcMessage *msg)
{
// 302: RPL_USERHOST
// :prefix 302 <target> :<userhost replies>
if(msg->connection()->notifyListManager())
{
if(msg->connection()->notifyListManager()->handleUserhost(msg))return;
}
// not handled...output it
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szUser = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_WHOISUSER,__tr2qs("USERHOST info: %Q"),&szUser);
}
}
void KviServerParser::parseNumericListStart(KviIrcMessage *msg)
{
// 321: RPL_LISTSTART [I,E,U,D]
// :prefix 321 <target> :Channel users name
if(msg->haltOutput())return; // stopped by raw
if(!(msg->console()->ircContext()->listWindow()))
{
// attempt to load the module...
msg->console()->ircContext()->createListWindow();
}
if(msg->console()->ircContext()->listWindow())
{
// module loaded
msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA);
} else {
msg->console()->output(KVI_OUT_LIST,__tr2qs("Channel list begin: channel, users, topic"));
}
}
void KviServerParser::parseNumericList(KviIrcMessage *msg)
{
// 322: RPL_LIST [I,E,U,D]
// :prefix 364 <target> <channel> <users> :<topic>
if(msg->haltOutput())return; // stopped by raw
if(!(msg->console()->ircContext()->listWindow()))
{
// attempt to load the module...
msg->console()->ircContext()->createListWindow();
if(msg->console()->ircContext()->listWindow())
{
msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_STARTOFDATA);
}
}
if(msg->console()->ircContext()->listWindow())
{
// module loaded
msg->console()->ircContext()->listWindow()->processData(msg);
} else {
// ops...can't load the module...
TQString szList = msg->connection()->decodeText(msg->allParams());
msg->console()->output(KVI_OUT_LIST,__tr2qs("List: %Q"),&szList);
}
}
void KviServerParser::parseNumericListEnd(KviIrcMessage *msg)
{
// 323: RPL_LISTEND [I,E,U,D]
// :prefix 323 <target> :End of /LIST
if(msg->haltOutput())return; // stopped by raw
if(msg->console()->ircContext()->listWindow())
{
msg->console()->ircContext()->listWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA);
} else {
msg->console()->output(KVI_OUT_LIST,__tr2qs("End of LIST"));
}
}
void KviServerParser::parseNumericLinks(KviIrcMessage *msg)
{
// 364: RPL_LINKS [I,E,U,D]
// :prefix 364 <target> <host> <parent> :<hops> <description>
if(!(msg->console()->ircContext()->linksWindow()))
{
// attempt to load the module...
msg->console()->ircContext()->createLinksWindow();
}
if(msg->console()->ircContext()->linksWindow())
{
// module loaded
msg->console()->ircContext()->linksWindow()->processData(msg);
} else {
// ops...can't load the module... or the event halted the window creation
if(!msg->haltOutput())
{
TQString szList = msg->connection()->decodeText(msg->allParams());
msg->console()->output(KVI_OUT_LINKS,__tr2qs("Link: %Q"),&szList);
}
}
}
void KviServerParser::parseNumericEndOfLinks(KviIrcMessage *msg)
{
// 365: RPL_ENDOFLINKS [I,E,U,D]
// :prefix 365 <target> :End of /LINKS
if(msg->console()->ircContext()->linksWindow())
{
msg->console()->ircContext()->linksWindow()->control(EXTERNAL_SERVER_DATA_PARSER_CONTROL_ENDOFDATA);
} else {
if(!msg->haltOutput())
{
msg->console()->output(KVI_OUT_LINKS,__tr2qs("End of LINKS"));
}
}
}
void KviServerParser::parseNumericBackFromAway(KviIrcMessage * msg)
{
// 305: RPL_UNAWAY [I,E,U,D]
// :prefix 305 <target> :You are no longer away
bool bWasAway = msg->connection()->userInfo()->isAway();
TQString szNickBeforeAway;
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
if(bWasAway)szNickBeforeAway = msg->connection()->userInfo()->nickNameBeforeAway();
msg->connection()->changeAwayState(false);
// trigger the event
TQString tmp;
KviTQString::sprintf(tmp,"%u",bWasAway ? (unsigned int)(msg->connection()->userInfo()->awayTime()) : 0);
if(KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnMeBack,msg->console(),tmp,szWText))
msg->setHaltOutput();
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
if(bWasAway)
{
int uTimeDiff = bWasAway ? (kvi_unixTime() - msg->connection()->userInfo()->awayTime()) : 0;
pOut->output(KVI_OUT_AWAY,__tr2qs("[Leaving away status after %ud %uh %um %us]: %Q"),
uTimeDiff / 86400,(uTimeDiff % 86400) / 3600,(uTimeDiff % 3600) / 60,uTimeDiff % 60,
&szWText);
} else {
pOut->output(KVI_OUT_AWAY,__tr2qs("[Leaving away status]: %Q"),&szWText);
}
}
if(KVI_OPTION_BOOL(KviOption_boolChangeNickAway) && bWasAway && (!(szNickBeforeAway.isEmpty())))
{
if(_OUTPUT_PARANOIC)
msg->console()->output(KVI_OUT_AWAY,__tr2qs("Restoring pre-away nickname (%Q)"),&szNickBeforeAway);
KviTQCString szDat = msg->connection()->encodeText(szNickBeforeAway);
msg->connection()->sendFmtData("NICK %s",szDat.data());
}
}
void KviServerParser::parseNumericAway(KviIrcMessage * msg)
{
// 306: RPL_NOWAWAY [I,E,U,D]
// :prefix 305 <target> :You're away man
msg->connection()->changeAwayState(true);
TQString szWText = msg->connection()->decodeText(msg->safeTrailing());
if(KVS_TRIGGER_EVENT_1_HALTED(KviEvent_OnMeAway,msg->console(),szWText))msg->setHaltOutput();
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_AWAY,__tr2qs("[Entering away status]: %Q"),&szWText);
}
if(KVI_OPTION_BOOL(KviOption_boolChangeNickAway))
{
TQString nick = msg->connection()->decodeText(msg->safeParam(0));
TQString szNewNick;
if(KVI_OPTION_BOOL(KviOption_boolAutoGeneratedAwayNick))
{
if(nick.length() > 5)szNewNick = nick.left(5);
else szNewNick = nick;
szNewNick.append("AWAY");
} else {
szNewNick = KVI_OPTION_STRING(KviOption_stringCustomAwayNick);
szNewNick.replace("%nick%",nick);
}
if(_OUTPUT_PARANOIC)
msg->console()->output(KVI_OUT_AWAY,__tr2qs("Setting away nickname (%Q)"),&szNewNick);
KviTQCString dat = msg->connection()->encodeText(szNewNick);
msg->connection()->sendFmtData("NICK %s",dat.data());
}
}
void KviServerParser::parseNumericWatch(KviIrcMessage *msg)
{
// 600: RPL_LOGON
// :prefix 600 <target> <nick> <user> <host> <logintime> :logged online
// 601: RPL_LOGON
// :prefix 601 <target> <nick> <user> <host> <logintime> :logged offline
// 602: RPL_WATCHOFF
// :prefix 602 <target> <nick> <user> <host> <logintime> :stopped watching
// 604: PRL_NOWON
// :prefix 604 <target> <nick> <user> <host> <logintime> :is online
// 605: PRL_NOWOFF
// :prefix 605 <target> <nick> <user> <host> 0 :is offline
if(msg->connection()->notifyListManager())
{
if(msg->connection()->notifyListManager()->handleWatchReply(msg))return;
}
// not handled...output it
// FIXME: #warning "OUTPUT IT! (In a suitable way) (And handle 602 , 603 , 606 and 607 gracefully)"
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_UNHANDLED,
"[%s][%s] %s",msg->prefix(),msg->command(),msg->allParams());
}
}
void KviServerParser::parseNumericStats(KviIrcMessage * msg)
{
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
if(msg->paramCount() > 2)
{
KviStr szParms;
KviStr *p = msg->firstParam();
for(p = msg->nextParam();p;p = msg->nextParam())
{
if(szParms.hasData())szParms.append(' ');
szParms.append(*p);
}
pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(szParms).utf8().data());
} else {
pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(msg->safeTrailing()).utf8().data());
}
}
}
void KviServerParser::parseNumericServerAdminInfoTitle(KviIrcMessage * msg)
{
//RPL_ADMINME 256
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->outputNoFmt(KVI_OUT_SERVERINFO,msg->connection()->decodeText(msg->safeTrailing()).utf8().data());
}
}
void KviServerParser::parseNumericServerAdminInfoServerName(KviIrcMessage * msg)
{
//RPL_ADMINLOC1 257
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's server info: %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
}
}
void KviServerParser::parseNumericServerAdminInfoAdminName(KviIrcMessage * msg)
{
//RPL_ADMINLOC2 258
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's administrator is %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
}
}
void KviServerParser::parseNumericServerAdminInfoAdminContact(KviIrcMessage * msg)
{
//RPL_ADMINEMAIL 259
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's contact adress is %s"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,szInfo.utf8().data());
}
}
void KviServerParser::parseNumericCommandSyntax(KviIrcMessage * msg)
{
//RPL_COMMANDSYNTAX 334
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->outputNoFmt(KVI_OUT_STATS,msg->connection()->decodeText(msg->safeTrailing()));
}
}
void KviServerParser::parseNumericInviting(KviIrcMessage * msg)
{
//RPL_INVITING 341
if(!msg->haltOutput())
{
TQString szWho = msg->connection()->decodeText(msg->safeParam(0));
TQString szTarget = msg->connection()->decodeText(msg->safeParam(1));
TQString szChan = msg->connection()->decodeText(msg->safeParam(2));
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
chan->output(KVI_OUT_INVITE,__tr2qs("\r!n\r%Q\r invited %Q into channel %Q"),&szWho,&szTarget,&szChan);
} else {
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_INVITE,__tr2qs("\r!n\r%Q\r invited %Q into channel %Q"),&szWho,&szTarget,&szChan);
}
}
}
void KviServerParser::parseNumericInfo(KviIrcMessage * msg)
{
//RPL_INFO 371
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
pOut->outputNoFmt(KVI_OUT_SERVERINFO,szInfo);
}
}
void KviServerParser::parseNumericInfoStart(KviIrcMessage * msg)
{
//RPL_INFOSTART 373
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's information:"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD);
}
}
void KviServerParser::parseNumericInfoEnd(KviIrcMessage * msg)
{
//RPL_ENDOFINFO 374
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("End of %c\r!s\r%s\r%c's information"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD);
}
}
void KviServerParser::parseNumericTime(KviIrcMessage * msg)
{
//RPL_TIME 391
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
pOut->output(KVI_OUT_SERVERINFO,__tr2qs("%c\r!s\r%s\r%c's time is %Q"),KVI_TEXT_BOLD,msg->prefix(),KVI_TEXT_BOLD,&szInfo);
}
}
void KviServerParser::parseNumericNoSuchServer(KviIrcMessage * msg)
{
//ERR_NOSUCHSERVER 402
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szWhat = msg->connection()->decodeText(msg->safeParam(1));
pOut->output(KVI_OUT_GENERICERROR,__tr2qs("%Q: no such server"),&szWhat);
}
}
void KviServerParser::parseNumericNoSuchChannel(KviIrcMessage * msg)
{
// ERR_NOSUCHCHANNEL 403
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szWhat = msg->connection()->decodeText(msg->safeParam(1));
pOut->output(KVI_OUT_GENERICERROR,__tr2qs("%Q: no such channel"),&szWhat);
}
}
void KviServerParser::parseNumericCannotSendColor(KviIrcMessage * msg)
{
// ERR_NOCOLORSONCHAN 408
if(!msg->haltOutput())
{
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
chan->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent to channel: %Q"),&szInfo);
} else {
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent text to channel %Q: %Q"),&szChan,&szInfo);
}
}
}
void KviServerParser::parseNumericCannotSend(KviIrcMessage * msg)
{
// ERR_CANNOTSENDTOCHAN 404
if(!msg->haltOutput())
{
TQString szChan = msg->connection()->decodeText(msg->safeParam(1));
TQString szInfo = msg->connection()->decodeText(msg->safeTrailing());
KviChannel * chan = msg->connection()->findChannel(szChan);
if(chan)
{
chan->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent to channel"));
} else {
KviWindow * pOut = (KviWindow *)(msg->console());
pOut->output(KVI_OUT_GENERICERROR,__tr2qs("Cannot sent text to channel %Q"),&szChan);
}
}
}
void KviServerParser::parseNumericCodePageSet(KviIrcMessage *msg)
{
// a nice extension for irc.wenet.ru
// 700: RPL_CODEPAGESET
// :prefix 700 target <encoding> :is now your translation scheme
TQString encoding = msg->connection()->decodeText(msg->safeParam(1));
if(msg->connection()->serverInfo()->supportsCodePages())
{
if(encoding=="NONE") encoding="KOI8-R"; //RusNet default codepage
msg->console()->output(KVI_OUT_TEXTENCODING,__tr2qs("Your encoding is now %Q"),&encoding);
msg->console()->setTextEncoding(encoding);
msg->connection()->setEncoding(encoding);
} else {
TQString szMe = msg->connection()->decodeText(msg->safeParam(0));
if( (szMe==msg->connection()->currentNickName() || szMe == "*" ) //fix for pre-login codepage message
&& KviLocale::codecForName(encoding.utf8().data()))
{
msg->console()->output(KVI_OUT_TEXTENCODING,__tr2qs("Your encoding is now %Q"),&encoding);
msg->console()->setTextEncoding(encoding);
msg->connection()->setEncoding(encoding);
} else if(!msg->haltOutput()) // simply unhandled
{
TQString szWText = msg->connection()->decodeText(msg->allParams());
msg->connection()->console()->output(KVI_OUT_UNHANDLED,
"[%s][%s] %Q",msg->prefix(),msg->command(),&szWText);
}
}
}
void KviServerParser::parseNumericCodePageScheme(KviIrcMessage *msg)
{
// a nice extension for irc.wenet.ru
// 703: RPL_WHOISSCHEME
// :prefix 703 <mynick> <nick> <encoding> :translation scheme
msg->connection()->stateData()->setLastReceivedWhoisReply(kvi_unixTime());
if(msg->connection()->serverInfo()->supportsCodePages())
{
TQString szNick = msg->connection()->decodeText(msg->safeParam(1));
TQString szCodepage = msg->connection()->decodeText(msg->safeParam(2));
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolWhoisRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
TQString szWText = pOut->decodeText(msg->safeTrailing());
pOut->output(
KVI_OUT_WHOISOTHER,__tr2qs("%c\r!n\r%Q\r%c's codepage is %Q: %Q"),KVI_TEXT_BOLD,
&szNick,KVI_TEXT_BOLD,&szCodepage,&szWText);
}
} else {
// simply unhandled
if(!msg->haltOutput())
{
TQString szWText = msg->connection()->decodeText(msg->allParams());
msg->connection()->console()->output(KVI_OUT_UNHANDLED,
"[%s][%s] %Q",msg->prefix(),msg->command(),&szWText);
}
}
}
void KviServerParser::parseNumericUserMode(KviIrcMessage *msg)
{
// 321: RPL_UMODEIS [I,E,U,D]
// :prefix 221 <target> <modeflags>
parseUserMode(msg,msg->safeParam(1));
if(!msg->haltOutput())
{
KviWindow * pOut = KVI_OPTION_BOOL(KviOption_boolServerRepliesToActiveWindow) ?
msg->console()->activeWindow() : (KviWindow *)(msg->console());
pOut->output(KVI_OUT_MODE,__tr2qs("Your user mode is %s"),msg->safeParam(1));
}
}
void KviServerParser::parseNumericEndOfStats(KviIrcMessage *msg)
{
if(!msg->haltOutput())
{
KviWindow * pOut = (KviWindow *)(msg->console());
TQString szText = msg->connection()->decodeText(msg->safeTrailing());
pOut->outputNoFmt(KVI_OUT_STATS, szText);
}
}