/[cvs]/eggdrop1.8/src/userrec.c
ViewVC logotype

Contents of /eggdrop1.8/src/userrec.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Sun Oct 24 13:22:40 2010 UTC (9 years, 1 month ago) by pseudo
Branch: MAIN
CVS Tags: HEAD
Branch point for: gettext
Changes since 1.1: +3 -4 lines
File MIME type: text/x-chdr
Removed the never-give-up, sort-users and kick-fun/ban-fun variables. Sorting users shouldn't be a challenge for CPUs nowadays. The rest are rarely used and can be scripted.

1 /*
2 * userrec.c -- handles:
3 * add_q() del_q() str2flags() flags2str() str2chflags() chflags2str()
4 * a bunch of functions to find and change user records
5 * change and check user (and channel-specific) flags
6 *
7 * $Id: userrec.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
8 */
9 /*
10 * Copyright (C) 1997 Robey Pointer
11 * Copyright (C) 1999 - 2010 Eggheads Development Team
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include <sys/stat.h>
29 #include "main.h"
30 #include "users.h"
31 #include "chan.h"
32 #include "modules.h"
33 #include "tandem.h"
34
35 extern struct dcc_t *dcc;
36 extern struct chanset_t *chanset;
37 extern int default_flags, default_uflags, quiet_save, dcc_total, share_greet;
38 extern char userfile[], ver[], botnetnick[];
39 extern time_t now;
40
41 int noshare = 1; /* don't send out to sharebots */
42 struct userrec *userlist = NULL; /* user records are stored here */
43 struct userrec *lastuser = NULL; /* last accessed user record */
44 maskrec *global_bans = NULL, *global_exempts = NULL, *global_invites = NULL;
45 struct igrec *global_ign = NULL;
46 int cache_hit = 0, cache_miss = 0; /* temporary cache accounting */
47 int strict_host = 1;
48 int userfile_perm = 0600; /* Userfile permissions
49 * (default rw-------) */
50
51 void *_user_malloc(int size, const char *file, int line)
52 {
53 #ifdef DEBUG_MEM
54 char x[1024];
55 const char *p;
56
57 p = strrchr(file, '/');
58 simple_sprintf(x, "userrec.c:%s", p ? p + 1 : file);
59 return n_malloc(size, x, line);
60 #else
61 return nmalloc(size);
62 #endif
63 }
64
65 void *_user_realloc(void *ptr, int size, const char *file, int line)
66 {
67 #ifdef DEBUG_MEM
68 char x[1024];
69 const char *p;
70
71 p = strrchr(file, '/');
72 simple_sprintf(x, "userrec.c:%s", p ? p + 1 : file);
73 return n_realloc(ptr, size, x, line);
74 #else
75 return nrealloc(ptr, size);
76 #endif
77 }
78
79 inline int expmem_mask(struct maskrec *m)
80 {
81 int result = 0;
82
83 for (; m; m = m->next) {
84 result += sizeof(struct maskrec);
85 result += strlen(m->mask) + 1;
86 if (m->user)
87 result += strlen(m->user) + 1;
88 if (m->desc)
89 result += strlen(m->desc) + 1;
90 }
91
92 return result;
93 }
94
95 /* Memory we should be using
96 */
97 int expmem_users()
98 {
99 int tot;
100 struct userrec *u;
101 struct chanuserrec *ch;
102 struct chanset_t *chan;
103 struct user_entry *ue;
104 struct igrec *i;
105
106 tot = 0;
107 for (u = userlist; u; u = u->next) {
108 for (ch = u->chanrec; ch; ch = ch->next) {
109 tot += sizeof(struct chanuserrec);
110
111 if (ch->info != NULL)
112 tot += strlen(ch->info) + 1;
113 }
114 tot += sizeof(struct userrec);
115
116 for (ue = u->entries; ue; ue = ue->next) {
117 tot += sizeof(struct user_entry);
118
119 if (ue->name) {
120 tot += strlen(ue->name) + 1;
121 tot += list_type_expmem(ue->u.list);
122 } else
123 tot += ue->type->expmem(ue);
124 }
125 }
126 /* Account for each channel's masks */
127 for (chan = chanset; chan; chan = chan->next) {
128
129 /* Account for each channel's ban-list user */
130 tot += expmem_mask(chan->bans);
131
132 /* Account for each channel's exempt-list user */
133 tot += expmem_mask(chan->exempts);
134
135 /* Account for each channel's invite-list user */
136 tot += expmem_mask(chan->invites);
137 }
138
139 tot += expmem_mask(global_bans);
140 tot += expmem_mask(global_exempts);
141 tot += expmem_mask(global_invites);
142
143 for (i = global_ign; i; i = i->next) {
144 tot += sizeof(struct igrec);
145
146 tot += strlen(i->igmask) + 1;
147 if (i->user)
148 tot += strlen(i->user) + 1;
149 if (i->msg)
150 tot += strlen(i->msg) + 1;
151 }
152 return tot;
153 }
154
155 int count_users(struct userrec *bu)
156 {
157 int tot = 0;
158 struct userrec *u;
159
160 for (u = bu; u; u = u->next)
161 tot++;
162 return tot;
163 }
164
165 /* Removes a username prefix (~+-^=) from a userhost.
166 * e.g, "nick!~user@host" -> "nick!user@host"
167 */
168 char *fixfrom(char *s)
169 {
170 static char uhost[UHOSTLEN];
171 char *p = uhost;
172
173 if (!s || !*s || strict_host)
174 return s;
175
176 while (*s) {
177 *p++ = *s;
178 if (*s == '!' && strchr("~+-^=", s[1]) && s[2] != '@') {
179 strcpy(p, s + 2);
180 return uhost;
181 }
182 s++;
183 }
184
185 *p = 0;
186 return uhost;
187 }
188
189 struct userrec *check_dcclist_hand(char *handle)
190 {
191 int i;
192
193 for (i = 0; i < dcc_total; i++)
194 if (!egg_strcasecmp(dcc[i].nick, handle))
195 return dcc[i].user;
196 return NULL;
197 }
198
199 struct userrec *get_user_by_handle(struct userrec *bu, char *handle)
200 {
201 struct userrec *u, *ret;
202
203 if (!handle)
204 return NULL;
205 /* FIXME: This should be done outside of this function. */
206 rmspace(handle);
207 if (!handle[0] || (handle[0] == '*'))
208 return NULL;
209 if (bu == userlist) {
210 if (lastuser && !egg_strcasecmp(lastuser->handle, handle)) {
211 cache_hit++;
212 return lastuser;
213 }
214 ret = check_dcclist_hand(handle);
215 if (ret) {
216 cache_hit++;
217 return ret;
218 }
219 ret = check_chanlist_hand(handle);
220 if (ret) {
221 cache_hit++;
222 return ret;
223 }
224 cache_miss++;
225 }
226 for (u = bu; u; u = u->next)
227 if (!egg_strcasecmp(u->handle, handle)) {
228 if (bu == userlist)
229 lastuser = u;
230 return u;
231 }
232 return NULL;
233 }
234
235 /* Fix capitalization, etc
236 */
237 void correct_handle(char *handle)
238 {
239 struct userrec *u;
240
241 u = get_user_by_handle(userlist, handle);
242 if (u == NULL || handle == u->handle)
243 return;
244 strcpy(handle, u->handle);
245 }
246
247 /* This will be usefull in a lot of places, much more code re-use so we
248 * endup with a smaller executable bot. <cybah>
249 */
250 void clear_masks(maskrec *m)
251 {
252 maskrec *temp = NULL;
253
254 for (; m; m = temp) {
255 temp = m->next;
256 if (m->mask)
257 nfree(m->mask);
258 if (m->user)
259 nfree(m->user);
260 if (m->desc)
261 nfree(m->desc);
262 nfree(m);
263 }
264 }
265
266 void clear_userlist(struct userrec *bu)
267 {
268 struct userrec *u, *v;
269 int i;
270
271 for (u = bu; u; u = v) {
272 v = u->next;
273 freeuser(u);
274 }
275 if (userlist == bu) {
276 struct chanset_t *cst;
277
278 for (i = 0; i < dcc_total; i++)
279 dcc[i].user = NULL;
280 clear_chanlist();
281 lastuser = NULL;
282
283 while (global_ign)
284 delignore(global_ign->igmask);
285
286 clear_masks(global_bans);
287 clear_masks(global_exempts);
288 clear_masks(global_invites);
289 global_exempts = global_invites = global_bans = NULL;
290
291 for (cst = chanset; cst; cst = cst->next) {
292 clear_masks(cst->bans);
293 clear_masks(cst->exempts);
294 clear_masks(cst->invites);
295
296 cst->bans = cst->exempts = cst->invites = NULL;
297 }
298 }
299 /* Remember to set your userlist to NULL after calling this */
300 }
301
302 /* Find CLOSEST host match
303 * (if "*!*@*" and "*!*@*clemson.edu" both match, use the latter!)
304 *
305 * Checks the chanlist first, to possibly avoid needless search.
306 */
307 struct userrec *get_user_by_host(char *host)
308 {
309 struct userrec *u, *ret;
310 struct list_type *q;
311 int cnt, i;
312 char host2[UHOSTLEN];
313
314 if (host == NULL)
315 return NULL;
316 rmspace(host);
317 if (!host[0])
318 return NULL;
319 ret = check_chanlist(host);
320 cnt = 0;
321 if (ret != NULL) {
322 cache_hit++;
323 return ret;
324 }
325 cache_miss++;
326 strncpyz(host2, host, sizeof host2);
327 host = fixfrom(host);
328 for (u = userlist; u; u = u->next) {
329 q = get_user(&USERENTRY_HOSTS, u);
330 for (; q; q = q->next) {
331 i = match_useraddr(q->extra, host);
332 if (i > cnt) {
333 ret = u;
334 cnt = i;
335 }
336 }
337 }
338 if (ret != NULL) {
339 lastuser = ret;
340 set_chanlist(host2, ret);
341 }
342 return ret;
343 }
344
345 /* use fixfrom() or dont? (drummer)
346 */
347 struct userrec *get_user_by_equal_host(char *host)
348 {
349 struct userrec *u;
350 struct list_type *q;
351
352 for (u = userlist; u; u = u->next)
353 for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next)
354 if (!rfc_casecmp(q->extra, host))
355 return u;
356 return NULL;
357 }
358
359 /* Try: pass_match_by_host("-",host)
360 * will return 1 if no password is set for that host
361 */
362 int u_pass_match(struct userrec *u, char *pass)
363 {
364 char *cmp, new[32];
365
366 if (!u)
367 return 0;
368 cmp = get_user(&USERENTRY_PASS, u);
369 if (!cmp && (!pass[0] || (pass[0] == '-')))
370 return 1;
371 if (!cmp || !pass || !pass[0] || (pass[0] == '-'))
372 return 0;
373 if (u->flags & USER_BOT) {
374 if (!strcmp(cmp, pass))
375 return 1;
376 } else {
377 if (strlen(pass) > 30)
378 pass[30] = 0;
379 encrypt_pass(pass, new);
380 if (!strcmp(cmp, new))
381 return 1;
382 }
383 return 0;
384 }
385
386 int write_user(struct userrec *u, FILE *f, int idx)
387 {
388 char s[181];
389 long tv;
390 struct chanuserrec *ch;
391 struct chanset_t *cst;
392 struct user_entry *ue;
393 struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
394
395 fr.global = u->flags;
396
397 fr.udef_global = u->flags_udef;
398 build_flags(s, &fr, NULL);
399 if (fprintf(f, "%-10s - %-24s\n", u->handle, s) == EOF)
400 return 0;
401 for (ch = u->chanrec; ch; ch = ch->next) {
402 cst = findchan_by_dname(ch->channel);
403 if (cst && ((idx < 0) || channel_shared(cst))) {
404 if (idx >= 0) {
405 fr.match = (FR_CHAN | FR_BOT);
406 get_user_flagrec(dcc[idx].user, &fr, ch->channel);
407 } else
408 fr.chan = BOT_SHARE;
409 if ((fr.chan & BOT_SHARE) || (fr.bot & BOT_GLOBAL)) {
410 fr.match = FR_CHAN;
411 fr.chan = ch->flags;
412 fr.udef_chan = ch->flags_udef;
413 build_flags(s, &fr, NULL);
414 tv = ch->laston;
415 if (fprintf(f, "! %-20s %lu %-10s %s\n", ch->channel, tv, s,
416 (((idx < 0) || share_greet) && ch->info) ? ch->info : "") == EOF)
417 return 0;
418 }
419 }
420 }
421 for (ue = u->entries; ue; ue = ue->next) {
422 if (ue->name) {
423 struct list_type *lt;
424
425 for (lt = ue->u.list; lt; lt = lt->next)
426 if (fprintf(f, "--%s %s\n", ue->name, lt->extra) == EOF)
427 return 0;
428 } else if (!ue->type->write_userfile(f, u, ue))
429 return 0;
430 }
431 return 1;
432 }
433
434 int write_ignores(FILE *f, int idx)
435 {
436 struct igrec *i;
437 char *mask;
438 long expire, added;
439
440 if (global_ign)
441 if (fprintf(f, IGNORE_NAME " - -\n") == EOF) /* Daemus */
442 return 0;
443 for (i = global_ign; i; i = i->next) {
444 mask = str_escape(i->igmask, ':', '\\');
445 expire = i->expire;
446 added = i->added;
447 if (!mask ||
448 fprintf(f, "- %s:%s%lu:%s:%lu:%s\n", mask,
449 (i->flags & IGREC_PERM) ? "+" : "", expire,
450 i->user ? i->user : botnetnick, added,
451 i->msg ? i->msg : "") == EOF) {
452 if (mask)
453 nfree(mask);
454 return 0;
455 }
456 nfree(mask);
457 }
458 return 1;
459 }
460
461 int sort_compare(struct userrec *a, struct userrec *b)
462 {
463 /* Order by flags, then alphabetically
464 * first bots: +h / +a / +l / other bots
465 * then users: +n / +m / +o / other users
466 * return true if (a > b)
467 */
468 if (a->flags & b->flags & USER_BOT) {
469 if (~bot_flags(a) & bot_flags(b) & BOT_HUB)
470 return 1;
471 if (bot_flags(a) & ~bot_flags(b) & BOT_HUB)
472 return 0;
473 if (~bot_flags(a) & bot_flags(b) & BOT_ALT)
474 return 1;
475 if (bot_flags(a) & ~bot_flags(b) & BOT_ALT)
476 return 0;
477 if (~bot_flags(a) & bot_flags(b) & BOT_LEAF)
478 return 1;
479 if (bot_flags(a) & ~bot_flags(b) & BOT_LEAF)
480 return 0;
481 } else {
482 if (~a->flags & b->flags & USER_BOT)
483 return 1;
484 if (a->flags & ~b->flags & USER_BOT)
485 return 0;
486 if (~a->flags & b->flags & USER_OWNER)
487 return 1;
488 if (a->flags & ~b->flags & USER_OWNER)
489 return 0;
490 if (~a->flags & b->flags & USER_MASTER)
491 return 1;
492 if (a->flags & ~b->flags & USER_MASTER)
493 return 0;
494 if (~a->flags & b->flags & USER_OP)
495 return 1;
496 if (a->flags & ~b->flags & USER_OP)
497 return 0;
498 if (~a->flags & b->flags & USER_HALFOP)
499 return 1;
500 if (a->flags & ~b->flags & USER_HALFOP)
501 return 0;
502 }
503 return (egg_strcasecmp(a->handle, b->handle) > 0);
504 }
505
506 void sort_userlist()
507 {
508 int again;
509 struct userrec *last, *p, *c, *n;
510
511 again = 1;
512 last = NULL;
513 while ((userlist != last) && (again)) {
514 p = NULL;
515 c = userlist;
516 n = c->next;
517 again = 0;
518 while (n != last) {
519 if (sort_compare(c, n)) {
520 again = 1;
521 c->next = n->next;
522 n->next = c;
523 if (p == NULL)
524 userlist = n;
525 else
526 p->next = n;
527 }
528 p = c;
529 c = n;
530 n = n->next;
531 }
532 last = c;
533 }
534 }
535
536 /* Rewrite the entire user file. Call USERFILE hook as well, probably
537 * causing the channel file to be rewritten as well.
538 */
539 void write_userfile(int idx)
540 {
541 FILE *f;
542 char *new_userfile;
543 char s1[81];
544 time_t tt;
545 struct userrec *u;
546 int ok;
547
548 if (userlist == NULL)
549 return; /* No point in saving userfile */
550
551 new_userfile = nmalloc(strlen(userfile) + 5);
552 sprintf(new_userfile, "%s~new", userfile);
553
554 f = fopen(new_userfile, "w");
555 chmod(new_userfile, userfile_perm);
556 if (f == NULL) {
557 putlog(LOG_MISC, "*", USERF_ERRWRITE);
558 nfree(new_userfile);
559 return;
560 }
561 if (!quiet_save)
562 putlog(LOG_MISC, "*", USERF_WRITING);
563
564 sort_userlist();
565 tt = now;
566 strcpy(s1, ctime(&tt));
567 fprintf(f, "#4v: %s -- %s -- written %s", ver, botnetnick, s1);
568 ok = 1;
569 for (u = userlist; u && ok; u = u->next)
570 if (!write_user(u, f, idx))
571 ok = 0;
572 if (!ok || !write_ignores(f, -1) || fflush(f)) {
573 putlog(LOG_MISC, "*", "%s (%s)", USERF_ERRWRITE, strerror(ferror(f)));
574 fclose(f);
575 nfree(new_userfile);
576 return;
577 }
578 fclose(f);
579 call_hook(HOOK_USERFILE);
580 movefile(new_userfile, userfile);
581 nfree(new_userfile);
582 }
583
584 int change_handle(struct userrec *u, char *newh)
585 {
586 int i;
587 char s[HANDLEN + 1];
588
589 if (!u)
590 return 0;
591 /* Nothing that will confuse the userfile */
592 if (!newh[1] && strchr(BADHANDCHARS, newh[0]))
593 return 0;
594 check_tcl_nkch(u->handle, newh);
595 /* Yes, even send bot nick changes now: */
596 if (!noshare && !(u->flags & USER_UNSHARED))
597 shareout(NULL, "h %s %s\n", u->handle, newh);
598 strncpyz(s, u->handle, sizeof s);
599 strncpyz(u->handle, newh, sizeof u->handle);
600 for (i = 0; i < dcc_total; i++)
601 if ((dcc[i].type == &DCC_CHAT || dcc[i].type == &DCC_CHAT_PASS) &&
602 !egg_strcasecmp(dcc[i].nick, s)) {
603 strncpyz(dcc[i].nick, newh, sizeof dcc[i].nick);
604 if (dcc[i].type == &DCC_CHAT && dcc[i].u.chat->channel >= 0) {
605 chanout_but(-1, dcc[i].u.chat->channel,
606 "*** Handle change: %s -> %s\n", s, newh);
607 if (dcc[i].u.chat->channel < GLOBAL_CHANS)
608 botnet_send_nkch(i, s);
609 }
610 }
611 return 1;
612 }
613
614 extern int noxtra;
615
616 struct userrec *adduser(struct userrec *bu, char *handle, char *host,
617 char *pass, int flags)
618 {
619 struct userrec *u, *x;
620 struct xtra_key *xk;
621 int oldshare = noshare;
622 long tv;
623
624 noshare = 1;
625 u = nmalloc(sizeof *u);
626
627 /* u->next=bu; bu=u; */
628 strncpyz(u->handle, handle, sizeof u->handle);
629 u->next = NULL;
630 u->chanrec = NULL;
631 u->entries = NULL;
632 if (flags != USER_DEFAULT) { /* drummer */
633 u->flags = flags;
634 u->flags_udef = 0;
635 } else {
636 u->flags = default_flags;
637 u->flags_udef = default_uflags;
638 }
639 set_user(&USERENTRY_PASS, u, pass);
640 if (!noxtra) {
641 char *now2;
642 xk = nmalloc(sizeof *xk);
643 xk->key = nmalloc(8);
644 strcpy(xk->key, "created");
645 now2 = nmalloc(15);
646 tv = now;
647 sprintf(now2, "%li", tv);
648 xk->data = nmalloc(strlen(now2) + 1);
649 sprintf(xk->data, "%li", tv);
650 set_user(&USERENTRY_XTRA, u, xk);
651 nfree(now2);
652 }
653 /* Strip out commas -- they're illegal */
654 if (host && host[0]) {
655 char *p;
656
657 /* About this fixfrom():
658 * We should use this fixfrom before every call of adduser()
659 * but its much easier to use here... (drummer)
660 * Only use it if we have a host :) (dw)
661 */
662 host = fixfrom(host);
663
664 p = strchr(host, ',');
665 while (p != NULL) {
666 *p = '?';
667 p = strchr(host, ',');
668 }
669 set_user(&USERENTRY_HOSTS, u, host);
670 } else
671 set_user(&USERENTRY_HOSTS, u, "none");
672 if (bu == userlist)
673 clear_chanlist();
674 noshare = oldshare;
675 if ((!noshare) && (handle[0] != '*') && (!(flags & USER_UNSHARED)) &&
676 (bu == userlist)) {
677 struct flag_record fr = { FR_GLOBAL, 0, 0, 0, 0, 0 };
678 char x[100];
679
680 fr.global = u->flags;
681
682 fr.udef_global = u->flags_udef;
683 build_flags(x, &fr, 0);
684 shareout(NULL, "n %s %s %s %s\n", handle, host && host[0] ? host : "none",
685 pass, x);
686 }
687 if (bu == NULL)
688 bu = u;
689 else {
690 if ((bu == userlist) && (lastuser != NULL))
691 x = lastuser;
692 else
693 x = bu;
694 while (x->next != NULL)
695 x = x->next;
696 x->next = u;
697 if (bu == userlist)
698 lastuser = u;
699 }
700 return bu;
701 }
702
703 void freeuser(struct userrec *u)
704 {
705 struct user_entry *ue, *ut;
706 struct chanuserrec *ch, *z;
707
708 if (u == NULL)
709 return;
710
711 ch = u->chanrec;
712 while (ch) {
713 z = ch;
714 ch = ch->next;
715 if (z->info != NULL)
716 nfree(z->info);
717 nfree(z);
718 }
719 u->chanrec = NULL;
720 for (ue = u->entries; ue; ue = ut) {
721 ut = ue->next;
722 if (ue->name) {
723 struct list_type *lt, *ltt;
724
725 for (lt = ue->u.list; lt; lt = ltt) {
726 ltt = lt->next;
727 nfree(lt->extra);
728 nfree(lt);
729 }
730 nfree(ue->name);
731 nfree(ue);
732 } else
733 ue->type->kill(ue);
734 }
735 nfree(u);
736 }
737
738 int deluser(char *handle)
739 {
740 struct userrec *u = userlist, *prev = NULL;
741 int fnd = 0;
742
743 while ((u != NULL) && (!fnd)) {
744 if (!egg_strcasecmp(u->handle, handle))
745 fnd = 1;
746 else {
747 prev = u;
748 u = u->next;
749 }
750 }
751 if (!fnd)
752 return 0;
753 if (prev == NULL)
754 userlist = u->next;
755 else
756 prev->next = u->next;
757 if (!noshare && (handle[0] != '*') && !(u->flags & USER_UNSHARED))
758 shareout(NULL, "k %s\n", handle);
759 for (fnd = 0; fnd < dcc_total; fnd++)
760 if (dcc[fnd].user == u)
761 dcc[fnd].user = 0; /* Clear any dcc users for this entry,
762 * null is safe-ish */
763 clear_chanlist();
764 freeuser(u);
765 lastuser = NULL;
766 return 1;
767 }
768
769 int delhost_by_handle(char *handle, char *host)
770 {
771 struct userrec *u;
772 struct list_type *q, *qnext, *qprev;
773 struct user_entry *e = NULL;
774 int i = 0;
775
776 u = get_user_by_handle(userlist, handle);
777 if (!u)
778 return 0;
779 q = get_user(&USERENTRY_HOSTS, u);
780 qprev = q;
781 if (q) {
782 if (!rfc_casecmp(q->extra, host)) {
783 e = find_user_entry(&USERENTRY_HOSTS, u);
784 e->u.extra = q->next;
785 nfree(q->extra);
786 nfree(q);
787 i++;
788 qprev = NULL;
789 q = e->u.extra;
790 } else
791 q = q->next;
792 while (q) {
793 qnext = q->next;
794 if (!rfc_casecmp(q->extra, host)) {
795 if (qprev)
796 qprev->next = q->next;
797 else if (e) {
798 e->u.extra = q->next;
799 qprev = NULL;
800 }
801 nfree(q->extra);
802 nfree(q);
803 i++;
804 } else
805 qprev = q;
806 q = qnext;
807 }
808 }
809 if (!qprev)
810 set_user(&USERENTRY_HOSTS, u, "none");
811 if (!noshare && i && !(u->flags & USER_UNSHARED))
812 shareout(NULL, "-h %s %s\n", handle, host);
813 clear_chanlist();
814 return i;
815 }
816
817 void addhost_by_handle(char *handle, char *host)
818 {
819 struct userrec *u = get_user_by_handle(userlist, handle);
820
821 set_user(&USERENTRY_HOSTS, u, host);
822 /* u will be cached, so really no overhead, even tho this looks dumb: */
823 if ((!noshare) && !(u->flags & USER_UNSHARED)) {
824 if (u->flags & USER_BOT)
825 shareout(NULL, "+bh %s %s\n", handle, host);
826 else
827 shareout(NULL, "+h %s %s\n", handle, host);
828 }
829 clear_chanlist();
830 }
831
832 void touch_laston(struct userrec *u, char *where, time_t timeval)
833 {
834 if (!u)
835 return;
836
837 if (timeval > 1) {
838 struct laston_info *li = get_user(&USERENTRY_LASTON, u);
839
840 if (!li)
841 li = nmalloc(sizeof *li);
842
843 else if (li->lastonplace)
844 nfree(li->lastonplace);
845 li->laston = timeval;
846 if (where) {
847 li->lastonplace = nmalloc(strlen(where) + 1);
848 strcpy(li->lastonplace, where);
849 } else
850 li->lastonplace = NULL;
851 set_user(&USERENTRY_LASTON, u, li);
852 } else if (timeval == 1)
853 set_user(&USERENTRY_LASTON, u, 0);
854 }
855
856 /* Go through all channel records and try to find a matching
857 * nick. Will return the user's user record if that is known
858 * to the bot. (Fabian)
859 *
860 * Warning: This is unreliable by concept!
861 */
862 struct userrec *get_user_by_nick(char *nick)
863 {
864 struct chanset_t *chan;
865 memberlist *m;
866
867 for (chan = chanset; chan; chan = chan->next) {
868 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
869 if (!rfc_casecmp(nick, m->nick)) {
870 char word[512];
871
872 egg_snprintf(word, sizeof word, "%s!%s", m->nick, m->userhost);
873 /* No need to check the return value ourself */
874 return get_user_by_host(word);;
875 }
876 }
877 }
878 /* Sorry, no matches */
879 return NULL;
880 }
881
882 void user_del_chan(char *dname)
883 {
884 struct chanuserrec *ch, *och;
885 struct userrec *u;
886
887 for (u = userlist; u; u = u->next) {
888 ch = u->chanrec;
889 och = NULL;
890 while (ch) {
891 if (!rfc_casecmp(dname, ch->channel)) {
892 if (och)
893 och->next = ch->next;
894 else
895 u->chanrec = ch->next;
896
897 if (ch->info)
898 nfree(ch->info);
899 nfree(ch);
900 break;
901 }
902 och = ch;
903 ch = ch->next;
904 }
905 }
906 }
907
908 /* Check if the console flags specified in md are permissible according
909 * to the given flagrec. If the FR_CHAN flag is not set in fr->match,
910 * only global user flags will be considered.
911 * Returns: md with all unallowed flags masked out.
912 */
913 int check_conflags(struct flag_record *fr, int md)
914 {
915 if (!glob_owner(*fr))
916 md &= ~(LOG_RAW | LOG_SRVOUT | LOG_BOTNET | LOG_BOTSHARE);
917 if (!glob_master(*fr)) {
918 md &= ~(LOG_FILES | LOG_LEV1 | LOG_LEV2 | LOG_LEV3 | LOG_LEV4 |
919 LOG_LEV5 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | LOG_DEBUG |
920 LOG_WALL);
921 if ((fr->match & FR_CHAN) && !chan_master(*fr))
922 md &= ~(LOG_MISC | LOG_CMDS);
923 }
924 if (!glob_botmast(*fr))
925 md &= ~LOG_BOTS;
926 return md;
927 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23