/[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.1 - (show annotations) (download) (as text)
Mon Jul 26 21:11:06 2010 UTC (8 years, 9 months ago) by simple
Branch: MAIN
Branch point for: eggheads
File MIME type: text/x-chdr
Initial revision

1 /*
2 * tcluser.c -- handles:
3 * Tcl stubs for the user-record-oriented commands
4 *
5 * $Id: tcluser.c,v 1.51 2010/07/01 16:10:49 thommey 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 q = strchr(argv[2], ':');
315 if (!q) {
316 bi->address = user_malloc(strlen(argv[2]) + 1);
317 strcpy(bi->address, argv[2]);
318 bi->telnet_port = 3333;
319 bi->relay_port = 3333;
320 } else {
321 bi->address = user_malloc(q - argv[2] + 1);
322 strncpy(bi->address, argv[2], q - argv[2]);
323 bi->address[q - argv[2]] = 0;
324 p = q + 1;
325 bi->telnet_port = atoi(p);
326 q = strchr(p, '/');
327 if (!q)
328 bi->relay_port = bi->telnet_port;
329 else
330 bi->relay_port = atoi(q + 1);
331 }
332 set_user(&USERENTRY_BOTADDR, get_user_by_handle(userlist, argv[1]), bi);
333 Tcl_AppendResult(irp, "1", NULL);
334 }
335 return TCL_OK;
336 }
337
338 static int tcl_deluser STDVAR
339 {
340 BADARGS(2, 2, " handle");
341
342 Tcl_AppendResult(irp, (argv[1][0] == '*') ? "0" :
343 int_to_base10(deluser(argv[1])), NULL);
344 return TCL_OK;
345 }
346
347 static int tcl_delhost STDVAR
348 {
349 BADARGS(3, 3, " handle hostmask");
350
351 if ((!get_user_by_handle(userlist, argv[1])) || (argv[1][0] == '*')) {
352 Tcl_AppendResult(irp, "non-existent user", NULL);
353 return TCL_ERROR;
354 }
355 Tcl_AppendResult(irp, delhost_by_handle(argv[1], argv[2]) ? "1" : "0", NULL);
356 return TCL_OK;
357 }
358
359 static int tcl_userlist STDVAR
360 {
361 struct userrec *u;
362 struct flag_record user, plus, minus;
363 int ok = 1, f = 0;
364
365 BADARGS(1, 3, " ?flags ?channel??");
366
367 if (argc == 3 && !findchan_by_dname(argv[2])) {
368 Tcl_AppendResult(irp, "Invalid channel: ", argv[2], NULL);
369 return TCL_ERROR;
370 }
371 if (argc >= 2) {
372 plus.match = FR_GLOBAL | FR_CHAN | FR_BOT;
373 break_down_flags(argv[1], &plus, &minus);
374 f = (minus.global ||minus.udef_global || minus.chan || minus.udef_chan ||
375 minus.bot);
376 }
377 minus.match = plus.match ^ (FR_AND | FR_OR);
378 for (u = userlist; u; u = u->next) {
379 if (argc >= 2) {
380 user.match = FR_GLOBAL | FR_CHAN | FR_BOT | (argc == 3 ? 0 : FR_ANYWH);
381 if (argc == 3)
382 get_user_flagrec(u, &user, argv[2]);
383 else
384 get_user_flagrec(u, &user, NULL);
385 if (flagrec_eq(&plus, &user) && !(f && flagrec_eq(&minus, &user)))
386 ok = 1;
387 else
388 ok = 0;
389 }
390 if (ok)
391 Tcl_AppendElement(interp, u->handle);
392 }
393 return TCL_OK;
394 }
395
396 static int tcl_save STDVAR
397 {
398 write_userfile(-1);
399 return TCL_OK;
400 }
401
402 static int tcl_reload STDVAR
403 {
404 reload();
405 return TCL_OK;
406 }
407
408 static int tcl_chhandle STDVAR
409 {
410 struct userrec *u;
411 char newhand[HANDLEN + 1];
412 int x = 1, i;
413
414 BADARGS(3, 3, " oldnick newnick");
415
416 u = get_user_by_handle(userlist, argv[1]);
417 if (!u)
418 x = 0;
419 else {
420 strncpyz(newhand, argv[2], sizeof newhand);
421 for (i = 0; i < strlen(newhand); i++)
422 if (((unsigned char) newhand[i] <= 32) || (newhand[i] == '@'))
423 newhand[i] = '?';
424 if (strchr(BADHANDCHARS, newhand[0]) != NULL)
425 x = 0;
426 else if (strlen(newhand) < 1)
427 x = 0;
428 else if (get_user_by_handle(userlist, newhand))
429 x = 0;
430 else if (!egg_strcasecmp(botnetnick, newhand) && (!(u->flags & USER_BOT) ||
431 nextbot(argv[1]) != -1))
432 x = 0;
433 else if (newhand[0] == '*')
434 x = 0;
435 }
436 if (x)
437 x = change_handle(u, newhand);
438
439 Tcl_AppendResult(irp, x ? "1" : "0", NULL);
440 return TCL_OK;
441 }
442
443 static int tcl_getting_users STDVAR
444 {
445 int i;
446
447 BADARGS(1, 1, "");
448
449 for (i = 0; i < dcc_total; i++) {
450 if (dcc[i].type == &DCC_BOT && dcc[i].status & STAT_GETTING) {
451 Tcl_AppendResult(irp, "1", NULL);
452 return TCL_OK;
453 }
454 }
455 Tcl_AppendResult(irp, "0", NULL);
456 return TCL_OK;
457 }
458
459 static int tcl_isignore STDVAR
460 {
461 BADARGS(2, 2, " nick!user@host");
462
463 Tcl_AppendResult(irp, match_ignore(argv[1]) ? "1" : "0", NULL);
464 return TCL_OK;
465 }
466
467 static int tcl_newignore STDVAR
468 {
469 time_t expire_time;
470 char ign[UHOSTLEN], cmt[66], from[HANDLEN + 1];
471
472 BADARGS(4, 5, " hostmask creator comment ?lifetime?");
473
474 strncpyz(ign, argv[1], sizeof ign);
475 strncpyz(from, argv[2], sizeof from);
476 strncpyz(cmt, argv[3], sizeof cmt);
477
478 if (argc == 4)
479 expire_time = now + (60 * ignore_time);
480 else {
481 if (argc == 5 && atol(argv[4]) == 0)
482 expire_time = 0L;
483 else
484 expire_time = now + (60 * atol(argv[4])); /* This is a potential crash. FIXME -poptix */
485 }
486 addignore(ign, from, cmt, expire_time);
487 return TCL_OK;
488 }
489
490 static int tcl_killignore STDVAR
491 {
492 BADARGS(2, 2, " hostmask");
493
494 Tcl_AppendResult(irp, delignore(argv[1]) ? "1" : "0", NULL);
495 return TCL_OK;
496 }
497
498 static int tcl_ignorelist STDVAR
499 {
500 char expire[11], added[11], *p;
501 long tv;
502 EGG_CONST char *list[5];
503 struct igrec *i;
504
505 BADARGS(1, 1, "");
506
507 for (i = global_ign; i; i = i->next) {
508 list[0] = i->igmask;
509 list[1] = i->msg;
510
511 tv = i->expire;
512 egg_snprintf(expire, sizeof expire, "%lu", tv);
513 list[2] = expire;
514
515 tv = i->added;
516 egg_snprintf(added, sizeof added, "%lu", tv);
517 list[3] = added;
518
519 list[4] = i->user;
520 p = Tcl_Merge(5, list);
521 Tcl_AppendElement(irp, p);
522 Tcl_Free((char *) p);
523 }
524 return TCL_OK;
525 }
526
527 static int tcl_getuser STDVAR
528 {
529 struct user_entry_type *et;
530 struct userrec *u;
531 struct user_entry *e;
532
533 BADARGS(3, -1, " handle type");
534
535 if (!(et = find_entry_type(argv[2])) && egg_strcasecmp(argv[2], "HANDLE")) {
536 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
537 return TCL_ERROR;
538 }
539 if (!(u = get_user_by_handle(userlist, argv[1]))) {
540 if (argv[1][0] != '*') {
541 Tcl_AppendResult(irp, "No such user.", NULL);
542 return TCL_ERROR;
543 } else
544 return TCL_OK; /* silently ignore user */
545 }
546 if (!egg_strcasecmp(argv[2], "HANDLE"))
547 Tcl_AppendResult(irp, u->handle, NULL);
548 else {
549 e = find_user_entry(et, u);
550 if (e)
551 return et->tcl_get(irp, u, e, argc, argv);
552 }
553 return TCL_OK;
554 }
555
556 static int tcl_setuser STDVAR
557 {
558 struct user_entry_type *et;
559 struct userrec *u;
560 struct user_entry *e;
561 int r;
562 module_entry *me;
563
564 BADARGS(3, -1, " handle type ?setting....?");
565
566 if (!(et = find_entry_type(argv[2]))) {
567 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
568 return TCL_ERROR;
569 }
570 if (!(u = get_user_by_handle(userlist, argv[1]))) {
571 if (argv[1][0] != '*') {
572 Tcl_AppendResult(irp, "No such user.", NULL);
573 return TCL_ERROR;
574 } else
575 return TCL_OK; /* Silently ignore user * */
576 }
577 me = module_find("irc", 0, 0);
578 if (me && !strcmp(argv[2], "hosts") && argc == 3) {
579 Function *func = me->funcs;
580
581 (func[IRC_CHECK_THIS_USER]) (argv[1], 1, NULL);
582 }
583 if (!(e = find_user_entry(et, u))) {
584 e = user_malloc(sizeof(struct user_entry));
585 e->type = et;
586 e->name = NULL;
587 e->u.list = NULL;
588 list_insert((&(u->entries)), e);
589 }
590 r = et->tcl_set(irp, u, e, argc, argv);
591 /* Yeah... e is freed, and we read it... (tcl: setuser hand HOSTS none) */
592 if ((!e->u.list) && (egg_list_delete((struct list_type **) &(u->entries),
593 (struct list_type *) e)))
594 nfree(e);
595 /* else maybe already freed... (entry_type==HOSTS) <drummer> */
596 if (me && !strcmp(argv[2], "hosts") && argc == 4) {
597 Function *func = me->funcs;
598
599 (func[IRC_CHECK_THIS_USER]) (argv[1], 0, NULL);
600 }
601 return r;
602 }
603
604 tcl_cmds tcluser_cmds[] = {
605 {"countusers", tcl_countusers},
606 {"validuser", tcl_validuser},
607 {"finduser", tcl_finduser},
608 {"passwdok", tcl_passwdOk},
609 {"chattr", tcl_chattr},
610 {"botattr", tcl_botattr},
611 {"matchattr", tcl_matchattr},
612 {"matchchanattr", tcl_matchattr},
613 {"adduser", tcl_adduser},
614 {"addbot", tcl_addbot},
615 {"deluser", tcl_deluser},
616 {"delhost", tcl_delhost},
617 {"userlist", tcl_userlist},
618 {"save", tcl_save},
619 {"reload", tcl_reload},
620 {"chhandle", tcl_chhandle},
621 {"chnick", tcl_chhandle},
622 {"getting-users", tcl_getting_users},
623 {"isignore", tcl_isignore},
624 {"newignore", tcl_newignore},
625 {"killignore", tcl_killignore},
626 {"ignorelist", tcl_ignorelist},
627 {"getuser", tcl_getuser},
628 {"setuser", tcl_setuser},
629 {NULL, NULL}
630 };

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23