mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
1191 lines
35 KiB
C++
1191 lines
35 KiB
C++
/*
|
|
* Descent 3
|
|
* Copyright (C) 2024 Parallax Software
|
|
*
|
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef WIN32
|
|
#include "windows.h"
|
|
#endif
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
#if defined(POSIX)
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "chat_api.h"
|
|
#include "crossplat.h"
|
|
#include "grdefs.h"
|
|
#include "mtstrings.h"
|
|
#include "networking.h"
|
|
|
|
extern const char *GetString(int d);
|
|
|
|
typedef void *(*mem_malloc_fp)(int size);
|
|
extern mem_malloc_fp DLLmem_malloc;
|
|
|
|
typedef void (*mem_free_fp)(void *memblock);
|
|
extern mem_free_fp DLLmem_free;
|
|
|
|
typedef int (*nw_Asyncgethostbyname_fp)(uint32_t *ip, int command, const char *hostname);
|
|
extern nw_Asyncgethostbyname_fp DLLnw_Asyncgethostbyname;
|
|
|
|
typedef int (*PollUI_fp)();
|
|
extern PollUI_fp DLLPollUI;
|
|
|
|
#ifndef RELEASE
|
|
#define DLLmprintf(...) DLLDebug_ConsolePrintf(__VA_ARGS__)
|
|
#else
|
|
#define DLLmprintf(...)
|
|
#endif
|
|
|
|
typedef void (*Debug_ConsolePrintf_fp)(int n, const char *format, ...);
|
|
extern Debug_ConsolePrintf_fp DLLDebug_ConsolePrintf;
|
|
#define MAXCHATBUFFER 500
|
|
|
|
SOCKET Chatsock;
|
|
SOCKADDR_IN Chataddr;
|
|
int Socket_connecting = 0;
|
|
char Nick_name[33];
|
|
char Orignial_nick_name[33];
|
|
int Nick_variety = 0;
|
|
char szChat_channel[33] = "";
|
|
char Input_chat_buffer[MAXCHATBUFFER] = "";
|
|
char Chat_tracker_id[33];
|
|
char Getting_user_channel_info_for[33] = "";
|
|
char Getting_user_tracker_info_for[33] = "";
|
|
int Getting_user_channel_error = 0;
|
|
int Getting_user_tracker_error = 0;
|
|
char User_req_tracker_id[100] = ""; // These are oversized for saftey
|
|
char User_req_channel[100] = "";
|
|
char *User_list = nullptr;
|
|
char *Chan_list = nullptr;
|
|
int Socket_connected = 0;
|
|
int Chat_server_connected = 0;
|
|
int Joining_channel = 0;
|
|
int Joined_channel = 0;
|
|
int GettingChannelList = 0;
|
|
int GettingUserTID = 0;
|
|
int GettingUserChannel = 0;
|
|
|
|
Chat_user *Firstuser, *Curruser;
|
|
Chat_command *Firstcommand, *Currcommand;
|
|
Chat_channel *Firstchannel, *Currchannel;
|
|
|
|
void ChatInit() {
|
|
Socket_connecting = 0;
|
|
Nick_name[0] = 0;
|
|
Orignial_nick_name[0] = 0;
|
|
Nick_variety = 0;
|
|
szChat_channel[0] = '\0';
|
|
Input_chat_buffer[0] = '\0';
|
|
Chat_tracker_id[0] = 0;
|
|
Getting_user_channel_info_for[0] = '\0';
|
|
Getting_user_tracker_info_for[0] = '\0';
|
|
Getting_user_channel_error = 0;
|
|
Getting_user_tracker_error = 0;
|
|
User_req_tracker_id[0] = '\0';
|
|
User_req_channel[0] = '\0';
|
|
User_list = nullptr;
|
|
Chan_list = nullptr;
|
|
Socket_connected = 0;
|
|
Chat_server_connected = 0;
|
|
Joining_channel = 0;
|
|
Joined_channel = 0;
|
|
GettingChannelList = 0;
|
|
GettingUserTID = 0;
|
|
GettingUserChannel = 0;
|
|
}
|
|
|
|
// Return codes:
|
|
//-2 Already connected
|
|
//-1 Failed to connect
|
|
// 0 Connecting
|
|
// 1 Connected
|
|
// Call it once with the server IP address, and it will return immediately
|
|
// with 0. Keep calling it until it returns something other than 0
|
|
// note: the nickname may be changed if someone with that name already
|
|
// exists (Scourge1 for instance)
|
|
int ConnectToChatServer(const char *serveraddr, int16_t chat_port, char *nickname, char *trackerid) {
|
|
char signon_str[100];
|
|
|
|
// if(Socket_connected && ) return -2;
|
|
|
|
if (!Socket_connecting) {
|
|
strcpy(Nick_name, nickname);
|
|
for (uint32_t l = 0; l < strlen(Nick_name); l++)
|
|
if (Nick_name[l] == ' ')
|
|
Nick_name[l] = '_';
|
|
strcpy(Orignial_nick_name, nickname);
|
|
strcpy(Chat_tracker_id, trackerid);
|
|
|
|
Firstuser = nullptr;
|
|
Firstcommand = nullptr;
|
|
Chat_server_connected = 0;
|
|
FlushChatCommandQueue();
|
|
|
|
if (chat_port == 0) {
|
|
// AfxMessageBox("Invalid chat port, must be host.com:port (ie. irc.dal.net:6667)");
|
|
return -1;
|
|
}
|
|
|
|
Chatsock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (INVALID_SOCKET == Chatsock) {
|
|
// AfxMessageBox("Unable to open socket!");
|
|
return -1;
|
|
}
|
|
|
|
memset(&Chataddr, 0, sizeof(SOCKADDR_IN));
|
|
Chataddr.sin_family = AF_INET;
|
|
Chataddr.sin_addr.s_addr = INADDR_ANY;
|
|
Chataddr.sin_port = 0;
|
|
|
|
if (SOCKET_ERROR == bind(Chatsock, (SOCKADDR *)&Chataddr, sizeof(sockaddr))) {
|
|
// AfxMessageBox("Unable to bind socket!");
|
|
return -1;
|
|
}
|
|
|
|
#ifdef WIN32
|
|
unsigned long arg = 1;
|
|
ioctlsocket(Chatsock, FIONBIO, &arg);
|
|
#else // WIN32
|
|
fcntl(Chatsock, F_SETFL, fcntl(Chatsock, F_GETFL, 0) | O_NONBLOCK);
|
|
#endif
|
|
|
|
/*
|
|
HOSTENT *he;
|
|
he = gethostbyname(chat_server);
|
|
if(!he)
|
|
{
|
|
//AfxMessageBox("Unable to gethostbyname.\n");
|
|
return -1;
|
|
}
|
|
|
|
memcpy(&Chataddr.sin_addr.s_addr, he->h_addr_list[0],4);//&iaddr, 4);
|
|
|
|
*/
|
|
|
|
int rcode;
|
|
uint32_t ip;
|
|
|
|
DLLnw_Asyncgethostbyname(&ip, NW_AGHBN_LOOKUP, serveraddr);
|
|
do {
|
|
rcode = DLLnw_Asyncgethostbyname(&ip, NW_AGHBN_READ, serveraddr);
|
|
if (99 == DLLPollUI()) {
|
|
return 0;
|
|
}
|
|
} while (rcode == 0);
|
|
|
|
if (rcode != 1) {
|
|
DLLmprintf(0, "Unable to gethostbyname(\"%s\").\n", serveraddr);
|
|
DLLmprintf(0, "WSAGetLastError() returned %d.\n", WSAGetLastError());
|
|
DLLnw_Asyncgethostbyname(nullptr, NW_AGHBN_CANCEL, nullptr);
|
|
return 0;
|
|
}
|
|
memcpy(&Chataddr.sin_addr.s_addr, &ip, 4);
|
|
|
|
Chataddr.sin_port = htons(chat_port);
|
|
|
|
if (SOCKET_ERROR == connect(Chatsock, (SOCKADDR *)&Chataddr, sizeof(SOCKADDR_IN))) {
|
|
int ret = WSAGetLastError();
|
|
#if !defined(POSIX)
|
|
if (WSAEWOULDBLOCK == WSAGetLastError())
|
|
#else
|
|
if (EINPROGRESS == ret || 0 == ret)
|
|
#endif
|
|
{
|
|
DLLmprintf(0, "Beginning socket connect\n");
|
|
Socket_connecting = 1;
|
|
return 0;
|
|
}
|
|
} else {
|
|
// This should never happen, connect should always return WSAEWOULDBLOCK
|
|
DLLmprintf(0, "connect returned too soon!\n");
|
|
Socket_connecting = 1;
|
|
Socket_connected = 1;
|
|
DLLmprintf(0, "Socket connected, sending user and nickname request\n");
|
|
snprintf(signon_str, sizeof(signon_str), "/USER %s %s %s :%s", "user", "user", "user", Chat_tracker_id);
|
|
SendChatString(signon_str, 1);
|
|
snprintf(signon_str, sizeof(signon_str), "/NICK %s", Nick_name);
|
|
SendChatString(signon_str, 1);
|
|
return 0;
|
|
}
|
|
} else {
|
|
if (Chat_server_connected) {
|
|
return 1;
|
|
}
|
|
|
|
if (!Socket_connected) {
|
|
// Do a few select to check for an error, or to see if we are writeable (connected)
|
|
fd_set write_fds, error_fds;
|
|
|
|
#ifdef WIN32
|
|
TIMEVAL timeout;
|
|
#else
|
|
struct timeval timeout;
|
|
#endif
|
|
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 0;
|
|
|
|
FD_ZERO(&write_fds);
|
|
FD_SET(Chatsock, &write_fds);
|
|
// Writable -- that means it's connected
|
|
if (select(Chatsock + 1, nullptr, &write_fds, nullptr, &timeout)) {
|
|
Socket_connected = 1;
|
|
DLLmprintf(0, "Socket connected, sending user and nickname request\n");
|
|
snprintf(signon_str, sizeof(signon_str), "/USER %s %s %s :%s", "user", "user", "user", Chat_tracker_id);
|
|
SendChatString(signon_str, 1);
|
|
snprintf(signon_str, sizeof(signon_str), "/NICK %s", Nick_name);
|
|
SendChatString(signon_str, 1);
|
|
return 0;
|
|
// Now we are waiting for Chat_server_connected
|
|
}
|
|
FD_ZERO(&error_fds);
|
|
FD_SET(Chatsock, &error_fds);
|
|
// error -- that means it's not going to connect
|
|
if (select(Chatsock + 1, nullptr, nullptr, &error_fds, &timeout)) {
|
|
DLLmprintf(0, "Select returned an error!\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Call it to close the connection. It returns immediately
|
|
void DisconnectFromChatServer() {
|
|
if (!Socket_connected)
|
|
return;
|
|
SendChatString("/QUIT", 1);
|
|
shutdown(Chatsock, 2);
|
|
#ifdef WIN32
|
|
closesocket(Chatsock);
|
|
#else
|
|
close(Chatsock);
|
|
#endif
|
|
Socket_connecting = 0;
|
|
Socket_connected = 0;
|
|
Input_chat_buffer[0] = '\0';
|
|
if (User_list) {
|
|
DLLmem_free(User_list);
|
|
User_list = nullptr;
|
|
}
|
|
if (Chan_list) {
|
|
DLLmem_free(Chan_list);
|
|
Chan_list = nullptr;
|
|
}
|
|
|
|
Chat_server_connected = 0;
|
|
Joining_channel = 0;
|
|
Joined_channel = 0;
|
|
RemoveAllChatUsers();
|
|
FlushChatCommandQueue();
|
|
FlushChannelList();
|
|
}
|
|
|
|
// returns NULL if no line is there to print, otherwise returns a string to
|
|
// print (all preformatted of course)
|
|
const char *GetChatText() {
|
|
|
|
if (!Socket_connected)
|
|
return nullptr;
|
|
|
|
// ChatGetString will do the formatting
|
|
return ChatGetString();
|
|
}
|
|
|
|
// Send a string to be sent as chat, or scanned for messages (/msg <user>
|
|
// string)
|
|
const char *SendChatString(const char *line, int raw) {
|
|
char szCmd[200];
|
|
char szTarget[50];
|
|
if (!Socket_connected)
|
|
return nullptr;
|
|
|
|
if (line[0] == '/') {
|
|
|
|
// Start off by getting the command
|
|
strcpy(szCmd, GetWordNum(0, line + 1));
|
|
if (stricmp(szCmd, "msg") == 0) {
|
|
strcpy(szTarget, GetWordNum(1, line + 1));
|
|
snprintf(szCmd, sizeof(szCmd), "PRIVMSG %s :%s\n\r", szTarget, line + strlen("/msg ") + strlen(szTarget) + 1);
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
szCmd[strlen(szCmd) - 2] = '\0';
|
|
return ParseIRCMessage(szCmd, MSG_LOCAL);
|
|
}
|
|
if (stricmp(szCmd, "me") == 0) {
|
|
snprintf(szCmd, sizeof(szCmd), "PRIVMSG %s :\001ACTION %s\001\n\r", szChat_channel, line + strlen("/me "));
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
szCmd[strlen(szCmd) - 2] = '\0';
|
|
return ParseIRCMessage(szCmd, MSG_LOCAL);
|
|
}
|
|
if (stricmp(szCmd, "xyz") == 0) {
|
|
// Special command to send raw irc commands
|
|
snprintf(szCmd, sizeof(szCmd), "%s\n\r", line + strlen("/xyz "));
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "list") == 0) {
|
|
snprintf(szCmd, sizeof(szCmd), "%s\n\r", line + 1);
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
return nullptr;
|
|
}
|
|
if (raw) {
|
|
snprintf(szCmd, sizeof(szCmd), "%s\n\r", line + 1);
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
return nullptr;
|
|
}
|
|
return "Unrecognized command";
|
|
|
|
} else {
|
|
if (szChat_channel[0]) {
|
|
snprintf(szCmd, sizeof(szCmd), "PRIVMSG %s :%s\n\r", szChat_channel, line);
|
|
send(Chatsock, szCmd, strlen(szCmd), 0);
|
|
szCmd[strlen(szCmd) - 2] = '\0';
|
|
return ParseIRCMessage(szCmd, MSG_LOCAL);
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// Returns a structure which contains a command and possible some data (like
|
|
// a user joining or leaving) if one is waiting
|
|
// This tells you if you need to add a user from the userlist, remove a user,
|
|
// etc. Also for status messages, like if you get knocked
|
|
// off the server for some reason.
|
|
Chat_command *GetChatCommand() {
|
|
if (!Socket_connected)
|
|
return nullptr;
|
|
return GetChatCommandFromQueue();
|
|
}
|
|
|
|
// This function returns a list of users in the current channel, in one
|
|
// string, separated by spaces, terminated by a null
|
|
// (Spaces aren't allowed as part of a nickname)
|
|
char *GetChatUserList() {
|
|
int iuser_list_length = 0;
|
|
;
|
|
if (User_list) {
|
|
DLLmem_free(User_list);
|
|
User_list = nullptr;
|
|
}
|
|
if (!Socket_connected)
|
|
return nullptr;
|
|
|
|
Curruser = Firstuser;
|
|
while (Curruser) {
|
|
iuser_list_length += strlen(Curruser->nick_name) + 1;
|
|
Curruser = Curruser->next;
|
|
}
|
|
Curruser = Firstuser;
|
|
User_list = (char *)DLLmem_malloc(iuser_list_length + 1);
|
|
User_list[0] = '\0';
|
|
while (Curruser) {
|
|
strcat(User_list, Curruser->nick_name);
|
|
strcat(User_list, " ");
|
|
Curruser = Curruser->next;
|
|
}
|
|
|
|
return User_list;
|
|
}
|
|
|
|
// Call this to set/join a channel. Since we can't be sure that we will be
|
|
// able to join that channel, check it for completion
|
|
// You can't be in more than one channel at a time with this API, so you
|
|
// leave the current channel before trying to join
|
|
// a new one. Because of this if the join fails, make sure you try to join
|
|
// another channel, or the user wont be able to chat
|
|
//-1 Failed to join
|
|
// 0 joining
|
|
// 1 successfully joined
|
|
int SetNewChatChannel(const char *channel) {
|
|
char partstr[100];
|
|
if (!Socket_connected)
|
|
return -1;
|
|
if (Joining_channel == 1) {
|
|
if (Joined_channel == 1) {
|
|
// We made it in!
|
|
Joining_channel = 0;
|
|
return 1;
|
|
} else if (Joined_channel == -1) {
|
|
// Error -- we got a message that the channel was invite only, or we were banned or something
|
|
Joining_channel = 0;
|
|
strcpy(szChat_channel, "");
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (szChat_channel[0]) {
|
|
snprintf(partstr, sizeof(partstr), "/PART %s", szChat_channel);
|
|
SendChatString(partstr, 1);
|
|
}
|
|
strcpy(szChat_channel, channel);
|
|
snprintf(partstr, sizeof(partstr), "/JOIN %s", szChat_channel);
|
|
SendChatString(partstr, 1);
|
|
Joining_channel = 1;
|
|
Joined_channel = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char *ChatGetString() {
|
|
char ch[2];
|
|
char *p;
|
|
int bytesread = 1;
|
|
static char return_string[MAXCHATBUFFER];
|
|
|
|
while ((bytesread != 0) && (bytesread != SOCKET_ERROR)) {
|
|
bytesread = recv(Chatsock, ch, 1, 0);
|
|
if (bytesread == SOCKET_ERROR) {
|
|
uint32_t lerror = WSAGetLastError();
|
|
#if !defined(POSIX)
|
|
if (WSAEWOULDBLOCK != lerror)
|
|
#else
|
|
if (WSAEWOULDBLOCK != lerror && 0 != lerror)
|
|
#endif
|
|
{
|
|
DLLmprintf(0, "recv caused an error: %d\n", lerror);
|
|
}
|
|
return nullptr;
|
|
}
|
|
if (bytesread) {
|
|
ch[1] = '\0';
|
|
// DLLmprintf(0,ch);
|
|
if ((ch[0] == 0x0a) || (ch[0] == 0x0d)) {
|
|
if (Input_chat_buffer[0] == '\0') {
|
|
// Blank line, ignore it
|
|
return nullptr;
|
|
}
|
|
strcpy(return_string, Input_chat_buffer);
|
|
Input_chat_buffer[0] = '\0';
|
|
// DLLmprintf(0,"->|%s\n",return_string);
|
|
p = ParseIRCMessage(return_string, MSG_REMOTE);
|
|
|
|
return p;
|
|
}
|
|
strcat(Input_chat_buffer, ch);
|
|
} else {
|
|
// Select said we had read data, but 0 bytes read means disconnected
|
|
DLLmprintf(0, "Disconnected! Doh!");
|
|
AddChatCommandToQueue(CC_DISCONNECTED, nullptr, 0);
|
|
return nullptr;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const char *GetWordNum(int num, const char *l_String) {
|
|
static char strreturn[600];
|
|
static char ptokstr[600];
|
|
char seps[10] = " \n\r\t";
|
|
char *token, *strstart;
|
|
|
|
strstart = ptokstr;
|
|
|
|
strcpy(ptokstr, l_String);
|
|
|
|
token = strtok(ptokstr, seps);
|
|
|
|
for (int i = 0; i != num; i++) {
|
|
token = strtok(nullptr, seps);
|
|
}
|
|
if (token) {
|
|
strcpy(strreturn, token);
|
|
} else {
|
|
return "";
|
|
}
|
|
// check for the ':' char....
|
|
if (token[0] == ':') {
|
|
// Its not pretty, but it works, return the rest of the string
|
|
strcpy(strreturn, l_String + ((token - strstart) + 1));
|
|
}
|
|
|
|
// return the appropriate response.
|
|
return strreturn;
|
|
}
|
|
|
|
int AddChatUser(const char *nickname) {
|
|
Curruser = Firstuser;
|
|
while (Curruser) {
|
|
if (stricmp(nickname, Curruser->nick_name) == 0)
|
|
return 0;
|
|
Curruser = Curruser->next;
|
|
}
|
|
|
|
Curruser = Firstuser;
|
|
if (Firstuser == nullptr) {
|
|
Firstuser = (Chat_user *)DLLmem_malloc(sizeof(Chat_user));
|
|
// ASSERT(Firstuser);
|
|
strcpy(Firstuser->nick_name, nickname);
|
|
Firstuser->next = nullptr;
|
|
AddChatCommandToQueue(CC_USER_JOINING, nickname, strlen(nickname) + 1);
|
|
return 1;
|
|
} else {
|
|
while (Curruser->next) {
|
|
Curruser = Curruser->next;
|
|
}
|
|
Curruser->next = (Chat_user *)DLLmem_malloc(sizeof(Chat_user));
|
|
Curruser = Curruser->next;
|
|
// ASSERT(Curruser);
|
|
strcpy(Curruser->nick_name, nickname);
|
|
Curruser->next = nullptr;
|
|
AddChatCommandToQueue(CC_USER_JOINING, nickname, strlen(nickname) + 1);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int RemoveChatUser(char *nickname) {
|
|
Chat_user *prv_user = nullptr;
|
|
|
|
Curruser = Firstuser;
|
|
while (Curruser) {
|
|
if (stricmp(nickname, Curruser->nick_name) == 0) {
|
|
if (prv_user) {
|
|
prv_user->next = Curruser->next;
|
|
|
|
} else {
|
|
Firstuser = Curruser->next;
|
|
}
|
|
AddChatCommandToQueue(CC_USER_LEAVING, Curruser->nick_name, strlen(Curruser->nick_name) + 1);
|
|
DLLmem_free(Curruser);
|
|
return 1;
|
|
}
|
|
prv_user = Curruser;
|
|
Curruser = Curruser->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void RemoveAllChatUsers() {
|
|
Chat_user *tmp_user = nullptr;
|
|
Curruser = Firstuser;
|
|
while (Curruser) {
|
|
tmp_user = Curruser->next;
|
|
AddChatCommandToQueue(CC_USER_LEAVING, Curruser->nick_name, strlen(Curruser->nick_name) + 1);
|
|
DLLmem_free(Curruser);
|
|
Curruser = tmp_user;
|
|
}
|
|
Firstuser = nullptr;
|
|
}
|
|
|
|
char *ParseIRCMessage(char *Line, int iMode) {
|
|
char szRemLine[MAXLOCALSTRING];
|
|
const char *pszTempStr;
|
|
char szPrefix[MAXLOCALSTRING];
|
|
char szHackPrefix[MAXLOCALSTRING];
|
|
char szTarget[MAXLOCALSTRING];
|
|
char szNick[MAXLOCALSTRING];
|
|
char szCmd[MAXLOCALSTRING];
|
|
char szCTCPCmd[MAXLOCALSTRING];
|
|
|
|
static char szResponse[MAXLOCALSTRING];
|
|
|
|
int iNickLen;
|
|
int iPrefixLen = 0;
|
|
|
|
szPrefix[0] = '\0';
|
|
szNick[0] = '\0';
|
|
|
|
if (strlen(Line) >= MAXLOCALSTRING) {
|
|
return nullptr;
|
|
}
|
|
// Nick included....
|
|
if (iMode == MSG_REMOTE) {
|
|
strcpy(szRemLine, Line);
|
|
// Start by getting the prefix
|
|
szHackPrefix[0] = '\0';
|
|
if (Line[0] == ':') {
|
|
//
|
|
pszTempStr = GetWordNum(0, Line + 1);
|
|
strcpy(szPrefix, pszTempStr);
|
|
strcpy(szHackPrefix, pszTempStr);
|
|
strcpy(szRemLine, Line + 1 + strlen(szPrefix));
|
|
}
|
|
// Next, get the Nick
|
|
pszTempStr = strtok(szHackPrefix, "!");
|
|
if (pszTempStr) {
|
|
strcpy(szNick, pszTempStr);
|
|
} else {
|
|
strncpy(szNick, szPrefix, 31);
|
|
szNick[31] = 0;
|
|
}
|
|
// strcpy(NewMsg.Nickname,szNick);
|
|
iNickLen = strlen(szNick);
|
|
iPrefixLen = strlen(szPrefix);
|
|
} else if (iMode == MSG_LOCAL) {
|
|
strcpy(szRemLine, Line);
|
|
strcpy(szNick, Nick_name);
|
|
strcpy(szPrefix, Nick_name);
|
|
// strcpy(NewMsg.Nickname,szNick);
|
|
iNickLen = -2;
|
|
iPrefixLen = -2;
|
|
}
|
|
// Next is the command
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
if (pszTempStr[0]) {
|
|
strcpy(szCmd, pszTempStr);
|
|
} else {
|
|
// Shouldn't ever happen, but we can't be sure of what the host will send us.
|
|
return nullptr;
|
|
}
|
|
|
|
// Move the szRemLine string up
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + 2);
|
|
// Now parse the commands!
|
|
// printf("%s",szCmd);
|
|
if (stricmp(szCmd, "PRIVMSG") == 0) {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
strcpy(szTarget, pszTempStr);
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 4);
|
|
if (szRemLine[0] == ':') {
|
|
strcpy(szCTCPCmd, GetWordNum(0, szRemLine + 1));
|
|
if (szCTCPCmd[strlen(szCTCPCmd) - 1] == 0x01)
|
|
szCTCPCmd[strlen(szCTCPCmd) - 1] = 0x00;
|
|
|
|
} else {
|
|
strcpy(szCTCPCmd, GetWordNum(0, szRemLine));
|
|
if (szCTCPCmd[strlen(szCTCPCmd) - 1] == 0x01)
|
|
szCTCPCmd[strlen(szCTCPCmd) - 1] = 0x00;
|
|
}
|
|
if (szCTCPCmd[0] == 0x01) {
|
|
// Handle ctcp message
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + strlen(szCTCPCmd) + 6);
|
|
szRemLine[strlen(szRemLine) - 1] = '\0'; // null out the ending 0x01
|
|
if (stricmp(szCTCPCmd + 1, "ACTION") == 0) {
|
|
// Posture
|
|
snprintf(szResponse, sizeof(szResponse), "\1\xff\x28\x28* %s %s", szNick, szRemLine);
|
|
return szResponse;
|
|
}
|
|
if (iMode == MSG_LOCAL) {
|
|
strcpy(szHackPrefix, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 4);
|
|
szRemLine[strlen(szRemLine) - 1] = '\0';
|
|
snprintf(szResponse, sizeof(szResponse), "** CTCP %s %s %s", szTarget, szCTCPCmd + 1, szRemLine);
|
|
return szResponse;
|
|
}
|
|
if (stricmp(szCTCPCmd + 1, "PING") == 0) {
|
|
snprintf(szResponse, sizeof(szResponse), "/NOTICE %s :\001PING %s\001", szNick,
|
|
szRemLine); // Don't need the trailing \001 because szremline has it.
|
|
SendChatString(szResponse, 1);
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCTCPCmd + 1, "VERSION") == 0) {
|
|
// reply with a notice version & copyright
|
|
// sprintf(szTempLine,"NOTICE %s :\001VERSION Copyright(c)\001\n",szNick);
|
|
|
|
return nullptr;
|
|
}
|
|
strcpy(szRemLine, 1 + GetWordNum(0, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 4));
|
|
szRemLine[strlen(szRemLine) - 1] = '\0';
|
|
snprintf(szResponse, sizeof(szResponse), "** CTCP Message from %s (%s)", szNick, szRemLine);
|
|
return nullptr; // szResponse;
|
|
}
|
|
// differentiate between channel and private
|
|
if ((szTarget[0] == '#') || (szTarget[0] == '+')) {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
snprintf(szResponse, sizeof(szResponse), "\1\xff\xff\xff[%s] %s", szNick, pszTempStr);
|
|
return szResponse;
|
|
} else {
|
|
if (iMode == MSG_LOCAL) {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
snprintf(szResponse, sizeof(szResponse), TXT_PXO_PRIVMSGTO, szTarget, pszTempStr);
|
|
} else {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
snprintf(szResponse, sizeof(szResponse), TXT_PXO_PRIVMSGFROM, szNick, pszTempStr);
|
|
}
|
|
return szResponse;
|
|
}
|
|
}
|
|
// don't handle any other messages locally.
|
|
if (iMode == MSG_LOCAL) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (stricmp(szCmd, "NOTICE") == 0) {
|
|
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
strcpy(szTarget, pszTempStr);
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 4);
|
|
if (szRemLine[0] == ':') {
|
|
strcpy(szCTCPCmd, GetWordNum(0, szRemLine + 1));
|
|
if (szCTCPCmd[strlen(szCTCPCmd) - 1] == 0x01)
|
|
szCTCPCmd[strlen(szCTCPCmd) - 1] = 0x00;
|
|
|
|
} else {
|
|
strcpy(szCTCPCmd, GetWordNum(0, szRemLine));
|
|
if (szCTCPCmd[strlen(szCTCPCmd) - 1] == 0x01)
|
|
szCTCPCmd[strlen(szCTCPCmd) - 1] = 0x00;
|
|
}
|
|
if (szCTCPCmd[0] == 0x01) {
|
|
// Handle ctcp message
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + strlen(szCTCPCmd) + 6);
|
|
szRemLine[strlen(szRemLine) - 1] = '\0'; // null out the ending 0x01
|
|
if (stricmp(szCTCPCmd + 1, "PING") == 0) {
|
|
// This is a ping response, figure out time and print
|
|
// sprintf(NewMsg.Message,"** Ping Response from %s: %ums",szNick,ulping);
|
|
return nullptr;
|
|
}
|
|
|
|
// Default message
|
|
strcpy(szRemLine, 1 + GetWordNum(0, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 4));
|
|
szRemLine[strlen(szRemLine) - 1] = '\0';
|
|
snprintf(szResponse, sizeof(szResponse), "** CTCP Message from %s (%s)", szNick, szRemLine);
|
|
return nullptr; // szResponse;
|
|
}
|
|
strncpy(szResponse, szRemLine, sizeof(szResponse));
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "JOIN") == 0) {
|
|
// see if it is me!
|
|
if (stricmp(Nick_name, szNick) == 0) {
|
|
// Yup, it's me!
|
|
// if(stricmp(szChat_channel,GetWordNum(0,szRemLine))==0)
|
|
//{
|
|
Joined_channel = 1;
|
|
// if(stricmp(szChat_channel,"#autoselect")==0)
|
|
//{
|
|
strcpy(szChat_channel, GetWordNum(0, szRemLine));
|
|
AddChatCommandToQueue(CC_YOURCHANNEL, szChat_channel, strlen(szChat_channel) + 1);
|
|
|
|
//}
|
|
// CC_YOURCHANNEL
|
|
//}
|
|
}
|
|
AddChatUser(szNick);
|
|
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
strcpy(szTarget, pszTempStr);
|
|
// strcpy(szRemLine,Line+iPrefixLen+strlen(szCmd)+strlen(szTarget)+3);
|
|
|
|
// strcpy(NewMsg.Channel,szTarget);
|
|
|
|
AddChatUser(szNick);
|
|
snprintf(szResponse, sizeof(szResponse), "** %s has joined %s", szNick, szTarget);
|
|
return nullptr; // szResponse;
|
|
// Add them to the userlist too!
|
|
}
|
|
if (stricmp(szCmd, "PART") == 0) {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
strcpy(szTarget, pszTempStr);
|
|
strcpy(szRemLine, Line + iPrefixLen + strlen(szCmd) + strlen(szTarget) + 3);
|
|
// see if it is me!
|
|
if (stricmp(Nick_name, szNick) == 0) {
|
|
// Yup, it's me!
|
|
// szChat_channel[0]=NULL;
|
|
RemoveAllChatUsers();
|
|
}
|
|
|
|
RemoveChatUser(szNick);
|
|
return nullptr;
|
|
// Remove them to the userlist too!
|
|
}
|
|
if (stricmp(szCmd, "KICK") == 0) {
|
|
pszTempStr = GetWordNum(0, szRemLine);
|
|
strcpy(szTarget, pszTempStr);
|
|
pszTempStr = GetWordNum(1, szRemLine);
|
|
strcpy(szHackPrefix, pszTempStr);
|
|
pszTempStr = GetWordNum(2, szRemLine);
|
|
// see if it is me!
|
|
if (stricmp(Nick_name, GetWordNum(1, szRemLine)) == 0) {
|
|
// Yup, it's me!
|
|
szChat_channel[0] = '\0';
|
|
// bNewStatus=1;
|
|
AddChatCommandToQueue(CC_KICKED, nullptr, 0);
|
|
RemoveAllChatUsers();
|
|
}
|
|
// sprintf(szResponse,"*** %s has kicked %s from channel %s (%s)",szNick,szHackPrefix,szTarget,pszTempStr);
|
|
// Remove them to the userlist too!
|
|
RemoveChatUser(szNick);
|
|
return nullptr; // szResponse;
|
|
}
|
|
if (stricmp(szCmd, "NICK") == 0) {
|
|
// see if it is me!
|
|
if (stricmp(Nick_name, szNick) == 0) {
|
|
// Yup, it's me!
|
|
strcpy(Nick_name, GetWordNum(0, szRemLine));
|
|
}
|
|
char nicks[70];
|
|
snprintf(nicks, sizeof(nicks), "%s %s", szNick, GetWordNum(0, szRemLine));
|
|
AddChatCommandToQueue(CC_NICKCHANGED, nicks, strlen(nicks) + 1);
|
|
RemoveChatUser(szNick);
|
|
AddChatUser(GetWordNum(0, szRemLine));
|
|
// sprintf(szResponse,"*** %s is now known as %s",szNick,GetWordNum(0,szRemLine));
|
|
return nullptr; // szResponse;
|
|
}
|
|
if (stricmp(szCmd, "PING") == 0) {
|
|
// respond with pong (GetWordNum(0,szRemLine))
|
|
snprintf(szResponse, sizeof(szResponse), "/PONG :%s", GetWordNum(0, szRemLine));
|
|
SendChatString(szResponse, 1);
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "MODE") == 0) {
|
|
// Channel Mode info
|
|
return nullptr;
|
|
}
|
|
|
|
if (stricmp(szCmd, "401") == 0) {
|
|
// This is whois user info, we can get their tracker info from here. -5
|
|
char szWhoisUser[33];
|
|
strcpy(szWhoisUser, GetWordNum(1, szRemLine));
|
|
Getting_user_tracker_error = 1;
|
|
Getting_user_channel_error = 1;
|
|
|
|
snprintf(szResponse, sizeof(szResponse), TXT_PXO_ERRORNOTONLINE, szWhoisUser);
|
|
return szResponse;
|
|
}
|
|
if (stricmp(szCmd, "311") == 0) {
|
|
char szWhoisUser[33];
|
|
strcpy(szWhoisUser, GetWordNum(1, szRemLine));
|
|
// This is whois user info, we can get their tracker info from here. -5
|
|
// if(stricmp(Getting_user_tracker_info_for,szWhoisUser)==0)
|
|
//{
|
|
strcpy(User_req_tracker_id, GetWordNum(5, szRemLine));
|
|
//}
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "319") == 0) {
|
|
char szWhoisUser[33];
|
|
strcpy(szWhoisUser, GetWordNum(1, szRemLine));
|
|
// This is whois channel info -- what channel they are on -2
|
|
// if(stricmp(Getting_user_channel_info_for,szWhoisUser)==0)
|
|
//{
|
|
strcpy(User_req_channel, GetWordNum(2, szRemLine));
|
|
//}
|
|
return nullptr;
|
|
}
|
|
|
|
// End of whois and we didn't get a channel means they aren't in a channel.
|
|
if (stricmp(szCmd, "318") == 0) {
|
|
if (!*User_req_channel) {
|
|
User_req_channel[0] = '*';
|
|
}
|
|
}
|
|
|
|
if (stricmp(szCmd, "321") == 0) {
|
|
// start of channel list
|
|
FlushChannelList();
|
|
GettingChannelList = 1;
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "322") == 0) {
|
|
// channel list data
|
|
if (GettingChannelList == 1) {
|
|
char channel_list_name[33];
|
|
char sztopic[200];
|
|
strcpy(sztopic, GetWordNum(3, szRemLine));
|
|
strcpy(channel_list_name, GetWordNum(1, szRemLine));
|
|
AddChannel(channel_list_name, atoi(GetWordNum(2, szRemLine)), sztopic);
|
|
}
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "323") == 0) {
|
|
// end of channel list
|
|
GettingChannelList = 2;
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "324") == 0) {
|
|
// Channel Mode info
|
|
return nullptr;
|
|
}
|
|
|
|
if (stricmp(szCmd, "332") == 0) {
|
|
// Channel Topic, update status bar.
|
|
if (stricmp(szChat_channel, szTarget) == 0) {
|
|
// strncpy(szChanTopic,GetWordNum(2,szRemLine),70);
|
|
}
|
|
// sprintf(NewMsg.Message,"*** %s has changed the topic to: %s",szNick,GetWordNum(2,szRemLine));
|
|
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "TOPIC") == 0) {
|
|
// Channel Topic, update status bar.
|
|
if (stricmp(szChat_channel, szTarget) == 0) {
|
|
// strncpy(szChanTopic,GetWordNum(1,szRemLine),70);
|
|
}
|
|
// sprintf(NewMsg.Message,"*** %s has changed the topic to: %s",szNick,GetWordNum(1,szRemLine));
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "QUIT") == 0) {
|
|
// Remove the user!
|
|
RemoveChatUser(szNick);
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "376") == 0) // end of motd, trigger autojoin...
|
|
{
|
|
if (!Chat_server_connected) {
|
|
DLLmprintf(0, "Connected to chat server!\n");
|
|
Chat_server_connected = 1;
|
|
// We want to make sure we know our nick. This is somewhat of a hack
|
|
strcpy(Nick_name, GetWordNum(0, szRemLine + 1));
|
|
}
|
|
return nullptr;
|
|
}
|
|
if ((stricmp(szCmd, "377") == 0) || (stricmp(szCmd, "372") == 0) || (stricmp(szCmd, "372") == 0)
|
|
|
|
) {
|
|
// Stip the message, and display it.
|
|
pszTempStr = GetWordNum(3, Line);
|
|
snprintf(szResponse, sizeof(szResponse), "\1\xcf\xf8\xb9%s", pszTempStr);
|
|
return szResponse;
|
|
}
|
|
// Ignore these messages
|
|
if (((stricmp(szCmd, "366") == 0)) || (stricmp(szCmd, "333") == 0) || // Who set the topic
|
|
(stricmp(szCmd, "329") == 0)) // Time Channel created
|
|
/*
|
|
(stricmp(szCmd,"305")==0) ||
|
|
(stricmp(szCmd,"306")==0) ||
|
|
(stricmp(szCmd,"311")==0) || //WHOIS stuff
|
|
(stricmp(szCmd,"312")==0) ||
|
|
(stricmp(szCmd,"313")==0) ||
|
|
(stricmp(szCmd,"317")==0) ||
|
|
(stricmp(szCmd,"318")==0) ||
|
|
(stricmp(szCmd,"319")==0) ||
|
|
*/
|
|
|
|
{
|
|
return nullptr;
|
|
}
|
|
if (stricmp(szCmd, "353") == 0) {
|
|
|
|
// Names in the channel.
|
|
pszTempStr = GetWordNum(3, Line + iPrefixLen + strlen(szCmd) + 2);
|
|
strcpy(szRemLine, pszTempStr);
|
|
pszTempStr = strtok(szRemLine, " ");
|
|
|
|
while (pszTempStr) {
|
|
if (pszTempStr[0] == '@') {
|
|
AddChatUser(pszTempStr + 1);
|
|
} else if (pszTempStr[0] == '+') {
|
|
AddChatUser(pszTempStr + 1);
|
|
} else {
|
|
AddChatUser(pszTempStr);
|
|
}
|
|
pszTempStr = strtok(nullptr, " ");
|
|
}
|
|
return nullptr;
|
|
}
|
|
// MOTD Codes
|
|
if ((stricmp(szCmd, "001") == 0) || (stricmp(szCmd, "002") == 0) || (stricmp(szCmd, "003") == 0) ||
|
|
(stricmp(szCmd, "004") == 0) || (stricmp(szCmd, "251") == 0) || (stricmp(szCmd, "254") == 0) ||
|
|
(stricmp(szCmd, "255") == 0) || (stricmp(szCmd, "265") == 0) || (stricmp(szCmd, "375") == 0) ||
|
|
(stricmp(szCmd, "372") == 0) || (stricmp(szCmd, "375") == 0)) {
|
|
// Stip the message, and display it.
|
|
pszTempStr = GetWordNum(3, Line);
|
|
strcpy(szResponse, pszTempStr);
|
|
return nullptr;
|
|
// return szResponse;
|
|
}
|
|
if (stricmp(szCmd, "432") == 0) {
|
|
// Channel Mode info
|
|
snprintf(szResponse, sizeof(szResponse), "%s", TXT_PXO_BADNICK);
|
|
AddChatCommandToQueue(CC_DISCONNECTED, nullptr, 0);
|
|
return szResponse;
|
|
}
|
|
if (stricmp(szCmd, "433") == 0) {
|
|
// Channel Mode info
|
|
char new_nick[33];
|
|
snprintf(new_nick, sizeof(new_nick), "%s%d", Orignial_nick_name, Nick_variety);
|
|
strcpy(Nick_name, new_nick);
|
|
Nick_variety++;
|
|
snprintf(szResponse, sizeof(szResponse), "/NICK %s", new_nick);
|
|
SendChatString(szResponse, 1);
|
|
return nullptr;
|
|
}
|
|
// Default print
|
|
strcpy(szResponse, Line);
|
|
// return szResponse;
|
|
return nullptr;
|
|
}
|
|
|
|
void AddChatCommandToQueue(int command, const void *data, int len) {
|
|
Currcommand = Firstcommand;
|
|
if (Firstcommand == nullptr) {
|
|
Firstcommand = (Chat_command *)DLLmem_malloc(sizeof(Chat_command));
|
|
// ASSERT(Firstcommand);
|
|
Firstcommand->next = nullptr;
|
|
Currcommand = Firstcommand;
|
|
} else {
|
|
while (Currcommand->next) {
|
|
Currcommand = Currcommand->next;
|
|
}
|
|
Currcommand->next = (Chat_command *)DLLmem_malloc(sizeof(Chat_command));
|
|
// ASSERT(Currcommand->next);
|
|
Currcommand = Currcommand->next;
|
|
}
|
|
Currcommand->command = command;
|
|
if (len && data)
|
|
memcpy(&Currcommand->data, data, len);
|
|
Currcommand->next = nullptr;
|
|
}
|
|
|
|
Chat_command *GetChatCommandFromQueue() {
|
|
static Chat_command response_cmd;
|
|
Chat_command *tmp_cmd;
|
|
if (!Firstcommand)
|
|
return nullptr;
|
|
Currcommand = Firstcommand;
|
|
memcpy(&response_cmd, Currcommand, sizeof(Chat_command));
|
|
tmp_cmd = Currcommand->next;
|
|
DLLmem_free(Firstcommand);
|
|
Firstcommand = tmp_cmd;
|
|
return &response_cmd;
|
|
}
|
|
|
|
void FlushChatCommandQueue() {
|
|
Chat_command *tmp_cmd;
|
|
Currcommand = Firstcommand;
|
|
|
|
while (Currcommand) {
|
|
tmp_cmd = Currcommand->next;
|
|
DLLmem_free(Currcommand);
|
|
Currcommand = tmp_cmd;
|
|
}
|
|
Firstcommand = nullptr;
|
|
}
|
|
|
|
void FlushChannelList() {
|
|
Chat_channel *tmp_chan;
|
|
Currchannel = Firstchannel;
|
|
|
|
while (Currchannel) {
|
|
tmp_chan = Currchannel->next;
|
|
DLLmem_free(Currchannel);
|
|
Currchannel = tmp_chan;
|
|
}
|
|
Firstchannel = nullptr;
|
|
}
|
|
char *GetChannelList() {
|
|
int ichan_list_length = 0;
|
|
char sznumusers[10];
|
|
|
|
if (GettingChannelList != 2)
|
|
return nullptr;
|
|
if (!Socket_connected)
|
|
return nullptr;
|
|
|
|
if (Chan_list) {
|
|
DLLmem_free(Chan_list);
|
|
Chan_list = nullptr;
|
|
}
|
|
|
|
Currchannel = Firstchannel;
|
|
while (Currchannel) {
|
|
ichan_list_length += strlen(Currchannel->topic) + 1 + strlen(Currchannel->channel_name) + 1 +
|
|
5; // 1 for the space, and 4 for the number of users 0000-9999 + space
|
|
Currchannel = Currchannel->next;
|
|
}
|
|
Currchannel = Firstchannel;
|
|
Chan_list = (char *)DLLmem_malloc(ichan_list_length + 1);
|
|
Chan_list[0] = '\0';
|
|
while (Currchannel) {
|
|
strcat(Chan_list, "$");
|
|
strcat(Chan_list, Currchannel->channel_name);
|
|
strcat(Chan_list, " ");
|
|
snprintf(sznumusers, sizeof(sznumusers), "%d ", Currchannel->users);
|
|
strcat(Chan_list, sznumusers);
|
|
strcat(Chan_list, Currchannel->topic); // fgets
|
|
strcat(Chan_list, " ");
|
|
Currchannel = Currchannel->next;
|
|
}
|
|
FlushChannelList();
|
|
GettingChannelList = 0;
|
|
return Chan_list;
|
|
}
|
|
|
|
void AddChannel(char *channel, uint16_t numusers, char *topic) {
|
|
Currchannel = Firstchannel;
|
|
if (Firstchannel == nullptr) {
|
|
Firstchannel = (Chat_channel *)DLLmem_malloc(sizeof(Chat_channel));
|
|
// ASSERT(Firstchannel);
|
|
strcpy(Firstchannel->channel_name, channel);
|
|
strcpy(Firstchannel->topic, topic);
|
|
Firstchannel->users = numusers;
|
|
Firstchannel->next = nullptr;
|
|
Currchannel = Firstchannel;
|
|
} else {
|
|
while (Currchannel->next) {
|
|
Currchannel = Currchannel->next;
|
|
}
|
|
Currchannel->next = (Chat_channel *)DLLmem_malloc(sizeof(Chat_channel));
|
|
// ASSERT(Currchannel->next);
|
|
Currchannel = Currchannel->next;
|
|
strcpy(Currchannel->channel_name, channel);
|
|
strcpy(Currchannel->topic, topic);
|
|
Currchannel->users = numusers;
|
|
}
|
|
Currchannel->next = nullptr;
|
|
}
|
|
|
|
char *GetTrackerIdByUser(const char *nickname) {
|
|
char szWhoisCmd[100];
|
|
|
|
if (nickname == (char *)-1) {
|
|
GettingUserTID = 0;
|
|
Getting_user_tracker_error = 0;
|
|
return nullptr;
|
|
} else if (GettingUserTID) {
|
|
if (Getting_user_tracker_error) {
|
|
Getting_user_tracker_error = 0;
|
|
GettingUserTID = 0;
|
|
return (char *)-1;
|
|
}
|
|
|
|
if (*User_req_tracker_id) {
|
|
GettingUserTID = 0;
|
|
return User_req_tracker_id;
|
|
}
|
|
} else {
|
|
strcpy(Getting_user_tracker_info_for, nickname);
|
|
snprintf(szWhoisCmd, sizeof(szWhoisCmd), "/WHOIS %s", nickname);
|
|
User_req_tracker_id[0] = '\0';
|
|
SendChatString(szWhoisCmd, 1);
|
|
GettingUserTID = 1;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
char *GetChannelByUser(const char *nickname) {
|
|
char szWhoisCmd[100];
|
|
|
|
if (nickname == (char *)-1) {
|
|
GettingUserChannel = 0;
|
|
Getting_user_channel_error = 0;
|
|
return nullptr;
|
|
} else if (GettingUserChannel) {
|
|
if (Getting_user_channel_error) {
|
|
Getting_user_channel_error = 0;
|
|
GettingUserChannel = 0;
|
|
return (char *)-1;
|
|
}
|
|
if (*User_req_channel) {
|
|
GettingUserChannel = 0;
|
|
return User_req_channel;
|
|
}
|
|
} else {
|
|
strcpy(Getting_user_channel_info_for, nickname);
|
|
User_req_channel[0] = '\0';
|
|
snprintf(szWhoisCmd, sizeof(szWhoisCmd), "/WHOIS %s", nickname);
|
|
SendChatString(szWhoisCmd, 1);
|
|
GettingUserChannel = 1;
|
|
}
|
|
return nullptr;
|
|
}
|