cs_akick.c

Go to the documentation of this file.
00001 /* ChanServ core functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  *
00012  */
00013 /*************************************************************************/
00014 
00015 #include "module.h"
00016 
00017 
00018 static int do_akick(User * u);
00019 static void myChanServHelp(User * u);
00020 static int get_access_nc(NickCore *nc, ChannelInfo *ci);
00021 
00028 int AnopeInit(int argc, char **argv)
00029 {
00030     Command *c;
00031 
00032     moduleAddAuthor("Anope");
00033     moduleAddVersion(VERSION_STRING);
00034     moduleSetType(CORE);
00035 
00036     c = createCommand("AKICK", do_akick, NULL, CHAN_HELP_AKICK, -1, -1, -1,
00037                       -1);
00038     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00039 
00040     moduleSetChanHelp(myChanServHelp);
00041 
00042     return MOD_CONT;
00043 }
00044 
00048 void AnopeFini(void)
00049 {
00050 
00051 }
00052 
00053 
00054 
00059 static void myChanServHelp(User * u)
00060 {
00061     notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AKICK);
00062 }
00063 
00069  /* `last' is set to the last index this routine was called with */
00070 static int akick_del(User * u, AutoKick * akick)
00071 {
00072     if (!(akick->flags & AK_USED))
00073         return 0;
00074     if (akick->flags & AK_ISNICK) {
00075         akick->u.nc = NULL;
00076     } else {
00077         free(akick->u.mask);
00078         akick->u.mask = NULL;
00079     }
00080     if (akick->reason) {
00081         free(akick->reason);
00082         akick->reason = NULL;
00083     }
00084     if (akick->creator) {
00085         free(akick->creator);
00086         akick->creator = NULL;
00087     }
00088     akick->addtime = 0;
00089     akick->flags = 0;
00090     return 1;
00091 }
00092 
00093 static int akick_del_callback(User * u, int num, va_list args)
00094 {
00095     ChannelInfo *ci = va_arg(args, ChannelInfo *);
00096     int *last = va_arg(args, int *);
00097 
00098     *last = num;
00099 
00100     if (num < 1 || num > ci->akickcount)
00101         return 0;
00102 
00103     return akick_del(u, &ci->akick[num - 1]);
00104 }
00105 
00106 
00107 static int akick_list(User * u, int index, ChannelInfo * ci, int *sent_header)
00108 {
00109     AutoKick *akick = &ci->akick[index];
00110 
00111     if (!(akick->flags & AK_USED))
00112         return 0;
00113     if (!*sent_header) {
00114         notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name);
00115         *sent_header = 1;
00116     }
00117 
00118     notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_FORMAT, index + 1,
00119                 ((akick->flags & AK_ISNICK) ? akick->u.nc->
00120                  display : akick->u.mask),
00121                 (akick->reason ? akick->
00122                  reason : getstring(u->na, NO_REASON)));
00123     return 1;
00124 }
00125 
00126 static int akick_list_callback(User * u, int num, va_list args)
00127 {
00128     ChannelInfo *ci = va_arg(args, ChannelInfo *);
00129     int *sent_header = va_arg(args, int *);
00130     if (num < 1 || num > ci->akickcount)
00131         return 0;
00132     return akick_list(u, num - 1, ci, sent_header);
00133 }
00134 
00135 static int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header)
00136 {
00137     AutoKick *akick = &ci->akick[index];
00138     char timebuf[64];
00139     struct tm tm;
00140 
00141     if (!(akick->flags & AK_USED))
00142         return 0;
00143     if (!*sent_header) {
00144         notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name);
00145         *sent_header = 1;
00146     }
00147 
00148     if (akick->addtime) {
00149         tm = *localtime(&akick->addtime);
00150         strftime_lang(timebuf, sizeof(timebuf), u,
00151                       STRFTIME_SHORT_DATE_FORMAT, &tm);
00152     } else {
00153         snprintf(timebuf, sizeof(timebuf), getstring(u->na, UNKNOWN));
00154     }
00155 
00156     notice_lang(s_ChanServ, u,
00157                 ((akick->
00158                   flags & AK_STUCK) ? CHAN_AKICK_VIEW_FORMAT_STUCK :
00159                  CHAN_AKICK_VIEW_FORMAT), index + 1,
00160                 ((akick->flags & AK_ISNICK) ? akick->u.nc->
00161                  display : akick->u.mask),
00162                 akick->creator ? akick->creator : getstring(u->na,
00163                                                             UNKNOWN),
00164                 timebuf,
00165                 (akick->reason ? akick->
00166                  reason : getstring(u->na, NO_REASON)));
00167     return 1;
00168 }
00169 
00170 static int akick_view_callback(User * u, int num, va_list args)
00171 {
00172     ChannelInfo *ci = va_arg(args, ChannelInfo *);
00173     int *sent_header = va_arg(args, int *);
00174     if (num < 1 || num > ci->akickcount)
00175         return 0;
00176     return akick_view(u, num - 1, ci, sent_header);
00177 }
00178 
00179 
00180 
00181 static int do_akick(User * u)
00182 {
00183     char *chan = strtok(NULL, " ");
00184     char *cmd = strtok(NULL, " ");
00185     char *mask = strtok(NULL, " ");
00186     char *reason = strtok(NULL, "");
00187     ChannelInfo *ci;
00188     AutoKick *akick;
00189     int i;
00190     Channel *c;
00191     struct c_userlist *cu = NULL;
00192     struct c_userlist *next;
00193     User *u2;
00194     char *argv[3];
00195     int count = 0;
00196 
00197     if (!cmd || (!mask && (!stricmp(cmd, "ADD") || !stricmp(cmd, "STICK")
00198                            || !stricmp(cmd, "UNSTICK")
00199                            || !stricmp(cmd, "DEL")))) {
00200 
00201         syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX);
00202     } else if (!(ci = cs_findchan(chan))) {
00203         notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
00204     } else if (ci->flags & CI_VERBOTEN) {
00205         notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
00206     } else if (!check_access(u, ci, CA_AKICK) && !is_services_admin(u)) {
00207         notice_lang(s_ChanServ, u, ACCESS_DENIED);
00208     } else if (stricmp(cmd, "ADD") == 0) {
00209         NickAlias *na = findnick(mask), *na2;
00210         NickCore *nc = NULL;
00211         char *nick, *user, *host;
00212         int freemask = 0;
00213 
00214         if (readonly) {
00215             notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED);
00216             return MOD_CONT;
00217         }
00218 
00219         if (!na) {
00220             split_usermask(mask, &nick, &user, &host);
00221             mask =
00222                 scalloc(strlen(nick) + strlen(user) + strlen(host) + 3, 1);
00223             freemask = 1;
00224             sprintf(mask, "%s!%s@%s", nick, user, host);
00225             free(nick);
00226             free(user);
00227             free(host);
00228         } else {
00229             if (na->status & NS_VERBOTEN) {
00230                 notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, mask);
00231                 return MOD_CONT;
00232             }
00233             nc = na->nc;
00234         }
00235 
00236         /* Check excepts BEFORE we get this far */
00237         if (ircd->except) {
00238             if (is_excepted_mask(ci, mask) == 1) {
00239                 notice_lang(s_ChanServ, u, CHAN_EXCEPTED, mask, chan);
00240                 if (freemask)
00241                     free(mask);
00242                 return MOD_CONT;
00243             }
00244         }
00245 
00246         /* Check whether target nick has equal/higher access 
00247          * or whether the mask matches a user with higher/equal access - Viper */
00248         if ((ci->flags & CI_PEACE) && nc) {
00249             if ((nc == ci->founder) || (get_access_nc(nc, ci) >= get_access(u, ci))) {
00250                 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00251                 if (freemask)
00252                     free(mask);
00253                 return MOD_CONT;
00254             }
00255         } else if ((ci->flags & CI_PEACE)) {
00256             char buf[BUFSIZE];
00257             /* Match against all currently online users with equal or
00258              * higher access. - Viper */
00259             for (i = 0; i < 1024; i++) {
00260                 for (u2 = userlist[i]; u2; u2 = u2->next) {
00261                     if (is_founder(u2, ci) || (get_access(u2, ci) >= get_access(u, ci))) {
00262                         if (match_usermask(mask, u2)) {
00263                             notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00264                             free(mask);
00265                             return MOD_CONT;
00266                         }
00267                     }
00268                 }
00269             }
00270 
00271             /* Match against the lastusermask of all nickalias's with equal
00272              * or higher access. - Viper */
00273             for (i = 0; i < 1024; i++) {
00274                 for (na2 = nalists[i]; na2; na2 = na2->next) {
00275                     if (na2->status & NS_VERBOTEN)
00276                         continue;
00277 
00278                     if (na2->nc && ((na2->nc == ci->founder) || (get_access_nc(na2->nc, ci) 
00279                             >= get_access(u, ci)))) {
00280                         snprintf(buf, BUFSIZE, "%s!%s", na2->nick, na2->last_usermask);
00281                         if (match_wild_nocase(mask, buf)) {
00282                             notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00283                             free(mask);
00284                             return MOD_CONT;
00285                         }
00286                     }
00287                 }
00288             }
00289         }
00290 
00291         for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
00292             if (!(akick->flags & AK_USED))
00293                 continue;
00294             if ((akick->flags & AK_ISNICK) ? akick->u.nc == nc
00295                 : stricmp(akick->u.mask, mask) == 0) {
00296                 notice_lang(s_ChanServ, u, CHAN_AKICK_ALREADY_EXISTS,
00297                             (akick->flags & AK_ISNICK) ? akick->u.nc->
00298                             display : akick->u.mask, chan);
00299                 if (freemask)
00300                     free(mask);
00301                 return MOD_CONT;
00302             }
00303         }
00304 
00305         /* All entries should be in use so we don't have to go over
00306          * the entire list. We simply add new entries at the end. */
00307         if (ci->akickcount >= CSAutokickMax) {
00308             notice_lang(s_ChanServ, u, CHAN_AKICK_REACHED_LIMIT, CSAutokickMax);
00309             if (freemask)
00310                 free(mask);
00311             return MOD_CONT;
00312         }
00313         ci->akickcount++;
00314         ci->akick =
00315             srealloc(ci->akick, sizeof(AutoKick) * ci->akickcount);
00316         akick = &ci->akick[i];
00317         akick->flags = AK_USED;
00318         if (nc) {
00319             akick->flags |= AK_ISNICK;
00320             akick->u.nc = nc;
00321         } else {
00322             akick->u.mask = sstrdup(mask);
00323         }
00324         akick->creator = sstrdup(u->nick);
00325         akick->addtime = time(NULL);
00326         if (reason) {
00327             if (strlen(reason) > 200)
00328                 reason[200] = '\0';
00329             akick->reason = sstrdup(reason);
00330         } else {
00331             akick->reason = NULL;
00332         }
00333 
00334         /* Auto ENFORCE #63 */
00335         c = findchan(ci->name);
00336         if (c) {
00337             cu = c->users;
00338             while (cu) {
00339                 next = cu->next;
00340                 if (check_kick(cu->user, c->name, c->creation_time)) {
00341                     argv[0] = sstrdup(c->name);
00342                     argv[1] = sstrdup(cu->user->nick);
00343                     if (akick->reason)
00344                         argv[2] = sstrdup(akick->reason);
00345                     else
00346                         argv[2] = sstrdup("none");
00347 
00348                     do_kick(s_ChanServ, 3, argv);
00349 
00350                     free(argv[2]);
00351                     free(argv[1]);
00352                     free(argv[0]);
00353                     count++;
00354 
00355                 }
00356                 cu = next;
00357             }
00358         }
00359         alog("%s: %s!%s@%s added akick for %s to %s",
00360               s_ChanServ, u->nick, u->username, u->host, mask, chan);
00361         notice_lang(s_ChanServ, u, CHAN_AKICK_ADDED, mask, chan);
00362 
00363         if (count)
00364             notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan,
00365                         count);
00366 
00367         if (freemask)
00368             free(mask);
00369 
00370     } else if (stricmp(cmd, "STICK") == 0) {
00371 
00372         if (readonly) {
00373             notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED);
00374             return MOD_CONT;
00375         }
00376 
00377         if (ci->akickcount == 0) {
00378             notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name);
00379             return MOD_CONT;
00380         }
00381 
00382         for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
00383             if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK))
00384                 continue;
00385             if (!stricmp(akick->u.mask, mask))
00386                 break;
00387         }
00388 
00389         if (i == ci->akickcount) {
00390             notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask,
00391                         ci->name);
00392             return MOD_CONT;
00393         }
00394 
00395         akick->flags |= AK_STUCK;
00396         alog("%s: %s!%s@%s set STICK on akick %s on %s",
00397              s_ChanServ, u->nick, u->username, u->host, akick->u.mask, ci->name);
00398         notice_lang(s_ChanServ, u, CHAN_AKICK_STUCK, akick->u.mask,
00399                     ci->name);
00400 
00401         if (ci->c)
00402             stick_mask(ci, akick);
00403     } else if (stricmp(cmd, "UNSTICK") == 0) {
00404         if (readonly) {
00405             notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED);
00406             return MOD_CONT;
00407         }
00408 
00409         if (ci->akickcount == 0) {
00410             notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name);
00411             return MOD_CONT;
00412         }
00413 
00414         for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
00415             if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK))
00416                 continue;
00417             if (!stricmp(akick->u.mask, mask))
00418                 break;
00419         }
00420 
00421         if (i == ci->akickcount) {
00422             notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask,
00423                         ci->name);
00424             return MOD_CONT;
00425         }
00426 
00427         akick->flags &= ~AK_STUCK;
00428         alog("%s: %s!%s@%s unset STICK on akick %s on %s",
00429              s_ChanServ, u->nick, u->username, u->host, akick->u.mask, ci->name);
00430         notice_lang(s_ChanServ, u, CHAN_AKICK_UNSTUCK, akick->u.mask,
00431                     ci->name);
00432 
00433     } else if (stricmp(cmd, "DEL") == 0) {
00434         int deleted, a, b;
00435 
00436         if (readonly) {
00437             notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED);
00438             return MOD_CONT;
00439         }
00440 
00441         if (ci->akickcount == 0) {
00442             notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan);
00443             return MOD_CONT;
00444         }
00445 
00446         /* Special case: is it a number/list?  Only do search if it isn't. */
00447         if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
00448             int count, last = -1;
00449             deleted = process_numlist(mask, &count, akick_del_callback, u,
00450                                       ci, &last);
00451             if (!deleted) {
00452                 if (count == 1) {
00453                     notice_lang(s_ChanServ, u, CHAN_AKICK_NO_SUCH_ENTRY,
00454                                 last, ci->name);
00455                 } else {
00456                     notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH,
00457                                 ci->name);
00458                 }
00459             } else if (deleted == 1) {
00460                 alog("%s: %s!%s@%s deleted 1 akick on %s",
00461                      s_ChanServ, u->nick, u->username, u->host, ci->name);
00462                 notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_ONE,
00463                             ci->name);
00464             } else {
00465                 alog("%s: %s!%s@%s deleted %d akicks on %s",
00466                      s_ChanServ, u->nick, u->username, u->host, deleted,
00467                      ci->name);
00468                 notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL,
00469                             deleted, ci->name);
00470             }
00471         } else {
00472             NickAlias *na = findnick(mask);
00473             NickCore *nc = (na ? na->nc : NULL);
00474 
00475             for (akick = ci->akick, i = 0; i < ci->akickcount;
00476                  akick++, i++) {
00477                 if (!(akick->flags & AK_USED))
00478                     continue;
00479                 if (((akick->flags & AK_ISNICK) && akick->u.nc == nc)
00480                     || (!(akick->flags & AK_ISNICK)
00481                         && stricmp(akick->u.mask, mask) == 0))
00482                     break;
00483             }
00484             if (i == ci->akickcount) {
00485                 notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask,
00486                             chan);
00487                 return MOD_CONT;
00488             }
00489             alog("%s: %s!%s@%s deleted akick %s on %s",
00490                  s_ChanServ, u->nick, u->username, u->host, mask, chan);
00491             notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED, mask, chan);
00492             akick_del(u, akick);
00493             deleted = 1;
00494         }
00495         if (deleted) {
00496             /* Reordering - DrStein */
00497             for (b = 0; b < ci->akickcount; b++) {
00498                 if (ci->akick[b].flags & AK_USED) {
00499                     for (a = 0; a < ci->akickcount; a++) {
00500                         if (a > b)
00501                             break;
00502                         if (!(ci->akick[a].flags & AK_USED)) {
00503                             ci->akick[a].flags = ci->akick[b].flags;
00504                             if (ci->akick[b].flags & AK_ISNICK) {
00505                                 ci->akick[a].u.nc = ci->akick[b].u.nc;
00506                             } else {
00507                                 ci->akick[a].u.mask =
00508                                     sstrdup(ci->akick[b].u.mask);
00509                             }
00510                             /* maybe we should first check whether there
00511                                is a reason before we sstdrup it -Certus */
00512                             if (ci->akick[b].reason)
00513                                 ci->akick[a].reason =
00514                                     sstrdup(ci->akick[b].reason);
00515                             else
00516                                 ci->akick[a].reason = NULL;
00517                             ci->akick[a].creator =
00518                                 sstrdup(ci->akick[b].creator);
00519                             ci->akick[a].addtime = ci->akick[b].addtime;
00520 
00521                             akick_del(u, &ci->akick[b]);
00522                             break;
00523                         }
00524                     }
00525                 }
00526             }
00527             /* After reordering only the entries at the end could still be empty.
00528              * We ll free the places no longer in use... - Viper */
00529             for (i = ci->akickcount - 1; i >= 0; i--) {
00530                 if (ci->akick[i].flags & AK_USED)
00531                     break;
00532 
00533                 ci->akickcount--;
00534             }
00535             ci->akick =
00536                 srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount);
00537         }
00538     } else if (stricmp(cmd, "LIST") == 0) {
00539         int sent_header = 0;
00540 
00541         if (ci->akickcount == 0) {
00542             notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan);
00543             return MOD_CONT;
00544         }
00545         if (mask && isdigit(*mask) &&
00546             strspn(mask, "1234567890,-") == strlen(mask)) {
00547             process_numlist(mask, NULL, akick_list_callback, u, ci,
00548                             &sent_header);
00549         } else {
00550             for (akick = ci->akick, i = 0; i < ci->akickcount;
00551                  akick++, i++) {
00552                 if (!(akick->flags & AK_USED))
00553                     continue;
00554                 if (mask) {
00555                     if (!(akick->flags & AK_ISNICK)
00556                         && !match_wild_nocase(mask, akick->u.mask))
00557                         continue;
00558                     if ((akick->flags & AK_ISNICK)
00559                         && !match_wild_nocase(mask, akick->u.nc->display))
00560                         continue;
00561                 }
00562                 akick_list(u, i, ci, &sent_header);
00563             }
00564         }
00565         if (!sent_header)
00566             notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan);
00567 
00568     } else if (stricmp(cmd, "VIEW") == 0) {
00569         int sent_header = 0;
00570 
00571         if (ci->akickcount == 0) {
00572             notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan);
00573             return MOD_CONT;
00574         }
00575         if (mask && isdigit(*mask) &&
00576             strspn(mask, "1234567890,-") == strlen(mask)) {
00577             process_numlist(mask, NULL, akick_view_callback, u, ci,
00578                             &sent_header);
00579         } else {
00580             for (akick = ci->akick, i = 0; i < ci->akickcount;
00581                  akick++, i++) {
00582                 if (!(akick->flags & AK_USED))
00583                     continue;
00584                 if (mask) {
00585                     if (!(akick->flags & AK_ISNICK)
00586                         && !match_wild_nocase(mask, akick->u.mask))
00587                         continue;
00588                     if ((akick->flags & AK_ISNICK)
00589                         && !match_wild_nocase(mask, akick->u.nc->display))
00590                         continue;
00591                 }
00592                 akick_view(u, i, ci, &sent_header);
00593             }
00594         }
00595         if (!sent_header)
00596             notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan);
00597 
00598     } else if (stricmp(cmd, "ENFORCE") == 0) {
00599         Channel *c = findchan(ci->name);
00600         struct c_userlist *cu = NULL;
00601         struct c_userlist *next;
00602         char *argv[3];
00603         int count = 0;
00604 
00605         if (!c) {
00606             notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, ci->name);
00607             return MOD_CONT;
00608         }
00609 
00610         cu = c->users;
00611 
00612         while (cu) {
00613             next = cu->next;
00614             if (check_kick(cu->user, c->name, c->creation_time)) {
00615                 argv[0] = sstrdup(c->name);
00616                 argv[1] = sstrdup(cu->user->nick);
00617                 argv[2] = sstrdup(CSAutokickReason);
00618 
00619                 do_kick(s_ChanServ, 3, argv);
00620 
00621                 free(argv[2]);
00622                 free(argv[1]);
00623                 free(argv[0]);
00624 
00625                 count++;
00626             }
00627             cu = next;
00628         }
00629 
00630         notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan, count);
00631 
00632     } else if (stricmp(cmd, "CLEAR") == 0) {
00633 
00634         if (readonly) {
00635             notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED);
00636             return MOD_CONT;
00637         }
00638 
00639         for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
00640             if (!(akick->flags & AK_USED))
00641                 continue;
00642             akick_del(u, akick);
00643         }
00644 
00645         free(ci->akick);
00646         ci->akick = NULL;
00647         ci->akickcount = 0;
00648 
00649         alog("%s: %s!%s@%s cleared akicks on %s",
00650               s_ChanServ, u->nick, u->username, u->host, ci->name);
00651         notice_lang(s_ChanServ, u, CHAN_AKICK_CLEAR, ci->name);
00652 
00653     } else {
00654         syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX);
00655     }
00656     return MOD_CONT;
00657 }
00658 
00659 
00660 static int get_access_nc(NickCore *nc, ChannelInfo *ci)
00661 {
00662     ChanAccess *access;
00663     if (!ci || !nc)
00664         return 0;
00665 
00666     if ((access = get_access_entry(nc, ci)))
00667         return access->level;
00668     return 0;
00669 }
00670 
00671 /* EOF */