summaryrefslogtreecommitdiff
path: root/src/operserv.c
diff options
context:
space:
mode:
authorAdam <Adam@Anope.org>2010-05-24 23:36:40 -0500
committerAdam <Adam@anope.org>2010-06-18 21:04:05 -0400
commit2fba686904e6f78ebab35df171c5757afeebf05d (patch)
tree523782bccc479606206f271cd6708b2f70fe8278 /src/operserv.c
parent3a2c2a916a26f4fa1844e71a9f1c2fc25337fd2b (diff)
Burned slist, rewrote operservs XLine code
Diffstat (limited to 'src/operserv.c')
-rw-r--r--src/operserv.c1325
1 files changed, 549 insertions, 776 deletions
diff --git a/src/operserv.c b/src/operserv.c
index fda5f5fd8..c8432b9f9 100644
--- a/src/operserv.c
+++ b/src/operserv.c
@@ -15,27 +15,10 @@
#include "modules.h"
#include "language.h"
-/*************************************************************************/
-
-/* AKILL, SGLINE, SQLINE and SZLINE lists */
-SList akills, sglines, sqlines, szlines;
-
-/*************************************************************************/
-
-static int is_akill_entry_equal(SList * slist, void *item1, void *item2);
-static void free_akill_entry(SList * slist, void *item);
-static int is_sgline_entry_equal(SList * slist, void *item1, void *item2);
-static void free_sgline_entry(SList * slist, void *item);
-static int is_sqline_entry_equal(SList * slist, void *item1, void *item2);
-static void free_sqline_entry(SList * slist, void *item);
-static int is_szline_entry_equal(SList * slist, void *item1, void *item2);
-static void free_szline_entry(SList * slist, void *item);
-
-/* News items */
std::vector<NewsItem *> News;
std::vector<std::bitset<32> > DefCon;
-int DefConModesSet = 0;
+bool DefConModesSet = false;
/* Defcon modes mlocked on */
Flags<ChannelModeName> DefConModesOn;
/* Defcon modes mlocked off */
@@ -43,20 +26,53 @@ Flags<ChannelModeName> DefConModesOff;
/* Map of Modesa and Params for DefCon */
std::map<ChannelModeName, std::string> DefConModesOnParams;
+XLineManager *SGLine, *SZLine, *SQLine, *SNLine;
+
+void os_init()
+{
+ ModuleManager::LoadModuleList(Config.OperServCoreModules);
+
+ /* Yes, these are in this order for a reason. Most violent->least violent. */
+ XLineManager::RegisterXLineManager(SGLine = new SGLineManager());
+ XLineManager::RegisterXLineManager(SZLine = new SZLineManager());
+ XLineManager::RegisterXLineManager(SQLine = new SQLineManager());
+ XLineManager::RegisterXLineManager(SNLine = new SNLineManager());
+}
+
+void operserv(User * u, char *buf)
+{
+ const char *cmd, *s;
+
+ Alog() << Config.s_OperServ << ": " << u->nick << ": " << buf;
+
+ cmd = strtok(buf, " ");
+ if (!cmd)
+ return;
+ else if (!stricmp(cmd, "\1PING")) {
+ if (!(s = strtok(NULL, ""))) {
+ s = "";
+ }
+ ircdproto->SendCTCP(OperServ, u->nick.c_str(), "PING %s", s);
+ }
+ else {
+ mod_run_cmd(OperServ, u, cmd);
+ }
+}
+
bool SetDefConParam(ChannelModeName Name, std::string &buf)
{
return DefConModesOnParams.insert(std::make_pair(Name, buf)).second;
}
-bool GetDefConParam(ChannelModeName Name, std::string *buf)
+bool GetDefConParam(ChannelModeName Name, std::string &buf)
{
std::map<ChannelModeName, std::string>::iterator it = DefConModesOnParams.find(Name);
- buf->clear();
+ buf.clear();
if (it != DefConModesOnParams.end())
{
- *buf = it->second;
+ buf = it->second;
return true;
}
@@ -73,83 +89,44 @@ void UnsetDefConParam(ChannelModeName Name)
}
}
-/*************************************************************************/
-
-void moduleAddOperServCmds();
-/*************************************************************************/
-
-/* Options for the lists */
-SListOpts akopts = { 0, NULL, &is_akill_entry_equal, &free_akill_entry };
-
-SListOpts sgopts = { 0, NULL, &is_sgline_entry_equal, &free_sgline_entry };
-SListOpts sqopts =
- { SLISTF_SORT, NULL, &is_sqline_entry_equal, &free_sqline_entry };
-SListOpts szopts = { 0, NULL, &is_szline_entry_equal, &free_szline_entry };
-
-/*************************************************************************/
-/* *INDENT-OFF* */
-void moduleAddOperServCmds() {
- ModuleManager::LoadModuleList(Config.OperServCoreModules);
+/** Check if a certain defcon option is currently in affect
+ * @param Level The level
+ * @return true and false
+ */
+bool CheckDefCon(DefconLevel Level)
+{
+ if (Config.DefConLevel)
+ return DefCon[Config.DefConLevel][Level];
+ return false;
}
-/* *INDENT-ON* */
-/*************************************************************************/
-/*************************************************************************/
-
-/* OperServ initialization. */
-
-void os_init()
+/** Check if a certain defcon option is in a certain defcon level
+ * @param level The defcon level
+ * @param Level The defcon level name
+ * @return true or false
+ */
+bool CheckDefCon(int level, DefconLevel Level)
{
- moduleAddOperServCmds();
-
- slist_init(&akills);
- akills.opts = &akopts;
-
- if (ircd->sgline) {
- slist_init(&sglines);
- sglines.opts = &sgopts;
- }
- if (ircd->sqline) {
- slist_init(&sqlines);
- sqlines.opts = &sqopts;
- }
- if (ircd->szline) {
- slist_init(&szlines);
- szlines.opts = &szopts;
- }
+ return DefCon[level][Level];
}
-/*************************************************************************/
-
-/* Main OperServ routine. */
-
-void operserv(User * u, char *buf)
+/** Add a defcon level option to a defcon level
+ * @param level The defcon level
+ * @param Level The defcon level option
+ */
+void AddDefCon(int level, DefconLevel Level)
{
- const char *cmd;
- const char *s;
-
- Alog() << Config.s_OperServ << ": " << u->nick << ": " << buf;
-
- cmd = strtok(buf, " ");
- if (!cmd) {
- return;
- } else if (stricmp(cmd, "\1PING") == 0) {
- if (!(s = strtok(NULL, ""))) {
- s = "";
- }
- ircdproto->SendCTCP(OperServ, u->nick.c_str(), "PING %s", s);
- } else {
- mod_run_cmd(OperServ, u, cmd);
- }
+ DefCon[level][Level] = true;
}
-/*************************************************************************/
-/*********************** OperServ command functions **********************/
-/*******************************
- * ******************************************/
-
-/*************************************************************************/
-
+/** Remove a defcon level option from a defcon level
+ * @param level The defcon level
+ * @param Level The defcon level option
+ */
+void DelDefCon(int level, DefconLevel Level)
+{
+ DefCon[level][Level] = false;
+}
void server_global(Server *s, const std::string &message)
{
@@ -175,7 +152,6 @@ void oper_global(char *nick, const char *fmt, ...)
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
- /* I don't like the way this is coded... */
if (nick && !Config.AnonymousGlobal)
{
std::string rmsg = std::string("[") + nick + std::string("] ") + msg;
@@ -188,868 +164,665 @@ void oper_global(char *nick, const char *fmt, ...)
/**************************************************************************/
-/* Adds an AKILL to the list. Returns >= 0 on success, -1 if it fails, -2
- * if only the expiry time was changed.
- * The success result is the number of AKILLs that were deleted to successfully add one.
- */
+/* List of XLine managers we check users against in XLineManager::CheckAll */
+std::list<XLineManager *> XLineManager::XLineManagers;
-int add_akill(User * u, const char *mask, const char *by, const time_t expires,
- const char *reason)
+XLine::XLine(const ci::string &mask, const std::string &reason) : Mask(mask), Reason(reason)
{
- int deleted = 0, i;
- char *user, *mask2, *host;
- Akill *entry;
+ Expires = Created = 0;
+}
- if (!mask) {
- return -1;
- }
+XLine::XLine(const ci::string &mask, const ci::string &by, const time_t expires, const std::string &reason) : Mask(mask), By(by), Created(time(NULL)), Expires(expires), Reason(reason)
+{
+}
- /* Checks whether there is an AKILL that already covers
- * the one we want to add, and whether there are AKILLs
- * that would be covered by this one. The masks AND the
- * expiry times are used to determine this, because some
- * AKILLs may become useful when another one expires.
- * If so, warn the user in the first case and cleanup
- * the useless AKILLs in the second.
- */
-
- if (akills.count > 0) {
-
- for (i = akills.count - 1; i >= 0; i--) {
- char amask[BUFSIZE];
-
- entry = static_cast<Akill *>(akills.list[i]);
-
- if (!entry)
- continue;
-
- snprintf(amask, sizeof(amask), "%s@%s", entry->user,
- entry->host);
-
- if (!stricmp(amask, mask)) {
- /* We change the AKILL expiry time if its current one is less than the new.
- * This is preferable to be sure we don't change an important AKILL
- * accidentely.
- */
- if (entry->expires >= expires || entry->expires == 0) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_AKILL_EXISTS,
- mask);
- return -1;
- } else {
- entry->expires = expires;
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_AKILL_CHANGED,
- amask);
- return -2;
- }
- }
+ci::string XLine::GetNick() const
+{
+ size_t nick_t = Mask.find('!');
- if (Anope::Match(mask, amask, false)
- && (entry->expires >= expires || entry->expires == 0)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_AKILL_ALREADY_COVERED,
- mask, amask);
- return -1;
- }
+ if (nick_t == ci::string::npos)
+ return "";
- if (Anope::Match(amask, mask, false)
- && (entry->expires <= expires || expires == 0)) {
- slist_delete(&akills, i);
- deleted++;
- }
- }
+ return Mask.substr(0, nick_t - 1);
+}
- }
+ci::string XLine::GetUser() const
+{
+ size_t user_t = Mask.find('!'), host_t = Mask.find('@');
- /* We can now check whether the list is full or not. */
- if (slist_full(&akills)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_AKILL_REACHED_LIMIT,
- akills.limit);
- return -1;
+ if (user_t == ci::string::npos)
+ {
+ return Mask.substr(0, host_t);
}
-
- /* We can now (really) add the AKILL. */
- mask2 = sstrdup(mask);
- host = strchr(mask2, '@');
-
- if (!host) {
- delete [] mask2;
- return -1;
+ else if (host_t != ci::string::npos)
+ {
+ return Mask.substr((user_t != ci::string::npos ? user_t + 1 : 0), host_t);
}
-
- user = mask2;
- *host = 0;
- host++;
-
- entry = new Akill;
-
- if (!entry) {
- delete [] mask2;
- return -1;
+ else
+ {
+ return "";
}
+}
- entry->user = sstrdup(user);
- entry->host = sstrdup(host);
- entry->by = sstrdup(by);
- entry->reason = sstrdup(reason);
- entry->seton = time(NULL);
- entry->expires = expires;
+ci::string XLine::GetHost() const
+{
+ size_t host_t = Mask.find('@');
- EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, entry));
- if (MOD_RESULT == EVENT_STOP)
+ if (host_t == ci::string::npos)
{
- delete entry;
- return -1;
+ return Mask;
+ }
+ else
+ {
+ return Mask.substr(host_t + 1);
}
-
- slist_add(&akills, entry);
-
- if (Config.AkillOnAdd)
- ircdproto->SendAkill(entry);
-
- delete [] mask2;
-
- return deleted;
}
-/* Does the user match any AKILLs? */
+/** Constructor
+ */
+XLineManager::XLineManager()
+{
+}
-int check_akill(const char *nick, const char *username, const char *host,
- const char *vhost, const char *ip)
+/** Destructor
+ * Clears all XLines in this XLineManager
+ */
+XLineManager::~XLineManager()
{
- int i;
- Akill *ak;
+ Clear();
+}
- if (akills.count == 0)
- return 0;
+ /** Register a XLineManager, places it in XLineManagers for use in XLineManager::CheckAll
+ * It is important XLineManagers are registered in the proper order. Eg, if you had one akilling
+ * clients and one handing them free olines, you would want the akilling one first. This way if a client
+ * matches an entry on both of the XLineManagers, they would be akilled.
+ * @param xlm THe XLineManager
+ */
+void XLineManager::RegisterXLineManager(XLineManager *xlm)
+{
+ XLineManagers.push_back(xlm);
+}
- for (i = 0; i < akills.count; i++) {
- ak = static_cast<Akill *>(akills.list[i]);
- if (!ak)
- continue;
- if (Anope::Match(username, ak->user, false)
- && Anope::Match(host, ak->host, false)) {
- ircdproto->SendAkill(ak);
- return 1;
- }
- if (ircd->vhost) {
- if (vhost) {
- if (Anope::Match(username, ak->user, false)
- && Anope::Match(vhost, ak->host, false)) {
- ircdproto->SendAkill(ak);
- return 1;
- }
- }
- }
- if (ircd->nickip) {
- if (ip) {
- if (Anope::Match(username, ak->user, false)
- && Anope::Match(ip, ak->host, false)) {
- ircdproto->SendAkill(ak);
- return 1;
- }
- }
- }
+/** Unregister a XLineManager
+ * @param xlm The XLineManager
+ */
+void XLineManager::UnregisterXLineManager(XLineManager *xlm)
+{
+ std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
+ if (it != XLineManagers.end())
+ {
+ XLineManagers.erase(it);
}
-
- return 0;
}
-/* Delete any expired autokills. */
-
-void expire_akills()
+/* Check a user against all known XLineManagers
+ * @param u The user
+ * @return A pair of the XLineManager the user was found in and the XLine they matched, both may be NULL for no match
+ */
+std::pair<XLineManager *, XLine *> XLineManager::CheckAll(User *u)
{
- int i;
- time_t now = time(NULL);
- Akill *ak;
+ std::pair<XLineManager *, XLine *> ret(NULL, NULL);
- for (i = akills.count - 1; i >= 0; i--) {
- ak = static_cast<Akill *>(akills.list[i]);
+ for (std::list<XLineManager *>::iterator it = XLineManagers.begin(); it != XLineManagers.end(); ++it)
+ {
+ XLineManager *xlm = *it;
- if (!ak->expires || ak->expires > now)
- continue;
+ XLine *x = xlm->Check(u);
- if (Config.WallAkillExpire)
- ircdproto->SendGlobops(OperServ, "AKILL on %s@%s has expired",
- ak->user, ak->host);
- slist_delete(&akills, i);
+ if (x)
+ {
+ ret.first = xlm;
+ ret.second = x;;
+ break;
+ }
}
+
+ return ret;
}
-static void free_akill_entry(SList * slist, void *item)
+/** Get the number of XLines in this XLineManager
+ * @return The number of XLines
+ */
+const size_t XLineManager::GetCount() const
{
- Akill *ak = static_cast<Akill *>(item);
-
- /* Remove the AKILLs from all the servers */
- ircdproto->SendAkillDel(ak);
+ return XLines.size();
+}
- /* Free the structure */
- delete [] ak->user;
- delete [] ak->host;
- delete [] ak->by;
- delete [] ak->reason;
- delete ak;
+/** Get the XLine list
+ * @return The list
+ */
+const std::deque<XLine *>& XLineManager::GetList() const
+{
+ return XLines;
}
-/* item1 is not an Akill pointer, but a char
+/** Add an entry to this XLineManager
+ * @param x The entry
*/
-
-static int is_akill_entry_equal(SList * slist, void *item1, void *item2)
+void XLineManager::AddXLine(XLine *x)
{
- char *ak1 = static_cast<char *>(item1), buf[BUFSIZE];
- Akill *ak2 = static_cast<Akill *>(item2);
-
- if (!ak1 || !ak2)
- return 0;
-
- snprintf(buf, sizeof(buf), "%s@%s", ak2->user, ak2->host);
-
- if (!stricmp(ak1, buf))
- return 1;
- else
- return 0;
+ XLines.push_back(x);
}
-
-/*************************************************************************/
-
-/* Adds an SGLINE to the list. Returns >= 0 on success, -1 if it failed, -2 if
- * only the expiry time changed.
- * The success result is the number of SGLINEs that were deleted to successfully add one.
+/** Delete an entry from this XLineManager
+ * @param x The entry
+ * @return true if the entry was found and deleted, else false
*/
-
-int add_sgline(User * u, const char *mask, const char *by, time_t expires,
- const char *reason)
+bool XLineManager::DelXLine(XLine *x)
{
- int deleted = 0, i;
- SXLine *entry;
-
- /* Checks whether there is an SGLINE that already covers
- * the one we want to add, and whether there are SGLINEs
- * that would be covered by this one.
- * If so, warn the user in the first case and cleanup
- * the useless SGLINEs in the second.
- */
-
- if (!mask) {
- return -1;
- }
+ std::deque<XLine *>::iterator it = std::find(XLines.begin(), XLines.end(), x);
- if (sglines.count > 0) {
-
- for (i = sglines.count - 1; i >= 0; i--) {
- entry = static_cast<SXLine *>(sglines.list[i]);
-
- if (!entry)
- continue;
-
- if (!stricmp(entry->mask, mask)) {
- if (entry->expires >= expires || entry->expires == 0) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SGLINE_EXISTS,
- mask);
- return -1;
- } else {
- entry->expires = expires;
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SGLINE_CHANGED,
- entry->mask);
- return -2;
- }
- }
-
- if (Anope::Match(mask, entry->mask, false )
- && (entry->expires >= expires || entry->expires == 0)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SGLINE_ALREADY_COVERED,
- mask, entry->mask);
- return -1;
- }
-
- if (Anope::Match(entry->mask, mask, false)
- && (entry->expires <= expires || expires == 0)) {
- slist_delete(&sglines, i);
- deleted++;
- }
- }
-
- }
+ if (it != XLines.end())
+ {
+ delete x;
+ XLines.erase(it);
- /* We can now check whether the list is full or not. */
- if (slist_full(&sglines)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SGLINE_REACHED_LIMIT,
- sglines.limit);
- return -1;
+ return true;
}
- /* We can now (really) add the SGLINE. */
- entry = new SXLine;
- if (!entry)
- return -1;
+ return false;
+}
- entry->mask = sstrdup(mask);
- entry->by = sstrdup(by);
- entry->reason = sstrdup(reason);
- entry->seton = time(NULL);
- entry->expires = expires;
+/** Gets an entry by index
+ * @param index The index
+ * @return The XLine, or NULL if the index is out of bounds
+ */
+XLine *XLineManager::GetEntry(unsigned index) const
+{
+ if (index >= XLines.size())
+ return NULL;
+
+ return XLines[index];
+}
- EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnAddSXLine, OnAddSXLine(u, entry, SX_SGLINE));
- if (MOD_RESULT == EVENT_STOP)
+/** Clear the XLine list
+ */
+void XLineManager::Clear()
+{
+ for (std::deque<XLine *>::iterator it = XLines.begin(); it != XLines.end(); ++it)
{
- delete entry;
- return -1;
+ delete *it;
}
+ XLines.clear();
+}
+
+/** Add an entry to this XLine Manager
+ * @param bi The bot error replies should be sent from
+ * @param u The user adding the XLine
+ * @param mask The mask of the XLine
+ * @param expires When this should expire
+ * @param reaosn The reason
+ * @return A pointer to the XLine
+ */
+XLine *XLineManager::Add(BotInfo *bi, User *u, const ci::string &mask, time_t expires, const std::string &reason)
+{
+ return NULL;
+}
- slist_add(&sglines, entry);
+/** Delete an XLine, eg, remove it from the IRCd.
+ * @param x The xline
+ */
+void XLineManager::Del(XLine *x)
+{
+}
- ircdproto->SendSGLine(entry);
+/** Checks if a mask can/should be added to the XLineManager
+ * @param mask The mask
+ * @param expires When the mask would expire
+ * @return A pair of int and XLine*.
+ * 1 - Mask already exists
+ * 2 - Mask already exists, but the expiry time was changed
+ * 3 - Mask is already covered by another mask
+ * In each case the XLine it matches/is covered by is returned in XLine*
+ */
+std::pair<int, XLine *> XLineManager::CanAdd(const ci::string &mask, time_t expires)
+{
+ std::pair<int, XLine *> ret(0, NULL);
- if (Config.KillonSGline && !ircd->sglineenforce)
+ for (unsigned i = 0; i < GetCount(); ++i)
{
- char buf[BUFSIZE];
- snprintf(buf, (BUFSIZE - 1), "G-Lined: %s", entry->reason);
+ XLine *x = GetEntry(i);
+ ret.second = x;
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();)
+ if (x->Mask == mask)
{
- User *u2 = it->second;
- ++it;
-
- if (!is_oper(u2) && Anope::Match(u2->realname, entry->mask, false))
+ if (x->Expires == 0 || x->Expires >= expires)
+ {
+ ret.first = 1;
+ break;
+ }
+ else
{
- kill_user(Config.ServerName, u2->nick, buf);
+ x->Expires = expires;
+
+ ret.first = 2;
+ break;
}
}
+ else if (Anope::Match(mask, x->Mask) && (x->Expires == 0 || x->Expires >= expires))
+ {
+ ret.first = 3;
+ break;
+ }
+ else if (Anope::Match(x->Mask, mask) && (expires == 0 || x->Expires <= expires))
+ {
+ this->DelXLine(x);
+ --i;
+ }
}
- return deleted;
-}
-/* Does the user match any SGLINEs? */
+ return ret;
+}
-int check_sgline(const char *nick, const char *realname)
+/** Checks if this list has an entry
+ * @param mask The mask
+ * @return The XLine the user matches, or NULL
+ */
+XLine *XLineManager::HasEntry(const ci::string &mask) const
{
- int i;
- SXLine *sx;
-
- if (sglines.count == 0)
- return 0;
-
- for (i = 0; i < sglines.count; i++) {
- sx = static_cast<SXLine *>(sglines.list[i]);
- if (!sx)
- continue;
+ for (unsigned i = 0; i < XLines.size(); ++i)
+ {
+ XLine *x = XLines[i];
- if (Anope::Match(realname, sx->mask, false)) {
- ircdproto->SendSGLine(sx);
- /* We kill nick since s_sgline can't */
- ircdproto->SendSVSKill(NULL, finduser(nick), "G-Lined: %s", sx->reason);
- return 1;
+ if (x->Mask == mask)
+ {
+ return x;
}
}
- return 0;
+ return NULL;
}
-/* Delete any expired SGLINEs. */
-
-void expire_sglines()
+/** Check a user against all of the xlines in this XLineManager
+ * @param u The user
+ * @return The xline the user marches, if any. Also calls OnMatch()
+ */
+XLine *XLineManager::Check(User *u)
{
- int i;
- time_t now = time(NULL);
- SXLine *sx;
+ const time_t now = time(NULL);
- for (i = sglines.count - 1; i >= 0; i--) {
- sx = static_cast<SXLine *>(sglines.list[i]);
+ for (std::deque<XLine *>::iterator it = XLines.begin(); it != XLines.end(); ++it)
+ {
+ XLine *x = *it;
- if (!sx->expires || sx->expires > now)
+ if (x->Expires && x->Expires < now)
+ {
+ OnExpire(x);
+ delete x;
+ it = XLines.erase(it);
+ --it;
continue;
+ }
- if (Config.WallSGLineExpire)
- ircdproto->SendGlobops(OperServ, "SGLINE on \2%s\2 has expired",
- sx->mask);
- slist_delete(&sglines, i);
- }
-}
+ if (!x->GetNick().empty() && !Anope::Match(u->nick.c_str(), x->GetNick()))
+ continue;
-static void free_sgline_entry(SList * slist, void *item)
-{
- SXLine *sx = static_cast<SXLine *>(item);
+ if (!x->GetUser().empty() && !Anope::Match(u->GetIdent().c_str(), x->GetUser()))
+ continue;
- /* Remove the SGLINE from all the servers */
- ircdproto->SendSGLineDel(sx);
+ if (x->GetNick().empty() && x->GetUser().empty() || ((u->hostip && Anope::Match(u->hostip, x->GetHost())) || Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost.c_str(), x->GetHost())) || (u->vhost && Anope::Match(u->vhost, x->GetHost()))))
+ {
+ OnMatch(u, x);
+ return x;
+ }
+ }
- /* Free the structure */
- delete [] sx->mask;
- delete [] sx->by;
- delete [] sx->reason;
- delete sx;
+ return NULL;
}
-/* item1 is not an SXLine pointer, but a char */
-
-static int is_sgline_entry_equal(SList * slist, void *item1, void *item2)
+/** Called when a user matches a xline in this XLineManager
+ * @param u The user
+ * @param x The XLine they match
+ */
+void XLineManager::OnMatch(User *u, XLine *x)
{
- char *sx1 = static_cast<char *>(item1);
- SXLine *sx2 = static_cast<SXLine *>(item2);
-
- if (!sx1 || !sx2)
- return 0;
-
- if (!stricmp(sx1, sx2->mask))
- return 1;
- else
- return 0;
}
-/*************************************************************************/
-
-/* Adds an SQLINE to the list. Returns >= 0 on success, -1 if it failed, -2 if
- * only the expiry time changed.
- * The success result is the number of SQLINEs that were deleted to successfully add one.
+/** Called when an XLine expires
+ * @param x The xline
*/
+void XLineManager::OnExpire(XLine *x)
+{
+}
-int add_sqline(User * u, const char *mask, const char *by, time_t expires,
- const char *reason)
+XLine *SGLineManager::Add(BotInfo *bi, User *u, const ci::string &mask, time_t expires, const std::string &reason)
{
- int deleted = 0, i;
- SXLine *entry;
-
- /* Checks whether there is an SQLINE that already covers
- * the one we want to add, and whether there are SQLINEs
- * that would be covered by this one.
- * If so, warn the user in the first case and cleanup
- * the useless SQLINEs in the second.
- */
-
- if (!mask) {
- return -1;
+ if (mask.find('!') != ci::string::npos)
+ {
+ if (bi && u)
+ notice_lang(bi->nick.c_str(), u, OPER_AKILL_NO_NICK);
+ return NULL;
}
- if (sqlines.count > 0) {
-
- for (i = sqlines.count - 1; i >= 0; i--) {
- entry = static_cast<SXLine *>(sqlines.list[i]);
-
- if (!entry)
- continue;
-
- if ((*mask == '#' && *entry->mask != '#') ||
- (*mask != '#' && *entry->mask == '#'))
- continue;
-
- if (!stricmp(entry->mask, mask)) {
- if (entry->expires >= expires || entry->expires == 0) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SQLINE_EXISTS,
- mask);
- return -1;
- } else {
- entry->expires = expires;
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SQLINE_CHANGED,
- entry->mask);
- return -2;
- }
- }
+ if (mask.find('@') == ci::string::npos)
+ {
+ if (bi && u)
+ notice_lang(bi->nick.c_str(), u, BAD_USERHOST_MASK);
+ return NULL;
+ }
- if (Anope::Match(mask, entry->mask, false)
- && (entry->expires >= expires || entry->expires == 0)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SQLINE_ALREADY_COVERED,
- mask, entry->mask);
- return -1;
- }
+ if (strspn(mask.c_str(), "~@.*?") == mask.length())
+ {
+ if (bi && u)
+ notice_lang(bi->nick.c_str(), u, USERHOST_MASK_TOO_WIDE, mask.c_str());
+ return NULL;
+ }
- if (Anope::Match(entry->mask, mask, false)
- && (entry->expires <= expires || expires == 0)) {
- slist_delete(&sqlines, i);
- deleted++;
- }
+ std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires);
+ if (canAdd.first)
+ {
+ if (bi && u)
+ {
+ if (canAdd.first == 1)
+ notice_lang(bi->nick.c_str(), u, OPER_AKILL_EXISTS, canAdd.second->Mask.c_str());
+ else if (canAdd.first == 2)
+ notice_lang(bi->nick.c_str(), u, OPER_AKILL_CHANGED, canAdd.second->Mask.c_str());
+ else if (canAdd.first == 3)
+ notice_lang(bi->nick.c_str(), u, OPER_AKILL_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
+ return canAdd.second;
}
- /* We can now check whether the list is full or not. */
- if (slist_full(&sqlines)) {
- if (u)
- notice_lang(Config.s_OperServ, u, OPER_SQLINE_REACHED_LIMIT,
- sqlines.limit);
- return -1;
- }
-
- /* We can now (really) add the SQLINE. */
- entry = new SXLine;
- if (!entry)
- return -1;
-
- entry->mask = sstrdup(mask);
- entry->by = sstrdup(by);
- entry->reason = sstrdup(reason);
- entry->seton = time(NULL);
- entry->expires = expires;
+ std::string realreason = reason;
+ if (u && Config.AddAkiller)
+ realreason = "[" + u->nick + "]" + reason;
+
+ XLine *x = new XLine(mask, u ? u->nick.c_str() : "", expires, realreason);
EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnAddSXLine, OnAddSXLine(u, entry, SX_SQLINE));
+ FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, x));
if (MOD_RESULT == EVENT_STOP)
{
- delete entry;
- return -1;
+ delete x;
+ return NULL;
}
+
+ this->AddXLine(x);
- slist_add(&sqlines, entry);
-
- sqline(entry->mask, entry->reason);
-
- if (Config.KillonSQline)
- {
- char buf[BUFSIZE];
- snprintf(buf, (BUFSIZE - 1), "Q-Lined: %s", entry->reason);
-
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();)
- {
- User *u2 = it->second;
- ++it;
-
- if (!is_oper(u2) && Anope::Match(u2->nick, entry->mask, false))
- {
- kill_user(Config.ServerName, u2->nick, buf);
- }
- }
- }
-
- return deleted;
+ if (Config.AkillOnAdd)
+ ircdproto->SendAkill(x);
+
+ return x;
}
-/* Does the user match any SQLINEs? */
-
-int check_sqline(const char *nick, int nick_change)
+void SGLineManager::Del(XLine *x)
{
- int i;
- SXLine *sx;
- char reason[300];
+ ircdproto->SendAkillDel(x);
+}
- if (sqlines.count == 0)
- return 0;
+void SGLineManager::OnMatch(User *u, XLine *x)
+{
+ ircdproto->SendAkill(x);
+}
- for (i = 0; i < sqlines.count; i++) {
- sx = static_cast<SXLine *>(sqlines.list[i]);
- if (!sx)
- continue;
+void SGLineManager::OnExpire(XLine *x)
+{
+ if (Config.WallAkillExpire)
+ ircdproto->SendGlobops(OperServ, "AKILL on %s has expired", x->Mask.c_str());
+}
- if (ircd->chansqline) {
- if (*sx->mask == '#')
- continue;
- }
+XLine *SNLineManager::Add(BotInfo *bi, User *u, const ci::string &mask, time_t expires, const std::string &reason)
+{
+ if (!mask.empty() && strspn(mask.c_str(), "*?") == mask.length())
+ {
+ if (bi && u)
+ notice_lang(bi->nick.c_str(), u, USERHOST_MASK_TOO_WIDE, mask.c_str());
+ return NULL;
+ }
- if (Anope::Match(nick, sx->mask, false)) {
- sqline(sx->mask, sx->reason);
- /* We kill nick since s_sqline can't */
- snprintf(reason, sizeof(reason), "Q-Lined: %s", sx->reason);
- kill_user(Config.s_OperServ, nick, reason);
- return 1;
+ std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires);
+ if (canAdd.first)
+ {
+ if (bi && u)
+ {
+ if (canAdd.first == 1)
+ notice_lang(bi->nick.c_str(), u, OPER_SNLINE_EXISTS, canAdd.second->Mask.c_str());
+ else if (canAdd.first == 2)
+ notice_lang(bi->nick.c_str(), u, OPER_SNLINE_CHANGED, canAdd.second->Mask.c_str());
+ else if (canAdd.first == 3)
+ notice_lang(bi->nick.c_str(), u, OPER_SNLINE_ALREADY_COVERED, mask.c_str(), canAdd.second->Mask.c_str());
}
+
+ return canAdd.second;
}
- return 0;
-}
+ XLine *x = new XLine(mask, u ? u->nick.c_str() : "", expires, reason);
-int check_chan_sqline(const char *chan)
-{
- int i;
- SXLine *sx;
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SNLINE));
+ if (MOD_RESULT == EVENT_STOP)
+ {
+ delete x;
+ return NULL;
+ }
- if (sqlines.count == 0)
- return 0;
+ this->AddXLine(x);
- for (i = 0; i < sqlines.count; i++) {
- sx = static_cast<SXLine *>(sqlines.list[i]);
- if (!sx)
- continue;
+ if (Config.KillonSNline && !ircd->sglineenforce)
+ {
+ std::string rreason = "G-Lined: " + reason;
- if (*sx->mask != '#')
- continue;
+ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();)
+ {
+ User *user = it->second;
+ ++it;
- if (Anope::Match(chan, sx->mask, false)) {
- sqline(sx->mask, sx->reason);
- return 1;
+ if (!is_oper(user) && Anope::Match(user->realname, x->Mask))
+ {
+ kill_user(Config.ServerName, user->nick, rreason.c_str());
+ }
}
}
- return 0;
+ return x;
}
-/* Delete any expired SQLINEs. */
-
-void expire_sqlines()
+void SNLineManager::Del(XLine *x)
{
- int i;
- time_t now = time(NULL);
- SXLine *sx;
-
- for (i = sqlines.count - 1; i >= 0; i--) {
- sx = static_cast<SXLine *>(sqlines.list[i]);
-
- if (!sx->expires || sx->expires > now)
- continue;
-
- if (Config.WallSQLineExpire)
- ircdproto->SendGlobops(OperServ, "SQLINE on \2%s\2 has expired",
- sx->mask);
-
- slist_delete(&sqlines, i);
- }
+ ircdproto->SendSGLineDel(x);
}
-static void free_sqline_entry(SList * slist, void *item)
+void SNLineManager::OnMatch(User *u, XLine *x)
{
- SXLine *sx = static_cast<SXLine *>(item);
-
- /* Remove the SQLINE from all the servers */
- ircdproto->SendSQLineDel(sx->mask);
+ ircdproto->SendSGLine(x);
- /* Free the structure */
- delete [] sx->mask;
- delete [] sx->by;
- delete [] sx->reason;
- delete sx;
+ std::string reason = "G-Lined: " + x->Reason;
+ kill_user(Config.s_OperServ, u->nick, reason.c_str());
}
-/* item1 is not an SXLine pointer, but a char */
-
-static int is_sqline_entry_equal(SList