X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_permchannels.cpp;h=6a5373009f8c14c8f9f4ff3c0b8bf26bec372f71;hb=73b5d276db1903256c7432e333b4db8d01d58d05;hp=f24a908004a5dc4aff18588c3a95df09ae5936f5;hpb=e21ee18e62aecee6d27a0f9ba497a52688cb8349;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index f24a90800..6a5373009 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -23,7 +23,7 @@ class PermChannel : public ModeHandler public: PermChannel(InspIRCd* Instance) : ModeHandler(Instance, 'P', 0, 0, false, MODETYPE_CHANNEL, false) { } - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool) + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool sm) { if (adding) { @@ -37,6 +37,29 @@ class PermChannel : public ModeHandler { if (channel->IsModeSet('P')) { + if (channel->GetUserCounter() == 0 && !sm) + { + /* + * ugh, ugh, UGH! + * + * We can't delete this channel the way things work at the moment, + * because of the following scenario: + * s1:#c <-> s2:#c + * + * s1 has a user in #c, s2 does not. s2 has +P set. s2 has a losing TS. + * + * On netmerge, s2 loses, so s2 removes all modes (including +P) which + * would subsequently delete the channel here causing big fucking problems. + * + * I don't think there's really a way around this, so just deny -P on a 0 user chan. + * -- w00t + * + * delete channel; + */ + return MODEACTION_DENY; + } + + /* for servers, remove +P (to avoid desyncs) but don't bother trying to delete. */ channel->SetMode('P',false); return MODEACTION_ALLOW; } @@ -50,7 +73,7 @@ class ModulePermanentChannels : public Module { PermChannel *p; public: - + ModulePermanentChannels(InspIRCd* Me) : Module(Me) { p = new PermChannel(ServerInstance); @@ -61,6 +84,8 @@ public: } Implementation eventlist[] = { I_OnChannelPreDelete }; ServerInstance->Modules->Attach(eventlist, this, 1); + + OnRehash(NULL, ""); } virtual ~ModulePermanentChannels() @@ -69,9 +94,63 @@ public: delete p; } + virtual void OnRehash(User *user, const std::string ¶meter) + { + /* + * Process config-defined list of permanent channels. + * -- w00t + */ + ConfigReader MyConf(ServerInstance); + for (int i = 0; i < MyConf.Enumerate("permchannels"); i++) + { + std::string channel = MyConf.ReadValue("permchannels", "channel", i); + std::string topic = MyConf.ReadValue("permchannels", "topic", i); + std::string modes = MyConf.ReadValue("permchannels", "modes", i); + + if (channel.empty() || topic.empty()) + { + ServerInstance->Logs->Log("blah", DEBUG, "Malformed permchannels tag with empty topic or channel name."); + continue; + } + + Channel *c = ServerInstance->FindChan(channel); + + if (!c) + { + c = new Channel(ServerInstance, channel, ServerInstance->Time()); + c->SetTopic(NULL, topic, true); + ServerInstance->Logs->Log("blah", DEBUG, "Added %s with topic %s", channel.c_str(), topic.c_str()); + + if (modes.empty()) + continue; + + irc::spacesepstream list(modes); + std::string modeseq; + std::string par; + + list.GetToken(modeseq); + + // XXX bleh, should we pass this to the mode parser instead? ugly. --w00t + for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n) + { + ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL); + if (mode) + { + if (mode->GetNumParams(true)) + list.GetToken(par); + else + par.clear(); + + mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); + } + } + } + } + } + virtual Version GetVersion() { - return Version(1,1,0,0,VF_COMMON|VF_VENDOR,API_VERSION); + return Version("$Id$",VF_COMMON|VF_VENDOR,API_VERSION); } virtual int OnChannelPreDelete(Channel *c)