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

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

Go to the source code of this file.

Defines

#define PLUS   0x01
#define MINUS   0x02
#define CHOP   0x04
#define BAN   0x08
#define VOICE   0x10
#define EXEMPT   0x20
#define INVITE   0x40
#define CHHOP   0x80

Functions

struct chanset_tmodebind_refresh (char *chname, char *usrhost, struct flag_record *usr, char *vcrhost, struct flag_record *vcr)
static void flush_mode (struct chanset_t *chan, int pri)
static void real_add_mode (struct chanset_t *chan, char plus, char mode, char *op)
static void got_key (struct chanset_t *chan, char *nick, char *from, char *key)
static void got_op (struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu, struct flag_record *opper)
static void got_halfop (struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu, struct flag_record *opper)
static void got_deop (struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu)
static void got_dehalfop (struct chanset_t *chan, char *nick, char *from, char *who, struct userrec *opu)
static void got_ban (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static void got_unban (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static void got_exempt (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static void got_unexempt (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static void got_invite (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static void got_uninvite (struct chanset_t *chan, char *nick, char *from, char *who, char *ch, struct userrec *u)
static int gotmode (char *from, char *origmsg)

Variables

static int reversing = 0
static struct flag_record user = { 0x00000001 | 0x00000004 , 0, 0, 0, 0, 0 }
static struct flag_record victim = { 0x00000001 | 0x00000004 , 0, 0, 0, 0, 0 }

Define Documentation

#define BAN   0x08

Definition at line 34 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define CHHOP   0x80

Definition at line 38 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define CHOP   0x04

Definition at line 33 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define EXEMPT   0x20

Definition at line 36 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define INVITE   0x40

Definition at line 37 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define MINUS   0x02

Definition at line 32 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define PLUS   0x01

Definition at line 31 of file mode.c.

Referenced by flush_mode(), and real_add_mode().

#define VOICE   0x10

Definition at line 35 of file mode.c.

Referenced by real_add_mode().


Function Documentation

static void flush_mode ( struct chanset_t chan,
int  pri 
) [static]

Definition at line 67 of file mode.c.

References BAN, chanset_t::bytes, CHHOP, CHOP, chanset_t::cmode, chanset_t::compat, DP_MODE, DP_SERVER, dprintf, egg_strcatn, EXEMPT, INVITE, chanset_t::key, chanset_t::limit, MINUS, chanset_t::mns, modesperline, chanset_t::name, nfree, NULL, chanset_t::op, chanset_t::pls, PLUS, QUICK, chanset_t::rmkey, and chanset_t::type.

Referenced by real_add_mode().

00068 {
00069   char *p, out[512], post[512];
00070   size_t postsize = sizeof(post);
00071   int i, plus = 2;              /* 0 = '-', 1 = '+', 2 = none */
00072 
00073   p = out;
00074   post[0] = 0, postsize--;
00075 
00076   if (chan->mns[0]) {
00077     *p++ = '-', plus = 0;
00078     for (i = 0; i < strlen(chan->mns); i++)
00079       *p++ = chan->mns[i];
00080     chan->mns[0] = 0;
00081   }
00082 
00083   if (chan->pls[0]) {
00084     *p++ = '+', plus = 1;
00085     for (i = 0; i < strlen(chan->pls); i++)
00086       *p++ = chan->pls[i];
00087     chan->pls[0] = 0;
00088   }
00089 
00090   chan->bytes = 0;
00091   chan->compat = 0;
00092 
00093   /* +k or +l ? */
00094   if (chan->key && !chan->rmkey) {
00095     if (plus != 1) {
00096       *p++ = '+', plus = 1;
00097     }
00098     *p++ = 'k';
00099 
00100     postsize -= egg_strcatn(post, chan->key, sizeof(post));
00101     postsize -= egg_strcatn(post, " ", sizeof(post));
00102 
00103     nfree(chan->key), chan->key = NULL;
00104   }
00105 
00106   /* max +l is signed 2^32 on IRCnet at least... so makesure we've got at least
00107    * a 13 char buffer for '-2147483647 \0'. We'll be overwriting the existing
00108    * terminating null in 'post', so makesure postsize >= 12.
00109    */
00110   if (chan->limit != 0 && postsize >= 12) {
00111     if (plus != 1) {
00112       *p++ = '+', plus = 1;
00113     }
00114     *p++ = 'l';
00115 
00116     /* 'sizeof(post) - 1' is used because we want to overwrite the old null */
00117     postsize -=
00118       sprintf(&post[(sizeof(post) - 1) - postsize], "%d ", chan->limit);
00119 
00120     chan->limit = 0;
00121   }
00122 
00123   /* -k ? */
00124   if (chan->rmkey) {
00125     if (plus) {
00126       *p++ = '-', plus = 0;
00127     }
00128     *p++ = 'k';
00129 
00130     postsize -= egg_strcatn(post, chan->rmkey, sizeof(post));
00131     postsize -= egg_strcatn(post, " ", sizeof(post));
00132 
00133     nfree(chan->rmkey), chan->rmkey = NULL;
00134   }
00135 
00136   /* Do -{b,e,I} before +{b,e,I} to avoid the server ignoring overlaps */
00137   for (i = 0; i < modesperline; i++) {
00138     if ((chan->cmode[i].type & MINUS) && postsize > strlen(chan->cmode[i].op)) {
00139       if (plus) {
00140         *p++ = '-', plus = 0;
00141       }
00142 
00143       *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
00144               ((chan->cmode[i].type & CHOP) ? 'o' :
00145               ((chan->cmode[i].type & CHHOP) ? 'h' :
00146               ((chan->cmode[i].type & EXEMPT) ? 'e' :
00147               ((chan->cmode[i].type & INVITE) ? 'I' : 'v')))));
00148 
00149       postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
00150       postsize -= egg_strcatn(post, " ", sizeof(post));
00151 
00152       nfree(chan->cmode[i].op), chan->cmode[i].op = NULL;
00153       chan->cmode[i].type = 0;
00154     }
00155   }
00156 
00157   /* now do all the + modes... */
00158   for (i = 0; i < modesperline; i++) {
00159     if ((chan->cmode[i].type & PLUS) && postsize > strlen(chan->cmode[i].op)) {
00160       if (plus != 1) {
00161         *p++ = '+', plus = 1;
00162       }
00163 
00164       *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
00165               ((chan->cmode[i].type & CHOP) ? 'o' :
00166               ((chan->cmode[i].type & CHHOP) ? 'h' :
00167               ((chan->cmode[i].type & EXEMPT) ? 'e' :
00168               ((chan->cmode[i].type & INVITE) ? 'I' : 'v')))));
00169 
00170       postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
00171       postsize -= egg_strcatn(post, " ", sizeof(post));
00172 
00173       nfree(chan->cmode[i].op), chan->cmode[i].op = NULL;
00174       chan->cmode[i].type = 0;
00175     }
00176   }
00177 
00178   /* remember to terminate the buffer ('out')... */
00179   *p = 0;
00180 
00181   if (post[0]) {
00182     /* remove the trailing space... */
00183     size_t index = (sizeof(post) - 1) - postsize;
00184 
00185     if (index > 0 && post[index - 1] == ' ')
00186       post[index - 1] = 0;
00187 
00188     egg_strcatn(out, " ", sizeof(out));
00189     egg_strcatn(out, post, sizeof(out));
00190   }
00191   if (out[0]) {
00192     if (pri == QUICK)
00193       dprintf(DP_MODE, "MODE %s %s\n", chan->name, out);
00194     else
00195       dprintf(DP_SERVER, "MODE %s %s\n", chan->name, out);
00196   }
00197 }

Here is the caller graph for this function:

static void got_ban ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 758 of file mode.c.

References add_mode, chanset_t::bans, botname, botuserhost, bounce_bans, bounce_modes, chan_deop, chan_friend, chan_master, chan_op, chanset_t::channel, channel_enforcebans, channel_nouserbans, channel_pending, check_tcl_mode(), maskrec::desc, chanset_t::dname, egg_snprintf, get_user_by_host, get_user_flagrec, glob_bot, glob_friend, glob_master, glob_op, global_bans, HALFOP_CANTDOMODE, IRC_BANNED, IRC_PREBANNED, isexempted, kick_all(), maskrec::mask, match_addr, match_my_nick(), chan_t::member, modebind_refresh(), newban, maskrec::next, memstruct::next, memstruct::nick, NULL, refresh_exempt(), reversing, u_equals_mask(), UHOSTLEN, and memstruct::userhost.

Referenced by gotmode().

00760 {
00761   char me[UHOSTLEN], s[UHOSTLEN], s1[UHOSTLEN];
00762   memberlist *m;
00763   struct userrec *targ;
00764 
00765   egg_snprintf(me, sizeof me, "%s!%s", botname, botuserhost);
00766   egg_snprintf(s, sizeof s, "%s!%s", nick, from);
00767   newban(chan, who, s);
00768   check_tcl_mode(nick, from, u, chan->dname, "+b", who);
00769   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00770     return;
00771 
00772   if (channel_pending(chan) || HALFOP_CANTDOMODE('b'))
00773     return;
00774 
00775   if (match_addr(who, me) && !isexempted(chan, me)) {
00776     add_mode(chan, '-', 'b', who);
00777     reversing = 1;
00778     return;
00779   }
00780   if (!match_my_nick(nick)) {
00781     if (nick[0] && channel_nouserbans(chan) && !glob_bot(user) &&
00782         !glob_master(user) && !chan_master(user)) {
00783       add_mode(chan, '-', 'b', who);
00784       return;
00785     }
00786     for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00787       egg_snprintf(s1, sizeof s1, "%s!%s", m->nick, m->userhost);
00788       if (match_addr(who, s1)) {
00789         targ = get_user_by_host(s1);
00790         if (targ) {
00791           get_user_flagrec(targ, &victim, chan->dname);
00792           if ((glob_friend(victim) || (glob_op(victim) && !chan_deop(victim)) ||
00793                chan_friend(victim) || chan_op(victim)) && !glob_master(user) &&
00794               !glob_bot(user) && !chan_master(user) && !isexempted(chan, s1)) {
00795             add_mode(chan, '-', 'b', who);
00796             return;
00797           }
00798         }
00799       }
00800     }
00801   }
00802   refresh_exempt(chan, who);
00803   if (nick[0] && channel_enforcebans(chan)) {
00804     register maskrec *b;
00805     int cycle;
00806     char resn[512] = "";
00807 
00808     for (cycle = 0; cycle < 2; cycle++) {
00809       for (b = cycle ? chan->bans : global_bans; b; b = b->next) {
00810         if (match_addr(b->mask, who)) {
00811           if (b->desc && b->desc[0] != '@')
00812             egg_snprintf(resn, sizeof resn, "%s %s", IRC_PREBANNED, b->desc);
00813           else
00814             resn[0] = 0;
00815         }
00816       }
00817     }
00818     kick_all(chan, who, resn[0] ? resn : IRC_BANNED,
00819              match_my_nick(nick) ? 0 : 1);
00820   }
00821   if (!nick[0] && (bounce_bans || bounce_modes) &&
00822       (!u_equals_mask(global_bans, who) || !u_equals_mask(chan->bans, who)))
00823     add_mode(chan, '-', 'b', who);
00824 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_dehalfop ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
struct userrec opu 
) [static]

Definition at line 688 of file mode.c.

References add_mode, CHAN_BADCHANMODE, chan_dehalfop, chan_friend, chan_halfop, chan_hasop, chan_master, CHAN_PEND, CHANHALFOP, channel_bitch, channel_pending, channel_protectfriends, channel_protecthalfops, CHANVOICE, check_tcl_mode(), chanset_t::dname, FAKEHALFOP, memstruct::flags, get_user_by_host, get_user_flagrec, glob_bot, glob_dehalfop, glob_friend, glob_halfop, glob_master, HALFOP_CANDOMODE, ismember, LOG_MISC, LOG_MODES, match_my_nick(), modebind_refresh(), chanset_t::name, memstruct::nick, putlog, refresh_who_chan(), reversing, rfc_casecmp, SENTDEHALFOP, simple_sprintf, chanset_t::status, STOPWHO, UHOSTLEN, memstruct::userhost, and WASHALFOP.

Referenced by gotmode().

00690 {
00691   memberlist *m;
00692   char ch[sizeof chan->name];
00693   char s[UHOSTLEN], s1[UHOSTLEN];
00694   struct userrec *u;
00695   int had_halfop;
00696 
00697   m = ismember(chan, who);
00698   if (!m) {
00699     if (channel_pending(chan))
00700       return;
00701     putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
00702     chan->status |= CHAN_PEND;
00703     refresh_who_chan(chan->name);
00704     return;
00705   }
00706 
00707   strcpy(ch, chan->name);
00708   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
00709   simple_sprintf(s1, "%s!%s", nick, from);
00710   u = get_user_by_host(s);
00711   get_user_flagrec(u, &victim, chan->dname);
00712 
00713   had_halfop = chan_hasop(m);
00714   /* Flags need to be set correctly right from the beginning now, so that
00715    * add_mode() doesn't get irritated.
00716    */
00717   m->flags &= ~(CHANHALFOP | SENTDEHALFOP | FAKEHALFOP);
00718   check_tcl_mode(nick, from, opu, chan->dname, "-h", who);
00719   if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
00720       !(m = ismember(chan, who)))
00721     return;
00722   /* Check comments in got_op()  (drummer) */
00723   m->flags &= ~WASHALFOP;
00724 
00725   if (channel_pending(chan))
00726     return;
00727 
00728   /* Dehalfop'd someone on my oplist? */
00729   if (HALFOP_CANDOMODE('h')) {
00730     int ok = 1;
00731 
00732     if (!glob_dehalfop(victim) && !chan_dehalfop(victim)) {
00733       if (channel_protecthalfops(chan) && (glob_master(victim) ||
00734           chan_master(victim) || glob_halfop(victim) || chan_halfop(victim)))
00735         ok = 0;
00736       else if (channel_protectfriends(chan) && (glob_friend(victim) ||
00737                chan_friend(victim)))
00738         ok = 0;
00739     }
00740     if ((reversing || !ok) && had_halfop && !match_my_nick(nick) &&
00741         rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) &&
00742         !chan_master(user) && !glob_bot(user) && ((chan_halfop(victim) ||
00743         (glob_halfop(victim) && !chan_dehalfop(victim))) ||
00744         !channel_bitch(chan)))
00745       add_mode(chan, '+', 'h', who);
00746   }
00747 
00748   if (!nick[0])
00749     putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s",
00750            chan->dname, who, from);
00751   if (!(m->flags & (CHANVOICE | STOPWHO))) {
00752     chan->status |= CHAN_PEND;
00753     refresh_who_chan(chan->name);
00754     m->flags |= STOPWHO;
00755   }
00756 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_deop ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
struct userrec opu 
) [static]

Definition at line 595 of file mode.c.

References add_mode, CHAN_BADCHANMODE, chan_deop, chan_friend, chan_hasop, chan_master, chan_op, CHAN_PEND, CHANHALFOP, chanset_t::channel, channel_bitch, channel_pending, channel_protectfriends, channel_protectops, CHANOP, CHANVOICE, check_tcl_mode(), check_tcl_need(), detect_chan_flood(), chanset_t::dname, do_tcl, FAKEOP, memstruct::flags, FLOOD_DEOP, get_user_by_host, get_user_flagrec, glob_bot, glob_deop, glob_friend, glob_master, glob_op, HALFOP_CANDOMODE, ismember, LOG_MISC, LOG_MODES, match_my_nick(), maybe_revenge(), chan_t::member, modebind_refresh(), chanset_t::name, chanset_t::need_op, memstruct::next, memstruct::nick, putlog, refresh_who_chan(), REVENGE_DEOP, reversing, rfc_casecmp, SENTDEOP, SENTDEVOICE, SENTKICK, SENTOP, SENTVOICE, simple_sprintf, chanset_t::status, STOPWHO, UHOSTLEN, memstruct::userhost, and WASOP.

Referenced by gotmode().

00597 {
00598   memberlist *m;
00599   char ch[sizeof chan->name];
00600   char s[UHOSTLEN], s1[UHOSTLEN];
00601   struct userrec *u;
00602   int had_halfop;
00603 
00604   m = ismember(chan, who);
00605   if (!m) {
00606     if (channel_pending(chan))
00607       return;
00608     putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
00609     chan->status |= CHAN_PEND;
00610     refresh_who_chan(chan->name);
00611     return;
00612   }
00613 
00614   strcpy(ch, chan->name);
00615   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
00616   simple_sprintf(s1, "%s!%s", nick, from);
00617   u = get_user_by_host(s);
00618   get_user_flagrec(u, &victim, chan->dname);
00619 
00620   had_halfop = chan_hasop(m);
00621   /* Flags need to be set correctly right from the beginning now, so that
00622    * add_mode() doesn't get irritated.
00623    */
00624   m->flags &= ~(CHANOP | SENTDEOP | FAKEOP);
00625   check_tcl_mode(nick, from, opu, chan->dname, "-o", who);
00626   if (!(chan = modebind_refresh(ch, from, &user, s, &victim)) ||
00627       !(m = ismember(chan, who)))
00628     return;
00629   m->flags &= ~WASOP;
00630 
00631   if (channel_pending(chan))
00632     return;
00633 
00634   if (HALFOP_CANDOMODE('o')) {
00635     int ok = 1;
00636 
00637     if (!glob_deop(victim) && !chan_deop(victim)) {
00638       if (channel_protectops(chan) && (glob_master(victim) ||
00639           chan_master(victim) || glob_op(victim) || chan_op(victim)))
00640         ok = 0;
00641       else if (channel_protectfriends(chan) && (glob_friend(victim) ||
00642                chan_friend(victim)))
00643         ok = 0;
00644     }
00645     if ((reversing || !ok) && had_halfop && !match_my_nick(nick) &&
00646         rfc_casecmp(who, nick) && !match_my_nick(who) && !glob_master(user) &&
00647         !chan_master(user) && !glob_bot(user) && ((chan_op(victim) ||
00648         (glob_op(victim) && !chan_deop(victim))) || !channel_bitch(chan)))
00649       add_mode(chan, '+', 'o', who);
00650   }
00651 
00652   if (!nick[0])
00653     putlog(LOG_MODES, chan->dname, "TS resync (%s): %s deopped by %s",
00654            chan->dname, who, from);
00655 
00656   /* Check for mass deop */
00657   if (nick[0])
00658     detect_chan_flood(nick, from, s1, chan, FLOOD_DEOP, who);
00659 
00660   /* Having op hides your +v and +h status -- so now that someone's lost ops,
00661    * check to see if they have +v or +h
00662    */
00663   if (!(m->flags & (CHANVOICE | CHANHALFOP | STOPWHO))) {
00664     chan->status |= CHAN_PEND;
00665     refresh_who_chan(chan->name);
00666     m->flags |= STOPWHO;
00667   }
00668 
00669   /* Was the bot deopped? */
00670   if (match_my_nick(who)) {
00671     /* Cancel any pending kicks and modes */
00672     memberlist *m2;
00673 
00674     for (m2 = chan->channel.member; m2 && m2->nick[0]; m2 = m2->next)
00675       m2->flags &= ~(SENTKICK | SENTDEOP | SENTOP | SENTVOICE | SENTDEVOICE);
00676 
00677     check_tcl_need(chan->dname, "op");
00678     if (chan->need_op[0])
00679       do_tcl("need-op", chan->need_op);
00680     if (!nick[0])
00681       putlog(LOG_MODES, chan->dname, "TS resync deopped me on %s :(",
00682              chan->dname);
00683   }
00684   if (nick[0])
00685     maybe_revenge(chan, s1, s, REVENGE_DEOP);
00686 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_exempt ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 859 of file mode.c.

References add_mode, bounce_exempts, bounce_modes, chan_master, channel_nouserexempts, channel_pending, check_tcl_mode(), chanset_t::dname, chanset_t::exempts, glob_bot, glob_master, global_exempts, HALFOP_CANTDOMODE, match_my_nick(), modebind_refresh(), newexempt, NULL, reversing, simple_sprintf, u_equals_mask(), and UHOSTLEN.

Referenced by gotmode().

00861 {
00862   char s[UHOSTLEN];
00863 
00864   simple_sprintf(s, "%s!%s", nick, from);
00865   newexempt(chan, who, s);
00866   check_tcl_mode(nick, from, u, chan->dname, "+e", who);
00867   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00868     return;
00869 
00870   if (channel_pending(chan) || HALFOP_CANTDOMODE('e'))
00871     return;
00872 
00873   if (!match_my_nick(nick)) {
00874     if (nick[0] && channel_nouserexempts(chan) && !glob_bot(user) &&
00875         !glob_master(user) && !chan_master(user)) {
00876       add_mode(chan, '-', 'e', who);
00877       return;
00878     }
00879     if (!nick[0] && bounce_modes)
00880       reversing = 1;
00881   }
00882   if (reversing || (bounce_exempts && !nick[0] &&
00883       (!u_equals_mask(global_exempts, who) ||
00884       !u_equals_mask(chan->exempts, who))))
00885     add_mode(chan, '-', 'e', who);
00886 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_halfop ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
struct userrec opu,
struct flag_record opper 
) [static]

Definition at line 498 of file mode.c.

References add_mode, chan_autohalfop, CHAN_BADCHANMODE, chan_dehalfop, chan_exempt, chan_halfop, chan_master, chan_op, CHAN_PEND, chan_washalfop, chan_washalfoptest, CHANHALFOP, channel_autohalfop, channel_bitch, channel_pending, check_tcl_mode(), chanset_t::dname, FAKEHALFOP, memstruct::flags, get_user_by_host, get_user_flagrec, glob_autohalfop, glob_bot, glob_dehalfop, glob_exempt, glob_halfop, glob_master, glob_op, glob_washalfoptest, HALFOP_CANDOMODE, ismember, LOG_MISC, match_my_nick(), me_halfop(), me_op(), modebind_refresh(), chanset_t::name, memstruct::nick, putlog, recheck_channel(), refresh_who_chan(), reversing, SENTHALFOP, simple_sprintf, chanset_t::status, chanset_t::stopnethack_mode, UHOSTLEN, memstruct::user, memstruct::userhost, and WASHALFOP.

Referenced by gotmode().

00501 {
00502   memberlist *m;
00503   char s[UHOSTLEN];
00504   char ch[sizeof chan->name];
00505   struct userrec *u;
00506   int check_chan = 0;
00507   int snm = chan->stopnethack_mode;
00508 
00509   m = ismember(chan, who);
00510   if (!m) {
00511     if (channel_pending(chan))
00512       return;
00513     putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
00514     chan->status |= CHAN_PEND;
00515     refresh_who_chan(chan->name);
00516     return;
00517   }
00518 
00519   /* Did *I* just get halfopped? */
00520   if (!me_op(chan) && !me_halfop(chan) && match_my_nick(who))
00521     check_chan = 1;
00522 
00523   strcpy(ch, chan->name);
00524   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
00525   if (!m->user)
00526     u = get_user_by_host(s);
00527   else
00528     u = m->user;
00529 
00530   get_user_flagrec(u, &victim, chan->dname);
00531   /* Flags need to be set correctly right from the beginning now, so that
00532    * add_mode() doesn't get irritated.
00533    */
00534   m->flags |= CHANHALFOP;
00535   check_tcl_mode(nick, from, opu, chan->dname, "+h", who);
00536   if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) ||
00537       !(m = ismember(chan, who)))
00538     return;
00539   m->flags &= ~SENTHALFOP;
00540 
00541   if (channel_pending(chan))
00542     return;
00543 
00544   if (nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who) &&
00545       !match_my_nick(nick)) {
00546     if (channel_bitch(chan) && !(glob_master(*opper) || glob_bot(*opper)) &&
00547         !chan_master(*opper) && !(glob_halfop(victim) || glob_op(victim) ||
00548         glob_bot(victim)) && !chan_op(victim) && !chan_halfop(victim))
00549       add_mode(chan, '-', 'h', who);
00550     else if ((chan_dehalfop(victim) || (glob_dehalfop(victim) &&
00551              !chan_halfop(victim))) && !glob_master(*opper) &&
00552              !chan_master(*opper))
00553       add_mode(chan, '-', 'h', who);
00554     else if (reversing)
00555       add_mode(chan, '-', 'h', who);
00556   } else if (reversing && HALFOP_CANDOMODE('h') && !match_my_nick(who) &&
00557              !match_my_nick(nick))
00558     add_mode(chan, '-', 'h', who);
00559   if (!nick[0] && HALFOP_CANDOMODE('h') && !match_my_nick(who)) {
00560     if (chan_dehalfop(victim) || (glob_dehalfop(victim) &&
00561         !chan_halfop(victim))) {
00562       m->flags |= FAKEHALFOP;
00563       add_mode(chan, '-', 'h', who);
00564     } else if (snm > 0 && snm < 7 && !((channel_autohalfop(chan) ||
00565              glob_autohalfop(victim) || chan_autohalfop(victim)) &&
00566              (chan_halfop(victim) || (glob_halfop(victim) &&
00567              !chan_dehalfop(victim)))) && !glob_exempt(victim) &&
00568              !chan_exempt(victim)) {
00569       if (snm == 5)
00570         snm = channel_bitch(chan) ? 1 : 3;
00571       if (snm == 6)
00572         snm = channel_bitch(chan) ? 4 : 2;
00573       if (chan_washalfoptest(victim) || glob_washalfoptest(victim) || snm == 2) {
00574         if (!chan_washalfop(m)) {
00575           m->flags |= FAKEHALFOP;
00576           add_mode(chan, '-', 'h', who);
00577         }
00578       } else if (!(chan_halfop(victim) || (glob_halfop(victim) &&
00579                !chan_dehalfop(victim)))) {
00580         if (snm == 1 || snm == 4 || (snm == 3 && !chan_washalfop(m))) {
00581           add_mode(chan, '-', 'h', who);
00582           m->flags |= FAKEHALFOP;
00583         }
00584       } else if (snm == 4 && !chan_washalfop(m)) {
00585         add_mode(chan, '-', 'h', who);
00586         m->flags |= FAKEHALFOP;
00587       }
00588     }
00589   }
00590   m->flags |= WASHALFOP;
00591   if (check_chan)
00592     recheck_channel(chan, 1);
00593 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_invite ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 936 of file mode.c.

References add_mode, bounce_invites, bounce_modes, chan_master, channel_nouserinvites, channel_pending, check_tcl_mode(), chanset_t::dname, glob_bot, glob_master, global_invites, HALFOP_CANTDOMODE, chanset_t::invites, match_my_nick(), modebind_refresh(), newinvite, NULL, reversing, simple_sprintf, u_equals_mask(), and UHOSTLEN.

Referenced by gotmode().

00938 {
00939   char s[UHOSTLEN];
00940 
00941   simple_sprintf(s, "%s!%s", nick, from);
00942   newinvite(chan, who, s);
00943   check_tcl_mode(nick, from, u, chan->dname, "+I", who);
00944   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00945     return;
00946 
00947   if (channel_pending(chan) || HALFOP_CANTDOMODE('I'))
00948     return;
00949 
00950   if (!match_my_nick(nick)) {
00951     if (nick[0] && channel_nouserinvites(chan) && !glob_bot(user) &&
00952         !glob_master(user) && !chan_master(user)) {
00953       add_mode(chan, '-', 'I', who);
00954       return;
00955     }
00956     if ((!nick[0]) && (bounce_modes))
00957       reversing = 1;
00958   }
00959   if (reversing || (bounce_invites && (!nick[0]) &&
00960       (!u_equals_mask(global_invites, who) ||
00961       !u_equals_mask(chan->invites, who))))
00962     add_mode(chan, '-', 'I', who);
00963 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_key ( struct chanset_t chan,
char *  nick,
char *  from,
char *  key 
) [static]

Definition at line 382 of file mode.c.

References add_mode, bounce_modes, chan_master, CHANKEY, glob_bot, glob_master, chanset_t::key_prot, match_my_nick(), chanset_t::mode_mns_prot, chanset_t::mode_pls_prot, and reversing.

Referenced by gotmode().

00383 {
00384   if (!nick[0] && bounce_modes)
00385     reversing = 1;
00386 
00387   if (!(glob_master(user) || glob_bot(user) || chan_master(user)) &&
00388       !match_my_nick(nick)) {
00389     if ((reversing && !chan->key_prot[0]) || (chan->mode_mns_prot & CHANKEY)) {
00390       if (strlen(key) != 0)
00391         add_mode(chan, '-', 'k', key);
00392       else
00393         add_mode(chan, '-', 'k', "");
00394     }
00395     if ((chan->mode_pls_prot & CHANKEY) && (chan->key_prot[0] != 0) &&
00396         strcmp(key, chan->key_prot)) {
00397       add_mode(chan, '+', 'k', chan->key_prot);
00398     }
00399   }
00400 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_op ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
struct userrec opu,
struct flag_record opper 
) [static]

Definition at line 402 of file mode.c.

References add_mode, chan_autoop, CHAN_BADCHANMODE, chan_deop, chan_exempt, chan_master, chan_op, CHAN_PEND, chan_wasop, chan_wasoptest, channel_autoop, channel_bitch, channel_pending, CHANOP, check_tcl_mode(), chanset_t::dname, FAKEOP, memstruct::flags, get_user_by_host, get_user_flagrec, glob_autoop, glob_bot, glob_deop, glob_exempt, glob_master, glob_op, glob_wasoptest, HALFOP_CANDOMODE, ismember, LOG_MISC, match_my_nick(), me_op(), modebind_refresh(), chanset_t::name, memstruct::nick, putlog, recheck_channel(), refresh_who_chan(), reversing, SENTOP, simple_sprintf, chanset_t::status, chanset_t::stopnethack_mode, UHOSTLEN, memstruct::user, memstruct::userhost, and WASOP.

Referenced by gotmode().

00404 {
00405   memberlist *m;
00406   char ch[sizeof chan->name];
00407   char s[UHOSTLEN];
00408   struct userrec *u;
00409   int check_chan = 0, snm = chan->stopnethack_mode;
00410 
00411   m = ismember(chan, who);
00412   if (!m) {
00413     if (channel_pending(chan))
00414       return;
00415     putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, who);
00416     chan->status |= CHAN_PEND;
00417     refresh_who_chan(chan->name);
00418     return;
00419   }
00420 
00421   /* Did *I* just get opped? */
00422   if (!me_op(chan) && match_my_nick(who))
00423     check_chan = 1;
00424 
00425   strcpy(ch, chan->name);
00426   simple_sprintf(s, "%s!%s", m->nick, m->userhost);
00427   if (!m->user)
00428     u = get_user_by_host(s);
00429   else
00430     u = m->user;
00431 
00432   get_user_flagrec(u, &victim, chan->dname);
00433   /* Flags need to be set correctly right from the beginning now, so that
00434    * add_mode() doesn't get irritated.
00435    */
00436   m->flags |= CHANOP;
00437   check_tcl_mode(nick, from, opu, chan->dname, "+o", who);
00438   if (!(chan = modebind_refresh(ch, from, opper, s, &victim)) ||
00439       !(m = ismember(chan, who)))
00440     return;
00441   /* Added new meaning of WASOP:
00442    * In mode binds it means: was the user an op before got (de)opped. A script
00443    * now can use [wasop nick chan] to check if user was op or wasnt.
00444    * (drummer)
00445    */
00446   m->flags &= ~SENTOP;
00447 
00448   if (channel_pending(chan))
00449     return;
00450 
00451   if (nick[0] && HALFOP_CANDOMODE('o') && !match_my_nick(who) &&
00452       !match_my_nick(nick)) {
00453     if (channel_bitch(chan) && !(glob_master(*opper) || glob_bot(*opper)) &&
00454         !chan_master(*opper) && !(glob_op(victim) || glob_bot(victim)) &&
00455         !chan_op(victim))
00456       add_mode(chan, '-', 'o', who);
00457     else if ((chan_deop(victim) || (glob_deop(victim) && !chan_op(victim))) &&
00458              !glob_master(*opper) && !chan_master(*opper))
00459       add_mode(chan, '-', 'o', who);
00460     else if (reversing)
00461       add_mode(chan, '-', 'o', who);
00462   } else if (reversing && HALFOP_CANDOMODE('o') && !match_my_nick(who) &&
00463              !match_my_nick(nick))
00464     add_mode(chan, '-', 'o', who);
00465   if (!nick[0] && HALFOP_CANDOMODE('o') && !match_my_nick(who)) {
00466     if (chan_deop(victim) || (glob_deop(victim) && !chan_op(victim))) {
00467       m->flags |= FAKEOP;
00468       add_mode(chan, '-', 'o', who);
00469     } else if (snm > 0 && snm < 7 && !((channel_autoop(chan) ||
00470              glob_autoop(victim) || chan_autoop(victim)) && (chan_op(victim) ||
00471              (glob_op(victim) && !chan_deop(victim)))) &&
00472              !glob_exempt(victim) && !chan_exempt(victim)) {
00473       if (snm == 5)
00474         snm = channel_bitch(chan) ? 1 : 3;
00475       if (snm == 6)
00476         snm = channel_bitch(chan) ? 4 : 2;
00477       if (chan_wasoptest(victim) || glob_wasoptest(victim) || snm == 2) {
00478         if (!chan_wasop(m)) {
00479           m->flags |= FAKEOP;
00480           add_mode(chan, '-', 'o', who);
00481         }
00482       } else if (!(chan_op(victim) || (glob_op(victim) && !chan_deop(victim)))) {
00483         if (snm == 1 || snm == 4 || (snm == 3 && !chan_wasop(m))) {
00484           add_mode(chan, '-', 'o', who);
00485           m->flags |= FAKEOP;
00486         }
00487       } else if (snm == 4 && !chan_wasop(m)) {
00488         add_mode(chan, '-', 'o', who);
00489         m->flags |= FAKEOP;
00490       }
00491     }
00492   }
00493   m->flags |= WASOP;
00494   if (check_chan)
00495     recheck_channel(chan, 1);
00496 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_unban ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 826 of file mode.c.

References add_mode, chan_t::ban, chanset_t::bans, bot_flags, BOT_SHARE, chan_dehalfop, chan_deop, chan_halfop, chan_op, chanset_t::channel, channel_dynamicbans, channel_pending, check_tcl_mode(), chanset_t::dname, glob_bot, glob_halfop, glob_op, global_bans, maskstruct::mask, modebind_refresh(), maskstruct::next, nfree, NULL, rfc_casecmp, u_equals_mask(), u_sticky_mask(), and maskstruct::who.

Referenced by gotmode().

00828 {
00829   masklist *b, *old;
00830 
00831   old = NULL;
00832   for (b = chan->channel.ban; b->mask[0] && rfc_casecmp(b->mask, who);
00833        old = b, b = b->next);
00834   if (b->mask[0]) {
00835     if (old)
00836       old->next = b->next;
00837     else
00838       chan->channel.ban = b->next;
00839     nfree(b->mask);
00840     nfree(b->who);
00841     nfree(b);
00842   }
00843   check_tcl_mode(nick, from, u, chan->dname, "-b", who);
00844   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00845     return;
00846 
00847   if (channel_pending(chan))
00848     return;
00849 
00850   if ((u_sticky_mask(chan->bans, who) || u_sticky_mask(global_bans, who)) ||
00851       ((u_equals_mask(global_bans, who) || u_equals_mask(chan->bans, who)) &&
00852       !channel_dynamicbans(chan) && ((!glob_bot(user) ||
00853       !(bot_flags(u) & BOT_SHARE)) && ((!glob_op(user) || chan_deop(user)) &&
00854       !chan_op(user)) && ((!glob_halfop(user) || chan_dehalfop(user)) &&
00855       !chan_halfop(user)))))
00856     add_mode(chan, '+', 'b', who);
00857 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_unexempt ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 888 of file mode.c.

References add_mode, chan_t::ban, bot_flags, BOT_SHARE, chan_master, chanset_t::channel, channel_dynamicexempts, channel_pending, check_tcl_mode(), chanset_t::dname, e, chan_t::exempt, chanset_t::exempts, glob_bot, glob_master, global_exempts, maskstruct::mask, mask_match, me_op(), modebind_refresh(), maskstruct::next, nfree, NULL, rfc_casecmp, u_equals_mask(), u_sticky_mask(), and maskstruct::who.

Referenced by gotmode().

00890 {
00891   masklist *e = chan->channel.exempt, *old = NULL;
00892   masklist *b;
00893   int match = 0;
00894 
00895   while (e && e->mask[0] && rfc_casecmp(e->mask, who)) {
00896     old = e;
00897     e = e->next;
00898   }
00899   if (e && e->mask[0]) {
00900     if (old)
00901       old->next = e->next;
00902     else
00903       chan->channel.exempt = e->next;
00904     nfree(e->mask);
00905     nfree(e->who);
00906     nfree(e);
00907   }
00908   check_tcl_mode(nick, from, u, chan->dname, "-e", who);
00909   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00910     return;
00911 
00912   if (channel_pending(chan))
00913     return;
00914 
00915   if (u_sticky_mask(chan->exempts, who) || u_sticky_mask(global_exempts, who))
00916     add_mode(chan, '+', 'e', who);
00917 
00918   /* If exempt was removed by master then leave it else check for bans */
00919   if (!nick[0] && glob_bot(user) && !glob_master(user) && !chan_master(user)) {
00920     b = chan->channel.ban;
00921     while (b->mask[0] && !match) {
00922       if (mask_match(b->mask, who)) {
00923         add_mode(chan, '+', 'e', who);
00924         match = 1;
00925       } else
00926         b = b->next;
00927     }
00928   }
00929   if ((u_equals_mask(global_exempts, who) ||
00930       u_equals_mask(chan->exempts, who)) && me_op(chan) &&
00931       !channel_dynamicexempts(chan) && (!glob_bot(user) ||
00932       !(bot_flags(u) & BOT_SHARE)))
00933     add_mode(chan, '+', 'e', who);
00934 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void got_uninvite ( struct chanset_t chan,
char *  nick,
char *  from,
char *  who,
char *  ch,
struct userrec u 
) [static]

Definition at line 965 of file mode.c.

References add_mode, bot_flags, BOT_SHARE, chan_master, CHANINV, chanset_t::channel, channel_dynamicinvites, channel_pending, check_tcl_mode(), chanset_t::dname, glob_bot, glob_master, global_invites, chan_t::invite, chanset_t::invites, maskstruct::mask, me_op(), chan_t::mode, modebind_refresh(), maskstruct::next, nfree, NULL, rfc_casecmp, u_equals_mask(), u_sticky_mask(), and maskstruct::who.

Referenced by gotmode().

00967 {
00968   masklist *inv = chan->channel.invite, *old = NULL;
00969 
00970   while (inv->mask[0] && rfc_casecmp(inv->mask, who)) {
00971     old = inv;
00972     inv = inv->next;
00973   }
00974   if (inv->mask[0]) {
00975     if (old)
00976       old->next = inv->next;
00977     else
00978       chan->channel.invite = inv->next;
00979     nfree(inv->mask);
00980     nfree(inv->who);
00981     nfree(inv);
00982   }
00983   check_tcl_mode(nick, from, u, chan->dname, "-I", who);
00984   if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
00985     return;
00986 
00987   if (channel_pending(chan))
00988     return;
00989 
00990   if (u_sticky_mask(chan->invites, who) || u_sticky_mask(global_invites, who))
00991     add_mode(chan, '+', 'I', who);
00992   if (!nick[0] && glob_bot(user) && !glob_master(user) && !chan_master(user) &&
00993       (chan->channel.mode & CHANINV))
00994     add_mode(chan, '+', 'I', who);
00995   if ((u_equals_mask(global_invites, who) ||
00996       u_equals_mask(chan->invites, who)) && me_op(chan) &&
00997       !channel_dynamicinvites(chan) && (!glob_bot(user) ||
00998       !(bot_flags(u) & BOT_SHARE)))
00999     add_mode(chan, '+', 'I', who);
01000 }

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1002 of file mode.c.

References add_mode, bounce_modes, CHAN_ASKEDMODES, CHAN_BADCHANMODE, chan_deop, CHAN_DESYNCMODE, CHAN_DESYNCMODE_KICK, chan_fakehalfop, CHAN_FAKEMODE, CHAN_FAKEMODE_KICK, chan_fakeop, CHAN_FORCEJOIN, chan_friend, chan_gvoice, chan_hashalfop, chan_hasop, chan_master, chan_op, CHAN_PEND, chan_quiet, chan_voice, CHANANON, CHANDELJN, CHANINV, CHANINVIS, CHANKEY, CHANLIMIT, CHANLONLY, CHANMETA, CHANMODER, CHANMODREG, chanset_t::channel, channel_active, channel_autovoice, channel_dontkickops, channel_nodesynch, channel_pending, CHANNOAMSG, CHANNOCLR, CHANNOCTCP, CHANNOMSG, CHANNONOTC, CHANPRIV, CHANQUIET, CHANREGON, CHANSEC, CHANSTRIP, CHANTOPIC, CHANVOICE, check_tcl_mode(), chanset_t::dname, DP_MODE, DP_SERVER, dprintf, findchan, fixcolon, memstruct::flags, get_user_by_host, get_user_flagrec, glob_friend, glob_gvoice, glob_master, glob_op, glob_quiet, glob_voice, got_ban(), got_dehalfop(), got_deop(), got_exempt(), got_halfop(), got_invite(), got_key(), got_op(), got_unban(), got_unexempt(), got_uninvite(), int_to_base10, ismember, chan_t::key, chanset_t::key_prot, memstruct::last, chanset_t::limit_prot, LOG_MISC, LOG_MODES, match_my_nick(), chan_t::maxmembers, me_halfop(), me_op(), chan_t::mode, chanset_t::mode_mns_prot, chanset_t::mode_pls_prot, modebind_refresh(), chanset_t::name, newsplit, memstruct::nick, now, NULL, putlog, refresh_who_chan(), reversing, SENTDEVOICE, SENTKICK, SENTVOICE, set_key(), simple_sprintf, splitnick, chanset_t::status, UHOSTLEN, memstruct::user, and memstruct::userhost.

01003 {
01004   char *nick, *ch, *op, *chg, *msg;
01005   char s[UHOSTLEN], buf[511];
01006   char ms2[3];
01007   int z;
01008   struct userrec *u;
01009   memberlist *m;
01010   struct chanset_t *chan;
01011 
01012   strncpy(buf, origmsg, 510);
01013   buf[510] = 0;
01014   msg = buf;
01015   /* Usermode changes? */
01016   if (msg[0] && (strchr(CHANMETA, msg[0]) != NULL)) {
01017     ch = newsplit(&msg);
01018     chg = newsplit(&msg);
01019     reversing = 0;
01020     chan = findchan(ch);
01021     if (!chan) {
01022       putlog(LOG_MISC, "*", CHAN_FORCEJOIN, ch);
01023       dprintf(DP_SERVER, "PART %s\n", ch);
01024     } else if (channel_active(chan) || channel_pending(chan)) {
01025       z = strlen(msg);
01026       if (msg[--z] == ' ')      /* I hate cosmetic bugs :P -poptix */
01027         msg[z] = 0;
01028       putlog(LOG_MODES, chan->dname, "%s: mode change '%s %s' by %s", ch, chg,
01029              msg, from);
01030       u = get_user_by_host(from);
01031       get_user_flagrec(u, &user, ch);
01032       nick = splitnick(&from);
01033       m = ismember(chan, nick);
01034       if (m)
01035         m->last = now;
01036       if (m && channel_active(chan) && (me_op(chan) || (me_halfop(chan) &&
01037           !chan_hasop(m))) && !(glob_friend(user) || chan_friend(user) ||
01038           (channel_dontkickops(chan) && (chan_op(user) || (glob_op(user) &&
01039           !chan_deop(user))))) && !match_my_nick(nick)) {
01040         if (chan_fakeop(m) || chan_fakehalfop(m)) {
01041           putlog(LOG_MODES, ch, CHAN_FAKEMODE, ch);
01042           dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_FAKEMODE_KICK);
01043           m->flags |= SENTKICK;
01044           reversing = 1;
01045         } else if (!chan_hasop(m) && !chan_hashalfop(m) &&
01046                  !channel_nodesynch(chan)) {
01047           putlog(LOG_MODES, ch, CHAN_DESYNCMODE, ch);
01048           dprintf(DP_MODE, "KICK %s %s :%s\n", ch, nick, CHAN_DESYNCMODE_KICK);
01049           m->flags |= SENTKICK;
01050           reversing = 1;
01051         }
01052       }
01053       ms2[0] = '+';
01054       ms2[2] = 0;
01055       while ((ms2[1] = *chg)) {
01056         int todo = 0;
01057 
01058         switch (*chg) {
01059         case '+':
01060           ms2[0] = '+';
01061           break;
01062         case '-':
01063           ms2[0] = '-';
01064           break;
01065         case 'i':
01066           todo = CHANINV;
01067           if (!nick[0] && bounce_modes)
01068             reversing = 1;
01069           break;
01070         case 'p':
01071           todo = CHANPRIV;
01072           if (!nick[0] && bounce_modes)
01073             reversing = 1;
01074           break;
01075         case 's':
01076           todo = CHANSEC;
01077           if (!nick[0] && bounce_modes)
01078             reversing = 1;
01079           break;
01080         case 'm':
01081           todo = CHANMODER;
01082           if (!nick[0] && bounce_modes)
01083             reversing = 1;
01084           break;
01085         case 'c':
01086           todo = CHANNOCLR;
01087           if (!nick[0] && bounce_modes)
01088             reversing = 1;
01089           break;
01090         case 'C':
01091           todo = CHANNOCTCP;
01092           if (!nick[0] && bounce_modes)
01093             reversing = 1;
01094           break;
01095         case 'R':
01096           todo = CHANREGON;
01097           if (!nick[0] && bounce_modes)
01098             reversing = 1;
01099           break;
01100         case 'M':
01101           todo = CHANMODREG;
01102           if (!nick[0] && bounce_modes)
01103             reversing = 1;
01104           break;
01105         case 'r':
01106           todo = CHANLONLY;
01107           if (!nick[0] && bounce_modes)
01108             reversing = 1;
01109           break;
01110         case 'D':
01111           todo = CHANDELJN;
01112           if (!nick[0] && bounce_modes)
01113             reversing = 1;
01114           break;
01115         case 'u':
01116           todo = CHANSTRIP;
01117           if (!nick[0] && bounce_modes)
01118             reversing = 1;
01119           break;
01120         case 'N':
01121           todo = CHANNONOTC;
01122           if (!nick[0] && bounce_modes)
01123             reversing = 1;
01124           break;
01125         case 'T':
01126           todo = CHANNOAMSG;
01127           if (!nick[0] && bounce_modes)
01128             reversing = 1;
01129           break;
01130         case 'd':
01131           todo = CHANINVIS;
01132           break;
01133         case 't':
01134           todo = CHANTOPIC;
01135           if (!nick[0] && bounce_modes)
01136             reversing = 1;
01137           break;
01138         case 'n':
01139           todo = CHANNOMSG;
01140           if (!nick[0] && bounce_modes)
01141             reversing = 1;
01142           break;
01143         case 'a':
01144           todo = CHANANON;
01145           if (!nick[0] && bounce_modes)
01146             reversing = 1;
01147           break;
01148         case 'q':
01149           todo = CHANQUIET;
01150           if (!nick[0] && bounce_modes)
01151             reversing = 1;
01152           break;
01153         case 'l':
01154           if (!nick[0] && bounce_modes)
01155             reversing = 1;
01156           if (ms2[0] == '-') {
01157             check_tcl_mode(nick, from, u, chan->dname, ms2, "");
01158             /* The Tcl proc might have modified/removed the chan or user */
01159             if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
01160               return 0;
01161             if (channel_active(chan)) {
01162               if (reversing && (chan->channel.maxmembers != 0)) {
01163                 simple_sprintf(s, "%d", chan->channel.maxmembers);
01164                 add_mode(chan, '+', 'l', s);
01165               } else if ((chan->limit_prot != 0) && !glob_master(user) &&
01166                          !chan_master(user) && !match_my_nick(nick)) {
01167                 simple_sprintf(s, "%d", chan->limit_prot);
01168                 add_mode(chan, '+', 'l', s);
01169               }
01170             }
01171             chan->channel.maxmembers = 0;
01172           } else {
01173             op = newsplit(&msg);
01174             fixcolon(op);
01175             if (op == '\0')
01176               break;
01177             chan->channel.maxmembers = atoi(op);
01178             check_tcl_mode(nick, from, u, chan->dname, ms2,
01179                            int_to_base10(chan->channel.maxmembers));
01180             /* The Tcl proc might have modified/removed the chan or user */
01181             if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
01182               return 0;
01183             if (channel_pending(chan))
01184               break;
01185             if ((reversing && !(chan->mode_pls_prot & CHANLIMIT)) ||
01186                 ((chan->mode_mns_prot & CHANLIMIT) && !glob_master(user) &&
01187                 !chan_master(user)))
01188               add_mode(chan, '-', 'l', "");
01189             if ((chan->limit_prot != chan->channel.maxmembers) &&
01190                 (chan->mode_pls_prot & CHANLIMIT) && (chan->limit_prot != 0) &&
01191                 !glob_master(user) && !chan_master(user)) {
01192               simple_sprintf(s, "%d", chan->limit_prot);
01193               add_mode(chan, '+', 'l', s);
01194             }
01195           }
01196           break;
01197         case 'k':
01198           if (ms2[0] == '+')
01199             chan->channel.mode |= CHANKEY;
01200           else
01201             chan->channel.mode &= ~CHANKEY;
01202           op = newsplit(&msg);
01203           fixcolon(op);
01204           if (op == '\0') {
01205             break;
01206           }
01207           check_tcl_mode(nick, from, u, chan->dname, ms2, op);
01208           /* The Tcl proc might have modified/removed the chan or user */
01209           if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
01210             return 0;
01211           if (ms2[0] == '+') {
01212             set_key(chan, op);
01213             if (channel_active(chan))
01214               got_key(chan, nick, from, op);
01215           } else {
01216             if (channel_active(chan)) {
01217               if (reversing && chan->channel.key[0])
01218                 add_mode(chan, '+', 'k', chan->channel.key);
01219               else if (chan->key_prot[0] && !glob_master(user) &&
01220                        !chan_master(user) && !match_my_nick(nick))
01221                 add_mode(chan, '+', 'k', chan->key_prot);
01222             }
01223             set_key(chan, NULL);
01224           }
01225           break;
01226         case 'o':
01227           op = newsplit(&msg);
01228           fixcolon(op);
01229           if (ms2[0] == '+')
01230             got_op(chan, nick, from, op, u, &user);
01231           else
01232             got_deop(chan, nick, from, op, u);
01233           break;
01234         case 'h':
01235           op = newsplit(&msg);
01236           fixcolon(op);
01237           if (ms2[0] == '+')
01238             got_halfop(chan, nick, from, op, u, &user);
01239           else
01240             got_dehalfop(chan, nick, from, op, u);
01241           break;
01242         case 'v':
01243           op = newsplit(&msg);
01244           fixcolon(op);
01245           m = ismember(chan, op);
01246           if (!m) {
01247             if (channel_pending(chan))
01248               break;
01249             putlog(LOG_MISC, chan->dname, CHAN_BADCHANMODE, chan->dname, op);
01250             chan->status |= CHAN_PEND;
01251             refresh_who_chan(chan->name);
01252           } else {
01253             simple_sprintf(s, "%s!%s", m->nick, m->userhost);
01254             get_user_flagrec(m->user ? m->user : get_user_by_host(s),
01255                              &victim, chan->dname);
01256             if (ms2[0] == '+') {
01257               m->flags &= ~SENTVOICE;
01258               m->flags |= CHANVOICE;
01259               check_tcl_mode(nick, from, u, chan->dname, ms2, op);
01260               if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
01261                 return 0;
01262               if (channel_active(chan) && !glob_master(user) &&
01263                   !chan_master(user) && !match_my_nick(nick)) {
01264                 if (chan_quiet(victim) ||
01265                     (glob_quiet(victim) && !chan_voice(victim)))
01266                   add_mode(chan, '-', 'v', op);
01267                 else if (reversing)
01268                   add_mode(chan, '-', 'v', op);
01269               }
01270             } else {
01271               m->flags &= ~SENTDEVOICE;
01272               m->flags &= ~CHANVOICE;
01273               check_tcl_mode(nick, from, u, chan->dname, ms2, op);
01274               if (!(chan = modebind_refresh(ch, from, &user, s, &victim)))
01275                 return 0;
01276               if (channel_active(chan) && !glob_master(user) &&
01277                   !chan_master(user) && !match_my_nick(nick)) {
01278                 if ((channel_autovoice(chan) && !chan_quiet(victim) &&
01279                     (chan_voice(victim) || glob_voice(victim))) ||
01280                     (!chan_quiet(victim) && (glob_gvoice(victim) ||
01281                     chan_gvoice(victim))))
01282                   add_mode(chan, '+', 'v', op);
01283                 else if (reversing)
01284                   add_mode(chan, '+', 'v', op);
01285               }
01286             }
01287           }
01288           break;
01289         case 'b':
01290           op = newsplit(&msg);
01291           fixcolon(op);
01292           if (ms2[0] == '+')
01293             got_ban(chan, nick, from, op, ch, u);
01294           else
01295             got_unban(chan, nick, from, op, ch, u);
01296           break;
01297         case 'e':
01298           op = newsplit(&msg);
01299           fixcolon(op);
01300           if (ms2[0] == '+')
01301             got_exempt(chan, nick, from, op, ch, u);
01302           else
01303             got_unexempt(chan, nick, from, op, ch, u);
01304           break;
01305         case 'I':
01306           op = newsplit(&msg);
01307           fixcolon(op);
01308           if (ms2[0] == '+')
01309             got_invite(chan, nick, from, op, ch, u);
01310           else
01311             got_uninvite(chan, nick, from, op, ch, u);
01312           break;
01313         }
01314         if (todo) {
01315           check_tcl_mode(nick, from, u, chan->dname, ms2, "");
01316           if (!(chan = modebind_refresh(ch, from, &user, NULL, NULL)))
01317             return 0;
01318           if (ms2[0] == '+')
01319             chan->channel.mode |= todo;
01320           else
01321             chan->channel.mode &= ~todo;
01322           if (channel_active(chan)) {
01323             if ((((ms2[0] == '+') && (chan->mode_mns_prot & todo)) ||
01324                 ((ms2[0] == '-') && (chan->mode_pls_prot & todo))) &&
01325                 !glob_master(user) && !chan_master(user) &&
01326                 !match_my_nick(nick))
01327               add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
01328             else if (reversing && ((ms2[0] == '+') ||
01329                      (chan->mode_pls_prot & todo)) && ((ms2[0] == '-') ||
01330                      (chan->mode_mns_prot & todo)))
01331               add_mode(chan, ms2[0] == '+' ? '-' : '+', *chg, "");
01332           }
01333         }
01334         chg++;
01335       }
01336       if (!me_op(chan) && !nick[0])
01337         chan->status |= CHAN_ASKEDMODES;
01338     }
01339   }
01340   return 0;
01341 }

Here is the call graph for this function:

struct chanset_t* modebind_refresh ( char *  chname,
char *  usrhost,
struct flag_record usr,
char *  vcrhost,
struct flag_record vcr 
) [read]

Definition at line 47 of file mode.c.

References chanset_t::dname, findchan, get_user_by_host, get_user_flagrec, and NULL.

Referenced by got_ban(), got_dehalfop(), got_deop(), got_exempt(), got_halfop(), got_invite(), got_op(), got_unban(), got_unexempt(), got_uninvite(), and gotmode().

00050 {
00051   struct userrec *u;
00052   struct chanset_t *chan;
00053 
00054   if (!chname || !(chan = findchan(chname)))
00055     return NULL;
00056   if (usrhost) {
00057     u = get_user_by_host(usrhost);
00058     get_user_flagrec(u, usr, chan->dname);
00059   }
00060   if (vcrhost) {
00061     u = get_user_by_host(vcrhost);
00062     get_user_flagrec(u, vcr, chan->dname);
00063   }
00064   return chan;
00065 }

Here is the caller graph for this function:

static void real_add_mode ( struct chanset_t chan,
char  plus,
char  mode,
char *  op 
) [static]

Definition at line 201 of file mode.c.

References chan_t::ban, BAN, chanset_t::bans, chanset_t::bytes, chan_hashalfop, chan_hasop, chan_hasvoice, chan_sentdehalfop, chan_sentdeop, chan_sentdevoice, chan_senthalfop, chan_sentop, chan_sentvoice, chanset_t::channel, channel_malloc(), CHHOP, CHOP, chanset_t::cmode, chanset_t::compat, chan_t::exempt, EXEMPT, chanset_t::exempts, memstruct::flags, flush_mode(), HALFOP_CANTDOMODE, include_lk, chan_t::invite, INVITE, chanset_t::invites, ischanban, ischanexempt, ischaninvite, ismember, chanset_t::key, chanset_t::limit, maskstruct::mask, max_bans, max_exempts, max_invites, max_modes, me_op(), MINUS, chanset_t::mns, mode_buf_len, modesperline, maskstruct::next, nfree, NORMAL, NULL, chanset_t::op, chanset_t::pls, PLUS, prevent_mixing, rfc_casecmp, chanset_t::rmkey, SENTDEHALFOP, SENTDEOP, SENTDEVOICE, SENTHALFOP, SENTOP, SENTVOICE, chanset_t::type, and VOICE.

Referenced by irc_close(), and irc_start().

00203 {
00204   int i, type, modes, l;
00205   masklist *m;
00206   memberlist *mx;
00207   char s[21];
00208 
00209   /* Some IRCds do not allow halfops to set certain modes. The modes halfops
00210    * are not allowed to set can be changed in chan.h. */
00211 #ifdef NO_HALFOP_CHANMODES
00212   if (!me_op(chan))
00213 #else
00214   if (HALFOP_CANTDOMODE(mode))
00215 #endif
00216     return;
00217 
00218   if (mode == 'o' || mode == 'h' || mode == 'v') {
00219     mx = ismember(chan, op);
00220     if (!mx)
00221       return;
00222     if (plus == '-' && mode == 'o') {
00223       if (chan_sentdeop(mx) || !chan_hasop(mx))
00224         return;
00225       mx->flags |= SENTDEOP;
00226     }
00227     if (plus == '+' && mode == 'o') {
00228       if (chan_sentop(mx) || chan_hasop(mx))
00229         return;
00230       mx->flags |= SENTOP;
00231     }
00232     if (plus == '-' && mode == 'h') {
00233       if (chan_sentdehalfop(mx) || !chan_hashalfop(mx))
00234         return;
00235       mx->flags |= SENTDEHALFOP;
00236     }
00237     if (plus == '+' && mode == 'h') {
00238       if (chan_senthalfop(mx) || chan_hashalfop(mx))
00239         return;
00240       mx->flags |= SENTHALFOP;
00241     }
00242     if (plus == '-' && mode == 'v') {
00243       if (chan_sentdevoice(mx) || !chan_hasvoice(mx))
00244         return;
00245       mx->flags |= SENTDEVOICE;
00246     }
00247     if (plus == '+' && mode == 'v') {
00248       if (chan_sentvoice(mx) || chan_hasvoice(mx))
00249         return;
00250       mx->flags |= SENTVOICE;
00251     }
00252   }
00253 
00254   if (chan->compat == 0) {
00255     if (mode == 'e' || mode == 'I')
00256       chan->compat = 2;
00257     else
00258       chan->compat = 1;
00259   } else if (mode == 'e' || mode == 'I') {
00260     if (prevent_mixing && chan->compat == 1)
00261       flush_mode(chan, NORMAL);
00262   } else if (prevent_mixing && chan->compat == 2)
00263     flush_mode(chan, NORMAL);
00264 
00265   if (mode == 'o' || mode == 'h' || mode == 'b' || mode == 'v' || mode == 'e' ||
00266       mode == 'I') {
00267     type = (plus == '+' ? PLUS : MINUS) | (mode == 'o' ? CHOP : (mode == 'h' ?
00268            CHHOP : (mode == 'b' ? BAN : (mode == 'v' ? VOICE : (mode == 'e' ?
00269            EXEMPT : INVITE)))));
00270     /*
00271      * FIXME: Some networks remove overlapped bans,
00272      *        IRCnet does not (poptix/drummer)
00273      *
00274      * Note:  On IRCnet ischanXXX() should be used, otherwise isXXXed().
00275      */
00276     if ((plus == '-' && ((mode == 'b' && !ischanban(chan, op)) ||
00277         (mode == 'e' && !ischanexempt(chan, op)) ||
00278         (mode == 'I' && !ischaninvite(chan, op)))) || (plus == '+' &&
00279         ((mode == 'b' && ischanban(chan, op)) ||
00280         (mode == 'e' && ischanexempt(chan, op)) ||
00281         (mode == 'I' && ischaninvite(chan, op)))))
00282       return;
00283 
00284     /* If there are already max_bans bans, max_exempts exemptions,
00285      * max_invites invitations or max_modes +b/+e/+I modes on the
00286      * channel, don't try to add one more.
00287      */
00288     if (plus == '+' && (mode == 'b' || mode == 'e' || mode == 'I')) {
00289       int bans = 0, exempts = 0, invites = 0;
00290 
00291       for (m = chan->channel.ban; m && m->mask[0]; m = m->next)
00292         bans++;
00293       if ((mode == 'b') && (bans >= max_bans))
00294         return;
00295 
00296       for (m = chan->channel.exempt; m && m->mask[0]; m = m->next)
00297         exempts++;
00298       if ((mode == 'e') && (exempts >= max_exempts))
00299         return;
00300 
00301       for (m = chan->channel.invite; m && m->mask[0]; m = m->next)
00302         invites++;
00303       if ((mode == 'I') && (invites >= max_invites))
00304         return;
00305 
00306       if (bans + exempts + invites >= max_modes)
00307         return;
00308     }
00309 
00310     /* op-type mode change */
00311     for (i = 0; i < modesperline; i++)
00312       if (chan->cmode[i].type == type && chan->cmode[i].op != NULL &&
00313           !rfc_casecmp(chan->cmode[i].op, op))
00314         return;                 /* Already in there :- duplicate */
00315     l = strlen(op) + 1;
00316     if (chan->bytes + l > mode_buf_len)
00317       flush_mode(chan, NORMAL);
00318     for (i = 0; i < modesperline; i++)
00319       if (chan->cmode[i].type == 0) {
00320         chan->cmode[i].type = type;
00321         chan->cmode[i].op = (char *) channel_malloc(l);
00322         chan->bytes += l;       /* Add 1 for safety */
00323         strcpy(chan->cmode[i].op, op);
00324         break;
00325       }
00326   }
00327 
00328   /* +k ? store key */
00329   else if (plus == '+' && mode == 'k') {
00330     if (chan->key)
00331       nfree(chan->key);
00332     chan->key = (char *) channel_malloc(strlen(op) + 1);
00333     if (chan->key)
00334       strcpy(chan->key, op);
00335   }
00336   /* -k ? store removed key */
00337   else if (plus == '-' && mode == 'k') {
00338     if (chan->rmkey)
00339       nfree(chan->rmkey);
00340     chan->rmkey = (char *) channel_malloc(strlen(op) + 1);
00341     if (chan->rmkey)
00342       strcpy(chan->rmkey, op);
00343   }
00344   /* +l ? store limit */
00345   else if (plus == '+' && mode == 'l')
00346     chan->limit = atoi(op);
00347   else {
00348     /* Typical mode changes */
00349     if (plus == '+')
00350       strcpy(s, chan->pls);
00351     else
00352       strcpy(s, chan->mns);
00353     if (!strchr(s, mode)) {
00354       if (plus == '+') {
00355         chan->pls[strlen(chan->pls) + 1] = 0;
00356         chan->pls[strlen(chan->pls)] = mode;
00357       } else {
00358         chan->mns[strlen(chan->mns) + 1] = 0;
00359         chan->mns[strlen(chan->mns)] = mode;
00360       }
00361     }
00362   }
00363   modes = modesperline;         /* Check for full buffer. */
00364   for (i = 0; i < modesperline; i++)
00365     if (chan->cmode[i].type)
00366       modes--;
00367   if (include_lk && chan->limit)
00368     modes--;
00369   if (include_lk && chan->rmkey)
00370     modes--;
00371   if (include_lk && chan->key)
00372     modes--;
00373   if (modes < 1)
00374     flush_mode(chan, NORMAL);   /* Full buffer! Flush modes. */
00375 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int reversing = 0 [static]
struct flag_record user = { 0x00000001 | 0x00000004 , 0, 0, 0, 0, 0 } [static]

Definition at line 40 of file mode.c.

struct flag_record victim = { 0x00000001 | 0x00000004 , 0, 0, 0, 0, 0 } [static]

Definition at line 41 of file mode.c.


Generated on 7 Sep 2016 for Eggdrop by  doxygen 1.6.1