From 1478b5bbd7ecc99c3ceefc0396845ebb0608d331 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 3 Sep 2011 01:10:12 -0400 Subject: [PATCH] Added chanserv/log --- data/chanserv.example.conf | 10 ++ include/logger.h | 7 ++ include/modules.h | 7 +- include/regchannel.h | 14 +++ include/services.h | 2 - modules/commands/cs_access.cpp | 2 +- modules/commands/cs_log.cpp | 198 ++++++++++++++++++++++++++++++++ modules/database/db_plain.cpp | 20 ++++ modules/protocol/bahamut.cpp | 5 - modules/protocol/inspircd-ts6.h | 5 - modules/protocol/inspircd11.cpp | 5 - modules/protocol/plexus.cpp | 5 - modules/protocol/ratbox.cpp | 5 - modules/protocol/unreal.cpp | 7 -- src/access.cpp | 4 + src/bots.cpp | 4 +- src/logger.cpp | 113 ++++++++++++------ src/protocol.cpp | 10 -- 18 files changed, 340 insertions(+), 83 deletions(-) create mode 100644 modules/commands/cs_log.cpp diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index d9bd6eb0c..7992fef9d 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -438,6 +438,16 @@ command { service = "ChanServ"; name = "K"; command = "chanserv/kick"; } module { name = "cs_list" } command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; permission = "chanserv/list"; } +/* + * cs_log + * + * Provides the command chanserv/log. + * + * Use for configuring what actions on channels are logged and where. + */ +module { name = "cs_log" } +command { service = "ChanServ"; name = "LOG"; command = "chanserv/log"; } + /* * cs_mode * diff --git a/include/logger.h b/include/logger.h index 423e096d3..5f611b277 100644 --- a/include/logger.h +++ b/include/logger.h @@ -35,6 +35,11 @@ class CoreExport Log { public: BotInfo *bi; + User *u; + Command *c; + Channel *chan; + ChannelInfo *ci; + Server *s; LogType Type; Anope::string Category; std::list Sources; @@ -59,6 +64,8 @@ class CoreExport Log ~Log(); + Anope::string BuildPrefix() const; + template Log &operator<<(T val) { this->buf << val; diff --git a/include/modules.h b/include/modules.h index 600b3ce8c..5d2e7247f 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1019,6 +1019,11 @@ class CoreExport Module : public Extensible * @param msg The message */ virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg) { } + + /** Called when a message is logged + * @param l The log message + */ + virtual void OnLog(Log *l) { } }; /** Implementation-specific flags which may be set in ModuleManager::Attach() @@ -1072,7 +1077,7 @@ enum Implementation I_OnServerQuit, I_OnTopicUpdated, I_OnEncrypt, I_OnDecrypt, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, - I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg, + I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg, I_OnLog, I_END }; diff --git a/include/regchannel.h b/include/regchannel.h index 1d071fb0f..017b93afe 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -96,6 +96,19 @@ struct ModeLock ModeLock(bool s, ChannelModeName n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime) : set(s), name(n), param(p), setter(se), created(c) { } }; +struct LogSetting +{ + /* Our service name of the command */ + Anope::string service_name; + /* The name of the client the command is on */ + Anope::string command_service; + /* Name of the command to the user, can have spaces */ + Anope::string command_name; + Anope::string method, extra; + Anope::string creator; + time_t created; +}; + class CoreExport ChannelInfo : public Extensible, public Flags { private: @@ -108,6 +121,7 @@ class CoreExport ChannelInfo : public Extensible, public Flags ModeList; ModeList mode_locks; + std::vector log_settings; /** Default constructor * @param chname The channel name diff --git a/include/services.h b/include/services.h index 84776d064..9ed5e2ba3 100644 --- a/include/services.h +++ b/include/services.h @@ -805,7 +805,6 @@ class CoreExport IRCDProto virtual void SendModeInternal(const BotInfo *, const Channel *, const Anope::string &) = 0; virtual void SendModeInternal(const BotInfo *, const User *, const Anope::string &) = 0; virtual void SendKickInternal(const BotInfo *, const Channel *, const User *, const Anope::string &) = 0; - virtual void SendNoticeChanopsInternal(const BotInfo *bi, const Channel *, const Anope::string &) = 0; virtual void SendMessageInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf); virtual void SendNoticeInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &msg); virtual void SendPrivmsgInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf); @@ -827,7 +826,6 @@ class CoreExport IRCDProto virtual void SendMode(const BotInfo *bi, const User *u, const char *fmt, ...); virtual void SendClientIntroduction(const User *u) = 0; virtual void SendKick(const BotInfo *bi, const Channel *chan, const User *user, const char *fmt, ...); - virtual void SendNoticeChanops(const BotInfo *bi, const Channel *dest, const char *fmt, ...); virtual void SendMessage(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); virtual void SendNotice(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); virtual void SendAction(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...); diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 8c3e1a1ca..c5f8313f0 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -319,7 +319,7 @@ class CommandCSAccess : public Command FOREACH_MOD(I_OnAccessAdd, OnAccessAdd(ci, u, access)); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level; + Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " as level " << level; source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->mask.c_str(), ci->name.c_str(), level); return; diff --git a/modules/commands/cs_log.cpp b/modules/commands/cs_log.cpp new file mode 100644 index 000000000..dc7fe0999 --- /dev/null +++ b/modules/commands/cs_log.cpp @@ -0,0 +1,198 @@ +/* ChanServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "memoserv.h" + +class CommandCSLog : public Command +{ +public: + CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4) + { + this->SetDesc(_("Configures channel logging settings")); + this->SetSyntax(_("\037channel\037")); + this->SetSyntax(_("\037channel\037 \037command\037 [\037method\037]")); + } + + void Execute(CommandSource &source, const std::vector ¶ms) + { + const Anope::string &channel = params[0]; + + User *u = source.u; + ChannelInfo *ci = cs_findchan(channel); + if (ci == NULL) + source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); + else if (!ci->AccessFor(u).HasPriv("SET")) + source.Reply(ACCESS_DENIED); + else if (params.size() == 1) + { + if (ci->log_settings.empty()) + source.Reply(_("There currently are no logging configurations for %s."), ci->name.c_str()); + else + { + source.Reply(_("Log list for %s:"), ci->name.c_str()); + for (unsigned i = 0; i < ci->log_settings.size(); ++i) + { + LogSetting &log = ci->log_settings[i]; + + source.Reply("%d: %s %s, %s %s", i + 1, log.command_service.c_str(), log.command_name.c_str(), log.method.c_str(), log.extra.c_str()); + } + } + } + else if (params.size() > 2) + { + const Anope::string &command = params[1]; + const Anope::string &method = params[2]; + const Anope::string &extra = params.size() > 3 ? params[3] : ""; + + size_t sl = command.find('/'); + if (sl == Anope::string::npos) + { + source.Reply(_("%s is not a valid command."), command.c_str()); + return; + } + + Anope::string service = command.substr(0, sl), + command_name = command.substr(sl + 1); + BotInfo *bi = findbot(service); + + if (bi == NULL || bi->commands.count(command_name) == 0) + { + source.Reply(_("%s is not a valid command."), command.c_str()); + return; + } + + service_reference c_service(bi->commands[command_name].name); + if (!c_service) + { + source.Reply(_("%s is not a valid command."), command.c_str()); + return; + } + + if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO")) + { + source.Reply(_("%s is not a valid logging method."), method.c_str()); + return; + } + + for (unsigned i = 0; i < extra.length(); ++i) + if (ModeManager::GetStatusChar(extra[i]) == 0) + { + source.Reply(_("%c is an unknown status mode."), extra[i]); + return; + } + + for (unsigned i = ci->log_settings.size(); i > 0; --i) + { + LogSetting &log = ci->log_settings[i - 1]; + + if (log.service_name == bi->commands[command_name].name && log.method.equals_ci(method)) + { + if (log.extra == extra) + { + ci->log_settings.erase(ci->log_settings.begin() + i - 1); + source.Reply(_("Logging for command %s on %s with method %s%s has been removed."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : extra.c_str()); + } + else + { + log.extra = extra; + source.Reply(_("Logging changed for command %s on %s, using log method %s %s"), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.c_str()); + } + return; + } + } + + LogSetting log; + log.service_name = bi->commands[command_name].name; + log.command_service = bi->nick; + log.command_name = command_name; + log.method = method; + log.extra = extra; + log.created = Anope::CurTime; + log.creator = u->nick; + + ci->log_settings.push_back(log); + Log(LOG_COMMAND, u, this, ci) << command << " " << method << " " << extra; + + source.Reply(_("Logging is now active for command %s on %s, using log method %s %s"), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.c_str()); + } + else + this->OnSyntaxError(source, ""); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("The %s command allows users to configure logging settings\n" + "for their channel. If no parameters are given this command\n" + "lists the current logging methods in place for this channel.\n" + " \n" + "Otherwise, \037command\037 must be a command name, and \037method\037\n" + "is one of the following logging methods:\n" + " \n" + " MESSAGE [status], NOTICE [status], MEMO\n" + " \n" + "Which are used to message, notice, and memo the channel respectively.\n" + "With MESSAGE or NOTICE you must have a service bot assigned to and joined\n" + "to your channel. Status may be a channel status such as @ or +.\n" + " \n" + "To remove a logging method use the same syntax as you would to add it.\n" + " \n" + "Example:\n" + " %s #anope chanserv/access MESSAGE @%\n" + " Would message any channel operators whenever someone used the\n" + " ACCESS command on ChanServ on the channel."), + source.command.c_str(), source.command.c_str()); + return true; + } +}; + +class CSLog : public Module +{ + CommandCSLog commandcslog; + + public: + CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcslog(this) + { + this->SetAuthor("Anope"); + + Implementation i[] = { I_OnLog }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + } + + void OnLog(Log *l) + { + if (l->Type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced()) + return; + + for (unsigned i = l->ci->log_settings.size(); i > 0; --i) + { + LogSetting &log = l->ci->log_settings[i - 1]; + + if (log.service_name == l->c->name) + { + Anope::string buffer = l->u->nick + " used " + log.command_name + " " + l->buf.str(); + + if (log.method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL) + ircdproto->SendPrivmsg(l->ci->bi, log.extra + l->ci->c->name, "%s", buffer.c_str()); + else if (log.method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL) + ircdproto->SendNotice(l->ci->bi, log.extra + l->ci->c->name, "%s", buffer.c_str()); + else if (log.method.equals_ci("MEMO") && memoserv && l->ci->WhoSends() != NULL) + memoserv->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true); + } + } + } +}; + +MODULE_INIT(CSLog) diff --git a/modules/database/db_plain.cpp b/modules/database/db_plain.cpp index dfcddfcfe..fffa02c87 100644 --- a/modules/database/db_plain.cpp +++ b/modules/database/db_plain.cpp @@ -561,6 +561,20 @@ class DBPlain : public Module ak->SetFlag(AK_ISNICK); } + else if (key.equals_ci("LOG")) + { + LogSetting l; + + l.service_name = params[0]; + l.command_service = params[1]; + l.command_name = params[2]; + l.method = params[3]; + l.creator = params[4]; + l.created = params[5].is_pos_number_only() ? convertTo(params[5]) : Anope::CurTime; + l.extra = params.size() > 6 ? params[6] : ""; + + ci->log_settings.push_back(l); + } else if (key.equals_ci("MLOCK")) { bool set = params[0] == "1" ? true : false; @@ -785,6 +799,12 @@ class DBPlain : public Module db_buffer << ci->GetAkick(k)->reason; db_buffer << endl; } + for (unsigned k = 0, end = ci->log_settings.size(); k < end; ++k) + { + LogSetting &l = ci->log_settings[k]; + + db_buffer << "MD LOG " << l.service_name << " " << l.command_service << " " << l.command_name << " " << l.method << " " << l.creator << " " << l.created << " " << l.extra << endl; + } { std::vector mlocks; if (ci->GetExtRegular("db_mlock", mlocks)) diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 9aae47086..008c4dd32 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -201,11 +201,6 @@ class BahamutIRCdProto : public IRCDProto send_cmd("", "BURST 0"); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf) { if (!buf.empty()) diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index bb2c1cc9a..3603555c4 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -117,11 +117,6 @@ class InspIRCdTS6Proto : public IRCDProto send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), user->nick.c_str()); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(Config->Numeric, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - /* SERVER services-dev.chatspike.net password 0 :Description here */ void SendServer(const Server *server) { diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 2a1b4e435..8b51c93a6 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -150,11 +150,6 @@ class InspIRCdProto : public IRCDProto send_cmd(source->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), user->nick.c_str()); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(Config->ServerName, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - /* SERVER services-dev.chatspike.net password 0 :Description here */ void SendServer(const Server *server) { diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 8bc3e21b9..f31bfea6a 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -216,11 +216,6 @@ class PlexusProto : public IRCDProto send_cmd(bi->GetUID(), "KICK %s %s", chan->name.c_str(), user->GetUID().c_str()); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - /* INVITE */ void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick) { diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index d4208760e..957564890 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -200,11 +200,6 @@ class RatboxProto : public IRCDProto send_cmd(bi->GetUID(), "KICK %s %s", chan->name.c_str(), user->GetUID().c_str()); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd("", "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - /* INVITE */ void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick) { diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index cbb23dcc5..cb6ec2091 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -154,13 +154,6 @@ class UnrealIRCdProto : public IRCDProto send_cmd(source->nick, "H %s %s", chan->name.c_str(), user->nick.c_str()); } - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - if (buf.empty()) - return; - send_cmd(source->nick, "B @%s :%s", dest->name.c_str(), buf.c_str()); - } - /* SERVER name hop descript */ /* Unreal 3.2 actually sends some info about itself in the descript area */ void SendServer(const Server *server) diff --git a/src/access.cpp b/src/access.cpp index 49636cd04..09310d441 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -89,7 +89,11 @@ void PrivilegeManager::Init() AddPrivilege(Privilege("ASSIGN", _("Allowed to assign/unassign a bot"))); AddPrivilege(Privilege("MEMO", _("Allowed to read channel memos"))); AddPrivilege(Privilege("ACCESS_CHANGE", _("Allowed to modify the access list"))); + AddPrivilege(Privilege("PROTECT", _("Allowed to (de)protect users"))); AddPrivilege(Privilege("PROTECTME", _("Allowed to (de)protect him/herself"))); + AddPrivilege(Privilege("SET", _("Allowed to set channel settings"))); + AddPrivilege(Privilege("OWNERME", _("Allowed to (de)owner him/herself"))); + AddPrivilege(Privilege("OWNER", _("Allowed to (de)owner users"))); } std::vector &PrivilegeManager::GetPrivileges() diff --git a/src/bots.cpp b/src/bots.cpp index f3c0af4fd..25ead29f5 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -156,7 +156,7 @@ void BotInfo::Join(Channel *c, ChannelStatus *status) /* Should we be invited? */ if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit)) - ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); + ircdproto->SendNotice(this, "@" + c->name, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); ModeManager::ProcessModes(); } @@ -229,7 +229,7 @@ void BotInfo::OnMessage(User *u, const Anope::string &message) if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) { u->SendMessage(this, NICK_IDENTIFY_REQUIRED); - Log(LOG_COMMAND, "denied", this) << "Access denied for unregistered user " << u->GetMask() << " with command " << c->name; + Log(LOG_NORMAL, "denied", this) << "Access denied for unregistered user " << u->GetMask() << " with command " << c->name; return; } diff --git a/src/logger.cpp b/src/logger.cpp index dbaba975a..d21a63e5a 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -63,7 +63,7 @@ Anope::string LogFile::GetName() const return this->filename; } -Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type(type), Category(category) +Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), u(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(type), Category(category) { if (!bi) bi = Config ? findbot(Config->Global) : NULL; @@ -71,7 +71,7 @@ Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type( this->Sources.push_back(bi->nick); } -Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) +Log::Log(LogType type, User *_u, Command *_c, ChannelInfo *_ci) : u(_u), c(_c), chan(NULL), ci(_ci), s(NULL), Type(type) { if (!u || !c) throw CoreException("Invalid pointers passed to Log::Log"); @@ -92,22 +92,11 @@ Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) this->Sources.push_back(c->name); if (ci) this->Sources.push_back(ci->name); - - if (type == LOG_ADMIN) - buf << "ADMIN: "; - else if (type == LOG_OVERRIDE) - buf << "OVERRIDE: "; - else - buf << "COMMAND: "; - Anope::string cname = sl != Anope::string::npos ? c->name.substr(sl + 1) : c->name; - buf << u->GetMask() << " used " << cname << " "; - if (ci) - buf << "on " << ci->name << " "; } -Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) +Log::Log(User *_u, Channel *ch, const Anope::string &category) : u(_u), c(NULL), chan(ch), ci(chan ? chan->ci : NULL), s(NULL), Type(LOG_CHANNEL) { - if (!c) + if (!chan) throw CoreException("Invalid pointers passed to Log::Log"); this->bi = Config ? findbot(Config->ChanServ) : NULL; @@ -116,16 +105,10 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) this->Sources.push_back(this->bi->nick); if (u) this->Sources.push_back(u->nick); - this->Sources.push_back(c->name); - - buf << "CHANNEL: "; - if (u) - buf << u->GetMask() << " " << this->Category << " " << c->name << " "; - else - buf << this->Category << " " << c->name << " "; + this->Sources.push_back(chan->name); } -Log::Log(User *u, const Anope::string &category) : bi(NULL), Type(LOG_USER), Category(category) +Log::Log(User *_u, const Anope::string &category) : bi(NULL), u(_u), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_USER), Category(category) { if (!u) throw CoreException("Invalid pointers passed to Log::Log"); @@ -134,11 +117,9 @@ Log::Log(User *u, const Anope::string &category) : bi(NULL), Type(LOG_USER), Cat if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(u->nick); - - buf << "USERS: " << u->GetMask() << " "; } -Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), Category(category) +Log::Log(Server *serv, const Anope::string &category) : bi(NULL), u(NULL), c(NULL), chan(NULL), ci(NULL), s(serv), Type(LOG_SERVER), Category(category) { if (!s) throw CoreException("Invalid pointer passed to Log::Log"); @@ -149,11 +130,9 @@ Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(s->GetName()); - - buf << "SERVER: " << s->GetName() << " (" << s->GetDescription() << ") "; } -Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_NORMAL), Category(category) +Log::Log(BotInfo *b, const Anope::string &category) : bi(b), u(NULL), c(NULL), chan(NULL), ci(NULL), s(NULL), Type(LOG_NORMAL), Category(category) { if (!this->bi) this->bi = Config ? findbot(Config->Global) : NULL; @@ -164,16 +143,79 @@ Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_NORMAL), C Log::~Log() { if (nofork && debug && this->Type >= LOG_NORMAL && this->Type <= LOG_DEBUG + debug - 1) - std::cout << GetTimeStamp() << " Debug: " << this->buf.str() << std::endl; + std::cout << GetTimeStamp() << " Debug: " << this->BuildPrefix() << this->buf.str() << std::endl; else if (nofork && this->Type <= LOG_TERMINAL) - std::cout << GetTimeStamp() << " " << this->buf.str() << std::endl; + std::cout << GetTimeStamp() << " " << this->BuildPrefix() << this->buf.str() << std::endl; else if (this->Type == LOG_TERMINAL) - std::cout << this->buf.str() << std::endl; + std::cout << this->BuildPrefix() << this->buf.str() << std::endl; for (unsigned i = 0; Config && i < Config->LogInfos.size(); ++i) { LogInfo *l = Config->LogInfos[i]; l->ProcessMessage(this); } + FOREACH_MOD(I_OnLog, OnLog(this)); +} + +Anope::string Log::BuildPrefix() const +{ + Anope::string buffer; + + switch (this->Type) + { + case LOG_ADMIN: + { + buffer += "ADMIN: "; + size_t sl = this->c->name.find('/'); + Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name; + buffer += this->u->GetMask() + " used " + cname + " "; + if (this->ci) + buffer += "on " + this->ci->name + " "; + break; + } + case LOG_OVERRIDE: + { + buffer += "OVERRIDE: "; + size_t sl = this->c->name.find('/'); + Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name; + buffer += this->u->GetMask() + " used " + cname + " "; + if (this->ci) + buffer += "on " + this->ci->name + " "; + break; + } + case LOG_COMMAND: + { + buffer += "COMMAND: "; + size_t sl = this->c->name.find('/'); + Anope::string cname = sl != Anope::string::npos ? this->c->name.substr(sl + 1) : this->c->name; + buffer += this->u->GetMask() + " used " + cname + " "; + if (this->ci) + buffer += "on " + this->ci->name + " "; + break; + } + case LOG_CHANNEL: + { + buffer += "CHANNEL: "; + if (this->u) + buffer += this->u->GetMask() + " " + this->Category + " " + this->chan->name + " "; + else + buffer += this->Category + " " + this->chan->name + " "; + break; + } + case LOG_USER: + { + buffer += "USERS: " + this->u->GetMask() + " "; + break; + } + case LOG_SERVER: + { + buffer += "SERVER: " + this->s->GetName() + " (" + this->s->GetDescription() + ") "; + break; + } + default: + break; + } + + return buffer; } LogInfo::LogInfo(int logage, bool rawio, bool ldebug) : LogAge(logage), RawIO(rawio), Debug(ldebug) @@ -291,6 +333,7 @@ void LogInfo::ProcessMessage(const Log *l) for (std::list::iterator it = this->Targets.begin(), it_end = this->Targets.end(); it != it_end; ++it) { const Anope::string &target = *it; + Anope::string buffer = l->BuildPrefix() + l->buf.str(); if (target[0] == '#') { @@ -299,14 +342,14 @@ void LogInfo::ProcessMessage(const Log *l) Channel *c = findchan(target); if (!c || !l->bi) continue; - ircdproto->SendPrivmsg(l->bi, c->name, "%s", l->buf.str().c_str()); + ircdproto->SendPrivmsg(l->bi, c->name, "%s", buffer.c_str()); } } else if (target == "globops") { if (UplinkSock && l->bi && l->Type <= LOG_NORMAL && Me && Me->IsSynced()) { - ircdproto->SendGlobops(l->bi, "%s", l->buf.str().c_str()); + ircdproto->SendGlobops(l->bi, "%s", buffer.c_str()); } } else @@ -364,7 +407,7 @@ void LogInfo::ProcessMessage(const Log *l) } if (log) - log->stream << GetTimeStamp() << " " << l->buf.str() << std::endl; + log->stream << GetTimeStamp() << " " << buffer << std::endl; } } } diff --git a/src/protocol.cpp b/src/protocol.cpp index 7e9fca07a..9ca6c1500 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -119,16 +119,6 @@ void IRCDProto::SendKick(const BotInfo *bi, const Channel *chan, const User *use SendKickInternal(bi, chan, user, buf); } -void IRCDProto::SendNoticeChanops(const BotInfo *bi, const Channel *dest, const char *fmt, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, fmt); - vsnprintf(buf, BUFSIZE - 1, fmt, args); - va_end(args); - SendNoticeChanopsInternal(bi, dest, buf); -} - void IRCDProto::SendMessage(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...) { va_list args;