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
35 * After you started srvx make the bot active:
36 /msg opserv bind hostserv * hostserv.*
37 /msg opserv bind hostserv help *modcmd.help
48 #define KEY_TOPLEVEL "TopLevel"
49 #define KEY_SECONDLEVEL "SecondLevel"
50 #define KEY_MANAGERS "Manager"
51 #define KEY_ASSIGNMENTS "Assignments"
52 #define KEY_ACTIVE "active"
54 #define HS_FAKEHOST_SPECIAL_CHARS "_-:;" /* alphanum already included */
56 #define HS_ASSIGNMENTSTATE_AUTO -1
57 #define HS_ASSIGNMENTSTATE_OFF 0
58 #define HS_ASSIGNMENTSTATE_ON 1
60 #define HS_FHPARSE_SUCCESS 0
61 #define HS_FHPARSE_INVALID 1
62 #define HS_FHPARSE_UNKNOWN 2
64 static const struct message_entry msgtab[] = {
65 { "HSMSG_ACCESS_DENIED", "Access denied." },
66 { "HSMSG_ASSIGNED_FAKEHOSTS", "Assigned Fakehosts for User $b%s$b:" },
67 { "HSMSG_ASSIGNED_FAKEHOST", " $b%s.%s$b" },
68 { "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE", " $b%s.%s$b (active)" },
69 { "HSMSG_ASSIGNED_FAKEHOST_NOT_ACTIVE", "Fakehost $b%s.%s.$b is not active." },
70 { "HSMSG_ASSIGN_HOWTO", "Use $bset xxx.yyy$b to activate one of the listed fakehosts or $bset *$b to use the default fakehost." },
71 { "HSMSG_ASSIGNED_NONE", " None." },
72 { "HSMSG_MANAGED_FAKEHOSTS", "Fakehosts managed by User $b%s$b:" },
73 { "HSMSG_MANAGED_TOPLEVEL", " $b*.%s$b fakehosts: %d assignments: %d" },
74 { "HSMSG_MANAGED_TOPLEVEL_OWN", " $b*.%s$b fakehosts: %d assignments: %d (active)" },
75 { "HSMSG_MANAGED_FAKEHOST", " $b%s.%s$b assignments: %d" },
76 { "HSMSG_MANAGE_HOWTO", "Use $bview xxx.yyy$b to view more information about a fakehost group." },
77 { "HSMSG_UNKNOWN_FAKEHOST", "Fakehost $b%s.%s$b is unknown or you have no access to manage it." },
78 { "HSMSG_TOPLEVEL_FAKEHOSTS", "Fakehosts in group $b*.%s$b:" },
79 { "HSMSG_TOPLEVEL_FAKEHOST", " $b%s.%s$b assignments: %d managers: %d" },
80 { "HSMSG_TOPLEVEL_INVALID", "The name of the group you entered is invalid ($b%s$b)" },
81 { "HSMSG_MANAGERS_TOPLEVEL", "Managers of group $b*.%s$b:" },
82 { "HSMSG_MANAGERS_FAKEHOST", "Managers of group $b%s.%s$b:" },
83 { "HSMSG_MANAGERS_MANAGERS", " %s" },
84 { "HSMSG_FAKEHOST_ASSIGNMENTS", "Assignments in group $b%s.%s$b:" },
85 { "HSMSG_FAKEHOST_ASSIGNMENT", " $b%s$b (%s.%s.%s)" },
86 { "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE", " $b%s$b (%s.%s.%s) active" },
87 { "HSMSG_FAKEHOST_SET_SUCCESS", "$b%s.%s$b where set successfully." },
88 { "HSMSG_FAKEHOST_TOPLEVEL_ADDED", "Group $b%s$b successfully added." },
89 { "HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", "Group $b%s$b already exists." },
90 { "HSMSG_FAKEHOST_TOPLEVEL_DELETED", "Group $b%s$b successfully deleted." },
91 { "HSMSG_FAKEHOST_SECONDLEVEL_ADDED", "Group $b%s.%s$b successfully added." },
92 { "HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", "Group $b%s.%s$b already exists." },
93 { "HSMSG_FAKEHOST_SECONDLEVEL_DELETED", "Group $b%s.%s$b successfully deleted." },
94 { "HSMSG_FAKEHOST_RENAMED", "Group $b%s.%s$b renamed to $b%s.%s$b." },
95 { "HSMSG_MANAGER_ALREADY", "$b%s$b is already a manager of %s.%s" },
96 { "HSMSG_MANAGER_ADDED", "$b%s$b is now a manager of %s.%s" },
97 { "HSMSG_MANAGER_NOT", "$b%s$b is not a manager of %s.%s" },
98 { "HSMSG_MANAGER_DELETED", "$b%s$b is no longer a manager of %s.%s" },
99 { "HSMSG_FAKEHOST_ASSIGN_SUCCESS", "Group $b%s.%s$b was assigned successfully." },
100 { "HSMSG_FAKEHOST_ASSIGNED", "Group $b%s.%s$b is already assigned to the user." },
101 { "HSMSG_FAKEHOST_UNASSIGN_SUCCESS", "Group $b%s.%s$b was unassigned successfully." },
110 int fallback_other_assignment : 1;
111 int manager_can_del_toplevel : 1;
112 int manager_can_del_secondlevel : 1;
113 int manager_can_rename_toplevel : 1;
114 int manager_can_rename_secondlevel : 1;
117 const char *hostserv_module_deps[] = { NULL };
118 struct userNode *hostserv;
119 struct helpfile *hostserv_helpfile;
120 static struct module *hostserv_module;
121 static struct service *hostserv_service;
122 static struct log_type *HS_LOG;
123 static struct hs_toplevel *toplevels = NULL;
124 static struct hs_user *hostserv_users = NULL;
126 /* FAKEHOST STRUCTS */
129 struct hs_manager *managers;
130 struct hs_secondlevel *secondlevel;
131 struct hs_toplevel *next;
134 struct hs_secondlevel {
135 struct hs_toplevel *toplevel;
137 struct hs_manager *managers;
138 struct hs_assignment *assignments;
139 struct hs_secondlevel *next;
142 struct hs_assignment {
143 struct hs_secondlevel *secondlevel;
144 struct hs_user *user;
146 struct hs_assignment *next;
147 struct hs_assignment *unext; /* for hs_user */
154 struct hs_user *user;
155 struct hs_manager *next;
156 struct hs_manager *unext; /* for hs_user */
160 struct handle_info *hi;
161 struct hs_assignment *assignments;
162 struct hs_manager *managements;
163 struct hs_user *next;
166 /* temporary structs */
167 struct hs_fakehost_info {
168 unsigned int parse_state : 4;
169 unsigned int have_secondlevel : 1;
172 struct hs_toplevel *tlfh;
173 struct hs_secondlevel *slfh;
176 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
177 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
178 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
179 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
180 static void hs_del_user(struct hs_user *user);
181 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment);
183 static void hs_free_all() {
184 struct hs_toplevel *tlfh, *next_tlfh;
185 struct hs_secondlevel *slfh, *next_slfh;
186 struct hs_assignment *assng, *next_assng;
187 struct hs_manager *manager, *next_manager;
188 struct hs_user *user, *next_user;
189 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
190 next_tlfh = tlfh->next;
191 for(manager = tlfh->managers; manager; manager = next_manager) {
192 next_manager = manager->next;
195 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
196 next_slfh = slfh->next;
197 for(manager = slfh->managers; manager; manager = next_manager) {
198 next_manager = manager->next;
201 for(assng = slfh->assignments; assng; assng = next_assng) {
202 next_assng = assng->next;
205 free(slfh->fakehost);
208 free(tlfh->fakehost);
211 for(user = hostserv_users; user; user = next_user) {
212 next_user = user->next;
216 hostserv_users = NULL;
219 static struct hs_toplevel *hs_add_toplevel(const char *name) {
220 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
221 tlfh->fakehost = strdup(name);
222 tlfh->next = toplevels;
227 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
228 //unassign all assignments
229 struct hs_secondlevel *slfh, *next_slfh;
230 struct hs_manager *manager, *next_manager;
231 for(manager = tlfh->managers; manager; manager = next_manager) {
232 next_manager = manager->next;
233 hs_del_manager(manager, 0);
235 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
236 next_slfh = slfh->next;
237 hs_del_secondlevel(slfh, 0);
240 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
241 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
244 last_tlfh->next = ctlfh->next;
246 toplevels = ctlfh->next;
250 free(tlfh->fakehost);
254 static void hs_rename_toplevel(struct hs_toplevel *tlfh, const char *name) {
255 struct hs_secondlevel *slfh;
256 struct hs_assignment *assng;
258 free(tlfh->fakehost);
259 tlfh->fakehost = strdup(name);
261 //trigger rename for all assignments
262 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
263 for(assng = slfh->assignments; assng; assng = assng->next) {
265 hs_activate_assignment(assng->user, assng);
271 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
272 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
273 slfh->toplevel = tlfh;
274 slfh->fakehost = strdup(name);
275 slfh->next = tlfh->secondlevel;
276 tlfh->secondlevel = slfh;
280 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
281 if(remove_from_tlfh) {
282 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
283 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
286 prev_slfh->next = slfh->next;
288 slfh->toplevel->secondlevel = slfh->next;
294 struct hs_assignment *assng, *next_assng;
295 struct hs_manager *manager, *next_manager;
296 for(manager = slfh->managers; manager; manager = next_manager) {
297 next_manager = manager->next;
298 hs_del_manager(manager, 0);
300 for(assng = slfh->assignments; assng; assng = next_assng) {
301 next_assng = assng->next;
302 hs_del_assignment(assng, 0);
304 free(slfh->fakehost);
308 static void hs_rename_secondlevel(struct hs_secondlevel *slfh, const char *name) {
309 struct hs_assignment *assng;
311 free(slfh->fakehost);
312 slfh->fakehost = strdup(name);
314 //trigger rename for all assignments
315 for(assng = slfh->assignments; assng; assng = assng->next) {
317 hs_activate_assignment(assng->user, assng);
322 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
323 struct hs_manager *manager = calloc(1, sizeof(*manager));
324 manager->user = user;
326 manager->object = tlfh;
327 manager->unext = user->managements;
328 user->managements = manager;
329 manager->next = tlfh->managers;
330 tlfh->managers = manager;
334 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
335 struct hs_manager *manager = calloc(1, sizeof(*manager));
336 manager->user = user;
338 manager->object = slfh;
339 manager->unext = user->managements;
340 user->managements = manager;
341 manager->next = slfh->managers;
342 slfh->managers = manager;
346 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
347 struct hs_manager *cmanager, *prev_manager = NULL;
348 if(remove_from_object) {
349 if(manager->type == 1) {
350 struct hs_toplevel *tlfh = manager->object;
351 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
352 if(cmanager == manager) {
354 prev_manager->next = manager->next;
356 tlfh->managers = manager->next;
359 prev_manager = cmanager;
361 } else if(manager->type == 2) {
362 struct hs_secondlevel *slfh = manager->object;
363 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
364 if(cmanager == manager) {
366 prev_manager->next = manager->next;
368 slfh->managers = manager->next;
371 prev_manager = cmanager;
376 if(remove_from_object != 2) {
377 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
378 if(cmanager == manager) {
380 prev_manager->unext = manager->unext;
382 manager->user->managements = manager->unext;
385 prev_manager = cmanager;
387 if(manager->user->managements == NULL && manager->user->assignments == NULL)
388 hs_del_user(manager->user);
393 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment) {
394 struct hs_toplevel *tlfh;
395 struct hs_secondlevel *slfh;
396 struct hs_assignment *assgn;
397 char fakehost[HOSTLEN];
399 assert((!assignment || (assignment->user == user)));
401 if(user->assignments) {
402 for(assgn = user->assignments; assgn; assgn = assgn->unext)
406 if(user->hi->fakehost) {
407 free(user->hi->fakehost);
408 user->hi->fakehost = NULL;
412 slfh = assignment->secondlevel;
413 tlfh = slfh->toplevel;
414 snprintf(fakehost, sizeof(fakehost), "$.%s.%s", slfh->fakehost, tlfh->fakehost);
415 user->hi->fakehost = strdup(fakehost);
416 assignment->active = 1;
419 apply_fakehost(user->hi, NULL);
422 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user, int active) {
423 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
424 assignment->secondlevel = slfh;
425 assignment->user = user;
426 if(active == HS_ASSIGNMENTSTATE_AUTO)
427 assignment->active = (user->assignments == NULL ? 1 : 0);
429 assignment->active = (active == HS_ASSIGNMENTSTATE_ON ? 1 : 0);
430 assignment->next = slfh->assignments;
431 slfh->assignments = assignment;
432 assignment->unext = user->assignments;
433 user->assignments = assignment;
434 if(assignment->active) {
435 hs_activate_assignment(user, assignment);
440 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
441 struct hs_assignment *cassignment, *prev_assignment = NULL;
442 if(remove_from_slfh) {
443 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
444 if(cassignment == assignment) {
446 prev_assignment->next = assignment->next;
448 assignment->secondlevel->assignments = assignment->next;
451 prev_assignment = cassignment;
453 prev_assignment = NULL;
455 if(remove_from_slfh != 2) {
456 prev_assignment = NULL;
457 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
458 if(cassignment == assignment) {
460 prev_assignment->unext = assignment->unext;
462 assignment->user->assignments = assignment->unext;
465 prev_assignment = cassignment;
468 if(assignment->active) {
469 /* use another assignment - or fall back to default user host? */
471 if(hostserv_conf.fallback_other_assignment && assignment->user->assignments) {
472 /* try to find another assignment from same slfh first */
473 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
474 if(cassignment != assignment && cassignment->user == assignment->user)
477 /* use another tlfh assignment */
479 cassignment = assignment->user->assignments;
481 hs_activate_assignment(assignment->user, cassignment);
484 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
485 hs_del_user(assignment->user);
490 static struct hs_assignment *hs_get_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
491 struct hs_assignment *cassignment;
492 for(cassignment = slfh->assignments; cassignment; cassignment = cassignment->next) {
493 if(cassignment->user == user)
499 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
500 struct hs_user *cuser;
501 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
506 cuser = calloc(1, sizeof(*cuser));
508 cuser->next = hostserv_users;
509 hostserv_users = cuser;
515 static void hs_del_user(struct hs_user *user) {
516 if(user->managements) {
517 struct hs_manager *manager, *next_manager;
518 for(manager = user->managements; manager; manager = next_manager) {
519 next_manager = manager->unext;
520 hs_del_manager(manager, 2);
523 if(user->assignments) {
524 struct hs_assignment *assng, *next_assng;
525 for(assng = user->assignments; assng; assng = next_assng) {
526 next_assng = assng->unext;
527 hs_del_assignment(assng, 2);
530 struct hs_user *cuser, *prev_user = NULL;
531 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
534 prev_user->next = user->next;
536 hostserv_users = user->next;
544 /* END OF MANAGEMENT FUNCTIONS */
546 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
549 if(hi->opserv_level >= hostserv_conf.toplevel_access)
551 struct hs_user *user = hs_get_user(hi, 0);
554 struct hs_manager *manager;
556 for(manager = user->managements; manager; manager = manager->next) {
557 if(manager->type == 2 && manager->object == slfh)
562 for(manager = user->managements; manager; manager = manager->next) {
563 if(manager->type == 1 && manager->object == tlfh)
570 struct hs_fakehost_info parse_fakehost_info(char *fakehost, int fix_name_case) {
571 struct hs_fakehost_info fhinfo;
573 memset(&fhinfo, 0, sizeof(fhinfo));
574 for(i = strlen(fakehost)-1; i >= 0; i--) {
575 if(!isalnum(fakehost[i]) && fakehost[i] != '.' && !(fakehost[i] == '*' && i == 0) && !strchr(HS_FAKEHOST_SPECIAL_CHARS, fakehost[i])) {
576 fhinfo.parse_state = HS_FHPARSE_INVALID;
580 fhinfo.slfh_name = fakehost;
581 fhinfo.tlfh_name = strchr(fakehost, '.');
582 if(!fhinfo.tlfh_name) {
583 fhinfo.parse_state = HS_FHPARSE_INVALID;
586 fhinfo.tlfh_name[0] = '\0';
588 if(strchr(fhinfo.tlfh_name, '.')) {
589 fhinfo.parse_state = HS_FHPARSE_INVALID;
591 fhinfo.tlfh_name[0] = '\0';
594 if(irccasecmp(fhinfo.slfh_name, "*"))
595 fhinfo.have_secondlevel = 1;
596 struct hs_toplevel *tlfh;
597 struct hs_secondlevel *slfh;
598 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
599 if(!irccasecmp(tlfh->fakehost, fhinfo.tlfh_name)) break;
604 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
607 if(fhinfo.have_secondlevel) {
608 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
609 if(!irccasecmp(slfh->fakehost, fhinfo.slfh_name)) break;
613 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
619 //simply copy the stored fakehosts over the given ones
620 strcpy(fhinfo.tlfh_name, fhinfo.tlfh->fakehost);
622 strcpy(fhinfo.slfh_name, fhinfo.slfh->fakehost);
624 fhinfo.parse_state = HS_FHPARSE_SUCCESS;
630 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
631 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
632 struct hs_secondlevel *slfh;
633 if(!tlfh->secondlevel)
634 reply("HSMSG_ASSIGNED_NONE");
636 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
637 struct hs_manager *cmanager;
639 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
641 struct hs_assignment *assignment;
643 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
645 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
647 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
648 struct hs_manager *cmanager;
650 reply("HSMSG_ASSIGNED_NONE");
652 char managerBuf[351];
654 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
655 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
656 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
659 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
661 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
665 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
666 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
667 struct hs_assignment *assignment;
668 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
669 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
671 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
672 struct hs_manager *cmanager;
674 reply("HSMSG_ASSIGNED_NONE");
676 char managerBuf[351];
678 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
679 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
680 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
683 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
685 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
689 static MODCMD_FUNC(cmd_view) {
690 struct handle_info *hi;
691 if(argc >= 2 && !strchr(argv[1], '.')) {
692 if (!(hi = modcmd_get_handle_info(user, argv[1])))
694 } else if(argc >= 2) {
695 if (!(hi = user->handle_info)) {
696 reply("NSMSG_MUST_AUTH");
699 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 0);
700 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
701 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
703 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
704 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
708 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
709 reply("HSMSG_ACCESS_DENIED");
712 cmd_view_toplevel_information(user, cmd, fhinfo.tlfh);
715 if(!check_management_access(hi, fhinfo.tlfh, fhinfo.slfh)) {
716 reply("HSMSG_ACCESS_DENIED");
719 cmd_view_secondlevel_information(user, cmd, fhinfo.slfh);
723 if (!(hi = user->handle_info)) {
724 reply("NSMSG_MUST_AUTH");
728 struct hs_user *huser = hs_get_user(hi, 0);
729 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
732 struct hs_assignment *assignment;
733 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
734 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
737 if(assigncount && huser->hi == user->handle_info)
738 reply("HSMSG_ASSIGN_HOWTO");
741 reply("HSMSG_ASSIGNED_NONE");
742 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
743 struct hs_toplevel *tlfh;
744 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
745 struct hs_secondlevel *slfh;
746 struct hs_assignment *assignment;
747 int slfhs = 0, assignments = 0;
748 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
750 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
753 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
755 reply("HSMSG_MANAGE_HOWTO");
756 } else if(huser && huser->managements) {
757 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
758 struct hs_manager *manager;
759 for(manager = huser->managements; manager; manager = manager->unext) {
760 if(manager->type == 1) {
761 struct hs_toplevel *tlfh = manager->object;
762 struct hs_secondlevel *slfh;
763 struct hs_assignment *assignment;
764 int slfhs = 0, assignments = 0;
765 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
767 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
770 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
773 for(manager = huser->managements; manager; manager = manager->next) {
774 if(manager->type == 2) {
775 struct hs_secondlevel *slfh = manager->object;
776 struct hs_toplevel *tlfh = slfh->toplevel;
777 //check if the user is already a manager of the tlfh
778 struct hs_manager *cmanager;
779 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
780 if(cmanager->user == huser) break;
782 if(cmanager) continue;
783 struct hs_assignment *assignment;
785 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
787 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
790 if(huser->hi == user->handle_info)
791 reply("HSMSG_MANAGE_HOWTO");
796 static MODCMD_FUNC(cmd_addhost) {
797 struct handle_info *hi;
798 if (!(hi = user->handle_info)) {
799 reply("NSMSG_MUST_AUTH");
802 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
803 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
804 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
807 if(!fhinfo.have_secondlevel) {
808 if(!check_management_access(hi, NULL, NULL)) {
809 reply("HSMSG_ACCESS_DENIED");
812 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
813 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
816 hs_add_toplevel(fhinfo.tlfh_name);
817 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", fhinfo.tlfh_name);
820 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
823 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
824 reply("HSMSG_ACCESS_DENIED");
827 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
828 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
831 hs_add_secondlevel(fhinfo.tlfh, fhinfo.slfh_name);
832 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", fhinfo.slfh_name, fhinfo.tlfh_name);
837 static MODCMD_FUNC(cmd_delhost) {
838 struct handle_info *hi;
839 if (!(hi = user->handle_info)) {
840 reply("NSMSG_MUST_AUTH");
843 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
844 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
845 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
847 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
848 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
852 if(!check_management_access(hi, (hostserv_conf.manager_can_del_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
853 reply("HSMSG_ACCESS_DENIED");
856 hs_del_toplevel(fhinfo.tlfh);
857 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", fhinfo.tlfh_name);
859 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_del_secondlevel ? fhinfo.slfh : NULL))) {
860 reply("HSMSG_ACCESS_DENIED");
863 hs_del_secondlevel(fhinfo.slfh, 1);
864 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", fhinfo.slfh_name, fhinfo.tlfh_name);
869 static MODCMD_FUNC(cmd_renamehost) {
870 struct handle_info *hi;
871 if (!(hi = user->handle_info)) {
872 reply("NSMSG_MUST_AUTH");
876 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
877 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
878 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
880 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
881 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
885 struct hs_fakehost_info new_fhinfo = parse_fakehost_info(argv[2], 0);
886 if(new_fhinfo.parse_state == HS_FHPARSE_INVALID) {
887 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
889 } 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)))) {
890 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
895 if(!check_management_access(hi, (hostserv_conf.manager_can_rename_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
896 reply("HSMSG_ACCESS_DENIED");
899 if(fhinfo.have_secondlevel) {
900 //can't rename toplevel into secondlevel fakehost!
901 new_fhinfo.tlfh_name--;
902 new_fhinfo.tlfh_name[0] = '.';
903 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
906 if(strcmp(new_fhinfo.tlfh_name, fhinfo.tlfh->fakehost))
907 hs_rename_toplevel(fhinfo.tlfh, new_fhinfo.tlfh_name);
908 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
910 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_rename_secondlevel ? fhinfo.slfh : NULL))) {
911 reply("HSMSG_ACCESS_DENIED");
914 if(irccasecmp(new_fhinfo.tlfh_name, fhinfo.tlfh_name)) {
915 //can't rename toplevel and secondlevel fakehost with one command!
916 new_fhinfo.tlfh_name--;
917 new_fhinfo.tlfh_name[0] = '.';
918 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
921 if(strcmp(new_fhinfo.slfh_name, fhinfo.slfh->fakehost))
922 hs_rename_secondlevel(fhinfo.slfh, new_fhinfo.slfh_name);
923 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
928 static MODCMD_FUNC(cmd_addmanager) {
929 struct handle_info *hi;
931 if(!strchr(argv[1], '.')) {
932 if (!(hi = modcmd_get_handle_info(user, argv[1])))
936 if (!(hi = modcmd_get_handle_info(user, argv[2])))
940 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
941 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
942 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
944 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
945 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
948 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
949 reply("HSMSG_ACCESS_DENIED");
952 struct hs_user *huser = hs_get_user(hi, 1);
953 struct hs_manager *manager;
955 for(manager = huser->managements; manager; manager = manager->next) {
956 if(manager->type == 2 && manager->object == fhinfo.slfh) {
957 reply("HSMSG_MANAGER_ALREADY", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
962 for(manager = huser->managements; manager; manager = manager->next) {
963 if(manager->type == 1 && manager->object == fhinfo.tlfh) {
964 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", fhinfo.tlfh_name);
969 hs_add_manager_secondlevel(fhinfo.slfh, huser);
971 hs_add_manager_toplevel(fhinfo.tlfh, huser);
972 reply("HSMSG_MANAGER_ADDED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
976 static MODCMD_FUNC(cmd_delmanager) {
977 struct handle_info *hi;
979 if(!strchr(argv[1], '.')) {
980 if (!(hi = modcmd_get_handle_info(user, argv[1])))
984 if (!(hi = modcmd_get_handle_info(user, argv[2])))
988 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
989 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
990 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
992 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
993 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
996 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
997 reply("HSMSG_ACCESS_DENIED");
1000 struct hs_user *huser = hs_get_user(hi, 0);
1001 struct hs_manager *manager;
1003 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1007 for(manager = huser->managements; manager; manager = manager->next) {
1008 if(manager->type == 2 && manager->object == fhinfo.slfh)
1012 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1016 for(manager = huser->managements; manager; manager = manager->next) {
1017 if(manager->type == 1 && manager->object == fhinfo.tlfh)
1021 reply("HSMSG_MANAGER_NOT", hi->handle, "*", fhinfo.tlfh_name);
1025 hs_del_manager(manager, 1);
1026 reply("HSMSG_MANAGER_DELETED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1030 static MODCMD_FUNC(cmd_set) {
1031 struct handle_info *hi;
1032 struct hs_user *hs_user;
1033 struct hs_assignment *assignment;
1034 struct hs_toplevel *tlfh;
1035 struct hs_secondlevel *slfh;
1037 if (!(hi = user->handle_info)) {
1038 reply("NSMSG_MUST_AUTH");
1041 hs_user = hs_get_user(hi, 0);
1043 return 0; //nothing to do here
1044 if(!strcmp(argv[1], "*")) {
1045 hs_activate_assignment(hs_user, NULL);
1048 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
1049 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1050 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
1052 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
1053 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1056 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1057 slfh = assignment->secondlevel;
1058 tlfh = slfh->toplevel;
1059 if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) {
1060 hs_activate_assignment(hs_user, assignment);
1061 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1065 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1070 static MODCMD_FUNC(cmd_assign) {
1071 struct handle_info *hi;
1073 if(!strchr(argv[1], '.')) {
1074 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1078 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1082 if (!user->handle_info) {
1083 reply("NSMSG_MUST_AUTH");
1086 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1087 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1088 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1090 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1091 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1094 struct hs_user *hs_user = hs_get_user(hi, 1);
1095 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1096 reply("HSMSG_ACCESS_DENIED");
1099 if(hs_get_assignment(fhinfo.slfh, hs_user)) {
1100 reply("HSMSG_FAKEHOST_ASSIGNED", fhinfo.slfh_name, fhinfo.tlfh_name);
1103 hs_add_assignment(fhinfo.slfh, hs_user, HS_ASSIGNMENTSTATE_AUTO);
1104 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1108 static MODCMD_FUNC(cmd_unassign) {
1109 struct handle_info *hi;
1111 if(!strchr(argv[1], '.')) {
1112 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1116 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1120 if (!user->handle_info) {
1121 reply("NSMSG_MUST_AUTH");
1124 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1125 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1126 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1128 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1129 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1132 struct hs_assignment *assignment;
1133 struct hs_user *hs_user = hs_get_user(hi, 0);
1135 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1138 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1139 reply("HSMSG_ACCESS_DENIED");
1142 if(!(assignment = hs_get_assignment(fhinfo.slfh, hs_user))) {
1143 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1146 hs_del_assignment(assignment, 1);
1147 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1151 static void hostserv_conf_read(void) {
1155 str = "modules/hostserv";
1156 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1157 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1161 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1162 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1165 hostserv_conf.nick = str;
1167 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1168 hostserv_conf.modes = (str ? str : NULL);
1170 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1171 unsigned int toplevel_access = atoi(str);
1172 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1174 str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING);
1175 hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0);
1177 str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING);
1178 hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0);
1180 str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING);
1181 hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0);
1183 str = database_get_data(conf_node, "manager_can_rename_toplevel", RECDB_QSTRING);
1184 hostserv_conf.manager_can_rename_toplevel = (atoi(str) ? 1 : 0);
1186 str = database_get_data(conf_node, "manager_can_rename_secondlevel", RECDB_QSTRING);
1187 hostserv_conf.manager_can_rename_secondlevel = (atoi(str) ? 1 : 0);
1189 /*str = database_get_data(conf_node, "description", RECDB_QSTRING);
1190 hostserv_conf.description = (str ? str : NULL);*/
1193 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1194 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1196 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1197 struct record_data *rd = data;
1198 struct hs_toplevel *tlfh;
1199 struct hs_manager *managerTL;
1200 struct hs_user *user;
1201 struct dict *object;
1203 if (rd->type == RECDB_OBJECT) {
1204 dict_t db = GET_RECORD_OBJECT(rd);
1207 tlfh = hs_add_toplevel(name);
1209 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1210 for (it = dict_first(object); it; it = iter_next(it)) {
1211 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1212 //rd = iter_data(it);
1213 /* nothing in here, yet */
1214 managerTL = hs_add_manager_toplevel(tlfh, user);
1215 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1216 managerTL->active = 1;
1218 managerTL->active = 0;
1222 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1223 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1228 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1229 struct record_data *rd = data;
1230 struct hs_toplevel *tlfh = extra;
1231 struct hs_secondlevel *slfh;
1232 struct hs_manager *managerSL;
1233 struct hs_user *user;
1234 struct dict *object;
1236 if (rd->type == RECDB_OBJECT) {
1237 dict_t db = GET_RECORD_OBJECT(rd);
1240 slfh = hs_add_secondlevel(tlfh, name);
1242 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1243 for (it = dict_first(object); it; it = iter_next(it)) {
1244 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1245 //rd = iter_data(it);
1246 /* nothing in here, yet */
1247 managerSL = hs_add_manager_secondlevel(slfh, user);
1248 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1249 managerSL->active = 1;
1251 managerSL->active = 0;
1255 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1256 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1261 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1262 struct record_data *rd = data;
1263 struct hs_secondlevel *slfh = extra;
1264 struct hs_user *user;
1267 if (rd->type == RECDB_OBJECT) {
1268 dict_t db = GET_RECORD_OBJECT(rd);
1270 user = hs_get_user(get_handle_info(name), 1);
1271 active = (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING) ? HS_ASSIGNMENTSTATE_ON : HS_ASSIGNMENTSTATE_OFF);
1273 hs_add_assignment(slfh, user, active);
1280 hostserv_saxdb_read(struct dict *db)
1282 struct dict *object;
1284 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1285 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1291 hostserv_saxdb_write(struct saxdb_context *ctx)
1293 struct hs_toplevel *tlfh;
1294 struct hs_secondlevel *slfh;
1295 struct hs_assignment *assng;
1296 struct hs_manager *manager;
1298 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1299 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1300 saxdb_start_record(ctx, tlfh->fakehost, 1);
1302 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1303 for(manager = tlfh->managers; manager; manager = manager->next) {
1304 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1305 //additional manager information?
1307 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1308 saxdb_end_record(ctx);
1310 saxdb_end_record(ctx);
1312 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1313 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1314 saxdb_start_record(ctx, slfh->fakehost, 1);
1316 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1317 for(manager = slfh->managers; manager; manager = manager->next) {
1318 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1319 //additional manager information?
1321 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1322 saxdb_end_record(ctx);
1324 saxdb_end_record(ctx);
1326 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1327 for(assng = slfh->assignments; assng; assng = assng->next) {
1328 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1329 //additional assignment information?
1331 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1332 saxdb_end_record(ctx);
1334 saxdb_end_record(ctx);
1336 saxdb_end_record(ctx);
1338 saxdb_end_record(ctx);
1340 saxdb_end_record(ctx);
1342 saxdb_end_record(ctx);
1348 static void hostserv_db_cleanup(void) {
1352 int hostserv_init() {
1353 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1355 const char *nick, *modes;
1356 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1357 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1358 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1359 hostserv_service = service_register(hostserv);
1360 hostserv_service->trigger = '*';
1363 conf_register_reload(hostserv_conf_read);
1364 reg_exit_func(hostserv_db_cleanup);
1365 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1366 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1367 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1368 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1369 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1370 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1371 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1372 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1373 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1374 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1375 modcmd_register(hostserv_module, "renamehost", cmd_renamehost, 3, MODCMD_REQUIRE_AUTHED, NULL);
1376 message_register_table(msgtab);
1380 int hostserv_finalize(void) {
1384 str = "modules/hostserv";
1385 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1386 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1390 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1391 if (str) hostserv_conf.nick = str;
1393 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1394 if (str) hostserv_conf.modes = str;