aboutsummaryrefslogtreecommitdiff
path: root/pseudoclients
diff options
context:
space:
mode:
authorTest_User <hax@andrewyu.org>2024-06-17 21:10:37 -0400
committerTest_User <hax@andrewyu.org>2024-06-17 21:10:37 -0400
commit351792c4ce9dad51a5464821e843b7e22ff6c6bd (patch)
tree270b8904ed602c39125443bfb8800787f227c455 /pseudoclients
parentc80cccdcc87aeee9d897ae9bfcea8632312fcb74 (diff)
downloadhaxircd-351792c4ce9dad51a5464821e843b7e22ff6c6bd.tar.gz
haxircd-351792c4ce9dad51a5464821e843b7e22ff6c6bd.zip
Spelling fixes
Diffstat (limited to 'pseudoclients')
-rw-r--r--pseudoclients/haxserv.c914
-rw-r--r--pseudoclients/haxserv.h66
2 files changed, 980 insertions, 0 deletions
diff --git a/pseudoclients/haxserv.c b/pseudoclients/haxserv.c
new file mode 100644
index 0000000..6c97067
--- /dev/null
+++ b/pseudoclients/haxserv.c
@@ -0,0 +1,914 @@
+// One of the code files 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 <dlfcn.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "../config.h"
+#include "../haxstring.h"
+#include "../haxstring_utils.h"
+#include "../general_network.h"
+#include "../pseudoclients.h"
+
+#include "haxserv.h"
+
+#ifdef USE_PROTOCOLS
+#include "../protocols.h"
+#endif
+
+struct table haxserv_pseudoclient_commands = {0};
+struct table haxserv_pseudoclient_prefixes = {0};
+
+// TODO: Potentially leaky on failure
+int haxserv_pseudoclient_init(void) {
+ size_t now;
+ {
+ time_t tmp = time(0);
+ if (tmp < 0) {
+ WRITES(2, STRING("Please check your clock.\r\n"));
+ return 1;
+ }
+
+ now = (size_t)tmp;
+ }
+
+ if (add_user(SID, SID, HAXSERV_UID, HAXSERV_NICK, HAXSERV_FULLNAME, HAXSERV_IDENT, HAXSERV_VHOST, HAXSERV_HOST, HAXSERV_ADDRESS, now, now, 0, 0, 0, 1, HAXSERV_PSEUDOCLIENT) != 0)
+ return 1;
+
+ struct user_info *user = get_table_index(user_list, HAXSERV_UID);
+ for (size_t i = 0; i < HAXSERV_NUM_PREJOIN_CHANNELS; i++) {
+ if (set_channel(SID, HAXSERV_PREJOIN_CHANNELS[i], now, 1, &user) != 0)
+ return 1;
+ }
+
+ return haxserv_pseudoclient_post_reload();
+}
+
+int haxserv_pseudoclient_post_reload(void) {
+ haxserv_pseudoclient_commands.array = malloc(0);
+ haxserv_pseudoclient_prefixes.array = malloc(0);
+
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("HELP"), &haxserv_pseudoclient_help_command_def) != 0)
+ return 1;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("SUS"), &haxserv_pseudoclient_sus_command_def) != 0)
+ return 1;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("CR"), &haxserv_pseudoclient_cr_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_clear_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("CLEAR"), &haxserv_pseudoclient_clear_command_def) != 0)
+ return 1;
+#ifdef USE_INSPIRCD2_PROTOCOL
+ haxserv_pseudoclient_raw_inspircd2_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING(":"), &haxserv_pseudoclient_raw_inspircd2_command_def) != 0)
+ return 1;
+ if (set_table_index(&haxserv_pseudoclient_prefixes, STRING(":"), &haxserv_pseudoclient_raw_inspircd2_command_def) != 0)
+ return 1;
+#endif
+ haxserv_pseudoclient_kill_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("KILL"), &haxserv_pseudoclient_kill_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_spam_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("SPAM"), &haxserv_pseudoclient_spam_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_reload_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("RELOAD"), &haxserv_pseudoclient_reload_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_allow_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("ALLOW"), &haxserv_pseudoclient_allow_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_deny_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("DENY"), &haxserv_pseudoclient_deny_command_def) != 0)
+ return 1;
+ haxserv_pseudoclient_reconnect_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("RECONNECT"), &haxserv_pseudoclient_reconnect_command_def) != 0)
+ return 1;
+// haxserv_pseudoclient_sanick_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+// if (set_table_index(&haxserv_pseudoclient_commands, STRING("SANICK"), &haxserv_pseudoclient_sanick_command_def) != 0)
+// return 1;
+ haxserv_pseudoclient_get_command_def.privs = HAXSERV_REQUIRED_OPER_TYPE;
+ if (set_table_index(&haxserv_pseudoclient_commands, STRING("GET"), &haxserv_pseudoclient_get_command_def) != 0)
+ return 1;
+
+ pseudoclients[HAXSERV_PSEUDOCLIENT].init = haxserv_pseudoclient_init;
+
+ pseudoclients[HAXSERV_PSEUDOCLIENT].post_reload = haxserv_pseudoclient_post_reload;
+ pseudoclients[HAXSERV_PSEUDOCLIENT].pre_reload = haxserv_pseudoclient_pre_reload;
+
+ pseudoclients[HAXSERV_PSEUDOCLIENT].allow_kill = haxserv_pseudoclient_allow_kill;
+ pseudoclients[HAXSERV_PSEUDOCLIENT].allow_kick = haxserv_pseudoclient_allow_kick;
+
+ pseudoclients[HAXSERV_PSEUDOCLIENT].handle_privmsg = haxserv_pseudoclient_handle_privmsg;
+
+ return 0;
+}
+
+int haxserv_pseudoclient_pre_reload(void) {
+ clear_table(&haxserv_pseudoclient_commands);
+ clear_table(&haxserv_pseudoclient_prefixes);
+
+ free(haxserv_pseudoclient_commands.array);
+ free(haxserv_pseudoclient_prefixes.array);
+
+ return 0;
+}
+
+int haxserv_pseudoclient_allow_kill(struct string from, struct string source, struct user_info *user, struct string reason) {
+ return 0;
+}
+
+int haxserv_pseudoclient_allow_kick(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason) {
+ return 0;
+}
+
+void haxserv_pseudoclient_handle_privmsg(struct string from, struct string source, struct string target, struct string msg) {
+ struct string respond_to;
+ struct string prefix;
+
+ size_t offset;
+ if (!STRING_EQ(target, HAXSERV_UID)) { // Must be channel
+ if (msg.len < HAXSERV_COMMAND_PREFIX.len || memcmp(msg.data, HAXSERV_COMMAND_PREFIX.data, HAXSERV_COMMAND_PREFIX.len) != 0)
+ return;
+
+ offset = HAXSERV_COMMAND_PREFIX.len;
+
+ respond_to = target;
+ prefix = HAXSERV_COMMAND_PREFIX;
+ } else {
+ offset = 0;
+
+ respond_to = source;
+ prefix = STRING("");
+ }
+
+ if (offset >= msg.len || msg.data[offset] == ' ')
+ return;
+
+ size_t argc = 0;
+ size_t old_offset = offset;
+ while (offset < msg.len) {
+ while (offset < msg.len && msg.data[offset] != ' ')
+ offset++;
+
+ argc++;
+
+ while (offset < msg.len && msg.data[offset] == ' ')
+ offset++;
+ }
+ offset = old_offset;
+
+ struct string argv[argc];
+ size_t i = 0;
+ while (offset < msg.len) {
+ argv[i].data = &(msg.data[offset]);
+ size_t start = offset;
+
+ while (offset < msg.len && msg.data[offset] != ' ')
+ offset++;
+
+ argv[i].len = offset - start;
+
+ while (offset < msg.len && msg.data[offset] == ' ')
+ offset++;
+
+ i++;
+ }
+
+ msg.data += prefix.len;
+ msg.len -= prefix.len;
+
+ struct command_def *cmd;
+
+ struct string case_str = {.len = argv[0].len};
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(argv[0].data[i]);
+
+ cmd = get_table_index(haxserv_pseudoclient_commands, case_str);
+
+ free(case_str.data);
+ } else {
+ cmd = get_table_index(haxserv_pseudoclient_commands, argv[0]);
+ }
+
+ char trim;
+ if (cmd) {
+ trim = 1;
+ } else {
+ trim = 0;
+ case_str.len = msg.len;
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(msg.data[i]);
+
+ cmd = get_table_prefix(haxserv_pseudoclient_prefixes, case_str);
+
+ free(case_str.data);
+ } else {
+ cmd = get_table_prefix(haxserv_pseudoclient_prefixes, msg);
+ }
+ }
+
+ if (cmd) {
+ if (cmd->privs.len != 0 && !(!has_table_index(user_list, source) && has_table_index(server_list, source))) {
+ struct user_info *user = get_table_index(user_list, source);
+ // TODO: Multiple privilege levels
+ if (!STRING_EQ(user->oper_type, cmd->privs)) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("You are not authorized to execute this command."));
+ return;
+ }
+ }
+
+ {
+ struct string log_msg_parts[] = {
+ STRING("User `"),
+ STRING(""),
+ STRING("' executes `"),
+ msg,
+ STRING("'"),
+ };
+
+ if (trim) {
+ msg.data += argv[0].len;
+ msg.len -= argv[0].len;
+ if (msg.len > 1) {
+ msg.data++;
+ msg.len--;
+ }
+ }
+
+ struct user_info *user = get_table_index(user_list, source);
+ if (user) {
+ log_msg_parts[1] = user->nick;
+ } else {
+ log_msg_parts[0] = STRING("Unknown user executes `");
+ log_msg_parts[2] = STRING("");
+ }
+
+ struct string log_msg;
+ if (str_combine(&log_msg, sizeof(log_msg_parts)/sizeof(*log_msg_parts), log_msg_parts) != 0)
+ return;
+ privmsg(SID, HAXSERV_UID, HAXSERV_LOG_CHANNEL, log_msg);
+ free(log_msg.data);
+ }
+
+ cmd->func(from, source, msg, respond_to, argc - 1, &(argv[1]));
+ } else {
+ struct string msg_parts[] = {
+ STRING("Unknown command: "),
+ prefix,
+ argv[0],
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, 3, msg_parts) != 0)
+ return;
+
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+
+ free(full_msg.data);
+ }
+}
+
+int haxserv_pseudoclient_help_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Command list:"));
+ for (size_t i = 0; i < haxserv_pseudoclient_commands.len; i++) {
+ struct command_def *cmd = haxserv_pseudoclient_commands.array[i].ptr;
+
+ struct string msg_parts[] = {
+ STRING(" "),
+ HAXSERV_COMMAND_PREFIX,
+ cmd->aligned_name,
+ STRING("\x0F"),
+ cmd->summary,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) != 0) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("ERROR: Unable to create help message line."));
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ }
+ }
+
+ notice(SID, HAXSERV_UID, respond_to, STRING("Prefix list:"));
+ for (size_t i = 0; i < haxserv_pseudoclient_prefixes.len; i++) {
+ struct command_def *cmd = haxserv_pseudoclient_prefixes.array[i].ptr;
+
+ struct string msg_parts[] = {
+ STRING(" "),
+ HAXSERV_COMMAND_PREFIX,
+ cmd->aligned_name,
+ STRING("\x0F"),
+ cmd->summary,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) != 0) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("ERROR: Unable to create help message line."));
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ }
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_help_command_def = {
+ .func = haxserv_pseudoclient_help_command,
+ .summary = STRING("Shows a list of commands."),
+ .aligned_name = STRING("help "),
+ .name = STRING("help"),
+};
+
+struct kill_or_msg {
+ char type;
+ struct string msg;
+} haxserv_pseudoclient_sus_actions[] = {
+ {0, STRING("DuckServ is very sus.")},
+ {0, STRING("I was the impostor, but you only know because I killed you.")},
+ {0, STRING("\\x1b(0")},
+ {1, STRING("Ejected (1 Impostor remains)")},
+ {1, STRING("Ejected, and the crewmates have won.")},
+}, haxserv_pseudoclient_cr_actions[] = {
+ {0, STRING("You are now a cruxian toxicpod, kill the sharded crewmates.")},
+ {0, STRING("You are now a cruxian omura, kill the sharded crewmates.")},
+ {0, STRING("You are now a cruxian oct, but you can out of reactors.")},
+ {1, STRING("Eliminated (You became a cruxian eclipse, but were drawn to my bait reactor)")},
+ {0, STRING("You attempted to change into a cruxian navanax, but were caught in the act.")},
+};
+
+int haxserv_pseudoclient_sus_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ size_t index = (size_t)random() % (sizeof(haxserv_pseudoclient_sus_actions) / sizeof(*haxserv_pseudoclient_sus_actions));
+
+ if (haxserv_pseudoclient_sus_actions[index].type) {
+ struct user_info *user = get_table_index(user_list, sender);
+ if (!user)
+ return 0;
+
+ kill_user(SID, HAXSERV_UID, user, haxserv_pseudoclient_sus_actions[index].msg);
+ } else {
+ privmsg(SID, HAXSERV_UID, respond_to, haxserv_pseudoclient_sus_actions[index].msg);
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_sus_command_def = {
+ .func = haxserv_pseudoclient_sus_command,
+ .summary = STRING("You seem a bit sus today."),
+ .aligned_name = STRING("sus "),
+ .name = STRING("sus"),
+};
+
+int haxserv_pseudoclient_cr_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ size_t index = (size_t)random() % (sizeof(haxserv_pseudoclient_cr_actions) / sizeof(*haxserv_pseudoclient_cr_actions));
+
+ if (haxserv_pseudoclient_cr_actions[index].type) {
+ struct user_info *user = get_table_index(user_list, sender);
+ if (!user)
+ return 0;
+
+ kill_user(SID, HAXSERV_UID, user, haxserv_pseudoclient_cr_actions[index].msg);
+ } else {
+ privmsg(SID, HAXSERV_UID, respond_to, haxserv_pseudoclient_cr_actions[index].msg);
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_cr_command_def = {
+ .func = haxserv_pseudoclient_cr_command,
+ .summary = STRING("Join the crux side."),
+ .aligned_name = STRING("cr "),
+ .name = STRING("cr"),
+};
+
+int haxserv_pseudoclient_clear_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 1) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Missing args!"));
+ return 0;
+ }
+
+ struct channel_info *channel = get_table_index(channel_list, argv[0]);
+ if (!channel) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("That channel doesn't seem to exist, so is thereby already cleared."));
+ return 0;
+ }
+
+ size_t i = 0;
+ while (channel->user_list.len > i) {
+ if (kick_channel(SID, HAXSERV_UID, channel, channel->user_list.array[i].ptr, STRING("")) != 0) {
+ i++;
+ }
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_clear_command_def = {
+ .func = haxserv_pseudoclient_clear_command,
+ .summary = STRING("Clears a channel."),
+ .aligned_name = STRING("clear "),
+ .name = STRING("clear"),
+};
+
+#ifdef USE_INSPIRCD2_PROTOCOL
+int haxserv_pseudoclient_raw_inspircd2_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ protocols[INSPIRCD2_PROTOCOL].propagate(SID, original_message);
+ protocols[INSPIRCD2_PROTOCOL].propagate(SID, STRING("\n"));
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_raw_inspircd2_command_def = {
+ .func = haxserv_pseudoclient_raw_inspircd2_command,
+ .summary = STRING("Sends a raw message to all InspIRCd v2 links."),
+ .aligned_name = STRING(": "),
+ .name = STRING(":"),
+};
+#endif
+
+// TODO: Kill reason as an argument
+int haxserv_pseudoclient_kill_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 1) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Insufficient parameters."));
+ return 0;
+ }
+
+ struct user_info *user = get_table_index(user_list, argv[0]);
+ if (user) {
+ kill_user(SID, HAXSERV_UID, user, STRING("Impostor removed."));
+ return 0;
+ }
+
+ for (size_t i = 0; i < user_list.len; i++) {
+ struct user_info *user = user_list.array[i].ptr;
+ if (STRING_EQ(user->nick, argv[0])) {
+ kill_user(SID, HAXSERV_UID, user_list.array[i].ptr, STRING("Impostor removed."));
+ return 0;
+ }
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_kill_command_def = {
+ .func = haxserv_pseudoclient_kill_command,
+ .summary = STRING("Kills a user."),
+ .aligned_name = STRING("kill "),
+ .name = STRING("kill"),
+};
+
+int haxserv_pseudoclient_spam_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 2) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Insufficient parameters."));
+ return 0;
+ }
+
+ char err;
+ size_t count = str_to_unsigned(argv[0], &err);
+ if (err) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Unknown number."));
+ } else if (count > 5000) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Number exceeds the limit."));
+ }
+
+ size_t offset = (size_t)(argv[1].data - original_message.data);
+ original_message.data += offset;
+ original_message.len -= offset;
+
+ struct command_def *cmd;
+
+ struct string case_str = {.len = argv[1].len};
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(argv[1].data[i]);
+
+ cmd = get_table_index(haxserv_pseudoclient_commands, case_str);
+
+ free(case_str.data);
+ } else {
+ cmd = get_table_index(haxserv_pseudoclient_commands, argv[1]);
+ }
+
+ if (cmd) {
+ original_message.data += argv[1].len;
+ original_message.len -= argv[1].len;
+ if (original_message.len > 1) {
+ original_message.data++;
+ original_message.len--;
+ }
+ } else {
+ case_str.len = original_message.len;
+ case_str.data = malloc(case_str.len);
+ if (case_str.data) {
+ for (size_t i = 0; i < case_str.len; i++)
+ case_str.data[i] = CASEMAP(original_message.data[i]);
+
+ cmd = get_table_prefix(haxserv_pseudoclient_prefixes, case_str);
+
+ free(case_str.data);
+ } else {
+ cmd = get_table_prefix(haxserv_pseudoclient_prefixes, original_message);
+ }
+ }
+
+ if (cmd) {
+ if (cmd->privs.len != 0 && !(!has_table_index(user_list, sender) && has_table_index(server_list, sender))) {
+ struct user_info *user = get_table_index(user_list, sender);
+ // TODO: Multiple privilege levels
+ if (!STRING_EQ(user->oper_type, cmd->privs)) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("You are not authorized to execute this command."));
+ return 0;
+ }
+ }
+
+ if (cmd->func == haxserv_pseudoclient_spam_command) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Spam recursion is not allowed. The limit is for your own sake, please do not violate it."));
+ return 0;
+ }
+
+ for (size_t i = 0; i < count; i++)
+ cmd->func(from, sender, original_message, respond_to, argc - 2, &(argv[2]));
+ } else {
+ struct string msg_parts[] = {
+ STRING("Unknown command: "),
+ argv[1],
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) != 0)
+ return 0;
+
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+
+ free(full_msg.data);
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_spam_command_def = {
+ .func = haxserv_pseudoclient_spam_command,
+ .summary = STRING("Repeats a command a specified amount of times."),
+ .aligned_name = STRING("spam "),
+ .name = STRING("spam"),
+};
+
+int haxserv_pseudoclient_reload_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ reload_pseudoclients[HAXSERV_PSEUDOCLIENT] = 1;
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_reload_command_def = {
+ .func = haxserv_pseudoclient_reload_command,
+ .summary = STRING("Reloads a module."),
+ .aligned_name = STRING("reload "),
+ .name = STRING("reload"),
+};
+
+int haxserv_pseudoclient_allow_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 1) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Insufficient parameters."));
+ return 0;
+ }
+
+ struct user_info *user = get_table_index(user_list, argv[0]);
+ if (!user) {
+ char found = 0;
+ for (size_t i = 0; i < user_list.len; i++) {
+ user = user_list.array[i].ptr;
+ if (STRING_EQ(user->nick, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return 0;
+ }
+
+ oper_user(SID, user, HAXSERV_REQUIRED_OPER_TYPE);
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_allow_command_def = {
+ .func = haxserv_pseudoclient_allow_command,
+ .summary = STRING("Grants a user access to the extended command set."),
+ .aligned_name = STRING("allow "),
+ .name = STRING("allow"),
+};
+
+int haxserv_pseudoclient_deny_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 1) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Insufficient parameters."));
+ return 0;
+ }
+
+ struct user_info *user = get_table_index(user_list, argv[0]);
+ if (!user) {
+ char found = 0;
+ for (size_t i = 0; i < user_list.len; i++) {
+ user = user_list.array[i].ptr;
+ if (STRING_EQ(user->nick, argv[0])) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return 0;
+ }
+
+ oper_user(SID, user, STRING(""));
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_deny_command_def = {
+ .func = haxserv_pseudoclient_deny_command,
+ .summary = STRING("Denys a user access to the extended command set."),
+ .aligned_name = STRING("deny "),
+ .name = STRING("deny"),
+};
+
+int haxserv_pseudoclient_reconnect_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ for (size_t i = 0; i < self->connected_to.len; i++) {
+ struct server_info *adjacent = self->connected_to.array[i].ptr;
+ networks[adjacent->net].shutdown(adjacent->handle);
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_reconnect_command_def = {
+ .func = haxserv_pseudoclient_reconnect_command,
+ .summary = STRING("Resets all connections."),
+ .aligned_name = STRING("reconnect "),
+ .name = STRING("reconnect"),
+};
+
+int haxserv_pseudoclient_sanick_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ // TODO: Implement this later
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_sanick_command_def = {
+ .func = haxserv_pseudoclient_sanick_command,
+ .summary = STRING("Changes a user's nick, without violating protocols."),
+ .aligned_name = STRING("sanick "),
+ .name = STRING("sanick"),
+};
+
+int haxserv_pseudoclient_get_command(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv) {
+ if (argc < 1) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Missing argument."));
+ return 0;
+ }
+
+ if (STRING_EQ(argv[0], STRING("help"))) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Valid parameters: [uid | nick | info]"));
+ } else if (STRING_EQ(argv[0], STRING("uid"))) {
+ if (argc < 2) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Missing arguments."));
+ return 0;
+ }
+
+ for (size_t i = 0; i < user_list.len; i++) {
+ struct user_info *user = user_list.array[i].ptr;
+ if (STRING_EQ(argv[1], user->nick)) {
+ notice(SID, HAXSERV_UID, respond_to, user->uid);
+ return 0;
+ }
+ }
+
+ notice(SID, HAXSERV_UID, respond_to, STRING("User is unknown."));
+ } else if (STRING_EQ(argv[0], STRING("nick"))) {
+ if (argc < 2) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Missing arguments."));
+ return 0;
+ }
+
+ struct user_info *user = get_table_index(user_list, argv[1]);
+ if (user) {
+ notice(SID, HAXSERV_UID, respond_to, user->nick);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("User is unknown."));
+ }
+ } else if (STRING_EQ(argv[0], STRING("info"))) {
+ if (argc < 2) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("Missing arguments."));
+ return 0;
+ }
+
+ struct user_info *user = get_table_index(user_list, argv[1]);
+ if (!user) {
+ char found = 0;
+ for (size_t i = 0; i < user_list.len; i++) {
+ user = user_list.array[i].ptr;
+ if (STRING_EQ(argv[1], user->nick)) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ notice(SID, HAXSERV_UID, respond_to, STRING("User is unknown."));
+ return 0;
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("UID: "),
+ user->uid,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Nick: "),
+ user->nick,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Fullname: "),
+ user->fullname,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Ident: "),
+ user->ident,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("VHost: "),
+ user->vhost,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Host: "),
+ user->host,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Address: "),
+ user->address,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("User timestamp: "),
+ user->user_ts_str,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Nick timestamp: "),
+ user->nick_ts_str,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Oper type: "),
+ user->oper_type,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+
+ {
+ struct string msg_parts[] = {
+ STRING("Server: "),
+ user->server,
+ };
+
+ struct string full_msg;
+ if (str_combine(&full_msg, sizeof(msg_parts)/sizeof(*msg_parts), msg_parts) == 0) {
+ notice(SID, HAXSERV_UID, respond_to, full_msg);
+ free(full_msg.data);
+ } else {
+ notice(SID, HAXSERV_UID, respond_to, STRING("<Allocation failure>"));
+ }
+ }
+ }
+
+ return 0;
+}
+struct command_def haxserv_pseudoclient_get_command_def = {
+ .func = haxserv_pseudoclient_get_command,
+ .summary = STRING("Resets all connections."),
+ .aligned_name = STRING("get "),
+ .name = STRING("get"),
+};
diff --git a/pseudoclients/haxserv.h b/pseudoclients/haxserv.h
new file mode 100644
index 0000000..89a955e
--- /dev/null
+++ b/pseudoclients/haxserv.h
@@ -0,0 +1,66 @@
+// 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.
+
+#pragma once
+
+#include "../haxstring.h"
+#include "../general_network.h"
+
+struct command_def {
+ int (*func)(struct string from, struct string sender, struct string original_message, struct string respond_to, size_t argc, struct string *argv);
+ struct string privs;
+ struct string summary;
+ struct string aligned_name;
+ struct string name;
+};
+
+int haxserv_pseudoclient_init(void);
+
+int haxserv_pseudoclient_post_reload(void);
+int haxserv_pseudoclient_pre_reload(void);
+
+int haxserv_pseudoclient_allow_kill(struct string from, struct string source, struct user_info *user, struct string reason);
+int haxserv_pseudoclient_allow_kick(struct string from, struct string source, struct channel_info *channel, struct user_info *user, struct string reason);
+
+void haxserv_pseudoclient_handle_privmsg(struct string from, struct string source, struct string target, struct string msg);
+
+extern struct table haxserv_pseudoclient_commands;
+
+extern struct command_def haxserv_pseudoclient_help_command_def;
+extern struct command_def haxserv_pseudoclient_sus_command_def;
+extern struct command_def haxserv_pseudoclient_cr_command_def;
+extern struct command_def haxserv_pseudoclient_clear_command_def;
+#ifdef USE_INSPIRCD2_PROTOCOL
+extern struct command_def haxserv_pseudoclient_raw_inspircd2_command_def;
+#endif
+extern struct command_def haxserv_pseudoclient_kill_command_def;
+extern struct command_def haxserv_pseudoclient_spam_command_def;
+extern struct command_def haxserv_pseudoclient_reload_command_def;
+extern struct command_def haxserv_pseudoclient_allow_command_def;
+extern struct command_def haxserv_pseudoclient_deny_command_def;
+extern struct command_def haxserv_pseudoclient_reconnect_command_def;
+extern struct command_def haxserv_pseudoclient_sanick_command_def;
+extern struct command_def haxserv_pseudoclient_get_command_def;