/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2010 InspIRCd Development Team * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "sql.h" class UserQuery : public SQLQuery { public: const std::string uid; reference tag; UserQuery(Module* me, const std::string& u, ConfigTag* q) : SQLQuery(me), uid(u), tag(q) { } void OnResult(SQLResult& res) { User* user = ServerInstance->FindUUID(uid); if (!user) return; int rows = res.Rows(); std::string format = tag->getString("rowformat"); std::map items; user->PopulateInfoMap(items); if (!format.empty()) { SQLEntries result; std::vector cols; res.GetCols(cols); while (res.GetRow(result)) { std::map row(items); for(unsigned int i=0; i < cols.size(); i++) { if (result[i].nul) continue; row.insert(std::make_pair(cols[i], result[i].value)); } user->SendText(MapFormatSubst(format, row)); } } format = tag->getString("resultformat"); if (!format.empty()) { items.insert(std::make_pair("rows", ConvToStr(rows))); user->SendText(MapFormatSubst(format, items)); } } void OnError(SQLerror& error) { User* user = ServerInstance->FindUUID(uid); if (!user) return; std::string format = tag->getString("errorformat", ":$server NOTICE $nick :SQL command failed: $msg"); if (!format.empty()) { std::map items; user->PopulateInfoMap(items); items.insert(std::make_pair("msg", error.str)); user->SendText(MapFormatSubst(format, items)); } } }; class SQLCommand : public Command { public: reference tag; dynamic_reference db; SQLCommand(Module* Parent, ConfigTag* Tag) : Command(Parent, Tag->getString("name")), tag(Tag), db("SQL/" + Tag->getString("dbid")) { syntax = Tag->getString("syntax"); if (Tag->getBool("operonly", true)) flags_needed = 'o'; if (!db) throw CoreException("Could not find database"); } CmdResult Handle(const std::vector ¶meters, User *user) { if (!db) return CMD_FAILURE; ParamM userinfo; user->PopulateInfoMap(userinfo); for(unsigned int i=0; i < parameters.size(); i++) userinfo.insert(std::make_pair(ConvToStr(i + 1), parameters[i])); std::string fmt = tag->getString("queryformat"); db->submit(new UserQuery(creator, user->uuid, tag), fmt, userinfo); return CMD_SUCCESS; } }; class ModuleSQLCommand : public Module { public: std::vector cmds; void init() { // everything is in readconfig } void ReadConfig(ConfigReadStatus& status) { for(std::vector::iterator i = cmds.begin(); i != cmds.end(); i++) { ServerInstance->Parser->RemoveCommand(*i); delete *i; } cmds.clear(); ConfigTagList tags = ServerInstance->Config->GetTags("sqlcommand"); for(ConfigIter i = tags.first; i != tags.second; i++) { ConfigTag* tag = i->second; SQLCommand* cmd = NULL; try { cmd = new SQLCommand(this, tag); ServerInstance->Modules->AddService(*cmd); cmds.push_back(cmd); } catch (CoreException& e) { status.ReportError(tag, e.err.c_str(), false); delete cmd; } } } ~ModuleSQLCommand() { for(std::vector::iterator i = cmds.begin(); i != cmds.end(); i++) delete *i; } Version GetVersion() { return Version("Add commands that execute arbitrary SQL queries", VF_VENDOR); } }; MODULE_INIT(ModuleSQLCommand)