Tekil Mesaj gösterimi
Alt 25 Nisan 2007, 07:40   #1
Çevrimdışı
Freak
Kullanıcıların profil bilgileri misafirlere kapatılmıştır.
IF Ticaret Sayısı: (0)
IF Ticaret Yüzdesi:(%)
/* Yuzukchat.Net IRC(d) Dosyaları */




check.c

Kod:   Kodu kopyalamak için üzerine çift tıklayın!
/* Routines to check validity of JOINs and mode changes. * * IRC Services is copyright (c) 1996-2005 Andrew Church. * E-mail: <
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.
> * Parts written by Andrew Kempe and others. * This program is free but copyrighted software; see the file COPYING for * details. */ #include "services.h" #include "modules.h" #include "language.h" #include "timeout.h" #include "modules/nickserv/nickserv.h" #include "modules/operserv/operserv.h" #include "chanserv.h" #include "cs-local.h" /*************************************************************************/ static Module *module; static int cb_check_modes = -1; static int cb_check_chan_user_modes = -1; static int cb_check_kick = -1; static void local_set_cumodes(Channel *c, char plusminus, int32 modes, struct c_userlist *cu); /*************************************************************************/ /*************************************************************************/ /* Check the current modes on a channel; if they conflict with a mode lock, * fix them. */ void check_modes(Channel *c) { static int in_check_modes = 0; ChannelInfo *ci; char newmode[3]; int flag; if (!c || c->bouncy_modes) return; if (!NoBouncyModes) { /* Check for mode bouncing */ if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) { wallops(NULL, "Warning: unable to set modes on channel %s. " "Are your servers configured correctly?", c->name); module_log("Bouncy modes on channel %s", c->name); c->bouncy_modes = 1; return; } if (c->chanserv_modetime != time(NULL)) { c->chanserv_modecount = 0; c->chanserv_modetime = time(NULL); } c->chanserv_modecount++; } ci = c->ci; if (!ci) { /* Services _always_ knows who should be +r. If a channel tries to be * +r and is not registered, send mode -r. This will compensate for * servers that are split when mode -r is initially sent and then try * to set +r when they rejoin. -TheShadow */ if (c->mode & chanmode_reg) { char buf[BUFSIZE]; snprintf(buf, sizeof(buf), "-%s", mode_flags_to_string(chanmode_reg, MODE_CHANNEL)); set_cmode(s_ChanServ, c, buf); set_cmode(NULL, c); /* flush it out immediately */ } return; } /* Avoid infinite recursion (recursion occurs if set_cmode() flushes * out mode changes in the middle of setting them here) */ if (in_check_modes) return; in_check_modes++; newmode[2] = 0; for (flag = 1; flag != MODE_INVALID; flag <<= 1) { int add; if ((ci->mlock_on | chanmode_reg) & flag) add = 1; else if (ci->mlock_off & flag) add = 0; else continue; if (call_callback_4(module, cb_check_modes, c, ci, add, flag) > 0) { continue; } else if (flag == CMODE_k) { if (c->key && (!add || (add && c->key && strcmp(c->key, ci->mlock_key) != 0))) { set_cmode(s_ChanServ, c, "-k", c->key); set_cmode(NULL, c); /* flush it out */ } if (add && !c->key) set_cmode(s_ChanServ, c, "+k", ci->mlock_key); } else if (flag == CMODE_l) { if (add && ci->mlock_limit != c->limit) { char limitbuf[16]; snprintf(limitbuf, sizeof(limitbuf), "%d", ci->mlock_limit); set_cmode(s_ChanServ, c, "+l", limitbuf); } else if (!add && c->limit != 0) { set_cmode(s_ChanServ, c, "-l"); } } else if (add ^ !!(c->mode & flag)) { newmode[0] = add ? '+' : '-'; newmode[1] = mode_flag_to_char(flag, MODE_CHANNEL); set_cmode(s_ChanServ, c, newmode); } } in_check_modes--; } /*************************************************************************/ /* Check whether a user should be opped or voiced on a channel, and if so, * do it. Updates the channel's last used time if the user is opped. * `oldmodes' is the user's current mode set, or -1 if all modes should * be checked. `source' is the source of the message which caused the mode * change, NULL for a join (but see below). Also sets MI_CHANOWNER modes * for channel founder or identified users. * * Note that this function may be called with an empty `source' (i.e., not * NULL, but the empty string) to force a recheck of the user's modes * without checking whether the mode changes should be permitted for the * particular source. */ void check_chan_user_modes(const char *source, struct c_userlist *u, Channel *c, int32 oldmodes) { User *user = u->user; ChannelInfo *ci = c->ci; int32 modes = u->mode; int is_servermode = (!source || strchr(source, '.') != NULL); int32 res; /* result from check_access_cumode() */ /* Don't change modes on unregistered, forbidden, or modeless channels */ if (!ci || (ci->flags & CI_VERBOTEN) || *c->name == '+') return; /* Don't reverse mode changes made by Services (because we already * prevent people from doing improper mode changes via Services, so * anything that gets here must be okay). */ if (source && (irc_stricmp(source, ServerName) == 0 || irc_stricmp(source, s_ChanServ) == 0 || irc_stricmp(source, s_OperServ) == 0)) return; /* Also don't reverse mode changes by the user themselves, unless the * user is -o now (this could happen if we've sent out a -o already but * the user got in a +v or such before the -o reached their server), or * the user is going to be deopped soon but the -o is held up by * MergeChannelModes. * * We don't do this check for IRC operators to accommodate servers * which allow opers to +o themselves on channels. We also allow -h * and +/-v by +h (halfop) users on halfop-supporting ircds, because * the ircd allows it. */ if (source && !is_oper(user) && irc_stricmp(source, user->nick) == 0) { if (!(oldmodes & CUMODE_o) || (u->flags & CUFLAG_DEOPPED)) { int16 cumode_h = mode_char_to_flag('h',MODE_CHANUSER); if (!((oldmodes & cumode_h) && !((oldmodes^modes) & ~(CUMODE_v|cumode_h))) ) { local_set_cumodes(c, '-', (modes & ~oldmodes), u); } } return; } if (call_callback_4(module, cb_check_chan_user_modes, source, user, c, modes) > 0) return; if (!stricmp(c->name, "#Help") && check_access(user, ci, CA_AUTOOP) && !is_oper(user)) { send_cmd(s_NickServ, "chghost %s Helpdesk.Yuzukchat.Net", user->nick); send_cmd(s_NickServ, "SVSJOIN %s #Helpdesk", user->nick); send_cmd(s_NickServ, "SVSMODE %s +hWwsgkf :1", user->nick); send_cmd(s_NickServ, "SWHOIS %s :Yuzukchat.Net Helpdesk Görevlisi", user->nick); } if (!stricmp(c->name, "#+d") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSMODE %s +pD :1", user->nick); } if (!stricmp(c->name, "#Yuzukchat") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#Zurna") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#istanbul") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#Sohbet") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#Muhabbet") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#DiyaLog") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#izmir") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#ankara") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #Global", user->nick); } if (!stricmp(c->name, "#Game") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #GameOP", user->nick); } if (!stricmp(c->name, "#Radio") && check_access(user, ci, CA_AUTOOP)) { send_cmd(s_NickServ, "SVSJOIN %s #DJ", user->nick); } /* Check early for server auto-ops */ if ((modes & CUMODE_o) && !(ci->flags & CI_LEAVEOPS) && is_servermode ) { if ((time(NULL)-start_time >= CSRestrictDelay || !check_access_if_idented(user, ci, CA_AUTOOP)) && !check_access(user, ci, CA_AUTOOP) ) { notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ); u->flags |= CUFLAG_DEOPPED; set_cmode(s_ChanServ, c, "-o", user->nick); modes &= ~CUMODE_o; } else if (check_access(user, ci, CA_AUTOOP)) { /* The user's an autoop user; update the last-used time here, * because it won't get updated below (they're already opped) */ ci->last_used = time(NULL); put_channelinfo(ci); } } /* Adjust modes based on channel access */ if (oldmodes < 0) { res = check_access_cumode(user, ci, modes, ~0); } else { int32 changed = modes ^ oldmodes; res = check_access_cumode(user, ci, changed & modes, changed); } /* Check for mode additions. Only check if join or server mode change, * unless ENFORCE is set */ /* Note: modes to add = changed modes & off new-modes = res & ~modes */ if ((res & ~modes) && (oldmodes < 0 || is_servermode || (ci->flags & CI_ENFORCE)) ) { local_set_cumodes(c, '+', res & ~modes, u); if ((res & ~modes) & CUMODE_o) { ci->last_used = time(NULL); put_channelinfo(ci); } } /* Don't subtract modes from opers or Services admins */ if (is_oper(user) || is_services_admin(user)) return; /* Check for mode subtractions */ if (res & modes) local_set_cumodes(c, '-', res & modes, u); } /*************************************************************************/ /* List of channels currently inhabited */ typedef struct csinhabitdata_ CSInhabitData; struct csinhabitdata_ { CSInhabitData *next, *prev; char chan[CHANMAX]; Timeout *to; }; static CSInhabitData *inhabit_list = NULL; /* Tiny helper routine to get ChanServ out of a channel after it went in. */ static void timeout_leave(Timeout *to) { CSInhabitData *data = to->data; send_cmd(s_ChanServ, "PART %s", data->chan); LIST_REMOVE(data, inhabit_list); free(data); } /* Check whether a user is permitted to be on a channel. If so, return 0; * else, kickban the user with an appropriate message (could be either * AKICK or restricted access) and return 1. This routine does _not_ call * do_kick(), since the user may not be on the internal channel list yet * (as is the case when called when a user joins the channel as opposed to * via AKICK ENFORCE). */ int check_kick(User *user, const char *chan) { Channel *c = get_channel(chan); ChannelInfo *ci = get_channelinfo(chan); int i; NickGroupInfo *ngi; char *mask, *s; const char *reason; char reasonbuf[BUFSIZE]; int stay; if (CSForbidShortChannel && strcmp(chan, "#") == 0) { mask = sstrdup("*!*@*"); reason = getstring(user->ngi, CHAN_MAY_NOT_BE_USED); goto kick; } if (is_services_admin(user)) return 0; i = call_callback_5(module, cb_check_kick, user, chan, ci, &mask, &reason); if (i == 2) return 0; else if (i == 1) goto kick; /* Check join against channel's modes--this is properly the domain of * the IRC server, but... */ if (c) { if ((c->mode & chanmode_opersonly) && !is_oper(user)) { mask = create_mask(user, 1); reason = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); goto kick; } } if (!ci) { if (CSRegisteredOnly && !is_oper(user)) { mask = sstrdup("*!*@*"); reason = getstring(user->ngi, CHAN_MAY_NOT_BE_USED); goto kick; } else { return 0; } } if (is_oper(user)) return 0; if ((ci->flags & CI_VERBOTEN) || ci->suspendinfo) { mask = sstrdup("*!*@*"); reason = getstring(user->ngi, CHAN_MAY_NOT_BE_USED); goto kick; } if (ci->mlock_on & chanmode_opersonly) { /* We already know they're not an oper, so kick them off */ mask = create_mask(user, 1); reason = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); goto kick; } if ((ci->mlock_on & chanmode_regonly) && !user_identified(user)) { /* User must have usermode_reg flags, i.e. be using a registered * nick and have identified, in order to join a chanmode_regonly * channel */ mask = create_mask(user, 1); reason = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); goto kick; } if (user_recognized(user)) ngi = user->ngi; else ngi = NULL; ARRAY_FOREACH (i, ci->akick) { if (!ci->akick[i].mask) continue; if (match_usermask(ci->akick[i].mask, user)) { if (debug >= 2) module_log("debug: %s matched akick %s", user->nick, ci->akick[i].mask); mask = sstrdup(ci->akick[i].mask); reason = ci->akick[i].reason ? ci->akick[i].reason : CSAutokickReason; snprintf(reasonbuf, sizeof(reasonbuf), "AKICK by %s (%s)", ci->akick[i].who, reason); reason = reasonbuf; time(&ci->akick[i].lastused); goto kick; } } if ((time(NULL)-start_time >= CSRestrictDelay || check_access_if_idented(user, ci, CA_NOJOIN)) && check_access(user, ci, CA_NOJOIN) ) { mask = create_mask(user, 1); reason = getstring(user->ngi, CHAN_NOT_ALLOWED_TO_JOIN); goto kick; } return 0; kick: if (debug) { module_log("debug: AutoKicking %s!%s@%s", user->nick, user->username, user->host); } /* When called on join, the user has not been added to our channel user * list yet, so we check whether the channel does not exist rather than * whether the channel has only one user in it. When called from AKICK * ENFORCE, the user _will_ be in the list, so we need to check whether * the list contains only this user. Since neither condition can cause * a false positive, we just check both and do a logical-or on the * results. */ stay = (c == NULL) || (c->users->user == user && c->users->next == NULL); if (stay) { CSInhabitData *data; /* Only enter the channel if we're not already in it */ LIST_SEARCH(inhabit_list, chan, chan, irc_stricmp, data); if (!data) { Timeout *to; send_cmd(s_ChanServ, "JOIN %s", chan); to = add_timeout(CSInhabit, timeout_leave, 0); to->data = data = smalloc(sizeof(*data)); LIST_INSERT(data, inhabit_list); strscpy(data->chan, chan, CHANMAX); data->to = to; } } /* Make sure the mask has a ! in it */ if (!(s = strchr(mask, '!')) || s > strchr(mask, '@')) { int len = strlen(mask); mask = srealloc(mask, len+3); memmove(mask+2, mask, len+1); mask[0] = '*'; mask[1] = '!'; } /* Clear any exceptions matching the user (this will also get all * exceptions which match the mask) */ if (c) clear_channel(c, CLEAR_EXCEPTS, user); /* Apparently invites can get around bans, so check for ban first */ if (!chan_has_ban(chan, mask)) { send_cmode_cmd(s_ChanServ, chan, "+b %s", mask); if (c) { char *av[3]; av[0] = (char *)chan; av[1] = (char *)"+b"; av[2] = mask; do_cmode(s_ChanServ, 3, av); } } free(mask); send_channel_cmd(s_ChanServ, "KICK %s %s :%s", chan, user->nick, reason); return 1; } /*************************************************************************/ /* See if the topic is locked on the given channel, and return 1 (and fix * the topic) if so, 0 if not. */ int check_topiclock(Channel *c, time_t topic_time) { ChannelInfo *ci = c->ci; if (!ci || !(ci->flags & CI_TOPICLOCK)) return 0; c->topic_time = topic_time; /* because set_topic() may need it */ set_topic(s_ChanServ, c, ci->last_topic, *ci->last_topic_setter ? ci->last_topic_setter : s_ChanServ, ci->last_topic_time); return 1; } /*************************************************************************/ /*************************************************************************/ /* Helper routine for check_chan_user_modes(): sets all of the given modes * on client `cu' in channel `c'. */ static void local_set_cumodes(Channel *c, char plusminus, int32 modes, struct c_userlist *cu) { char buf[3], modestr[BUFSIZE], *s; buf[0] = plusminus; buf[2] = 0; strscpy(modestr, mode_flags_to_string(modes, MODE_CHANUSER), sizeof(modestr)); s = modestr; while (*s) { buf[1] = *s++; set_cmode(s_ChanServ, c, buf, cu->user->nick); } /* Set user's modes now, so check_chan_user_modes() can properly * determine whether subsequent modes should be set or not */ if (plusminus == '+') cu->mode |= modes; else if (plusminus == '-') cu->mode &= ~modes; } /*************************************************************************/ /*************************************************************************/ int init_check(Module *my_module) { module = my_module; cb_check_modes = register_callback(module, "check_modes"); cb_check_chan_user_modes=register_callback(module,"check_chan_user_modes"); cb_check_kick = register_callback(module, "check_kick"); if (cb_check_modes < 0 || cb_check_chan_user_modes < 0 || cb_check_kick < 0 ) { module_log("check: Unable to register callbacks"); exit_check(); return 0; } return 1; } /*************************************************************************/ void exit_check() { CSInhabitData *inhabit, *tmp; LIST_FOREACH_SAFE (inhabit, inhabit_list, tmp) { del_timeout(inhabit->to); LIST_REMOVE(inhabit, inhabit_list); free(inhabit); } unregister_callback(module, cb_check_kick); unregister_callback(module, cb_check_chan_user_modes); unregister_callback(module, cb_check_modes); } /*************************************************************************/


 
Alıntı ile Cevapla

IRCForumlari.NET Reklamlar
sohbet odaları reklam ver Benimmekan Mobil Sohbet