diff options
| author | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2010-01-14 21:29:08 +0000 |
|---|---|---|
| committer | Adam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864> | 2010-01-14 21:29:08 +0000 |
| commit | 711787b54d8b57ace877b09587f368cee5553b70 (patch) | |
| tree | f5093aeeec5c1f4155e31f72488ae4040e37f551 | |
| parent | f2c44c67b59bd4f6a5a01412f2dc5df59010b1da (diff) | |
Burned do_sjoin and rewrote it to be sane. This changes how Anope handles new channel creations drasitcally as we now truely track it all instead of hack around it by not initially tracking user joins to new channels
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2755 5417fbe8-f217-4b02-8779-1006273d7864
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | include/extern.h | 6 | ||||
| -rw-r--r-- | include/modes.h | 10 | ||||
| -rw-r--r-- | include/modules.h | 5 | ||||
| -rw-r--r-- | include/services.h | 23 | ||||
| -rw-r--r-- | src/channels.c | 827 | ||||
| -rw-r--r-- | src/chanserv.c | 79 | ||||
| -rw-r--r-- | src/core/cs_forbid.c | 1 | ||||
| -rw-r--r-- | src/core/cs_set.c | 2 | ||||
| -rw-r--r-- | src/core/os_defcon.c | 2 | ||||
| -rw-r--r-- | src/modes.cpp | 4 | ||||
| -rw-r--r-- | src/protocol/bahamut.c | 166 | ||||
| -rw-r--r-- | src/protocol/inspircd11.c | 157 | ||||
| -rw-r--r-- | src/protocol/inspircd12.cpp | 181 | ||||
| -rw-r--r-- | src/protocol/ratbox.c | 130 | ||||
| -rw-r--r-- | src/protocol/unreal32.c | 158 | ||||
| -rw-r--r-- | src/users.c | 2 |
17 files changed, 944 insertions, 811 deletions
@@ -30,6 +30,7 @@ Legend: [x] CS SET INHABIT to keep pseudoclient in a channel after it empties to maintain banlists and such [x] Set forbidden channels +s [x] SendAkill should just take a pointer to the Akill class instead of millions of fields (same for some other stuff) +[x] burn do_sjoin with fire Future ------ @@ -37,7 +38,6 @@ Future [?] Remote identification (1.9.1? will this break stuff?) [ ] Language charset stuff, including collation (1.9.1? phoenix?) [ ] Add support for +k, +q, etc type umodes -[ ] burn do_sjoin with fire [ ] fantasy: allow replies/notifications to fantasy commands to go to the channel via notice [?] a way for a module to queue itself (or even another module) for unloading [ ] add overridden form of SendGlobops accepting BotInfo diff --git a/include/extern.h b/include/extern.h index 75ad3eb28..a46894fa2 100644 --- a/include/extern.h +++ b/include/extern.h @@ -68,9 +68,6 @@ E void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode, char * E Channel *chanlist[1024]; -E void chan_adduser2(User * user, Channel * c); -E Channel *join_user_update(User * user, Channel * chan, const char *name, time_t chants); - E void get_channel_stats(long *nrec, long *memuse); E Channel *findchan(const char *chan); E Channel *firstchan(); @@ -78,8 +75,6 @@ E Channel *nextchan(); E void ChanSetInternalModes(Channel *c, int ac, const char **av); -E void chan_deluser(User * user, Channel * c); - E int is_on_chan(Channel * c, User * u); E User *nc_on_chan(Channel * c, NickCore * nc); @@ -97,7 +92,6 @@ E void do_cmode(const char *source, int ac, const char **av); E void do_join(const char *source, int ac, const char **av); E void do_kick(const std::string &source, int ac, const char **av); E void do_part(const char *source, int ac, const char **av); -E void do_sjoin(const char *source, int ac, const char **av); E void do_topic(const char *source, int ac, const char **av); E void MassChannelModes(BotInfo *bi, const std::string &modes); diff --git a/include/modes.h b/include/modes.h index 5a1fd60b5..64532bb6d 100644 --- a/include/modes.h +++ b/include/modes.h @@ -99,7 +99,7 @@ class UserModeParam : public UserMode * @param value The param * @return true or false */ - virtual bool IsValid(const char *value) { return true; } + virtual bool IsValid(const std::string &value) { return true; } }; /** This class is a channel mode, all channel modes use this/inherit from this @@ -151,7 +151,7 @@ class CoreExport ChannelModeList : public ChannelMode * @param mask The mask * @return true for yes, false for no */ - virtual bool IsValid(const char *mask) { return true; } + virtual bool IsValid(const std::string &mask) { return true; } /** Add the mask to the channel, this should be overridden * @param chan The channel @@ -190,7 +190,7 @@ class CoreExport ChannelModeParam : public ChannelMode * @param value The param * @return true for yes, false for no */ - virtual bool IsValid(const char *value) { return true; } + virtual bool IsValid(const std::string &value) { return true; } }; /** This is a mode that is a channel status, eg +v/h/o/a/q. @@ -264,7 +264,7 @@ class CoreExport ChannelModeKey : public ChannelModeParam public: ChannelModeKey() : ChannelModeParam(CMODE_KEY) { } - bool IsValid(const char *value); + bool IsValid(const std::string &value); }; /** Channel mode +f (flood) @@ -274,7 +274,7 @@ class ChannelModeFlood : public ChannelModeParam public: ChannelModeFlood() : ChannelModeParam(CMODE_FLOOD) { } - bool IsValid(const char *value); + bool IsValid(const std::string &value); }; /** This class is used for channel mode +A (Admin only) diff --git a/include/modules.h b/include/modules.h index 8903eb9c2..45541c28c 100644 --- a/include/modules.h +++ b/include/modules.h @@ -644,9 +644,10 @@ class CoreExport Module /** Called before a user joins a channel * @param u The user - * @param channel The channel + * @param c The channel + * @return EVENT_STOP to allow the user to join the channel through restrictions, EVENT_CONTINUE to let other modules decide */ - virtual void OnPreJoinChannel(User *u, const char *channel) { } + virtual EventReturn OnPreJoinChannel(User *u, Channel *c) { return EVENT_CONTINUE; } /** Called when a user joins a channel * @param u The user diff --git a/include/services.h b/include/services.h index de6972fc2..244377419 100644 --- a/include/services.h +++ b/include/services.h @@ -410,10 +410,7 @@ struct ircdvars_ { int knock_needs_i; /* Check if we needed +i when setting NOKNOCK */ char *chanmodes; /* If the ircd sends CHANMODE in CAPAB this is where we store it */ int token; /* Does Anope support the tokens for the ircd */ - int sjb64; /* Base 64 encode TIMESTAMP */ - int sjoinbanchar; /* use single quotes to define it */ - int sjoinexchar; /* use single quotes to define it */ - int sjoininvchar; /* use single quotes to define it */ + int sjb64; int svsmode_ucmode; /* Can remove User Channel Modes with SVSMODE */ int sglineenforce; int ts6; /* ircd is TS6 */ @@ -832,7 +829,9 @@ struct c_userlist { enum ChannelFlags { /* Channel still exists when emptied */ - CH_PERSIST + CH_PERSIST, + /* If set the channel is syncing users (eg, multi user SJOIN) and it should not be deleted */ + CH_SYNCING }; class CoreExport Channel : public Extensible, public Flags<ChannelFlags> @@ -878,6 +877,20 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlags> int16 bouncy_modes; /* Did we fail to set modes here? */ int16 topic_sync; /* Is the topic in sync? */ + /** Restore the channel topic, set mlock (key), set stickied bans, etc + */ + void Sync(); + + /** Join a user internally to the channel + * @param u The user + */ + void JoinUser(User *u); + + /** Remove a user internally from the channel + * @param u The user + */ + void DeleteUser(User *u); + /** * See if a channel has a mode * @param Name The mode name diff --git a/src/channels.c b/src/channels.c index 6c6c399c6..e82da8dc2 100644 --- a/src/channels.c +++ b/src/channels.c @@ -52,16 +52,8 @@ Channel::Channel(const std::string &name, time_t ts) this->ci = cs_findchan(this->name); if (this->ci) - { this->ci->c = this; - check_modes(this); - stick_all(this->ci); - } - - if (serv_uplink && is_sync(serv_uplink) && (!(this->topic_sync))) - restore_topic(name.c_str()); - FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(this)); } @@ -122,6 +114,141 @@ Channel::~Channel() chanlist[HASH(this->name)] = this->next; } +void Channel::Sync() +{ + if (this->ci) + { + check_modes(this); + stick_all(this->ci); + } + + if (serv_uplink && is_sync(serv_uplink) && !this->topic_sync) + restore_topic(name.c_str()); +} + +void Channel::JoinUser(User *user) +{ + struct u_chanlist *c; + + if (debug) + alog("debug: %s joins %s", user->nick.c_str(), this->name.c_str()); + + c = new u_chanlist; + c->prev = NULL; + c->next = user->chans; + if (user->chans) + user->chans->prev = c; + user->chans = c; + c->chan = this; + c->status = 0; + + struct c_userlist *u; + + u = new c_userlist; + u->prev = NULL; + u->next = this->users; + if (this->users) + this->users->prev = u; + this->users = u; + u->user = user; + u->ud = NULL; + this->usercount++; + + if (get_ignore(user->nick.c_str()) == NULL) + { + if (this->ci && (check_access(user, this->ci, CA_MEMO)) && (this->ci->memos.memos.size() > 0)) + { + if (this->ci->memos.memos.size() == 1) + notice_lang(Config.s_MemoServ, user, MEMO_X_ONE_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); + else + notice_lang(Config.s_MemoServ, user, MEMO_X_MANY_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); + } + /* Added channelname to entrymsg - 30.03.2004, Certus */ + /* Also, don't send the entrymsg when bursting -GD */ + if (this->ci && this->ci->entry_message && is_sync(user->server)) + user->SendMessage(whosends(this->ci)->nick, "[%s] %s", this->name.c_str(), this->ci->entry_message); + } + + /** + * We let the bot join even if it was an ignored user, as if we don't, + * and the ignored user doesnt just leave, the bot will never + * make it into the channel, leaving the channel botless even for + * legit users - Rob + * But don't join the bot if the channel is persistant - Adam + **/ + if (Config.s_BotServ && this->ci && this->ci->bi && !this->ci->HasFlag(CI_PERSIST)) + { + if (this->usercount == Config.BSMinUsers) + bot_join(this->ci); + } + if (Config.s_BotServ && this->ci && this->ci->bi) + { + if (this->usercount >= Config.BSMinUsers && (this->ci->botflags.HasFlag(BS_GREET)) + && user->nc && user->nc->greet && check_access(user, this->ci, CA_GREET)) + { + /* Only display the greet if the main uplink we're connected + * to has synced, or we'll get greet-floods when the net + * recovers from a netsplit. -GD + */ + if (is_sync(user->server)) + { + ircdproto->SendPrivmsg(this->ci->bi, this->name.c_str(), "[%s] %s", user->nc->display, user->nc->greet); + this->ci->bi->lastmsg = time(NULL); + } + } + } +} + +/** Remove a user internally from the channel + * @param u The user + */ +void Channel::DeleteUser(User *user) +{ + if (this->ci) + update_cs_lastseen(user, this->ci); + + struct c_userlist *u; + for (u = this->users; u && u->user != user; u = u->next); + if (!u) + return; + + if (u->ud) + { + if (u->ud->lastline) + delete [] u->ud->lastline; + delete u->ud; + } + + if (u->next) + u->next->prev = u->prev; + if (u->prev) + u->prev->next = u->next; + else + this->users = u->next; + delete u; + this->usercount--; + + /* Channel is persistant, it shouldn't be deleted and the service bot should stay */ + if (this->HasFlag(CH_PERSIST) || (this->ci && this->ci->HasFlag(CI_PERSIST))) + return; + + /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly + * We also don't part the bot here either, if necessary we will part it after the sync + */ + if (this->HasFlag(CH_SYNCING)) + return; + + /* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */ + if (this->ci && this->ci->HasFlag(CI_INHABIT)) + return; + + if (Config.s_BotServ && this->ci && this->ci->bi && this->usercount <= Config.BSMinUsers - 1) + ircdproto->SendPart(this->ci->bi, this, NULL); + + if (!this->users) + delete this; +} + /** * See if a channel has a mode * @param Name The mode name @@ -290,12 +417,12 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const std::string ¶m, bool User *u = finduser(param); if (!u) { - alog("Channel::RemoveModeInternal() MODE %s +%c for nonexistant user %s", this->name.c_str(), cm->ModeChar, param.c_str()); + alog("Channel::RemoveModeInternal() MODE %s -%c for nonexistant user %s", this->name.c_str(), cm->ModeChar, param.c_str()); return; } if (debug) - alog("debug: Setting +%c on %s for %s", cm->ModeChar, this->name.c_str(), u->nick.c_str()); + alog("debug: Setting -%c on %s for %s", cm->ModeChar, this->name.c_str(), u->nick.c_str()); ChannelModeStatus *cms = dynamic_cast<ChannelModeStatus *>(cm); chan_remove_user_status(this, u, cms->Status); @@ -381,9 +508,24 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const std::string ¶m, bool */ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const std::string ¶m, bool EnforceMLock) { - if (!cm || HasMode(cm->Name)) + if (!cm) + return; + /* Don't set modes already set */ + if ((cm->Type == MODE_REGULAR || cm->Type == MODE_PARAM) && HasMode(cm->Name)) return; + else if (cm->Type == MODE_STATUS) + { + User *u = finduser(param); + if (u) + { + if (chan_has_user_status(this, u, dynamic_cast<ChannelModeStatus *>(cm)->Status)) + { + return; + } + } + } + ModeManager::StackerAdd(bi, this, cm, true, param); SetModeInternal(cm, param, EnforceMLock); } @@ -420,8 +562,23 @@ void Channel::SetMode(BotInfo *bi, char Mode, const std::string ¶m, bool Enf */ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const std::string ¶m, bool EnforceMLock) { - if (!cm || !HasMode(cm->Name)) + if (!cm) + return; + /* Don't unset modes that arent set */ + if ((cm->Type == MODE_REGULAR || cm->Type == MODE_PARAM) && !HasMode(cm->Name)) return; + /* Don't unset status that aren't set */ + else if (cm->Type == MODE_STATUS) + { + User *u = finduser(param); + if (u) + { + if (!chan_has_user_status(this, u, dynamic_cast<ChannelModeStatus *>(cm)->Status)) + { + return; + } + } + } ModeManager::StackerAdd(bi, this, cm, false, param); RemoveModeInternal(cm, param, EnforceMLock); @@ -748,7 +905,7 @@ void Channel::KickInternal(const std::string &source, const std::string &nick, c if (c) { FOREACH_MOD(I_OnUserKicked, OnUserKicked(c->chan, user, source, reason)); - chan_deluser(user, c->chan); + c->chan->DeleteUser(user); if (c->next) c->next->prev = c->prev; if (c->prev) @@ -784,47 +941,6 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) return true; } -/*************************************************************************/ - -void chan_deluser(User * user, Channel * c) -{ - struct c_userlist *u; - - if (c->ci) - update_cs_lastseen(user, c->ci); - - for (u = c->users; u && u->user != user; u = u->next); - if (!u) - return; - - if (u->ud) { - if (u->ud->lastline) - delete [] u->ud->lastline; - delete u->ud; - } - - if (u->next) - u->next->prev = u->prev; - if (u->prev) - u->prev->next = u->next; - else - c->users = u->next; - delete u; - c->usercount--; - - /* Channel is persistant, it shouldn't be deleted and the service bot should stay */ - if (c->HasFlag(CH_PERSIST) || (c->ci && c->ci->HasFlag(CI_PERSIST))) - return; - - if (Config.s_BotServ && c->ci && c->ci->bi && c->usercount == Config.BSMinUsers - 1) - ircdproto->SendPart(c->ci->bi, c, NULL); - - if (!c->users) - delete c; -} - -/*************************************************************************/ - /* Returns a fully featured binary modes string. If complete is 0, the * eventual parameters won't be added to the string. */ @@ -1134,6 +1250,7 @@ void do_join(const char *source, int ac, const char **av) char *s, *t; struct u_chanlist *c, *nextc; char *channame; + time_t ctime = time(NULL); if (ircd->ts6) { user = find_byuid(source); @@ -1162,7 +1279,7 @@ void do_join(const char *source, int ac, const char **av) nextc = c->next; channame = sstrdup(c->chan->name.c_str()); FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, c->chan)); - chan_deluser(user, c->chan); + c->chan->DeleteUser(user); FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(channame), channame, "")); delete [] channame; delete c; @@ -1174,28 +1291,52 @@ void do_join(const char *source, int ac, const char **av) chan = findchan(s); - /* how about not triggering the JOIN event on an actual /part :) -certus */ - FOREACH_MOD(I_OnPreJoinChannel, OnPreJoinChannel(user, s)); + /* Channel doesn't exist, create it */ + if (!chan) + { + chan = new Channel(av[0], ctime); + } - /* Make sure check_kick comes before chan_adduser, so banned users - * don't get to see things like channel keys. */ - /* If channel already exists, check_kick() will use correct TS. - * Otherwise, we lose. */ - if (chan && chan->ci && chan->ci->CheckKick(user)) - continue; + /* Join came with a TS */ + if (ac == 2) + { + time_t ts = atol(av[1]); - time_t ts = time(NULL); - if (ac == 2) { - ts = strtoul(av[1], NULL, 10); - if (debug) { - alog("debug: recieved a new TS for JOIN: %ld", - static_cast<long>(ts)); + /* Their time is older, we lose */ + if (chan->creation_time > ts) + { + if (debug) + alog("debug: recieved a new TS for JOIN: %ld", ts); + + if (chan->ci) + { + /* Cycle the bot to fix ts */ + if (chan->ci->bi) + { + ircdproto->SendPart(chan->ci->bi, chan, "TS reop"); + bot_join(chan->ci); + } + /* Be sure to set mlock again, else we could be -r etc.. */ + check_modes(chan); + } } } - chan = join_user_update(user, chan, s, ts); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(user, chan)); + + /* Join the user to the channel */ + chan->JoinUser(user); + /* Set the propre modes on the user */ chan_set_correct_modes(user, chan, 1); + /* Modules may want to allow this user in the channel, check. + * If not, CheckKick will kick/ban them, don't call OnJoinChannel after this as the user will have + * been destroyed + */ + if (MOD_RESULT != EVENT_STOP && chan && chan->ci && chan->ci->CheckKick(user)) + continue; + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, chan)); } } @@ -1269,7 +1410,7 @@ void do_part(const char *source, int ac, const char **av) FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, c->chan)); std::string ChannelName = c->chan->name; - chan_deluser(user, c->chan); + c->chan->DeleteUser(user); FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(ChannelName.c_str()), ChannelName, av[1] ? av[1] : "")); @@ -1286,424 +1427,6 @@ void do_part(const char *source, int ac, const char **av) /*************************************************************************/ -/* Handle a SJOIN command. - - On channel creation, syntax is: - - av[0] = timestamp - av[1] = channel name - av[2|3|4] = modes \ depends of whether the modes k and l - av[3|4|5] = users / are set or not. - - When a single user joins an (existing) channel, it is: - - av[0] = timestamp - av[1] = user - - ============================================================ - - Unreal SJOIN - - On Services connect there is - SJOIN !11LkOb #ircops +nt :@Trystan &*!*@*.aol.com "*@*.home.com - - av[0] = time stamp (base64) - av[1] = channel - av[2] = modes - av[3] = users + bans + exceptions - - On Channel Creation or a User joins an existing - Luna.NomadIrc.Net SJOIN !11LkW9 #akill :@Trystan - Luna.NomadIrc.Net SJOIN !11LkW9 #akill :Trystan` - - av[0] = time stamp (base64) - av[1] = channel - av[2] = users - -*/ - -void do_sjoin(const char *source, int ac, const char **av) -{ - Channel *c; - User *user; - Server *serv; - struct c_userlist *cu; - const char *s = NULL; - char *buf, *end, cubuf[7], *end2, value; - const char *modes[6]; - int is_sqlined = 0; - int ts = 0; - int is_created = 0; - int keep_their_modes = 1; - ChannelModeList *cml; - - serv = findserver(servlist, source); - - if (ircd->sjb64) { - ts = base64dects(av[0]); - } else { - ts = strtoul(av[0], NULL, 10); - } - c = findchan(av[1]); - if (c != NULL) { - if (c->creation_time == 0 || ts == 0) - c->creation_time = 0; - else if (c->creation_time > ts) { - c->creation_time = ts; - for (cu = c->users; cu; cu = cu->next) { - c->RemoveMode(NULL, CMODE_OP, cu->user->nick); - c->RemoveMode(NULL, CMODE_VOICE, cu->user->nick); - } - if (c->ci) - { - if (c->ci->bi) - { - /* This is ugly, but it always works */ - ircdproto->SendPart(c->ci->bi, c, "TS reop"); - bot_join(c->ci); - } - /* Make sure +r is set */ - if (ModeManager::FindChannelModeByName(CMODE_REGISTERED)) - { - c->SetMode(NULL, CMODE_REGISTERED); - } - } - /* XXX simple modes and bans */ - } else if (c->creation_time < ts) - keep_their_modes = 0; - } else - is_created = 1; - - /* Double check to avoid unknown modes that need parameters */ - if (ac >= 4) { - if (ircd->chansqline) { - if (!c) - is_sqlined = check_chan_sqline(av[1]); - } - - cubuf[0] = '+'; - modes[0] = cubuf; - - /* We make all the users join */ - s = av[ac - 1]; /* Users are always the last element */ - - while (*s) { - end = const_cast<char *>(strchr(s, ' ')); - if (end) - *end = 0; - - end2 = cubuf + 1; - - - if (ircd->sjoinbanchar) { - if (*s == ircd->sjoinbanchar && keep_their_modes) { - buf = myStrGetToken(s, ircd->sjoinbanchar, 1); - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN)); - if (cml->IsValid(buf)) - cml->AddMask(c, buf); - - delete [] buf; - if (!end) - break; - s = end + 1; - continue; - } - } - if (ircd->sjoinexchar) { - if (*s == ircd->sjoinexchar && keep_their_modes) { - buf = myStrGetToken(s, ircd->sjoinexchar, 1); - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); - if (cml->IsValid(buf)) - cml->AddMask(c, buf); - - delete [] buf; - if (!end) - break; - s = end + 1; - continue; - } - } - - if (ircd->sjoininvchar) { - if (*s == ircd->sjoininvchar && keep_their_modes) { - buf = myStrGetToken(s, ircd->sjoininvchar, 1); - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); - if (cml->IsValid(buf)) - cml->AddMask(c, buf); - - delete [] buf; - if (!end) - break; - s = end + 1; - continue; - } - } - - while ((value = ModeManager::GetStatusChar(*s))) - { - *end2++ = value; - *s++; - } - *end2 = 0; - - if (ircd->ts6) { - user = find_byuid(s); - if (!user) - user = finduser(s); - } else { - user = finduser(s); - } - - if (!user) { - if (debug) { - alog("debug: SJOIN for nonexistent user %s on %s", s, - av[1]); - } - return; - } - - if (is_sqlined && !is_oper(user)) { - ircdproto->SendKick(findbot(Config.s_OperServ), c, user, "Q-Lined"); - } else { - if (!c || !c->ci || !c->ci->CheckKick(user)) - { - FOREACH_MOD(I_OnPreJoinChannel, OnPreJoinChannel(user, av[1])); - - /* Make the user join; if the channel does not exist it - * will be created there. This ensures that the channel - * is not created to be immediately destroyed, and - * that the locked key or topic is not shown to anyone - * who joins the channel when empty. - */ - c = join_user_update(user, c, av[1], ts); - - /* We update user mode on the channel */ - if (end2 - cubuf > 1 && keep_their_modes) { - int i; - - for (i = 1; i < end2 - cubuf; i++) - modes[i] = user->nick.c_str(); - - ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes); - } - - if (c->ci && (!serv || is_sync(serv)) - && !c->topic_sync) - restore_topic(c->name.c_str()); - chan_set_correct_modes(user, c, 1); - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, c)); - } - } - - if (!end) - break; - s = end + 1; - } - - if (c && keep_their_modes) { - /* We now update the channel mode. */ - ChanSetInternalModes(c, ac - 3, &av[2]); - } - - /* Unreal just had to be different */ - } else if (ac == 3 && !ircd->ts6) { - if (ircd->chansqline) { - if (!c) - is_sqlined = check_chan_sqline(av[1]); - } - - cubuf[0] = '+'; - modes[0] = cubuf; - - /* We make all the users join */ - s = av[2]; /* Users are always the last element */ - - while (*s) { - end = const_cast<char *>(strchr(s, ' ')); - if (end) - *end = 0; - - end2 = cubuf + 1; - - while ((value = ModeManager::GetStatusChar(*s))) - { - *end2++ = value; - *s++; - } - *end2 = 0; - - if (ircd->ts6) { - user = find_byuid(s); - if (!user) - user = finduser(s); - } else { - user = finduser(s); - } - - if (!user) { - if (debug) { - alog("debug: SJOIN for nonexistent user %s on %s", s, - av[1]); - } - return; - } - - if (is_sqlined && !is_oper(user)) { - ircdproto->SendKick(findbot(Config.s_OperServ), c, user, "Q-Lined"); - } else { - if (!c || !c->ci || !c->ci->CheckKick(user)) - { - FOREACH_MOD(I_OnPreJoinChannel, OnPreJoinChannel(user, av[1])); - - /* Make the user join; if the channel does not exist it - * will be created there. This ensures that the channel - * is not created to be immediately destroyed, and - * that the locked key or topic is not shown to anyone - * who joins the channel when empty. - */ - c = join_user_update(user, c, av[1], ts); - - /* We update user mode on the channel */ - if (end2 - cubuf > 1 && keep_their_modes) { - int i; - - for (i = 1; i < end2 - cubuf; i++) - modes[i] = user->nick.c_str(); - ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes); - } - - chan_set_correct_modes(user, c, 1); - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, c)); - } - } - - if (!end) - break; - s = end + 1; - } - } else if (ac == 3 && ircd->ts6) { - if (ircd->chansqline) { - if (!c) - is_sqlined = check_chan_sqline(av[1]); - } - - cubuf[0] = '+'; - modes[0] = cubuf; - - /* We make all the users join */ - s = sstrdup(source); /* Users are always the last element */ - - while (*s) { - end = const_cast<char *>(strchr(s, ' ')); - if (end) - *end = 0; - - end2 = cubuf + 1; - - while ((value = ModeManager::GetStatusChar(*s))) - { - *end2++ = value; - *s++; - } - *end2 = 0; - - if (ircd->ts6) { - user = find_byuid(s); - if (!user) - user = finduser(s); - } else { - user = finduser(s); - } - if (!user) { - if (debug) { - alog("debug: SJOIN for nonexistent user %s on %s", s, - av[1]); - } - delete [] s; - return; - } - - if (is_sqlined && !is_oper(user)) { - ircdproto->SendKick(findbot(Config.s_OperServ), c, user, "Q-Lined"); - } else { - if (!c || !c->ci || !c->ci->CheckKick(user)) - { - FOREACH_MOD(I_OnPreJoinChannel, OnPreJoinChannel(user, av[1])); - - /* Make the user join; if the channel does not exist it - * will be created there. This ensures that the channel - * is not created to be immediately destroyed, and - * that the locked key or topic is not shown to anyone - * who joins the channel when empty. - */ - c = join_user_update(user, c, av[1], ts); - - /* We update user mode on the channel */ - if (end2 - cubuf > 1 && keep_their_modes) { - int i; - - for (i = 1; i < end2 - cubuf; i++) - modes[i] = user->nick.c_str(); - ChanSetInternalModes(c, 1 + (end2 - cubuf - 1), modes); - } - - chan_set_correct_modes(user, c, 1); - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, c)); - } - } - - if (!end) - break; - s = end + 1; - } - delete [] s; - } else if (ac == 2) { - if (ircd->ts6) { - user = find_byuid(source); - if (!user) - user = finduser(source); - } else { - user = finduser(source); - } - if (!user) { - if (debug) { - alog("debug: SJOIN for nonexistent user %s on %s", source, - av[1]); - } - return; - } - - if (c && c->ci && c->ci->CheckKick(user)) - return; - - if (ircd->chansqline) { - if (!c) - is_sqlined = check_chan_sqline(av[1]); - } - - if (is_sqlined && !is_oper(user)) { - ircdproto->SendKick(findbot(Config.s_OperServ), c, user, "Q-Lined"); - } else { - FOREACH_MOD(I_OnPreJoinChannel, OnPreJoinChannel(user, av[1])); - - c = join_user_update(user, c, av[1], ts); - if (is_created && c->ci) - restore_topic(c->name.c_str()); - chan_set_correct_modes(user, c, 1); - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(user, c)); - } - } -} - -/*************************************************************************/ - /** Process a MODE command from the server, and set the modes on the user/channel * it was sent for * @param source The source of the command @@ -1997,132 +1720,6 @@ void chan_set_correct_modes(User * user, Channel * c, int give_modes) /*************************************************************************/ -/* Add/remove a user to/from a channel, creating or deleting the channel as - * necessary. If creating the channel, restore mode lock and topic as - * necessary. Also check for auto-opping and auto-voicing. - */ - -void chan_adduser2(User * user, Channel * c) -{ - struct c_userlist *u; - - u = new c_userlist; - u->prev = NULL; - u->next = c->users; - if (c->users) - c->users->prev = u; - c->users = u; - u->user = user; - u->ud = NULL; - c->usercount++; - - if (get_ignore(user->nick.c_str()) == NULL) { - if (c->ci && (check_access(user, c->ci, CA_MEMO)) - && (c->ci->memos.memos.size() > 0)) { |
