anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
command.cpp (8200B)
1 /* 2 * 3 * (C) 2008-2011 Robin Burchell <w00t@inspircd.org> 4 * (C) 2008-2022 Anope Team <team@anope.org> 5 * 6 * Please read COPYING and README for further details. 7 */ 8 9 #include "services.h" 10 #include "commands.h" 11 #include "users.h" 12 #include "language.h" 13 #include "config.h" 14 #include "bots.h" 15 #include "opertype.h" 16 #include "access.h" 17 #include "regchannel.h" 18 #include "channels.h" 19 20 CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r), 21 c(NULL), service(bi) 22 { 23 } 24 25 const Anope::string &CommandSource::GetNick() const 26 { 27 return this->nick; 28 } 29 30 User *CommandSource::GetUser() 31 { 32 return this->u; 33 } 34 35 NickCore *CommandSource::GetAccount() 36 { 37 return this->nc; 38 } 39 40 AccessGroup CommandSource::AccessFor(ChannelInfo *ci) 41 { 42 if (this->u) 43 return ci->AccessFor(this->u); 44 else if (this->nc) 45 return ci->AccessFor(this->nc); 46 else 47 return AccessGroup(); 48 } 49 50 bool CommandSource::IsFounder(ChannelInfo *ci) 51 { 52 if (this->u) 53 return ::IsFounder(this->u, ci); 54 else if (this->nc) 55 return *this->nc == ci->GetFounder(); 56 return false; 57 } 58 59 bool CommandSource::HasCommand(const Anope::string &cmd) 60 { 61 if (this->u) 62 return this->u->HasCommand(cmd); 63 else if (this->nc && this->nc->o) 64 return this->nc->o->ot->HasCommand(cmd); 65 return false; 66 } 67 68 bool CommandSource::HasPriv(const Anope::string &cmd) 69 { 70 if (this->u) 71 return this->u->HasPriv(cmd); 72 else if (this->nc && this->nc->o) 73 return this->nc->o->ot->HasPriv(cmd); 74 return false; 75 } 76 77 bool CommandSource::IsServicesOper() 78 { 79 if (this->u) 80 return this->u->IsServicesOper(); 81 else if (this->nc) 82 return this->nc->IsServicesOper(); 83 return false; 84 } 85 86 bool CommandSource::IsOper() 87 { 88 if (this->u) 89 return this->u->HasMode("OPER"); 90 else if (this->nc) 91 return this->nc->IsServicesOper(); 92 return false; 93 } 94 95 void CommandSource::Reply(const char *message, ...) 96 { 97 va_list args; 98 char buf[4096]; // Messages can be really big. 99 100 const char *translated_message = Language::Translate(this->nc, message); 101 102 va_start(args, message); 103 vsnprintf(buf, sizeof(buf), translated_message, args); 104 105 this->Reply(Anope::string(buf)); 106 107 va_end(args); 108 } 109 110 void CommandSource::Reply(const Anope::string &message) 111 { 112 const char *translated_message = Language::Translate(this->nc, message.c_str()); 113 114 sepstream sep(translated_message, '\n', true); 115 Anope::string tok; 116 while (sep.GetToken(tok)) 117 this->reply->SendMessage(this->service, tok); 118 } 119 120 Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o) 121 { 122 allow_unregistered = require_user = false; 123 } 124 125 Command::~Command() 126 { 127 } 128 129 void Command::SetDesc(const Anope::string &d) 130 { 131 this->desc = d; 132 } 133 134 void Command::ClearSyntax() 135 { 136 this->syntax.clear(); 137 } 138 139 void Command::SetSyntax(const Anope::string &s) 140 { 141 this->syntax.push_back(s); 142 } 143 144 void Command::SendSyntax(CommandSource &source) 145 { 146 Anope::string s = Language::Translate(source.GetAccount(), _("Syntax")); 147 if (!this->syntax.empty()) 148 { 149 source.Reply("%s: \002%s %s\002", s.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[0].c_str())); 150 Anope::string spaces(s.length(), ' '); 151 for (unsigned i = 1, j = this->syntax.size(); i < j; ++i) 152 source.Reply("%s \002%s %s\002", spaces.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[i].c_str())); 153 } 154 else 155 source.Reply("%s: \002%s\002", s.c_str(), source.command.c_str()); 156 } 157 158 bool Command::AllowUnregistered() const 159 { 160 return this->allow_unregistered; 161 } 162 163 void Command::AllowUnregistered(bool b) 164 { 165 this->allow_unregistered = b; 166 } 167 168 bool Command::RequireUser() const 169 { 170 return this->require_user; 171 } 172 173 void Command::RequireUser(bool b) 174 { 175 this->require_user = b; 176 } 177 178 const Anope::string Command::GetDesc(CommandSource &) const 179 { 180 return this->desc; 181 } 182 183 void Command::OnServHelp(CommandSource &source) 184 { 185 source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str())); 186 } 187 188 bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; } 189 190 void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand) 191 { 192 this->SendSyntax(source); 193 bool has_help = source.service->commands.find("HELP") != source.service->commands.end(); 194 if (has_help) 195 source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str()); 196 } 197 198 void Command::Run(CommandSource &source, const Anope::string &message) 199 { 200 std::vector<Anope::string> params; 201 spacesepstream(message).GetTokens(params); 202 bool has_help = source.service->commands.find("HELP") != source.service->commands.end(); 203 204 CommandInfo::map::const_iterator it = source.service->commands.end(); 205 unsigned count = 0; 206 for (unsigned max = params.size(); it == source.service->commands.end() && max > 0; --max) 207 { 208 Anope::string full_command; 209 for (unsigned i = 0; i < max; ++i) 210 full_command += " " + params[i]; 211 full_command.erase(full_command.begin()); 212 213 ++count; 214 it = source.service->commands.find(full_command); 215 } 216 217 if (it == source.service->commands.end()) 218 { 219 if (has_help) 220 source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str()); 221 else 222 source.Reply(_("Unknown command \002%s\002."), message.c_str()); 223 return; 224 } 225 226 const CommandInfo &info = it->second; 227 ServiceReference<Command> c("Command", info.name); 228 if (!c) 229 { 230 if (has_help) 231 source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str()); 232 else 233 source.Reply(_("Unknown command \002%s\002."), message.c_str()); 234 Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!"; 235 return; 236 } 237 238 for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i) 239 params.erase(params.begin()); 240 241 while (c->max_params > 0 && params.size() > c->max_params) 242 { 243 params[c->max_params - 1] += " " + params[c->max_params]; 244 params.erase(params.begin() + c->max_params); 245 } 246 247 c->Run(source, it->first, info, params); 248 } 249 250 void Command::Run(CommandSource &source, const Anope::string &cmdname, const CommandInfo &info, std::vector<Anope::string> ¶ms) 251 { 252 if (this->RequireUser() && !source.GetUser()) 253 return; 254 255 // Command requires registered users only 256 if (!this->AllowUnregistered() && !source.nc) 257 { 258 source.Reply(NICK_IDENTIFY_REQUIRED); 259 if (source.GetUser()) 260 Log(LOG_NORMAL, "access_denied_unreg", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << cmdname; 261 return; 262 } 263 264 source.command = cmdname; 265 source.permission = info.permission; 266 267 EventReturn MOD_RESULT; 268 FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, this, params)); 269 if (MOD_RESULT == EVENT_STOP) 270 return; 271 272 if (params.size() < this->min_params) 273 { 274 this->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : ""); 275 return; 276 } 277 278 // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED 279 if (!info.permission.empty() && !source.HasCommand(info.permission)) 280 { 281 source.Reply(ACCESS_DENIED); 282 if (source.GetUser()) 283 Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << cmdname; 284 return; 285 } 286 287 this->Execute(source, params); 288 FOREACH_MOD(OnPostCommand, (source, this, params)); 289 } 290 291 bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo* &bot, Anope::string &name) 292 { 293 bot = NULL; 294 295 for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) 296 { 297 BotInfo *bi = it->second; 298 299 for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) 300 { 301 const Anope::string &c_name = cit->first; 302 const CommandInfo &info = cit->second; 303 304 if (info.name != command_service) 305 continue; 306 307 bot = bi; 308 name = c_name; 309 return true; 310 } 311 } 312 313 return false; 314 }