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
00027
00028
00029
00030 #include "flagmaps.c"
00031
00032
00033 char *channel_info_names[] = {
00034 "chanmode",
00035 "stop_net_hack",
00036 "aop_delay",
00037 NULL
00038 };
00039
00040 static int lookup_flag_by_name(channel_flag_map_t *map, char *name, int *flagval);
00041
00042
00043 static int script_killsomething(void *type, char *chan_name, char *mask)
00044 {
00045 struct chanset_t *chan = NULL;
00046
00047 if (chan_name && chan_name[0]) {
00048 chan = findchan_by_dname(chan_name);
00049 if (!chan) return(-1);
00050 }
00051
00052 if (u_delmask((int) type, chan, mask, 1) > 0) {
00053 if (!chan) {
00054 for (chan = chanset; chan; chan = chan->next) {
00055 add_mode(chan, '-', (int) type, mask);
00056 }
00057 }
00058 else add_mode(chan, '-', (int) type, mask);
00059 }
00060 return(0);
00061 }
00062
00063
00064 static int script_sticksomething(void *type, char *chan_name, char *mask)
00065 {
00066 struct chanset_t *chan = NULL;
00067
00068 if (chan_name && chan_name[0]) {
00069 chan = findchan_by_dname(chan_name);
00070 if (!chan) return(-1);
00071 }
00072
00073
00074 return u_setsticky_mask((int)type & 255, chan, mask, ((int)type > 255) ? 0 : 1);
00075 }
00076
00077 static int get_maskrec_and_alt(char type, char *chan_name, struct maskrec **u, struct maskrec **alt)
00078 {
00079 struct chanset_t *chan = NULL;
00080
00081 if (chan_name && chan_name[0]) {
00082 chan = findchan_by_dname(chan_name);
00083 if (!chan) return(1);
00084 }
00085
00086 *u = NULL;
00087 *alt = NULL;
00088 if (type == 'b') {
00089 if (chan) {
00090 *u = chan->bans;
00091 if (channel_honor_global_bans(chan)) *alt = global_bans;
00092 }
00093 else *u = global_bans;
00094 }
00095 else if (type == 'I') {
00096 if (chan) {
00097 *u = chan->invites;
00098 if (channel_honor_global_invites(chan)) *alt = global_invites;
00099 }
00100 else *u = global_invites;
00101 }
00102 else {
00103 if (chan) {
00104 *u = chan->exempts;
00105 if (channel_honor_global_exempts(chan)) *alt = global_exempts;
00106 }
00107 else *u = global_exempts;
00108 }
00109 return(0);
00110 }
00111
00112 static int script_issomething(void *type, char *chan_name, char *mask)
00113 {
00114 maskrec *u, *alt;
00115 int matches;
00116
00117 get_maskrec_and_alt((int) type, chan_name, &u, &alt);
00118
00119 matches = u_equals_mask(u, mask);
00120 if (!matches && alt) matches = u_equals_mask(alt, mask);
00121 return(matches ? 1 : 0);
00122 }
00123
00124 static int script_isstickysomething(void *type, char *chan_name, char *mask)
00125 {
00126 maskrec *u, *alt;
00127 int sticky;
00128
00129 if (get_maskrec_and_alt((int) type, chan_name, &u, &alt)) return(-1);
00130
00131 sticky = u_sticky_mask(u, mask);
00132 if (!sticky && alt) sticky = u_sticky_mask(alt, mask);
00133 return(sticky ? 1 : 0);
00134 }
00135
00136 static int script_ispermsomething(void *type, char *chan_name, char *mask)
00137 {
00138 maskrec *u, *alt;
00139
00140 if (get_maskrec_and_alt((int) type, chan_name, &u, &alt)) return(-1);
00141
00142 if (u_equals_mask(u, mask) == 2) return(1);
00143 if (alt && (u_equals_mask(alt, mask) == 2)) return(1);
00144 return(0);
00145 }
00146
00147 static int script_matchsomething(void *type, char *chan_name, char *mask)
00148 {
00149 maskrec *u, *alt;
00150
00151 if (get_maskrec_and_alt((int) type, chan_name, &u, &alt)) return(-1);
00152
00153 if (u_match_mask(u, mask)) return(1);
00154 if (alt && u_match_mask(alt, mask)) return(1);
00155 return(0);
00156 }
00157
00158 static int script_newsomething(void *type, char *chan_name, char *mask, char *creator, char *comment, char *lifetime, char *options)
00159 {
00160 time_t expire_time;
00161 struct chanset_t *chan = NULL;
00162 int sticky = 0;
00163 int r;
00164 module_entry *me;
00165
00166 if (chan_name[0]) {
00167 chan = findchan_by_dname(chan_name);
00168 if (!chan) return(-1);
00169 }
00170
00171 if (lifetime) {
00172 expire_time = atoi(lifetime);
00173 if (expire_time) expire_time = expire_time * 60 + now;
00174 }
00175 expire_time = now + (60 * (((int) type == 'b') ?
00176 ((chan->ban_time == 0) ? 0L : chan->ban_time) :
00177 (((int) type == 'e') ? ((chan->exempt_time == 0) ?
00178 0L : chan->exempt_time) :
00179 ((chan->invite_time == 0) ?
00180 0L : chan->invite_time))));
00181
00182 if (options && !strcasecmp(options, "sticky")) sticky = 1;
00183
00184 r = u_addmask((int) type, chan, mask, creator, comment, expire_time, sticky);
00185 if (chan && !r) return(-1);
00186
00187 if ((int) type == 'b') {
00188 me = module_find("irc", 0, 0);
00189 if (me) {
00190 if (chan) (me->funcs[IRC_CHECK_THIS_BAN])(chan, mask, sticky);
00191 else for (chan = chanset; chan; chan = chan->next) {
00192 (me->funcs[IRC_CHECK_THIS_BAN])(chan, mask, sticky);
00193 }
00194 }
00195 return(0);
00196 }
00197
00198 if (chan) add_mode(chan, '+', (int) type, mask);
00199 else {
00200 for (chan = chanset; chan; chan = chan->next) {
00201 add_mode(chan, '+', (int) type, mask);
00202 }
00203 }
00204 return(0);
00205 }
00206
00207 static int script_channel_info(script_var_t *retval)
00208 {
00209 int i;
00210 channel_flag_map_t *flag_map;
00211 struct udef_struct *ul;
00212
00213 retval->type = SCRIPT_ARRAY | SCRIPT_VAR | SCRIPT_FREE;
00214 retval->len = 0;
00215
00216 for (i = 0; channel_info_names[i]; i++) {
00217 script_list_append(retval, script_string(channel_info_names[i], -1));
00218 }
00219
00220 for (flag_map = normal_flag_map; flag_map->name; flag_map++) {
00221 script_list_append(retval, script_string(flag_map->name, -1));
00222 }
00223
00224 for (flag_map = stupid_ircnet_flag_map; flag_map->name; flag_map++) {
00225 script_list_append(retval, script_string(flag_map->name, -1));
00226 }
00227
00228 for (ul = udef; ul; ul = ul->next) {
00229
00230 if (!ul->defined || !ul->name) continue;
00231 script_list_append(retval, script_string(ul->name, -1));
00232 }
00233
00234 return(0);
00235 }
00236
00237 static int script_channel_get(script_var_t *retval, char *channel_name, char *setting)
00238 {
00239 char s[121];
00240 struct chanset_t *chan;
00241 struct udef_struct *ul;
00242 int flagval;
00243
00244 retval->type = SCRIPT_STRING;
00245 retval->len = -1;
00246
00247 chan = findchan_by_dname(channel_name);
00248 if (!chan) return(-1);
00249
00250 #define CHECK(x) !strcmp(setting, x)
00251 if (CHECK("chanmode")) get_mode_protect(chan, s);
00252 else if (CHECK("aop_delay")) sprintf(s, "%d %d", chan->aop_min, chan->aop_max);
00253 else if (CHECK("ban_time")) sprintf(s, "%d", chan->ban_time);
00254 else if (CHECK("exempt_time")) sprintf(s, "%d", chan->exempt_time);
00255 else if (CHECK("invite_time")) sprintf(s, "%d", chan->invite_time);
00256
00257 else if (lookup_flag_by_name(normal_flag_map, setting, &flagval)) sprintf(s, "%d", chan->status & flagval);
00258 else if (lookup_flag_by_name(stupid_ircnet_flag_map, setting, &flagval)) sprintf(s, "%d", chan->ircnet_status & flagval);
00259 else {
00260
00261 for (ul = udef; ul && ul->name; ul = ul->next) {
00262 if (!strcmp(setting, ul->name)) break;
00263 }
00264 if (!ul || !ul->name) {
00265
00266 return(-1);
00267 }
00268 if (ul->type == UDEF_STR) {
00269 char *value;
00270
00271
00272 value = (char *)getudef(ul->values, chan->dname);
00273 if (!value) value = "";
00274
00275 retval->value = value;
00276 return(0);
00277 }
00278 else {
00279
00280 sprintf(s, "%d", getudef(ul->values, chan->dname));
00281 }
00282 }
00283
00284 retval->value = strdup(s);
00285 retval->type |= SCRIPT_FREE;
00286 return(0);
00287 }
00288
00289 static int tcl_channel(ClientData cd, Tcl_Interp *irp, int argc, char *argv[])
00290 {
00291 struct chanset_t *chan;
00292
00293 BADARGS(2, 999, " command ?options?");
00294 if (!strcmp(argv[1], "add")) {
00295 BADARGS(3, 4, " add channel-name ?options-list?");
00296 if (argc == 3)
00297 return tcl_channel_add(irp, argv[2], "");
00298 return tcl_channel_add(irp, argv[2], argv[3]);
00299 }
00300 if (!strcmp(argv[1], "set")) {
00301 BADARGS(3, 999, " set channel-name ?options?");
00302 chan = findchan_by_dname(argv[2]);
00303 if (chan == NULL) {
00304 if (chan_hack == 1)
00305 return TCL_OK;
00306
00307
00308 Tcl_AppendResult(irp, "no such channel record", NULL);
00309 return TCL_ERROR;
00310 }
00311 return tcl_channel_modify(irp, chan, argc - 3, &argv[3]);
00312 }
00313 if (!strcmp(argv[1], "remove")) {
00314 BADARGS(3, 3, " remove channel-name");
00315 chan = findchan_by_dname(argv[2]);
00316 if (chan == NULL) {
00317 Tcl_AppendResult(irp, "no such channel record", NULL);
00318 return TCL_ERROR;
00319 }
00320 remove_channel(chan);
00321 return TCL_OK;
00322 }
00323 Tcl_AppendResult(irp, "unknown channel command: should be one of: ",
00324 "add, set, info, remove", NULL);
00325 return TCL_ERROR;
00326 }
00327
00328 static int lookup_flag_by_name(channel_flag_map_t *map, char *name, int *flagval)
00329 {
00330 channel_flag_map_t *flagmap;
00331
00332 for (flagmap = map; flagmap->name; flagmap++) {
00333 if (!strcmp(flagmap->name, name)) {
00334 *flagval = flagmap->flagval;
00335 return(1);
00336 }
00337 }
00338 return(0);
00339 }
00340
00341
00342
00343 static int tcl_channel_modify(Tcl_Interp * irp, struct chanset_t *chan,
00344 int items, char **item)
00345 {
00346 int i, x = 0, found,
00347 old_status = chan->status,
00348 old_mode_mns_prot = chan->mode_mns_prot,
00349 old_mode_pls_prot = chan->mode_pls_prot;
00350 struct udef_struct *ul = udef;
00351 char s[121];
00352 module_entry *me;
00353
00354 for (i = 0; i < items; i++) {
00355 if (!strcmp(item[i], "chanmode")) {
00356 i++;
00357 if (i >= items) {
00358 if (irp)
00359 Tcl_AppendResult(irp, "channel chanmode needs argument", NULL);
00360 return TCL_ERROR;
00361 }
00362 strlcpy(s, item[i], sizeof s);
00363 set_mode_protect(chan, s);
00364 } else if (!strcmp(item[i], "ban_time")) {
00365 i++;
00366 if (i >= items) {
00367 if (irp)
00368 Tcl_AppendResult(irp, "channel ban_time needs argument", NULL);
00369 return TCL_ERROR;
00370 }
00371 chan->ban_time = atoi(item[i]);
00372 } else if (!strcmp(item[i], "exempt_time")) {
00373 i++;
00374 if (i >= items) {
00375 if (irp)
00376 Tcl_AppendResult(irp, "channel exempt_time needs argument", NULL);
00377 return TCL_ERROR;
00378 }
00379 chan->exempt_time = atoi(item[i]);
00380 } else if (!strcmp(item[i], "invite_time")) {
00381 i++;
00382 if (i >= items) {
00383 if (irp)
00384 Tcl_AppendResult(irp, "channel invite_time needs argument", NULL);
00385 return TCL_ERROR;
00386 }
00387 chan->invite_time = atoi(item[i]);
00388 }
00389 else if (item[i][0] == '+' || item[i][0] == '-') {
00390 int flagval;
00391
00392 if (lookup_flag_by_name(normal_flag_map, item[i]+1, &flagval)) {
00393 if (item[i][0] == '-') chan->status &= ~flagval;
00394 else chan->status |= flagval;
00395 }
00396 else if (lookup_flag_by_name(stupid_ircnet_flag_map, item[i]+1, &flagval)) {
00397 if (item[i][0] == '-') chan->ircnet_status &= ~flagval;
00398 else chan->ircnet_status |= flagval;
00399 }
00400 else {
00401
00402 goto check_for_udef_flags;
00403 }
00404 } else if (!strncmp(item[i], "aop_delay", 9)) {
00405 char *p;
00406 i++;
00407 if (i >= items) {
00408 if (irp)
00409 Tcl_AppendResult(irp, item[i - 1], " needs argument", NULL);
00410 return TCL_ERROR;
00411 }
00412 p = strchr(item[i], ':');
00413 if (p) {
00414 p++;
00415 chan->aop_min = atoi(item[i]);
00416 chan->aop_max = atoi(p);
00417 } else {
00418 chan->aop_min = atoi(item[i]);
00419 chan->aop_max = chan->aop_min;
00420 }
00421 } else {
00422 if (!strncmp(item[i] + 1, "udef_flag_", 10))
00423 initudef(UDEF_FLAG, item[i] + 11, 0);
00424 else if (!strncmp(item[i], "udef_int_", 9))
00425 initudef(UDEF_INT, item[i] + 9, 0);
00426 else if (!strncmp(item[i], "udef_str_", 9))
00427 initudef(UDEF_STR, item[i] + 9, 0);
00428 check_for_udef_flags:
00429 found = 0;
00430 for (ul = udef; ul; ul = ul->next) {
00431 if (ul->type == UDEF_FLAG &&
00432
00433 (!strcasecmp(item[i] + 1, ul->name) ||
00434
00435 (!strncmp(item[i] + 1, "udef_flag_", 10) &&
00436 !strcasecmp(item[i] + 11, ul->name)))) {
00437 if (item[i][0] == '+')
00438 setudef(ul, chan->dname, 1);
00439 else
00440 setudef(ul, chan->dname, 0);
00441 found = 1;
00442 break;
00443 } else if (ul->type == UDEF_INT &&
00444
00445 (!strcasecmp(item[i], ul->name) ||
00446
00447 (!strncmp(item[i], "udef_int_", 9) &&
00448 !strcasecmp(item[i] + 9, ul->name)))) {
00449 i++;
00450 if (i >= items) {
00451 if (irp)
00452 Tcl_AppendResult(irp, "this setting needs an argument", NULL);
00453 return TCL_ERROR;
00454 }
00455 setudef(ul, chan->dname, atoi(item[i]));
00456 found = 1;
00457 break;
00458 }
00459 else if (ul->type == UDEF_STR && (!strcasecmp(item[i], ul->name) || (!strncmp(item[i], "udef_str_", 9) && !strcasecmp(item[i] + 9, ul->name)))) {
00460 char *val;
00461 i++;
00462 if (i >= items) {
00463 if (irp) Tcl_AppendResult(irp, "this setting needs an argument", NULL);
00464 return TCL_ERROR;
00465 }
00466 val = (char *)getudef(ul->values, chan->dname);
00467 if (val) free(val);
00468
00469 val = malloc(3 * strlen(item[i]) + 10);
00470 convert_element(item[i], val);
00471 val = realloc(val, strlen(val)+1);
00472 setudef(ul, chan->dname, (int)val);
00473 found = 1;
00474 break;
00475 }
00476 }
00477 if (!found) {
00478 if (irp && item[i][0])
00479 Tcl_AppendResult(irp, "illegal channel option: ", item[i], NULL);
00480 x++;
00481 }
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 if (protect_readonly || chan_hack) {
00491 if (((old_status ^ chan->status) & CHAN_INACTIVE) &&
00492 module_find("irc", 0, 0)) {
00493 if (channel_inactive(chan) &&
00494 (chan->status & (CHAN_ACTIVE | CHAN_PEND)))
00495 dprintf(DP_SERVER, "PART %s\n", chan->name);
00496 if (!channel_inactive(chan) &&
00497 !(chan->status & (CHAN_ACTIVE | CHAN_PEND)))
00498 dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ?
00499 chan->name : chan->dname,
00500 chan->channel.key[0] ?
00501 chan->channel.key : chan->key_prot);
00502 }
00503 if ((old_status ^ chan->status) &
00504 (CHAN_ENFORCEBANS | CHAN_OPONJOIN | CHAN_AUTOVOICE)) {
00505 if ((me = module_find("irc", 0, 0)))
00506 (me->funcs[IRC_RECHECK_CHANNEL])(chan, 1);
00507 } else if (old_mode_pls_prot != chan->mode_pls_prot ||
00508 old_mode_mns_prot != chan->mode_mns_prot)
00509 if ((me = module_find("irc", 1, 2)))
00510 (me->funcs[IRC_RECHECK_CHANNEL_MODES])(chan);
00511 }
00512 if (x > 0)
00513 return TCL_ERROR;
00514 return TCL_OK;
00515 }
00516
00517 static int script_channels(script_var_t *retval)
00518 {
00519 struct chanset_t *chan;
00520
00521 retval->type = SCRIPT_ARRAY | SCRIPT_VAR | SCRIPT_FREE;
00522 retval->len = 0;
00523
00524 for (chan = chanset; chan; chan = chan->next) {
00525 script_list_append(retval, script_string(chan->dname, -1));
00526 }
00527 return(0);
00528 }
00529
00530 static int script_listmask(void *type, script_var_t *retval, char *channel_name)
00531 {
00532 script_var_t *mlist;
00533 struct chanset_t *chan = NULL;
00534 struct maskrec *m, *masks;
00535
00536 retval->type = SCRIPT_ARRAY | SCRIPT_VAR | SCRIPT_FREE;
00537 retval->len = 0;
00538
00539 if (channel_name) {
00540 chan = findchan_by_dname(channel_name);
00541 if (!chan) return(-1);
00542 }
00543 if ((int) type == 'b') masks = (chan ? chan->bans : global_bans);
00544 else if ((int) type == 'I') masks = (chan ? chan->invites : global_invites);
00545 else if ((int) type == 'e') masks = (chan ? chan->exempts : global_exempts);
00546 else return(-1);
00547
00548 for (m = masks; m; m = m->next) {
00549 mlist = script_list(6, script_string(m->mask, -1),
00550 script_string(m->desc, -1),
00551 script_int(m->expire),
00552 script_int(m->added),
00553 script_int(m->lastactive),
00554 script_string(m->user, -1)
00555 );
00556 script_list_append(retval, mlist);
00557 }
00558 return(0);
00559 }
00560
00561
00562 static int tcl_savechannels(ClientData cd, Tcl_Interp *irp, int argc,
00563 char *argv[])
00564 {
00565 BADARGS(1, 1, "");
00566 if (!chanfile[0]) {
00567 Tcl_AppendResult(irp, "no channel file");
00568 return TCL_ERROR;
00569 }
00570 write_channels();
00571 return TCL_OK;
00572 }
00573
00574
00575 static int tcl_loadchannels(ClientData cd, Tcl_Interp *irp, int argc,
00576 char *argv[])
00577 {
00578 BADARGS(1, 1, "");
00579 if (!chanfile[0]) {
00580 Tcl_AppendResult(irp, "no channel file");
00581 return TCL_ERROR;
00582 }
00583 setstatic = 0;
00584 read_channels(1);
00585 return TCL_OK;
00586 }
00587
00588 static int script_channel_valid(char *channel_name)
00589 {
00590 return findchan_by_dname(channel_name) ? 1 : 0;
00591 }
00592
00593
00594 static int tcl_isdynamic(ClientData cd, Tcl_Interp *irp, int argc,
00595 char *argv[])
00596 {
00597 struct chanset_t *chan;
00598
00599 BADARGS(2, 2, " channel");
00600 chan = findchan_by_dname(argv[1]);
00601 if (chan != NULL)
00602 if (!channel_static(chan)) {
00603 Tcl_AppendResult(irp, "1", NULL);
00604 return TCL_OK;
00605 }
00606 Tcl_AppendResult(irp, "0", NULL);
00607 return TCL_OK;
00608 }
00609
00610 static char *script_channel_getinfo(struct userrec *u, char *channel_name)
00611 {
00612 struct chanuserrec *ch;
00613
00614 ch = get_chanrec(u, channel_name);
00615 if (ch && ch->info) return ch->info;
00616 return "";
00617 }
00618
00619 static int script_channel_setinfo(struct userrec *u, char *channel_name, char *info)
00620 {
00621 if (!findchan_by_dname(channel_name)) return(-1);
00622 set_handle_chaninfo(userlist, u->handle, channel_name, info);
00623 return(0);
00624 }
00625
00626 static int script_setlaston(struct userrec *u, int when, char *chan)
00627 {
00628 if (!when) when = now;
00629
00630 if (!chan || !findchan_by_dname(chan)) chan = "*";
00631 set_handle_laston(chan, u, when);
00632 return(0);
00633 }
00634
00635 static int script_chanrec_add(struct userrec *u, char *chan)
00636 {
00637 if (!findchan_by_dname(chan)) return(-1);
00638 if (get_chanrec(u, chan) != NULL) return(-1);
00639 add_chanrec(u, chan);
00640 return(0);
00641 }
00642
00643 static int script_chanrec_del(struct userrec *u, char *chan)
00644 {
00645 if (get_chanrec(u, chan) != NULL) return(-1);
00646 del_chanrec(u, chan);
00647 return(0);
00648 }
00649
00650 static int script_chanrec_exists(struct userrec *u, char *chan)
00651 {
00652 if (!findchan_by_dname(chan)) return(0);
00653 if (get_chanrec(u, chan) != NULL) return(1);
00654 return(0);
00655 }
00656
00657 static void init_masklist(masklist *m)
00658 {
00659 m->mask = calloc(1, 1);
00660 m->who = NULL;
00661 m->next = NULL;
00662 }
00663
00664
00665
00666 static void init_channel(struct chanset_t *chan, int reset)
00667 {
00668 chan->channel.maxmembers = 0;
00669 chan->channel.mode = 0;
00670 chan->channel.members = 0;
00671 if (!reset)
00672 chan->channel.key = calloc(1, 1);
00673
00674 chan->channel.ban = (masklist *) malloc(sizeof(masklist));
00675 init_masklist(chan->channel.ban);
00676
00677 chan->channel.exempt = (masklist *) malloc(sizeof(masklist));
00678 init_masklist(chan->channel.exempt);
00679
00680 chan->channel.invite = (masklist *) malloc(sizeof(masklist));
00681 init_masklist(chan->channel.invite);
00682
00683 chan->channel.member = (memberlist *) malloc(sizeof(memberlist));
00684 chan->channel.member->nick[0] = 0;
00685 chan->channel.member->next = NULL;
00686 chan->channel.topic = NULL;
00687 }
00688
00689 static void clear_masklist(masklist *m)
00690 {
00691 masklist *temp;
00692
00693 for (; m; m = temp) {
00694 temp = m->next;
00695 if (m->mask)
00696 free(m->mask);
00697 if (m->who)
00698 free(m->who);
00699 free(m);
00700 }
00701 }
00702
00703
00704
00705 static void clear_channel(struct chanset_t *chan, int reset)
00706 {
00707 memberlist *m, *m1;
00708
00709 if (chan->channel.topic)
00710 free(chan->channel.topic);
00711 for (m = chan->channel.member; m; m = m1) {
00712 m1 = m->next;
00713 free(m);
00714 }
00715
00716 clear_masklist(chan->channel.ban);
00717 chan->channel.ban = NULL;
00718 clear_masklist(chan->channel.exempt);
00719 chan->channel.exempt = NULL;
00720 clear_masklist(chan->channel.invite);
00721 chan->channel.invite = NULL;
00722
00723 if (reset)
00724 init_channel(chan, 1);
00725 }
00726
00727
00728
00729 static int tcl_channel_add(Tcl_Interp *irp, char *newname, char *options)
00730 {
00731 struct chanset_t *chan;
00732 int items;
00733 int ret = TCL_OK;
00734 int join = 0;
00735 char **item;
00736 char buf[2048], buf2[256];
00737
00738 if (!newname || !newname[0] || (strchr(CHANMETA, newname[0]) == NULL)) {
00739 if (irp)
00740 Tcl_AppendResult(irp, "invalid channel prefix", NULL);
00741 return TCL_ERROR;
00742 }
00743
00744 if (strchr(newname, ',') != NULL) {
00745 if (irp)
00746 Tcl_AppendResult(irp, "invalid channel name", NULL);
00747 return TCL_ERROR;
00748 }
00749
00750 convert_element(glob_chanmode, buf2);
00751 simple_sprintf(buf, "chanmode %s ", buf2);
00752 strlcat(buf, glob_chanset, sizeof buf);
00753 strlcat(buf, options, sizeof buf);
00754
00755 if (Tcl_SplitList(NULL, buf, &items, &item) != TCL_OK)
00756 return TCL_ERROR;
00757 if ((chan = findchan_by_dname(newname))) {
00758
00759 chan->status &= ~CHAN_FLAGGED;
00760 } else {
00761 chan = calloc(1, sizeof(struct chanset_t));
00762 chan->limit_prot = 0;
00763 chan->limit = 0;
00764
00765 chan->ban_time = global_ban_time;
00766 chan->exempt_time = global_exempt_time;
00767 chan->invite_time = global_invite_time;
00768 chan->aop_min = global_aop_min;
00769 chan->aop_max = global_aop_max;
00770
00771
00772
00773
00774
00775 strlcpy(chan->dname, newname, sizeof chan->dname);
00776
00777
00778 init_channel(chan, 0);
00779 list_append((struct list_type **) &chanset, (struct list_type *) chan);
00780 join = 1;
00781 }
00782 if (setstatic)
00783 chan->status |= CHAN_STATIC;
00784
00785
00786
00787
00788
00789 if ((tcl_channel_modify(irp, chan, items, item) != TCL_OK) && !chan_hack) {
00790 ret = TCL_ERROR;
00791 }
00792 Tcl_Free((char *) item);
00793 if (join && !channel_inactive(chan) && module_find("irc", 0, 0))
00794 dprintf(DP_SERVER, "JOIN %s %s\n", chan->dname, chan->key_prot);
00795 return ret;
00796 }
00797
00798 static int tcl_setudef(ClientData cd, Tcl_Interp *irp, int argc, char *argv[])
00799 {
00800 int type;
00801
00802 BADARGS(3, 3, " type name");
00803 if (!strcasecmp(argv[1], "flag"))
00804 type = UDEF_FLAG;
00805 else if (!strcasecmp(argv[1], "int"))
00806 type = UDEF_INT;
00807
00808 else if (!strcasecmp(argv[1], "str"))
00809 type = UDEF_STR;
00810 else {
00811 Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int, str", NULL);
00812 return TCL_ERROR;
00813 }
00814 initudef(type, argv[2], 1);
00815 return TCL_OK;
00816 }
00817
00818 static int tcl_renudef(ClientData cd, Tcl_Interp *irp, int argc, char *argv[])
00819 {
00820 struct udef_struct *ul;
00821 int type, found = 0;
00822
00823 BADARGS(4, 4, " type oldname newname");
00824 if (!strcasecmp(argv[1], "flag"))
00825 type = UDEF_FLAG;
00826 else if (!strcasecmp(argv[1], "int"))
00827 type = UDEF_INT;
00828
00829 else if (!strcasecmp(argv[1], "str"))
00830 type = UDEF_STR;
00831 else {
00832 Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int, str", NULL);
00833 return TCL_ERROR;
00834 }
00835 for (ul = udef; ul; ul = ul->next) {
00836 if (ul->type == type && !strcasecmp(ul->name, argv[2])) {
00837 free(ul->name);
00838 ul->name = strdup(argv[3]);
00839 found = 1;
00840 }
00841 }
00842 if (!found) {
00843 Tcl_AppendResult(irp, "not found", NULL);
00844 return TCL_ERROR;
00845 } else
00846 return TCL_OK;
00847 }
00848
00849 static int tcl_deludef(ClientData cd, Tcl_Interp *irp, int argc, char *argv[])
00850 {
00851 struct udef_struct *ul, *ull;
00852 int type, found = 0;
00853
00854 BADARGS(3, 3, " type name");
00855 if (!strcasecmp(argv[1], "flag"))
00856 type = UDEF_FLAG;
00857 else if (!strcasecmp(argv[1], "int"))
00858 type = UDEF_INT;
00859
00860 else if (!strcasecmp(argv[1], "str"))
00861 type = UDEF_STR;
00862 else {
00863 Tcl_AppendResult(irp, "invalid type. Must be one of: flag, int, str", NULL);
00864 return TCL_ERROR;
00865 }
00866 for (ul = udef; ul; ul = ul->next) {
00867 ull = ul->next;
00868 if (!ull)
00869 break;
00870 if (ull->type == type && !strcasecmp(ull->name, argv[2])) {
00871 ul->next = ull->next;
00872 free(ull->name);
00873 free_udef_chans(ull->values, ull->type);
00874 free(ull);
00875 found = 1;
00876 }
00877 }
00878 if (udef) {
00879 if (udef->type == type && !strcasecmp(udef->name, argv[2])) {
00880 ul = udef->next;
00881 free(udef->name);
00882 free_udef_chans(udef->values, udef->type);
00883 free(udef);
00884 udef = ul;
00885 found = 1;
00886 }
00887 }
00888 if (!found) {
00889 Tcl_AppendResult(irp, "not found", NULL);
00890 return TCL_ERROR;
00891 } else
00892 return TCL_OK;
00893 }
00894
00895 static script_command_t channel_script_cmds[] = {
00896 {"", "newban", script_newsomething, (void *)'b', 1, "ssssss", "channel mask creator comment ?lifetime? ?sticky?", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS},
00897 {"", "newinvite", script_newsomething, (void *)'I', 1, "ssssss", "channel mask creator comment ?lifetime? ?sticky?", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS},
00898 {"", "newexempt", script_newsomething, (void *)'e', 1, "ssssss", "channel mask creator comment ?lifetime? ?sticky?", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS},
00899
00900 {"", "killban", script_killsomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00901 {"", "killinvite", script_killsomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00902 {"", "killexempt", script_killsomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00903
00904 {"", "matchban", script_matchsomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00905 {"", "matchinvite", script_matchsomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00906 {"", "matchexempt", script_matchsomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00907
00908 {"", "isban", script_issomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00909 {"", "isinvite", script_issomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00910 {"", "isexempt", script_issomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00911
00912 {"", "ispermban", script_ispermsomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00913 {"", "isperminvite", script_ispermsomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00914 {"", "ispermexempt", script_ispermsomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00915
00916 {"", "isbansticky", script_isstickysomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00917 {"", "isinvitesticky", script_isstickysomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00918 {"", "isexemptsticky", script_isstickysomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00919
00920 {"", "stickban", script_sticksomething, (void *)'b', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00921 {"", "stickinvite", script_sticksomething, (void *)'I', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00922 {"", "stickexempt", script_sticksomething, (void *)'e', 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00923
00924 {"", "unstickban", script_sticksomething, (void *)('b'+256), 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00925 {"", "unstickinvite", script_sticksomething, (void *)('I'+256), 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00926 {"", "unstickexempt", script_sticksomething, (void *)('e'+256), 1, "ss", "?channel? mask", SCRIPT_INTEGER, SCRIPT_PASS_CDATA | SCRIPT_VAR_ARGS | SCRIPT_VAR_FRONT},
00927
00928 {"", "listbans", script_listmask, (void *)'b', 0, "s", "?channel?", 0, SCRIPT_VAR_ARGS | SCRIPT_PASS_RETVAL | SCRIPT_PASS_CDATA},
00929 {"", "listinvites", script_listmask, (void *)'I', 0, "s", "?channel?", 0, SCRIPT_VAR_ARGS | SCRIPT_PASS_RETVAL | SCRIPT_PASS_CDATA},
00930 {"", "listexempts", script_listmask, (void *)'e', 0, "s", "?channel?", 0, SCRIPT_VAR_ARGS | SCRIPT_PASS_RETVAL | SCRIPT_PASS_CDATA},
00931
00932 {"", "channel_get", script_channel_get, NULL, 2, "ss", "channel setting", 0, SCRIPT_PASS_RETVAL},
00933 {"", "channel_info", script_channel_info, NULL, 0, "", "", 0, SCRIPT_PASS_RETVAL},
00934 {"", "channel_valid", script_channel_valid, NULL, 1, "s", "channel", SCRIPT_INTEGER, 0},
00935 {"", "channel_setinfo", script_channel_setinfo, NULL, 2, "Uss", "handle channel ?info?", SCRIPT_INTEGER, SCRIPT_VAR_ARGS},
00936 {"", "channel_getinfo", script_channel_getinfo, NULL, 2, "Us", "handle channel", SCRIPT_STRING, 0},
00937 {"", "channels", script_channels, NULL, 0, "", "", 0, SCRIPT_PASS_RETVAL},
00938
00939 {"", "chanrec_add", script_chanrec_add, NULL, 2, "Us", "handle channel", SCRIPT_INTEGER, 0},
00940 {"", "chanrec_del", script_chanrec_del, NULL, 2, "Us", "handle channel", SCRIPT_INTEGER, 0},
00941 {"", "chanrec_exists", script_chanrec_exists, NULL, 2, "Us", "handle channel", SCRIPT_INTEGER, 0},
00942
00943 {"", "setlaston", script_setlaston, NULL, 2, "Uis", "handle when ?channel?", SCRIPT_INTEGER, SCRIPT_VAR_ARGS},
00944
00945 {0}
00946 };
00947
00948 static tcl_cmds channels_cmds[] =
00949 {
00950 {"channel", tcl_channel},
00951 {"savechannels", tcl_savechannels},
00952 {"loadchannels", tcl_loadchannels},
00953 {"isdynamic", tcl_isdynamic},
00954 {"setudef", tcl_setudef},
00955 {"renudef", tcl_renudef},
00956 {"deludef", tcl_deludef},
00957 {NULL, NULL}
00958 };