Exemplo n.º 1
0
/* Makes a simple ban and kicks the target
 * @param requester The user requesting the kickban
 * @param ci The channel
 * @param u The user being kicked
 * @param reason The reason
 */
void bot_raw_ban(User *requester, ChannelInfo *ci, User *u, const Anope::string &reason)
{
	if (!u || !ci)
		return;

	if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u)
	{
		ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", translate(requester, ACCESS_DENIED));
		return;
	}

	AccessGroup u_access = ci->AccessFor(u), req_access = ci->AccessFor(requester);
	if (ci->HasFlag(CI_PEACE) && u != requester && u_access >= req_access)
		return;

	if (matches_list(ci->c, u, CMODE_EXCEPT))
	{
		ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", translate(requester, _("User matches channel except.")));
		return;
	}

	Anope::string mask;
	get_idealban(ci, u, mask);

	ci->c->SetMode(NULL, CMODE_BAN, mask);

	/* Check if we need to do a signkick or not -GD */
	if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !req_access.HasPriv("SIGNKICK")))
		ci->c->Kick(ci->bi, u, "%s (%s)", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str(), requester->nick.c_str());
	else
		ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str());
}
Exemplo n.º 2
0
void do_enforce_restricted(Channel * c)
{
    struct c_userlist *user;
    struct c_userlist *next;
    ChannelInfo *ci;
    int16 old_nojoin_level;
    char mask[BUFSIZE];
    char *reason;
    char *av[3];
    User *u;

    if (!(ci = c->ci))
        return;

    if (debug)
        alog("debug: cs_enforce: Enforcing RESTRICTED on %s", c->name);

    old_nojoin_level = ci->levels[CA_NOJOIN];
    if (ci->levels[CA_NOJOIN] < 0)
        ci->levels[CA_NOJOIN] = 0;

    user = c->users;
    do {
        next = user->next;
        u = user->user;
        if (check_access(u, c->ci, CA_NOJOIN)) {
            get_idealban(ci, u, mask, sizeof(mask));
            reason = getstring(u->na, CHAN_NOT_ALLOWED_TO_JOIN);
            anope_cmd_mode(whosends(ci), ci->name, "+b %s %lu", mask,
                           time(NULL));
            anope_cmd_kick(whosends(ci), ci->name, u->nick, "%s", reason);
            av[0] = ci->name;
            av[1] = u->nick;
            av[2] = reason;
            do_kick(s_ChanServ, 3, av);
        }
        user = next;
    } while (user);

    ci->levels[CA_NOJOIN] = old_nojoin_level;
}
Exemplo n.º 3
0
static int do_tban(User * u)
{
    char mask[BUFSIZE];
    Channel *c;
    User *u2 = NULL;

    char *buffer = moduleGetLastBuffer();
    char *chan;
    char *nick;
    char *time;

    chan = myStrGetToken(buffer, ' ', 0);
    nick = myStrGetToken(buffer, ' ', 1);
    time = myStrGetToken(buffer, ' ', 2);

    if (time && chan && nick) {

        if (!(c = findchan(chan))) {
            notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
        } else if (!(u2 = finduser(nick))) {
            notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, nick);
        } else {
            if (canBanUser(c, u, u2)) {
                get_idealban(c->ci, u2, mask, sizeof(mask));
                addBan(c, dotime(time), mask);
                mySendResponse(u, chan, mask, time);
            }
        }
    } else {
        myFullHelpSyntax(u);
    }
    if (time)
        free(time);
    if (nick)
        free(nick);
    if (chan)
        free(chan);

    return MOD_CONT;
}
Exemplo n.º 4
0
void do_enforce_cmode_R(Channel * c)
{
    struct c_userlist *user;
    struct c_userlist *next;
    ChannelInfo *ci;
    char mask[BUFSIZE];
    char *reason;
    char *av[3];
    User *u;
    CBMode *cbm;

    if (!(ci = c->ci))
        return;

    if (debug)
        alog("debug: cs_enforce: Enforcing mode +R on %s", c->name);

    user = c->users;
    do {
        next = user->next;
        u = user->user;
        if (!nick_identified(u)) {
            get_idealban(ci, u, mask, sizeof(mask));
            reason = getstring(u->na, CHAN_NOT_ALLOWED_TO_JOIN);
            if (((cbm = &cbmodes['R'])->flag == 0)
                || !(c->mode & cbm->flag))
                anope_cmd_mode(whosends(ci), ci->name, "+b %s %lu", mask,
                               time(NULL));
            anope_cmd_kick(whosends(ci), ci->name, u->nick, "%s", reason);
            av[0] = ci->name;
            av[1] = u->nick;
            av[2] = reason;
            do_kick(s_ChanServ, 3, av);
        }
        user = next;
    } while (user);
}
Exemplo n.º 5
0
/**
 * The /cs ban command.
 * @param u The user who issued the command
 * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing.
 **/
int do_ban(User * u)
{
    char *chan = strtok(NULL, " ");
    char *params = strtok(NULL, " ");
    char *reason = strtok(NULL, "");

    Channel *c;
    ChannelInfo *ci;
    User *u2;

    int is_same;

    if (!reason) {
        reason = "Requested";
    } else {
        if (strlen(reason) > 200)
            reason[200] = '\0';
    }

    if (!chan) {
        struct u_chanlist *uc, *next;

        /* Bans the user on every channels he is on. */

        for (uc = u->chans; uc; uc = next) {
            next = uc->next;
            if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN)
                && check_access(u, ci, CA_BANME)) {
                char *av[3];
                char mask[BUFSIZE];

                /*
                 * Dont ban/kick the user on channels where he is excepted
                 * to prevent services <-> server wars.
                 */
                if (ircd->except) {
                    if (is_excepted(ci, u))
                        notice_lang(s_ChanServ, u, CHAN_EXCEPTED,
                                    u->nick, ci->name);
                    continue;
                }
                if (is_protected(u)) {
                    notice_lang(s_ChanServ, u, PERMISSION_DENIED);
                    continue;
                }

                av[0] = sstrdup("+b");
                get_idealban(ci, u, mask, sizeof(mask));
                av[1] = mask;
                xanadu_cmd_mode(whosends(ci), uc->chan->name, "+b %s",
                               av[1]);
                chan_set_modes(s_ChanServ, uc->chan, 2, av, 1);
                free(av[0]);

                if ((ci->flags & CI_SIGNKICK)
                    || ((ci->flags & CI_SIGNKICK_LEVEL)
                        && !check_access(u, ci, CA_SIGNKICK)))
                    xanadu_cmd_kick(whosends(ci), ci->name, u->nick,
                                   "%s (%s)", reason, u->nick);
                else
                    xanadu_cmd_kick(whosends(ci), ci->name, u->nick, "%s",
                                   reason);
                av[0] = ci->name;
                av[1] = u->nick;
                av[2] = reason;
                do_kick(s_ChanServ, 3, av);
            }
        }

        return MOD_CONT;
    } else if (!params) {
        params = u->nick;
    }

    is_same = (params == u->nick) ? 1 : (stricmp(params, u->nick) == 0);

    if (!(c = findchan(chan))) {
        notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
    } else if (!(ci = c->ci)) {
        notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
    } else if (ci->flags & CI_VERBOTEN) {
        notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
    } else if (is_same ? !(u2 = u) : !(u2 = finduser(params))) {
        notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, params);
    } else if (!is_same ? !check_access(u, ci, CA_BAN) :
               !check_access(u, ci, CA_BANME)) {
        notice_lang(s_ChanServ, u, ACCESS_DENIED);
    } else if (!is_same && (ci->flags & CI_PEACE)
               && (get_access(u2, ci) >= get_access(u, ci))) {
        notice_lang(s_ChanServ, u, PERMISSION_DENIED);
        /*
         * Dont ban/kick the user on channels where he is excepted
         * to prevent services <-> server wars.
         */
    } else if (ircd->except && is_excepted(ci, u2)) {
        notice_lang(s_ChanServ, u, CHAN_EXCEPTED, u2->nick, ci->name);
    } else if (ircd->protectedumode && is_protected(u2)) {
        notice_lang(s_ChanServ, u, PERMISSION_DENIED);
    } else {
        char *av[3];
        char mask[BUFSIZE];

        av[0] = sstrdup("+b");
        get_idealban(ci, u2, mask, sizeof(mask));
        av[1] = mask;
        xanadu_cmd_mode(whosends(ci), c->name, "+b %s", av[1]);
        chan_set_modes(s_ChanServ, c, 2, av, 1);
        free(av[0]);

        /* We still allow host banning while not allowing to kick */
        if (!is_on_chan(c, u2))
            return MOD_CONT;

        if ((ci->flags & CI_SIGNKICK)
            || ((ci->flags & CI_SIGNKICK_LEVEL)
                && !check_access(u, ci, CA_SIGNKICK)))
            xanadu_cmd_kick(whosends(ci), ci->name, params, "%s (%s)",
                           reason, u->nick);
        else
            xanadu_cmd_kick(whosends(ci), ci->name, params, "%s", reason);

        av[0] = ci->name;
        av[1] = params;
        av[2] = reason;
        do_kick(s_ChanServ, 3, av);
    }
    return MOD_CONT;
}
Exemplo n.º 6
0
int do_akick(User * u, Channel *c, char *cmd, char *mask, char *reason) {
	ChannelInfo *ci = c->ci;
	AutoKick *akick;
	int i;
	struct c_userlist *cu = NULL, *next = NULL;
	User *u2;
	char *argv[3];
	int count = 0;

	if (!cmd || (!mask && (!stricmp(cmd, "ADD") || !stricmp(cmd, "STICK")
		|| !stricmp(cmd, "UNSTICK") || !stricmp(cmd, "DEL")))) {
		noticeLang(ci->bi->nick, u, LANG_AKICK_SYNTAX);
	} else if (!check_access(u, ci, CA_AKICK) && !is_services_admin(u)) {
		notice_lang(ci->bi->nick, u, ACCESS_DENIED);
	} else if (stricmp(cmd, "ADD") == 0) {
		NickAlias *na = findnick(mask), *na2;
		User *target = finduser(mask);
		NickCore *nc = NULL;
		char *nick, *user, *host;
		int freemask = 0;

		if (readonly) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DISABLED);
			return MOD_CONT;
		}

		if (!na) {
			if (target) {
				char tmp[BUFSIZE];
				mask = NULL;
				freemask = 1;
				get_idealban(ci, target, tmp, BUFSIZE);
				mask = sstrdup(tmp);
			} else {
				split_usermask(mask, &nick, &user, &host);
				mask = scalloc(strlen(nick) + strlen(user) + strlen(host) + 3, 1);
				freemask = 1;
				sprintf(mask, "%s!%s@%s", nick, user, host);

				free(nick);
				free(user);
				free(host);
			}
		} else {
			if (na->status & NS_VERBOTEN) {
				notice_lang(ci->bi->nick, u, NICK_X_FORBIDDEN, mask);
				return MOD_CONT;
			}
			nc = na->nc;
		}

		/* Check excepts BEFORE we get this far */
		if (ircd->except) {
			if (is_excepted_mask(ci, mask) == 1) {
				notice_lang(ci->bi->nick, u, CHAN_EXCEPTED, mask, c->name);
				if (freemask) free(mask);
				return MOD_CONT;
			}
		}

		/* Check whether target nick has equal/higher access 
		 * or whether the mask matches a user with higher/equal access ~ Viper */
		if ((ci->flags & CI_PEACE) && nc) {
			if ((nc == ci->founder) || (get_access_nc(nc, ci) >= get_access(u, ci))) {
				notice_lang(s_ChanServ, u, PERMISSION_DENIED);
				if (freemask)
					free(mask);
				return MOD_CONT;
			}
		} else if ((ci->flags & CI_PEACE)) {
			char buf[BUFSIZE];
			/* Match against all currently online users with equal or
			 * higher access. - Viper */
			for (i = 0; i < 1024; i++) {
				for (u2 = userlist[i]; u2; u2 = u2->next) {
					if (is_founder(u2, ci) || (get_access(u2, ci) >= get_access(u, ci))) {
						if (match_usermask(mask, u2)) {
							notice_lang(s_ChanServ, u, PERMISSION_DENIED);
							free(mask);
							return MOD_CONT;
						}
					}
				}
			}

			/* Match against the lastusermask of all nickalias's with equal
			 * or higher access. ~ Viper */
			for (i = 0; i < 1024; i++) {
				for (na2 = nalists[i]; na2; na2 = na2->next) {
					if (na2->status & NS_VERBOTEN)
						continue;

					if (na2->nc && ((na2->nc == ci->founder) || (get_access_nc(na2->nc, ci) 
							>= get_access(u, ci)))) {
						snprintf(buf, BUFSIZE, "%s!%s", na2->nick, na2->last_usermask);
						if (match_wild_nocase(mask, buf)) {
							notice_lang(s_ChanServ, u, PERMISSION_DENIED);
							free(mask);
							return MOD_CONT;
						}
					}
				}
			}
		}

		for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
			if (!(akick->flags & AK_USED))
				continue;
			if ((akick->flags & AK_ISNICK) ? akick->u.nc == nc : stricmp(akick->u.mask, mask) == 0) {
				notice_lang(ci->bi->nick, u, CHAN_AKICK_ALREADY_EXISTS, (akick->flags & AK_ISNICK) ? akick->u.nc->
					display : akick->u.mask, c->name);
				if (freemask) free(mask);
				return MOD_CONT;
			}
		}

		/* All entries should be in use so we don't have to go over
		 * the entire list. We simply add new entries at the end. */
		if (ci->akickcount >= CSAutokickMax) {
			notice_lang(s_ChanServ, u, CHAN_AKICK_REACHED_LIMIT, CSAutokickMax);
			if (freemask) free(mask);
			return MOD_CONT;
		}
		ci->akickcount++;
		ci->akick = srealloc(ci->akick, sizeof(AutoKick) * ci->akickcount);

		akick = &ci->akick[i];
		akick->flags = AK_USED;
		if (nc) {
			akick->flags |= AK_ISNICK;
			akick->u.nc = nc;
		} else {
			akick->u.mask = sstrdup(mask);
		}
		akick->creator = sstrdup(u->nick);
		akick->addtime = time(NULL);
		if (reason) {
			if (strlen(reason) > 200)
				reason[200] = '\0';
			akick->reason = sstrdup(reason);
		} else {
			akick->reason = NULL;
		}

		/* Auto ENFORCE #63 */
		cu = c->users;
		while (cu) {
			next = cu->next;
			if (check_kick(cu->user, c->name, c->creation_time)) {
				argv[0] = sstrdup(c->name);
				argv[1] = sstrdup(cu->user->nick);
				if (akick->reason)
					argv[2] = sstrdup(akick->reason);
				else
					argv[2] = sstrdup("none");

				do_kick(ci->bi->nick, 3, argv);

				free(argv[2]);
				free(argv[1]);
				free(argv[0]);
				count++;

			}
			cu = next;
		}
		alog("%s: %s!%s@%s added akick for %s to %s",
				ci->bi->nick, u->nick, u->username, u->host, mask, c->name);
		notice_lang(ci->bi->nick, u, CHAN_AKICK_ADDED, mask, c->name);

		if (count)
			notice_lang(ci->bi->nick, u, CHAN_AKICK_ENFORCE_DONE, c->name, count);

		if (freemask) free(mask);

	} else if (stricmp(cmd, "STICK") == 0) {
		NickAlias *na;
		NickCore *nc;

		if (readonly) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DISABLED);
			return MOD_CONT;
		}

		if (ci->akickcount == 0) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_LIST_EMPTY, ci->name);
			return MOD_CONT;
		}

		na = findnick(mask);
		nc = (na ? na->nc : NULL);

		for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
			if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK))
				continue;
			if (!stricmp(akick->u.mask, mask))
				break;
		}

		if (i == ci->akickcount) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_NOT_FOUND, mask, ci->name);
			return MOD_CONT;
		}

		akick->flags |= AK_STUCK;
		alog("%s: %s!%s@%s set STICK on akick %s on %s",
				ci->bi->nick, u->nick, u->username, u->host, akick->u.mask, ci->name);
		notice_lang(ci->bi->nick, u, CHAN_AKICK_STUCK, akick->u.mask, ci->name);

		if (ci->c)
			stick_mask(ci, akick);

	} else if (stricmp(cmd, "UNSTICK") == 0) {
		NickAlias *na;
		NickCore *nc;

		if (readonly) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DISABLED);
			return MOD_CONT;
		}

		if (ci->akickcount == 0) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_LIST_EMPTY, ci->name);
			return MOD_CONT;
		}

		na = findnick(mask);
		nc = (na ? na->nc : NULL);

		for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
			if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK))
				continue;
			if (!stricmp(akick->u.mask, mask))
				break;
		}

		if (i == ci->akickcount) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_NOT_FOUND, mask, ci->name);
			return MOD_CONT;
		}

		akick->flags &= ~AK_STUCK;
		alog("%s: %s!%s@%s unset STICK on akick %s on %s",
				ci->bi->nick, u->nick, u->username, u->host, akick->u.mask, ci->name);
		notice_lang(ci->bi->nick, u, CHAN_AKICK_UNSTUCK, akick->u.mask, ci->name);

	} else if (stricmp(cmd, "DEL") == 0) {
		int deleted, a, b;

		if (readonly) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DISABLED);
			return MOD_CONT;
		}

		if (ci->akickcount == 0) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_LIST_EMPTY, c->name);
			return MOD_CONT;
		}

		/* Special case: is it a number/list?  Only do search if it isn't. */
		if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
			int count, last = -1;
			deleted = process_numlist(mask, &count, akick_del_callback, u, ci, &last);
			if (!deleted) {
				if (count == 1) {
					notice_lang(ci->bi->nick, u, CHAN_AKICK_NO_SUCH_ENTRY, last, ci->name);
				} else {
					notice_lang(ci->bi->nick, u, CHAN_AKICK_NO_MATCH, ci->name);
				}
			} else if (deleted == 1) {
				alog("%s: %s!%s@%s deleted 1 akick on %s",
						ci->bi->nick, u->nick, u->username, u->host, ci->name);
				notice_lang(ci->bi->nick, u, CHAN_AKICK_DELETED_ONE, ci->name);
			} else {
				alog("%s: %s!%s@%s deleted %d akicks on %s",
						ci->bi->nick, u->nick, u->username, u->host, deleted, ci->name);
				notice_lang(ci->bi->nick, u, CHAN_AKICK_DELETED_SEVERAL, deleted, ci->name);
			}
		} else {
			NickAlias *na = findnick(mask);
			NickCore *nc = (na ? na->nc : NULL);

			for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
				if (!(akick->flags & AK_USED))
					continue;
				if (((akick->flags & AK_ISNICK) && akick->u.nc == nc) || (!(akick->flags & AK_ISNICK)
					&& stricmp(akick->u.mask, mask) == 0))
					break;
			}
			if (i == ci->akickcount) {
				notice_lang(ci->bi->nick, u, CHAN_AKICK_NOT_FOUND, mask, c->name);
				return MOD_CONT;
			}
			alog("%s: %s!%s@%s deleted akick %s on %s",
					ci->bi->nick, u->nick, u->username, u->host, mask, c->name);
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DELETED, mask, c->name);
			akick_del(u, akick);
			deleted = 1;
		}
		if (deleted) {
			/* Reordering - DrStein */
			for (b = 0; b < ci->akickcount; b++) {
				if (ci->akick[b].flags & AK_USED) {
					for (a = 0; a < ci->akickcount; a++) {
					if (a > b)
						break;
						if (!(ci->akick[a].flags & AK_USED)) {
							ci->akick[a].flags = ci->akick[b].flags;
							if (ci->akick[b].flags & AK_ISNICK) {
								ci->akick[a].u.nc = ci->akick[b].u.nc;
							} else {
								ci->akick[a].u.mask = sstrdup(ci->akick[b].u.mask);
							}
							/* maybe we should first check whether there
							is a reason before we sstdrup it -Certus */
							if (ci->akick[b].reason)
								ci->akick[a].reason = sstrdup(ci->akick[b].reason);
							else
								ci->akick[a].reason = NULL;
							ci->akick[a].creator = sstrdup(ci->akick[b].creator);
							ci->akick[a].addtime = ci->akick[b].addtime;

							akick_del(u, &ci->akick[b]);
							break;
						}
					}
				}
			}

			/* After reordering only the entries at the end could still be empty.
			 * We ll free the places no longer in use... - Viper */
			for (i = ci->akickcount - 1; i >= 0; i--) {
				if (ci->akick[i].flags & AK_USED)
					break;

				ci->akickcount--;
			}
			ci->akick = srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount);
		}
    } else if (stricmp(cmd, "LIST") == 0) {
		int sent_header = 0;

		if (ci->akickcount == 0) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_LIST_EMPTY, c->name);
			return MOD_CONT;
		}
		if (mask && isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
			process_numlist(mask, NULL, akick_list_callback, u, ci, &sent_header);
		} else {
			for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
				if (!(akick->flags & AK_USED))
					continue;
				if (mask) {
					if (!(akick->flags & AK_ISNICK) && !my_match_wild_nocase(mask, akick->u.mask))
						continue;
					if ((akick->flags & AK_ISNICK) && !my_match_wild_nocase(mask, akick->u.nc->display))
						continue;
				}
				akick_list(u, i, ci, &sent_header);
			}
		}
		if (!sent_header)
		notice_lang(ci->bi->nick, u, CHAN_AKICK_NO_MATCH, c->name);

	} else if (stricmp(cmd, "VIEW") == 0) {
		int sent_header = 0;

		if (ci->akickcount == 0) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_LIST_EMPTY, c->name);
			return MOD_CONT;
		}
		if (mask && isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
			process_numlist(mask, NULL, akick_view_callback, u, ci, &sent_header);
		} else {
			for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
				if (!(akick->flags & AK_USED))
					continue;
				if (mask) {
					if (!(akick->flags & AK_ISNICK) && !my_match_wild_nocase(mask, akick->u.mask))
						continue;
					if ((akick->flags & AK_ISNICK) && !my_match_wild_nocase(mask, akick->u.nc->display))
						continue;
				}
				akick_view(u, i, ci, &sent_header);
			}
		}
		if (!sent_header)
		notice_lang(ci->bi->nick, u, CHAN_AKICK_NO_MATCH, c->name);

	} else if (stricmp(cmd, "ENFORCE") == 0) {
		struct c_userlist *cu = NULL, *next = NULL;
		char *argv[3];
		int count = 0;

		if (!c) {
			notice_lang(ci->bi->nick, u, CHAN_X_NOT_IN_USE, ci->name);
			return MOD_CONT;
		}

		cu = c->users;

		while (cu) {
			next = cu->next;
			if (check_kick(cu->user, c->name, c->creation_time)) {
				argv[0] = sstrdup(c->name);
				argv[1] = sstrdup(cu->user->nick);
				argv[2] = sstrdup(CSAutokickReason);

				do_kick(ci->bi->nick, 3, argv);

				free(argv[2]);
				free(argv[1]);
				free(argv[0]);

				count++;
			}
			cu = next;
		}

		notice_lang(ci->bi->nick, u, CHAN_AKICK_ENFORCE_DONE, ci->name, count);

	} else if (stricmp(cmd, "CLEAR") == 0) {

		if (readonly) {
			notice_lang(ci->bi->nick, u, CHAN_AKICK_DISABLED);
			return MOD_CONT;
		}

		for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
			if (!(akick->flags & AK_USED))
				continue;
			akick_del(u, akick);
		}

		free(ci->akick);
		ci->akick = NULL;
		ci->akickcount = 0;

		alog("%s: %s!%s@%s cleared akicks on %s",
				ci->bi->nick, u->nick, u->username, u->host, ci->name);
		notice_lang(ci->bi->nick, u, CHAN_AKICK_CLEAR, ci->name);

	} else {
		noticeLang(ci->bi->nick, u, LANG_AKICK_SYNTAX);
	}
	return MOD_CONT;
}