|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|