diff --git a/data/tables.sql b/data/tables.sql index 6b1394e56..14d612c56 100644 --- a/data/tables.sql +++ b/data/tables.sql @@ -172,6 +172,8 @@ CREATE TABLE anope_cs_info ( PRIMARY KEY (name) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; +-- -------------------------------------------------------- + -- -- Table structure for table 'anope_cs_info_metadata' -- @@ -218,6 +220,87 @@ CREATE TABLE anope_bs_core ( -- -------------------------------------------------------- +-- +-- Table structure for table 'anope_ms_info' +-- + +DROP TABLE IF EXISTS anope_ms_info; +CREATE TABLE anope_ms_info ( + receiver varchar(255) NOT NULL, + number int(11) NOT NULL default '0', + flags int(11) NOT NULL default '0', + time int(11) NOT NULL default '0', + sender text NOT NULL, + text blob NOT NULL, + serv enum('NICK','CHAN') NOT NULL default 'NICK' +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table 'anope_os_akills' +-- + +DROP TABLE IF EXISTS anope_os_akills; +CREATE TABLE anope_os_akills ( + user varchar(255) NOT NULL, + host varchar(255) NOT NULL, + xby text NOT NULL, + reason text NOT NULL, + seton int(11) NOT NULL default '0', + expire int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table 'anope_os_core' +-- + +DROP TABLE IF EXISTS anope_os_core; +CREATE TABLE anope_os_core ( + maxusercnt int(11) NOT NULL default '0', + maxusertime int(11) NOT NULL default '0', + akills_count int(11) NOT NULL default '0', + sglines_count int(11) NOT NULL default '0', + sqlines_count int(11) NOT NULL default '0', + szlines_count int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table 'anope_os_exceptions' +-- + +DROP TABLE IF EXISTS anope_os_exceptions; +CREATE TABLE anope_os_exceptions ( + mask varchar(255) NOT NULL, + `limit` int(11) NOT NULL default '0', + who text NOT NULL, + reason text NOT NULL, + time int(11) NOT NULL default '0', + expires int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + +-- +-- Table structure for table 'anope_os_sxlines' +-- + +DROP TABLE IF EXISTS anope_os_sxlines; +CREATE TABLE anope_os_sxlines ( + type varchar(20) NOT NULL, + mask varchar(255) NOT NULL, + xby text NOT NULL, + reason text NOT NULL, + seton int(11) NOT NULL default '0', + expire int(11) NOT NULL default '0' +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- -------------------------------------------------------- + -- -- Table structure for table 'anope_metadata' -- diff --git a/include/modules.h b/include/modules.h index 4a94cd830..945641511 100644 --- a/include/modules.h +++ b/include/modules.h @@ -777,6 +777,47 @@ class CoreExport Module */ virtual void OnDefconLevel(int level) { } + /** Called before an akill is added + * @param u The user adding the akill + * @param ak The akill + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnAddAkill(User *u, Akill *ak) { return EVENT_CONTINUE; } + + /** Called before an akill is deleted + * @param u The user removing the akill + * @param ak The akill, can be NULL for all akills! + */ + virtual void OnDelAkill(User *u, Akill *ak) { } + + /** Called after an exception has been added + * @param u The user who added it + * @param ex The exception + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnExceptionAdd(User *u, Exception *ex) { return EVENT_CONTINUE; } + + /** Called before an exception is deleted + * @param u The user who is deleting it + * @param ex The exceotion + */ + virtual void OnExceptionDel(User *u, Exception *ex) { } + + /** Called before a SXLine is added + * @param u The user adding the SXLine + * @param sx The SXLine + * @param Type The type of SXLine this is + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + */ + virtual EventReturn OnAddSXLine(User *u, SXLine *sx, SXLineType Type) { return EVENT_CONTINUE; } + + /** Called before a SXLine is deleted + * @param u The user deleting the SXLine + * @param sx The SXLine, can be NULL for all SXLines + * @param Type The type of SXLine this is + */ + virtual void OnDelSXLine(User *u, SXLine *sx, SXLineType Type) { } + /** Called when a server quits * @param server The server */ @@ -990,6 +1031,34 @@ class CoreExport Module */ virtual void OnSetVhost(NickAlias *na) { } + /** Called when a memo is sent + * @param u The user sending the memo + * @param nc The nickcore of who the memo was sent to + * @param m The memo + */ + virtual void OnMemoSend(User *u, NickCore *nc, Memo *m) { } + + /** Called when a memo is sent + * @param u The user sending the memo + * @param ci The channel the memo was sent to + * @param m The memo + */ + virtual void OnMemoSend(User *u, ChannelInfo *ci, Memo *m) { } + + /** Called when a memo is deleted + * @param nc The nickcore of the memo being deleted + * @param mi The memo info + * @param number What memo number is being deleted, can be 0 for all memos + */ + virtual void OnMemoDel(NickCore *nc, MemoInfo *mi, int number) { } + + /** Called when a memo is deleted + * @param ci The channel of the memo being deleted + * @param mi The memo info + * @param number What memo number is being deleted, can be 0 for all memos + */ + virtual void OnMemoDel(ChannelInfo *ci, MemoInfo *mi, int number) { } + /** Called when a mode is set on a channel * @param c The channel * @param Name The mode name @@ -1081,14 +1150,15 @@ enum Implementation I_OnHostServHelp, I_OnSetVhost, I_OnDeleteVhost, /* MemoServ */ - I_OnMemoServHelp, + I_OnMemoServHelp, I_OnMemoSend, I_OnMemoDel, /* Users */ I_OnPreUserConnect, I_OnUserConnect, I_OnUserNickChange, I_OnUserQuit, I_OnUserLogoff, I_OnPreJoinChannel, I_OnJoinChannel, I_OnPrePartChannel, I_OnPartChannel, /* OperServ */ - I_OnOperServHelp, I_OnDefconLevel, + I_OnOperServHelp, I_OnDefconLevel, I_OnAddAkill, I_OnDelAkill, I_OnExceptionAdd, I_OnExceptionDel, + I_OnAddSXLine, I_OnDelSXLine, /* Database */ I_OnPostLoadDatabases, I_OnSaveDatabase, I_OnLoadDatabase, I_OnBackupDatabase, diff --git a/include/services.h b/include/services.h index 10304c757..e924a5238 100644 --- a/include/services.h +++ b/include/services.h @@ -362,7 +362,6 @@ struct EList; typedef struct bandata_ BanData; typedef struct mailinfo_ MailInfo; typedef struct akill_ Akill; -typedef struct sxline_ SXLine; typedef struct exception_ Exception; typedef struct session_ Session; @@ -842,7 +841,14 @@ struct akill_ { /* Structure for OperServ SGLINE and SZLINE commands */ -struct sxline_ { +enum SXLineType +{ + SX_SGLINE, + SX_SQLINE, + SX_SZLINE +}; + +struct SXLine { char *mask; char *by; char *reason; diff --git a/src/core/ms_cancel.c b/src/core/ms_cancel.c index 2a2f67b4d..0c5458647 100644 --- a/src/core/ms_cancel.c +++ b/src/core/ms_cancel.c @@ -48,6 +48,7 @@ class CommandMSCancel : public Command { if ((mi->memos[i]->HasFlag(MF_UNREAD)) && !stricmp(mi->memos[i]->sender.c_str(), u->Account()->display) && !mi->memos[i]->HasFlag(MF_NOTIFYS)) { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(findnick(name)->nc, mi, mi->memos[i]->number)) delmemo(mi, mi->memos[i]->number); notice_lang(Config.s_MemoServ, u, MEMO_CANCELLED, name); return MOD_CONT; diff --git a/src/core/ms_del.c b/src/core/ms_del.c index e13732f88..9b48ae856 100644 --- a/src/core/ms_del.c +++ b/src/core/ms_del.c @@ -27,9 +27,10 @@ class CommandMSDel : public Command CommandReturn Execute(User *u, const std::vector ¶ms) { MemoInfo *mi; - ChannelInfo *ci; + ChannelInfo *ci = NULL; ci::string numstr = params.size() ? params[0] : "", chan; - int last, last0, i; + int last, last0; + unsigned i; char buf[BUFSIZE], *end; int delcount, count, left; @@ -77,7 +78,7 @@ class CommandMSDel : public Command last0 = -1; /* Beginning of range of last memos deleted */ end = buf; left = sizeof(buf); - delcount = process_numlist(numstr.c_str(), &count, del_memo_callback, u, mi, &last, &last0, &end, &left); + delcount = process_numlist(numstr.c_str(), &count, del_memo_callback, u, mi, &last, &last0, &end, &left, ci); if (last != -1) { /* Some memos got deleted; tell them which ones. */ @@ -107,11 +108,27 @@ class CommandMSDel : public Command /* Delete last memo. */ for (i = 0; i < mi->memos.size(); ++i) last = mi->memos[i]->number; + if (ci) + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(ci, mi, last)); + } + else + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(u->Account(), mi, last)) + } delmemo(mi, last); notice_lang(Config.s_MemoServ, u, MEMO_DELETED_ONE, last); } else { + if (ci) + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(ci, mi, 0)); + } + else + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(u->Account(), mi, 0)); + } /* Delete all memos. */ for (i = 0; i < mi->memos.size(); ++i) { @@ -176,7 +193,16 @@ int del_memo_callback(User *u, int num, va_list args) int *last0 = va_arg(args, int *); char **end = va_arg(args, char **); int *left = va_arg(args, int *); + ChannelInfo *ci = va_arg(args, ChannelInfo *); + if (ci) + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(ci, mi, num)); + } + else + { + FOREACH_MOD(I_OnMemoDel, OnMemoDel(u->Account(), mi, num)); + } if (delmemo(mi, num)) { if (num != (*last) + 1) diff --git a/src/core/os_akill.c b/src/core/os_akill.c index a045e2bae..5b987b7c3 100644 --- a/src/core/os_akill.c +++ b/src/core/os_akill.c @@ -20,6 +20,13 @@ int akill_list_callback(SList *slist, int number, void *item, va_list args); int akill_view(int number, Akill *ak, User *u, int *sent_header); int akill_list(int number, Akill *ak, User *u, int *sent_header); +static int akill_del_callback(SList *slist, void *item, va_list args) +{ + User *u = va_arg(args, User *); + FOREACH_MOD(I_OnDelAkill, OnDelAkill(u, static_cast(item))); + return 1; +} + class CommandOSAKill : public Command { private: @@ -159,7 +166,7 @@ class CommandOSAKill : public Command if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ - res = slist_delete_range(&akills, mask, NULL); + res = slist_delete_range(&akills, mask, akill_del_callback, u); if (!res) { notice_lang(Config.s_OperServ, u, OPER_AKILL_NO_MATCH); @@ -178,6 +185,8 @@ class CommandOSAKill : public Command return MOD_CONT; } + FOREACH_MOD(I_OnDelAkill, OnDelAkill(u, static_cast(akills.list[res]))); + slist_delete(&akills, res); notice_lang(Config.s_OperServ, u, OPER_AKILL_DELETED, mask); } @@ -276,6 +285,7 @@ class CommandOSAKill : public Command CommandReturn DoClear(User *u) { + FOREACH_MOD(I_OnDelAkill, OnDelAkill(u, NULL)); slist_clear(&akills, 1); notice_lang(Config.s_OperServ, u, OPER_AKILL_CLEAR); diff --git a/src/core/os_session.c b/src/core/os_session.c index 98087aaad..5df784dd7 100644 --- a/src/core/os_session.c +++ b/src/core/os_session.c @@ -93,10 +93,12 @@ class CommandOSSession : public Command } }; -static int exception_del(const int index) +static int exception_del(User *u, const int index) { if (index < 0 || index >= nexceptions) return 0; + + FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(u, &exceptions[index])); delete [] exceptions[index].mask; delete [] exceptions[index].reason; @@ -124,7 +126,7 @@ static int exception_del_callback(User *u, int num, va_list args) break; if (i < nexceptions) - return exception_del(i); + return exception_del(u, i); else return 0; } @@ -290,7 +292,7 @@ class CommandOSException : public Command { if (!stricmp(mask, exceptions[i].mask)) { - exception_del(i); + exception_del(u, i); notice_lang(Config.s_OperServ, u, OPER_EXCEPTION_DELETED, mask); deleted = 1; break; diff --git a/src/core/os_sgline.c b/src/core/os_sgline.c index 81d228c00..39f62c16d 100644 --- a/src/core/os_sgline.c +++ b/src/core/os_sgline.c @@ -21,6 +21,13 @@ int sgline_list_callback(SList *slist, int number, void *item, va_list args); int sgline_view(int number, SXLine *sx, User *u, int *sent_header); int sgline_list(int number, SXLine *sx, User *u, int *sent_header); +static int sxline_del_callback(SList *slist, void *item, va_list args) +{ + User *u = va_arg(args, User *); + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(item), SX_SGLINE)); + return 1; +} + class CommandOSSGLine : public Command { private: @@ -164,7 +171,7 @@ class CommandOSSGLine : public Command if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ - res = slist_delete_range(&sglines, mask, NULL); + res = slist_delete_range(&sglines, mask, sxline_del_callback); if (!res) { notice_lang(Config.s_OperServ, u, OPER_SGLINE_NO_MATCH); @@ -182,6 +189,7 @@ class CommandOSSGLine : public Command return MOD_CONT; } + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(sglines.list[res]), SX_SGLINE)); slist_delete(&sglines, res); notice_lang(Config.s_OperServ, u, OPER_SGLINE_DELETED, mask); } @@ -277,6 +285,7 @@ class CommandOSSGLine : public Command CommandReturn OnClear(User *u) { + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, NULL, SX_SGLINE)); slist_clear(&sglines, 1); notice_lang(Config.s_OperServ, u, OPER_SGLINE_CLEAR); diff --git a/src/core/os_sqline.c b/src/core/os_sqline.c index 8c3beb9ba..2a1dc91f5 100644 --- a/src/core/os_sqline.c +++ b/src/core/os_sqline.c @@ -20,6 +20,13 @@ int sqline_list_callback(SList *slist, int number, void *item, va_list args); int sqline_view(int number, SXLine *sx, User *u, int *sent_header); int sqline_list(int number, SXLine *sx, User *u, int *sent_header); +static int sxline_del_callback(SList *slist, void *item, va_list args) +{ + User *u = va_arg(args, User *); + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(item), SX_SQLINE)); + return 1; +} + class CommandOSSQLine : public Command { private: @@ -150,7 +157,7 @@ class CommandOSSQLine : public Command if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ - res = slist_delete_range(&sqlines, mask, NULL); + res = slist_delete_range(&sqlines, mask, sxline_del_callback); if (!res) { notice_lang(Config.s_OperServ, u, OPER_SQLINE_NO_MATCH); @@ -168,6 +175,7 @@ class CommandOSSQLine : public Command return MOD_CONT; } + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(sglines.list[res]), SX_SQLINE)); slist_delete(&sqlines, res); notice_lang(Config.s_OperServ, u, OPER_SQLINE_DELETED, mask); } @@ -264,6 +272,7 @@ class CommandOSSQLine : public Command CommandReturn DoClear(User *u) { + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, NULL, SX_SQLINE)); slist_clear(&sqlines, 1); notice_lang(Config.s_OperServ, u, OPER_SQLINE_CLEAR); diff --git a/src/core/os_szline.c b/src/core/os_szline.c index 02b864e95..b5946150b 100644 --- a/src/core/os_szline.c +++ b/src/core/os_szline.c @@ -20,6 +20,13 @@ int szline_list_callback(SList *slist, int number, void *item, va_list args); int szline_view(int number, SXLine *sx, User *u, int *sent_header); int szline_list(int number, SXLine *sx, User *u, int *sent_header); +static int sxline_del_callback(SList *slist, void *item, va_list args) +{ + User *u = va_arg(args, User *); + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(item), SX_SZLINE)); + return 1; +} + class CommandOSSZLine : public Command { private: @@ -150,7 +157,7 @@ class CommandOSSZLine : public Command if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { /* Deleting a range */ - res = slist_delete_range(&szlines, mask, NULL); + res = slist_delete_range(&szlines, mask, sxline_del_callback); if (!res) { notice_lang(Config.s_OperServ, u, OPER_SZLINE_NO_MATCH); @@ -169,6 +176,7 @@ class CommandOSSZLine : public Command return MOD_CONT; } + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, static_cast(sglines.list[res]), SX_SZLINE)); slist_delete(&szlines, res); notice_lang(Config.s_OperServ, u, OPER_SZLINE_DELETED, mask); } @@ -263,6 +271,7 @@ class CommandOSSZLine : public Command CommandReturn DoClear(User *u) { + FOREACH_MOD(I_OnDelSXLine, OnDelSXLine(u, NULL, SX_SZLINE)); slist_clear(&szlines, 1); notice_lang(Config.s_OperServ, u, OPER_SZLINE_CLEAR); diff --git a/src/memoserv.c b/src/memoserv.c index 1db5aa06d..3548ac71c 100644 --- a/src/memoserv.c +++ b/src/memoserv.c @@ -247,17 +247,19 @@ void memo_send(User * u, const char *name, const char *text, int z) m = new Memo; mi->memos.push_back(m); m->sender = source; - if (mi->memos.size() > 1) { + if (mi->memos.size() > 1) + { m->number = mi->memos[mi->memos.size() - 2]->number + 1; - if (m->number < 1) { - unsigned i; - for (i = 0; i < mi->memos.size(); i++) { + if (m->number < 1) + { + for (unsigned i = 0; i < mi->memos.size(); i++) + { mi->memos[i]->number = i + 1; } } - } else { - m->number = 1; } + else + m->number = 1; m->time = time(NULL); m->text = sstrdup(text); m->SetFlag(MF_UNREAD); @@ -274,6 +276,8 @@ void memo_send(User * u, const char *name, const char *text, int z) NickAlias *na; NickCore *nc = (findnick(name))->nc; + FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, nc, m)); + if (Config.MSNotifyAll) { if ((nc->HasFlag(NI_MEMO_RECEIVE)) && get_ignore(name) == NULL) { @@ -301,6 +305,8 @@ void memo_send(User * u, const char *name, const char *text, int z) } else { Channel *c; + FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, cs_findchan(name), m)); + if (Config.MSNotifyAll && (c = findchan(name))) { for (CUserList::iterator it = c->users.begin(); it != c->users.end(); ++it) diff --git a/src/modules/mysql/db_mysql.h b/src/modules/mysql/db_mysql.h index b617b7dd5..aeb365563 100644 --- a/src/modules/mysql/db_mysql.h +++ b/src/modules/mysql/db_mysql.h @@ -149,6 +149,19 @@ BotServFlagInfo BotServFlags[] = { {"", static_cast(-1)} }; +struct MemoFlagInfo +{ + std::string Name; + MemoFlag Flag; +}; + +MemoFlagInfo MemoFlags[] = { + {"UNREAD", MF_UNREAD}, + {"RECEIPT", MF_RECEIPT}, + {"NOTIFYS", MF_NOTIFYS}, + {"", static_cast(-1)} +}; + #define MYSQLPP_MYSQL_HEADERS_BURIED #include diff --git a/src/modules/mysql/db_mysql_read.cpp b/src/modules/mysql/db_mysql_read.cpp index f9330270c..36c48b4eb 100644 --- a/src/modules/mysql/db_mysql_read.cpp +++ b/src/modules/mysql/db_mysql_read.cpp @@ -486,6 +486,108 @@ static void LoadDatabase() } } } + + query << "SELECT * FROM `anope_ms_info`"; + qres = StoreQuery(query); + + if (qres) + { + for (size_t i = 0; i < qres.num_rows(); ++i) + { + MemoInfo *mi = NULL; + if (qres[i]["serv"] == "NICK") + { + NickCore *nc = findcore(qres[i]["receiver"].c_str()); + if (nc) + mi = &nc->memos; + } + else if (qres[i]["serv"] == "CHAN") + { + ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["receiver"])); + if (ci) + mi = &ci->memos; + } + if (mi) + { + Memo *m = new Memo(); + mi->memos.push_back(m); + m->sender = SQLAssign(qres[i]["sender"]); + if (mi->memos.size() > 1) + { + m->number = mi->memos[mi->memos.size() - 2]->number + 1; + if (m->number < 1) + { + for (unsigned j = 0; j < mi->memos.size(); ++j) + mi->memos[j]->number = j + 1; + } + } + else + { + m->number = 1; + } + m->time = atol(qres[i]["time"].c_str()); + m->text = sstrdup(qres[i]["text"].c_str()); + + if (!qres[i]["flags"].empty()) + { + spacesepstream sep(SQLAssign(qres[i]["flags"])); + std::string buf; + while (sep.GetToken(buf)) + { + for (unsigned j = 0; MemoFlags[j].Flag != -1; ++j) + { + if (MemoFlags[j].Name == buf) + { + m->SetFlag(MemoFlags[j].Flag); + } + } + } + } + } + } + } + + query << "SELECT * FROM `anope_os_akills`"; + qres = StoreQuery(query); + + if (qres) + { + for (size_t i = 0; i < qres.size(); ++i) + { + Akill *ak = new Akill; + ak->user = sstrdup(qres[i]["user"].c_str()); + ak->host = sstrdup(qres[i]["host"].c_str()); + ak->by = sstrdup(qres[i]["xby"].c_str()); + ak->reason = sstrdup(qres[i]["reason"].c_str()); + ak->seton = atol(qres[i]["seton"].c_str()); + ak->expires = atol(qres[i]["expire"].c_str()); + slist_add(&akills, ak); + } + } + + query << "SELECT * FROM `anope_os_sxlines`"; + qres = StoreQuery(query); + + if (qres) + { + for (size_t i = 0; i < qres.size(); ++i) + { + SXLine *sx = new SXLine; + sx->mask = sstrdup(qres[i]["mask"].c_str()); + sx->by = sstrdup(qres[i]["xby"].c_str()); + sx->reason = sstrdup(qres[i]["reason"].c_str()); + sx->seton = atol(qres[i]["seton"].c_str()); + sx->expires = atol(qres[i]["expires"].c_str()); + if (qres[i]["type"] == "SGLINE") + slist_add(&sglines, sx); + else if (qres[i]["type"] == "SQLINE") + slist_add(&sqlines, sx); + else if (qres[i]["type"] == "SZLINE") + slist_add(&szlines, sx); + else + delete sx; + } + } } class DBMySQLRead : public DBMySQL diff --git a/src/modules/mysql/db_mysql_write.cpp b/src/modules/mysql/db_mysql_write.cpp index 746b46260..c66486f15 100644 --- a/src/modules/mysql/db_mysql_write.cpp +++ b/src/modules/mysql/db_mysql_write.cpp @@ -56,6 +56,24 @@ static std::string BuildFlagsList(NickCore *nc) return ret; } +static std::string BuildFlagsList(Memo *m) +{ + std::string ret; + + for (int i = 0; MemoFlags[i].Flag != -1; ++i) + { + if (m->HasFlag(MemoFlags[i].Flag)) + { + ret += " " + MemoFlags[i].Name; + } + } + + if (!ret.empty()) + ret.erase(ret.begin()); + + return ret; +} + static std::string MakeMLock(ChannelInfo *ci, bool status) { std::string ret; @@ -365,10 +383,13 @@ class DBMySQLWrite : public DBMySQL /* BotServ */ I_OnBotCreate, I_OnBotChange, I_OnBotDelete, I_OnBotAssign, I_OnBotUnAssign, + /* MemoServ */ + I_OnMemoSend, I_OnMemoDel, /* OperServ */ - I_OnOperServHelp + I_OnOperServHelp, I_OnAddAkill, I_OnDelAkill, I_OnExceptionAdd, I_OnExceptionDel, + I_OnAddSXLine, I_OnDelSXLine }; - ModuleManager::Attach(i, this, 27); + ModuleManager::Attach(i, this, 35); } void OnOperServHelp(User *u) @@ -378,6 +399,12 @@ class DBMySQLWrite : public DBMySQL EventReturn OnSaveDatabase() { + mysqlpp::Query query(Me->Con); + + query << "INSERT DELAYED INTO `anope_os_core` (maxusercnt, maxusertime, akills_count, sglines_count, sqlines_count, szlines_count) VALUES("; + query << maxusercnt << ", " << maxusertime << ", " << akills.count << ", " << sqlines.count << ", " << sglines.count << ", " << szlines.count << ")"; + ExecuteQuery(query); + for (int i = 0; i < 1024; ++i) { for (NickCore *nc = nclists[i]; nc; nc = nc->next) @@ -553,6 +580,8 @@ class DBMySQLWrite : public DBMySQL ExecuteQuery(query); query << "DELETE FROM `anope_ns_core` WHERE `display` = " << mysqlpp::quote << nc->display; ExecuteQuery(query); + query << "DELETE FROM `anope_ms_core` WHERE `receiver` = " << mysqlpp::quote << nc->display; + ExecuteQuery(query); } void OnNickForbidden(NickAlias *na) @@ -623,6 +652,8 @@ class DBMySQLWrite : public DBMySQL ExecuteQuery(query); query << "UPDATE `anope_cs_info` SET `successor` = " << mysqlpp::quote << newdisplay << " WHERE `successor` = " << mysqlpp::quote << nc->display; ExecuteQuery(query); + query << "UDATEE `anope_ms_info` SET `receiver` = " << mysqlpp::quote << newdisplay << " WHERE `receiver` = " << mysqlpp::quote << nc->display; + ExecuteQuery(query); } void OnNickSuspend(NickAlias *na) @@ -750,6 +781,105 @@ class DBMySQLWrite : public DBMySQL ExecuteQuery(query); return EVENT_CONTINUE; } + + void OnMemoSend(User *u, NickCore *nc, Memo *m) + { + mysqlpp::Query query(Me->Con); + query << "INSERT DELAYED INTO `anope_ms_info` (receiver, number, flags, time, sender, text, serv) VALUES("; + query << mysqlpp::quote << nc->display << ", " << m->number << ", '" << BuildFlagsList(m) << "', " << m->time << ", "; + query << mysqlpp::quote << u->nick << ", " << mysqlpp::quote << m->text << ", 'NICK')"; + ExecuteQuery(query); + } + + void OnMemoSend(User *u, ChannelInfo *ci, Memo *m) + { + mysqlpp::Query query(Me->Con); + query << "INSERT DELAYED INTO `anope_ms_info` (receiver, number, flags, time, sender, text, serv) VALUES("; + query << mysqlpp::quote << ci->name << ", " << m->number << ", '" << BuildFlagsList(m) << "', " << m->time << ", "; + query << mysqlpp::quote << u->nick << ", " << mysqlpp::quote << m->text << ", 'CHAN')"; + ExecuteQuery(query); + } + + void OnMemoDel(NickCore *nc, MemoInfo *mi, int number) + { + mysqlpp::Query query(Me->Con); + if (number) + query << "DELETE FROM `anope_ms_info` WHERE `receiver` = " << mysqlpp::quote << nc->display << " AND `number` = " << number; + else + query << "DELETE FROM `anope_ms_info` WHERE `receiver` = " << mysqlpp::quote << nc->display; + ExecuteQuery(query); + } + + void OnMemoDel(ChannelInfo *ci, MemoInfo *mi, int number) + { + mysqlpp::Query query(Me->Con); + if (number) + query << "DELETE FROM `anope_ms_info` WHERE `receiver` = " << mysqlpp::quote << ci->name << " AND `number` = " << number; + else + query << "DELETE FROM `anope_ms_info` WHERE `receiver` = " << mysqlpp::quote << ci->name; + ExecuteQuery(query); + } + + EventReturn OnAddAkill(User *u, Akill *ak) + { + mysqlpp::Query query(Me->Con); + query << "INSERT DELAYED INTO `anope_os_akills` (user, host, xby, reason, seton, expire) VALUES("; + query << mysqlpp::quote << ak->user << ", " << mysqlpp::quote << ak->host << ", " << mysqlpp::quote << ak->by; + query << ", " << mysqlpp::quote << ak->reason << ", " << ak->seton << ", " << ak->expires << ")"; + ExecuteQuery(query); + return EVENT_CONTINUE; + } + + void OnDelAkill(User *u, Akill *ak) + { + mysqlpp::Query query(Me->Con); + if (ak) + query << "DELETE FROM `anope_os_akills` WHERE `host` = " << mysqlpp::quote << ak->host; + else + query << "TRUNCATE TABLE `anope_os_akills`"; + ExecuteQuery(query); + } + + EventReturn OnExceptionAdd(User *u, Exception *ex) + { + mysqlpp::Query query(Me->Con); + query << "INSERT DELAYED INTO `anope_os_exceptions` (mask, limit, who, reason, time, expires) VALUES("; + query << mysqlpp::quote << ex->mask << ", " << ex->limit << ", " << mysqlpp::quote << ex->who << ", "; + query << mysqlpp::quote << ex->reason << ", " << ex->time << ", " << ex->expires << ")"; + ExecuteQuery(query); + return EVENT_CONTINUE; + } + + void OnExceptionDel(User *u, Exception *ex) + { + mysqlpp::Query query(Me->Con); + query << "DELETE FROM `anope_os_exceptions` WHERE `mask` = " << mysqlpp::quote << ex->mask; + ExecuteQuery(query); + } + + EventReturn OnAddSXLine(User *u, SXLine *sx, SXLineType Type) + { + mysqlpp::Query query(Me->Con); + query << "INSERT DELAYED INTO `anope_os_sxlines` (type, mask, xby, reason, seton, expire) VALUES('"; + query << (Type == SX_SGLINE ? "SGLINE" : (Type == SX_SQLINE ? "SQLINE" : "SZLINE")) << "', "; + query << mysqlpp::quote << sx->mask << ", " << mysqlpp::quote << sx->by << ", " << mysqlpp::quote << sx->reason; + query << ", " << sx->seton << ", " << sx->expires << ")"; + ExecuteQuery(query); + return EVENT_CONTINUE; + } + + void OnDelSXLine(User *u, SXLine *sx, SXLineType Type) + { + mysqlpp::Query query(Me->Con); + if (sx) + { + query << "DELETE FROM `anope_os_sxlines` WHERE `mask` = " << mysqlpp::quote << sx->mask << " AND `type` = '"; + query << (Type == SX_SGLINE ? "SGLINE" : (Type == SX_SQLINE ? "SQLINE" : "SZLINE")) << "'"; + } + else + query << "DELETE FROM `anope_os_sxlines` WHERE `type` = '" << (Type == SX_SGLINE ? "SGLINE" : (Type == SX_SQLINE ? "SQLINE" : "SZLINE")) << "'"; + ExecuteQuery(query); + } }; MODULE_INIT(DBMySQLWrite) diff --git a/src/operserv.c b/src/operserv.c index 3f7a68df7..958f1f422 100644 --- a/src/operserv.c +++ b/src/operserv.c @@ -308,6 +308,14 @@ int add_akill(User * u, const char *mask, const char *by, const time_t expires, entry->seton = time(NULL); entry->expires = expires; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, entry)); + if (MOD_RESULT == EVENT_STOP) + { + delete entry; + return -1; + } + slist_add(&akills, entry); if (Config.AkillOnAdd) @@ -504,6 +512,14 @@ int add_sgline(User * u, const char *mask, const char *by, time_t expires, entry->seton = time(NULL); entry->expires = expires; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddSXLine, OnAddSXLine(u, entry, SX_SGLINE)); + if (MOD_RESULT == EVENT_STOP) + { + delete entry; + return -1; + } + slist_add(&sglines, entry); ircdproto->SendSGLine(entry); @@ -691,6 +707,14 @@ int add_sqline(User * u, const char *mask, const char *by, time_t expires, entry->seton = time(NULL); entry->expires = expires; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddSXLine, OnAddSXLine(u, entry, SX_SQLINE)); + if (MOD_RESULT == EVENT_STOP) + { + delete entry; + return -1; + } + slist_add(&sqlines, entry); sqline(entry->mask, entry->reason); @@ -903,6 +927,14 @@ int add_szline(User * u, const char *mask, const char *by, time_t expires, entry->seton = time(NULL); entry->expires = expires; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddSXLine, OnAddSXLine(u, entry, SX_SZLINE)); + if (MOD_RESULT == EVENT_STOP) + { + delete entry; + return -1; + } + slist_add(&szlines, entry); ircdproto->SendSZLine(entry); diff --git a/src/sessions.c b/src/sessions.c index 94752482c..128978ba3 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -335,5 +335,16 @@ int exception_add(User * u, const char *mask, const int limit, exceptions[nexceptions - 1].expires = expires; exceptions[nexceptions - 1].num = nexceptions - 1; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(u, &exceptions[nexceptions - 1])); + if (MOD_RESULT == EVENT_STOP) + { + delete [] exceptions[nexceptions - 1].mask; + delete [] exceptions[nexceptions - 1].reason; + --nexceptions; + exceptions = static_cast(srealloc(exceptions, sizeof(Exception) * nexceptions)); + return -3; + } + return 1; }