From 7de39dee04b8492a7ab87dee55f0753a400e0e13 Mon Sep 17 00:00:00 2001 From: pk910 Date: Tue, 1 Jan 2013 18:57:01 +0100 Subject: [PATCH] added essential HostServ functions --- src/mod-hostserv.c | 748 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 748 insertions(+) create mode 100644 src/mod-hostserv.c diff --git a/src/mod-hostserv.c b/src/mod-hostserv.c new file mode 100644 index 0000000..6dd35d0 --- /dev/null +++ b/src/mod-hostserv.c @@ -0,0 +1,748 @@ +/* mod-watchdog.c - Watchdog module for srvx + * Copyright 2003-2004 Martijn Smit and srvx Development Team + * + * This file is part of srvx. + * + * srvx 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 2 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 srvx; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Adds new section to srvx.conf: + * "modules" { + * "hostserv" { + * "nick" "HostServ"; + * "modes" "+iok"; + "toplevel_access" "600"; + * }; + * }; + * + */ + +#include "chanserv.h" +#include "opserv.h" +#include "nickserv.h" +#include "conf.h" +#include "modcmd.h" +#include "saxdb.h" +#include "timeq.h" +#include "gline.h" + +#define KEY_TOPLEVEL "toplevel" +#define KEY_SECONDLEVEL "secondlevel" +#define KEY_MANAGERS "managers" +#define KEY_FAKEHOST "fakehost" +#define KEY_ASSIGNMENTS "assignments" + + + +static const struct message_entry msgtab[] = { + { "HSMSG_ASSIGNED_FAKEHOSTS", "Assigned Fakehosts for User $b%s$b:" }, + { "HSMSG_ASSIGNED_FAKEHOST", " $b%s.%s$b" }, + { "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE", " $b%s.%s$b (active)" }, + { "HSMSG_ASSIGN_HOWTO", "Use $bassign xxx.yyy$b to activate one of the listed fakehosts or $bassign *$b to use the default fakehost." }, + { "HSMSG_ASSIGNED_NONE", " None." }, + { "HSMSG_MANAGED_FAKEHOSTS", "Fakehosts managed by User $b%s$b:" }, + { "HSMSG_MANAGED_TOPLEVEL", " $b*.%s$b fakehosts: %d assignments: %d" }, + { "HSMSG_MANAGED_FAKEHOST", " $b%s.%s$b assignments: %d" }, + { "HSMSG_MANAGE_HOWTO", "Use $bview xxx.yyy$b to view more information about a fakehost group." }, + { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." }, + { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" }, + { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" }, + { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" }, + { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" }, + { "HSMSG_MANAGERS_MANAGERS", " %s" }, + { "HSMSG_FAKEHOST_ASSIGNMENTS", "Assignments in group $b%s.%s$b:" }, + { "HSMSG_FAKEHOST_ASSIGNMENT", " $b%s$b (%s.%s.%s)" }, + { "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE", " $b%s$b (%s.%s.%s) active" }, + { "HSMSG_MANAGER_ALREADY", "$b%s$b is already a manager of %s.%s" }, + { "HSMSG_MANAGER_ADDED", "$b%s$b is now a manager of %s.%s" }, + { "HSMSG_MANAGER_NOT", "$b%s$b is not a manager of %s.%s" }, + + { NULL, NULL } +}; + +static struct { + const char *nick; + const char *modes; + int toplevel_access; +} hostserv_conf; + +const char *hostserv_module_deps[] = { NULL }; +struct userNode *hostserv; +static struct module *hostserv_module; +static struct service *hostserv_service; +static struct log_type *MS_LOG; +static struct hs_toplevel *toplevels = NULL; +static struct hs_user *hostserv_users = NULL; + +/* FAKEHOST STRUCTS */ +struct hs_toplevel { + char *fakehost; + struct hs_manager *managers; + struct hs_secondlevel *secondlevel; + struct hs_toplevel *next; +}; + +struct hs_secondlevel { + struct hs_toplevel *toplevel; + char *fakehost; + struct hs_manager *managers; + struct hs_assignment *assignment; + struct hs_secondlevel *next; +}; + +struct hs_assignment { + struct hs_secondlevel *secondlevel; + struct hs_user *user; + int active; + struct hs_assignment *next; + struct hs_assignment *unext; /* for hs_user */ +}; + +struct hs_manager { + char type; + void *object; + struct hs_user *user; + struct hs_manager *next; + struct hs_manager *unext; /* for hs_user */ +}; + +struct hs_user { + struct handle_info *hi; + struct hs_assignment *assignments; + struct hs_manager *managements; + struct hs_user *next; +}; + +/* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */ +static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh); +static void hs_del_manager(struct hs_manager *manager, int remove_from_object); +static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh); +static void hs_del_user(struct hs_user *user); + +static void hs_free_all() { + struct hs_toplevel *tlfh, *next_tlfh; + struct hs_secondlevel *slfh, *next_slfh; + struct hs_assignment *assng, *next_assng; + struct hs_manager *manager, *next_manager; + struct hs_user *user, *next_user; + for(tlfh = toplevels; tlfh; tlfh = next_tlfh) { + next_tlfh = tlfh->next; + for(manager = tlfh->managers; manager; manager = next_manager) { + next_manager = manager->next; + free(manager); + } + for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) { + next_slfh = slfh->next; + for(manager = tlfh->managers; manager; manager = next_manager) { + next_manager = manager->next; + free(manager); + } + for(assng = slfh->assignments; assng; assng = next_assng) { + next_assng = assng->next; + free(assng); + } + free(slfh->fakehost); + free(slfh); + } + free(tlfh->fakehost); + free(tlfh); + } + for(user = hostserv_users; user; user = next_user) { + next_user = user->next; + free(user); + } + toplevels = NULL; + hostserv_users = NULL; +} + +static struct hs_toplevel *hs_add_toplevel(char *name) { + struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh)); + tlfh->fakehost = strdup(name); + tlfh->next = toplevels; + toplevels = tlfh; + return tlfh; +} + +static void hs_del_toplevel(struct hs_toplevel *tlfh) { + //unassign all assignments + struct hs_secondlevel *slfh, *next_slfh; + struct hs_manager *manager, *next_manager; + for(manager = tlfh->managers; manager; manager = next_manager) { + next_manager = manager->next; + hs_del_manager(manager, 0); + } + for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) { + next_slfh = slfh->next; + hs_del_secondlevel(slfh, 0); + } + free(tlfh->fakehost); + free(tlfh); +} + +static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, char *name) { + struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh)); + slfh->toplevel = tlfh; + slfh->fakehost = strdup(name); + slfh->next = tlfh->secondlevel; + tlfh->secondlevel = slfh; + return slfh; +} + +static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) { + if(remove_from_tlfh) { + struct hs_secondlevel *cslfh, *prev_slfh = NULL; + for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) { + if(cslfh == slfh) { + if(prev_slfh) + prev_slfh->next = slfh->next; + else + slfh->toplevel->secondlevel = slfh->next; + break; + } else + prev_slfh = cslfh; + } + } + struct hs_assignment *assng, *next_assng; + struct hs_manager *manager, *next_manager; + for(manager = slfh->managers; manager; manager = next_manager) { + next_manager = manager->next; + hs_del_manager(manager, 0); + } + for(assng = slfh->assignments; assng; assng = next_assng) { + next_assng = assng->next; + hs_del_assignment(assng, 0); + } + free(slfh->fakehost); + free(slfh); +} + +static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) { + struct hs_manager *manager = calloc(1, sizeof(*manager)); + manager->user = user; + manager->type = 1; + manager->object = tlfh; + manager->unext = user->managements; + user->managements = manager; + manager->next = tlfh->managers; + tlfh->managers = manager; + return manager; +} + +static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) { + struct hs_manager *manager = calloc(1, sizeof(*manager)); + manager->user = user; + manager->type = 2; + manager->object = slfh; + manager->unext = user->managements; + user->managements = manager; + manager->next = slfh->managers; + slfh->managers = manager; + return manager; +} + +static void hs_del_manager(struct hs_manager *manager, int remove_from_object) { + struct hs_manager *cmanager, *prev_manager = NULL; + if(remove_from_object) { + if(manager->type == 1) { + struct hs_toplevel *tlfh = manager->object; + for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) { + if(cmanager = manager) { + if(prev_manager) + prev_manager->next = manager->next; + else + tlfh->managers = manager->next; + break; + } else + prev_manager = cmanager; + } + } else if(manager->type == 2) { + struct hs_secondlevel *slfh = manager->object; + for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) { + if(cmanager = manager) { + if(prev_manager) + prev_manager->next = manager->next; + else + slfh->managers = manager->next; + break; + } else + prev_manager = cmanager; + } + } + prev_manager = NULL; + } + if(remove_from_object != 2) { + for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) { + if(cmanager == manager) { + if(prev_manager) + prev_manager->unext = manager->unext; + else + manager->user->managements = manager->unext; + break; + } else + prev_manager = cmanager; + } + if(manager->user->managements == NULL && manager->user->assignments == NULL) + hs_del_user(manager->user); + } + free(manager); +} + +static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user) { + struct hs_assignment *assignment = calloc(1, sizeof(*assignment)); + assignment->secondlevel = slfh; + assignment->user = user; + if(user->assignments == NULL) + assignment->active = 1; + assignment->next = slfh->assignments; + slfh->assignments = assignment; + assignment->unext = user->assignments; + user->assignments = assignment; + if(assignment->active) { + /* use this assignment */ + } + return assignment; +} + +static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) { + struct hs_assignment *cassignment, *prev_assignment = NULL; + if(remove_from_slfh) { + for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) { + if(cassignment == assignment) { + if(prev_assignment) + prev_assignment->next = assignment->next; + else + assignment->secondlevel->assignments = assignment->next; + break; + } else + prev_assignment = cassignment; + } + prev_assignment = NULL; + } + if(remove_from_slfh != 2) { + for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) { + if(cassignment == assignment) { + if(prev_assignment) + prev_assignment->unext = assignment->unext; + else + assignment->user->assignments = assignment->unext; + break; + } else + prev_assignment = cassignment; + } + if(assignment->user->managements == NULL && assignment->user->assignments == NULL) + hs_del_user(assignment->user); + if(assignment->active) { + /* use other assignment */ + } + } + free(assignment); +} + +static struct hs_user *hs_get_user(struct handle_info *hi, int create) { + struct hs_user *cuser; + for(cuser = hostserv_users; cuser; cuser = cuser->next) { + if(cuser->hi == hi) + return cuser; + } + if(create) { + cuser = calloc(1, sizeof(*cuser)); + cuser->hi = hi; + cuser->next = hostserv_users; + hostserv_users = cuser; + return cuser; + } else + return NULL; +} + +static void hs_del_user(struct hs_user *user) { + if(user->managements) { + struct hs_manager *manager, *next_manager; + for(manager = user->managements; manager; manager = next_manager) { + next_manager = manager->unext; + hs_del_manager(manager, 2); + } + } + if(user->assignments) { + struct hs_assignment *assng, *next_assng; + for(assng = user->assignments; assng; assng = next_assng) { + next_assng = assng->unext; + hs_del_assignment(assng, 2); + } + } + struct hs_user *cuser, *prev_user = NULL; + for(cuser = hostserv_users; cuser; cuser = cuser->next) { + if(cuser == user) { + if(prev_user) + prev_user->next = user->next; + else + hostserv_users = user->next; + break; + } else + prev_user = cuser; + } + free(user); +} + +/* END OF MANAGEMENT FUNCTIONS */ + +static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_toplevel *slfh) { + if(!hi) + return 0; + if(hi->opserv_level >= hostserv_conf.toplevel_access) + return 1; + struct hs_user *user = hs_get_user(hi, 0); + if(!user) + return 0; + struct hs_manager *manager; + if(slfh) { + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 2 && manager->object == slfh) + return 1; + } + } + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 1 && manager->object == tlfh) + return 1; + } + return 0; +} + + +static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) { + reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost); + struct hs_secondlevel *slfh; + if(!tlfh->secondlevel) + reply("HSMSG_ASSIGNED_NONE"); + else + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + struct hs_manager *cmanager; + int managers = 0; + for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) + managers++; + struct hs_assignment *assignment; + int assignments = 0; + for(assignment = slfh->assignment; assignment; assignment = assignment->next) + assignments++; + reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers); + } + reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost); + struct hs_manager *cmanager; + if(!tlfh->managers) + reply("HSMSG_ASSIGNED_NONE"); + else { + char managerBuf[351]; + int managerPos = 0; + for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) { + if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) { + reply("HSMSG_MANAGERS_MANAGERS", managerBuf); + managerPos = 0; + } + managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle); + } + reply("HSMSG_MANAGERS_MANAGERS", managerBuf); + } +} + +static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) { + reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost); + struct hs_assignment *assignment; + for(assignment = slfh->assignment; assignment; assignment = assignment->next) { + reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost); + } + reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost); + struct hs_manager *cmanager; + if(!tlfh->managers) + reply("HSMSG_ASSIGNED_NONE"); + else { + char managerBuf[351]; + int managerPos = 0; + for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) { + if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) { + reply("HSMSG_MANAGERS_MANAGERS", managerBuf); + managerPos = 0; + } + managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle); + } + reply("HSMSG_MANAGERS_MANAGERS", managerBuf); + } +} + + +static MODCMD_FUNC(cmd_view) { + struct handle_info *hi; + if(argc >= 2 && !strchr(argv[1], '.')) { + if (!(hi = modcmd_get_handle_info(user, argv[1]))) + return 0 + } else if(argc >= 2) { + if (!(hi = user->handle_info)) { + reply("NSMSG_MUST_AUTH"); + return 0; + } + char *slfh_name = argv[1]; + char *tlfh_name = strchr(argv[1], '.'); + *tlfh_name = '\0'; + tlfh_name++; + if(strchr(tlfh_name, '.')) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + struct hs_toplevel *tlfh; + for(tlfh = toplevels; tlfh; tlfh = tlfh->next) { + if(!irccasecmp(tlfh->fakehost, tlfh_name)) break; + } + if(!tlfh) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + if(!irccasecmp(slfh_name, "*")) { + if(!check_management_access(hi, tlfh, NULL)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + cmd_view_toplevel_information(user, cmd, tlfh); + return 1; + } else { + struct hs_secondlevel *slfh; + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + if(!irccasecmp(slfh->fakehost, slfh_name)) break; + } + if(!slfh || !check_management_access(hi, tlfh, slfh)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + cmd_view_secondlevel_information(user, cmd, slfh); + return 1; + } + } else { + if (!(hi = user->handle_info)) { + reply("NSMSG_MUST_AUTH"); + return 0; + } + } + struct hs_user *huser = hs_get_user(hi, 0); + reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle); + int assigncount = 0; + if(huser) { + struct hs_assignment *assignment; + for(assignment = huser->assignments; assignment; assignment = assignment->unext) { + reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost); + assigncount++; + } + if(assigncount && huser->hi == user->handle_info) + reply("HSMSG_ASSIGN_HOWTO"); + } + if(!assigncount) + reply("HSMSG_ASSIGNED_NONE"); + if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) { + struct hs_toplevel *tlfh; + for(tlfh = toplevels; tlfh; tlfh = tlfh->next) { + struct hs_secondlevel *slfh; + struct hs_assignment *assignment; + int slfhs = 0, assignments = 0; + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + slfhs++; + for(assignment = slfh->assignment; assignment; assignment = assignment->next) + assignments++; + } + reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments); + } + reply("HSMSG_MANAGE_HOWTO"); + } else if(huser && huser->managements) { + reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle); + struct hs_manager *manager; + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 1) { + struct hs_toplevel *tlfh = manager->object; + struct hs_secondlevel *slfh; + struct hs_assignment *assignment; + int slfhs = 0, assignments = 0; + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + slfhs++; + for(assignment = slfh->assignment; assignment; assignment = assignment->next) + assignments++; + } + reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments); + } + } + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 2) { + struct hs_secondlevel *slfh = manager->object; + struct hs_toplevel *tlfh = slfh->toplevel; + //check if the user is already a manager of the tlfh + struct hs_manager *cmanager; + for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) { + if(cmanager->user == huser) break; + } + if(cmanager) continue; + struct hs_assignment *assignment; + int assignments = 0; + for(assignment = slfh->assignment; assignment; assignment = assignment->next) + assignments++; + reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments); + } + } + if(huser->hi == user->handle_info) + reply("HSMSG_MANAGE_HOWTO"); + } + return 1; +} + +static MODCMD_FUNC(cmd_addmanager) { + struct handle_info *hi; + char *fakehost; + if(!strchr(argv[1], '.')) { + if (!(hi = modcmd_get_handle_info(user, argv[1]))) + return 0 + fakehost = argv[2]; + } else { + if (!(hi = modcmd_get_handle_info(user, argv[2]))) + return 0 + fakehost = argv[1]; + } + char *slfh_name = fakehost; + char *tlfh_name = strchr(fakehost, '.'); + *tlfh_name = '\0'; + tlfh_name++; + if(strchr(tlfh_name, '.')) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + struct hs_toplevel *tlfh; + struct hs_secondlevel *slfh = NULL; + for(tlfh = toplevels; tlfh; tlfh = tlfh->next) { + if(!irccasecmp(tlfh->fakehost, tlfh_name)) break; + } + if(!tlfh) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + if(!irccasecmp(slfh_name, "*")) { + if(!check_management_access(user->handle_info, tlfh, NULL)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + } else { + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + if(!irccasecmp(slfh->fakehost, slfh_name)) break; + } + if(!slfh || !check_management_access(user->handle_info, tlfh, slfh)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + } + struct hs_user *huser = hs_get_user(hi, 1); + struct hs_manager *manager; + if(slfh) { + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 2 && manager->object == slfh) { + reply("HSMSG_MANAGER_ALREADY", hi->handle, slfh_name, tlfh_name); + return 0; + } + } + } + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 1 && manager->object == tlfh) { + reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", tlfh_name); + return 0; + } + } + if(slfh) + hs_add_manager_secondlevel(slfh, huser); + else + hs_add_manager_toplevel(tlfh, huser); + reply("HSMSG_MANAGER_ADDED", hi->handle, slfh_name, tlfh_name); +} + +static MODCMD_FUNC(cmd_delmanager) { + struct handle_info *hi; + char *fakehost; + if(!strchr(argv[1], '.')) { + if (!(hi = modcmd_get_handle_info(user, argv[1]))) + return 0 + fakehost = argv[2]; + } else { + if (!(hi = modcmd_get_handle_info(user, argv[2]))) + return 0 + fakehost = argv[1]; + } + char *slfh_name = fakehost; + char *tlfh_name = strchr(fakehost, '.'); + *tlfh_name = '\0'; + tlfh_name++; + if(strchr(tlfh_name, '.')) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + struct hs_toplevel *tlfh; + struct hs_secondlevel *slfh = NULL; + for(tlfh = toplevels; tlfh; tlfh = tlfh->next) { + if(!irccasecmp(tlfh->fakehost, tlfh_name)) break; + } + if(!tlfh) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + if(!irccasecmp(slfh_name, "*")) { + if(!check_management_access(user->handle_info, tlfh, NULL)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + } else { + for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) { + if(!irccasecmp(slfh->fakehost, slfh_name)) break; + } + if(!slfh || !check_management_access(user->handle_info, tlfh, slfh)) { + reply("HSMSG_UNKNOWN_FAKEHOST", slfh_name, tlfh_name); + return 0; + } + } + struct hs_user *huser = hs_get_user(hi, 0); + struct hs_manager *manager; + if(!huser) { + reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name); + return 0; + } + if(slfh) { + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 2 && manager->object == slfh) + break; + } + if(!manager) { + reply("HSMSG_MANAGER_NOT", hi->handle, slfh_name, tlfh_name); + return 0; + } + } else { + for(manager = huser->managements; manager; manager = manager->next) { + if(manager->type == 1 && manager->object == tlfh) + break; + } + if(!manager) { + reply("HSMSG_MANAGER_NOT", hi->handle, "*", tlfh_name); + return 0; + } + } + hs_del_manager(manager, 1); + reply("HSMSG_MANAGER_DELETED", hi->handle, slfh_name, tlfh_name); +} + + + + + + + +/* to be continued - some day in the future - maybe? */ + + -- 2.20.1