00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016
00017
00018
00019
00020
00021
00022
00023
00026 class RemoveBase
00027 {
00028 private:
00029 bool& supportnokicks;
00030 InspIRCd* ServerInstance;
00031
00032 protected:
00033 RemoveBase(InspIRCd* Instance, bool& snk) : supportnokicks(snk), ServerInstance(Instance)
00034 {
00035 }
00036
00037 enum ModeLevel { PEON = 0, HALFOP = 1, OP = 2, ADMIN = 3, OWNER = 4, ULINE = 5 };
00038
00039
00040
00041
00042 ModeLevel chartolevel(const std::string &privs)
00043 {
00044 if(privs.empty())
00045 {
00046 return PEON;
00047 }
00048
00049 switch (privs[0])
00050 {
00051 case 'U':
00052
00053 return ULINE;
00054 case '~':
00055
00056 return OWNER;
00057 case '&':
00058
00059 return ADMIN;
00060 case '@':
00061
00062 return OP;
00063 case '%':
00064
00065 return HALFOP;
00066 default:
00067
00068 return PEON;
00069 }
00070 }
00071
00072 CmdResult Handle (const std::vector<std::string>& parameters, User *user, bool neworder)
00073 {
00074 const char* channame;
00075 const char* username;
00076 User* target;
00077 Channel* channel;
00078 ModeLevel tlevel;
00079 ModeLevel ulevel;
00080 std::string reason;
00081 std::string protectkey;
00082 std::string founderkey;
00083 bool hasnokicks;
00084
00085
00086
00087
00088
00089
00090 channame = parameters[ neworder ? 0 : 1].c_str();
00091 username = parameters[ neworder ? 1 : 0].c_str();
00092
00093
00094 target = ServerInstance->FindNick(username);
00095
00096
00097 channel = ServerInstance->FindChan(channame);
00098
00099
00100 if (!target || !channel)
00101 {
00102 user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel", user->nick.c_str(), !target ? username : channame);
00103 return CMD_FAILURE;
00104 }
00105
00106 if (!channel->HasUser(target))
00107 {
00108 user->WriteServ( "NOTICE %s :*** The user %s is not on channel %s", user->nick.c_str(), target->nick.c_str(), channel->name.c_str());
00109 return CMD_FAILURE;
00110 }
00111
00112
00113
00114 protectkey = "cm_protect_" + std::string(channel->name);
00115 founderkey = "cm_founder_" + std::string(channel->name);
00116
00117 if (ServerInstance->ULine(user->server) || ServerInstance->ULine(user->nick.c_str()))
00118 {
00119 ulevel = chartolevel("U");
00120 }
00121 if (user->GetExt(founderkey))
00122 {
00123 ulevel = chartolevel("~");
00124 }
00125 else if (user->GetExt(protectkey))
00126 {
00127 ulevel = chartolevel("&");
00128 }
00129 else
00130 {
00131 ulevel = chartolevel(channel->GetPrefixChar(user));
00132 }
00133
00134
00135 if (ServerInstance->ULine(target->server) || ServerInstance->ULine(target->nick.c_str()))
00136 {
00137 tlevel = chartolevel("U");
00138 }
00139 else if (target->GetExt(founderkey))
00140 {
00141 tlevel = chartolevel("~");
00142 }
00143 else if (target->GetExt(protectkey))
00144 {
00145 tlevel = chartolevel("&");
00146 }
00147 else
00148 {
00149 tlevel = chartolevel(channel->GetPrefixChar(target));
00150 }
00151
00152 hasnokicks = (ServerInstance->Modules->Find("m_nokicks.so") && channel->IsModeSet('Q'));
00153
00154
00155 if ((!IS_LOCAL(user)) || (!supportnokicks || !hasnokicks || (ulevel == ULINE)))
00156 {
00157
00158
00159
00160
00161
00162 if ((!IS_LOCAL(user)) || ((ulevel > PEON) && (ulevel >= tlevel) && (tlevel != OWNER)))
00163 {
00164
00165
00166
00167 std::string reasonparam("No reason given");
00168
00169
00170 if(parameters.size() > 2)
00171 {
00172
00173 irc::stringjoiner reason_join(" ", parameters, 2, parameters.size() - 1);
00174 reasonparam = reason_join.GetJoined();
00175 }
00176
00177
00178 reason = std::string("Removed by ") + user->nick + ": " + reasonparam;
00179
00180 channel->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s removed %s from the channel", channel->name.c_str(), user->nick.c_str(), target->nick.c_str());
00181 target->WriteServ("NOTICE %s :*** %s removed you from %s with the message: %s", target->nick.c_str(), user->nick.c_str(), channel->name.c_str(), reasonparam.c_str());
00182
00183 if (!channel->PartUser(target, reason))
00184 delete channel;
00185 }
00186 else
00187 {
00188 user->WriteServ( "NOTICE %s :*** You do not have access to /remove %s from %s", user->nick.c_str(), target->nick.c_str(), channel->name.c_str());
00189 return CMD_FAILURE;
00190 }
00191 }
00192 else
00193 {
00194
00195 user->WriteServ( "484 %s %s :Can't remove user %s from channel (+Q set)", user->nick.c_str(), channel->name.c_str(), target->nick.c_str());
00196 return CMD_FAILURE;
00197 }
00198
00199
00200 return CMD_SUCCESS;
00201 }
00202 };
00203
00206 class CommandRemove : public Command, public RemoveBase
00207 {
00208 public:
00209 CommandRemove(InspIRCd* Instance, bool& snk) : Command(Instance, "REMOVE", 0, 2), RemoveBase(Instance, snk)
00210 {
00211 this->source = "m_remove.so";
00212 syntax = "<nick> <channel> [<reason>]";
00213 TRANSLATE4(TR_NICK, TR_TEXT, TR_TEXT, TR_END);
00214 }
00215
00216 CmdResult Handle (const std::vector<std::string>& parameters, User *user)
00217 {
00218 return RemoveBase::Handle(parameters, user, false);
00219 }
00220 };
00221
00224 class CommandFpart : public Command, public RemoveBase
00225 {
00226 public:
00227 CommandFpart(InspIRCd* Instance, bool& snk) : Command(Instance, "FPART", 0, 2), RemoveBase(Instance, snk)
00228 {
00229 this->source = "m_remove.so";
00230 syntax = "<channel> <nick> [<reason>]";
00231 }
00232
00233 CmdResult Handle (const std::vector<std::string>& parameters, User *user)
00234 {
00235 return RemoveBase::Handle(parameters, user, true);
00236 }
00237 };
00238
00239 class ModuleRemove : public Module
00240 {
00241 CommandRemove* mycommand;
00242 CommandFpart* mycommand2;
00243 bool supportnokicks;
00244
00245
00246 public:
00247 ModuleRemove(InspIRCd* Me)
00248 : Module(Me)
00249 {
00250 mycommand = new CommandRemove(ServerInstance, supportnokicks);
00251 mycommand2 = new CommandFpart(ServerInstance, supportnokicks);
00252 ServerInstance->AddCommand(mycommand);
00253 ServerInstance->AddCommand(mycommand2);
00254 OnRehash(NULL,"");
00255 Implementation eventlist[] = { I_On005Numeric, I_OnRehash };
00256 ServerInstance->Modules->Attach(eventlist, this, 2);
00257 }
00258
00259
00260 virtual void On005Numeric(std::string &output)
00261 {
00262 output.append(" REMOVE");
00263 }
00264
00265 virtual void OnRehash(User* user, const std::string&)
00266 {
00267 ConfigReader conf(ServerInstance);
00268 supportnokicks = conf.ReadFlag("remove", "supportnokicks", 0);
00269 }
00270
00271 virtual ~ModuleRemove()
00272 {
00273 }
00274
00275 virtual Version GetVersion()
00276 {
00277 return Version("$Id: m_remove.cpp 10291 2008-08-25 20:35:51Z w00t $", VF_COMMON | VF_VENDOR, API_VERSION);
00278 }
00279
00280 };
00281
00282 MODULE_INIT(ModuleRemove)