/* +------------------------------------+
* | Inspire Internet Relay Chat Daemon |
* +------------------------------------+
*
* InspIRCd: (C) 2002-2011 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 "command_parse.h"
#include "sql.h"
class UserQuery : public SQLQuery
{
public:
const std::string uid;
reference<ConfigTag> 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<std::string, std::string> items;
user->PopulateInfoMap(items);
if (!format.empty())
{
SQLEntries result;
std::vector<std::string> cols;
res.GetCols(cols);
while (res.GetRow(result))
{
std::map<std::string, std::string> 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<std::string, std::string> items;
user->PopulateInfoMap(items);
items.insert(std::make_pair("msg", error.str));
user->SendText(MapFormatSubst(format, items));
}
}
};
class SQLCommand : public Command
{
public:
reference<ConfigTag> tag;
dynamic_reference<SQLProvider> 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<std::string> ¶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<SQLCommand*> cmds;
void init()
{
// everything is in readconfig
}
void ReadConfig(ConfigReadStatus& status)
{
for(std::vector<SQLCommand*>::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<SQLCommand*>::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)