1
0
Fork 0
coupserv/general_network.c
2024-04-28 08:02:01 -04:00

193 lines
5.4 KiB
C

// Network stuff for HaxServ
//
// Written by: Test_User <hax@andrewyu.org>
//
// This is free and unencumbered software released into the public
// domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include "network.h"
#include "tls.h"
#include "config.h"
char channel_mode_types[UCHAR_MAX+1] = {
['v'] = MODE_TYPE_USERS,
['h'] = MODE_TYPE_USERS,
['o'] = MODE_TYPE_USERS,
['a'] = MODE_TYPE_USERS,
['q'] = MODE_TYPE_USERS,
['b'] = MODE_TYPE_MULTIPLE,
['e'] = MODE_TYPE_MULTIPLE,
['I'] = MODE_TYPE_MULTIPLE,
['c'] = MODE_TYPE_NOARGS,
['d'] = MODE_TYPE_REPLACE,
['f'] = MODE_TYPE_REPLACE,
['g'] = MODE_TYPE_MULTIPLE,
['i'] = MODE_TYPE_NOARGS,
['j'] = MODE_TYPE_REPLACE,
['k'] = MODE_TYPE_REPLACE,
['l'] = MODE_TYPE_REPLACE,
['m'] = MODE_TYPE_NOARGS,
['n'] = MODE_TYPE_NOARGS,
['p'] = MODE_TYPE_NOARGS,
['r'] = MODE_TYPE_NOARGS,
['s'] = MODE_TYPE_NOARGS,
['t'] = MODE_TYPE_NOARGS,
['u'] = MODE_TYPE_NOARGS,
['w'] = MODE_TYPE_MULTIPLE,
['z'] = MODE_TYPE_NOARGS,
['A'] = MODE_TYPE_NOARGS,
['B'] = MODE_TYPE_NOARGS,
['C'] = MODE_TYPE_NOARGS,
['D'] = MODE_TYPE_NOARGS,
['E'] = MODE_TYPE_REPLACE,
['F'] = MODE_TYPE_REPLACE,
['G'] = MODE_TYPE_NOARGS,
['H'] = MODE_TYPE_REPLACE,
['J'] = MODE_TYPE_REPLACE,
['K'] = MODE_TYPE_NOARGS,
['L'] = MODE_TYPE_REPLACE,
['M'] = MODE_TYPE_NOARGS,
['N'] = MODE_TYPE_NOARGS,
['O'] = MODE_TYPE_NOARGS,
['P'] = MODE_TYPE_NOARGS,
['Q'] = MODE_TYPE_NOARGS,
['R'] = MODE_TYPE_NOARGS,
['S'] = MODE_TYPE_NOARGS,
['T'] = MODE_TYPE_NOARGS,
['X'] = MODE_TYPE_MULTIPLE,
};
int privmsg(struct string source, struct string target, size_t num_message_parts, struct string message[num_message_parts]) {
if (!STRING_EQ(target, STRING("1HC000001"))) { // if not sending to our one local user
if (source.len != 0) {
SEND(STRING(":"));
SEND(source);
SEND(STRING(" PRIVMSG "));
} else {
SEND(STRING("PRIVMSG "));
}
SEND(target);
SEND(STRING(" :"));
for (size_t i = 0; i < num_message_parts; i++)
SEND(message[i]);
SEND(STRING("\n"));
} else {
goto privmsg_client;
}
if (target.data[0] == '#') {
struct channel_info *channel = get_table_index(channel_list, target);
if (channel && has_table_index(channel->user_list, STRING("1HC000001")))
goto privmsg_client;
}
return 0;
privmsg_client:
if (source.len != 0) {
SENDCLIENT(STRING(":"));
// TODO: Proper lookups of users and such
if (STRING_EQ(source, STRING("1HC000000"))) {
SENDCLIENT(nick);
SENDCLIENT(STRING("!"));
SENDCLIENT(nick);
SENDCLIENT(STRING("@"));
SENDCLIENT(hostmask);
} else if (STRING_EQ(source, STRING("1HC"))) {
SENDCLIENT(server_name);
} else {
SENDCLIENT(source);
}
SENDCLIENT(STRING(" PRIVMSG "));
} else {
SENDCLIENT(STRING(":"));
SENDCLIENT(server_name);
SENDCLIENT(STRING(" PRIVMSG "));
}
if (STRING_EQ(target, STRING("1HC000001")))
SENDCLIENT(client_nick);
else
SENDCLIENT(target);
SENDCLIENT(STRING(" :"));
for (size_t i = 0; i < num_message_parts; i++)
SENDCLIENT(message[i]);
SENDCLIENT(STRING("\r\n"));
return 0;
}
int remove_user(struct string uid, struct string reason) { // If disconnecting the local client, set client_connected = 0 *before* calling this
struct user_info *info = get_table_index(user_list, uid);
if (!info)
return 1;
int send_client = client_connected;
for (uint64_t i = 0; i < channel_list.len; i++) { // TODO: Use channel list attached to the user (doesn't exist yet)
struct channel_info *chan_info = channel_list.array[i].ptr;
if (has_table_index(chan_info->user_list, uid)) {
if (send_client && has_table_index(chan_info->user_list, STRING("1HC000001"))) {
SENDCLIENT(STRING(":"));
SENDCLIENT(info->nick);
SENDCLIENT(STRING("!"));
SENDCLIENT(info->ident);
SENDCLIENT(STRING("@"));
SENDCLIENT(info->vhost);
if (reason.len != 0) {
SENDCLIENT(STRING(" QUIT :"));
SENDCLIENT(reason);
SENDCLIENT(STRING("\r\n"));
} else {
SENDCLIENT(STRING(" QUIT\r\n"));
}
send_client = 0;
}
remove_table_index(&(chan_info->user_list), uid);
}
}
remove_table_index(&user_list, uid);
free(info->server.data);
free(info->nick.data);
free(info->opertype.data);
free(info->metadata.array);
free(info->realname.data);
free(info->hostname.data);
free(info->ip.data);
free(info->ident.data);
free(info->vhost.data);
free(info);
return 0;
}