/*
* ----------------------------------------------------------------
* Night Light IRC Proxy - Connection Parser Functions
* ----------------------------------------------------------------
* Copyright (C) 1997-2007 Jonas Kvinge <jonas@night-light.net>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* Last modified by:
* Jonas Kvinge (24.08.2007)
*
*/
#define CONN_PARSER_C
#define NEED_SYS_TYPES_H 1 /* Extra types */
#define NEED_SYS_PARAM_H 1 /* Some systems need this */
#define NEED_LIMITS_H 0 /* Kernel limits */
#define NEED_STDARG_H 1 /* va_list, etc */
#define NEED_ERRNO_H 1 /* errno */
#define NEED_CTYPE_H 1 /* isdigit(), etc */
#define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 0 /* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1 /* Standard C UNIX functions */
#define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1 /* time(), etc */
#define NEED_SYSCTL_H 0 /* sysctl(), etc */
#define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0 /* iovec, etc */
#define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 0 /* ioctl(), etc */
#define NEED_SYS_FILIO_H 0 /* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1 /* Unix standard functions */
#define NEED_STRING_H 1 /* C string functions */
#define NEED_SIGNAL_H 0 /* Signal functions */
#define NEED_SYS_SOCKET_H 0 /* Socket functions */
#define NEED_NETDB_H 0 /* Network database functions */
#define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
#define NEED_ARES 0 /* Functions needed for ares */
#define NEED_SSL 1 /* Needed for SSL support */
#include "includes.h"
#include "irc.h"
#include "conn_conf.h"
#include "client.h"
#include "client_connection.h"
#include "client_notice.h"
#include "conn.h"
#include "conn_connection.h"
#include "conn_parser.h"
#include "conn_sendq.h"
#include "conn_log.h"
#include "conn_ignore.h"
#include "chan.h"
#include "chan_user.h"
/* VARIABLES - JONAS (31.07.2001) */
extern char *IRCNICK;
extern struct Client_Struct *Client_Head;
/* CONN_PARSER FUNCTION - JONAS (18.07.2001) */
void conn_parser(struct Conn_Struct *ConnS) {
char *BufferPT = NULL;
char *LinePT = NULL;
char *DumbPT = NULL;
unsigned long int Count = 0;
unsigned long int Len = 0;
char *TempPT = NULL;
assert(ConnS != NULL);
BufferPT = ConnS->RecvBuffer;
for (Count = 1 ; BufferPT != NULL ; Count++) {
DumbPT = strchr(BufferPT, '\n');
if (DumbPT == NULL) {
if (Count == 1) { return; }
Len = strlen(BufferPT) + 1;
memmove(ConnS->RecvBuffer, BufferPT, Len);
TempPT = realloc(ConnS->RecvBuffer, Len);
if (TempPT == NULL) {
if (Conn_IsWelcome(ConnS)) { conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno)); }
else { conn_disconnect(ConnS, "Connection %s: Memory allocation failure: [%d] %s", ConnS->Name, errno, strerror(errno)); }
return;
}
ConnS->RecvBuffer = TempPT;
return;
}
LinePT = strtok(BufferPT, "\n");
BufferPT = strtok(NULL, "\0");
if (LinePT == NULL) { continue; }
Len = strlen(LinePT);
if (LinePT[Len-1] == '\r') { LinePT[Len-1] = '\0'; }
DEBUGPRINT(BITMASK_DEBUG_CONN, "Connection %s: Server: %s: Receive: %s", ConnS->Name, ConnS->ServerHostName, LinePT);
conn_parse_message(ConnS, LinePT);
if (ConnS->RecvBuffer == NULL) { return; }
}
FREE(ConnS->RecvBuffer);
}
/* CONN_PARSE_MESSAGE FUNCTION - JONAS (17.07.2001) */
void conn_parse_message(struct Conn_Struct *ConnS, char *MessagePT) {
char *PrefixPT = NULL;
char *CommandPT = NULL;
char *LinePT = NULL;
char **ParamsPT = NULL;
char **TempPT = NULL;
unsigned short int Index = 0;
unsigned short int Params = 0;
unsigned short int Numeric = 0;
struct Client_Struct *ClientS = NULL;
assert(ConnS != NULL);
assert(MessagePT != NULL);
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') { return; }
LinePT = strdup(MessagePT);
if (LinePT == NULL) {
if (Conn_IsWelcome(ConnS)) { conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno)); }
else { conn_disconnect(ConnS, "Connection %s: Memory allocation failure: [%d] %s", ConnS->Name, errno, strerror(errno)); }
return;
}
if (MessagePT[0] == ':') {
MessagePT++;
PrefixPT = MessagePT;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT == NULL) {
free(LinePT);
return;
}
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') {
free(LinePT);
return;
}
}
else {
if (ConnS->ServerName == NULL) {
if (ConnS->ServerHostName == NULL) { PrefixPT = ConnS->ServerHostIPS; }
else { PrefixPT = ConnS->ServerHostName; }
}
else { PrefixPT = ConnS->ServerName; }
}
CommandPT = MessagePT;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT == NULL) {
free(LinePT);
return;
}
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') {
free(LinePT);
return;
}
FOREVERLOOP {
if (MessagePT[0] == ':') {
MessagePT++;
++Params;
TempPT = realloc(ParamsPT, (sizeof(char *) * Params));
if (TempPT == NULL) {
if (Conn_IsWelcome(ConnS)) { conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno)); }
else { conn_disconnect(ConnS, "Connection %s: Memory allocation failure: [%d] %s", ConnS->Name, errno, strerror(errno)); }
free(LinePT);
free(ParamsPT);
return;
}
ParamsPT = TempPT;
ParamsPT[Index] = MessagePT;
break;
}
else {
++Params;
TempPT = realloc(ParamsPT, (sizeof(char *) * Params));
if (TempPT == NULL) {
if (Conn_IsWelcome(ConnS)) { conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno)); }
else { conn_disconnect(ConnS, "Connection %s: Memory allocation failure: [%d] %s", ConnS->Name, errno, strerror(errno)); }
free(LinePT);
free(ParamsPT);
return;
}
ParamsPT = TempPT;
ParamsPT[Index] = MessagePT;
++Index;
MessagePT = strchr(MessagePT, ' ');
if (MessagePT == NULL) { break; }
MessagePT[0] = '\0';
MessagePT++;
while (MessagePT[0] == ' ') { MessagePT++; }
if (MessagePT[0] == '\0') { break; }
}
}
if (strdigit(CommandPT) == TRUE) {
Numeric = atoi(CommandPT);
if (conn_parse_numeric(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params) == FALSE) {
free(LinePT);
free(ParamsPT);
return;
}
}
else {
if (conn_parse_event(ConnS, PrefixPT, CommandPT, ParamsPT, Params) == FALSE) {
free(LinePT);
free(ParamsPT);
return;
}
}
for (ClientS = Client_Head ; ClientS != NULL ; ClientS = ClientS->Next) {
if (ClientS->ConnS == ConnS) { client_addsend(ClientS, "%s", LinePT); }
}
free(LinePT);
free(ParamsPT);
}
/* CONN_PARSE_NUMERIC FUNCTION - JONAS (17.07.2001) */
unsigned short int conn_parse_numeric(struct Conn_Struct *ConnS, const char *const PrefixPT, const char *const LinePT, const unsigned short int Numeric, char **ParamsPT, const unsigned short int Params) {
unsigned short int Result = TRUE;
switch(Numeric) {
case 1:
case 2:
case 3:
case 4:
CONN_PARSE_NUMERIC_CHECKPARAMS(1);
Result = conn_parse_numeric_welcome(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_GENERIC_RPL_ISUPPORT:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(1);
Result = conn_parse_numeric_isupport(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_NOWAWAY:
if (!Conn_IsWelcome(ConnS)) { break; }
Result = conn_parse_numeric_nowaway(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_UNAWAY:
if (!Conn_IsWelcome(ConnS)) { break; }
Result = conn_parse_numeric_unaway(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_ERR_NONICKNAMEGIVEN:
case IRC_UNDERNET_RPL_NICKTOOFAST:
if (!Conn_IsWelcome(ConnS)) { break; }
Conn_ClearSentNick(ConnS);
Conn_ClearSentAwayNick(ConnS);
break;
case IRC_RFC1459_ERR_ERRONEUSNICKNAME:
case IRC_RFC1459_ERR_NICKCOLLISION:
case IRC_RFC1459_ERR_NICKNAMEINUSE:
CONN_PARSE_NUMERIC_CHECKPARAMS(3);
Result = conn_parse_numeric_nextnick(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_ISON:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(2);
Result = conn_parse_numeric_ison(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_NAMEREPLY:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(4);
Result = conn_parse_numeric_namereply(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_ENDOFNAMES:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(2);
Result = conn_parse_numeric_endofnames(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_WHOREPLY:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(8);
Result = conn_parse_numeric_whoreply(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
case IRC_RFC1459_RPL_ENDOFWHO:
if (!Conn_IsWelcome(ConnS)) { break; }
CONN_PARSE_NUMERIC_CHECKPARAMS(2);
Result = conn_parse_numeric_endofwho(ConnS, PrefixPT, LinePT, Numeric, ParamsPT, Params);
break;
}
return(Result);
}
/* CONN_PARSE_NUMERIC_WELCOME FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_welcome) {
char *TextPT = NULL;
char *DumbPT = NULL;
unsigned short int TextIndex = 0;
unsigned short int TextLen = 1;
unsigned short int Len = 0;
unsigned short int Count = 0;
if (Numeric == 1) {
unsigned short int Index = 0;
Conn_SetWelcome(ConnS);
ConnS->ServerName = CONN_PARSE_STRREALLOC(ConnS->ServerName, PrefixPT);
ConnS->IRCNick = CONN_PARSE_STRREALLOC(ConnS->IRCNick, ParamsPT[0]);
for (Index = 0 ; Index <= 4 ; Index++) { FREE(ConnS->Welcome[Index]); }
if (Conn_IsSentAwayNick(ConnS)) { Conn_SetAwayNick(ConnS); }
else { Conn_ClearAwayNick(ConnS); }
Conn_ClearSentNick(ConnS);
Conn_ClearSentAwayNick(ConnS);
conn_addsendq(ConnS, "MODE %s %s", ConnS->IRCNick, ConnS->Mode);
conn_addsendq(ConnS, "JOIN %s", ConnS->Chans);
client_noticealluser(ConnS->User, "Connection %s: Successfully connected on %s(%s):%ld \"%s\" as %s.", ConnS->Name, ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH, ConnS->ServerName, ConnS->IRCNick);
if ((ConnS->NumClients <= 0) && (ConnConf_IsAutoAway(ConnS)) && (!Conn_IsAway(ConnS))) { conn_addsendq(ConnS, "AWAY :%s", ConnS->AwayMsg); }
}
for (Count = 1 ; Count < Params ; Count++) {
Len = strlen(ParamsPT[Count]);
if (Count > 1) { Len++; }
if ((Count == (Params - 1)) && (strchr(ParamsPT[Count], ' ') != NULL)) { ++Len; }
TextLen += Len;
DumbPT = realloc(TextPT, TextLen);
if (DumbPT == NULL) {
free(TextPT);
if (Conn_IsWelcome(ConnS)) { conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno)); }
else { conn_disconnect(ConnS, "Connection %s: Memory allocation failure: [%d] %s", ConnS->Name, errno, strerror(errno)); }
return(FALSE);
}
TextPT = DumbPT;
DumbPT += TextIndex;
if (Count > 1) { strcpy(DumbPT, " "); DumbPT++; }
if ((Count == (Params - 1)) && (strchr(ParamsPT[Count], ' ') != NULL)) { strcpy(DumbPT, ":"); DumbPT++; }
strcpy(DumbPT, ParamsPT[Count]);
TextIndex += Len;
}
ConnS->Welcome[Numeric] = CONN_PARSE_STRREALLOC(ConnS->Welcome[Numeric], TextPT);
FREE(TextPT);
return(TRUE);
}
/* CONN_PARSE_NUMERIC_ISUPPORT FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_isupport) {
char *TextPT = NULL;
char *TempPT = NULL;
char *ISupportPT = NULL;
unsigned short int TextIndex = 0;
unsigned short int TextLen = 1;
unsigned short int Len = 0;
unsigned short int Index = 0;
char **ISupportTempPT = NULL;
unsigned short int ISupportIndex = 0;
for (Index = 1 ; Index < Params ; Index++) {
/* Gather ISupport info that can be used internally */
ISupportPT = strdup(ParamsPT[Index]);
TempPT = ISupportPT;
while (TempPT[0] == ' ') { ++TempPT; }
if (TempPT[0] != '\0') {
char *OptionPT = NULL;
char *ValuePT = NULL;
OptionPT = TempPT;
TempPT = strchr(TempPT, '=');
if (TempPT == NULL) { ValuePT = ""; }
else {
TempPT[0] = '\0';
++TempPT;
while (TempPT[0] == ' ') { ++TempPT; }
if (TempPT == '\0') { ValuePT = ""; }
else { ValuePT = TempPT; }
}
if (strcasecmp(OptionPT, "NETWORK") == FALSE) {
if (strcasecmp(ValuePT, "IRCNET") == FALSE) { ConnS->ISupport.Networks |= IRC_NETWORK_IRCNET; }
else if (strcasecmp(ValuePT, "EFNET") == FALSE) { ConnS->ISupport.Networks |= IRC_NETWORK_EFNET; }
else if (strcasecmp(ValuePT, "UNDERNET") == FALSE) { ConnS->ISupport.Networks |= IRC_NETWORK_UNDERNET; }
else if (strcasecmp(ValuePT, "DALNET") == FALSE) { ConnS->ISupport.Networks |= IRC_NETWORK_DALNET; }
else if (strcasecmp(ValuePT, "FREENODE") == FALSE) { ConnS->ISupport.Networks |= IRC_NETWORK_FREENODE; }
TempPT = strrealloc(ConnS->ISupport.Network, ValuePT);
if (TempPT != NULL) { ConnS->ISupport.Network = TempPT; }
}
else if (strcasecmp(OptionPT, "MODES") == FALSE) { ConnS->ISupport.MaxModes = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "MAXCHANNELS") == FALSE) { ConnS->ISupport.MaxChans = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "MAXBANS") == FALSE) { ConnS->ISupport.MaxBans = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "NICKLEN") == FALSE) { ConnS->ISupport.NickLen = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "AWAYLEN") == FALSE) { ConnS->ISupport.AwayMsgLen = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "TOPICLEN") == FALSE) { ConnS->ISupport.TopicLen = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "KICKLEN") == FALSE) { ConnS->ISupport.KickMsgLen = atoi(ValuePT); }
else if (strcasecmp(OptionPT, "CHANMODES") == FALSE) {
for (; *ValuePT != '\0' ; ValuePT++) {
switch (*ValuePT) {
case 'a': /* ANONYMOUS */
ConnISupport_SetAnonymous(ConnS);
break;
case 'i': /* INVITE-ONLY */
ConnISupport_SetInviteOnly(ConnS);
break;
case 'm': /* MODERATED */
ConnISupport_SetModerated(ConnS);
break;
case 'n': /* NO OUTSIDE USER MESSAGES */
ConnISupport_SetNoOutSide(ConnS);
break;
case 'q': /* QUIET */
ConnISupport_SetQuiet(ConnS);
break;
case 'p': /* PRIVATE */
ConnISupport_SetPrivate(ConnS);
break;
case 's': /* SECRET */
ConnISupport_SetSecret(ConnS);
break;
case 'r': /* REOP */
ConnISupport_SetReOP(ConnS);
break;
case 't': /* ONLY OP TOPIC */
ConnISupport_SetOnlyOPTopic(ConnS);
break;
case 'k': /* KEY */
ConnISupport_SetKey(ConnS);
break;
case 'l': /* LIMIT */
ConnISupport_SetLimit(ConnS);
break;
case 'b': /* BAN */
ConnISupport_SetBan(ConnS);
break;
case 'e': /* EXCEPTION */
ConnISupport_SetException(ConnS);
break;
case 'I': /* INVITATION */
ConnISupport_SetInvitation(ConnS);
break;
case 'O': /* CREATOR */
ConnISupport_SetCreator(ConnS);
break;
case 'v': /* VOICE */
ConnISupport_SetVoice(ConnS);
break;
case 'o': /* OPERATOR */
ConnISupport_SetOperator(ConnS);
break;
default:
break;
}
}
}
}
free(ISupportPT);
/* Create "fake" ISupport lines that can be sent to the IRC client */
Len = strlen(ParamsPT[Index]);
if (Index > 1) { Len++; }
if ((Index == Params-1) && (strchr(ParamsPT[Index], ' ') != NULL)) { Len++; }
TextLen += Len;
TempPT = realloc(TextPT, TextLen);
if (TempPT == NULL) {
free(TextPT);
conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
return(FALSE);
}
TextPT = TempPT;
TempPT += TextIndex;
if (Index > 1) { strcpy(TempPT, " "); TempPT++; }
if ((Index == Params-1) && (strchr(ParamsPT[Index], ' ') != NULL)) { strcpy(TempPT, ":"); TempPT++; }
strcpy(TempPT, ParamsPT[Index]);
TextIndex += Len;
}
++ConnS->ISupportLines;
ISupportTempPT = realloc(ConnS->ISupport_String, (sizeof(char *) * ConnS->ISupportLines));
if (ISupportTempPT == NULL) {
free(TextPT);
conn_quit(ConnS, "Memory allocation failure: [%d] %s", errno, strerror(errno));
return(FALSE);
}
ConnS->ISupport_String = ISupportTempPT;
ISupportIndex = ConnS->ISupportLines - 1;
ConnS->ISupport_String[ISupportIndex] = TextPT;
DEBUGPRINT(BITMASK_DEBUG_CONN, "Connection: %s ISUPPORT Network: %s MaxModes: %d MaxChans: %d MaxBans: %d, NickLen: %d ChanTypes: %s Prefix: %s ChanModes: %s\n", ConnS->Name, ConnS->ISupport.Network, ConnS->ISupport.MaxModes, ConnS->ISupport.MaxChans, ConnS->ISupport.MaxBans, ConnS->ISupport.NickLen, ConnS->ISupport.ChanTypes, ConnS->ISupport.Prefix, ConnS->ISupport.ChanModes);
return(TRUE);
}
/* CONN_PARSE_NUMERIC_NOWAWAY FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_nowaway) {
Conn_SetAway(ConnS);
return(TRUE);
}
/* CONN_PARSE_NUMERIC_UNAWAY FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_unaway) {
Conn_ClearAway(ConnS);
return(TRUE);
}
/* CONN_PARSE_NUMERIC_NEXTNICK FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_nextnick) {
assert(ConnS->Nick != NULL);
FREE(IRCNICK);
if ((Conn_IsSentNick(ConnS)) || (Conn_IsSentAwayNick(ConnS))) {
if (Conn_IsSentNick(ConnS)) {
ConnS->NicksIndex = irc_nextnick(ConnS->Nick, ConnS->NicksIndex, ConnS->ISupport.NickLen);
++ConnS->NicksIndex;
}
else if (Conn_IsSentAwayNick(ConnS)) {
ConnS->NicksIndex = irc_nextnick(ConnS->AwayNick, ConnS->NicksIndex, ConnS->ISupport.NickLen);
++ConnS->NicksIndex;
}
DEBUGPRINT(BITMASK_DEBUG_CONN, "Connection %s: %s: Server said: %s: Trying new nickname \"%s\".", ConnS->Name, ParamsPT[1], ParamsPT[2], IRCNICK);
conn_addsendq(ConnS, "NICK %s", IRCNICK);
}
return(TRUE);
}
/* CONN_PARSE_NUMERIC_ISON FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_ison) {
if (Conn_IsSentISON(ConnS)) {
char *P_NicksPT = ParamsPT[1];
unsigned short int Found = FALSE;
Conn_ClearSentISON(ConnS);
while (P_NicksPT != NULL) {
char *P_NickPT = strtok(P_NicksPT, " ");
if (P_NickPT == NULL) { break; }
P_NicksPT = strtok(NULL, "\0");
if ((Conn_IsAwayNick(ConnS)) && (strcmp(P_NickPT, ConnS->AwayNick) == FALSE)) { Found = TRUE; }
else if (strcmp(P_NickPT, ConnS->Nick) == FALSE) { Found = TRUE; }
}
if (Found == FALSE) {
if (Conn_IsAwayNick(ConnS)) {
Conn_SetSentAwayNick(ConnS);
ConnS->NicksIndex = 0;
conn_addsendq(ConnS, "NICK %s", ConnS->AwayNick);
}
else {
Conn_SetSentNick(ConnS);
ConnS->NicksIndex = 0;
conn_addsendq(ConnS, "NICK %s", ConnS->Nick);
}
}
return(FALSE);
}
return(TRUE);
}
/* CONN_PARSE_NUMERIC_NAMEREPLY FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_namereply) {
char *P_ChanPT = ParamsPT[2];
char *P_NicksPT = ParamsPT[3];
char *P_NickPT = NULL;
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
char Mode = 0;
ChanS = chan_get(ConnS, P_ChanPT);
if (ChanS == NULL) { return(TRUE); }
while (P_NicksPT != NULL) {
P_NickPT = strtok(P_NicksPT, " ");
if (P_NickPT == NULL) { break; }
P_NicksPT = strtok(NULL, "\0");
Mode = '\0';
if (P_NickPT[0] == '+') { Mode = 'v'; P_NickPT++; }
else if (P_NickPT[0] == '@') { Mode = 'o'; P_NickPT++; }
FAKELOOP {
unsigned short int NUHLen = strlen(P_NickPT) + 16;
char NUH[NUHLen+1];
snprintf(NUH, NUHLen+1, "%s!unknown@unknown", P_NickPT);
ChanUser = chan_adduser(ConnS, ChanS, P_NickPT, "unknown", "unknown", NUH);
if (ChanUser == NULL) {
CONN_PARSE_NUMERIC_ERROR("chan_adduser");
return(FALSE);
}
}
if (Mode == 'v') { ChanUser_SetVoice(ChanUser); }
if (Mode == 'o') { ChanUser_SetOP(ChanUser); }
}
return(TRUE);
}
/* CONN_PARSE_NUMERIC_ENDOFNAMES FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_endofnames) {
char *ChanPT = ParamsPT[1];
struct Chan_Struct *ChanS = NULL;
ChanS = chan_get(ConnS, ChanPT);
if (ChanS == NULL) { return(TRUE); }
Chan_SetNames(ChanS);
return(TRUE);
}
/* CONN_PARSE_NUMERIC_WHOREPLY FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_whoreply) {
char *ChanPT = ParamsPT[1];
char *P_UserPT = ParamsPT[2];
char *P_HostPT = ParamsPT[3];
char *P_NickPT = ParamsPT[5];
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
ChanS = chan_get(ConnS, ChanPT);
if (ChanS == NULL) { return(TRUE); }
ChanUser = chan_getuser(ConnS, ChanS, P_NickPT);
if (ChanUser != NULL) {
ChanUser->User = CONN_PARSE_STRREALLOC(ChanUser->User, P_UserPT);
ChanUser->Host = CONN_PARSE_STRREALLOC(ChanUser->Host, P_HostPT);
FAKELOOP {
char NUH[strlen(ChanUser->Nick)+1+strlen(ChanUser->User)+1+strlen(ChanUser->Host)+1];
sprintf(NUH, "%s!%s@%s", ChanUser->Nick, ChanUser->User, ChanUser->Host);
ChanUser->NUH = CONN_PARSE_STRREALLOC(ChanUser->NUH, NUH);
}
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
}
if (ChanS->Who_Head != NULL) {
if (ChanS->Who_Head->ClientS != NULL) { client_addsend(ChanS->Who_Head->ClientS, "%s", LinePT); }
return(FALSE);
}
return(TRUE);
}
/* CONN_PARSE_NUMERIC_ENDOFWHO FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_NUMERIC(conn_parse_numeric_endofwho) {
char *ChanPT = ParamsPT[1];
struct Chan_Struct *ChanS = NULL;
ChanS = chan_get(ConnS, ChanPT);
if (ChanS == NULL) { return(TRUE); }
Chan_ClearSentWho(ChanS);
Chan_SetWho(ChanS);
if (ChanS->Who_Head) {
struct Who_Struct *WhoS = ChanS->Who_Head;
ChanS->Who_Head = WhoS->NextForChan;
if (WhoS->PrevForClient != NULL) { WhoS->PrevForClient->NextForClient = WhoS->NextForClient; }
if (WhoS->NextForClient != NULL) { WhoS->NextForClient->PrevForClient = WhoS->PrevForClient; }
if (WhoS->ClientS != NULL) {
if (WhoS->ClientS->Who_Head == WhoS) { WhoS->ClientS->Who_Head = WhoS->NextForClient; }
client_addsend(WhoS->ClientS, "%s", LinePT);
}
free(WhoS);
return(FALSE);
}
return(TRUE);
}
/* CONN_PARSE_EVENT FUNCTION - JONAS (17.07.2001) */
unsigned short int conn_parse_event(struct Conn_Struct *ConnS, const char *PrefixPT, const char *const CommandPT, char **ParamsPT, const unsigned short int Params) {
const char *NUHPT = PrefixPT;
unsigned short int NUHLen = strlen(NUHPT);
char P_NUH[NUHLen+1];
char *P_NUHPT = P_NUH;
char *NickPT = NULL;
char *UserPT = NULL;
char *HostPT = NULL;
unsigned short int Result = TRUE;
strcpy(P_NUHPT, NUHPT);
NickPT = P_NUHPT;
if (P_NUHPT != NULL) {
P_NUHPT = strchr(P_NUHPT, '!');
if (P_NUHPT != NULL) {
*P_NUHPT = '\0';
P_NUHPT++;
UserPT = P_NUHPT;
if (UserPT == NULL) { UserPT = NickPT; }
}
else { UserPT = NickPT; }
}
else { UserPT = NickPT; }
if (P_NUHPT != NULL) {
P_NUHPT = strchr(P_NUHPT, '@');
if (P_NUHPT != NULL) {
*P_NUHPT = '\0';
P_NUHPT++;
HostPT = P_NUHPT;
if (HostPT == NULL) { HostPT = NickPT; }
}
else { HostPT = NickPT; }
}
else { HostPT = NickPT; }
if (strcasecmp(CommandPT, "PING") == FALSE) {
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_ping(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "PONG") == FALSE) {
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_pong(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "ERROR") == FALSE) {
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_error(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "NICK") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_nick(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "JOIN") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_join(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "PART") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_part(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "QUIT") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(1);
Result = conn_parse_event_quit(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "KICK") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(2);
Result = conn_parse_event_kick(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if (strcasecmp(CommandPT, "MODE") == FALSE) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(2);
Result = conn_parse_event_mode(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
else if ((strcasecmp(CommandPT, "PRIVMSG") == FALSE) || (strcasecmp(CommandPT, "NOTICE") == FALSE) || (strcasecmp(CommandPT, "TOPIC") == FALSE)) {
if (!Conn_IsWelcome(ConnS)) { return(Result); }
CONN_PARSE_EVENT_CHECKPARAMS(2);
Result = conn_parse_event_privmsg_notice_topic(ConnS, NickPT, UserPT, HostPT, NUHPT, CommandPT, ParamsPT, Params);
return(Result);
}
return(TRUE);
}
/* CONN_PARSE_EVENT_PING FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_ping) {
conn_addsendq(ConnS, "PONG :%s", ParamsPT[0]);
return(FALSE);
}
/* CONN_PARSE_EVENT_PONG FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_pong) {
Conn_ClearSentPing(ConnS);
ConnS->SentPingTime = 0;
return(FALSE);
}
/* CONN_PARSE_EVENT_ERROR FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_error) {
client_noticealluser(ConnS->User, "Connection %s: Received ERROR: \"%s\" from server %s(%s):%ld \"%s\"", ConnS->Name, ParamsPT[0], ConnS->ServerHostName, ConnS->ServerHostIPS, ConnS->ServerPortH, ConnS->ServerName);
return(FALSE);
}
/* CONN_PARSE_EVENT_NICK FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_nick) {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
if (ConnS->IRCNick == NULL) { conn_quit(ConnS, "%s: Internal error: ConnS->IRCNick == NULL.", CommandPT); return(FALSE); }
if (strcasecmp(ConnS->IRCNick, NickPT) == FALSE) {
if (Conn_IsSentAwayNick(ConnS)) { Conn_SetAwayNick(ConnS); }
else { Conn_ClearAwayNick(ConnS); }
Conn_ClearSentNick(ConnS);
Conn_ClearSentAwayNick(ConnS);
ConnS->IRCNick = CONN_PARSE_STRREALLOC(ConnS->IRCNick, ParamsPT[0]);
}
for (ChanS = ConnS->Chan_Head ; ChanS != NULL ; ChanS = ChanS->Next) {
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser == NULL) { continue; }
chan_changeuser(ConnS, ChanS, ChanUser, ParamsPT[0]);
if (aerrno != SUCCESS) { CONN_PARSE_EVENT_ERROR("chan_changeuser"); }
ChanUser->User = CONN_PARSE_STRREALLOC(ChanUser->User, UserPT);
ChanUser->Host = CONN_PARSE_STRREALLOC(ChanUser->Host, HostPT);
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
if ((ConnS->NumClients <= 0) && (!ChanUser_IsOP(ChanUser)) && (!ChanUser_IsSentOP(ChanUser)) && (!ChanUser_IsAutoOPCheck(ChanUser))) { chanuser_autoopcheck(ConnS, ChanS, ChanUser); }
}
return(TRUE);
}
/* CONN_PARSE_EVENT_JOIN FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_join) {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
if (ConnS->IRCNick == NULL) { conn_quit(ConnS, "%s: Internal error", CommandPT); return(FALSE); }
if (strcasecmp(ConnS->IRCNick, NickPT) == FALSE) {
ChanS = chan_add(ConnS, ParamsPT[0]);
if (ChanS == NULL) { CONN_PARSE_EVENT_ERROR("chan_add"); }
ChanUser = chan_adduser(ConnS, ChanS, NickPT, UserPT, HostPT, NUHPT);
if (ChanUser == NULL) { CONN_PARSE_EVENT_ERROR("chan_adduser"); }
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
ChanS->Me = ChanUser;
return(TRUE);
}
ChanS = chan_get(ConnS, ParamsPT[0]);
if (ChanS == NULL) { CONN_PARSE_EVENT_ERROR("chan_get"); }
ChanUser = chan_adduser(ConnS, ChanS, NickPT, UserPT, HostPT, NUHPT);
if (ChanUser == NULL) { CONN_PARSE_EVENT_ERROR("chan_adduser"); }
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
if ((ConnS->NumClients <= 0) && (!ChanUser_IsOP(ChanUser)) && (!ChanUser_IsSentOP(ChanUser)) && (!ChanUser_IsAutoOPCheck(ChanUser))) { chanuser_autoopcheck(ConnS, ChanS, ChanUser); }
return(TRUE);
}
/* CONN_PARSE_EVENT_PART FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_part) {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
ChanS = chan_get(ConnS, ParamsPT[0]);
if (ChanS == NULL) { return(TRUE); }
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser == NULL) { return(TRUE); }
if (ChanUser_IsWho(ChanUser)) { ChanS->UserWhos--; }
if (ChanUser == ChanS->Me) { chan_rem(ConnS, ChanS); return(TRUE); }
chan_remuser(ConnS, ChanS, ChanUser);
if ((ConnConf_IsChanCycle(ConnS)) && (ChanS->Users <= 1) && (ConnS->NumClients <= 0) && (ChanS->Me != NULL) && (!ChanUser_IsOP(ChanS->Me))) {
conn_addsendq(ConnS, "PART %s", ChanS->Chan);
conn_addsendq(ConnS, "JOIN %s", ChanS->Chan);
}
return(TRUE);
}
/* CONN_PARSE_EVENT_QUIT FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_quit) {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
for (ChanS = ConnS->Chan_Head ; ChanS != NULL ; ChanS = ChanS->Next) {
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser == NULL) { continue; }
if (ChanUser_IsWho(ChanUser)) { ChanS->UserWhos--; }
chan_remuser(ConnS, ChanS, ChanUser);
if ((ConnConf_IsChanCycle(ConnS)) && (ChanS->Users <= 1) && (ConnS->NumClients <= 0) && (ChanS->Me != NULL) && (!ChanUser_IsOP(ChanS->Me))) {
conn_addsendq(ConnS, "PART %s", ChanS->Chan);
conn_addsendq(ConnS, "JOIN %s", ChanS->Chan);
}
}
return(TRUE);
}
/* CONN_PARSE_EVENT_KICK FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_kick) {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
ChanS = chan_get(ConnS, ParamsPT[0]);
if (ChanS == NULL) { return(TRUE); }
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser != NULL) {
ChanUser->User = CONN_PARSE_STRREALLOC(ChanUser->User, UserPT);
ChanUser->Host = CONN_PARSE_STRREALLOC(ChanUser->Host, HostPT);
ChanUser->NUH = CONN_PARSE_STRREALLOC(ChanUser->NUH, NUHPT);
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
}
ChanUser = chan_getuser(ConnS, ChanS, ParamsPT[1]);
if (ChanUser == NULL) { return(TRUE); }
if (ChanUser_IsWho(ChanUser)) { ChanS->UserWhos--; }
if (ChanUser == ChanS->Me) { chan_rem(ConnS, ChanS); return(TRUE); }
chan_remuser(ConnS, ChanS, ChanUser);
/* This is valid if the only OP on the channel kicks himself */
if ((ConnConf_IsChanCycle(ConnS)) && (ChanS->Users <= 1) && (ConnS->NumClients <= 0) && (ChanS->Me != NULL) && (!ChanUser_IsOP(ChanS->Me))) {
conn_addsendq(ConnS, "PART %s", ChanS->Chan);
conn_addsendq(ConnS, "JOIN %s", ChanS->Chan);
}
return(TRUE);
}
/* CONN_PARSE_EVENT_MODE FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_mode) {
char *TargetPT = ParamsPT[0];
char *ModeCharsPT = ParamsPT[1];
char **ModeParamsPT = (ParamsPT + 2);
char ModeChar = 0;
char *ModeParamPT = NULL;
unsigned short int ModeCharNumber = strlen(ModeCharsPT);
unsigned short int ModeCharCount = 0;
unsigned short int ModeCharIndex = 0;
unsigned short int ModeParamNumber = (Params - 2);
unsigned short int ModeParamCount = 0;
unsigned short int ModeParamIndex = 0;
char ModeChange = 0;
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
ChanS = chan_get(ConnS, TargetPT);
if (ChanS == NULL) { return(TRUE); }
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser != NULL) {
ChanUser->User = CONN_PARSE_STRREALLOC(ChanUser->User, UserPT);
ChanUser->Host = CONN_PARSE_STRREALLOC(ChanUser->Host, HostPT);
ChanUser->NUH = CONN_PARSE_STRREALLOC(ChanUser->NUH, NUHPT);
ChanUser_SetWho(ChanUser);
}
for (ModeCharCount = 1, ModeCharIndex = 0 ; ModeCharCount <= ModeCharNumber ; ModeCharCount++) {
struct ChanUser_Struct *P_ChanUser = NULL;
ModeChar = ModeCharsPT[ModeCharIndex];
ModeCharIndex++;
if ((ModeChar == '+') || (ModeChar == '-')) { ModeChange = ModeChar; continue; }
switch (ModeChar) {
case 'v':
case 'o':
case 'O':
ModeParamCount++;
if (ModeParamCount > ModeParamNumber) { conn_quit(ConnS, "Too few params for %s", CommandPT); return(FALSE); }
ModeParamPT = ModeParamsPT[ModeParamIndex];
ModeParamIndex++;
P_ChanUser = chan_getuser(ConnS, ChanS, ModeParamPT);
if (P_ChanUser == NULL) { break; }
if (ModeChange == '+') {
switch (ModeChar) {
case 'v':
ChanUser_SetVoice(P_ChanUser);
break;
case 'o':
ChanUser_SetOP(P_ChanUser);
break;
case 'O':
ChanUser_SetCreator(P_ChanUser);
break;
default:
break;
}
}
else if (ModeChange == '-') {
switch (ModeChar) {
case 'v':
ChanUser_ClearVoice(P_ChanUser);
break;
case 'o':
ChanUser_ClearOP(P_ChanUser);
break;
case 'O':
ChanUser_ClearCreator(P_ChanUser);
break;
default:
break;
}
}
break;
case 'I':
case 'e':
case 'b':
ModeParamCount++;
ModeParamIndex++;
break;
default:
break;
}
}
return(TRUE);
}
/* CONN_PARSE_EVENT_PRIVMSG_NOTICE_TOPIC FUNCTION - JONAS (18.07.2001) */
CONN_PARSE_EVENT(conn_parse_event_privmsg_notice_topic) {
if (irc_isvalidchan(ParamsPT[0]) == FALSE) {
if (*ParamsPT[0] == '@') { return(TRUE); }
if (ConnS->NumClients > 0) { return(TRUE); }
else {
char *MaskPT = NULL;
struct Ignore_Struct *IgnoreS = NULL;
char *CTCPCmdPT = NULL;
char *MessagePT = NULL;
signed long int Result = 0;
if (ConnConf_IsLogging(ConnS)) {
if (Params >= 2) { MessagePT = ParamsPT[1]; }
else { MessagePT = ""; }
Result = conn_log(ConnS, NUHPT, CommandPT, MessagePT);
}
MaskPT = irc_nuhmask(NickPT, UserPT, HostPT, CONN_IGNORENICKMASK, CONN_IGNOREUSERMASK, CONN_IGNOREHOSTMASK);
assert(MaskPT != NULL);
IgnoreS = conn_addignore(ConnS, MaskPT);
if (IgnoreS == NULL) { return(TRUE); }
IgnoreS->ExpireTime = NOW + CONN_IGNORETTL;
if (aerrno == AEEXISTS) { return(TRUE); }
if ((ConnS->NickServNUH != NULL) && (strwm(ConnS->NickServNUH, NUHPT) == TRUE)) {
conn_addsendq(ConnS, "PRIVMSG %s :IDENTIFY %s", NickPT, ConnS->NickServPass);
return(FALSE);
}
if ((strcmp(CommandPT, "PRIVMSG") == FALSE) && (MessagePT[0] == 1) && (MessagePT[strlen(MessagePT)-1] == 1)) {
++MessagePT;
MessagePT[strlen(MessagePT)-1] = '\0';
CTCPCmdPT = strtok(MessagePT, " ");
if (CTCPCmdPT == NULL) { return(FALSE); }
MessagePT = strtok(NULL, "\0");
if (strcmp(CTCPCmdPT, "VERSION") == FALSE) { conn_addsendq(ConnS, "NOTICE %s :\1VERSION %s v%s - %s %s %s - %s\1", NickPT, SHORTNAME, VERSION, OSNAME, OSRELEASE, PLATFORM, URL); }
else if (strcmp(CTCPCmdPT, "PING") == FALSE) {
if (MessagePT == NULL) { conn_addsendq(ConnS, "NOTICE %s :\1PING\1", NickPT); }
else { conn_addsendq(ConnS, "NOTICE %s :\1PING %s\1", NickPT, MessagePT); }
}
return(FALSE);
}
if ((ConnConf_IsLogging(ConnS)) && (Result == SUCCESS)) { conn_addsendq(ConnS, "%s %s :I'm currently not here, your message has been logged.", CommandPT, NickPT); }
else { conn_addsendq(ConnS, "%s %s :I'm currently not here, messages are not logged.", CommandPT, NickPT); }
}
}
else {
struct Chan_Struct *ChanS = NULL;
struct ChanUser_Struct *ChanUser = NULL;
ChanS = chan_get(ConnS, ParamsPT[0]);
if (ChanS == NULL) { return(TRUE); }
ChanUser = chan_getuser(ConnS, ChanS, NickPT);
if (ChanUser == NULL) { return(TRUE); }
ChanUser->User = CONN_PARSE_STRREALLOC(ChanUser->User, UserPT);
ChanUser->Host = CONN_PARSE_STRREALLOC(ChanUser->Host, HostPT);
ChanUser->NUH = CONN_PARSE_STRREALLOC(ChanUser->NUH, NUHPT);
if (!ChanUser_IsWho(ChanUser)) {
ChanUser_SetWho(ChanUser);
ChanS->UserWhos++;
}
if ((ConnS->NumClients <= 0) && (!ChanUser_IsOP(ChanUser)) && (!ChanUser_IsSentOP(ChanUser)) && (!ChanUser_IsAutoOPCheck(ChanUser))) { chanuser_autoopcheck(ConnS, ChanS, ChanUser); }
}
return(TRUE);
}
syntax highlighted by Code2HTML, v. 0.9.1