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;
115 int manager_toplevel_can_oset : 1;
116 int manager_secondlevel_can_oset : 1;
119 const char *hostserv_module_deps[] = { NULL };
120 struct userNode *hostserv;
121 struct helpfile *hostserv_helpfile;
122 static struct module *hostserv_module;
123 static struct service *hostserv_service;
124 static struct log_type *HS_LOG;
125 static struct hs_toplevel *toplevels = NULL;
126 static struct hs_user *hostserv_users = NULL;
128 /* FAKEHOST STRUCTS */
131 struct hs_manager *managers;
132 struct hs_secondlevel *secondlevel;
133 struct hs_toplevel *next;
136 struct hs_secondlevel {
137 struct hs_toplevel *toplevel;
139 struct hs_manager *managers;
140 struct hs_assignment *assignments;
141 struct hs_secondlevel *next;
144 struct hs_assignment {
145 struct hs_secondlevel *secondlevel;
146 struct hs_user *user;
148 struct hs_assignment *next;
149 struct hs_assignment *unext; /* for hs_user */
156 struct hs_user *user;
157 struct hs_manager *next;
158 struct hs_manager *unext; /* for hs_user */
162 struct handle_info *hi;
163 struct hs_assignment *assignments;
164 struct hs_manager *managements;
165 struct hs_user *next;
168 /* temporary structs */
169 struct hs_fakehost_info {
170 unsigned int parse_state : 4;
171 unsigned int have_secondlevel : 1;
174 struct hs_toplevel *tlfh;
175 struct hs_secondlevel *slfh;
178 /* MANAGEMENT FUNCTIONS for FAKEHOST STRUCTS */
179 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh);
180 static void hs_del_manager(struct hs_manager *manager, int remove_from_object);
181 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh);
182 static void hs_del_user(struct hs_user *user);
183 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment);
185 static void hs_free_all() {
186 struct hs_toplevel *tlfh, *next_tlfh;
187 struct hs_secondlevel *slfh, *next_slfh;
188 struct hs_assignment *assng, *next_assng;
189 struct hs_manager *manager, *next_manager;
190 struct hs_user *user, *next_user;
191 for(tlfh = toplevels; tlfh; tlfh = next_tlfh) {
192 next_tlfh = tlfh->next;
193 for(manager = tlfh->managers; manager; manager = next_manager) {
194 next_manager = manager->next;
197 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
198 next_slfh = slfh->next;
199 for(manager = slfh->managers; manager; manager = next_manager) {
200 next_manager = manager->next;
203 for(assng = slfh->assignments; assng; assng = next_assng) {
204 next_assng = assng->next;
207 free(slfh->fakehost);
210 free(tlfh->fakehost);
213 for(user = hostserv_users; user; user = next_user) {
214 next_user = user->next;
218 hostserv_users = NULL;
221 static struct hs_toplevel *hs_add_toplevel(const char *name) {
222 struct hs_toplevel *tlfh = calloc(1, sizeof(*tlfh));
223 tlfh->fakehost = strdup(name);
224 tlfh->next = toplevels;
229 static void hs_del_toplevel(struct hs_toplevel *tlfh) {
230 //unassign all assignments
231 struct hs_secondlevel *slfh, *next_slfh;
232 struct hs_manager *manager, *next_manager;
233 for(manager = tlfh->managers; manager; manager = next_manager) {
234 next_manager = manager->next;
235 hs_del_manager(manager, 0);
237 for(slfh = tlfh->secondlevel; slfh; slfh = next_slfh) {
238 next_slfh = slfh->next;
239 hs_del_secondlevel(slfh, 0);
242 struct hs_toplevel *ctlfh, *last_tlfh = NULL;
243 for(ctlfh = toplevels; ctlfh; ctlfh = ctlfh->next) {
246 last_tlfh->next = ctlfh->next;
248 toplevels = ctlfh->next;
252 free(tlfh->fakehost);
256 static void hs_rename_toplevel(struct hs_toplevel *tlfh, const char *name) {
257 struct hs_secondlevel *slfh;
258 struct hs_assignment *assng;
260 free(tlfh->fakehost);
261 tlfh->fakehost = strdup(name);
263 //trigger rename for all assignments
264 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
265 for(assng = slfh->assignments; assng; assng = assng->next) {
267 hs_activate_assignment(assng->user, assng);
273 static struct hs_secondlevel *hs_add_secondlevel(struct hs_toplevel *tlfh, const char *name) {
274 struct hs_secondlevel *slfh = calloc(1, sizeof(*slfh));
275 slfh->toplevel = tlfh;
276 slfh->fakehost = strdup(name);
277 slfh->next = tlfh->secondlevel;
278 tlfh->secondlevel = slfh;
282 static void hs_del_secondlevel(struct hs_secondlevel *slfh, int remove_from_tlfh) {
283 if(remove_from_tlfh) {
284 struct hs_secondlevel *cslfh, *prev_slfh = NULL;
285 for(cslfh = slfh->toplevel->secondlevel; cslfh; cslfh = cslfh->next) {
288 prev_slfh->next = slfh->next;
290 slfh->toplevel->secondlevel = slfh->next;
296 struct hs_assignment *assng, *next_assng;
297 struct hs_manager *manager, *next_manager;
298 for(manager = slfh->managers; manager; manager = next_manager) {
299 next_manager = manager->next;
300 hs_del_manager(manager, 0);
302 for(assng = slfh->assignments; assng; assng = next_assng) {
303 next_assng = assng->next;
304 hs_del_assignment(assng, 0);
306 free(slfh->fakehost);
310 static void hs_rename_secondlevel(struct hs_secondlevel *slfh, const char *name) {
311 struct hs_assignment *assng;
313 free(slfh->fakehost);
314 slfh->fakehost = strdup(name);
316 //trigger rename for all assignments
317 for(assng = slfh->assignments; assng; assng = assng->next) {
319 hs_activate_assignment(assng->user, assng);
324 static struct hs_manager *hs_add_manager_toplevel(struct hs_toplevel *tlfh, struct hs_user *user) {
325 struct hs_manager *manager = calloc(1, sizeof(*manager));
326 manager->user = user;
328 manager->object = tlfh;
329 manager->unext = user->managements;
330 user->managements = manager;
331 manager->next = tlfh->managers;
332 tlfh->managers = manager;
336 static struct hs_manager *hs_add_manager_secondlevel(struct hs_secondlevel *slfh, struct hs_user *user) {
337 struct hs_manager *manager = calloc(1, sizeof(*manager));
338 manager->user = user;
340 manager->object = slfh;
341 manager->unext = user->managements;
342 user->managements = manager;
343 manager->next = slfh->managers;
344 slfh->managers = manager;
348 static void hs_del_manager(struct hs_manager *manager, int remove_from_object) {
349 struct hs_manager *cmanager, *prev_manager = NULL;
350 if(remove_from_object) {
351 if(manager->type == 1) {
352 struct hs_toplevel *tlfh = manager->object;
353 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
354 if(cmanager == manager) {
356 prev_manager->next = manager->next;
358 tlfh->managers = manager->next;
361 prev_manager = cmanager;
363 } else if(manager->type == 2) {
364 struct hs_secondlevel *slfh = manager->object;
365 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
366 if(cmanager == manager) {
368 prev_manager->next = manager->next;
370 slfh->managers = manager->next;
373 prev_manager = cmanager;
378 if(remove_from_object != 2) {
379 for(cmanager = manager->user->managements; cmanager; cmanager = cmanager->unext) {
380 if(cmanager == manager) {
382 prev_manager->unext = manager->unext;
384 manager->user->managements = manager->unext;
387 prev_manager = cmanager;
389 if(manager->user->managements == NULL && manager->user->assignments == NULL)
390 hs_del_user(manager->user);
395 static void hs_activate_assignment(struct hs_user *user, struct hs_assignment *assignment) {
396 struct hs_toplevel *tlfh;
397 struct hs_secondlevel *slfh;
398 struct hs_assignment *assgn;
399 char fakehost[HOSTLEN];
401 assert((!assignment || (assignment->user == user)));
403 if(user->assignments) {
404 for(assgn = user->assignments; assgn; assgn = assgn->unext)
408 if(user->hi->fakehost) {
409 free(user->hi->fakehost);
410 user->hi->fakehost = NULL;
414 slfh = assignment->secondlevel;
415 tlfh = slfh->toplevel;
416 snprintf(fakehost, sizeof(fakehost), "$.%s.%s", slfh->fakehost, tlfh->fakehost);
417 user->hi->fakehost = strdup(fakehost);
418 assignment->active = 1;
421 apply_fakehost(user->hi, NULL);
424 static struct hs_assignment *hs_add_assignment(struct hs_secondlevel *slfh, struct hs_user *user, int active) {
425 struct hs_assignment *assignment = calloc(1, sizeof(*assignment));
426 assignment->secondlevel = slfh;
427 assignment->user = user;
428 if(active == HS_ASSIGNMENTSTATE_AUTO)
429 assignment->active = (user->assignments == NULL ? 1 : 0);
431 assignment->active = (active == HS_ASSIGNMENTSTATE_ON ? 1 : 0);
432 assignment->next = slfh->assignments;
433 slfh->assignments = assignment;
434 assignment->unext = user->assignments;
435 user->assignments = assignment;
436 if(assignment->active) {
437 hs_activate_assignment(user, assignment);
442 static void hs_del_assignment(struct hs_assignment *assignment, int remove_from_slfh) {
443 struct hs_assignment *cassignment, *prev_assignment = NULL;
444 if(remove_from_slfh) {
445 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
446 if(cassignment == assignment) {
448 prev_assignment->next = assignment->next;
450 assignment->secondlevel->assignments = assignment->next;
453 prev_assignment = cassignment;
455 prev_assignment = NULL;
457 if(remove_from_slfh != 2) {
458 prev_assignment = NULL;
459 for(cassignment = assignment->user->assignments; cassignment; cassignment = cassignment->unext) {
460 if(cassignment == assignment) {
462 prev_assignment->unext = assignment->unext;
464 assignment->user->assignments = assignment->unext;
467 prev_assignment = cassignment;
470 if(assignment->active) {
471 /* use another assignment - or fall back to default user host? */
473 if(hostserv_conf.fallback_other_assignment && assignment->user->assignments) {
474 /* try to find another assignment from same slfh first */
475 for(cassignment = assignment->secondlevel->assignments; cassignment; cassignment = cassignment->next) {
476 if(cassignment != assignment && cassignment->user == assignment->user)
479 /* use another tlfh assignment */
481 cassignment = assignment->user->assignments;
483 hs_activate_assignment(assignment->user, cassignment);
486 if(assignment->user->managements == NULL && assignment->user->assignments == NULL)
487 hs_del_user(assignment->user);
492 static struct hs_assignment *hs_get_assignment(struct hs_secondlevel *slfh, struct hs_user *user) {
493 struct hs_assignment *cassignment;
494 for(cassignment = slfh->assignments; cassignment; cassignment = cassignment->next) {
495 if(cassignment->user == user)
501 static struct hs_user *hs_get_user(struct handle_info *hi, int create) {
502 struct hs_user *cuser;
503 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
508 cuser = calloc(1, sizeof(*cuser));
510 cuser->next = hostserv_users;
511 hostserv_users = cuser;
517 static void hs_del_user(struct hs_user *user) {
518 if(user->managements) {
519 struct hs_manager *manager, *next_manager;
520 for(manager = user->managements; manager; manager = next_manager) {
521 next_manager = manager->unext;
522 hs_del_manager(manager, 2);
525 if(user->assignments) {
526 struct hs_assignment *assng, *next_assng;
527 for(assng = user->assignments; assng; assng = next_assng) {
528 next_assng = assng->unext;
529 hs_del_assignment(assng, 2);
532 struct hs_user *cuser, *prev_user = NULL;
533 for(cuser = hostserv_users; cuser; cuser = cuser->next) {
536 prev_user->next = user->next;
538 hostserv_users = user->next;
546 /* END OF MANAGEMENT FUNCTIONS */
548 static int check_management_access(struct handle_info *hi, struct hs_toplevel *tlfh, struct hs_secondlevel *slfh) {
551 if(hi->opserv_level >= hostserv_conf.toplevel_access)
553 struct hs_user *user = hs_get_user(hi, 0);
556 struct hs_manager *manager;
558 for(manager = user->managements; manager; manager = manager->next) {
559 if(manager->type == 2 && manager->object == slfh)
564 for(manager = user->managements; manager; manager = manager->next) {
565 if(manager->type == 1 && manager->object == tlfh)
572 struct hs_fakehost_info parse_fakehost_info(char *fakehost, int fix_name_case) {
573 struct hs_fakehost_info fhinfo;
575 memset(&fhinfo, 0, sizeof(fhinfo));
576 for(i = strlen(fakehost)-1; i >= 0; i--) {
577 if(!isalnum(fakehost[i]) && fakehost[i] != '.' && !(fakehost[i] == '*' && i == 0) && !strchr(HS_FAKEHOST_SPECIAL_CHARS, fakehost[i])) {
578 fhinfo.parse_state = HS_FHPARSE_INVALID;
582 fhinfo.slfh_name = fakehost;
583 fhinfo.tlfh_name = strchr(fakehost, '.');
584 if(!fhinfo.tlfh_name) {
585 fhinfo.parse_state = HS_FHPARSE_INVALID;
588 fhinfo.tlfh_name[0] = '\0';
590 if(strchr(fhinfo.tlfh_name, '.')) {
591 fhinfo.parse_state = HS_FHPARSE_INVALID;
593 fhinfo.tlfh_name[0] = '\0';
596 if(irccasecmp(fhinfo.slfh_name, "*"))
597 fhinfo.have_secondlevel = 1;
598 struct hs_toplevel *tlfh;
599 struct hs_secondlevel *slfh;
600 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
601 if(!irccasecmp(tlfh->fakehost, fhinfo.tlfh_name)) break;
606 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
609 if(fhinfo.have_secondlevel) {
610 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
611 if(!irccasecmp(slfh->fakehost, fhinfo.slfh_name)) break;
615 fhinfo.parse_state = HS_FHPARSE_UNKNOWN;
621 //simply copy the stored fakehosts over the given ones
622 strcpy(fhinfo.tlfh_name, fhinfo.tlfh->fakehost);
624 strcpy(fhinfo.slfh_name, fhinfo.slfh->fakehost);
626 fhinfo.parse_state = HS_FHPARSE_SUCCESS;
632 static void cmd_view_toplevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_toplevel *tlfh) {
633 reply("HSMSG_TOPLEVEL_FAKEHOSTS", tlfh->fakehost);
634 struct hs_secondlevel *slfh;
635 if(!tlfh->secondlevel)
636 reply("HSMSG_ASSIGNED_NONE");
638 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
639 struct hs_manager *cmanager;
641 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next)
643 struct hs_assignment *assignment;
645 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
647 reply("HSMSG_TOPLEVEL_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments, managers);
649 reply("HSMSG_MANAGERS_TOPLEVEL", tlfh->fakehost);
650 struct hs_manager *cmanager;
652 reply("HSMSG_ASSIGNED_NONE");
654 char managerBuf[351];
656 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
657 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
658 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
661 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
663 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
667 static void cmd_view_secondlevel_information(UNUSED_ARG(struct userNode *user), UNUSED_ARG(struct svccmd *cmd), struct hs_secondlevel *slfh) {
668 reply("HSMSG_FAKEHOST_ASSIGNMENTS", slfh->fakehost, slfh->toplevel->fakehost);
669 struct hs_assignment *assignment;
670 for(assignment = slfh->assignments; assignment; assignment = assignment->next) {
671 reply((assignment->active ? "HSMSG_FAKEHOST_ASSIGNMENT_ACTIVE" : "HSMSG_FAKEHOST_ASSIGNMENT"), assignment->user->hi->handle, assignment->user->hi->handle, slfh->fakehost, slfh->toplevel->fakehost);
673 reply("HSMSG_MANAGERS_FAKEHOST", slfh->fakehost, slfh->toplevel->fakehost);
674 struct hs_manager *cmanager;
676 reply("HSMSG_ASSIGNED_NONE");
678 char managerBuf[351];
680 for(cmanager = slfh->managers; cmanager; cmanager = cmanager->next) {
681 if(managerPos + strlen(cmanager->user->hi->handle) + 2 >= 350) {
682 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
685 managerPos += sprintf(managerBuf + managerPos, (managerPos ? ", %s" : "%s"), cmanager->user->hi->handle);
687 reply("HSMSG_MANAGERS_MANAGERS", managerBuf);
691 static MODCMD_FUNC(cmd_view) {
692 struct handle_info *hi;
693 if(argc >= 2 && !strchr(argv[1], '.')) {
694 if (!(hi = modcmd_get_handle_info(user, argv[1])))
696 } else if(argc >= 2) {
697 if (!(hi = user->handle_info)) {
698 reply("NSMSG_MUST_AUTH");
701 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 0);
702 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
703 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
705 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
706 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
710 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
711 reply("HSMSG_ACCESS_DENIED");
714 cmd_view_toplevel_information(user, cmd, fhinfo.tlfh);
717 if(!check_management_access(hi, fhinfo.tlfh, fhinfo.slfh)) {
718 reply("HSMSG_ACCESS_DENIED");
721 cmd_view_secondlevel_information(user, cmd, fhinfo.slfh);
725 if (!(hi = user->handle_info)) {
726 reply("NSMSG_MUST_AUTH");
730 struct hs_user *huser = hs_get_user(hi, 0);
731 reply("HSMSG_ASSIGNED_FAKEHOSTS", hi->handle);
734 struct hs_assignment *assignment;
735 for(assignment = huser->assignments; assignment; assignment = assignment->unext) {
736 reply((assignment->active ? "HSMSG_ASSIGNED_FAKEHOST_ACTTIVE" : "HSMSG_ASSIGNED_FAKEHOST"), assignment->secondlevel->fakehost, assignment->secondlevel->toplevel->fakehost);
739 if(assigncount && huser->hi == user->handle_info)
740 reply("HSMSG_ASSIGN_HOWTO");
743 reply("HSMSG_ASSIGNED_NONE");
744 if(user->handle_info == hi && hi->opserv_level >= hostserv_conf.toplevel_access) {
745 struct hs_toplevel *tlfh;
746 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
747 struct hs_secondlevel *slfh;
748 struct hs_assignment *assignment;
749 int slfhs = 0, assignments = 0;
750 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
752 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
755 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
757 reply("HSMSG_MANAGE_HOWTO");
758 } else if(huser && huser->managements) {
759 reply("HSMSG_MANAGED_FAKEHOSTS", hi->handle);
760 struct hs_manager *manager;
761 for(manager = huser->managements; manager; manager = manager->unext) {
762 if(manager->type == 1) {
763 struct hs_toplevel *tlfh = manager->object;
764 struct hs_secondlevel *slfh;
765 struct hs_assignment *assignment;
766 int slfhs = 0, assignments = 0;
767 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
769 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
772 reply("HSMSG_MANAGED_TOPLEVEL", tlfh->fakehost, slfhs, assignments);
775 for(manager = huser->managements; manager; manager = manager->next) {
776 if(manager->type == 2) {
777 struct hs_secondlevel *slfh = manager->object;
778 struct hs_toplevel *tlfh = slfh->toplevel;
779 //check if the user is already a manager of the tlfh
780 struct hs_manager *cmanager;
781 for(cmanager = tlfh->managers; cmanager; cmanager = cmanager->next) {
782 if(cmanager->user == huser) break;
784 if(cmanager) continue;
785 struct hs_assignment *assignment;
787 for(assignment = slfh->assignments; assignment; assignment = assignment->next)
789 reply("HSMSG_MANAGED_FAKEHOST", slfh->fakehost, tlfh->fakehost, assignments);
792 if(huser->hi == user->handle_info)
793 reply("HSMSG_MANAGE_HOWTO");
798 static MODCMD_FUNC(cmd_addhost) {
799 struct handle_info *hi;
800 if (!(hi = user->handle_info)) {
801 reply("NSMSG_MUST_AUTH");
804 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
805 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
806 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
809 if(!fhinfo.have_secondlevel) {
810 if(!check_management_access(hi, NULL, NULL)) {
811 reply("HSMSG_ACCESS_DENIED");
814 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
815 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
818 hs_add_toplevel(fhinfo.tlfh_name);
819 reply("HSMSG_FAKEHOST_TOPLEVEL_ADDED", fhinfo.tlfh_name);
822 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
825 if(!check_management_access(hi, fhinfo.tlfh, NULL)) {
826 reply("HSMSG_ACCESS_DENIED");
829 if(fhinfo.parse_state != HS_FHPARSE_UNKNOWN) {
830 reply("HSMSG_FAKEHOST_SECONDLEVEL_ALREADY_EXISTS", fhinfo.slfh_name, fhinfo.tlfh_name);
833 hs_add_secondlevel(fhinfo.tlfh, fhinfo.slfh_name);
834 reply("HSMSG_FAKEHOST_SECONDLEVEL_ADDED", fhinfo.slfh_name, fhinfo.tlfh_name);
839 static MODCMD_FUNC(cmd_delhost) {
840 struct handle_info *hi;
841 if (!(hi = user->handle_info)) {
842 reply("NSMSG_MUST_AUTH");
845 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
846 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
847 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
849 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
850 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
854 if(!check_management_access(hi, (hostserv_conf.manager_can_del_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
855 reply("HSMSG_ACCESS_DENIED");
858 hs_del_toplevel(fhinfo.tlfh);
859 reply("HSMSG_FAKEHOST_TOPLEVEL_DELETED", fhinfo.tlfh_name);
861 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_del_secondlevel ? fhinfo.slfh : NULL))) {
862 reply("HSMSG_ACCESS_DENIED");
865 hs_del_secondlevel(fhinfo.slfh, 1);
866 reply("HSMSG_FAKEHOST_SECONDLEVEL_DELETED", fhinfo.slfh_name, fhinfo.tlfh_name);
871 static MODCMD_FUNC(cmd_renamehost) {
872 struct handle_info *hi;
873 if (!(hi = user->handle_info)) {
874 reply("NSMSG_MUST_AUTH");
878 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
879 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
880 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
882 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
883 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
887 struct hs_fakehost_info new_fhinfo = parse_fakehost_info(argv[2], 0);
888 if(new_fhinfo.parse_state == HS_FHPARSE_INVALID) {
889 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
891 } 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)))) {
892 reply("HSMSG_FAKEHOST_TOPLEVEL_ALREADY_EXISTS", new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
897 if(!check_management_access(hi, (hostserv_conf.manager_can_rename_toplevel ? fhinfo.tlfh : NULL), NULL)) { /* manager access is enough to delete whole toplevel? */
898 reply("HSMSG_ACCESS_DENIED");
901 if(fhinfo.have_secondlevel) {
902 //can't rename toplevel into secondlevel fakehost!
903 new_fhinfo.tlfh_name--;
904 new_fhinfo.tlfh_name[0] = '.';
905 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
908 if(strcmp(new_fhinfo.tlfh_name, fhinfo.tlfh->fakehost))
909 hs_rename_toplevel(fhinfo.tlfh, new_fhinfo.tlfh_name);
910 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
912 if(!check_management_access(hi, fhinfo.tlfh, (hostserv_conf.manager_can_rename_secondlevel ? fhinfo.slfh : NULL))) {
913 reply("HSMSG_ACCESS_DENIED");
916 if(irccasecmp(new_fhinfo.tlfh_name, fhinfo.tlfh_name)) {
917 //can't rename toplevel and secondlevel fakehost with one command!
918 new_fhinfo.tlfh_name--;
919 new_fhinfo.tlfh_name[0] = '.';
920 reply("HSMSG_TOPLEVEL_INVALID", new_fhinfo.slfh_name);
923 if(strcmp(new_fhinfo.slfh_name, fhinfo.slfh->fakehost))
924 hs_rename_secondlevel(fhinfo.slfh, new_fhinfo.slfh_name);
925 reply("HSMSG_FAKEHOST_RENAMED", fhinfo.slfh_name, fhinfo.tlfh_name, new_fhinfo.slfh_name, new_fhinfo.tlfh_name);
930 static MODCMD_FUNC(cmd_addmanager) {
931 struct handle_info *hi;
933 if(!strchr(argv[1], '.')) {
934 if (!(hi = modcmd_get_handle_info(user, argv[1])))
938 if (!(hi = modcmd_get_handle_info(user, argv[2])))
942 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
943 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
944 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
946 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
947 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
950 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
951 reply("HSMSG_ACCESS_DENIED");
954 struct hs_user *huser = hs_get_user(hi, 1);
955 struct hs_manager *manager;
957 for(manager = huser->managements; manager; manager = manager->next) {
958 if(manager->type == 2 && manager->object == fhinfo.slfh) {
959 reply("HSMSG_MANAGER_ALREADY", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
964 for(manager = huser->managements; manager; manager = manager->next) {
965 if(manager->type == 1 && manager->object == fhinfo.tlfh) {
966 reply("HSMSG_MANAGER_ALREADY", hi->handle, "*", fhinfo.tlfh_name);
971 hs_add_manager_secondlevel(fhinfo.slfh, huser);
973 hs_add_manager_toplevel(fhinfo.tlfh, huser);
974 //remove from all slfh's
975 struct hs_manager *next_manager;
976 struct hs_secondlevel *slfh;
977 for(manager = huser->managements; manager; manager = next_manager) {
978 next_manager = manager->next;
979 if(manager->type == 2) {
980 slfh = manager->object;
981 if(slfh->toplevel == fhinfo.tlfh)
982 hs_del_manager(manager, 1);
986 reply("HSMSG_MANAGER_ADDED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
990 static MODCMD_FUNC(cmd_delmanager) {
991 struct handle_info *hi;
993 if(!strchr(argv[1], '.')) {
994 if (!(hi = modcmd_get_handle_info(user, argv[1])))
998 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1002 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1003 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1004 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1006 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
1007 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1010 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1011 reply("HSMSG_ACCESS_DENIED");
1014 struct hs_user *huser = hs_get_user(hi, 0);
1015 struct hs_manager *manager;
1017 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1021 for(manager = huser->managements; manager; manager = manager->unext) {
1022 if(manager->type == 2 && manager->object == fhinfo.slfh)
1026 reply("HSMSG_MANAGER_NOT", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1030 for(manager = huser->managements; manager; manager = manager->unext) {
1031 if(manager->type == 1 && manager->object == fhinfo.tlfh)
1035 reply("HSMSG_MANAGER_NOT", hi->handle, "*", fhinfo.tlfh_name);
1039 hs_del_manager(manager, 1);
1040 reply("HSMSG_MANAGER_DELETED", hi->handle, fhinfo.slfh_name, fhinfo.tlfh_name);
1044 static MODCMD_FUNC(cmd_set) {
1045 struct handle_info *hi;
1046 struct hs_user *hs_user;
1047 struct hs_assignment *assignment;
1048 struct hs_toplevel *tlfh;
1049 struct hs_secondlevel *slfh;
1051 if (!(hi = user->handle_info)) {
1052 reply("NSMSG_MUST_AUTH");
1055 hs_user = hs_get_user(hi, 0);
1057 return 0; //nothing to do here
1058 if(!strcmp(argv[1], "*")) {
1059 hs_activate_assignment(hs_user, NULL);
1062 struct hs_fakehost_info fhinfo = parse_fakehost_info(argv[1], 1);
1063 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1064 reply("HSMSG_TOPLEVEL_INVALID", argv[1]);
1066 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN) {
1067 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1070 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1071 slfh = assignment->secondlevel;
1072 tlfh = slfh->toplevel;
1073 if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) {
1074 hs_activate_assignment(hs_user, assignment);
1075 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1079 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1084 static MODCMD_FUNC(cmd_assign) {
1085 struct handle_info *hi;
1087 if(!strchr(argv[1], '.')) {
1088 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1092 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1096 if (!user->handle_info) {
1097 reply("NSMSG_MUST_AUTH");
1100 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1101 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1102 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1104 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1105 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1108 struct hs_user *hs_user = hs_get_user(hi, 1);
1109 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1110 reply("HSMSG_ACCESS_DENIED");
1113 if(hs_get_assignment(fhinfo.slfh, hs_user)) {
1114 reply("HSMSG_FAKEHOST_ASSIGNED", fhinfo.slfh_name, fhinfo.tlfh_name);
1117 hs_add_assignment(fhinfo.slfh, hs_user, HS_ASSIGNMENTSTATE_AUTO);
1118 reply("HSMSG_FAKEHOST_ASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1122 static MODCMD_FUNC(cmd_unassign) {
1123 struct handle_info *hi;
1125 if(!strchr(argv[1], '.')) {
1126 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1130 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1134 if (!user->handle_info) {
1135 reply("NSMSG_MUST_AUTH");
1138 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1139 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1140 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1142 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1143 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1146 struct hs_assignment *assignment;
1147 struct hs_user *hs_user = hs_get_user(hi, 0);
1149 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1152 if(!check_management_access(user->handle_info, fhinfo.tlfh, fhinfo.slfh)) {
1153 reply("HSMSG_ACCESS_DENIED");
1156 if(!(assignment = hs_get_assignment(fhinfo.slfh, hs_user))) {
1157 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1160 hs_del_assignment(assignment, 1);
1161 reply("HSMSG_FAKEHOST_UNASSIGN_SUCCESS", fhinfo.slfh_name, fhinfo.tlfh_name);
1165 static MODCMD_FUNC(cmd_oset) {
1166 struct handle_info *hi;
1168 struct hs_assignment *assgn;
1169 if(!strchr(argv[1], '.')) {
1170 if (!(hi = modcmd_get_handle_info(user, argv[1])))
1174 if (!(hi = modcmd_get_handle_info(user, argv[2])))
1178 if (!user->handle_info) {
1179 reply("NSMSG_MUST_AUTH");
1182 if(!strcmp(argv[1], "*")) {
1183 if(!check_management_access(user->handle_info)) {
1184 reply("HSMSG_ACCESS_DENIED");
1187 hs_activate_assignment(hs_user, NULL);
1190 struct hs_fakehost_info fhinfo = parse_fakehost_info(fakehost, 1);
1191 if(fhinfo.parse_state == HS_FHPARSE_INVALID) {
1192 reply("HSMSG_TOPLEVEL_INVALID", fakehost);
1194 } else if(fhinfo.parse_state == HS_FHPARSE_UNKNOWN || !fhinfo.slfh) {
1195 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1198 struct hs_user *hs_user = hs_get_user(hi, 1);
1199 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))) {
1200 reply("HSMSG_ACCESS_DENIED");
1203 for(assignment = hs_user->assignments; assignment; assignment = assignment->unext) {
1204 slfh = assignment->secondlevel;
1205 tlfh = slfh->toplevel;
1206 if(tlfh == fhinfo.tlfh && slfh == fhinfo.slfh) {
1207 hs_activate_assignment(hs_user, assignment);
1208 reply("HSMSG_FAKEHOST_SET_SUCCESS", slfh->fakehost, tlfh->fakehost);
1212 reply("HSMSG_UNKNOWN_FAKEHOST", fhinfo.slfh_name, fhinfo.tlfh_name);
1217 static void hostserv_conf_read(void) {
1221 str = "modules/hostserv";
1222 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1223 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1227 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1228 if(hostserv_conf.nick && strcmp(hostserv_conf.nick, str)) {
1231 hostserv_conf.nick = str;
1233 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1234 hostserv_conf.modes = (str ? str : NULL);
1236 str = database_get_data(conf_node, "toplevel_access", RECDB_QSTRING);
1237 unsigned int toplevel_access = atoi(str);
1238 hostserv_conf.toplevel_access = (toplevel_access ? toplevel_access : 600);
1240 str = database_get_data(conf_node, "fallback_other_assignment", RECDB_QSTRING);
1241 hostserv_conf.fallback_other_assignment = (atoi(str) ? 1 : 0);
1243 str = database_get_data(conf_node, "manager_can_del_toplevel", RECDB_QSTRING);
1244 hostserv_conf.manager_can_del_toplevel = (atoi(str) ? 1 : 0);
1246 str = database_get_data(conf_node, "manager_can_del_secondlevel", RECDB_QSTRING);
1247 hostserv_conf.manager_can_del_secondlevel = (atoi(str) ? 1 : 0);
1249 str = database_get_data(conf_node, "manager_can_rename_toplevel", RECDB_QSTRING);
1250 hostserv_conf.manager_can_rename_toplevel = (atoi(str) ? 1 : 0);
1252 str = database_get_data(conf_node, "manager_can_rename_secondlevel", RECDB_QSTRING);
1253 hostserv_conf.manager_can_rename_secondlevel = (atoi(str) ? 1 : 0);
1255 str = database_get_data(conf_node, "manager_toplevel_can_oset", RECDB_QSTRING);
1256 hostserv_conf.manager_toplevel_can_oset = (atoi(str) ? 1 : 0);
1258 str = database_get_data(conf_node, "manager_secondlevel_can_oset", RECDB_QSTRING);
1259 hostserv_conf.manager_secondlevel_can_oset = (atoi(str) ? 1 : 0);
1262 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra));
1263 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra));
1265 static int hostserv_saxdb_read_toplevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1266 struct record_data *rd = data;
1267 struct hs_toplevel *tlfh;
1268 struct hs_manager *managerTL;
1269 struct hs_user *user;
1270 struct dict *object;
1272 if (rd->type == RECDB_OBJECT) {
1273 dict_t db = GET_RECORD_OBJECT(rd);
1276 tlfh = hs_add_toplevel(name);
1278 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1279 for (it = dict_first(object); it; it = iter_next(it)) {
1280 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1281 //rd = iter_data(it);
1282 /* nothing in here, yet */
1283 managerTL = hs_add_manager_toplevel(tlfh, user);
1284 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1285 managerTL->active = 1;
1287 managerTL->active = 0;
1291 if ((object = database_get_data(db, KEY_SECONDLEVEL, RECDB_OBJECT)))
1292 dict_foreach(object, hostserv_saxdb_read_secondlevel, tlfh);
1297 static int hostserv_saxdb_read_secondlevel(const char *name, void *data, UNUSED_ARG(void *extra)) {
1298 struct record_data *rd = data;
1299 struct hs_toplevel *tlfh = extra;
1300 struct hs_secondlevel *slfh;
1301 struct hs_manager *managerSL;
1302 struct hs_user *user;
1303 struct dict *object;
1305 if (rd->type == RECDB_OBJECT) {
1306 dict_t db = GET_RECORD_OBJECT(rd);
1309 slfh = hs_add_secondlevel(tlfh, name);
1311 if ((object = database_get_data(db, KEY_MANAGERS, RECDB_OBJECT))) {
1312 for (it = dict_first(object); it; it = iter_next(it)) {
1313 user = hs_get_user(get_handle_info(iter_key(it)), 1);
1314 //rd = iter_data(it);
1315 /* nothing in here, yet */
1316 managerSL = hs_add_manager_secondlevel(slfh, user);
1317 if (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING))
1318 managerSL->active = 1;
1320 managerSL->active = 0;
1324 if ((object = database_get_data(db, KEY_ASSIGNMENTS, RECDB_OBJECT)))
1325 dict_foreach(object, hostserv_saxdb_read_assignments, slfh);
1330 static int hostserv_saxdb_read_assignments(const char *name, void *data, UNUSED_ARG(void *extra)) {
1331 struct record_data *rd = data;
1332 struct hs_secondlevel *slfh = extra;
1333 struct hs_user *user;
1336 if (rd->type == RECDB_OBJECT) {
1337 dict_t db = GET_RECORD_OBJECT(rd);
1339 user = hs_get_user(get_handle_info(name), 1);
1340 active = (database_get_data(db, KEY_ACTIVE, RECDB_QSTRING) ? HS_ASSIGNMENTSTATE_ON : HS_ASSIGNMENTSTATE_OFF);
1342 hs_add_assignment(slfh, user, active);
1349 hostserv_saxdb_read(struct dict *db)
1351 struct dict *object;
1353 if ((object = database_get_data(db, KEY_TOPLEVEL, RECDB_OBJECT)))
1354 dict_foreach(object, hostserv_saxdb_read_toplevel, NULL);
1360 hostserv_saxdb_write(struct saxdb_context *ctx)
1362 struct hs_toplevel *tlfh;
1363 struct hs_secondlevel *slfh;
1364 struct hs_assignment *assng;
1365 struct hs_manager *manager;
1367 saxdb_start_record(ctx, KEY_TOPLEVEL, 1);
1368 for(tlfh = toplevels; tlfh; tlfh = tlfh->next) {
1369 saxdb_start_record(ctx, tlfh->fakehost, 1);
1371 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1372 for(manager = tlfh->managers; manager; manager = manager->next) {
1373 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1374 //additional manager information?
1376 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1377 saxdb_end_record(ctx);
1379 saxdb_end_record(ctx);
1381 saxdb_start_record(ctx, KEY_SECONDLEVEL, 1);
1382 for(slfh = tlfh->secondlevel; slfh; slfh = slfh->next) {
1383 saxdb_start_record(ctx, slfh->fakehost, 1);
1385 saxdb_start_record(ctx, KEY_MANAGERS, 1);
1386 for(manager = slfh->managers; manager; manager = manager->next) {
1387 saxdb_start_record(ctx, manager->user->hi->handle, 0);
1388 //additional manager information?
1390 saxdb_write_int(ctx, KEY_ACTIVE, manager->active);
1391 saxdb_end_record(ctx);
1393 saxdb_end_record(ctx);
1395 saxdb_start_record(ctx, KEY_ASSIGNMENTS, 1);
1396 for(assng = slfh->assignments; assng; assng = assng->next) {
1397 saxdb_start_record(ctx, assng->user->hi->handle, 0);
1398 //additional assignment information?
1400 saxdb_write_int(ctx, KEY_ACTIVE, assng->active);
1401 saxdb_end_record(ctx);
1403 saxdb_end_record(ctx);
1405 saxdb_end_record(ctx);
1407 saxdb_end_record(ctx);
1409 saxdb_end_record(ctx);
1411 saxdb_end_record(ctx);
1417 static void hostserv_db_cleanup(void) {
1421 int hostserv_init() {
1422 HS_LOG = log_register_type("HostServ", "file:hostserv.log");
1424 const char *nick, *modes;
1425 if((nick = conf_get_data("modules/hostserv/nick", RECDB_QSTRING))) {
1426 modes = conf_get_data("modules/hostserv/modes", RECDB_QSTRING);
1427 hostserv = AddLocalUser(nick, nick, NULL, "Host Service", modes);
1428 hostserv_service = service_register(hostserv);
1429 hostserv_service->trigger = '*';
1432 conf_register_reload(hostserv_conf_read);
1433 reg_exit_func(hostserv_db_cleanup);
1434 saxdb_register("HostServ", hostserv_saxdb_read, hostserv_saxdb_write);
1435 hostserv_module = module_register("HostServ", HS_LOG, "mod-hostserv.help", NULL);
1436 modcmd_register(hostserv_module, "view", cmd_view, 0, MODCMD_REQUIRE_AUTHED, NULL);
1437 modcmd_register(hostserv_module, "addmanager", cmd_addmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1438 modcmd_register(hostserv_module, "delmanager", cmd_delmanager, 3, MODCMD_REQUIRE_AUTHED, NULL);
1439 modcmd_register(hostserv_module, "set", cmd_set, 2, MODCMD_REQUIRE_AUTHED, NULL);
1440 modcmd_register(hostserv_module, "assign", cmd_assign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1441 modcmd_register(hostserv_module, "unassign", cmd_unassign, 3, MODCMD_REQUIRE_AUTHED, NULL);
1442 modcmd_register(hostserv_module, "addhost", cmd_addhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1443 modcmd_register(hostserv_module, "delhost", cmd_delhost, 2, MODCMD_REQUIRE_AUTHED, NULL);
1444 modcmd_register(hostserv_module, "renamehost", cmd_renamehost, 3, MODCMD_REQUIRE_AUTHED, NULL);
1445 modcmd_register(hostserv_module, "oset", cmd_oset, 3, MODCMD_REQUIRE_AUTHED, NULL);
1446 message_register_table(msgtab);
1450 int hostserv_finalize(void) {
1454 str = "modules/hostserv";
1455 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
1456 log_module(HS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
1460 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
1461 if (str) hostserv_conf.nick = str;
1463 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
1464 if (str) hostserv_conf.modes = str;