// Network stuff for HaxServ // // Written by: Test_User // // 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 #include #include #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; }