forked from noisytoot/rubyserv-iirc
193 lines
5.4 KiB
C
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;
|
|
}
|