1 /* mod-hostserv.c - HostServ module for srvx
2 * Copyright 2012-2013 pk910, Stricted, NurPech
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 /* Adds new section to srvx.conf:
26 * "toplevel_access" "600";
27 * "fallback_other_assignment" "1"; //fall back to another assignment when active assignment gets removed
28 * "manager_can_rename_toplevel" "0"; //managers of a toplevel group may rename the whole group
29 * "manager_can_del_toplevel" "0"; //managers of a toplevel group may delete the whole group
30 * "manager_can_rename_secondlevel" "0"; //managers of a secondlevel group may rename the whole group
31 * "manager_can_del_secondlevel" "0"; //managers of a secondlevel group may delete the whole group
32 * "manager_toplevel_can_oset" "0"; //managers of a toplevel group can set other user's fakehosts
33 * "manager_secondlevel_can_oset" "0"; //managers of a secondlevel group can set other user's fakehosts
37 * After you started srvx make the bot active:
38 /msg opserv bind hostserv * hostserv.*
39 /msg opserv bind hostserv help *modcmd.help
50 #define KEY_TOPLEVEL "TopLevel"
51 #define KEY_SECONDLEVEL "SecondLevel"
52 #define KEY_MANAGERS "Manager"
53 #define KEY_ASSIGNMENTS "Assignments"
54 #define KEY_ACTIVE "active"
56 #define HS_FAKEHOST_SPECIAL_CHARS "_-:;" /* alphanum already included */
58 #define HS_ASSIGNMENTSTATE_AUTO -1
59 #define HS_ASSIGNMENTSTATE_OFF 0
60 #define HS_ASSIGNMENTSTATE_ON 1
62 #define HS_FHPARSE_SUCCESS 0
63 #define HS_FHPARSE_INVALID 1
64 #define HS_FHPARSE_UNKNOWN 2
66 static const struct message_entry msgtab[] = {
67 { "HSMSG_ACCESS_DENIED", "Access denied." },
68 { "HSMSG_ASSIGNED_FAKEHOSTS", "Assigned Fakehosts for User $b%s$b:" },
69 { "HSMSG_ASSIGNED_FAKEHOST", " $b%s.%s$b" },
70 { "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE", " $b%s.%s$b (active)" },
71 { "HSMSG_ASSIGNED_FAKEHOST_NOT_ACTIVE", "Fakehost $b%s.%s.$b is not active." },
72 { "HSMSG_ASSIGN_HOWTO", "Use $bset xxx.yyy$b to activate one of the listed fakehosts or $bset *$b to use the default fakehost." },
73 { "HSMSG_ASSIGNED_NONE", " None." },
74 { "HSMSG_MANAGED_FAKEHOSTS", "Fakehosts managed by User $b%s$b:" },
75 { "HSMSG_MANAGED_TOPLEVEL", " $b*.%s$b fakehosts: %d assignments: %d" },
76 { "HSMSG_MANAGED_TOPLEVEL_OWN", " $b*.%s$b fakehosts: %d assignments: %d (active)" },
77 { "HSMSG_MANAGED_FAKEHOST", " $b%s.%s$b assignments: %d" },
78 { "HSMSG_MANAGE_HOWTO", "Use $bview xxx.yyy$b to view more information about a fakehost group." },
79 { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." },
80 { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" },
81 { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" },
82 { "HSMSG_TOPLEVEL_INVALID", "The name of the group you entered is invalid ($b%s$b)" },
83 { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" },
84 { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" },
85 { "HSMSG_MANAGERS_MANAGERS", " %s" },
86 { "HSMSG_FAKEHOST_ASSIGNMENTS", "Assignments in group $b%s.%s$b:" },
87 { "HSMSG_FAKEHOST_ASSIGNMENT", " $b%s$b (%s.%s.%s)" },
88 { "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE", " $b%s$b (%s.%s.%s) active" },
89 { "HSMSG_FAKEHOST_SET_SUCCESS", "$b%s.%s$b where set successfully." },
90 { "HSMSG_FAKEHOST_TOPLEVEL_ADDED", "Group $b%s$b successfully added." },
91 { "HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", "Group $b%s$b already exists." },
92 { "HSMSG_FAKEHOST_TOPLEVEL_DELETED", "Group $b%s$b successfully deleted." },
93 { "HSMSG_FAKEHOST_SECONDLEVEL_ADDED", "Group $b%s.%s$b successfully added." },
94 { "HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", "Group $b%s.%s$b already exists." },
95 { "HSMSG_FAKEHOST_SECONDLEVEL_DELETED", "Group $b%s.%s$b successfully deleted." },
96 { "HSMSG_FAKEHOST_RENAMED", "Group $b%s.%s$b renamed to $b%s.%s$b." },
97 { "HSMSG_MANAGER_ALREADY", "$b%s$b is already a manager of %s.%s" },
98 { "HSMSG_MANAGER_ADDED", "$b%s$b is now a manager of %s.%s" },
99 { "HSMSG_MANAGER_NOT", "$b%s$b is not a manager of %s.%s" },
100 { "HSMSG_MANAGER_DELETED", "$b%s$b is no longer a manager of %s.%s" },
101 { "HSMSG_FAKEHOST_ASSIGN_SUCCESS", "Group $b%s.%s$b was assigned successfully." },
102 { "HSMSG_FAKEHOST_ASSIGNED", "Group $b%s.%s$b is already assigned to the user." },
103 { "HSMSG_FAKEHOST_UNASSIGN_SUCCESS", "Group $b%s.%s$b was unassigned successfully." },
112 int fallback_other_assignment : 1;
113 int manager_can_del_toplevel : 1;
114 int manager_can_del_secondlevel : 1;
115 int manager_can_rename_toplevel : 1;
116 int manager_can_rename_secondlevel : 1;
117 int manager_toplevel_can_oset : 1;
118 int manager_secondlevel_can_oset : 1;
121 const char *hostserv_module_deps[] = { NULL };
122 struct userNode *hostserv;
123 struct helpfile *hostserv_helpfile;
124 static struct module *hostserv_module;
125 static struct service *hostserv_service;
126 static struct log_type *HS_LOG;
127 static struct hs_toplevel *toplevels = NULL;
128 static struct hs_user *hostserv_users = NULL;
130 /* FAKEHOST STRUCTS */
133 struct hs_manager *managers;
134 struct hs_secondlevel *secondlevel;
135 struct hs_toplevel *next;
138 struct hs_secondlevel {
139 struct hs_toplevel *toplevel;
141 struct hs_manager *managers;
142 struct hs_assignment *assignments;
143 struct hs_secondlevel *next;
146 struct hs_assignment {
147 struct hs_secondlevel *secondlevel;
148 struct hs_user *user;
150 struct hs_assignment *next;
151 struct hs_assignment *unext; /* for hs_user */
158 struct hs_user *user;
159 struct hs_manager *next;
160 struct hs_manager *unext; /* for hs_user */
164 struct handle_info *hi;
165 struct hs_assignment *assignments;
166 struct hs_manager *managements;
167 struct hs_user *next;
170 /* temporary structs */
171 struct hs_fakehost_info {
172 unsigned int parse_state : 4;
173 unsigned int have_secondlevel : 1;
176 struct hs_toplevel *tlfh;
177 struct hs_secondlevel *slfh;
180 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
181 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
182 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
183 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
184 static void hs_del_user(struct hs_user *user);
185 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment);
187 static void hs_free_all() {
188 struct hs_toplevel *tlfh, *next_tlfh;
189 struct hs_secondlevel *slfh, *next_slfh;
190 struct hs_assignment *assng, *next_assng;
191 struct hs_manager *manager, *next_manager;
192 struct hs_user *user, *next_user;
193 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
194 next_tlfh = tlfh->next;
195 for(manager = tlfh->managers; manager; manager = next_manager) {
196 next_manager = manager->next;
199 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
200 next_slfh = slfh->next;
201 for(manager = slfh->managers; manager; manager = next_manager) {
202 next_manager = manager->next;
205 for(assng = slfh->assignments; assng; assng = next_assng) {
206 next_assng = assng->next;
209 free(slfh->fakehost);
212 free(tlfh->fakehost);
215 for(user = hostserv_users; user; user = next_user) {
216 next_user = user->next;
220 hostserv_users = NULL;
223 static struct hs_toplevel *hs_add_toplevel(const char *name) {
224 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
225 tlfh->fakehost = strdup(name);
226 tlfh->next = toplevels;
231 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
232 //unassign all assignments
233 struct hs_secondlevel *slfh, *next_slfh;
234 struct hs_manager *manager, *next_manager;
235 for(manager = tlfh->managers; manager; manager = next_manager) {
236 next_manager = manager->next;
237 hs_del_manager(manager, 0);
239 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
240 next_slfh = slfh->next;
241 hs_del_secondlevel(slfh, 0);
244 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
245 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
248 last_tlfh->next = ctlfh->next;
250 toplevels = ctlfh->next;
254 free(tlfh->fakehost);
258 static void hs_rename_toplevel(struct hs_toplevel *tlfh, const char *name) {
259 struct hs_secondlevel *slfh;
260 struct hs_assignment *assng;
262 free(tlfh->fakehost);
263 tlfh->fakehost = strdup(name);
265 //trigger rename for all assignments
266 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
267 for(assng = slfh->assignments; assng; assng = assng->next) {
269 hs_activate_assignment(assng->user, assng);
275 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
276 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
277 slfh->toplevel = tlfh;
278 slfh->fakehost = strdup(name);
279 slfh->next = tlfh->secondlevel;
280 tlfh->secondlevel = slfh;
284 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
285 if(remove_from_tlfh) {
286 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
287 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
290 prev_slfh->next = slfh->next;
292 slfh->toplevel->secondlevel = slfh->next;
298 struct hs_assignment *assng, *next_assng;
299 struct hs_manager *manager, *next_manager;
300 for(manager = slfh->managers; manager; manager = next_manager) {
301 next_manager = manager->next;
302 hs_del_manager(manager, 0);
304 for(assng = slfh->assignments; assng; assng = next_assng) {
305 next_assng = assng->next;
306 hs_del_assignment(assng, 0);
308 free(slfh->fakehost);
312 static void hs_rename_secondlevel(struct hs_secondlevel *slfh, const char *name) {
313 struct hs_assignment *assng;
315 free(slfh->fakehost);
316 slfh->fakehost = strdup(name);
318 //trigger rename for all assignments
319 for(assng = slfh->assignments; assng; assng = assng->next) {
321 hs_activate_assignment(assng->user, assng);
326 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
327 struct hs_manager *manager = calloc(1, sizeof(*manager));
328 manager->user = user;
330 manager->object = tlfh;
331 manager->unext = user->managements;
332 user->managements = manager;
333 manager->next = tlfh->managers;
334 tlfh->managers = manager;
338 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
339 struct hs_manager *manager = calloc(1, sizeof(*manager));
340 manager->user = user;
342 manager->object = slfh;
343 manager->unext = user->managements;
344 user->managements = manager;
345 manager->next = slfh->managers;
346 slfh->managers = manager;
350 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
351 struct hs_manager *cmanager, *prev_manager = NULL;
352 if(remove_from_object) {
353 if(manager->type == 1) {
354 struct hs_toplevel *tlfh = manager->object;
355 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
356 if(cmanager == manager) {
358 prev_manager->next = manager->next;
360 tlfh->managers = manager->next;
363 prev_manager = cmanager;
365 } else if(manager->type == 2) {
366 struct hs_secondlevel *slfh = manager->object;
367 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
368 if(cmanager == manager) {
370 prev_manager->next = manager->next;
372 slfh->managers = manager->next;
375 prev_manager = cmanager;
380 if(remove_from_object != 2) {
381 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
382 if(cmanager == manager) {
384 prev_manager->unext = manager->unext;
386 manager->user->managements = manager->unext;
389 prev_manager = cmanager;
391 if(manager->user->managements == NULL && manager->user->assignments == NULL)
392 hs_del_user(manager->user);
397 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment) {
398 struct hs_toplevel *tlfh;
399 struct hs_secondlevel *slfh;
400 struct hs_assignment *assgn;
401 char fakehost[HOSTLEN];
403 assert((!assignment || (assignment->user == user)));
405 if(user->assignments) {
406 for(assgn = user->assignments; assgn; assgn = assgn->unext)
410 if(user->hi->fakehost) {
411 free(user->hi->fakehost);
412 user->hi->fakehost = NULL;
416 slfh = assignment->secondlevel;
417 tlfh = slfh->toplevel;
418 snprintf(fakehost, sizeof(fakehost), "$.%s.%s", slfh->fakehost, tlfh->fakehost);
419 user->hi->fakehost = strdup(fakehost);
420 assignment->active = 1;
423 apply_fakehost(user->hi, NULL);
426 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user, int active) {
427 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
428 assignment->secondlevel = slfh;
429 assignment->user = user;
430 if(active == HS_ASSIGNMENTSTATE_AUTO)
431 assignment->active = (user->assignments == NULL ? 1 : 0);
433 assignment->active = (active == HS_ASSIGNMENTSTATE_ON ? 1 : 0);
434 assignment->next = slfh->assignments;
435 slfh->assignments = assignment;
436 assignment->unext = user->assignments;
437 user->assignments = assignment;
438 if(assignment->active) {
439 hs_activate_assignment(user, assignment);
444 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
445 struct hs_assignment *cassignment, *prev_assignment = NULL;
446 if(remove_from_slfh) {
447 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
448 if(cassignment == assignment) {
450 prev_assignment->next = assignment->next;
452 assignment->secondlevel->assignments = assignment->next;
455 prev_assignment = cassignment;
457 prev_assignment = NULL;
459 if(remove_from_slfh != 2) {
460 prev_assignment = NULL;
461 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
462 if(cassignment == assignment) {
464 prev_assignment->unext = assignment->unext;
466 assignment->user->assignments = assignment->unext;
469 prev_assignment = cassignment;
472 if(assignment->active) {
473 /* use another assignment - or fall back to default user host? */
475 if(hostserv_conf.fallback_other_assignment && assignment->user->assignments) {
476 /* try to find another assignment from same slfh first */
477 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
478 if(cassignment != assignment && cassignment->user == assignment->user)
481 /* use another tlfh assignment */
483 cassignment = assignment->user->assignments;
485 hs_activate_assignment(assignment->user, cassignment);
488 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
489 hs_del_user(assignment->user);
494 static struct hs_assignment *hs_get_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
495 struct hs_assignment *cassignment;
496 for(cassignment = slfh->assignments; cassignment; cassignment = cassignment->next) {
497 if(cassignment->user == user)
503 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
504 struct hs_user *cuser;
505 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
510 cuser = calloc(1, sizeof(*cuser));
512 cuser->next = hostserv_users;
513 hostserv_users = cuser;
519 static void hs_del_user(struct hs_user *user) {
520 if(user->managements) {
521 struct hs_manager *manager, *next_manager;
522 for(manager = user->managements; manager; manager = next_manager) {
523 next_manager = manager->unext;
524 hs_del_manager(manager, 2);
527 if(user->assignments) {
528 struct hs_assignment *assng, *next_assng;
529 for(assng = user->assignments; assng; assng = next_assng) {
530 next_assng = assng->unext;
531 hs_del_assignment(assng, 2);
534 struct hs_user *cuser, *prev_user = NULL;
535 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
538 prev_user->next = user->next;
540 hostserv_users = user->next;
548 /* END OF MANAGEMENT FUNCTIONS */
550 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
553 if(hi->opserv_level >= hostserv_conf.toplevel_access)
555 struct hs_user *user = hs_get_user(hi, 0);
558 struct hs_manager *manager;
560 for(manager = user->managements; manager; manager = manager->next) {
561 if(manager->type == 2 && manager->object == slfh)
566 for(manager = user->managements; manager; manager = manager->next) {
567 if(manager->type == 1 && manager->object == tlfh)
574 struct hs_fakehost_info parse_fakehost_info(char *fakehost, int fix_name_case) {
575 struct hs_fakehost_info fhinfo;
577 memset(&fhinfo, 0, sizeof(fhinfo));
578 for(i = strlen(fakehost)-1; i >= 0; i--) {
579 if(!isalnum(fakehost[i]) && fakehost[i] != '.' && !(fakehost[i] == '*' && i == 0) && !strchr(HS_FAKEHOST_SPECIAL_CHARS, fakehost[i])) {
580 fhinfo.parse_state = HS_FHPARSE_INVALID;
584 fhinfo.slfh_name = fakehost;
585 fhinfo.tlfh_name = strchr(fakehost, '.');
586 if(!fhinfo.tlfh_name) {
587 fhinfo.parse_state = HS_FHPARSE_INVALID;
590 fhinfo.tlfh_name[0] = '\0';
592 if(strchr(fhinfo.tlfh_name, '.')) {
593 fhinfo.parse_state = HS_FHPARSE_INVALID;
595 fhinfo.tlfh_name[0] = '\0';
598 if(irccasecmp(fhinfo.slfh_name, "*"))
599 fhinfo.have_secondlevel = 1;
600 struct hs_toplevel *tlfh;
601 struct hs_secondlevel *slfh;
602 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
603 if(!irccasecmp(tlfh->fakehost, fhinfo.tlfh_name)) break;
608 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
611 if(fhinfo.have_secondlevel) {
612 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
613 if(!irccasecmp(slfh->fakehost, fhinfo.slfh_name)) break;
617 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
623 //simply copy the stored fakehosts over the given ones
624 strcpy(fhinfo.tlfh_name, fhinfo.tlfh->fakehost);
626 strcpy(fhinfo.slfh_name, fhinfo.slfh->fakehost);
628 fhinfo.parse_state = HS_FHPARSE_SUCCESS;
634 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
635 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
636 struct hs_secondlevel *slfh;
637 if(!tlfh->secondlevel)
638 reply("HSMSG_ASSIGNED_NONE");
640 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
641 struct hs_manager *cmanager;
643 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
645 struct hs_assignment *assignment;
647 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
649 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
651 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
652 struct hs_manager *cmanager;
654 reply("HSMSG_ASSIGNED_NONE");
656 char managerBuf[351];
658 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
659 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
660 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
663 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
665 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
669 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
670 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
671 struct hs_assignment *assignment;
672 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
673 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
675 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
676 struct hs_manager *cmanager;
678 reply("HSMSG_ASSIGNED_NONE");
680 char managerBuf[351];
682 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
683 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
684 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
687 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
689 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
693 static MODCMD_FUNC(cmd_view) {
694 struct handle_info *hi;
695 if(argc >= 2 && !strchr(argv[1], '.')) {
696 if (!(hi = modcmd_get_handle_info(user, argv[1])))
698 } else if(argc >= 2) {
699 if (!(hi = user->handle_info)) {
700 reply("NSMSG_MUST_AUTH");
703 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 0);
704 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
705 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
707 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
708 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
712 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
713 reply("HSMSG_ACCESS_DENIED");
716 cmd_view_toplevel_information(user, cmd, fhinfo.tlfh);
719 if(!check_management_access(hi, fhinfo.tlfh, fhinfo.slfh)) {
720 reply("HSMSG_ACCESS_DENIED");
723 cmd_view_secondlevel_information(user, cmd, fhinfo.slfh);
727 if (!(hi = user->handle_info)) {
728 reply("NSMSG_MUST_AUTH");
732 struct hs_user *huser = hs_get_user(hi, 0);
733 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
736 struct hs_assignment *assignment;
737 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
738 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
741 if(assigncount && huser->hi == user->handle_info)
742 reply("HSMSG_ASSIGN_HOWTO");
745 reply("HSMSG_ASSIGNED_NONE");
746 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
747 struct hs_toplevel *tlfh;
748 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
749 struct hs_secondlevel *slfh;
750 struct hs_assignment *assignment;
751 int slfhs = 0, assignments = 0;
752 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
754 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
757 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
759 reply("HSMSG_MANAGE_HOWTO");
760 } else if(huser && huser->managements) {
761 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
762 struct hs_manager *manager;
763 for(manager = huser->managements; manager; manager = manager->unext) {
764 if(manager->type == 1) {
765 struct hs_toplevel *tlfh = manager->object;
766 struct hs_secondlevel *slfh;
767 struct hs_assignment *assignment;
768 int slfhs = 0, assignments = 0;
769 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
771 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
774 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
777 for(manager = huser->managements; manager; manager = manager->unext) {
778 if(manager->type == 2) {
779 struct hs_secondlevel *slfh = manager->object;
780 struct hs_toplevel *tlfh = slfh->toplevel;
781 //check if the user is already a manager of the tlfh
782 struct hs_manager *cmanager;
783 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->unext) {
784 if(cmanager->user == huser) break;
786 if(cmanager) continue;
787 struct hs_assignment *assignment;
789 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
791 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
794 if(huser->hi == user->handle_info)
795 reply("HSMSG_MANAGE_HOWTO");
800 static MODCMD_FUNC(cmd_addhost) {
801 struct handle_info *hi;
802 if (!(hi = user->handle_info)) {
803 reply("NSMSG_MUST_AUTH");
806 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
807 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
808 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
811 if(!fhinfo.have_secondlevel) {
812 if(!check_management_access(hi, NULL, NULL)) {
813 reply("HSMSG_ACCESS_DENIED");
816 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
817 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
820 hs_add_toplevel(fhinfo.tlfh_name);
821 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", fhinfo.tlfh_name);
824 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
827 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
828 reply("HSMSG_ACCESS_DENIED");
831 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
832 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
835 hs_add_secondlevel(fhinfo.tlfh, fhinfo.slfh_name);
836 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", fhinfo.slfh_name, fhinfo.tlfh_name);
841 static MODCMD_FUNC(cmd_delhost) {
842 struct handle_info *hi;
843 if (!(hi = user->handle_info)) {
844 reply("NSMSG_MUST_AUTH");
847 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
848 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
849 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
851 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
852 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
856 if(!check_management_access(hi, (hostserv_conf.manager_can_del_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
857 reply("HSMSG_ACCESS_DENIED");
860 hs_del_toplevel(fhinfo.tlfh);
861 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", fhinfo.tlfh_name);
863 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_del_secondlevel ? fhinfo.slfh : NULL))) {
864 reply("HSMSG_ACCESS_DENIED");
867 hs_del_secondlevel(fhinfo.slfh, 1);
868 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", fhinfo.slfh_name, fhinfo.tlfh_name);
873 static MODCMD_FUNC(cmd_renamehost) {
874 struct handle_info *hi;
875 if (!(hi = user->handle_info)) {
876 reply("NSMSG_MUST_AUTH");
880 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
881 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
882 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
884 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
885 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
889 struct hs_fakehost_info new_fhinfo = parse_fakehost_info(argv[2], 0);
890 if(new_fhinfo.parse_state == HS_FHPARSE_INVALID) {
891 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
893 } else if(new_fhinfo.parse_state != HS_FHPARSE_UNKNOWN && (irccasecmp(fhinfo.tlfh_name, new_fhinfo.tlfh_name) || (new_fhinfo.slfh && irccasecmp(fhinfo.slfh_name, new_fhinfo.slfh_name)))) {
894 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
899 if(!check_management_access(hi, (hostserv_conf.manager_can_rename_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
900 reply("HSMSG_ACCESS_DENIED");
903 if(fhinfo.have_secondlevel) {
904 //can't rename toplevel into secondlevel fakehost!
905 new_fhinfo.tlfh_name--;
906 new_fhinfo.tlfh_name[0] = '.';
907 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
910 if(strcmp(new_fhinfo.tlfh_name, fhinfo.tlfh->fakehost))
911 hs_rename_toplevel(fhinfo.tlfh, new_fhinfo.tlfh_name);
912 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
914 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_rename_secondlevel ? fhinfo.slfh : NULL))) {
915 reply("HSMSG_ACCESS_DENIED");
918 if(irccasecmp(new_fhinfo.tlfh_name, fhinfo.tlfh_name)) {
919 //can't rename toplevel and secondlevel fakehost with one command!
920 new_fhinfo.tlfh_name--;
921 new_fhinfo.tlfh_name[0] = '.';
922 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
925 if(strcmp(new_fhinfo.slfh_name, fhinfo.slfh->fakehost))
926 hs_rename_secondlevel(fhinfo.slfh, new_fhinfo.slfh_name);
927 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
932 static MODCMD_FUNC(cmd_addmanager) {
933 struct handle_info *hi;
935 if(!strchr(argv[1], '.')) {
936 if (!(hi = modcmd_get_handle_info(user, argv[1])))
940 if (!(hi = modcmd_get_handle_info(user, argv[2])))
944 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
945 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
946 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
948 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
949 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
952 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
953 reply("HSMSG_ACCESS_DENIED");
956 struct hs_user *huser = hs_get_user(hi, 1);
957 struct hs_manager *manager;
959 for(manager = huser->managements; manager; manager = manager->next) {
960 if(manager->type == 2 && manager->object == fhinfo.slfh) {
961 reply("HSMSG_MANAGER_ALREADY", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
966 for(manager = huser->managements; manager; manager = manager->next) {
967 if(manager->type == 1 && manager->object == fhinfo.tlfh) {
968 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", fhinfo.tlfh_name);
973 hs_add_manager_secondlevel(fhinfo.slfh, huser);
975 hs_add_manager_toplevel(fhinfo.tlfh, huser);
976 //remove from all slfh's
977 struct hs_manager *next_manager;
978 struct hs_secondlevel *slfh;
979 for(manager = huser->managements; manager; manager = next_manager) {
980 next_manager = manager->next;
981 if(manager->type == 2) {
982 slfh = manager->object;
983 if(slfh->toplevel == fhinfo.tlfh)
984 hs_del_manager(manager, 1);
988 reply("HSMSG_MANAGER_ADDED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
992 static MODCMD_FUNC(cmd_delmanager) {
993 struct handle_info *hi;
995 if(!strchr(argv[1], '.')) {
996 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1000 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1004 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1005 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1006 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1008 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
1009 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1012 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1013 reply("HSMSG_ACCESS_DENIED");
1016 struct hs_user *huser = hs_get_user(hi, 0);
1017 struct hs_manager *manager;
1019 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1023 for(manager = huser->managements; manager; manager = manager->unext) {
1024 if(manager->type == 2 && manager->object == fhinfo.slfh)
1028 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1032 for(manager = huser->managements; manager; manager = manager->unext) {
1033 if(manager->type == 1 && manager->object == fhinfo.tlfh)
1037 reply("HSMSG_MANAGER_NOT", hi->handle, "*", fhinfo.tlfh_name);
1041 hs_del_manager(manager, 1);
1042 reply("HSMSG_MANAGER_DELETED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1046 static MODCMD_FUNC(cmd_set) {
1047 struct handle_info *hi;
1048 struct hs_user *hs_user;
1049 struct hs_assignment *assignment;
1050 struct hs_toplevel *tlfh;
1051 struct hs_secondlevel *slfh;
1053 if (!(hi = user->handle_info)) {
1054 reply("NSMSG_MUST_AUTH");
1057 hs_user = hs_get_user(hi, 0);
1059 return 0; //nothing to do here
1060 if(!strcmp(argv[1], "*")) {
1061 hs_activate_assignment(hs_user, NULL);
1064 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
1065 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1066 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
1068 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
1069 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1072 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1073 slfh = assignment->secondlevel;
1074 tlfh = slfh->toplevel;
1075 if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) {
1076 hs_activate_assignment(hs_user, assignment);
1077 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1081 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1086 static MODCMD_FUNC(cmd_assign) {
1087 struct handle_info *hi;
1089 if(!strchr(argv[1], '.')) {
1090 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1094 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1098 if (!user->handle_info) {
1099 reply("NSMSG_MUST_AUTH");
1102 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1103 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1104 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1106 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1107 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1110 struct hs_user *hs_user = hs_get_user(hi, 1);
1111 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1112 reply("HSMSG_ACCESS_DENIED");
1115 if(hs_get_assignment(fhinfo.slfh, hs_user)) {
1116 reply("HSMSG_FAKEHOST_ASSIGNED", fhinfo.slfh_name, fhinfo.tlfh_name);
1119 hs_add_assignment(fhinfo.slfh, hs_user, HS_ASSIGNMENTSTATE_AUTO);
1120 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1124 static MODCMD_FUNC(cmd_unassign) {
1125 struct handle_info *hi;
1127 if(!strchr(argv[1], '.')) {
1128 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1132 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1136 if (!user->handle_info) {
1137 reply("NSMSG_MUST_AUTH");
1140 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1141 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1142 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1144 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1145 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1148 struct hs_assignment *assignment;
1149 struct hs_user *hs_user = hs_get_user(hi, 0);
1151 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1154 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1155 reply("HSMSG_ACCESS_DENIED");
1158 if(!(assignment = hs_get_assignment(fhinfo.slfh, hs_user))) {
1159 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1162 hs_del_assignment(assignment, 1);
1163 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1167 static MODCMD_FUNC(cmd_oset) {
1168 struct handle_info *hi;
1170 struct hs_assignment *assignment;
1171 if(!strchr(argv[1], '.')) {
1172 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1176 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1180 if (!user->handle_info) {
1181 reply("NSMSG_MUST_AUTH");
1184 struct hs_user *hs_user = hs_get_user(hi, 1);
1185 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1186 if(assignment->active)
1189 if(assignment && !check_management_access(user->handle_info, (hostserv_conf.manager_toplevel_can_oset ? assignment->secondlevel->toplevel : NULL), (hostserv_conf.manager_secondlevel_can_oset ? assignment->secondlevel : NULL))) {
1190 reply("HSMSG_ACCESS_DENIED");
1193 if(!strcmp(argv[1], "*")) {
1195 return 0; //simply ignore (there is no assignment in use)
1196 hs_activate_assignment(hs_user, NULL);
1199 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1200 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1201 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1203 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1204 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1207 if(!check_management_access(user->handle_info, (hostserv_conf.manager_toplevel_can_oset ? fhinfo.tlfh : NULL), (hostserv_conf.manager_secondlevel_can_oset ? fhinfo.slfh : NULL))) {
1208 reply("HSMSG_ACCESS_DENIED");
1211 struct hs_toplevel *tlfh;
1212 struct hs_secondlevel *slfh;
1213 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1214 slfh = assignment->secondlevel;
1215 tlfh = slfh->toplevel;
1216 if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) {
1217 hs_activate_assignment(hs_user, assignment);
1218 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1222 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1227 static void hostserv_conf_read(void) {
1231 str = "modules/hostserv";
1232 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1233 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1237 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1238 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1241 hostserv_conf.nick = str;
1243 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1244 hostserv_conf.modes = (str ? str : NULL);
1246 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1247 unsigned int toplevel_access = atoi(str);
1248 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1250 str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING);
1251 hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0);
1253 str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING);
1254 hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0);
1256 str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING);
1257 hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0);
1259 str = database_get_data(conf_node, "manager_can_rename_toplevel", RECDB_QSTRING);
1260 hostserv_conf.manager_can_rename_toplevel = (atoi(str) ? 1 : 0);
1262 str = database_get_data(conf_node, "manager_can_rename_secondlevel", RECDB_QSTRING);
1263 hostserv_conf.manager_can_rename_secondlevel = (atoi(str) ? 1 : 0);
1265 str = database_get_data(conf_node, "manager_toplevel_can_oset", RECDB_QSTRING);
1266 hostserv_conf.manager_toplevel_can_oset = (atoi(str) ? 1 : 0);
1268 str = database_get_data(conf_node, "manager_secondlevel_can_oset", RECDB_QSTRING);
1269 hostserv_conf.manager_secondlevel_can_oset = (atoi(str) ? 1 : 0);
1272 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1273 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1275 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1276 struct record_data *rd = data;
1277 struct hs_toplevel *tlfh;
1278 struct hs_manager *managerTL;
1279 struct hs_user *user;
1280 struct dict *object;
1282 if (rd->type == RECDB_OBJECT) {
1283 dict_t db = GET_RECORD_OBJECT(rd);
1286 tlfh = hs_add_toplevel(name);
1288 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1289 for (it = dict_first(object); it; it = iter_next(it)) {
1290 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1291 //rd = iter_data(it);
1292 /* nothing in here, yet */
1293 managerTL = hs_add_manager_toplevel(tlfh, user);
1294 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1295 managerTL->active = 1;
1297 managerTL->active = 0;
1301 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1302 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1307 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1308 struct record_data *rd = data;
1309 struct hs_toplevel *tlfh = extra;
1310 struct hs_secondlevel *slfh;
1311 struct hs_manager *managerSL;
1312 struct hs_user *user;
1313 struct dict *object;
1315 if (rd->type == RECDB_OBJECT) {
1316 dict_t db = GET_RECORD_OBJECT(rd);
1319 slfh = hs_add_secondlevel(tlfh, name);
1321 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1322 for (it = dict_first(object); it; it = iter_next(it)) {
1323 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1324 //rd = iter_data(it);
1325 /* nothing in here, yet */
1326 managerSL = hs_add_manager_secondlevel(slfh, user);
1327 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1328 managerSL->active = 1;
1330 managerSL->active = 0;
1334 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1335 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1340 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1341 struct record_data *rd = data;
1342 struct hs_secondlevel *slfh = extra;
1343 struct hs_user *user;
1346 if (rd->type == RECDB_OBJECT) {
1347 dict_t db = GET_RECORD_OBJECT(rd);
1349 user = hs_get_user(get_handle_info(name), 1);
1350 active = (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING) ? HS_ASSIGNMENTSTATE_ON : HS_ASSIGNMENTSTATE_OFF);
1352 hs_add_assignment(slfh, user, active);
1359 hostserv_saxdb_read(struct dict *db)
1361 struct dict *object;
1363 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1364 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1370 hostserv_saxdb_write(struct saxdb_context *ctx)
1372 struct hs_toplevel *tlfh;
1373 struct hs_secondlevel *slfh;
1374 struct hs_assignment *assng;
1375 struct hs_manager *manager;
1377 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1378 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1379 saxdb_start_record(ctx, tlfh->fakehost, 1);
1381 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1382 for(manager = tlfh->managers; manager; manager = manager->next) {
1383 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1384 //additional manager information?
1386 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1387 saxdb_end_record(ctx);
1389 saxdb_end_record(ctx);
1391 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1392 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1393 saxdb_start_record(ctx, slfh->fakehost, 1);
1395 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1396 for(manager = slfh->managers; manager; manager = manager->next) {
1397 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1398 //additional manager information?
1400 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1401 saxdb_end_record(ctx);
1403 saxdb_end_record(ctx);
1405 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1406 for(assng = slfh->assignments; assng; assng = assng->next) {
1407 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1408 //additional assignment information?
1410 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1411 saxdb_end_record(ctx);
1413 saxdb_end_record(ctx);
1415 saxdb_end_record(ctx);
1417 saxdb_end_record(ctx);
1419 saxdb_end_record(ctx);
1421 saxdb_end_record(ctx);
1427 static void hostserv_db_cleanup(void) {
1431 int hostserv_init() {
1432 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1434 const char *nick, *modes;
1435 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1436 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1437 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1438 hostserv_service = service_register(hostserv);
1439 hostserv_service->trigger = '*';
1442 conf_register_reload(hostserv_conf_read);
1443 reg_exit_func(hostserv_db_cleanup);
1444 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1445 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1446 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1447 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1448 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1449 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1450 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1451 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1452 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1453 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1454 modcmd_register(hostserv_module, "renamehost", cmd_renamehost, 3, MODCMD_REQUIRE_AUTHED, NULL);
1455 modcmd_register(hostserv_module, "oset", cmd_oset, 3, MODCMD_REQUIRE_AUTHED, NULL);
1456 message_register_table(msgtab);
1460 int hostserv_finalize(void) {
1464 str = "modules/hostserv";
1465 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1466 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1470 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1471 if (str) hostserv_conf.nick = str;
1473 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1474 if (str) hostserv_conf.modes = str;