00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "main.h"
00027 #include "users.h"
00028 #include "chan.h"
00029 #include "tandem.h"
00030 #include "modules.h"
00031
00032 extern Tcl_Interp *interp;
00033 extern struct userrec *userlist;
00034 extern int default_flags, dcc_total, ignore_time;
00035 extern struct dcc_t *dcc;
00036 extern char botnetnick[];
00037 extern time_t now;
00038
00039
00040 static int tcl_countusers STDVAR
00041 {
00042 BADARGS(1, 1, "");
00043
00044 Tcl_AppendResult(irp, int_to_base10(count_users(userlist)), NULL);
00045 return TCL_OK;
00046 }
00047
00048 static int tcl_validuser STDVAR
00049 {
00050 BADARGS(2, 2, " handle");
00051
00052 Tcl_AppendResult(irp, get_user_by_handle(userlist, argv[1]) ? "1" : "0",
00053 NULL);
00054 return TCL_OK;
00055 }
00056
00057 static int tcl_finduser STDVAR
00058 {
00059 struct userrec *u;
00060
00061 BADARGS(2, 2, " nick!user@host");
00062
00063 u = get_user_by_host(argv[1]);
00064 Tcl_AppendResult(irp, u ? u->handle : "*", NULL);
00065 return TCL_OK;
00066 }
00067
00068 static int tcl_passwdOk STDVAR
00069 {
00070 struct userrec *u;
00071
00072 BADARGS(3, 3, " handle passwd");
00073
00074 Tcl_AppendResult(irp, ((u = get_user_by_handle(userlist, argv[1])) &&
00075 u_pass_match(u, argv[2])) ? "1" : "0", NULL);
00076 return TCL_OK;
00077 }
00078
00079 static int tcl_chattr STDVAR
00080 {
00081 int of, ocf = 0;
00082 char *chan, *chg, work[100];
00083 struct flag_record pls, mns, user;
00084 struct userrec *u;
00085
00086 BADARGS(2, 4, " handle ?changes? ?channel?");
00087
00088 if ((argv[1][0] == '*') || !(u = get_user_by_handle(userlist, argv[1]))) {
00089 Tcl_AppendResult(irp, "*", NULL);
00090 return TCL_OK;
00091 }
00092 if (argc == 4) {
00093 user.match = FR_GLOBAL | FR_CHAN;
00094 chan = argv[3];
00095 chg = argv[2];
00096 } else if (argc == 3 && argv[2][0]) {
00097 int ischan = (findchan_by_dname(argv[2]) != NULL);
00098
00099 if (strchr(CHANMETA, argv[2][0]) && !ischan && argv[2][0] != '+' &&
00100 argv[2][0] != '-') {
00101 Tcl_AppendResult(irp, "no such channel", NULL);
00102 return TCL_ERROR;
00103 } else if (ischan) {
00104
00105 user.match = FR_GLOBAL | FR_CHAN;
00106 chan = argv[2];
00107 chg = NULL;
00108 } else {
00109
00110
00111
00112 user.match = FR_GLOBAL;
00113 chan = NULL;
00114 chg = argv[2];
00115 }
00116 } else {
00117 user.match = FR_GLOBAL;
00118 chan = NULL;
00119 chg = NULL;
00120 }
00121 if (chan && !findchan_by_dname(chan)) {
00122 Tcl_AppendResult(irp, "no such channel", NULL);
00123 return TCL_ERROR;
00124 }
00125
00126 get_user_flagrec(u, &user, chan);
00127
00128 if (chg) {
00129 of = user.global;
00130 pls.match = user.match;
00131 break_down_flags(chg, &pls, &mns);
00132
00133 pls.global &=~(USER_BOT);
00134 mns.global &=~(USER_BOT);
00135
00136 if (chan) {
00137 pls.chan &= ~(BOT_SHARE);
00138 mns.chan &= ~(BOT_SHARE);
00139 }
00140 user.global = sanity_check((user.global |pls.global) &~mns.global);
00141
00142 user.udef_global = (user.udef_global | pls.udef_global)
00143 & ~mns.udef_global;
00144 if (chan) {
00145 ocf = user.chan;
00146 user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan,
00147 user.global);
00148 user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
00149
00150 }
00151 set_user_flagrec(u, &user, chan);
00152 check_dcc_attrs(u, of);
00153 if (chan)
00154 check_dcc_chanattrs(u, chan, user.chan, ocf);
00155 }
00156 user.chan &= ~BOT_SHARE;
00157
00158 build_flags(work, &user, NULL);
00159 Tcl_AppendResult(irp, work, NULL);
00160 return TCL_OK;
00161 }
00162
00163 static int tcl_botattr STDVAR
00164 {
00165 char *chan, *chg, work[100];
00166 struct flag_record pls, mns, user;
00167 struct userrec *u;
00168
00169 BADARGS(2, 4, " bot-handle ?changes? ?channel?");
00170
00171 u = get_user_by_handle(userlist, argv[1]);
00172 if ((argv[1][0] == '*') || !u || !(u->flags & USER_BOT)) {
00173 Tcl_AppendResult(irp, "*", NULL);
00174 return TCL_OK;
00175 }
00176 if (argc == 4) {
00177 user.match = FR_BOT | FR_CHAN;
00178 chan = argv[3];
00179 chg = argv[2];
00180 } else if (argc == 3 && argv[2][0] && strchr(CHANMETA, argv[2][0]) != NULL) {
00181
00182
00183
00184 if (!findchan_by_dname(argv[2]) && argv[2][0] != '+') {
00185
00186
00187
00188 Tcl_AppendResult(irp, "no such channel", NULL);
00189 return TCL_ERROR;
00190 } else if (findchan_by_dname(argv[2])) {
00191
00192 user.match = FR_BOT | FR_CHAN;
00193 chan = argv[2];
00194 chg = NULL;
00195 } else {
00196
00197
00198
00199 user.match = FR_BOT;
00200 chan = NULL;
00201 chg = argv[2];
00202 }
00203 } else {
00204 user.match = FR_BOT;
00205 chan = NULL;
00206 if (argc < 3)
00207 chg = NULL;
00208 else
00209 chg = argv[2];
00210 }
00211 if (chan && !findchan_by_dname(chan)) {
00212 Tcl_AppendResult(irp, "no such channel", NULL);
00213 return TCL_ERROR;
00214 }
00215
00216 get_user_flagrec(u, &user, chan);
00217
00218 if (chg) {
00219 pls.match = user.match;
00220 break_down_flags(chg, &pls, &mns);
00221
00222 if (chan) {
00223 pls.chan &= BOT_SHARE;
00224 mns.chan &= BOT_SHARE;
00225 }
00226 user.bot = sanity_check((user.bot | pls.bot) & ~mns.bot);
00227 if (chan) {
00228 user.chan = (user.chan | pls.chan) & ~mns.chan;
00229 user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
00230 }
00231 set_user_flagrec(u, &user, chan);
00232 }
00233
00234
00235 user.chan &= BOT_SHARE;
00236 user.udef_chan = 0;
00237
00238
00239 build_flags(work, &user, NULL);
00240 Tcl_AppendResult(irp, work, NULL);
00241 return TCL_OK;
00242 }
00243
00244 static int tcl_matchattr STDVAR
00245 {
00246 struct userrec *u;
00247 struct flag_record plus, minus, user;
00248 int ok = 0, f;
00249
00250 BADARGS(3, 4, " handle flags ?channel?");
00251
00252 if ((u = get_user_by_handle(userlist, argv[1]))) {
00253 user.match = FR_GLOBAL | (argc == 4 ? FR_CHAN : 0) | FR_BOT;
00254 get_user_flagrec(u, &user, argv[3]);
00255 plus.match = user.match;
00256 break_down_flags(argv[2], &plus, &minus);
00257 f = (minus.global || minus.udef_global || minus.chan || minus.udef_chan ||
00258 minus.bot);
00259 if (flagrec_eq(&plus, &user)) {
00260 if (!f)
00261 ok = 1;
00262 else {
00263 minus.match = plus.match ^ (FR_AND | FR_OR);
00264 if (!flagrec_eq(&minus, &user))
00265 ok = 1;
00266 }
00267 }
00268 }
00269 Tcl_AppendResult(irp, ok ? "1" : "0", NULL);
00270 return TCL_OK;
00271 }
00272
00273 static int tcl_adduser STDVAR
00274 {
00275 unsigned char *p;
00276
00277 BADARGS(2, 3, " handle ?hostmask?");
00278
00279 if (strlen(argv[1]) > HANDLEN)
00280 argv[1][HANDLEN] = 0;
00281 for (p = (unsigned char *) argv[1]; *p; p++)
00282 if (*p <= 32 || *p == '@')
00283 *p = '?';
00284
00285 if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
00286 get_user_by_handle(userlist, argv[1]))
00287 Tcl_AppendResult(irp, "0", NULL);
00288 else {
00289 userlist = adduser(userlist, argv[1], argv[2], "-", default_flags);
00290 Tcl_AppendResult(irp, "1", NULL);
00291 }
00292 return TCL_OK;
00293 }
00294
00295 static int tcl_addbot STDVAR
00296 {
00297 struct bot_addr *bi;
00298 char *p, *q;
00299
00300 BADARGS(3, 3, " handle address");
00301
00302 if (strlen(argv[1]) > HANDLEN)
00303 argv[1][HANDLEN] = 0;
00304 for (p = argv[1]; *p; p++)
00305 if ((unsigned char) *p <= 32 || *p == '@')
00306 *p = '?';
00307
00308 if ((argv[1][0] == '*') || strchr(BADHANDCHARS, argv[1][0]) ||
00309 get_user_by_handle(userlist, argv[1]))
00310 Tcl_AppendResult(irp, "0", NULL);
00311 else {
00312 userlist = adduser(userlist, argv[1], "none", "-", USER_BOT);
00313 bi = user_malloc(sizeof(struct bot_addr));
00314 q = strchr(argv[2], ':');
00315 if (!q) {
00316 bi->address = user_malloc(strlen(argv[2]) + 1);
00317 strcpy(bi->address, argv[2]);
00318 bi->telnet_port = 3333;
00319 bi->relay_port = 3333;
00320 } else {
00321 bi->address = user_malloc(q - argv[2] + 1);
00322 strncpy(bi->address, argv[2], q - argv[2]);
00323 bi->address[q - argv[2]] = 0;
00324 p = q + 1;
00325 bi->telnet_port = atoi(p);
00326 q = strchr(p, '/');
00327 if (!q)
00328 bi->relay_port = bi->telnet_port;
00329 else
00330 bi->relay_port = atoi(q + 1);
00331 }
00332 set_user(&USERENTRY_BOTADDR, get_user_by_handle(userlist, argv[1]), bi);
00333 Tcl_AppendResult(irp, "1", NULL);
00334 }
00335 return TCL_OK;
00336 }
00337
00338 static int tcl_deluser STDVAR
00339 {
00340 BADARGS(2, 2, " handle");
00341
00342 Tcl_AppendResult(irp, (argv[1][0] == '*') ? "0" :
00343 int_to_base10(deluser(argv[1])), NULL);
00344 return TCL_OK;
00345 }
00346
00347 static int tcl_delhost STDVAR
00348 {
00349 BADARGS(3, 3, " handle hostmask");
00350
00351 if ((!get_user_by_handle(userlist, argv[1])) || (argv[1][0] == '*')) {
00352 Tcl_AppendResult(irp, "non-existent user", NULL);
00353 return TCL_ERROR;
00354 }
00355 Tcl_AppendResult(irp, delhost_by_handle(argv[1], argv[2]) ? "1" : "0", NULL);
00356 return TCL_OK;
00357 }
00358
00359 static int tcl_userlist STDVAR
00360 {
00361 struct userrec *u;
00362 struct flag_record user, plus, minus;
00363 int ok = 1, f = 0;
00364
00365 BADARGS(1, 3, " ?flags ?channel??");
00366
00367 if (argc == 3 && !findchan_by_dname(argv[2])) {
00368 Tcl_AppendResult(irp, "Invalid channel: ", argv[2], NULL);
00369 return TCL_ERROR;
00370 }
00371 if (argc >= 2) {
00372 plus.match = FR_GLOBAL | FR_CHAN | FR_BOT;
00373 break_down_flags(argv[1], &plus, &minus);
00374 f = (minus.global ||minus.udef_global || minus.chan || minus.udef_chan ||
00375 minus.bot);
00376 }
00377 minus.match = plus.match ^ (FR_AND | FR_OR);
00378 for (u = userlist; u; u = u->next) {
00379 if (argc >= 2) {
00380 user.match = FR_GLOBAL | FR_CHAN | FR_BOT | (argc == 3 ? 0 : FR_ANYWH);
00381 if (argc == 3)
00382 get_user_flagrec(u, &user, argv[2]);
00383 else
00384 get_user_flagrec(u, &user, NULL);
00385 if (flagrec_eq(&plus, &user) && !(f && flagrec_eq(&minus, &user)))
00386 ok = 1;
00387 else
00388 ok = 0;
00389 }
00390 if (ok)
00391 Tcl_AppendElement(interp, u->handle);
00392 }
00393 return TCL_OK;
00394 }
00395
00396 static int tcl_save STDVAR
00397 {
00398 write_userfile(-1);
00399 return TCL_OK;
00400 }
00401
00402 static int tcl_reload STDVAR
00403 {
00404 reload();
00405 return TCL_OK;
00406 }
00407
00408 static int tcl_chhandle STDVAR
00409 {
00410 struct userrec *u;
00411 char newhand[HANDLEN + 1];
00412 int x = 1, i;
00413
00414 BADARGS(3, 3, " oldnick newnick");
00415
00416 u = get_user_by_handle(userlist, argv[1]);
00417 if (!u)
00418 x = 0;
00419 else {
00420 strncpyz(newhand, argv[2], sizeof newhand);
00421 for (i = 0; i < strlen(newhand); i++)
00422 if (((unsigned char) newhand[i] <= 32) || (newhand[i] == '@'))
00423 newhand[i] = '?';
00424 if (strchr(BADHANDCHARS, newhand[0]) != NULL)
00425 x = 0;
00426 else if (strlen(newhand) < 1)
00427 x = 0;
00428 else if (get_user_by_handle(userlist, newhand))
00429 x = 0;
00430 else if (!egg_strcasecmp(botnetnick, newhand) && (!(u->flags & USER_BOT) ||
00431 nextbot(argv[1]) != -1))
00432 x = 0;
00433 else if (newhand[0] == '*')
00434 x = 0;
00435 }
00436 if (x)
00437 x = change_handle(u, newhand);
00438
00439 Tcl_AppendResult(irp, x ? "1" : "0", NULL);
00440 return TCL_OK;
00441 }
00442
00443 static int tcl_getting_users STDVAR
00444 {
00445 int i;
00446
00447 BADARGS(1, 1, "");
00448
00449 for (i = 0; i < dcc_total; i++) {
00450 if (dcc[i].type == &DCC_BOT && dcc[i].status & STAT_GETTING) {
00451 Tcl_AppendResult(irp, "1", NULL);
00452 return TCL_OK;
00453 }
00454 }
00455 Tcl_AppendResult(irp, "0", NULL);
00456 return TCL_OK;
00457 }
00458
00459 static int tcl_isignore STDVAR
00460 {
00461 BADARGS(2, 2, " nick!user@host");
00462
00463 Tcl_AppendResult(irp, match_ignore(argv[1]) ? "1" : "0", NULL);
00464 return TCL_OK;
00465 }
00466
00467 static int tcl_newignore STDVAR
00468 {
00469 time_t expire_time;
00470 char ign[UHOSTLEN], cmt[66], from[HANDLEN + 1];
00471
00472 BADARGS(4, 5, " hostmask creator comment ?lifetime?");
00473
00474 strncpyz(ign, argv[1], sizeof ign);
00475 strncpyz(from, argv[2], sizeof from);
00476 strncpyz(cmt, argv[3], sizeof cmt);
00477
00478 if (argc == 4)
00479 expire_time = now + (60 * ignore_time);
00480 else {
00481 if (argc == 5 && atol(argv[4]) == 0)
00482 expire_time = 0L;
00483 else
00484 expire_time = now + (60 * atol(argv[4]));
00485 }
00486 addignore(ign, from, cmt, expire_time);
00487 return TCL_OK;
00488 }
00489
00490 static int tcl_killignore STDVAR
00491 {
00492 BADARGS(2, 2, " hostmask");
00493
00494 Tcl_AppendResult(irp, delignore(argv[1]) ? "1" : "0", NULL);
00495 return TCL_OK;
00496 }
00497
00498 static int tcl_ignorelist STDVAR
00499 {
00500 char expire[11], added[11], *p;
00501 long tv;
00502 EGG_CONST char *list[5];
00503 struct igrec *i;
00504
00505 BADARGS(1, 1, "");
00506
00507 for (i = global_ign; i; i = i->next) {
00508 list[0] = i->igmask;
00509 list[1] = i->msg;
00510
00511 tv = i->expire;
00512 egg_snprintf(expire, sizeof expire, "%lu", tv);
00513 list[2] = expire;
00514
00515 tv = i->added;
00516 egg_snprintf(added, sizeof added, "%lu", tv);
00517 list[3] = added;
00518
00519 list[4] = i->user;
00520 p = Tcl_Merge(5, list);
00521 Tcl_AppendElement(irp, p);
00522 Tcl_Free((char *) p);
00523 }
00524 return TCL_OK;
00525 }
00526
00527 static int tcl_getuser STDVAR
00528 {
00529 struct user_entry_type *et;
00530 struct userrec *u;
00531 struct user_entry *e;
00532
00533 BADARGS(3, -1, " handle type");
00534
00535 if (!(et = find_entry_type(argv[2])) && egg_strcasecmp(argv[2], "HANDLE")) {
00536 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
00537 return TCL_ERROR;
00538 }
00539 if (!(u = get_user_by_handle(userlist, argv[1]))) {
00540 if (argv[1][0] != '*') {
00541 Tcl_AppendResult(irp, "No such user.", NULL);
00542 return TCL_ERROR;
00543 } else
00544 return TCL_OK;
00545 }
00546 if (!egg_strcasecmp(argv[2], "HANDLE"))
00547 Tcl_AppendResult(irp, u->handle, NULL);
00548 else {
00549 e = find_user_entry(et, u);
00550 if (e)
00551 return et->tcl_get(irp, u, e, argc, argv);
00552 }
00553 return TCL_OK;
00554 }
00555
00556 static int tcl_setuser STDVAR
00557 {
00558 struct user_entry_type *et;
00559 struct userrec *u;
00560 struct user_entry *e;
00561 int r;
00562 module_entry *me;
00563
00564 BADARGS(3, -1, " handle type ?setting....?");
00565
00566 if (!(et = find_entry_type(argv[2]))) {
00567 Tcl_AppendResult(irp, "No such info type: ", argv[2], NULL);
00568 return TCL_ERROR;
00569 }
00570 if (!(u = get_user_by_handle(userlist, argv[1]))) {
00571 if (argv[1][0] != '*') {
00572 Tcl_AppendResult(irp, "No such user.", NULL);
00573 return TCL_ERROR;
00574 } else
00575 return TCL_OK;
00576 }
00577 me = module_find("irc", 0, 0);
00578 if (me && !strcmp(argv[2], "hosts") && argc == 3) {
00579 Function *func = me->funcs;
00580
00581 (func[IRC_CHECK_THIS_USER]) (argv[1], 1, NULL);
00582 }
00583 if (!(e = find_user_entry(et, u))) {
00584 e = user_malloc(sizeof(struct user_entry));
00585 e->type = et;
00586 e->name = NULL;
00587 e->u.list = NULL;
00588 list_insert((&(u->entries)), e);
00589 }
00590 r = et->tcl_set(irp, u, e, argc, argv);
00591
00592 if ((!e->u.list) && (egg_list_delete((struct list_type **) &(u->entries),
00593 (struct list_type *) e)))
00594 nfree(e);
00595
00596 if (me && !strcmp(argv[2], "hosts") && argc == 4) {
00597 Function *func = me->funcs;
00598
00599 (func[IRC_CHECK_THIS_USER]) (argv[1], 0, NULL);
00600 }
00601 return r;
00602 }
00603
00604 tcl_cmds tcluser_cmds[] = {
00605 {"countusers", tcl_countusers},
00606 {"validuser", tcl_validuser},
00607 {"finduser", tcl_finduser},
00608 {"passwdok", tcl_passwdOk},
00609 {"chattr", tcl_chattr},
00610 {"botattr", tcl_botattr},
00611 {"matchattr", tcl_matchattr},
00612 {"matchchanattr", tcl_matchattr},
00613 {"adduser", tcl_adduser},
00614 {"addbot", tcl_addbot},
00615 {"deluser", tcl_deluser},
00616 {"delhost", tcl_delhost},
00617 {"userlist", tcl_userlist},
00618 {"save", tcl_save},
00619 {"reload", tcl_reload},
00620 {"chhandle", tcl_chhandle},
00621 {"chnick", tcl_chhandle},
00622 {"getting-users", tcl_getting_users},
00623 {"isignore", tcl_isignore},
00624 {"newignore", tcl_newignore},
00625 {"killignore", tcl_killignore},
00626 {"ignorelist", tcl_ignorelist},
00627 {"getuser", tcl_getuser},
00628 {"setuser", tcl_setuser},
00629 {NULL, NULL}
00630 };