00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015 #include "users.h"
00016 #include "channels.h"
00017 #include "modules.h"
00018
00019
00020
00023 class Redirect : public ModeHandler
00024 {
00025 public:
00026 Redirect(InspIRCd* Instance) : ModeHandler(Instance, 'L', 1, 0, false, MODETYPE_CHANNEL, false) { }
00027
00028 ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter)
00029 {
00030 if (channel->IsModeSet('L'))
00031 return std::make_pair(true, channel->GetModeParameter('L'));
00032 else
00033 return std::make_pair(false, parameter);
00034 }
00035
00036 bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
00037 {
00038
00039 return (their_param < our_param);
00040 }
00041
00042 ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding)
00043 {
00044 if (adding)
00045 {
00046 chanrec* c = NULL;
00047
00048 if (!ServerInstance->IsChannel(parameter.c_str()))
00049 {
00050 source->WriteServ("403 %s %s :Invalid channel name",source->nick, parameter.c_str());
00051 parameter.clear();
00052 return MODEACTION_DENY;
00053 }
00054
00055 c = ServerInstance->FindChan(parameter);
00056 if (c)
00057 {
00058
00059 if (IS_LOCAL(source))
00060 {
00061 if ((c == channel) || (c->IsModeSet('L')))
00062 {
00063 source->WriteServ("690 %s :Circular or chained +L to %s not allowed (Channel already has +L). Pack of wild dogs has been unleashed.",source->nick,parameter.c_str());
00064 parameter.clear();
00065 return MODEACTION_DENY;
00066 }
00067 else
00068 {
00069 for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++)
00070 {
00071 if ((i->second != channel) && (i->second->IsModeSet('L')) && (irc::string(i->second->GetModeParameter('L').c_str()) == irc::string(channel->name)))
00072 {
00073 source->WriteServ("690 %s :Circular or chained +L to %s not allowed (Already forwarded here from %s). Angry monkeys dispatched.",source->nick,parameter.c_str(),i->second->name);
00074 return MODEACTION_DENY;
00075 }
00076 }
00077 }
00078 }
00079 }
00080
00081 channel->SetMode('L', true);
00082 channel->SetModeParam('L', parameter.c_str(), true);
00083 return MODEACTION_ALLOW;
00084 }
00085 else
00086 {
00087 if (channel->IsModeSet('L'))
00088 {
00089 channel->SetMode('L', false);
00090 return MODEACTION_ALLOW;
00091 }
00092 }
00093
00094 return MODEACTION_DENY;
00095
00096 }
00097 };
00098
00099 class ModuleRedirect : public Module
00100 {
00101
00102 Redirect* re;
00103
00104 public:
00105
00106 ModuleRedirect(InspIRCd* Me)
00107 : Module(Me)
00108 {
00109
00110 re = new Redirect(ServerInstance);
00111 if (!ServerInstance->AddMode(re, 'L'))
00112 throw ModuleException("Could not add new modes!");
00113 }
00114
00115 void Implements(char* List)
00116 {
00117 List[I_OnUserPreJoin] = 1;
00118 }
00119
00120 virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
00121 {
00122 if (chan)
00123 {
00124 if (chan->IsModeSet('L') && chan->limit)
00125 {
00126 if (chan->GetUserCounter() >= chan->limit)
00127 {
00128 std::string channel = chan->GetModeParameter('L');
00129
00130
00131 chanrec* destchan = NULL;
00132 destchan = ServerInstance->FindChan(channel);
00133 if (destchan && destchan->IsModeSet('L'))
00134 {
00135 user->WriteServ("470 %s :%s is full, but has a circular redirect (+L), not following redirection to %s", user->nick, cname, channel.c_str());
00136 return 1;
00137 }
00138
00139 user->WriteServ("470 %s :%s has become full, so you are automatically being transferred to the linked channel %s", user->nick, cname, channel.c_str());
00140 chanrec::JoinUser(ServerInstance, user, channel.c_str(), false, "", ServerInstance->Time(true));
00141 return 1;
00142 }
00143 }
00144 }
00145 return 0;
00146 }
00147
00148 virtual ~ModuleRedirect()
00149 {
00150 ServerInstance->Modes->DelMode(re);
00151 DELETE(re);
00152 }
00153
00154 virtual Version GetVersion()
00155 {
00156 return Version(1, 1, 0, 0, VF_COMMON | VF_VENDOR, API_VERSION);
00157 }
00158 };
00159
00160 MODULE_INIT(ModuleRedirect)