src/mod/irc.mod/chan.c File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define CHANNEL_ID_LEN   5

Functions

static memberlistnewmember (struct chanset_t *chan)
static void sync_members (struct chanset_t *chan)
static void update_idle (char *chname, char *nick)
static char * getchanmode (struct chanset_t *chan)
static void check_exemptlist (struct chanset_t *chan, char *from)
static void do_mask (struct chanset_t *chan, masklist *m, char *mask, char mode)
static int detect_chan_flood (char *floodnick, char *floodhost, char *from, struct chanset_t *chan, int which, char *victim)
static char * quickban (struct chanset_t *chan, char *uhost)
static void kick_all (struct chanset_t *chan, char *hostmask, char *comment, int bantype)
static void refresh_ban_kick (struct chanset_t *chan, char *user, char *nick)
static void refresh_exempt (struct chanset_t *chan, char *user)
static void refresh_invite (struct chanset_t *chan, char *user)
static void enforce_bans (struct chanset_t *chan)
static void recheck_bans (struct chanset_t *chan)
static void recheck_exempts (struct chanset_t *chan)
static void recheck_invites (struct chanset_t *chan)
static void resetmasks (struct chanset_t *chan, masklist *m, maskrec *mrec, maskrec *global_masks, char mode)
static void check_this_ban (struct chanset_t *chan, char *banmask, int sticky)
static void recheck_channel_modes (struct chanset_t *chan)
static void check_this_member (struct chanset_t *chan, char *nick, struct flag_record *fr)
static void check_this_user (char *hand, int delete, char *host)
static void recheck_channel (struct chanset_t *chan, int dobans)
static int got324 (char *from, char *msg)
static int got352or4 (struct chanset_t *chan, char *user, char *host, char *nick, char *flags)
static int got352 (char *from, char *msg)
static int got354 (char *from, char *msg)
static int got315 (char *from, char *msg)
static int got367 (char *from, char *origmsg)
static int got368 (char *from, char *msg)
static int got348 (char *from, char *origmsg)
static int got349 (char *from, char *msg)
static int got346 (char *from, char *origmsg)
static int got347 (char *from, char *msg)
static int got405 (char *from, char *msg)
static int got403 (char *from, char *msg)
static int got471 (char *from, char *msg)
static int got473 (char *from, char *msg)
static int got474 (char *from, char *msg)
static int got475 (char *from, char *msg)
static int gotinvite (char *from, char *msg)
static void set_topic (struct chanset_t *chan, char *k)
static int gottopic (char *from, char *msg)
static int got331 (char *from, char *msg)
static int got332 (char *from, char *msg)
static void set_delay (struct chanset_t *chan, char *nick)
static int gotjoin (char *from, char *chname)
static int gotpart (char *from, char *msg)
static int gotkick (char *from, char *origmsg)
static int gotnick (char *from, char *msg)
static int gotquit (char *from, char *msg)
static int gotmsg (char *from, char *msg)
static int gotnotice (char *from, char *msg)

Variables

static time_t last_ctcp = (time_t) 0L
static int count_ctcp = 0
static time_t last_invtime = (time_t) 0L
static char last_invchan [300] = ""
static cmd_t irc_raw []

Define Documentation

#define CHANNEL_ID_LEN   5

Definition at line 37 of file chan.c.

Referenced by got471(), got473(), got474(), got475(), and gotjoin().


Function Documentation

static void check_exemptlist ( struct chanset_t chan,
char *  from 
) [static]

Definition at line 147 of file chan.c.

References add_mode, chanset_t::channel, e, chan_t::exempt, flush_mode(), maskstruct::mask, match_addr, maskstruct::next, prevent_mixing, QUICK, and use_exempts.

Referenced by check_this_member(), cmd_kickban(), detect_chan_flood(), gotjoin(), gotmsg(), gotnotice(), and refresh_ban_kick().

00148 {
00149   masklist *e;
00150   int ok = 0;
00151 
00152   if (!use_exempts)
00153     return;
00154 
00155   for (e = chan->channel.exempt; e->mask[0]; e = e->next)
00156     if (match_addr(e->mask, from)) {
00157       add_mode(chan, '-', 'e', e->mask);
00158       ok = 1;
00159     }
00160   if (prevent_mixing && ok)
00161     flush_mode(chan, QUICK);
00162 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_this_ban ( struct chanset_t chan,
char *  banmask,
int  sticky 
) [static]

Definition at line 638 of file chan.c.

References add_mode, chanset_t::channel, channel_dynamicbans, chanset_t::exempts, global_exempts, HALFOP_CANTDOMODE, isbanned, match_addr, chan_t::member, memstruct::next, memstruct::nick, refresh_ban_kick(), u_match_mask(), UHOSTLEN, use_exempts, user, and memstruct::userhost.

00639 {
00640   memberlist *m;
00641   char user[UHOSTLEN];
00642 
00643   if (HALFOP_CANTDOMODE('b'))
00644     return;
00645 
00646   for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00647     sprintf(user, "%s!%s", m->nick, m->userhost);
00648     if (match_addr(banmask, user) &&
00649         !(use_exempts &&
00650           (u_match_mask(global_exempts, user) ||
00651            u_match_mask(chan->exempts, user))))
00652       refresh_ban_kick(chan, user, m->nick);
00653   }
00654   if (!isbanned(chan, banmask) && (!channel_dynamicbans(chan) || sticky))
00655     add_mode(chan, '+', 'b', banmask);
00656 }

Here is the call graph for this function:

static void check_this_member ( struct chanset_t chan,
char *  nick,
struct flag_record fr 
) [static]

Definition at line 750 of file chan.c.

References add_mode, chanset_t::aop_min, chanset_t::bans, chan_autohalfop, chan_autoop, chan_dehalfop, chan_deop, chan_gvoice, chan_halfop, chan_hashalfop, chan_hasop, chan_hasvoice, chan_kick, chan_op, chan_quiet, chan_sentkick, chan_sentop, chan_voice, channel_autohalfop, channel_autoop, channel_autovoice, channel_bitch, check_exemptlist(), DP_SERVER, dprintf, chanset_t::exempts, memstruct::flags, get_user, glob_autohalfop, glob_autoop, glob_dehalfop, glob_deop, glob_gvoice, glob_halfop, glob_kick, glob_op, glob_quiet, glob_voice, global_bans, global_exempts, global_invites, HALFOP_CANDOMODE, chanset_t::invites, IRC_POLITEKICK, ismember, match_my_nick(), me_halfop(), me_op(), chanset_t::name, memstruct::nick, NOHALFOPS_MODES, NULL, quickban(), refresh_ban_kick(), refresh_invite(), SENTHALFOP, SENTKICK, SENTOP, SENTVOICE, set_delay(), u_match_mask(), UHOSTLEN, use_exempts, use_invites, memstruct::user, USERENTRY_COMMENT, and memstruct::userhost.

Referenced by check_this_user(), gotnick(), and recheck_channel().

00752 {
00753   memberlist *m;
00754   char s[UHOSTLEN], *p;
00755 
00756   m = ismember(chan, nick);
00757   if (!m || match_my_nick(nick) || (!me_op(chan) && !me_halfop(chan)))
00758     return;
00759 
00760 
00761 #ifdef NO_HALFOP_CHANMODES
00762   if (me_op(chan)) {
00763 #else
00764   if (me_op(chan) || me_halfop(chan)) {
00765 #endif
00766     if (HALFOP_CANDOMODE('o')) {
00767       if (chan_hasop(m) && ((chan_deop(*fr) || (glob_deop(*fr) &&
00768           !chan_op(*fr))) || (channel_bitch(chan) && (!chan_op(*fr) &&
00769           !(glob_op(*fr) && !chan_deop(*fr)))))) {
00770         add_mode(chan, '-', 'o', m->nick);
00771       }
00772       if (!chan_hasop(m) && (chan_op(*fr) || (glob_op(*fr) &&
00773           !chan_deop(*fr))) && (channel_autoop(chan) || glob_autoop(*fr) ||
00774           chan_autoop(*fr))) {
00775         if (!chan->aop_min)
00776           add_mode(chan, '+', 'o', m->nick);
00777         else {
00778           set_delay(chan, m->nick);
00779           m->flags |= SENTOP;
00780         }
00781       }
00782     }
00783 
00784     if (HALFOP_CANDOMODE('h')) {
00785       if (chan_hashalfop(m) && ((chan_dehalfop(*fr) || (glob_dehalfop(*fr) &&
00786           !chan_halfop(*fr)) || (channel_bitch(chan) && (!chan_halfop(*fr) &&
00787           !(glob_halfop(*fr) && !chan_dehalfop(*fr)))))))
00788         add_mode(chan, '-', 'h', m->nick);
00789       if (!chan_sentop(m) && !chan_hasop(m) && !chan_hashalfop(m) &&
00790           (chan_halfop(*fr) || (glob_halfop(*fr) && !chan_dehalfop(*fr))) &&
00791           (channel_autohalfop(chan) || glob_autohalfop(*fr) ||
00792           chan_autohalfop(*fr))) {
00793         if (!chan->aop_min)
00794           add_mode(chan, '+', 'h', m->nick);
00795         else {
00796           set_delay(chan, m->nick);
00797           m->flags |= SENTHALFOP;
00798         }
00799       }
00800     }
00801 
00802     if (HALFOP_CANDOMODE('v')) {
00803       if (chan_hasvoice(m) && (chan_quiet(*fr) || (glob_quiet(*fr) &&
00804           !chan_voice(*fr))))
00805         add_mode(chan, '-', 'v', m->nick);
00806       if (!chan_hasvoice(m) && !chan_hasop(m) && !chan_hashalfop(m) &&
00807           (chan_voice(*fr) || (glob_voice(*fr) && !chan_quiet(*fr))) &&
00808           (channel_autovoice(chan) || glob_gvoice(*fr) || chan_gvoice(*fr))) {
00809         if (!chan->aop_min)
00810           add_mode(chan, '+', 'v', m->nick);
00811         else {
00812           set_delay(chan, m->nick);
00813           m->flags |= SENTVOICE;
00814         }
00815       }
00816     }
00817   }
00818 
00819   if (!me_op(chan) && (!me_halfop(chan) ||
00820       (strchr(NOHALFOPS_MODES, 'b') != NULL) ||
00821       (strchr(NOHALFOPS_MODES, 'e') != NULL) ||
00822       (strchr(NOHALFOPS_MODES, 'I') != NULL)))
00823     return;
00824 
00825   sprintf(s, "%s!%s", m->nick, m->userhost);
00826   if (use_invites && (u_match_mask(global_invites, s) ||
00827       u_match_mask(chan->invites, s)))
00828     refresh_invite(chan, s);
00829   if (!(use_exempts && (u_match_mask(global_exempts, s) ||
00830       u_match_mask(chan->exempts, s)))) {
00831     if (u_match_mask(global_bans, s) || u_match_mask(chan->bans, s))
00832       refresh_ban_kick(chan, s, m->nick);
00833     if (!chan_sentkick(m) && (chan_kick(*fr) || glob_kick(*fr)) &&
00834         (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) {
00835       check_exemptlist(chan, s);
00836       quickban(chan, m->userhost);
00837       p = get_user(&USERENTRY_COMMENT, m->user);
00838       dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick,
00839               p ? p : IRC_POLITEKICK);
00840       m->flags |= SENTKICK;
00841     }
00842   }
00843 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_this_user ( char *  hand,
int  delete,
char *  host 
) [static]

Definition at line 845 of file chan.c.

References chanset_t::channel, chanset, check_this_member(), chanset_t::dname, egg_strcasecmp, fixfrom, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, userrec::handle, match_addr, chan_t::member, memstruct::next, chanset_t::next, memstruct::nick, NULL, UHOSTLEN, memstruct::user, and memstruct::userhost.

Referenced by cmd_adduser(), msg_addhost(), and msg_ident().

00846 {
00847   char s[UHOSTLEN];
00848   memberlist *m;
00849   struct userrec *u;
00850   struct chanset_t *chan;
00851   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00852 
00853   for (chan = chanset; chan; chan = chan->next)
00854     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00855       sprintf(s, "%s!%s", m->nick, m->userhost);
00856       u = m->user ? m->user : get_user_by_host(s);
00857       if ((u && !egg_strcasecmp(u->handle, hand) && delete < 2) ||
00858           (!u && delete == 2 && match_addr(host, fixfrom(s)))) {
00859         u = delete ? NULL : u;
00860         get_user_flagrec(u, &fr, chan->dname);
00861         check_this_member(chan, m->nick, &fr);
00862       }
00863     }
00864 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int detect_chan_flood ( char *  floodnick,
char *  floodhost,
char *  from,
struct chanset_t chan,
int  which,
char *  victim 
) [static]

Definition at line 181 of file chan.c.

References chan_t::ban, chanset_t::ban_time, chanset_t::bans, botnetnick, botuserhost, chan_deop, CHAN_FLOOD, chan_friend, chan_hasop, CHAN_MASSDEOP, CHAN_MASSDEOP_KICK, chan_master, chan_op, chan_sentkick, chanset_t::channel, channel_dontkickops, channel_enforcebans, check_exemptlist(), check_tcl_flud(), chanset_t::deopd, chanset_t::dname, do_mask(), DP_MODE, DP_SERVER, dprintf, egg_strcasecmp, chanset_t::exempts, memstruct::flags, FLOOD_CHAN_MAX, FLOOD_CTCP, chanset_t::flood_ctcp_thr, chanset_t::flood_ctcp_time, FLOOD_DEOP, chanset_t::flood_deop_thr, chanset_t::flood_deop_time, FLOOD_JOIN, chanset_t::flood_join_thr, chanset_t::flood_join_time, FLOOD_KICK, chanset_t::flood_kick_thr, chanset_t::flood_kick_time, FLOOD_NICK, chanset_t::flood_nick_thr, chanset_t::flood_nick_time, FLOOD_NOTICE, FLOOD_PRIVMSG, chanset_t::flood_pub_thr, chanset_t::flood_pub_time, chanset_t::floodnum, chanset_t::floodtime, chanset_t::floodwho, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_bot, glob_friend, glob_master, glob_op, global_bans, global_exempts, IRC_FLOODIGNORE3, IRC_FLOODIGNORE4, IRC_FLOODKICK, IRC_JOIN_FLOOD, IRC_MASSKICK, IRC_NICK_FLOOD, isbanned, ismember, memstruct::joined, LOG_JOIN, LOG_MISC, LOG_MODES, match_my_nick(), me_halfop(), me_op(), chan_t::member, chanset_t::name, memstruct::next, memstruct::nick, now, putlog, rfc_casecmp, SENTKICK, simple_sprintf, u_addban(), u_match_mask(), UHOSTLEN, use_exempts, memstruct::userhost, and wild_match.

Referenced by got_deop(), gotjoin(), gotkick(), gotmsg(), gotnick(), and gotnotice().

00183 {
00184   char h[UHOSTLEN], ftype[12], *p;
00185   struct userrec *u;
00186   memberlist *m;
00187   int thr = 0, lapse = 0;
00188   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00189 
00190   if (!chan || (which < 0) || (which >= FLOOD_CHAN_MAX))
00191     return 0;
00192 
00193   /* Okay, make sure i'm not flood-checking myself */
00194   if (match_my_nick(floodnick))
00195     return 0;
00196 
00197   /* My user@host (?) */
00198   if (!egg_strcasecmp(floodhost, botuserhost))
00199     return 0;
00200 
00201   m = ismember(chan, floodnick);
00202 
00203   /* Do not punish non-existant channel members and IRC services like
00204    * ChanServ
00205    */
00206   if (!m && (which != FLOOD_JOIN))
00207     return 0;
00208 
00209   get_user_flagrec(get_user_by_host(from), &fr, chan->dname);
00210   if (glob_bot(fr) || ((which == FLOOD_DEOP) && (glob_master(fr) ||
00211       chan_master(fr)) && (glob_friend(fr) || chan_friend(fr))) ||
00212       ((which == FLOOD_KICK) && (glob_master(fr) || chan_master(fr)) &&
00213       (glob_friend(fr) || chan_friend(fr))) || ((which != FLOOD_DEOP) &&
00214       (which != FLOOD_KICK) && (glob_friend(fr) || chan_friend(fr))) ||
00215       (channel_dontkickops(chan) && (chan_op(fr) || (glob_op(fr) &&
00216       !chan_deop(fr)))))
00217     return 0;
00218 
00219   /* Determine how many are necessary to make a flood. */
00220   switch (which) {
00221   case FLOOD_PRIVMSG:
00222   case FLOOD_NOTICE:
00223     thr = chan->flood_pub_thr;
00224     lapse = chan->flood_pub_time;
00225     strcpy(ftype, "pub");
00226     break;
00227   case FLOOD_CTCP:
00228     thr = chan->flood_ctcp_thr;
00229     lapse = chan->flood_ctcp_time;
00230     strcpy(ftype, "pub");
00231     break;
00232   case FLOOD_NICK:
00233     thr = chan->flood_nick_thr;
00234     lapse = chan->flood_nick_time;
00235     strcpy(ftype, "nick");
00236     break;
00237   case FLOOD_JOIN:
00238     thr = chan->flood_join_thr;
00239     lapse = chan->flood_join_time;
00240     strcpy(ftype, "join");
00241     break;
00242   case FLOOD_DEOP:
00243     thr = chan->flood_deop_thr;
00244     lapse = chan->flood_deop_time;
00245     strcpy(ftype, "deop");
00246     break;
00247   case FLOOD_KICK:
00248     thr = chan->flood_kick_thr;
00249     lapse = chan->flood_kick_time;
00250     strcpy(ftype, "kick");
00251     break;
00252   }
00253   if ((thr == 0) || (lapse == 0))
00254     return 0;                   /* no flood protection */
00255 
00256   if ((which == FLOOD_KICK) || (which == FLOOD_DEOP))
00257     p = floodnick;
00258   else {
00259     p = strchr(floodhost, '@');
00260     if (p) {
00261       p++;
00262     }
00263     if (!p)
00264       return 0;
00265   }
00266   if (rfc_casecmp(chan->floodwho[which], p)) {  /* new */
00267     strncpy(chan->floodwho[which], p, 80);
00268     chan->floodwho[which][80] = 0;
00269     chan->floodtime[which] = now;
00270     chan->floodnum[which] = 1;
00271     return 0;
00272   }
00273   if (chan->floodtime[which] < now - lapse) {
00274     /* Flood timer expired, reset it */
00275     chan->floodtime[which] = now;
00276     chan->floodnum[which] = 1;
00277     return 0;
00278   }
00279   /* Deop'n the same person, sillyness ;) - so just ignore it */
00280   if (which == FLOOD_DEOP) {
00281     if (!rfc_casecmp(chan->deopd, victim))
00282       return 0;
00283     else
00284       strcpy(chan->deopd, victim);
00285   }
00286   chan->floodnum[which]++;
00287   if (chan->floodnum[which] >= thr) {   /* FLOOD */
00288     /* Reset counters */
00289     chan->floodnum[which] = 0;
00290     chan->floodtime[which] = 0;
00291     chan->floodwho[which][0] = 0;
00292     if (which == FLOOD_DEOP)
00293       chan->deopd[0] = 0;
00294     u = get_user_by_host(from);
00295     if (check_tcl_flud(floodnick, floodhost, u, ftype, chan->dname))
00296       return 0;
00297     switch (which) {
00298     case FLOOD_PRIVMSG:
00299     case FLOOD_NOTICE:
00300     case FLOOD_CTCP:
00301       /* Flooding chan! either by public or notice */
00302       if (!chan_sentkick(m) &&
00303           (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) {
00304         putlog(LOG_MODES, chan->dname, IRC_FLOODKICK, floodnick);
00305         dprintf(DP_MODE, "KICK %s %s :%s\n", chan->name, floodnick, CHAN_FLOOD);
00306         m->flags |= SENTKICK;
00307       }
00308       return 1;
00309     case FLOOD_JOIN:
00310     case FLOOD_NICK:
00311       if (use_exempts && (u_match_mask(global_exempts, from) ||
00312           u_match_mask(chan->exempts, from)))
00313         return 1;
00314       simple_sprintf(h, "*!*@%s", p);
00315       if (!isbanned(chan, h) && (me_op(chan) || me_halfop(chan))) {
00316         check_exemptlist(chan, from);
00317         do_mask(chan, chan->channel.ban, h, 'b');
00318       }
00319       if ((u_match_mask(global_bans, from)) ||
00320           (u_match_mask(chan->bans, from)))
00321         return 1;               /* Already banned */
00322       if (which == FLOOD_JOIN)
00323         putlog(LOG_MISC | LOG_JOIN, chan->dname, IRC_FLOODIGNORE3, p);
00324       else
00325         putlog(LOG_MISC | LOG_JOIN, chan->dname, IRC_FLOODIGNORE4, p);
00326       strcpy(ftype + 4, " flood");
00327       u_addban(chan, h, botnetnick, ftype, now + (60 * chan->ban_time), 0);
00328       if (!channel_enforcebans(chan) && (me_op(chan) || me_halfop(chan))) {
00329         char s[UHOSTLEN];
00330 
00331         for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00332           sprintf(s, "%s!%s", m->nick, m->userhost);
00333           if (wild_match(h, s) && (m->joined >= chan->floodtime[which]) &&
00334               !chan_sentkick(m) && !match_my_nick(m->nick) && (me_op(chan) ||
00335               (me_halfop(chan) && !chan_hasop(m)))) {
00336             m->flags |= SENTKICK;
00337             if (which == FLOOD_JOIN)
00338               dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick,
00339                       IRC_JOIN_FLOOD);
00340             else
00341               dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick,
00342                       IRC_NICK_FLOOD);
00343           }
00344         }
00345       }
00346       return 1;
00347     case FLOOD_KICK:
00348       if ((me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) &&
00349           !chan_sentkick(m)) {
00350         putlog(LOG_MODES, chan->dname, "Kicking %s, for mass kick.", floodnick);
00351         dprintf(DP_MODE, "KICK %s %s :%s\n", chan->name, floodnick,
00352                 IRC_MASSKICK);
00353         m->flags |= SENTKICK;
00354       }
00355       return 1;
00356     case FLOOD_DEOP:
00357       if ((me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) &&
00358           !chan_sentkick(m)) {
00359         putlog(LOG_MODES, chan->dname, CHAN_MASSDEOP, chan->dname, from);
00360         dprintf(DP_MODE, "KICK %s %s :%s\n",
00361                 chan->name, floodnick, CHAN_MASSDEOP_KICK);
00362         m->flags |= SENTKICK;
00363       }
00364       return 1;
00365     }
00366   }
00367   return 0;
00368 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void do_mask ( struct chanset_t chan,
masklist m,
char *  mask,
char  mode 
) [static]

Definition at line 169 of file chan.c.

References add_mode, cmp_masks, flush_mode(), maskstruct::mask, maskstruct::next, QUICK, and rfc_casecmp.

Referenced by cmd_kickban(), detect_chan_flood(), quickban(), refresh_ban_kick(), refresh_exempt(), and refresh_invite().

00170 {
00171   for (; m && m->mask[0]; m = m->next)
00172     if (cmp_masks(mask, m->mask) && rfc_casecmp(mask, m->mask))
00173       add_mode(chan, '-', mode, m->mask);
00174   add_mode(chan, '+', mode, mask);
00175   flush_mode(chan, QUICK);
00176 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void enforce_bans ( struct chanset_t chan  )  [static]

Definition at line 518 of file chan.c.

References chan_t::ban, botname, botuserhost, chanset_t::channel, HALFOP_CANTDOMODE, IRC_YOUREBANNED, isexempted, kick_all(), maskstruct::mask, match_addr, maskstruct::next, simple_sprintf, and UHOSTLEN.

Referenced by recheck_channel().

00519 {
00520   char me[UHOSTLEN];
00521   masklist *b;
00522 
00523   if (HALFOP_CANTDOMODE('b'))
00524     return;
00525 
00526   simple_sprintf(me, "%s!%s", botname, botuserhost);
00527   /* Go through all bans, kicking the users. */
00528   for (b = chan->channel.ban; b && b->mask[0]; b = b->next) {
00529     if (!match_addr(b->mask, me))
00530       if (!isexempted(chan, b->mask))
00531         kick_all(chan, b->mask, IRC_YOUREBANNED, 1);
00532   }
00533 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char* getchanmode ( struct chanset_t chan  )  [static]

Definition at line 93 of file chan.c.

References CHANANON, CHANDELJN, CHANINV, CHANINVIS, CHANKEY, CHANLONLY, CHANMODER, CHANMODREG, chanset_t::channel, CHANNOAMSG, CHANNOCLR, CHANNOCTCP, CHANNOMSG, CHANNONOTC, CHANPRIV, CHANREGON, CHANSEC, CHANSTRIP, CHANTOPIC, chan_t::key, chan_t::maxmembers, and chan_t::mode.

Referenced by cmd_channel(), and status_log().

00094 {
00095   static char s[121];
00096   int atr, i;
00097 
00098   s[0] = '+';
00099   i = 1;
00100   atr = chan->channel.mode;
00101   if (atr & CHANINV)
00102     s[i++] = 'i';
00103   if (atr & CHANPRIV)
00104     s[i++] = 'p';
00105   if (atr & CHANSEC)
00106     s[i++] = 's';
00107   if (atr & CHANMODER)
00108     s[i++] = 'm';
00109   if (atr & CHANNOCLR)
00110     s[i++] = 'c';
00111   if (atr & CHANNOCTCP)
00112     s[i++] = 'C';
00113   if (atr & CHANREGON)
00114     s[i++] = 'R';
00115   if (atr & CHANTOPIC)
00116     s[i++] = 't';
00117   if (atr & CHANMODREG)
00118     s[i++] = 'M';
00119   if (atr & CHANLONLY)
00120     s[i++] = 'r';
00121   if (atr & CHANDELJN)
00122     s[i++] = 'D';
00123   if (atr & CHANSTRIP)
00124     s[i++] = 'u';
00125   if (atr & CHANNONOTC)
00126     s[i++] = 'N';
00127   if (atr & CHANNOAMSG)
00128     s[i++] = 'T';
00129   if (atr & CHANINVIS)
00130     s[i++] = 'd';
00131   if (atr & CHANNOMSG)
00132     s[i++] = 'n';
00133   if (atr & CHANANON)
00134     s[i++] = 'a';
00135   if (atr & CHANKEY)
00136     s[i++] = 'k';
00137   if (chan->channel.maxmembers != 0)
00138     s[i++] = 'l';
00139   s[i] = 0;
00140   if (chan->channel.key[0])
00141     i += sprintf(s + i, " %s", chan->channel.key);
00142   if (chan->channel.maxmembers != 0)
00143     sprintf(s + i, " %d", chan->channel.maxmembers);
00144   return s;
00145 }

Here is the caller graph for this function:

static int got315 ( char *  from,
char *  msg 
) [static]

Definition at line 1126 of file chan.c.

References botname, CHAN_ACTIVE, CHAN_PEND, CHAN_STOP_CYCLE, chanset_t::channel, channel_pending, clear_channel(), chanset_t::dname, DP_SERVER, dprintf, findchan, ismember, chan_t::key, chanset_t::key, chanset_t::key_prot, LOG_JOIN, LOG_MISC, me_op(), chan_t::members, chanset_t::name, newsplit, putlog, recheck_channel(), chanset_t::status, and sync_members().

01127 {
01128   char *chname, *key;
01129   struct chanset_t *chan;
01130 
01131   newsplit(&msg);
01132   chname = newsplit(&msg);
01133   chan = findchan(chname);
01134   if (!chan || !channel_pending(chan)) /* Left channel before we got a 315? */
01135     return 0;
01136 
01137   sync_members(chan);
01138   chan->status |= CHAN_ACTIVE;
01139   chan->status &= ~CHAN_PEND;
01140   if (!ismember(chan, botname)) {      /* Am I on the channel now?          */
01141     putlog(LOG_MISC | LOG_JOIN, chan->dname, "Oops, I'm not really on %s.",
01142            chan->dname);
01143     clear_channel(chan, 1);
01144     chan->status &= ~CHAN_ACTIVE;
01145 
01146     key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
01147     if (key[0])
01148       dprintf(DP_SERVER, "JOIN %s %s\n",
01149               chan->name[0] ? chan->name : chan->dname, key);
01150     else
01151       dprintf(DP_SERVER, "JOIN %s\n",
01152               chan->name[0] ? chan->name : chan->dname);
01153   } else if (me_op(chan))
01154     recheck_channel(chan, 1);
01155   else if (chan->channel.members == 1)
01156     chan->status |= CHAN_STOP_CYCLE;
01157   return 0;                            /* Don't check for I-Lines here.     */
01158 }

Here is the call graph for this function:

static int got324 ( char *  from,
char *  msg 
) [static]

Definition at line 931 of file chan.c.

References CHAN_ASKEDMODES, CHANANON, CHANDELJN, CHANINV, CHANINVIS, CHANKEY, CHANLONLY, CHANMODER, CHANMODREG, chanset_t::channel, CHANNOAMSG, CHANNOCLR, CHANNOCTCP, CHANNOMSG, CHANNONOTC, CHANPRIV, CHANQUIET, CHANREGON, CHANSEC, CHANSTRIP, CHANTOPIC, DP_SERVER, dprintf, findchan, IRC_UNEXPECTEDMODE, chan_t::key, LOG_MISC, chan_t::maxmembers, chan_t::mode, newsplit, NULL, putlog, recheck_channel_modes(), set_key(), and chanset_t::status.

00932 {
00933   int i = 1, ok = 0;
00934   char *p, *q, *chname;
00935   struct chanset_t *chan;
00936 
00937   newsplit(&msg);
00938   chname = newsplit(&msg);
00939   chan = findchan(chname);
00940   if (!chan) {
00941     putlog(LOG_MISC, "*", "%s: %s", IRC_UNEXPECTEDMODE, chname);
00942     dprintf(DP_SERVER, "PART %s\n", chname);
00943     return 0;
00944   }
00945   if (chan->status & CHAN_ASKEDMODES)
00946     ok = 1;
00947   chan->status &= ~CHAN_ASKEDMODES;
00948   chan->channel.mode = 0;
00949   while (msg[i] != 0) {
00950     if (msg[i] == 'i')
00951       chan->channel.mode |= CHANINV;
00952     if (msg[i] == 'p')
00953       chan->channel.mode |= CHANPRIV;
00954     if (msg[i] == 's')
00955       chan->channel.mode |= CHANSEC;
00956     if (msg[i] == 'm')
00957       chan->channel.mode |= CHANMODER;
00958     if (msg[i] == 'c')
00959       chan->channel.mode |= CHANNOCLR;
00960     if (msg[i] == 'C')
00961       chan->channel.mode |= CHANNOCTCP;
00962     if (msg[i] == 'R')
00963       chan->channel.mode |= CHANREGON;
00964     if (msg[i] == 'M')
00965       chan->channel.mode |= CHANMODREG;
00966     if (msg[i] == 'r')
00967       chan->channel.mode |= CHANLONLY;
00968     if (msg[i] == 'D')
00969       chan->channel.mode |= CHANDELJN;
00970     if (msg[i] == 'u')
00971       chan->channel.mode |= CHANSTRIP;
00972     if (msg[i] == 'N')
00973       chan->channel.mode |= CHANNONOTC;
00974     if (msg[i] == 'T')
00975       chan->channel.mode |= CHANNOAMSG;
00976     if (msg[i] == 'd')
00977       chan->channel.mode |= CHANINVIS;
00978     if (msg[i] == 't')
00979       chan->channel.mode |= CHANTOPIC;
00980     if (msg[i] == 'n')
00981       chan->channel.mode |= CHANNOMSG;
00982     if (msg[i] == 'a')
00983       chan->channel.mode |= CHANANON;
00984     if (msg[i] == 'q')
00985       chan->channel.mode |= CHANQUIET;
00986     if (msg[i] == 'k') {
00987       chan->channel.mode |= CHANKEY;
00988       p = strchr(msg, ' ');
00989       if (p != NULL) {          /* Test for null key assignment */
00990         p++;
00991         q = strchr(p, ' ');
00992         if (q != NULL) {
00993           *q = 0;
00994           set_key(chan, p);
00995           strcpy(p, q + 1);
00996         } else {
00997           set_key(chan, p);
00998           *p = 0;
00999         }
01000       }
01001       if ((chan->channel.mode & CHANKEY) && (!chan->channel.key[0] ||
01002           !strcmp("*", chan->channel.key)))
01003         /* Undernet use to show a blank channel key if one was set when
01004          * you first joined a channel; however, this has been replaced by
01005          * an asterisk and this has been agreed upon by other major IRC
01006          * networks so we'll check for an asterisk here as well
01007          * (guppy 22Dec2001) */
01008         chan->status |= CHAN_ASKEDMODES;
01009     }
01010     if (msg[i] == 'l') {
01011       p = strchr(msg, ' ');
01012       if (p != NULL) {          /* test for null limit assignment */
01013         p++;
01014         q = strchr(p, ' ');
01015         if (q != NULL) {
01016           *q = 0;
01017           chan->channel.maxmembers = atoi(p);
01018           strcpy(p, q + 1);
01019         } else {
01020           chan->channel.maxmembers = atoi(p);
01021           *p = 0;
01022         }
01023       }
01024     }
01025     i++;
01026   }
01027   if (ok)
01028     recheck_channel_modes(chan);
01029   return 0;
01030 }

Here is the call graph for this function:

static int got331 ( char *  from,
char *  msg 
) [static]

Definition at line 1580 of file chan.c.

References check_tcl_topc, chanset_t::dname, findchan, newsplit, NULL, and set_topic().

01581 {
01582   char *chname;
01583   struct chanset_t *chan;
01584 
01585   newsplit(&msg);
01586   chname = newsplit(&msg);
01587   chan = findchan(chname);
01588   if (chan) {
01589     set_topic(chan, NULL);
01590     check_tcl_topc("*", "*", NULL, chan->dname, "");
01591   }
01592   return 0;
01593 }

Here is the call graph for this function:

static int got332 ( char *  from,
char *  msg 
) [static]

Definition at line 1598 of file chan.c.

References check_tcl_topc, chanset_t::dname, findchan, fixcolon, newsplit, NULL, and set_topic().

01599 {
01600   struct chanset_t *chan;
01601   char *chname;
01602 
01603   newsplit(&msg);
01604   chname = newsplit(&msg);
01605   chan = findchan(chname);
01606   if (chan) {
01607     fixcolon(msg);
01608     set_topic(chan, msg);
01609     check_tcl_topc("*", "*", NULL, chan->dname, msg);
01610   }
01611   return 0;
01612 }

Here is the call graph for this function:

static int got346 ( char *  from,
char *  origmsg 
) [static]

Definition at line 1256 of file chan.c.

References channel_active, channel_pending, findchan, newinvite, newsplit, and use_invites.

01257 {
01258   char *invite, *who, *chname, buf[511], *msg;
01259   struct chanset_t *chan;
01260 
01261   strncpy(buf, origmsg, 510);
01262   buf[510] = 0;
01263   msg = buf;
01264   if (use_invites == 0)
01265     return 0;
01266   newsplit(&msg);
01267   chname = newsplit(&msg);
01268   chan = findchan(chname);
01269   if (!chan || !(channel_pending(chan) || channel_active(chan)))
01270     return 0;
01271   invite = newsplit(&msg);
01272   who = newsplit(&msg);
01273   /* Extended timestamp format? */
01274   if (who[0])
01275     newinvite(chan, invite, who);
01276   else
01277     newinvite(chan, invite, "existent");
01278   return 0;
01279 }

static int got347 ( char *  from,
char *  msg 
) [static]

Definition at line 1284 of file chan.c.

References CHAN_ASKED_INVITED, findchan, chanset_t::ircnet_status, newsplit, and use_invites.

01285 {
01286   struct chanset_t *chan;
01287   char *chname;
01288 
01289   if (use_invites == 1) {
01290     newsplit(&msg);
01291     chname = newsplit(&msg);
01292     chan = findchan(chname);
01293     if (chan)
01294       chan->ircnet_status &= ~CHAN_ASKED_INVITED;
01295   }
01296   return 0;
01297 }

static int got348 ( char *  from,
char *  origmsg 
) [static]

Definition at line 1209 of file chan.c.

References channel_active, channel_pending, findchan, newexempt, newsplit, and use_exempts.

01210 {
01211   char *exempt, *who, *chname, buf[511], *msg;
01212   struct chanset_t *chan;
01213 
01214   if (use_exempts == 0)
01215     return 0;
01216 
01217   strncpy(buf, origmsg, 510);
01218   buf[510] = 0;
01219   msg = buf;
01220   newsplit(&msg);
01221   chname = newsplit(&msg);
01222   chan = findchan(chname);
01223   if (!chan || !(channel_pending(chan) || channel_active(chan)))
01224     return 0;
01225   exempt = newsplit(&msg);
01226   who = newsplit(&msg);
01227   /* Extended timestamp format? */
01228   if (who[0])
01229     newexempt(chan, exempt, who);
01230   else
01231     newexempt(chan, exempt, "existent");
01232   return 0;
01233 }

static int got349 ( char *  from,
char *  msg 
) [static]

Definition at line 1238 of file chan.c.

References CHAN_ASKED_EXEMPTS, findchan, chanset_t::ircnet_status, newsplit, and use_exempts.

01239 {
01240   struct chanset_t *chan;
01241   char *chname;
01242 
01243   if (use_exempts == 1) {
01244     newsplit(&msg);
01245     chname = newsplit(&msg);
01246     chan = findchan(chname);
01247     if (chan)
01248       chan->ircnet_status &= ~CHAN_ASKED_EXEMPTS;
01249   }
01250   return 0;
01251 }

static int got352 ( char *  from,
char *  msg 
) [static]

Definition at line 1079 of file chan.c.

References findchan, got352or4(), newsplit, and user.

01080 {
01081   char *nick, *user, *host, *chname, *flags;
01082   struct chanset_t *chan;
01083 
01084   newsplit(&msg);               /* Skip my nick - effeciently */
01085   chname = newsplit(&msg);      /* Grab the channel */
01086   chan = findchan(chname);      /* See if I'm on channel */
01087   if (chan) {                   /* Am I? */
01088     user = newsplit(&msg);      /* Grab the user */
01089     host = newsplit(&msg);      /* Grab the host */
01090     newsplit(&msg);             /* Skip the server */
01091     nick = newsplit(&msg);      /* Grab the nick */
01092     flags = newsplit(&msg);     /* Grab the flags */
01093     got352or4(chan, user, host, nick, flags);
01094   }
01095   return 0;
01096 }

Here is the call graph for this function:

static int got352or4 ( struct chanset_t chan,
char *  user,
char *  host,
char *  nick,
char *  flags 
) [static]

Definition at line 1032 of file chan.c.

References any_ops(), botuserhost, CHANHALFOP, CHANOP, CHANVOICE, check_tcl_need(), memstruct::delay, chanset_t::dname, do_tcl, memstruct::flags, get_user_by_host, ismember, memstruct::joined, memstruct::last, match_my_nick(), me_op(), chanset_t::need_op, newmember(), memstruct::nick, now, NULL, opchars, simple_sprintf, memstruct::split, STOPWHO, UHOSTLEN, memstruct::user, memstruct::userhost, WASHALFOP, WASOP, and WHO_SYNCED.

Referenced by got352(), and got354().

01034 {
01035   char userhost[UHOSTLEN];
01036   memberlist *m;
01037 
01038   m = ismember(chan, nick);     /* In my channel list copy? */
01039   if (!m) {                     /* Nope, so update */
01040     m = newmember(chan);        /* Get a new channel entry */
01041     m->joined = m->split = m->delay = 0L;       /* Don't know when he joined */
01042     m->flags = 0;               /* No flags for now */
01043     m->last = now;              /* Last time I saw him */
01044   }
01045   strcpy(m->nick, nick);        /* Store the nick in list */
01046   /* Store the userhost */
01047   simple_sprintf(m->userhost, "%s@%s", user, host);
01048   simple_sprintf(userhost, "%s!%s", nick, m->userhost);
01049   /* Combine n!u@h */
01050   m->user = NULL;               /* No handle match (yet) */
01051   if (match_my_nick(nick))      /* Is it me? */
01052     strcpy(botuserhost, m->userhost);   /* Yes, save my own userhost */
01053   m->flags |= WHO_SYNCED;
01054   if (strpbrk(flags, opchars) != NULL)
01055     m->flags |= (CHANOP | WASOP);
01056   else
01057     m->flags &= ~(CHANOP | WASOP);
01058   if (strchr(flags, '%') != NULL)
01059     m->flags |= (CHANHALFOP | WASHALFOP);
01060   else
01061     m->flags &= ~(CHANHALFOP | WASHALFOP);
01062   if (strchr(flags, '+') != NULL)
01063     m->flags |= CHANVOICE;
01064   else
01065     m->flags &= ~CHANVOICE;
01066   if (!(m->flags & (CHANVOICE | CHANOP | CHANHALFOP)))
01067     m->flags |= STOPWHO;
01068   if (match_my_nick(nick) && any_ops(chan) && !me_op(chan)) {
01069     check_tcl_need(chan->dname, "op");
01070     if (chan->need_op[0])
01071       do_tcl("need-op", chan->need_op);
01072   }
01073   m->user = get_user_by_host(userhost);
01074   return 0;
01075 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int got354 ( char *  from,
char *  msg 
) [static]

Definition at line 1100 of file chan.c.

References CHANMETA, findchan, got352or4(), newsplit, NULL, use_354, and user.

01101 {
01102   char *nick, *user, *host, *chname, *flags;
01103   struct chanset_t *chan;
01104 
01105   if (use_354) {
01106     newsplit(&msg);             /* Skip my nick - effeciently */
01107     if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) {
01108       chname = newsplit(&msg);  /* Grab the channel */
01109       chan = findchan(chname);  /* See if I'm on channel */
01110       if (chan) {               /* Am I? */
01111         user = newsplit(&msg);  /* Grab the user */
01112         host = newsplit(&msg);  /* Grab the host */
01113         nick = newsplit(&msg);  /* Grab the nick */
01114         flags = newsplit(&msg); /* Grab the flags */
01115         got352or4(chan, user, host, nick, flags);
01116       }
01117     }
01118   }
01119   return 0;
01120 }

Here is the call graph for this function:

static int got367 ( char *  from,
char *  origmsg 
) [static]

Definition at line 1163 of file chan.c.

References channel_active, channel_pending, findchan, newban, and newsplit.

01164 {
01165   char *ban, *who, *chname, buf[511], *msg;
01166   struct chanset_t *chan;
01167 
01168   strncpy(buf, origmsg, 510);
01169   buf[510] = 0;
01170   msg = buf;
01171   newsplit(&msg);
01172   chname = newsplit(&msg);
01173   chan = findchan(chname);
01174   if (!chan || !(channel_pending(chan) || channel_active(chan)))
01175     return 0;
01176   ban = newsplit(&msg);
01177   who = newsplit(&msg);
01178   /* Extended timestamp format? */
01179   if (who[0])
01180     newban(chan, ban, who);
01181   else
01182     newban(chan, ban, "existent");
01183   return 0;
01184 }

static int got368 ( char *  from,
char *  msg 
) [static]

Definition at line 1189 of file chan.c.

References CHAN_ASKEDBANS, findchan, newsplit, and chanset_t::status.

01190 {
01191   struct chanset_t *chan;
01192   char *chname;
01193 
01194   /* Okay, now add bans that i want, which aren't set yet */
01195   newsplit(&msg);
01196   chname = newsplit(&msg);
01197   chan = findchan(chname);
01198   if (chan)
01199     chan->status &= ~CHAN_ASKEDBANS;
01200   /* If i sent a mode -b on myself (deban) in got367, either
01201    * resetbans() or recheck_bans() will flush that.
01202    */
01203   return 0;
01204 }

static int got403 ( char *  from,
char *  msg 
) [static]

Definition at line 1317 of file chan.c.

References chanset_t::dname, DP_SERVER, dprintf, findchan, findchan_by_dname, LOG_MISC, newsplit, and putlog.

01318 {
01319   char *chname;
01320   struct chanset_t *chan;
01321 
01322   newsplit(&msg);
01323   chname = newsplit(&msg);
01324   if (chname && chname[0] == '!') {
01325     chan = findchan_by_dname(chname);
01326     if (!chan) {
01327       chan = findchan(chname);
01328       if (!chan)
01329         return 0;               /* Ignore it */
01330       /* We have the channel unique name, so we have attempted to join
01331        * a specific !channel that doesnt exist. Now attempt to join the
01332        * channel using it's short name.
01333        */
01334       putlog(LOG_MISC, "*",
01335              "Unique channel %s does not exist... Attempting to join with "
01336              "short name.", chname);
01337       dprintf(DP_SERVER, "JOIN %s\n", chan->dname);
01338     } else {
01339       /* We have found the channel, so the server has given us the short
01340        * name. Prefix another '!' to it, and attempt the join again...
01341        */
01342       putlog(LOG_MISC, "*",
01343              "Channel %s does not exist... Attempting to create it.", chname);
01344       dprintf(DP_SERVER, "JOIN !%s\n", chan->dname);
01345     }
01346   }
01347   return 0;
01348 }

static int got405 ( char *  from,
char *  msg 
) [static]

Definition at line 1301 of file chan.c.

References IRC_TOOMANYCHANS, LOG_MISC, newsplit, and putlog.

01302 {
01303   char *chname;
01304 
01305   newsplit(&msg);
01306   chname = newsplit(&msg);
01307   putlog(LOG_MISC, "*", IRC_TOOMANYCHANS, chname);
01308   return 0;
01309 }

static int got471 ( char *  from,
char *  msg 
) [static]

Definition at line 1352 of file chan.c.

References CHANNEL_ID_LEN, check_tcl_need(), chanset_t::dname, do_tcl, findchan_by_dname, IRC_CHANFULL, LOG_JOIN, chanset_t::need_limit, newsplit, and putlog.

01353 {
01354   char *chname;
01355   struct chanset_t *chan;
01356 
01357   newsplit(&msg);
01358   chname = newsplit(&msg);
01359   /* !channel short names (also referred to as 'description names'
01360    * can be received by skipping over the unique ID.
01361    */
01362   if ((chname[0] == '!') && (strlen(chname) > CHANNEL_ID_LEN)) {
01363     chname += CHANNEL_ID_LEN;
01364     chname[0] = '!';
01365   }
01366   /* We use dname because name is first set on JOIN and we might not
01367    * have joined the channel yet.
01368    */
01369   chan = findchan_by_dname(chname);
01370   if (chan) {
01371     putlog(LOG_JOIN, chan->dname, IRC_CHANFULL, chan->dname);
01372     check_tcl_need(chan->dname, "limit");
01373 
01374     chan = findchan_by_dname(chname);
01375     if (!chan)
01376       return 0;
01377 
01378     if (chan->need_limit[0])
01379       do_tcl("need-limit", chan->need_limit);
01380   } else
01381     putlog(LOG_JOIN, chname, IRC_CHANFULL, chname);
01382   return 0;
01383 }

Here is the call graph for this function:

static int got473 ( char *  from,
char *  msg 
) [static]

Definition at line 1387 of file chan.c.

References CHANNEL_ID_LEN, check_tcl_need(), chanset_t::dname, do_tcl, findchan_by_dname, IRC_CHANINVITEONLY, LOG_JOIN, chanset_t::need_invite, newsplit, and putlog.

01388 {
01389   char *chname;
01390   struct chanset_t *chan;
01391 
01392   newsplit(&msg);
01393   chname = newsplit(&msg);
01394   /* !channel short names (also referred to as 'description names'
01395    * can be received by skipping over the unique ID.
01396    */
01397   if ((chname[0] == '!') && (strlen(chname) > CHANNEL_ID_LEN)) {
01398     chname += CHANNEL_ID_LEN;
01399     chname[0] = '!';
01400   }
01401   /* We use dname because name is first set on JOIN and we might not
01402    * have joined the channel yet.
01403    */
01404   chan = findchan_by_dname(chname);
01405   if (chan) {
01406     putlog(LOG_JOIN, chan->dname, IRC_CHANINVITEONLY, chan->dname);
01407     check_tcl_need(chan->dname, "invite");
01408 
01409     chan = findchan_by_dname(chname);
01410     if (!chan)
01411       return 0;
01412 
01413     if (chan->need_invite[0])
01414       do_tcl("need-invite", chan->need_invite);
01415   } else
01416     putlog(LOG_JOIN, chname, IRC_CHANINVITEONLY, chname);
01417   return 0;
01418 }

Here is the call graph for this function:

static int got474 ( char *  from,
char *  msg 
) [static]

Definition at line 1422 of file chan.c.

References CHANNEL_ID_LEN, check_tcl_need(), chanset_t::dname, do_tcl, findchan_by_dname, IRC_BANNEDFROMCHAN, LOG_JOIN, chanset_t::need_unban, newsplit, and putlog.

01423 {
01424   char *chname;
01425   struct chanset_t *chan;
01426 
01427   newsplit(&msg);
01428   chname = newsplit(&msg);
01429   /* !channel short names (also referred to as 'description names'
01430    * can be received by skipping over the unique ID.
01431    */
01432   if ((chname[0] == '!') && (strlen(chname) > CHANNEL_ID_LEN)) {
01433     chname += CHANNEL_ID_LEN;
01434     chname[0] = '!';
01435   }
01436   /* We use dname because name is first set on JOIN and we might not
01437    * have joined the channel yet.
01438    */
01439   chan = findchan_by_dname(chname);
01440   if (chan) {
01441     putlog(LOG_JOIN, chan->dname, IRC_BANNEDFROMCHAN, chan->dname);
01442     check_tcl_need(chan->dname, "unban");
01443 
01444     chan = findchan_by_dname(chname);
01445     if (!chan)
01446       return 0;
01447 
01448     if (chan->need_unban[0])
01449       do_tcl("need-unban", chan->need_unban);
01450   } else
01451     putlog(LOG_JOIN, chname, IRC_BANNEDFROMCHAN, chname);
01452   return 0;
01453 }

Here is the call graph for this function:

static int got475 ( char *  from,
char *  msg 
) [static]

Definition at line 1457 of file chan.c.

References chanset_t::channel, CHANNEL_ID_LEN, channel_malloc(), check_tcl_need(), chanset_t::dname, do_tcl, DP_SERVER, dprintf, findchan_by_dname, IRC_BADCHANKEY, chan_t::key, chanset_t::key_prot, LOG_JOIN, chanset_t::need_key, newsplit, nfree, and putlog.

01458 {
01459   char *chname;
01460   struct chanset_t *chan;
01461 
01462   newsplit(&msg);
01463   chname = newsplit(&msg);
01464   /* !channel short names (also referred to as 'description names'
01465    * can be received by skipping over the unique ID.
01466    */
01467   if ((chname[0] == '!') && (strlen(chname) > CHANNEL_ID_LEN)) {
01468     chname += CHANNEL_ID_LEN;
01469     chname[0] = '!';
01470   }
01471   /* We use dname because name is first set on JOIN and we might not
01472    * have joined the channel yet.
01473    */
01474   chan = findchan_by_dname(chname);
01475   if (chan) {
01476     putlog(LOG_JOIN, chan->dname, IRC_BADCHANKEY, chan->dname);
01477     if (chan->channel.key[0]) {
01478       nfree(chan->channel.key);
01479       chan->channel.key = (char *) channel_malloc(1);
01480       chan->channel.key[0] = 0;
01481 
01482       if (chan->key_prot[0])
01483         dprintf(DP_SERVER, "JOIN %s %s\n", chan->dname, chan->key_prot);
01484       else
01485         dprintf(DP_SERVER, "JOIN %s\n", chan->dname);
01486     } else {
01487       check_tcl_need(chan->dname, "key");
01488 
01489       chan = findchan_by_dname(chname);
01490       if (!chan)
01491         return 0;
01492 
01493       if (chan->need_key[0])
01494         do_tcl("need-key", chan->need_key);
01495     }
01496   } else
01497     putlog(LOG_JOIN, chname, IRC_BADCHANKEY, chname);
01498   return 0;
01499 }

Here is the call graph for this function:

static int gotinvite ( char *  from,
char *  msg 
) [static]

Definition at line 1503 of file chan.c.

References chanset_t::channel, channel_active, channel_inactive, channel_pending, chanset_t::dname, DP_HELP, DP_SERVER, dprintf, findchan, findchan_by_dname, fixcolon, chan_t::key, chanset_t::key, chanset_t::key_prot, last_invchan, last_invtime, LOG_MISC, chanset_t::name, newsplit, now, putlog, rfc_casecmp, and splitnick.

01504 {
01505   char *nick, *key;
01506   struct chanset_t *chan;
01507 
01508   newsplit(&msg);
01509   fixcolon(msg);
01510   nick = splitnick(&from);
01511   if (!rfc_casecmp(last_invchan, msg))
01512     if (now - last_invtime < 30)
01513       return 0; /* Two invites to the same channel in 30 seconds? */
01514   putlog(LOG_MISC, "*", "%s!%s invited me to %s", nick, from, msg);
01515   strncpy(last_invchan, msg, 299);
01516   last_invchan[299] = 0;
01517   last_invtime = now;
01518   chan = findchan(msg);
01519   if (!chan)
01520     /* Might be a short-name */
01521     chan = findchan_by_dname(msg);
01522 
01523   if (chan && (channel_pending(chan) || channel_active(chan)))
01524     dprintf(DP_HELP, "NOTICE %s :I'm already here.\n", nick);
01525   else if (chan && !channel_inactive(chan)) {
01526 
01527     key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
01528     if (key[0])
01529       dprintf(DP_SERVER, "JOIN %s %s\n",
01530               chan->name[0] ? chan->name : chan->dname, key);
01531     else
01532       dprintf(DP_SERVER, "JOIN %s\n",
01533               chan->name[0] ? chan->name : chan->dname);
01534   }
01535   return 0;
01536 }

static int gotjoin ( char *  from,
char *  chname 
) [static]

Definition at line 1670 of file chan.c.

References add_mode, chanset_t::aop_min, chan_t::ban, chanset_t::bans, CHAN_ACTIVE, chan_autohalfop, chan_autoop, chan_dehalfop, chan_deop, chan_friend, chan_gvoice, chan_halfop, chan_hashalfop, chan_hasop, CHAN_INACTIVE, CHAN_JUPED, chan_kick, chan_op, CHAN_PEND, chan_quiet, CHAN_RESETALL, CHAN_RESETTOPIC, chan_sentkick, CHAN_STOP_CYCLE, chan_voice, chanset_t::channel, channel_active, channel_autohalfop, channel_autoop, channel_autovoice, channel_enforcebans, channel_greet, CHANNEL_ID_LEN, channel_inactive, channel_pending, check_exemptlist(), check_tcl_join, check_tcl_rejn, memstruct::delay, detect_chan_flood(), chanset_t::dname, DP_HELP, DP_MODE, DP_SERVER, dprintf, egg_snprintf, egg_strcasecmp, chanset_t::exempts, findchan, findchan_by_dname, fixcolon, userrec::flags, memstruct::flags, FLOOD_JOIN, FR_CHAN, FR_GLOBAL, get_chanrec(), get_handle_chaninfo(), get_user, get_user_by_host, get_user_flagrec, glob_autohalfop, glob_autoop, glob_friend, glob_gvoice, glob_halfop, glob_kick, glob_op, glob_voice, global_bans, global_exempts, global_invites, userrec::handle, chanset_t::invites, IRC_COMMENTKICK, IRC_YOUREBANNED, isexempted, ismember, memstruct::joined, killmember(), memstruct::last, laston_info::laston, chanuserrec::laston, LOG_JOIN, LOG_MISC, maskstruct::mask, match_addr, match_my_nick(), me_halfop(), me_op(), chanset_t::name, newmember(), maskstruct::next, nfree, memstruct::nick, nmalloc, no_chanrec_info, NOHALFOPS_MODES, now, NULL, putlog, quickban(), refresh_ban_kick(), refresh_invite(), reset_chan_info(), SENTHALFOP, SENTKICK, SENTOP, SENTVOICE, set_delay(), set_handle_laston(), memstruct::split, splitnick, chanset_t::status, STOPWHO, u_match_mask(), UHOSTLEN, use_exempts, use_info, memstruct::user, USER_BOT, USERENTRY_COMMENT, USERENTRY_INFO, USERENTRY_LASTON, memstruct::userhost, wait_info, WASHALFOP, and WASOP.

01671 {
01672   char *nick, *p, buf[UHOSTLEN], *uhost = buf;
01673   char *ch_dname = NULL;
01674   struct chanset_t *chan;
01675   memberlist *m;
01676   masklist *b;
01677   struct userrec *u;
01678   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
01679 
01680   fixcolon(chname);
01681   chan = findchan(chname);
01682   if (!chan && chname[0] == '!') {
01683     /* As this is a !channel, we need to search for it by display (short)
01684      * name now. This will happen when we initially join the channel, as we
01685      * dont know the unique channel name that the server has made up. <cybah>
01686      */
01687     int l_chname = strlen(chname);
01688 
01689     if (l_chname > (CHANNEL_ID_LEN + 1)) {
01690       ch_dname = nmalloc(l_chname + 1);
01691       if (ch_dname) {
01692         egg_snprintf(ch_dname, l_chname + 2, "!%s",
01693                      chname + (CHANNEL_ID_LEN + 1));
01694         chan = findchan_by_dname(ch_dname);
01695         if (!chan) {
01696           /* Hmm.. okay. Maybe the admin's a genius and doesn't know the
01697            * difference between id and descriptive channel names. Search
01698            * the channel name in the dname list using the id-name.
01699            */
01700           chan = findchan_by_dname(chname);
01701           if (chan) {
01702             /* Duh, I was right. Mark this channel as inactive and log
01703              * the incident.
01704              */
01705             chan->status |= CHAN_INACTIVE;
01706             putlog(LOG_MISC, "*", "Deactivated channel %s, because it uses "
01707                    "an ID channel-name. Use the descriptive name instead.",
01708                    chname);
01709             dprintf(DP_SERVER, "PART %s\n", chname);
01710             goto exit;
01711           }
01712         }
01713       }
01714     }
01715   } else if (!chan) {
01716     /* As this is not a !chan, we need to search for it by display name now.
01717      * Unlike !chan's, we dont need to remove the unique part.
01718      */
01719     chan = findchan_by_dname(chname);
01720   }
01721 
01722   if (!chan || channel_inactive(chan)) {
01723     strcpy(uhost, from);
01724     nick = splitnick(&uhost);
01725     if (match_my_nick(nick)) {
01726       putlog(LOG_MISC, "*", "joined %s but didn't want to!", chname);
01727       dprintf(DP_MODE, "PART %s\n", chname);
01728     }
01729   } else if (!channel_pending(chan)) {
01730     chan->status &= ~CHAN_STOP_CYCLE;
01731     strcpy(uhost, from);
01732     nick = splitnick(&uhost);
01733     detect_chan_flood(nick, uhost, from, chan, FLOOD_JOIN, NULL);
01734 
01735     chan = findchan(chname);
01736     if (!chan) {
01737       if (ch_dname)
01738         chan = findchan_by_dname(ch_dname);
01739       else
01740         chan = findchan_by_dname(chname);
01741     }
01742     if (!chan)
01743       /* The channel doesn't exist anymore, so get out of here. */
01744       goto exit;
01745 
01746     /* Grab last time joined before we update it */
01747     u = get_user_by_host(from);
01748     get_user_flagrec(u, &fr, chan->dname);      /* Lam: fix to work with !channels */
01749     if (!channel_active(chan) && !match_my_nick(nick)) {
01750       /* uh, what?!  i'm on the channel?! */
01751       putlog(LOG_MISC, chan->dname,
01752              "confused bot: guess I'm on %s and didn't realize it",
01753              chan->dname);
01754       chan->status |= CHAN_ACTIVE;
01755       chan->status &= ~CHAN_PEND;
01756       reset_chan_info(chan, CHAN_RESETALL);
01757     } else {
01758       m = ismember(chan, nick);
01759       if (m && m->split && !egg_strcasecmp(m->userhost, uhost)) {
01760         check_tcl_rejn(nick, uhost, u, chan->dname);
01761 
01762         chan = findchan(chname);
01763         if (!chan) {
01764           if (ch_dname)
01765             chan = findchan_by_dname(ch_dname);
01766           else
01767             chan = findchan_by_dname(chname);
01768         }
01769         if (!chan)
01770           /* The channel doesn't exist anymore, so get out of here. */
01771           goto exit;
01772 
01773         /* The tcl binding might have deleted the current user. Recheck. */
01774         u = get_user_by_host(from);
01775         m->split = 0;
01776         m->last = now;
01777         m->delay = 0L;
01778         m->flags = (chan_hasop(m) ? WASOP : 0) | (chan_hashalfop(m) ? WASHALFOP : 0);
01779         m->user = u;
01780         set_handle_laston(chan->dname, u, now);
01781         m->flags |= STOPWHO;
01782         putlog(LOG_JOIN, chan->dname, "%s (%s) returned to %s.", nick, uhost,
01783                chan->dname);
01784       } else {
01785         if (m)
01786           killmember(chan, nick);
01787         m = newmember(chan);
01788         m->joined = now;
01789         m->split = 0L;
01790         m->flags = 0;
01791         m->last = now;
01792         m->delay = 0L;
01793         strcpy(m->nick, nick);
01794         strcpy(m->userhost, uhost);
01795         m->user = u;
01796         m->flags |= STOPWHO;
01797 
01798         check_tcl_join(nick, uhost, u, chan->dname);
01799 
01800         /* The tcl binding might have deleted the current user and the
01801          * current channel, so we'll now have to re-check whether they
01802          * both still exist.
01803          */
01804         chan = findchan(chname);
01805         if (!chan) {
01806           if (ch_dname)
01807             chan = findchan_by_dname(ch_dname);
01808           else
01809             chan = findchan_by_dname(chname);
01810         }
01811         if (!chan)
01812           /* The channel doesn't exist anymore, so get out of here. */
01813           goto exit;
01814 
01815         /* The record saved in the channel record always gets updated,
01816          * so we can use that. */
01817         u = m->user;
01818 
01819         if (match_my_nick(nick)) {
01820           /* It was me joining! Need to update the channel record with the
01821            * unique name for the channel (as the server see's it). <cybah>
01822            */
01823           strncpy(chan->name, chname, 81);
01824           chan->name[80] = 0;
01825           chan->status &= ~CHAN_JUPED;
01826 
01827           /* ... and log us joining. Using chan->dname for the channel is
01828            * important in this case. As the config file will never contain
01829            * logs with the unique name.
01830            */
01831           if (chname[0] == '!')
01832             putlog(LOG_JOIN | LOG_MISC, chan->dname, "%s joined %s (%s)",
01833                    nick, chan->dname, chname);
01834           else
01835             putlog(LOG_JOIN | LOG_MISC, chan->dname, "%s joined %s.", nick,
01836                    chname);
01837           reset_chan_info(chan, (CHAN_RESETALL & ~CHAN_RESETTOPIC));
01838         } else {
01839           struct chanuserrec *cr;
01840 
01841           putlog(LOG_JOIN, chan->dname,
01842                  "%s (%s) joined %s.", nick, uhost, chan->dname);
01843           /* Don't re-display greeting if they've been on the channel
01844            * recently.
01845            */
01846           if (u) {
01847             struct laston_info *li = 0;
01848 
01849             cr = get_chanrec(m->user, chan->dname);
01850             if (!cr && no_chanrec_info)
01851               li = get_user(&USERENTRY_LASTON, m->user);
01852             if (channel_greet(chan) && use_info &&
01853                 ((cr && now - cr->laston > wait_info) ||
01854                 (no_chanrec_info && (!li || now - li->laston > wait_info)))) {
01855               char s1[512], *s;
01856 
01857               if (!(u->flags & USER_BOT)) {
01858                 s = get_user(&USERENTRY_INFO, u);
01859                 get_handle_chaninfo(u->handle, chan->dname, s1);
01860                 /* Locked info line overides non-locked channel specific
01861                  * info line.
01862                  */
01863                 if (!s || (s1[0] && (s[0] != '@' || s1[0] == '@')))
01864                   s = s1;
01865                 if (s[0] == '@')
01866                   s++;
01867                 if (s && s[0])
01868                   dprintf(DP_HELP, "PRIVMSG %s :[%s] %s\n", chan->name, nick,
01869                           s);
01870               }
01871             }
01872           }
01873           set_handle_laston(chan->dname, u, now);
01874         }
01875       }
01876       if (me_op(chan) || me_halfop(chan)) {
01877         /* Check for and reset exempts and invites.
01878          *
01879          * This will require further checking to account for when to use the
01880          * various modes.
01881          */
01882         if ((me_op(chan) || (strchr(NOHALFOPS_MODES, 'I') == NULL)) &&
01883             (u_match_mask(global_invites, from) ||
01884             u_match_mask(chan->invites, from)))
01885           refresh_invite(chan, from);
01886         if ((me_op(chan) || (strchr(NOHALFOPS_MODES, 'b') == NULL)) &&
01887             (!use_exempts || (!u_match_mask(global_exempts, from) &&
01888             !u_match_mask(chan->exempts, from)))) {
01889           if (channel_enforcebans(chan) && !chan_op(fr) && !glob_op(fr) &&
01890               !glob_friend(fr) && !chan_friend(fr) && !chan_sentkick(m) &&
01891               (!use_exempts || !isexempted(chan, from)) && (me_op(chan) ||
01892               (me_halfop(chan) && !chan_hasop(m)))) {
01893             for (b = chan->channel.ban; b->mask[0]; b = b->next) {
01894               if (match_addr(b->mask, from)) {
01895                 dprintf(DP_SERVER, "KICK %s %s :%s\n", chname, m->nick,
01896                         IRC_YOUREBANNED);
01897                 m->flags |= SENTKICK;
01898                 goto exit;
01899               }
01900             }
01901           }
01902           /* If it matches a ban, dispose of them. */
01903           if (u_match_mask(global_bans, from) || u_match_mask(chan->bans, from))
01904             refresh_ban_kick(chan, from, nick);
01905           else if (!chan_sentkick(m) && (glob_kick(fr) || chan_kick(fr)) &&
01906                    (me_op(chan) || (me_halfop(chan) && !chan_hasop(m)))) {
01907             check_exemptlist(chan, from);
01908             quickban(chan, from);
01909             p = get_user(&USERENTRY_COMMENT, m->user);
01910             dprintf(DP_MODE, "KICK %s %s :%s\n", chname, nick,
01911                     (p && (p[0] != '@')) ? p : IRC_COMMENTKICK);
01912             m->flags |= SENTKICK;
01913           }
01914         }
01915 #ifdef NO_HALFOP_CHANMODES
01916         if (me_op(chan)) {
01917 #endif
01918         if ((me_op(chan) || (strchr(NOHALFOPS_MODES, 'o') == NULL)) &&
01919             (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) &&
01920             (channel_autoop(chan) || glob_autoop(fr) || chan_autoop(fr))) {
01921           if (!chan->aop_min)
01922             add_mode(chan, '+', 'o', nick);
01923           else {
01924             set_delay(chan, nick);
01925             m->flags |= SENTOP;
01926           }
01927         } else if ((me_op(chan) || (strchr(NOHALFOPS_MODES, 'h') == NULL)) &&
01928                    (chan_halfop(fr) || (glob_halfop(fr) &&
01929                    !chan_dehalfop(fr))) && (channel_autohalfop(chan) ||
01930                    glob_autohalfop(fr) || chan_autohalfop(fr))) {
01931           if (!chan->aop_min)
01932             add_mode(chan, '+', 'h', nick);
01933           else {
01934             set_delay(chan, nick);
01935             m->flags |= SENTHALFOP;
01936           }
01937         } else if ((me_op(chan) || (strchr(NOHALFOPS_MODES, 'v') == NULL)) &&
01938                    ((channel_autovoice(chan) && (chan_voice(fr) ||
01939                    (glob_voice(fr) && !chan_quiet(fr)))) ||
01940                    ((glob_gvoice(fr) || chan_gvoice(fr)) &&
01941                    !chan_quiet(fr)))) {
01942           if (!chan->aop_min)
01943             add_mode(chan, '+', 'v', nick);
01944           else {
01945             set_delay(chan, nick);
01946             m->flags |= SENTVOICE;
01947           }
01948         }
01949 #ifdef NO_HALFOP_CHANMODES
01950         }
01951 #endif
01952       }
01953     }
01954   }
01955 
01956 exit:
01957   if (ch_dname)
01958     nfree(ch_dname);
01959   return 0;
01960 }

Here is the call graph for this function:

static int gotkick ( char *  from,
char *  origmsg 
) [static]

Definition at line 2029 of file chan.c.

References CHAN_ACTIVE, CHAN_PEND, chanset_t::channel, channel_active, channel_inactive, channel_pending, check_lonely_channel(), check_tcl_kick(), clear_channel(), detect_chan_flood(), chanset_t::dname, DP_SERVER, dprintf, findchan, fixcolon, FLOOD_KICK, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, ismember, chan_t::key, chanset_t::key_prot, killmember(), memstruct::last, LOG_MODES, match_my_nick(), maybe_revenge(), chanset_t::name, newsplit, memstruct::nick, now, putlog, REVENGE_KICK, set_handle_laston(), simple_sprintf, splitnick, chanset_t::status, UHOSTLEN, and memstruct::userhost.

02030 {
02031   char *nick, *whodid, *chname, s1[UHOSTLEN], buf[UHOSTLEN], *uhost = buf;
02032   char buf2[511], *msg, *key;
02033   memberlist *m;
02034   struct chanset_t *chan;
02035   struct userrec *u;
02036   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
02037 
02038   strncpy(buf2, origmsg, 510);
02039   buf2[510] = 0;
02040   msg = buf2;
02041   chname = newsplit(&msg);
02042   chan = findchan(chname);
02043   if (!chan)
02044     return 0;
02045   nick = newsplit(&msg);
02046   if (match_my_nick(nick) && channel_pending(chan) &&
02047       !channel_inactive(chan)) {
02048     chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
02049 
02050     key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
02051     if (key[0])
02052       dprintf(DP_SERVER, "JOIN %s %s\n",
02053               chan->name[0] ? chan->name : chan->dname, key);
02054     else
02055       dprintf(DP_SERVER, "JOIN %s\n",
02056               chan->name[0] ? chan->name : chan->dname);
02057     clear_channel(chan, 1);
02058     return 0;                   /* rejoin if kicked before getting needed info <Wcc[08/08/02]> */
02059   }
02060   if (channel_active(chan)) {
02061     fixcolon(msg);
02062     u = get_user_by_host(from);
02063     strcpy(uhost, from);
02064     whodid = splitnick(&uhost);
02065     detect_chan_flood(whodid, uhost, from, chan, FLOOD_KICK, nick);
02066 
02067     chan = findchan(chname);
02068     if (!chan)
02069       return 0;
02070 
02071     m = ismember(chan, whodid);
02072     if (m)
02073       m->last = now;
02074     /* This _needs_ to use chan->dname <cybah> */
02075     get_user_flagrec(u, &fr, chan->dname);
02076     set_handle_laston(chan->dname, u, now);
02077     check_tcl_kick(whodid, uhost, u, chan->dname, nick, msg);
02078 
02079     chan = findchan(chname);
02080     if (!chan)
02081       return 0;
02082 
02083     m = ismember(chan, nick);
02084     if (m) {
02085       struct userrec *u2;
02086 
02087       simple_sprintf(s1, "%s!%s", m->nick, m->userhost);
02088       u2 = get_user_by_host(s1);
02089       set_handle_laston(chan->dname, u2, now);
02090       maybe_revenge(chan, from, s1, REVENGE_KICK);
02091     }
02092     putlog(LOG_MODES, chan->dname, "%s kicked from %s by %s: %s", s1,
02093            chan->dname, from, msg);
02094     /* Kicked ME?!? the sods! */
02095     if (match_my_nick(nick) && !channel_inactive(chan)) {
02096       chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
02097 
02098       key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
02099       if (key[0])
02100         dprintf(DP_SERVER, "JOIN %s %s\n",
02101                 chan->name[0] ? chan->name : chan->dname, key);
02102       else
02103         dprintf(DP_SERVER, "JOIN %s\n",
02104                 chan->name[0] ? chan->name : chan->dname);
02105       clear_channel(chan, 1);
02106     } else {
02107       killmember(chan, nick);
02108       check_lonely_channel(chan);
02109     }
02110   }
02111   return 0;
02112 }

Here is the call graph for this function:

static int gotmsg ( char *  from,
char *  msg 
) [static]

Definition at line 2285 of file chan.c.

References addignore, answer_ctcp, ban_fun, chanset_t::ban_time, botnetnick, chan_deop, chan_friend, chan_hasop, chan_op, chan_sentkick, CHANMETA, channel_dontkickops, check_exemptlist(), check_tcl_ctcp, check_tcl_pub(), check_tcl_pubm(), count_ctcp, ctcp_mode, ctcp_reply, detect_avalanche(), detect_chan_flood(), chanset_t::dname, DP_HELP, DP_SERVER, dprintf, exclusive_binds, chanset_t::exempts, findchan, fixcolon, memstruct::flags, FLOOD_CTCP, FLOOD_PRIVMSG, flud_ctcp_thr, flud_ctcp_time, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_friend, glob_op, global_exempts, ignore_time, IRC_FUNKICK, ismember, kick_fun, last_ctcp, LOG_MODES, LOG_PUBLIC, match_ignore, me_halfop(), me_op(), chanset_t::name, newsplit, now, NULL, putlog, quickban(), SENTKICK, simple_sprintf, splitnick, trigger_on_ignore, u_addban(), u_match_mask(), UHOSTLEN, update_idle(), and use_exempts.

02286 {
02287   char *to, *realto, buf[UHOSTLEN], *nick, buf2[512], *uhost = buf, *p, *p1,
02288        *code, *ctcp;
02289   int ctcp_count = 0, ignoring;
02290   struct chanset_t *chan;
02291   struct userrec *u;
02292   memberlist *m;
02293   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
02294 
02295   /* Only handle if message is to a channel, or to @#channel. */
02296   /* FIXME: Properly handle ovNotices (@+#channel), vNotices (+#channel), etc. */
02297   if (!strchr(CHANMETA "@", msg[0]))
02298     return 0;
02299 
02300   to = newsplit(&msg);
02301   realto = (to[0] == '@') ? to + 1 : to;
02302   chan = findchan(realto);
02303   if (!chan)
02304     return 0; /* Unknown channel; don't process. */
02305 
02306   fixcolon(msg);
02307   strcpy(uhost, from);
02308   nick = splitnick(&uhost);
02309   ignoring = match_ignore(from);
02310   /* Only check if flood-ctcp is active */
02311   if (flud_ctcp_thr && detect_avalanche(msg)) {
02312     u = get_user_by_host(from);
02313     get_user_flagrec(u, &fr, chan->dname);
02314     m = ismember(chan, nick);
02315     /* Discard -- kick user if it was to the channel */
02316     if (m && (me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) &&
02317         !chan_sentkick(m) && !chan_friend(fr) && !glob_friend(fr) &&
02318         !(channel_dontkickops(chan) && (chan_op(fr) || (glob_op(fr) &&
02319         !chan_deop(fr)))) && !(use_exempts && ban_fun &&
02320         (u_match_mask(global_exempts, from) ||
02321         u_match_mask(chan->exempts, from)))) {
02322       if (ban_fun) {
02323         check_exemptlist(chan, from);
02324         u_addban(chan, quickban(chan, uhost), botnetnick, IRC_FUNKICK,
02325                  now + (60 * chan->ban_time), 0);
02326       }
02327       if (kick_fun) {
02328         /* This can induce kickflood - arthur2 */
02329         dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, nick, IRC_FUNKICK);
02330         m->flags |= SENTKICK;
02331       }
02332     }
02333     if (!ignoring) {
02334       putlog(LOG_MODES, "*", "Avalanche from %s!%s in %s - ignoring",
02335              nick, uhost, chan->dname);
02336       p = strchr(uhost, '@');
02337       if (p)
02338         p++;
02339       else
02340         p = uhost;
02341       simple_sprintf(buf2, "*!*@%s", p);
02342       addignore(buf2, botnetnick, "ctcp avalanche", now + (60 * ignore_time));
02343     }
02344     return 0;
02345   }
02346   /* Check for CTCP: */
02347   ctcp_reply[0] = 0;
02348   p = strchr(msg, 1);
02349   while (p && *p) {
02350     p++;
02351     p1 = p;
02352     while ((*p != 1) && *p)
02353       p++;
02354     if (*p == 1) {
02355       *p = 0;
02356       ctcp = buf2;
02357       strcpy(ctcp, p1);
02358       strcpy(p1 - 1, p + 1);
02359       detect_chan_flood(nick, uhost, from, chan, strncmp(ctcp, "ACTION ", 7) ?
02360                         FLOOD_CTCP : FLOOD_PRIVMSG, NULL);
02361 
02362       chan = findchan(realto);
02363       if (!chan)
02364         return 0;
02365 
02366       /* Respond to the first answer_ctcp */
02367       p = strchr(msg, 1);
02368       if (ctcp_count < answer_ctcp) {
02369         ctcp_count++;
02370         if (ctcp[0] != ' ') {
02371           code = newsplit(&ctcp);
02372           u = get_user_by_host(from);
02373           if (!ignoring || trigger_on_ignore) {
02374             if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp)) {
02375               chan = findchan(realto);
02376               if (!chan)
02377                 return 0;
02378 
02379               update_idle(chan->dname, nick);
02380             }
02381             if (!ignoring) {
02382               /* Log DCC, it's to a channel damnit! */
02383               if (!strcmp(code, "ACTION")) {
02384                 putlog(LOG_PUBLIC, chan->dname, "Action: %s %s", nick, ctcp);
02385               } else {
02386                 putlog(LOG_PUBLIC, chan->dname,
02387                        "CTCP %s: %s from %s (%s) to %s", code, ctcp, nick,
02388                        from, to);
02389               }
02390             }
02391           }
02392         }
02393       }
02394     }
02395   }
02396 
02397   /* Send out possible ctcp responses. */
02398   if (ctcp_reply[0]) {
02399     if (ctcp_mode != 2) {
02400       dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
02401     } else {
02402       if (now - last_ctcp > flud_ctcp_time) {
02403         dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
02404         count_ctcp = 1;
02405       } else if (count_ctcp < flud_ctcp_thr) {
02406         dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
02407         count_ctcp++;
02408       }
02409       last_ctcp = now;
02410     }
02411   }
02412 
02413   if (msg[0]) {
02414     int result = 0;
02415 
02416     /* Check even if we're ignoring the host. (modified by Eule 17.7.99) */
02417     detect_chan_flood(nick, uhost, from, chan, FLOOD_PRIVMSG, NULL);
02418 
02419     chan = findchan(realto);
02420     if (!chan)
02421       return 0;
02422 
02423     update_idle(chan->dname, nick);
02424 
02425     if (!ignoring || trigger_on_ignore) {
02426       result = check_tcl_pubm(nick, uhost, chan->dname, msg);
02427 
02428       if (!result || !exclusive_binds)
02429         if (check_tcl_pub(nick, uhost, chan->dname, msg))
02430           return 0;
02431     }
02432 
02433     if (!ignoring && result != 2) {
02434       if (to[0] == '@')
02435         putlog(LOG_PUBLIC, chan->dname, "@<%s> %s", nick, msg);
02436       else
02437         putlog(LOG_PUBLIC, chan->dname, "<%s> %s", nick, msg);
02438     }
02439   }
02440   return 0;
02441 }

Here is the call graph for this function:

static int gotnick ( char *  from,
char *  msg 
) [static]

Definition at line 2116 of file chan.c.

References chan_sentdehalfop, chan_sentdeop, chan_sentdevoice, chan_senthalfop, chan_sentkick, chan_sentop, chan_sentvoice, chan_stopcheck, chanset, check_tcl_nick, check_this_member(), clear_chanlist_member, detect_chan_flood(), chanset_t::dname, findchan_by_dname, fixcolon, memstruct::flags, FLOOD_NICK, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, ismember, killmember(), memstruct::last, LOG_JOIN, LOG_MISC, chanset_t::next, memstruct::nick, now, NULL, putlog, rfc_casecmp, SENTDEHALFOP, SENTDEOP, SENTDEVOICE, SENTHALFOP, SENTKICK, SENTOP, SENTVOICE, memstruct::split, splitnick, STOPCHECK, UHOSTLEN, and memstruct::user.

02117 {
02118   char *nick, *chname, s1[UHOSTLEN], buf[UHOSTLEN], *uhost = buf;
02119   unsigned char found = 0;
02120   memberlist *m, *mm;
02121   struct chanset_t *chan, *oldchan = NULL;
02122   struct userrec *u;
02123   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
02124 
02125   strcpy(uhost, from);
02126   nick = splitnick(&uhost);
02127   fixcolon(msg);
02128   clear_chanlist_member(nick);  /* Cache for nick 'nick' is meaningless now. */
02129   for (chan = chanset; chan; chan = chan->next) {
02130     oldchan = chan;
02131     chname = chan->dname;
02132     m = ismember(chan, nick);
02133     if (m) {
02134       putlog(LOG_JOIN, chan->dname, "Nick change: %s -> %s", nick, msg);
02135       m->last = now;
02136       if (rfc_casecmp(nick, msg)) {
02137         /* Not just a capitalization change */
02138         mm = ismember(chan, msg);
02139         if (mm) {
02140           /* Someone on channel with old nick?! */
02141           if (mm->split)
02142             putlog(LOG_JOIN, chan->dname,
02143                    "Possible future nick collision: %s", mm->nick);
02144           else
02145             putlog(LOG_MISC, chan->dname,
02146                    "* Bug: nick change to existing nick");
02147           killmember(chan, mm->nick);
02148         }
02149       }
02150       /*
02151        * Banned?
02152        */
02153       /* Compose a nick!user@host for the new nick */
02154       sprintf(s1, "%s!%s", msg, uhost);
02155       strcpy(m->nick, msg);
02156       detect_chan_flood(msg, uhost, from, chan, FLOOD_NICK, NULL);
02157 
02158       if (!findchan_by_dname(chname)) {
02159         chan = oldchan;
02160         continue;
02161       }
02162       /* don't fill the serverqueue with modes or kicks in a nickflood */
02163       if (chan_sentkick(m) || chan_sentdeop(m) || chan_sentop(m) ||
02164           chan_sentdehalfop(m) || chan_senthalfop(m) || chan_sentdevoice(m) ||
02165           chan_sentvoice(m))
02166         m->flags |= STOPCHECK;
02167       /* Any pending kick or mode to the old nick is lost. */
02168       m->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTDEHALFOP | SENTHALFOP |
02169                     SENTVOICE | SENTDEVOICE);
02170       /* nick-ban or nick is +k or something? */
02171       if (!chan_stopcheck(m)) {
02172         get_user_flagrec(m->user ? m->user : get_user_by_host(s1), &fr,
02173                          chan->dname);
02174         check_this_member(chan, m->nick, &fr);
02175       }
02176       /* Make sure this is in the loop, someone could have changed the record
02177        * in an earlier iteration of the loop. */
02178       u = get_user_by_host(from);
02179       found = 1;
02180       check_tcl_nick(nick, uhost, u, chan->dname, msg);
02181 
02182       if (!findchan_by_dname(chname)) {
02183         chan = oldchan;
02184         continue;
02185       }
02186     }
02187   }
02188   if (!found) {
02189     u = get_user_by_host(from);
02190     s1[0] = '*';
02191     s1[1] = 0;
02192     check_tcl_nick(nick, uhost, u, s1, msg);
02193   }
02194   return 0;
02195 }

Here is the call graph for this function:

static int gotnotice ( char *  from,
char *  msg 
) [static]

Definition at line 2445 of file chan.c.

References ban_fun, chanset_t::ban_time, botnetnick, chan_deop, chan_friend, chan_op, chan_sentkick, CHANMETA, channel_dontkickops, check_exemptlist(), check_tcl_ctcr, check_tcl_notc(), detect_avalanche(), detect_chan_flood(), chanset_t::dname, DP_SERVER, dprintf, chanset_t::exempts, findchan, fixcolon, memstruct::flags, FLOOD_CTCP, FLOOD_NOTICE, FLOOD_PRIVMSG, flud_ctcp_thr, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_friend, glob_op, global_exempts, IRC_FUNKICK, ismember, kick_fun, LOG_MODES, LOG_PUBLIC, match_ignore, me_op(), chanset_t::name, newsplit, now, NULL, putlog, quickban(), SENTKICK, splitnick, trigger_on_ignore, u_addban(), u_match_mask(), update_idle(), and use_exempts.

02446 {
02447   char *to, *realto, *nick, buf2[512], *p, *p1, buf[512], *uhost = buf;
02448   char *ctcp, *code;
02449   struct userrec *u;
02450   memberlist *m;
02451   struct chanset_t *chan;
02452   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
02453   int ignoring;
02454 
02455   if (!strchr(CHANMETA "@", *msg))
02456     return 0;
02457   ignoring = match_ignore(from);
02458   to = newsplit(&msg);
02459   realto = (*to == '@') ? to + 1 : to;
02460   chan = findchan(realto);
02461   if (!chan)
02462     return 0;                   /* Notice to an unknown channel?? */
02463   fixcolon(msg);
02464   strcpy(uhost, from);
02465   nick = splitnick(&uhost);
02466   u = get_user_by_host(from);
02467   if (flud_ctcp_thr && detect_avalanche(msg)) {
02468     get_user_flagrec(u, &fr, chan->dname);
02469     m = ismember(chan, nick);
02470     /* Discard -- kick user if it was to the channel */
02471     if (me_op(chan) && m && !chan_sentkick(m) && !chan_friend(fr) &&
02472         !glob_friend(fr) && !(channel_dontkickops(chan) && (chan_op(fr) ||
02473         (glob_op(fr) && !chan_deop(fr)))) && !(use_exempts && ban_fun &&
02474         (u_match_mask(global_exempts, from) ||
02475         u_match_mask(chan->exempts, from)))) {
02476       if (ban_fun) {
02477         check_exemptlist(chan, from);
02478         u_addban(chan, quickban(chan, uhost), botnetnick,
02479                  IRC_FUNKICK, now + (60 * chan->ban_time), 0);
02480       }
02481       if (kick_fun) {
02482         /* This can induce kickflood - arthur2 */
02483         dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, nick, IRC_FUNKICK);
02484         m->flags |= SENTKICK;
02485       }
02486     }
02487     if (!ignoring)
02488       putlog(LOG_MODES, "*", "Avalanche from %s", from);
02489     return 0;
02490   }
02491   /* Check for CTCP: */
02492   p = strchr(msg, 1);
02493   while (p && *p) {
02494     p++;
02495     p1 = p;
02496     while ((*p != 1) && *p)
02497       p++;
02498     if (*p == 1) {
02499       *p = 0;
02500       ctcp = buf2;
02501       strcpy(ctcp, p1);
02502       strcpy(p1 - 1, p + 1);
02503       p = strchr(msg, 1);
02504       detect_chan_flood(nick, uhost, from, chan,
02505                         strncmp(ctcp, "ACTION ", 7) ?
02506                         FLOOD_CTCP : FLOOD_PRIVMSG, NULL);
02507 
02508       chan = findchan(realto);
02509       if (!chan)
02510         return 0;
02511 
02512       if (ctcp[0] != ' ') {
02513         code = newsplit(&ctcp);
02514         if (!ignoring || trigger_on_ignore) {
02515           check_tcl_ctcr(nick, uhost, u, chan->dname, code, msg);
02516 
02517           chan = findchan(realto);
02518           if (!chan)
02519             return 0;
02520 
02521           if (!ignoring) {
02522             putlog(LOG_PUBLIC, chan->dname,
02523                    "CTCP reply %s: %s from %s (%s) to %s", code, msg, nick,
02524                    from, chan->dname);
02525             update_idle(chan->dname, nick);
02526           }
02527         }
02528       }
02529     }
02530   }
02531   if (msg[0]) {
02532 
02533     /* Check even if we're ignoring the host. (modified by Eule 17.7.99) */
02534     detect_chan_flood(nick, uhost, from, chan, FLOOD_NOTICE, NULL);
02535 
02536     chan = findchan(realto);
02537     if (!chan)
02538       return 0;
02539 
02540     update_idle(chan->dname, nick);
02541 
02542     if (!ignoring || trigger_on_ignore)
02543       if (check_tcl_notc(nick, uhost, u, to, msg) == 2)
02544         return 0;
02545 
02546     if (!ignoring)
02547       putlog(LOG_PUBLIC, chan->dname, "-%s:%s- %s", nick, to, msg);
02548   }
02549   return 0;
02550 }

Here is the call graph for this function:

static int gotpart ( char *  from,
char *  msg 
) [static]

Definition at line 1964 of file chan.c.

References CHAN_ACTIVE, CHAN_PEND, CHAN_RESETALL, chanset_t::channel, channel_active, channel_inactive, channel_pending, check_lonely_channel(), check_tcl_part(), clear_channel(), chanset_t::dname, DP_SERVER, dprintf, findchan, fixcolon, get_user_by_host, chan_t::key, chanset_t::key_prot, killmember(), LOG_JOIN, LOG_MISC, match_my_nick(), chanset_t::name, newsplit, now, putlog, reset_chan_info(), set_handle_laston(), splitnick, and chanset_t::status.

01965 {
01966   char *nick, *chname, *key;
01967   struct chanset_t *chan;
01968   struct userrec *u;
01969 
01970   chname = newsplit(&msg);
01971   fixcolon(chname);
01972   fixcolon(msg);
01973   chan = findchan(chname);
01974   if (chan && channel_inactive(chan)) {
01975     clear_channel(chan, 1);
01976     chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
01977     return 0;
01978   }
01979   if (chan && !channel_pending(chan)) {
01980     u = get_user_by_host(from);
01981     nick = splitnick(&from);
01982     if (!channel_active(chan)) {
01983       /* whoa! */
01984       putlog(LOG_MISC, chan->dname,
01985              "confused bot: guess I'm on %s and didn't realize it",
01986              chan->dname);
01987       chan->status |= CHAN_ACTIVE;
01988       chan->status &= ~CHAN_PEND;
01989       reset_chan_info(chan, CHAN_RESETALL);
01990     }
01991     set_handle_laston(chan->dname, u, now);
01992     /* This must be directly above the killmember, in case we're doing anything
01993      * to the record that would affect the above */
01994     check_tcl_part(nick, from, u, chan->dname, msg);
01995 
01996     chan = findchan(chname);
01997     if (!chan)
01998       return 0;
01999 
02000     killmember(chan, nick);
02001     if (msg[0])
02002       putlog(LOG_JOIN, chan->dname, "%s (%s) left %s (%s).", nick, from,
02003              chan->dname, msg);
02004     else
02005       putlog(LOG_JOIN, chan->dname, "%s (%s) left %s.", nick, from,
02006              chan->dname);
02007     /* If it was me, all hell breaks loose... */
02008     if (match_my_nick(nick)) {
02009       clear_channel(chan, 1);
02010       chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
02011       if (!channel_inactive(chan)) {
02012 
02013         key = chan->channel.key[0] ? chan->channel.key : chan->key_prot;
02014         if (key[0])
02015           dprintf(DP_SERVER, "JOIN %s %s\n",
02016                   chan->name[0] ? chan->name : chan->dname, key);
02017         else
02018           dprintf(DP_SERVER, "JOIN %s\n",
02019                   chan->name[0] ? chan->name : chan->dname);
02020       }
02021     } else
02022       check_lonely_channel(chan);
02023   }
02024   return 0;
02025 }

Here is the call graph for this function:

static int gotquit ( char *  from,
char *  msg 
) [static]

Definition at line 2199 of file chan.c.

References botname, chanset, check_lonely_channel(), check_tcl_sign, check_tcl_splt, chanset_t::dname, DP_SERVER, dprintf, findchan_by_dname, fixcolon, get_altbotnick(), get_user_by_host, IRC_GETALTNICK, IRC_GETORIGNICK, ismember, keepnick, killmember(), LOG_JOIN, LOG_MISC, chanset_t::next, NICKMAX, now, NULL, origbotname, putlog, rfc_casecmp, set_handle_laston(), memstruct::split, splitnick, and UHOSTMAX.

02200 {
02201   char *nick, *chname, *p, *alt;
02202   int split = 0;
02203   char from2[NICKMAX + UHOSTMAX + 1];
02204   memberlist *m;
02205   struct chanset_t *chan, *oldchan = NULL;
02206   struct userrec *u;
02207 
02208   strcpy(from2, from);
02209   u = get_user_by_host(from2);
02210   nick = splitnick(&from);
02211   fixcolon(msg);
02212   /* Fred1: Instead of expensive wild_match on signoff, quicker method.
02213    *        Determine if signoff string matches "%.% %.%", and only one
02214    *        space.
02215    */
02216   p = strchr(msg, ' ');
02217   if (p && (p == strrchr(msg, ' '))) {
02218     char *z1, *z2;
02219 
02220     *p = 0;
02221     z1 = strchr(p + 1, '.');
02222     z2 = strchr(msg, '.');
02223     if (z1 && z2 && (*(z1 + 1) != 0) && (z1 - 1 != p) &&
02224         (z2 + 1 != p) && (z2 != msg)) {
02225       /* Server split, or else it looked like it anyway (no harm in
02226        * assuming)
02227        */
02228       split = 1;
02229     } else
02230       *p = ' ';
02231   }
02232   for (chan = chanset; chan; chan = chan->next) {
02233     oldchan = chan;
02234     chname = chan->dname;
02235     m = ismember(chan, nick);
02236     if (m) {
02237       u = get_user_by_host(from2);
02238       if (u)
02239         /* If you remove this, the bot will crash when the user record in
02240          * question is removed/modified during the tcl binds below, and the
02241          * users was on more than one monitored channel */
02242         set_handle_laston(chan->dname, u, now);
02243       if (split) {
02244         m->split = now;
02245         check_tcl_splt(nick, from, u, chan->dname);
02246 
02247         if (!findchan_by_dname(chname)) {
02248           chan = oldchan;
02249           continue;
02250         }
02251         putlog(LOG_JOIN, chan->dname, "%s (%s) got netsplit.", nick, from);
02252       } else {
02253         check_tcl_sign(nick, from, u, chan->dname, msg);
02254 
02255         if (!findchan_by_dname(chname)) {
02256           chan = oldchan;
02257           continue;
02258         }
02259         putlog(LOG_JOIN, chan->dname, "%s (%s) left irc: %s", nick, from, msg);
02260         killmember(chan, nick);
02261         check_lonely_channel(chan);
02262       }
02263     }
02264   }
02265   /* Our nick quit? if so, grab it. Heck, our altnick quit maybe, maybe
02266    * we want it.
02267    */
02268   if (keepnick) {
02269     alt = get_altbotnick();
02270     if (!rfc_casecmp(nick, origbotname)) {
02271       putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
02272       dprintf(DP_SERVER, "NICK %s\n", origbotname);
02273     } else if (alt[0]) {
02274       if (!rfc_casecmp(nick, alt) && strcmp(botname, origbotname)) {
02275         putlog(LOG_MISC, "*", IRC_GETALTNICK, alt);
02276         dprintf(DP_SERVER, "NICK %s\n", alt);
02277       }
02278     }
02279   }
02280   return 0;
02281 }

Here is the call graph for this function:

static int gottopic ( char *  from,
char *  msg 
) [static]

Definition at line 1553 of file chan.c.

References check_tcl_topc, chanset_t::dname, findchan, fixcolon, get_user_by_host, ismember, memstruct::last, LOG_JOIN, newsplit, now, NULL, putlog, set_topic(), and splitnick.

01554 {
01555   char *nick, *chname;
01556   memberlist *m;
01557   struct chanset_t *chan;
01558   struct userrec *u;
01559 
01560   chname = newsplit(&msg);
01561   fixcolon(msg);
01562   u = get_user_by_host(from);
01563   nick = splitnick(&from);
01564   chan = findchan(chname);
01565   if (chan) {
01566     putlog(LOG_JOIN, chan->dname, "Topic changed on %s by %s!%s: %s",
01567            chan->dname, nick, from, msg);
01568     m = ismember(chan, nick);
01569     if (m != NULL)
01570       m->last = now;
01571     set_topic(chan, msg);
01572     check_tcl_topc(nick, from, u, chan->dname, msg);
01573   }
01574   return 0;
01575 }

Here is the call graph for this function:

static void kick_all ( struct chanset_t chan,
char *  hostmask,
char *  comment,
int  bantype 
) [static]

Definition at line 384 of file chan.c.

References chan_deop, chan_friend, chan_hasop, chan_issplit, chan_op, chan_sentkick, chanset_t::channel, channel_dontkickops, chanset_t::dname, DP_SERVER, dprintf, chanset_t::exempts, memstruct::flags, flush_mode(), FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_friend, glob_op, global_exempts, isexempted, kick_method, match_addr, match_my_nick(), me_halfop(), me_op(), chan_t::member, chanset_t::name, memstruct::next, memstruct::nick, QUICK, SENTKICK, u_match_mask(), UHOSTLEN, use_exempts, memstruct::user, and memstruct::userhost.

Referenced by enforce_bans(), got_ban(), and refresh_ban_kick().

00386 {
00387   memberlist *m;
00388   char kicknick[512], s[UHOSTLEN];
00389   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00390   int k, l, flushed;
00391 
00392   if (!me_op(chan) && !me_halfop(chan))
00393     return;
00394 
00395   k = 0;
00396   flushed = 0;
00397   kicknick[0] = 0;
00398   for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00399     sprintf(s, "%s!%s", m->nick, m->userhost);
00400     get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, chan->dname);
00401     if ((me_op(chan) || (me_halfop(chan) && !chan_hasop(m))) &&
00402         match_addr(hostmask, s) && !chan_sentkick(m) &&
00403         !match_my_nick(m->nick) && !chan_issplit(m) &&
00404         !glob_friend(fr) && !chan_friend(fr) && !(use_exempts && ((bantype &&
00405         isexempted(chan, s)) || (u_match_mask(global_exempts, s) ||
00406         u_match_mask(chan->exempts, s)))) && !(channel_dontkickops(chan) &&
00407         (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))))) {
00408       if (!flushed) {
00409         /* We need to kick someone, flush eventual bans first */
00410         flush_mode(chan, QUICK);
00411         flushed += 1;
00412       }
00413       m->flags |= SENTKICK;     /* Mark as pending kick */
00414       if (kicknick[0])
00415         strcat(kicknick, ",");
00416       strcat(kicknick, m->nick);
00417       k += 1;
00418       l = strlen(chan->name) + strlen(kicknick) + strlen(comment) + 5;
00419       if ((kick_method != 0 && k == kick_method) || (l > 480)) {
00420         dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick, comment);
00421         k = 0;
00422         kicknick[0] = 0;
00423       }
00424     }
00425   }
00426   if (k > 0)
00427     dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, kicknick, comment);
00428 }

Here is the call graph for this function:

Here is the caller graph for this function:

static memberlist* newmember ( struct chanset_t chan  )  [static]

Definition at line 42 of file chan.c.

References chanset_t::channel, channel_malloc(), memstruct::delay, memstruct::last, chan_t::member, chan_t::members, memstruct::next, memstruct::nick, NULL, and memstruct::split.

Referenced by got352or4(), and gotjoin().

00043 {
00044   memberlist *x;
00045 
00046   for (x = chan->channel.member; x && x->nick[0]; x = x->next);
00047   x->next = (memberlist *) channel_malloc(sizeof(memberlist));
00048   x->next->next = NULL;
00049   x->next->nick[0] = 0;
00050   x->next->split = 0L;
00051   x->next->last = 0L;
00052   x->next->delay = 0L;
00053   chan->channel.members++;
00054   return x;
00055 }

Here is the call graph for this function:

Here is the caller graph for this function:

static char* quickban ( struct chanset_t chan,
char *  uhost 
) [static]

Definition at line 372 of file chan.c.

References chan_t::ban, chanset_t::ban_type, chanset_t::channel, do_mask(), and maskaddr.

Referenced by check_this_member(), cmd_kickban(), gotjoin(), gotmsg(), and gotnotice().

00373 {
00374   static char s1[512];
00375 
00376   maskaddr(uhost, s1, chan->ban_type);
00377   do_mask(chan, chan->channel.ban, s1, 'b');
00378   return s1;
00379 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void recheck_bans ( struct chanset_t chan  )  [static]

Definition at line 540 of file chan.c.

References add_mode, chanset_t::bans, channel_dynamicbans, maskrec::flags, global_bans, isbanned, maskrec::mask, MASKREC_STICKY, and maskrec::next.

Referenced by recheck_channel(), and resetmasks().

00541 {
00542   maskrec *u;
00543   int cycle;
00544 
00545   /* Check global bans in first cycle and channel bans in second cycle. */
00546   for (cycle = 0; cycle < 2; cycle++) {
00547     for (u = cycle ? chan->bans : global_bans; u; u = u->next)
00548       if (!isbanned(chan, u->mask) && (!channel_dynamicbans(chan) ||
00549           (u->flags & MASKREC_STICKY)))
00550         add_mode(chan, '+', 'b', u->mask);
00551   }
00552 }

Here is the caller graph for this function:

static void recheck_channel ( struct chanset_t chan,
int  dobans 
) [static]

Definition at line 868 of file chan.c.

References CHAN_ASKED_EXEMPTS, CHAN_ASKED_INVITED, CHAN_ASKEDMODES, chan_hasop, CHAN_RESETEXEMPTS, CHAN_RESETINVITED, chanset_t::channel, channel_enforcebans, channel_inactive, channel_nouserbans, channel_nouserexempts, channel_nouserinvites, check_this_member(), chanset_t::dname, DP_MODE, dprintf, enforce_bans(), memstruct::flags, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_bot, chanset_t::ircnet_status, match_my_nick(), chan_t::member, chanset_t::name, memstruct::next, memstruct::nick, recheck_bans(), recheck_channel_modes(), recheck_exempts(), recheck_invites(), reset_chan_info(), resetbans, resetexempts, resetinvites, SENTHALFOP, SENTKICK, chanset_t::status, memstruct::tried_getuser, UHOSTLEN, use_exempts, use_invites, memstruct::user, memstruct::userhost, and userlist.

Referenced by got315(), got_halfop(), and got_op().

00869 {
00870   memberlist *m;
00871   char s[UHOSTLEN];
00872   struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00873   static int stacking = 0;
00874   int stop_reset = 0;
00875 
00876   if (stacking || !userlist)
00877     return;
00878 
00879   stacking++;
00880   /* Okay, sort through who needs to be deopped. */
00881   for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00882     sprintf(s, "%s!%s", m->nick, m->userhost);
00883     if (!m->user && !m->tried_getuser) {
00884       m->tried_getuser = 1;
00885       m->user = get_user_by_host(s);
00886     }
00887     get_user_flagrec(m->user, &fr, chan->dname);
00888     if (glob_bot(fr) && chan_hasop(m) && !match_my_nick(m->nick))
00889       stop_reset = 1;
00890     /* Perhaps we were halfop and tried to halfop/kick the user earlier but
00891      * the server rejected the request, so let's try again. */
00892     m->flags &= ~(SENTHALFOP | SENTKICK);
00893     check_this_member(chan, m->nick, &fr);
00894   }
00895   /* Most IRCDs nowadays require +h/+o for getting e/I lists,
00896    * so if we're still waiting for these, we'll request them here.
00897    * In case we got them on join, nothing will be done */
00898   if (chan->ircnet_status & (CHAN_ASKED_EXEMPTS | CHAN_ASKED_INVITED)) {
00899     chan->ircnet_status &= ~(CHAN_ASKED_EXEMPTS | CHAN_ASKED_INVITED);
00900     reset_chan_info(chan, CHAN_RESETEXEMPTS | CHAN_RESETINVITED);
00901   }
00902   if (dobans) {
00903     if (channel_nouserbans(chan) && !stop_reset)
00904       resetbans(chan);
00905     else
00906       recheck_bans(chan);
00907     if (use_invites) {
00908       if (channel_nouserinvites(chan) && !stop_reset)
00909         resetinvites(chan);
00910       else
00911         recheck_invites(chan);
00912     }
00913     if (use_exempts) {
00914       if (channel_nouserexempts(chan) && !stop_reset)
00915         resetexempts(chan);
00916       else
00917         recheck_exempts(chan);
00918     }
00919     if (channel_enforcebans(chan))
00920       enforce_bans(chan);
00921     if ((chan->status & CHAN_ASKEDMODES) && !channel_inactive(chan))
00922       dprintf(DP_MODE, "MODE %s\n", chan->name);
00923     recheck_channel_modes(chan);
00924   }
00925   stacking--;
00926 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void recheck_channel_modes ( struct chanset_t chan  )  [static]

Definition at line 658 of file chan.c.

References add_mode, CHAN_ASKEDMODES, CHANANON, CHANDELJN, CHANINV, CHANKEY, CHANLIMIT, CHANLONLY, CHANMODER, CHANMODREG, chanset_t::channel, CHANNOAMSG, CHANNOCLR, CHANNOCTCP, CHANNOMSG, CHANNONOTC, CHANPRIV, CHANQUIET, CHANREGON, CHANSEC, CHANSTRIP, CHANTOPIC, chan_t::key, chanset_t::key_prot, chanset_t::limit_prot, chan_t::maxmembers, chan_t::mode, chanset_t::mode_mns_prot, chanset_t::mode_pls_prot, rfc_casecmp, and chanset_t::status.

Referenced by got324(), and recheck_channel().

00659 {
00660   int cur = chan->channel.mode, mns = chan->mode_mns_prot,
00661       pls = chan->mode_pls_prot;
00662 
00663   if (!(chan->status & CHAN_ASKEDMODES)) {
00664     if (pls & CHANINV && !(cur & CHANINV))
00665       add_mode(chan, '+', 'i', "");
00666     else if (mns & CHANINV && cur & CHANINV)
00667       add_mode(chan, '-', 'i', "");
00668     if (pls & CHANPRIV && !(cur & CHANPRIV))
00669       add_mode(chan, '+', 'p', "");
00670     else if (mns & CHANPRIV && cur & CHANPRIV)
00671       add_mode(chan, '-', 'p', "");
00672     if (pls & CHANSEC && !(cur & CHANSEC))
00673       add_mode(chan, '+', 's', "");
00674     else if (mns & CHANSEC && cur & CHANSEC)
00675       add_mode(chan, '-', 's', "");
00676     if (pls & CHANMODER && !(cur & CHANMODER))
00677       add_mode(chan, '+', 'm', "");
00678     else if (mns & CHANMODER && cur & CHANMODER)
00679       add_mode(chan, '-', 'm', "");
00680     if (pls & CHANNOCLR && !(cur & CHANNOCLR))
00681       add_mode(chan, '+', 'c', "");
00682     else if (mns & CHANNOCLR && cur & CHANNOCLR)
00683       add_mode(chan, '-', 'c', "");
00684     if (pls & CHANNOCTCP && !(cur & CHANNOCTCP))
00685       add_mode(chan, '+', 'C', "");
00686     else if (mns & CHANNOCTCP && cur & CHANNOCTCP)
00687       add_mode(chan, '-', 'C', "");
00688     if (pls & CHANREGON && !(cur & CHANREGON))
00689       add_mode(chan, '+', 'R', "");
00690     else if (mns & CHANREGON && cur & CHANREGON)
00691       add_mode(chan, '-', 'R', "");
00692     if (pls & CHANMODREG && !(cur & CHANMODREG))
00693       add_mode(chan, '+', 'M', "");
00694     else if (mns & CHANMODREG && cur & CHANMODREG)
00695       add_mode(chan, '-', 'M', "");
00696     if (pls & CHANLONLY && !(cur & CHANLONLY))
00697       add_mode(chan, '+', 'r', "");
00698     else if (mns & CHANLONLY && cur & CHANLONLY)
00699       add_mode(chan, '-', 'r', "");
00700     if (pls & CHANDELJN && !(cur & CHANDELJN))
00701       add_mode(chan, '+', 'D', "");
00702     else if (mns & CHANDELJN && cur & CHANDELJN)
00703       add_mode(chan, '-', 'D', "");
00704     if (pls & CHANSTRIP && !(cur & CHANSTRIP))
00705       add_mode(chan, '+', 'u', "");
00706     else if (mns & CHANSTRIP && cur & CHANSTRIP)
00707       add_mode(chan, '-', 'u', "");
00708     if (pls & CHANNONOTC && !(cur & CHANNONOTC))
00709       add_mode(chan, '+', 'N', "");
00710     else if (mns & CHANNONOTC && cur & CHANNONOTC)
00711       add_mode(chan, '-', 'N', "");
00712     if (pls & CHANNOAMSG && !(cur & CHANNOAMSG))
00713       add_mode(chan, '+', 'T', "");
00714     else if (mns & CHANNOAMSG && cur & CHANNOAMSG)
00715       add_mode(chan, '-', 'T', "");
00716     if (pls & CHANTOPIC && !(cur & CHANTOPIC))
00717       add_mode(chan, '+', 't', "");
00718     else if (mns & CHANTOPIC && cur & CHANTOPIC)
00719       add_mode(chan, '-', 't', "");
00720     if (pls & CHANNOMSG && !(cur & CHANNOMSG))
00721       add_mode(chan, '+', 'n', "");
00722     else if ((mns & CHANNOMSG) && (cur & CHANNOMSG))
00723       add_mode(chan, '-', 'n', "");
00724     if ((pls & CHANANON) && !(cur & CHANANON))
00725       add_mode(chan, '+', 'a', "");
00726     else if ((mns & CHANANON) && (cur & CHANANON))
00727       add_mode(chan, '-', 'a', "");
00728     if ((pls & CHANQUIET) && !(cur & CHANQUIET))
00729       add_mode(chan, '+', 'q', "");
00730     else if ((mns & CHANQUIET) && (cur & CHANQUIET))
00731       add_mode(chan, '-', 'q', "");
00732     if ((chan->limit_prot != 0) && (chan->channel.maxmembers == 0)) {
00733       char s[50];
00734 
00735       sprintf(s, "%d", chan->limit_prot);
00736       add_mode(chan, '+', 'l', s);
00737     } else if ((mns & CHANLIMIT) && (chan->channel.maxmembers != 0))
00738       add_mode(chan, '-', 'l', "");
00739     if (chan->key_prot[0]) {
00740       if (rfc_casecmp(chan->channel.key, chan->key_prot) != 0) {
00741         if (chan->channel.key[0])
00742           add_mode(chan, '-', 'k', chan->channel.key);
00743         add_mode(chan, '+', 'k', chan->key_prot);
00744       }
00745     } else if ((mns & CHANKEY) && (chan->channel.key[0]))
00746       add_mode(chan, '-', 'k', chan->channel.key);
00747   }
00748 }

Here is the caller graph for this function:

static void recheck_exempts ( struct chanset_t chan  )  [static]

Definition at line 559 of file chan.c.

References add_mode, chan_t::ban, chanset_t::channel, channel_dynamicexempts, e, chanset_t::exempts, maskrec::flags, global_exempts, isexempted, maskstruct::mask, maskrec::mask, mask_match, MASKREC_STICKY, maskstruct::next, and maskrec::next.

Referenced by recheck_channel(), and resetmasks().

00560 {
00561   maskrec *e;
00562   masklist *b;
00563   int cycle;
00564 
00565   /* Check global exempts in first cycle and channel exempts in second cycle. */
00566   for (cycle = 0; cycle < 2; cycle++) {
00567     for (e = cycle ? chan->exempts : global_exempts; e; e = e->next) {
00568       if (!isexempted(chan, e->mask) &&
00569           (!channel_dynamicexempts(chan) || (e->flags & MASKREC_STICKY)))
00570         add_mode(chan, '+', 'e', e->mask);
00571       for (b = chan->channel.ban; b && b->mask[0]; b = b->next) {
00572         if (mask_match(b->mask, e->mask) &&
00573             !isexempted(chan, e->mask))
00574           add_mode(chan, '+', 'e', e->mask);
00575         /* do_mask(chan, chan->channel.exempt, e->mask, 'e'); */
00576       }
00577     }
00578   }
00579 }

Here is the caller graph for this function:

static void recheck_invites ( struct chanset_t chan  )  [static]

Definition at line 586 of file chan.c.

References add_mode, CHANINV, chanset_t::channel, channel_dynamicinvites, maskrec::flags, global_invites, chanset_t::invites, isinvited, maskrec::mask, MASKREC_STICKY, chan_t::mode, and maskrec::next.

Referenced by recheck_channel(), and resetmasks().

00587 {
00588   maskrec *ir;
00589   int cycle;
00590 
00591   /* Check global invites in first cycle and channel invites in second cycle. */
00592   for (cycle = 0; cycle < 2; cycle++) {
00593     for (ir = cycle ? chan->invites : global_invites; ir; ir = ir->next) {
00594       /* If invite isn't set and (channel is not dynamic invites and not invite
00595        * only) or invite is sticky.
00596        */
00597       if (!isinvited(chan, ir->mask) && ((!channel_dynamicinvites(chan) &&
00598           !(chan->channel.mode & CHANINV)) || ir->flags & MASKREC_STICKY))
00599         add_mode(chan, '+', 'I', ir->mask);
00600       /* do_mask(chan, chan->channel.invite, ir->mask, 'I'); */
00601     }
00602   }
00603 }

Here is the caller graph for this function:

static void refresh_ban_kick ( struct chanset_t chan,
char *  user,
char *  nick 
) [static]

Definition at line 432 of file chan.c.

References add_mode, chan_t::ban, chanset_t::bans, chan_friend, chan_sentkick, chanset_t::channel, check_exemptlist(), maskrec::desc, chanset_t::dname, do_mask(), egg_snprintf, FR_CHAN, FR_GLOBAL, get_user_by_host, get_user_flagrec, glob_friend, global_bans, IRC_PREBANNED, IRC_YOUREBANNED, ismember, kick_all(), maskrec::lastactive, maskrec::mask, match_addr, maskrec::next, memstruct::nick, now, UHOSTLEN, memstruct::user, and memstruct::userhost.

Referenced by check_this_ban(), check_this_member(), and gotjoin().

00433 {
00434   register maskrec *b;
00435   memberlist *m;
00436   int cycle;
00437 
00438   m = ismember(chan, nick);
00439   if (!m || chan_sentkick(m))
00440     return;
00441 
00442   /* Check global bans in first cycle and channel bans in second cycle. */
00443   for (cycle = 0; cycle < 2; cycle++) {
00444     for (b = cycle ? chan->bans : global_bans; b; b = b->next) {
00445       if (match_addr(b->mask, user)) {
00446         struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00447         char c[512];            /* The ban comment.     */
00448         char s[UHOSTLEN];
00449 
00450         sprintf(s, "%s!%s", m->nick, m->userhost);
00451         get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr,
00452                          chan->dname);
00453         if (!glob_friend(fr) && !chan_friend(fr)) {
00454           add_mode(chan, '-', 'o', nick);       /* Guess it can't hurt. */
00455           check_exemptlist(chan, user);
00456           do_mask(chan, chan->channel.ban, b->mask, 'b');
00457           b->lastactive = now;
00458           if (b->desc && b->desc[0] != '@')
00459             egg_snprintf(c, sizeof c, "%s %s", IRC_PREBANNED, b->desc);
00460           else
00461             c[0] = 0;
00462           kick_all(chan, b->mask, c[0] ? c : IRC_YOUREBANNED, 0);
00463           return;               /* Drop out on 1st ban. */
00464         }
00465       }
00466     }
00467   }
00468 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void refresh_exempt ( struct chanset_t chan,
char *  user 
) [static]

Definition at line 473 of file chan.c.

References chan_t::ban, chanset_t::channel, do_mask(), e, chan_t::exempt, chanset_t::exempts, global_exempts, isexempted, maskrec::lastactive, maskstruct::mask, maskrec::mask, mask_match, maskstruct::next, maskrec::next, and now.

Referenced by got_ban().

00474 {
00475   maskrec *e;
00476   masklist *b;
00477   int cycle;
00478 
00479   /* Check global exempts in first cycle and channel exempts in second cycle. */
00480   for (cycle = 0; cycle < 2; cycle++) {
00481     for (e = cycle ? chan->exempts : global_exempts; e; e = e->next) {
00482       if (mask_match(user, e->mask)) {
00483         for (b = chan->channel.ban; b && b->mask[0]; b = b->next) {
00484           if (mask_match(b->mask, user)) {
00485             if (e->lastactive < now - 60 && !isexempted(chan, e->mask)) {
00486               do_mask(chan, chan->channel.exempt, e->mask, 'e');
00487               e->lastactive = now;
00488             }
00489           }
00490         }
00491       }
00492     }
00493   }
00494 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void refresh_invite ( struct chanset_t chan,
char *  user 
) [static]

Definition at line 496 of file chan.c.

References CHANINV, chanset_t::channel, do_mask(), maskrec::flags, global_invites, chan_t::invite, chanset_t::invites, isinvited, maskrec::lastactive, maskrec::mask, MASKREC_STICKY, match_addr, chan_t::mode, maskrec::next, and now.

Referenced by check_this_member(), and gotjoin().

00497 {
00498   maskrec *i;
00499   int cycle;
00500 
00501   /* Check global invites in first cycle and channel invites in second cycle. */
00502   for (cycle = 0; cycle < 2; cycle++) {
00503     for (i = cycle ? chan->invites : global_invites; i; i = i->next) {
00504       if (match_addr(i->mask, user) &&
00505           ((i->flags & MASKREC_STICKY) || (chan->channel.mode & CHANINV))) {
00506         if (i->lastactive < now - 60 && !isinvited(chan, i->mask)) {
00507           do_mask(chan, chan->channel.invite, i->mask, 'I');
00508           i->lastactive = now;
00509           return;
00510         }
00511       }
00512     }
00513   }
00514 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void resetmasks ( struct chanset_t chan,
masklist m,
maskrec mrec,
maskrec global_masks,
char  mode 
) [static]

Definition at line 607 of file chan.c.

References add_mode, LOG_MISC, maskstruct::mask, me_halfop(), me_op(), maskstruct::next, NOHALFOPS_MODES, NULL, putlog, recheck_bans(), recheck_exempts(), recheck_invites(), and u_equals_mask().

00609 {
00610   if (!me_op(chan) && (!me_halfop(chan) ||
00611       (strchr(NOHALFOPS_MODES, 'b') != NULL) ||
00612       (strchr(NOHALFOPS_MODES, 'e') != NULL) ||
00613       (strchr(NOHALFOPS_MODES, 'I') != NULL)))
00614     return;
00615 
00616   /* Remove masks we didn't put there */
00617   for (; m && m->mask[0]; m = m->next) {
00618     if (!u_equals_mask(global_masks, m->mask) && !u_equals_mask(mrec, m->mask))
00619       add_mode(chan, '-', mode, m->mask);
00620   }
00621 
00622   /* Make sure the intended masks are still there */
00623   switch (mode) {
00624   case 'b':
00625     recheck_bans(chan);
00626     break;
00627   case 'e':
00628     recheck_exempts(chan);
00629     break;
00630   case 'I':
00631     recheck_invites(chan);
00632     break;
00633   default:
00634     putlog(LOG_MISC, "*", "(!) Invalid mode '%c' in resetmasks()", mode);
00635     break;
00636   }
00637 }

Here is the call graph for this function:

static void set_delay ( struct chanset_t chan,
char *  nick 
) [static]

Definition at line 1616 of file chan.c.

References chanset_t::aop_max, chanset_t::aop_min, chanset_t::channel, count, memstruct::delay, memstruct::flags, FULL_DELAY, ismember, chan_t::member, modesperline, memstruct::next, memstruct::nick, now, randint, and time_t.

Referenced by check_this_member(), and gotjoin().

01617 {
01618   time_t a_delay;
01619   int aop_min, aop_max, aop_diff, count = 0;
01620   memberlist *m, *m2;
01621 
01622   m = ismember(chan, nick);
01623   if (!m)
01624     return;
01625 
01626   /* aop-delay 5:30 -- aop_min:aop_max */
01627   aop_min = chan->aop_min;
01628   aop_max = chan->aop_max;
01629   aop_diff = aop_max - aop_min;
01630 
01631   /* If either min or max is less than or equal to 0 we don't delay. */
01632   if ((aop_min <= 0) || (aop_max <= 0)) {
01633     a_delay = now + 1;
01634 
01635   /* Use min value for delay if min greater then or equal to max or if the
01636    * difference of max and min is greater than RANDOM_MAX (sanity check).
01637    */
01638   } else if ((aop_min >= aop_max) || (aop_diff > RANDOM_MAX)) {
01639     a_delay = now + aop_min;
01640 
01641   /* Set a random delay based on the difference of max and min */
01642   } else {
01643     a_delay = now + randint(aop_diff) + aop_min + 1;
01644   }
01645 
01646   for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
01647     if (m2->delay && !(m2->flags & FULL_DELAY))
01648       count++;
01649 
01650   if (count) {
01651     for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next) {
01652       if (m2->delay && !(m2->flags & FULL_DELAY)) {
01653         m2->delay = a_delay;
01654 
01655         if (count + 1 >= modesperline)
01656           m2->flags |= FULL_DELAY;
01657 
01658       }
01659     }
01660   }
01661 
01662   if (count + 1 >= modesperline)
01663     m->flags |= FULL_DELAY;
01664 
01665   m->delay = a_delay;
01666 }

Here is the caller graph for this function:

static void set_topic ( struct chanset_t chan,
char *  k 
) [static]

Definition at line 1540 of file chan.c.

References chanset_t::channel, channel_malloc(), nfree, NULL, and chan_t::topic.

Referenced by got331(), got332(), and gottopic().

01541 {
01542   if (chan->channel.topic)
01543     nfree(chan->channel.topic);
01544   if (k && k[0]) {
01545     chan->channel.topic = (char *) channel_malloc(strlen(k) + 1);
01546     strcpy(chan->channel.topic, k);
01547   } else
01548     chan->channel.topic = NULL;
01549 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void sync_members ( struct chanset_t chan  )  [inline, static]

Definition at line 58 of file chan.c.

References chan_whosynced, chanset_t::channel, chan_t::member, chan_t::members, memstruct::next, nfree, and memstruct::nick.

Referenced by got315().

00059 {
00060   memberlist *m, *next, *prev;
00061 
00062   for (m = chan->channel.member, prev = 0; m && m->nick[0]; m = next) {
00063     next = m->next;
00064     if (!chan_whosynced(m)) {
00065       if (prev)
00066         prev->next = next;
00067       else
00068         chan->channel.member = next;
00069       nfree(m);
00070       chan->channel.members--;
00071     } else
00072       prev = m;
00073   }
00074 }

Here is the caller graph for this function:

static void update_idle ( char *  chname,
char *  nick 
) [static]

Definition at line 78 of file chan.c.

References findchan_by_dname, ismember, memstruct::last, and now.

Referenced by gotmsg(), and gotnotice().

00079 {
00080   memberlist *m;
00081   struct chanset_t *chan;
00082 
00083   chan = findchan_by_dname(chname);
00084   if (chan) {
00085     m = ismember(chan, nick);
00086     if (m)
00087       m->last = now;
00088   }
00089 }

Here is the caller graph for this function:


Variable Documentation

int count_ctcp = 0 [static]

Definition at line 31 of file chan.c.

Referenced by gotmsg().

cmd_t irc_raw[] [static]

Definition at line 2552 of file chan.c.

Referenced by irc_close(), and irc_start().

time_t last_ctcp = (time_t) 0L [static]

Definition at line 30 of file chan.c.

Referenced by gotmsg().

char last_invchan[300] = "" [static]

Definition at line 33 of file chan.c.

Referenced by gotinvite().

time_t last_invtime = (time_t) 0L [static]

Definition at line 32 of file chan.c.

Referenced by gotinvite().


Generated on 7 Sep 2016 for Eggdrop by  doxygen 1.6.1