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

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

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


Revision 1.2 - (show annotations) (download) (as text)
Thu Aug 5 18:12:05 2010 UTC (8 years, 10 months ago) by pseudo
Branch: MAIN
CVS Tags: HEAD
Branch point for: gettext
Changes since 1.1: +9 -1 lines
File MIME type: text/x-chdr
Added new, full IPv6 support to eggdrop.

1 /*
2 * tcluser.c -- handles:
3 * Tcl stubs for the user-record-oriented commands
4 *
5 * $Id: tcluser.c,v 1.1.1.1 2010/07/26 21:11:06 simple Exp $
6 */
7 /*
8 * Copyright (C) 1997 Robey Pointer
9 * Copyright (C) 1999 - 2010 Eggheads Development Team
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include "main.h"
27 #include "users.h"
28 #include "chan.h"
29 #include "tandem.h"
30 #include "modules.h"
31
32 extern Tcl_Interp *interp;
33 extern struct userrec *userlist;
34 extern int default_flags, dcc_total, ignore_time;
35 extern struct dcc_t *dcc;
36 extern char botnetnick[];
37 extern time_t now;
38
39
40 static int tcl_countusers STDVAR
41 {
42 BADARGS(1, 1, "");
43
44 Tcl_AppendResult(irp, int_to_base10(count_users(userlist)), NULL);
45 return TCL_OK;
46 }
47
48 static int tcl_validuser STDVAR
49 {
50 BADARGS(2, 2, " handle");
51
52 Tcl_AppendResult(irp, get_user_by_handle(userlist, argv[1]) ? "1" : "0",
53 NULL);
54 return TCL_OK;
55 }
56
57 static int tcl_finduser STDVAR
58 {
59 struct userrec *u;
60
61 BADARGS(2, 2, " nick!user@host");
62
63 u = get_user_by_host(argv[1]);
64 Tcl_AppendResult(irp, u ? u->handle : "*", NULL);
65 return TCL_OK;
66 }
67
68 static int tcl_passwdOk STDVAR
69 {
70 struct userrec *u;
71
72 BADARGS(3, 3, " handle passwd");
73
74 Tcl_AppendResult(irp, ((u = get_user_by_handle(userlist, argv[1])) &&
75 u_pass_match(u, argv[2])) ? "1" : "0", NULL);
76 return TCL_OK;
77 }
78
79 static int tcl_chattr STDVAR
80 {
81 int of, ocf = 0;
82 char *chan, *chg, work[100];
83 struct flag_record pls, mns, user;
84 struct userrec *u;
85
86 BADARGS(2, 4, " handle ?changes? ?channel?");
87
88 if ((argv[1][0] == '*') || !(u = get_user_by_handle(userlist, argv[1]))) {
89 Tcl_AppendResult(irp, "*", NULL);
90 return TCL_OK;
91 }
92 if (argc == 4) {
93 user.match = FR_GLOBAL | FR_CHAN;
94 chan = argv[3];
95 chg = argv[2];
96 } else if (argc == 3 && argv[2][0]) {
97 int ischan = (findchan_by_dname(argv[2]) != NULL);
98
99 if (strchr(CHANMETA, argv[2][0]) && !ischan && argv[2][0] != '+' &&
100 argv[2][0] != '-') {
101 Tcl_AppendResult(irp, "no such channel", NULL);
102 return TCL_ERROR;
103 } else if (ischan) {
104 /* Channel exists */
105 user.match = FR_GLOBAL | FR_CHAN;
106 chan = argv[2];
107 chg = NULL;
108 } else {
109 /* 3rd possibility... channel doesnt exist, does start with a +.
110 * In this case we assume the string is flags.
111 */
112 user.match = FR_GLOBAL;
113 chan = NULL;
114 chg = argv[2];
115 }
116 } else {
117 user.match = FR_GLOBAL;
118 chan = NULL;
119 chg = NULL;
120 }
121 if (chan && !findchan_by_dname(chan)) {
122 Tcl_AppendResult(irp, "no such channel", NULL);
123 return TCL_ERROR;
124 }
125 /* Retrieve current flags */
126 get_user_flagrec(u, &user, chan);
127 /* Make changes */
128 if (chg) {
129 of = user.global;
130 pls.match = user.match;
131 break_down_flags(chg, &pls, &mns);
132 /* No-one can change these flags on-the-fly */
133 pls.global &=~(USER_BOT);
134 mns.global &=~(USER_BOT);
135
136 if (chan) {
137 pls.chan &= ~(BOT_SHARE);
138 mns.chan &= ~(BOT_SHARE);
139 }
140 user.global = sanity_check((user.global |pls.global) &~mns.global);
141
142 user.udef_global = (user.udef_global | pls.udef_global)
143 & ~mns.udef_global;
144 if (chan) {
145 ocf = user.chan;
146 user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan,
147 user.global);
148 user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
149
150 }
151 set_user_flagrec(u, &user, chan);
152 check_dcc_attrs(u, of);
153 if (chan)
154 check_dcc_chanattrs(u, chan, user.chan, ocf);
155 }
156 user.chan &= ~BOT_SHARE; /* actually not a user flag, hide it */
157 /* Build flag string */
158 build_flags(work, &user, NULL);
159 Tcl_AppendResult(irp, work, NULL);
160 return TCL_OK;
161 }
162
163 static int tcl_botattr STDVAR
164 {
165 char *chan, *chg, work[100];
166 struct flag_record pls, mns, user;
167 struct userrec *u;
168
169 BADARGS(2, 4, " bot-handle ?changes? ?channel?");
170
171 u = get_user_by_handle(userlist, argv[1]);
172 if ((argv[1][0] == '*') || !u || !(u->flags & USER_BOT)) {
173 Tcl_AppendResult(irp, "*", NULL);
174 return TCL_OK;
175 }
176 if (argc == 4) {
177 user.match = FR_BOT | FR_CHAN;
178 chan = argv[3];
179 chg = argv[2];
180 } else if (argc == 3 && argv[2][0] && strchr(CHANMETA, argv[2][0]) != NULL) {
181 /* We need todo extra checking here to stop us mixing up +channel's
182 * with flags. <cybah>
183 */
184 if (!findchan_by_dname(argv[2]) && argv[2][0] != '+') {
185 /* Channel doesnt exist, and it cant possibly be flags as there
186 * is no + at the start of the string.
187 */
188 Tcl_AppendResult(irp, "no such channel", NULL);
189 return TCL_ERROR;
190 } else if (findchan_by_dname(argv[2])) {
191 /* Channel exists */
192 user.match = FR_BOT | FR_CHAN;
193 chan = argv[2];
194 chg = NULL;
195 } else {
196 /* 3rd possibility... channel doesnt exist, does start with a +.
197 * In this case we assume the string is flags.
198 */
199 user.match = FR_BOT;
200 chan = NULL;
201 chg = argv[2];
202 }
203 } else {
204 user.match = FR_BOT;
205 chan = NULL;
206 if (argc < 3)
207 chg = NULL;
208 else
209 chg = argv[2];
210 }
211 if (chan && !findchan_by_dname(chan)) {
212 Tcl_AppendResult(irp, "no such channel", NULL);
213 return TCL_ERROR;
214 }
215 /* Retrieve current flags */
216 get_user_flagrec(u, &user, chan);
217 /* Make changes */
218 if (chg) {
219 pls.match = user.match;
220 break_down_flags(chg, &pls, &mns);
221 /* No-one can change these flags on-the-fly */
222 if (chan) {
223 pls.chan &= BOT_SHARE;
224 mns.chan &= BOT_SHARE;
225 }
226 user.bot = sanity_check((user.bot | pls.bot) & ~mns.bot);
227 if (chan) {
228 user.chan = (user.chan | pls.chan) & ~mns.chan;
229 user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
230 }
231 set_user_flagrec(u, &user, chan);
232 }
233 /* Only user flags can be set per channel, not bot ones,
234 so BOT_SHARE is a hack to allow botattr |+s */
235 user.chan &= BOT_SHARE;
236 user.udef_chan = 0; /* User definable bot flags are global only,
237 anything here is a regular flag, so hide it. */
238 /* Build flag string */
239 build_flags(work, &user, NULL);
240 Tcl_AppendResult(irp, work, NULL);
241 return TCL_OK;
242 }
243
244 static int tcl_matchattr STDVAR
245 {
246 struct userrec *u;
247 struct flag_record plus, minus, user;
248 int ok = 0, f;
249
250 BADARGS(3, 4, " handle flags ?channel?");
251
252 if ((u = get_user_by_handle(userlist, argv[1]))) {
253 user.match = FR_GLOBAL | (argc == 4 ? FR_CHAN : 0) | FR_BOT;
254 get_user_flagrec(u, &user, argv[3]);
255 plus.match = user.match;
256 break_down_flags(argv[2], &plus, &minus);
257 f = (minus.global || minus.udef_global || minus.chan || minus.udef_chan ||
258 minus.bot);
259 if (flagrec_eq(&plus, &user)) {
260 if (!f)
261 ok = 1;
262 else {
263 minus.match = plus.match ^ (FR_AND | FR_OR);
264 if (!flagrec_eq(&minus, &user))
265 ok = 1;
266 }
267 }
268 }
269 Tcl_AppendResult(irp, ok ? "1" : "0", NULL);
270 return TCL_OK;
271 }
272
273 static int tcl_adduser STDVAR
274 {
275 unsigned char *p;
276
277 BADARGS(2, 3, " handle ?hostmask?");
278
279 if (strlen(argv[1]) > HANDLEN)
280 argv[1][HANDLEN] = 0;
281 for (p = (unsigned char *) argv[1]; *p; p++)
282 if (*p <= 32 || *p == '@')
283 *p = '?';
284
285 if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
286 get_user_by_handle(userlist, argv[1]))
287 Tcl_AppendResult(irp, "0", NULL);
288 else {
289 userlist = adduser(userlist, argv[1], argv[2], "-", default_flags);
290 Tcl_AppendResult(irp, "1", NULL);
291 }
292 return TCL_OK;
293 }
294
295 static int tcl_addbot STDVAR
296 {
297 struct bot_addr *bi;
298 char *p, *q;
299
300 BADARGS(3, 3, " handle address");
301
302 if (strlen(argv[1]) > HANDLEN)
303 argv[1][HANDLEN] = 0;
304 for (p = argv[1]; *p; p++)
305 if ((unsigned char) *p <= 32 || *p == '@')
306 *p = '?';
307
308 if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
309 get_user_by_handle(userlist, argv[1]))
310 Tcl_AppendResult(irp, "0", NULL);
311 else {
312 userlist = adduser(userlist, argv[1], "none", "-", USER_BOT);
313 bi = user_malloc(sizeof(struct bot_addr));
314 #ifdef IPV6
315 if ((q = strchr(argv[2], '/'))) {
316 if (!q[1]) {
317 *q = 0;
318 q = 0;
319 }
320 } else
321 #endif
322 q = strchr(argv[2], ':');
323 if (!q) {
324 bi->address = user_malloc(strlen(argv[2]) + 1);
325 strcpy(bi->address, argv[2]);
326 bi->telnet_port = 3333;
327 bi->relay_port = 3333;
328 } else {
329 bi->address = user_malloc(q - argv[2] + 1);
330 strncpy(bi->address, argv[2], q - argv[2]);
331 bi->address[q - argv[2]] = 0;
332 p = q + 1;
333 bi->telnet_port = atoi(p);
334 q = strchr(p, '/');
335 if (!q)
336 bi->relay_port = bi->telnet_port;
337 else
338 bi->relay_port = atoi(q + 1);
339 }
340 set_user(&USERENTRY_BOTADDR, get_user_by_handle(userlist, argv[1]), bi);
341 Tcl_AppendResult(irp, "1", NULL);
342 }
343 return TCL_OK;
344 }
345
346 static int tcl_deluser STDVAR
347 {
348 BADARGS(2, 2, " handle");
349
350 Tcl_AppendResult(irp, (argv[1][0] == '*') ? "0" :
351 int_to_base10(deluser(argv[1])), NULL);
352 return TCL_OK;
353 }
354
355 static int tcl_delhost STDVAR
356 {
357 BADARGS(3, 3, " handle hostmask");
358
359 if ((!get_user_by_handle(userlist, argv[1])) || (argv[1][0] == '*')) {
360 Tcl_AppendResult(irp, "non-existent user", NULL);
361 return TCL_ERROR;
362 }
363 Tcl_AppendResult(irp, delhost_by_handle(argv[1], argv[2]) ? "1" : "0", NULL);
364 return TCL_OK;
365 }
366
367 static int tcl_userlist STDVAR
368 {
369 struct userrec *u;
370 struct flag_record user, plus, minus;
371 int ok = 1, f = 0;
372
373 BADARGS(1, 3, " ?flags ?channel??");
374
375 if (argc == 3 && !findchan_by_dname(argv[2])) {
376 Tcl_AppendResult(irp, "Invalid channel: ", argv[2], NULL);
377 return TCL_ERROR;
378 }
379 if (argc >= 2) {
380 plus.match = FR_GLOBAL | FR_CHAN | FR_BOT;
381 break_down_flags(argv[1], &plus, &minus);
382 f = (minus.global ||minus.udef_global || minus.chan || minus.udef_chan ||
383 minus.bot);
384 }
385 minus.match = plus.match ^ (FR_AND | FR_OR);
386 for (u = userlist; u; u = u->next) {
387 if (argc >= 2) {
388 user.match = FR_GLOBAL | FR_CHAN | FR_BOT | (argc == 3 ? 0 : FR_ANYWH);
389 if (argc == 3)
390 get_user_flagrec(u, &user, argv[2]);
391 else
392 get_user_flagrec(u, &user, NULL);
393 if (flagrec_eq(&plus, &user) && !(f && flagrec_eq(&minus, &user)))
394 ok = 1;
395 else
396 ok = 0;
397 }
398 if (ok)
399 Tcl_AppendElement(interp, u->handle);
400 }
401 return TCL_OK;
402 }
403
404 static int tcl_save STDVAR
405 {
406 write_userfile(-1);
407 return TCL_OK;
408 }
409
410 static int tcl_reload STDVAR
411 {
412 reload();
413 return TCL_OK;
414 }
415
416 static int tcl_chhandle STDVAR
417 {
418 struct userrec *u;
419 char newhand[HANDLEN + 1];
420 int x = 1, i;
421
422 BADARGS(3, 3, " oldnick newnick");
423
424 u = get_user_by_handle(userlist, argv[1]);
425 if (!u)
426 x = 0;
427 else {
428 strncpyz(newhand, argv[2], sizeof newhand);
429 for (i = 0; i < strlen(newhand); i++)
430 if (((unsigned char) newhand[i] <= 32) || (newhand[i] == '@'))
431 newhand[i] = '?';
432 if (strchr(BADHANDCHARS, newhand[0]) != NULL)
433 x = 0;
434 else if (strlen(newhand) < 1)
435 x = 0;
436 else if (get_user_by_handle(userlist, newhand))
437 x = 0;
438 else if (!egg_strcasecmp(botnetnick, newhand) && (!(u->flags & USER_BOT) ||
439 nextbot(argv[1]) != -1))
440 x = 0;
441 else if (newhand[0] == '*')
442 x = 0;
443 }
444 if (x)
445 x = change_handle(u, newhand);
446
447 Tcl_AppendResult(irp, x ? "1" : "0", NULL);
448 return TCL_OK;
449 }
450
451 static int tcl_getting_users STDVAR
452 {
453 int i;
454
455 BADARGS(1, 1, "");
456
457 for (i = 0; i < dcc_total; i++) {
458 if (dcc[i].type == &DCC_BOT && dcc[i].status & STAT_GETTING) {
459 Tcl_AppendResult(irp, "1", NULL);
460 return TCL_OK;
461 }
462 }
463 Tcl_AppendResult(irp, "0", NULL);
464 return TCL_OK;
465 }
466
467 static int tcl_isignore STDVAR
468 {
469 BADARGS(2, 2, " nick!user@host");
470
471 Tcl_AppendResult(irp, match_ignore(argv[1]) ? "1" : "0", NULL);
472 return TCL_OK;
473 }
474
475 static int tcl_newignore STDVAR
476 {
477 time_t expire_time;
478 char ign[UHOSTLEN], cmt[66], from[HANDLEN + 1];
479
480 BADARGS(4, 5, " hostmask creator comment ?lifetime?");
481
482 strncpyz(ign, argv[1], sizeof ign);
483 strncpyz(from, argv[2], sizeof from);
484 strncpyz(cmt, argv[3], sizeof cmt);
485
486 if (argc == 4)
487 expire_time = now + (60 * ignore_time);
488 else {
489 if (argc == 5 && atol(argv[4]) == 0)
490 expire_time = 0L;
491 else
492 expire_time = now + (60 * atol(argv[4])); /* This is a potential crash. FIXME -poptix */
493 }
494 addignore(ign, from, cmt, expire_time);
495 return TCL_OK;
496 }
497
498 static int tcl_killignore STDVAR
499 {
500 BADARGS(2, 2, " hostmask");
501
502 Tcl_AppendResult(irp, delignore(argv[1]) ? "1" : "0", NULL);
503 return TCL_OK;
504 }
505
506 static int tcl_ignorelist STDVAR
507 {
508 char expire[11], added[11], *p;
509 long tv;
510 EGG_CONST char *list[5];
511 struct igrec *i;
512
513 BADARGS(1, 1, "");
514
515 for (i = global_ign; i; i = i->next) {
516 list[0] = i->igmask;
517 list[1] = i->msg;
518
519 tv = i->expire;
520 egg_snprintf(expire, sizeof expire, "%lu", tv);
521 list[2] = expire;
522
523 tv = i->added;
524 egg_snprintf(added, sizeof added, "%lu", tv);
525 list[3] = added;
526
527 list[4] = i->user;
528 p = Tcl_Merge(5, list);
529 Tcl_AppendElement(irp, p);
530 Tcl_Free((char *) p);
531 }
532 return TCL_OK;
533 }
534
535 static int tcl_getuser STDVAR
536 {
537 struct user_entry_type *et;
538 struct userrec *u;
539 struct user_entry *e;
540
541 BADARGS(3, -1, " handle type");
542
543 if (!(et = find_entry_type(argv[2])) && egg_strcasecmp(argv[2], "HANDLE")) {
544 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
545 return TCL_ERROR;
546 }
547 if (!(u = get_user_by_handle(userlist, argv[1]))) {
548 if (argv[1][0] != '*') {
549 Tcl_AppendResult(irp, "No such user.", NULL);
550 return TCL_ERROR;
551 } else
552 return TCL_OK; /* silently ignore user */
553 }
554 if (!egg_strcasecmp(argv[2], "HANDLE"))
555 Tcl_AppendResult(irp, u->handle, NULL);
556 else {
557 e = find_user_entry(et, u);
558 if (e)
559 return et->tcl_get(irp, u, e, argc, argv);
560 }
561 return TCL_OK;
562 }
563
564 static int tcl_setuser STDVAR
565 {
566 struct user_entry_type *et;
567 struct userrec *u;
568 struct user_entry *e;
569 int r;
570 module_entry *me;
571
572 BADARGS(3, -1, " handle type ?setting....?");
573
574 if (!(et = find_entry_type(argv[2]))) {
575 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
576 return TCL_ERROR;
577 }
578 if (!(u = get_user_by_handle(userlist, argv[1]))) {
579 if (argv[1][0] != '*') {
580 Tcl_AppendResult(irp, "No such user.", NULL);
581 return TCL_ERROR;
582 } else
583 return TCL_OK; /* Silently ignore user * */
584 }
585 me = module_find("irc", 0, 0);
586 if (me && !strcmp(argv[2], "hosts") && argc == 3) {
587 Function *func = me->funcs;
588
589 (func[IRC_CHECK_THIS_USER]) (argv[1], 1, NULL);
590 }
591 if (!(e = find_user_entry(et, u))) {
592 e = user_malloc(sizeof(struct user_entry));
593 e->type = et;
594 e->name = NULL;
595 e->u.list = NULL;
596 list_insert((&(u->entries)), e);
597 }
598 r = et->tcl_set(irp, u, e, argc, argv);
599 /* Yeah... e is freed, and we read it... (tcl: setuser hand HOSTS none) */
600 if ((!e->u.list) && (egg_list_delete((struct list_type **) &(u->entries),
601 (struct list_type *) e)))
602 nfree(e);
603 /* else maybe already freed... (entry_type==HOSTS) <drummer> */
604 if (me && !strcmp(argv[2], "hosts") && argc == 4) {
605 Function *func = me->funcs;
606
607 (func[IRC_CHECK_THIS_USER]) (argv[1], 0, NULL);
608 }
609 return r;
610 }
611
612 tcl_cmds tcluser_cmds[] = {
613 {"countusers", tcl_countusers},
614 {"validuser", tcl_validuser},
615 {"finduser", tcl_finduser},
616 {"passwdok", tcl_passwdOk},
617 {"chattr", tcl_chattr},
618 {"botattr", tcl_botattr},
619 {"matchattr", tcl_matchattr},
620 {"matchchanattr", tcl_matchattr},
621 {"adduser", tcl_adduser},
622 {"addbot", tcl_addbot},
623 {"deluser", tcl_deluser},
624 {"delhost", tcl_delhost},
625 {"userlist", tcl_userlist},
626 {"save", tcl_save},
627 {"reload", tcl_reload},
628 {"chhandle", tcl_chhandle},
629 {"chnick", tcl_chhandle},
630 {"getting-users", tcl_getting_users},
631 {"isignore", tcl_isignore},
632 {"newignore", tcl_newignore},
633 {"killignore", tcl_killignore},
634 {"ignorelist", tcl_ignorelist},
635 {"getuser", tcl_getuser},
636 {"setuser", tcl_setuser},
637 {NULL, NULL}
638 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23