diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 3 | ||||
-rw-r--r-- | src/core/os_news.c | 271 | ||||
-rw-r--r-- | src/core/os_stats.c | 3 | ||||
-rw-r--r-- | src/init.c | 24 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/news.c | 271 | ||||
-rw-r--r-- | src/protocol/bahamut.c | 1 | ||||
-rw-r--r-- | src/protocol/inspircd11.c | 1 | ||||
-rw-r--r-- | src/protocol/inspircd12.cpp | 1 | ||||
-rw-r--r-- | src/protocol/ratbox.c | 1 | ||||
-rw-r--r-- | src/protocol/unreal32.c | 1 | ||||
-rw-r--r-- | src/users.c | 3 |
12 files changed, 260 insertions, 321 deletions
diff --git a/src/Makefile b/src/Makefile index 2f8845b4d..8388386a8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o commands.o compat.o \ config.o datafiles.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ - memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \ + memory.o memoserv.o messages.o misc.o modules.o nickserv.o operserv.o \ process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o users.o module.o modulemanager.o configreader.o \ wildcard.o nickcore.o nickalias.o timers.o modes.o @@ -63,7 +63,6 @@ modules.o: modules.c $(INCLUDES) module.o: module.cpp $(INCLUDES) modulemanager.o: modulemanager.cpp $(INCLUDES) misc.o: misc.c $(INCLUDES) -news.o: news.c $(INCLUDES) nickserv.o: nickserv.c $(INCLUDES) operserv.o: operserv.c $(INCLUDES) process.o: process.c $(INCLUDES) diff --git a/src/core/os_news.c b/src/core/os_news.c index 4fe690da1..103c416b2 100644 --- a/src/core/os_news.c +++ b/src/core/os_news.c @@ -14,6 +14,7 @@ /*************************************************************************/ #include "module.h" +#include "pseudo.h" // Remove once new dbs are added /* List of messages for each news type. This simplifies message sending. */ @@ -31,12 +32,30 @@ #define MSG_DELETED_ALL 11 #define MSG_MAX 11 +enum NewsType +{ + NEWS_LOGON, + NEWS_RANDOM, + NEWS_OPER +}; + struct newsmsgs { - int16 type; + NewsType type; const char *name; int msgs[MSG_MAX + 1]; }; +struct NewsItem +{ + NewsType type; + uint32 num; + std::string Text; + char who[NICKMAX]; + time_t time; +}; + +std::vector<NewsItem *> News; + struct newsmsgs msgarray[] = { {NEWS_LOGON, "LOGON", {NEWS_LOGON_SYNTAX, @@ -82,7 +101,188 @@ struct newsmsgs msgarray[] = { } }; -static int *findmsgs(int16 type, const char **type_name) +#define SAFE(x) do { \ + if ((x) < 0) { \ + if (!forceload) \ + fatal("Read error on %s", NewsDBName); \ + break; \ + } \ +} while (0) + +void load_news() +{ + dbFILE *f; + int i; + uint16 n, type; + uint32 tmp32; + NewsItem *news; + char *text; + + if (!(f = open_db(s_OperServ, NewsDBName, "r", NEWS_VERSION))) + return; + switch (i = get_file_version(f)) { + case 9: + case 8: + case 7: + SAFE(read_int16(&n, f)); + if (!n) { + close_db(f); + return; + } + for (i = 0; i < n; i++) { + news = new NewsItem; + + SAFE(read_int16(&type, f)); + news->type = (NewsType)type; + SAFE(read_int32(&news->num, f)); + SAFE(read_string(&text, f)); + news->Text = text; + delete [] text; + SAFE(read_buffer(news->who, f)); + SAFE(read_int32(&tmp32, f)); + news->time = tmp32; + + News.push_back(news); + } + break; + + default: + fatal("Unsupported version (%d) on %s", i, NewsDBName); + } /* switch (ver) */ + + close_db(f); +} + +#undef SAFE + +#define SAFE(x) do { \ + if ((x) < 0) { \ + restore_db(f); \ + log_perror("Write error on %s", NewsDBName); \ + if (time(NULL) - lastwarn > WarningTimeout) { \ + ircdproto->SendGlobops(NULL, "Write error on %s: %s", NewsDBName, \ + strerror(errno)); \ + lastwarn = time(NULL); \ + } \ + return; \ + } \ +} while (0) + +void save_news() +{ + dbFILE *f; + static time_t lastwarn = 0; + + if (!(f = open_db(s_OperServ, NewsDBName, "w", NEWS_VERSION))) + return; + SAFE(write_int16(News.size(), f)); + for (unsigned i = 0; i < News.size(); i++) { + SAFE(write_int16(News[i]->type, f)); + SAFE(write_int32(News[i]->num, f)); + SAFE(write_string(News[i]->Text.c_str(), f)); + SAFE(write_buffer(News[i]->who, f)); + SAFE(write_int32(News[i]->time, f)); + } + close_db(f); +} + +#undef SAFE + +static void DisplayNews(User *u, NewsType Type) +{ + int msg; + static unsigned current_news = 0; + + if (Type == NEWS_LOGON) + msg = NEWS_LOGON_TEXT; + else if (Type == NEWS_OPER) + msg = NEWS_OPER_TEXT; + else if (Type == NEWS_RANDOM) + msg = NEWS_RANDOM_TEXT; + else + { + alog("news: Invalid type (%d) to display_news()", Type); + return; + } + + unsigned displayed = 0; + bool NewsExists = false; + for (unsigned i = 0; i < News.size(); ++i) + { + if (News[i]->type == Type) + { + tm *tm; + char timebuf[64]; + + NewsExists = true; + + if (Type == NEWS_RANDOM && i == current_news) + continue; + + tm = localtime(&News[i]->time); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, tm); + notice_lang(s_GlobalNoticer, u, msg, timebuf, News[i]->Text.c_str()); + + ++displayed; + + if (Type == NEWS_RANDOM) + { + current_news = i; + return; + } + else if (displayed >= NewsCount) + return; + } + + /* Reset to head of list to get first random news value */ + if (i + 1 == News.size() && Type == NEWS_RANDOM && NewsExists) + i = 0; + } +} + +static int add_newsitem(User * u, const char *text, NewsType type) +{ + int num = 0; + + for (unsigned i = News.size(); i > 0; --i) + { + if (News[i - 1]->type == type) + { + num = News[i - 1]->num; + break; + } + } + + NewsItem *news = new NewsItem; + news->type = type; + news->num = num + 1; + news->Text = text; + news->time = time(NULL); + strscpy(news->who, u->nick, NICKMAX); + + News.push_back(news); + + return num + 1; +} + +static int del_newsitem(unsigned num, NewsType type) +{ + int count = 0; + + for (unsigned i = News.size(); i > 0; --i) + { + if (News[i - 1]->type == type && (num == 0 || News[i - 1]->num == num)) + { + delete News[i - 1]; + News.erase(News.begin() + i - 1); + ++count; + } + } + + return count; +} + +static int *findmsgs(NewsType type, const char **type_name) { for (unsigned i = 0; i < lenof(msgarray); i++) { if (msgarray[i].type == type) { @@ -97,21 +297,21 @@ static int *findmsgs(int16 type, const char **type_name) class NewsBase : public Command { protected: - CommandReturn DoList(User *u, short type, int *msgs) + CommandReturn DoList(User *u, NewsType type, int *msgs) { - int i, count = 0; + int count = 0; char timebuf[64]; struct tm *tm; - for (i = 0; i < nnews; ++i) + for (unsigned i = 0; i < News.size(); ++i) { - if (news[i].type == type) + if (News[i]->type == type) { if (!count) notice_lang(s_OperServ, u, msgs[MSG_LIST_HEADER]); - tm = localtime(&news[i].time); + tm = localtime(&News[i]->time); strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, tm); - notice_lang(s_OperServ, u, msgs[MSG_LIST_ENTRY], news[i].num, timebuf, *news[i].who ? news[i].who : "<unknown>", news[i].text); + notice_lang(s_OperServ, u, msgs[MSG_LIST_ENTRY], News[i]->num, timebuf, *News[i]->who ? News[i]->who : "<unknown>", News[i]->Text.c_str()); ++count; } } @@ -123,7 +323,7 @@ class NewsBase : public Command return MOD_CONT; } - CommandReturn DoAdd(User *u, std::vector<ci::string> ¶ms, short type, int *msgs) + CommandReturn DoAdd(User *u, std::vector<ci::string> ¶ms, NewsType type, int *msgs) { const char *text = params.size() > 1 ? params[1].c_str() : NULL; int n; @@ -147,10 +347,10 @@ class NewsBase : public Command return MOD_CONT; } - CommandReturn DoDel(User *u, std::vector<ci::string> ¶ms, short type, int *msgs) + CommandReturn DoDel(User *u, std::vector<ci::string> ¶ms, NewsType type, int *msgs) { const char *text = params.size() > 1 ? params[1].c_str() : NULL; - int num; + unsigned num; if (!text) this->OnSyntaxError(u); @@ -167,11 +367,10 @@ class NewsBase : public Command if (num > 0 && del_newsitem(num, type)) { notice_lang(s_OperServ, u, msgs[MSG_DELETED], num); - /* Reset the order - #0000397 */ - for (int i = 0; i < nnews; ++i) + for (unsigned i = 0; i < News.size(); ++i) { - if (news[i].type == type && news[i].num > num) - --news[i].num; + if (News[i]->type == type && News[i]->num > num) + --News[i]->num; } } else @@ -189,18 +388,12 @@ class NewsBase : public Command return MOD_CONT; } - CommandReturn DoNews(User *u, std::vector<ci::string> ¶ms, short type) + CommandReturn DoNews(User *u, std::vector<ci::string> ¶ms, NewsType type) { ci::string cmd = params[0]; const char *type_name; int *msgs; - if (!u->nc->HasCommand("operserv/news")) - { - notice_lang(s_OperServ, u, ACCESS_DENIED); - return MOD_CONT; - } - msgs = findmsgs(type, &type_name); if (!msgs) { @@ -319,6 +512,14 @@ class OSNews : public Module this->AddCommand(OPERSERV, new CommandOSLogonNews()); this->AddCommand(OPERSERV, new CommandOSOperNews()); this->AddCommand(OPERSERV, new CommandOSRandomNews()); + + Implementation i[] = { I_OnUserModeSet, I_OnUserConnect, I_OnSaveDatabase, I_OnPostLoadDatabases }; + ModuleManager::Attach(i, this, 4); + } + + ~OSNews() + { + save_news(); } void OperServHelp(User *u) @@ -327,6 +528,32 @@ class OSNews : public Module notice_lang(s_OperServ, u, OPER_HELP_CMD_OPERNEWS); notice_lang(s_OperServ, u, OPER_HELP_CMD_RANDOMNEWS); } + + void OnUserModeSet(User *u, UserModeName Name) + { + if (Name == UMODE_OPER) + { + DisplayNews(u, NEWS_OPER); + } + } + + void OnUserConnect(User *u) + { + DisplayNews(u, NEWS_LOGON); + DisplayNews(u, NEWS_RANDOM); + } + + void OnSaveDatabase() + { + /* This needs to be destroyed when new dbs are added... */ + save_news(); + } + + void OnPostLoadDatabases() + { + /* This needs to be destroyed when new dbs are added... */ + load_news(); + } }; MODULE_INIT(OSNews) diff --git a/src/core/os_stats.c b/src/core/os_stats.c index 937590e57..67bac0fa0 100644 --- a/src/core/os_stats.c +++ b/src/core/os_stats.c @@ -384,9 +384,6 @@ void get_operserv_stats(long *nrec, long *memuse) } } - get_news_stats(&count2, &mem2); - count += count2; - mem += mem2; get_exception_stats(&count2, &mem2); count += count2; mem += mem2; diff --git a/src/init.c b/src/init.c index 5cda3e198..4cd654088 100644 --- a/src/init.c +++ b/src/init.c @@ -508,43 +508,39 @@ int init_secondary(int ac, char **av) load_ns_dbase(); if (debug) alog("debug: Loaded %s database (1/%d)", s_NickServ, - (PreNickDBName ? 8 : 7)); + (PreNickDBName ? 7 : 6)); if (s_HostServ) { load_hs_dbase(); if (debug) alog("debug: Loaded %s database (2/%d)", s_HostServ, - (PreNickDBName ? 8 : 7)); + (PreNickDBName ? 7 : 6)); } else if (debug) { - alog("debug: HostServ database (2/%d) not loaded because HostServ is disabled", (PreNickDBName ? 8 : 7)); + alog("debug: HostServ database (2/%d) not loaded because HostServ is disabled", (PreNickDBName ? 7 : 6)); } if (s_BotServ) { load_bs_dbase(); if (debug) alog("debug: Loaded %s database (3/%d)", s_BotServ, - (PreNickDBName ? 8 : 7)); + (PreNickDBName ? 7 : 6)); } else if (debug) { - alog("debug: BotServ database (3/%d) not loaded because BotServ is disabled", (PreNickDBName ? 8 : 7)); + alog("debug: BotServ database (3/%d) not loaded because BotServ is disabled", (PreNickDBName ? 7 : 6)); } load_cs_dbase(); if (debug) alog("debug: Loaded %s database (4/%d)", s_ChanServ, - (PreNickDBName ? 8 : 7)); + (PreNickDBName ? 7 : 6)); load_os_dbase(); if (debug) alog("debug: Loaded %s database (5/%d)", s_OperServ, - (PreNickDBName ? 8 : 7)); - load_news(); - if (debug) - alog("debug: Loaded news database (6/%d)", - (PreNickDBName ? 8 : 7)); + (PreNickDBName ? 7 : 6)); load_exceptions(); if (debug) - alog("debug: Loaded exception database (7/%d)", - (PreNickDBName ? 8 : 7)); + alog("debug: Loaded exception database (6/%d)", + (PreNickDBName ? 7 : 6)); if (PreNickDBName) { load_ns_req_db(); if (debug) - alog("debug: Loaded PreNick database (8/8)"); + alog("debug: Loaded PreNick database (7/7)"); } alog("Databases loaded"); diff --git a/src/main.c b/src/main.c index d2aa0442f..d8fbe5627 100644 --- a/src/main.c +++ b/src/main.c @@ -152,7 +152,6 @@ void save_databases() save_hs_dbase(); } save_os_dbase(); - save_news(); save_exceptions(); } diff --git a/src/news.c b/src/news.c deleted file mode 100644 index 2fb156e8b..000000000 --- a/src/news.c +++ /dev/null @@ -1,271 +0,0 @@ - -/* News functions. - * - * (C) 2003-2009 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. - * - * $Id$ - * - */ - -#include "services.h" -#include "pseudo.h" - -#define MSG_MAX 11 -/*************************************************************************/ - -int32 nnews = 0; -int32 news_size = 0; -NewsItem *news = NULL; - -/*************************************************************************/ - - - -/*************************************************************************/ -/****************************** Statistics *******************************/ -/*************************************************************************/ - -void get_news_stats(long *nrec, long *memuse) -{ - long mem; - int i; - - mem = sizeof(NewsItem) * news_size; - for (i = 0; i < nnews; i++) - mem += strlen(news[i].text) + 1; - *nrec = nnews; - *memuse = mem; -} - -/*************************************************************************/ -/*********************** News item loading/saving ************************/ -/*************************************************************************/ - -#define SAFE(x) do { \ - if ((x) < 0) { \ - if (!forceload) \ - fatal("Read error on %s", NewsDBName); \ - nnews = i; \ - break; \ - } \ -} while (0) - -void load_news() -{ - dbFILE *f; - int i; - uint16 n; - uint32 tmp32; - - if (!(f = open_db(s_OperServ, NewsDBName, "r", NEWS_VERSION))) - return; - switch (i = get_file_version(f)) { - case 9: - case 8: - case 7: - SAFE(read_int16(&n, f)); - nnews = n; - if (nnews < 8) - news_size = 16; - else if (nnews >= 16384) - news_size = 32767; - else - news_size = 2 * nnews; - news = static_cast<NewsItem *>(scalloc(sizeof(*news) * news_size, 1)); - if (!nnews) { - close_db(f); - return; - } - for (i = 0; i < nnews; i++) { - SAFE(read_int16(&news[i].type, f)); - SAFE(read_int32(&news[i].num, f)); - SAFE(read_string(&news[i].text, f)); - SAFE(read_buffer(news[i].who, f)); - SAFE(read_int32(&tmp32, f)); - news[i].time = tmp32; - } - break; - - default: - fatal("Unsupported version (%d) on %s", i, NewsDBName); - } /* switch (ver) */ - - close_db(f); -} - -#undef SAFE - -/*************************************************************************/ - -#define SAFE(x) do { \ - if ((x) < 0) { \ - restore_db(f); \ - log_perror("Write error on %s", NewsDBName); \ - if (time(NULL) - lastwarn > WarningTimeout) { \ - ircdproto->SendGlobops(NULL, "Write error on %s: %s", NewsDBName, \ - strerror(errno)); \ - lastwarn = time(NULL); \ - } \ - return; \ - } \ -} while (0) - -void save_news() -{ - dbFILE *f; - int i; - static time_t lastwarn = 0; - - if (!(f = open_db(s_OperServ, NewsDBName, "w", NEWS_VERSION))) - return; - SAFE(write_int16(nnews, f)); - for (i = 0; i < nnews; i++) { - SAFE(write_int16(news[i].type, f)); - SAFE(write_int32(news[i].num, f)); - SAFE(write_string(news[i].text, f)); - SAFE(write_buffer(news[i].who, f)); - SAFE(write_int32(news[i].time, f)); - } - close_db(f); -} - -#undef SAFE - -/*************************************************************************/ -/***************************** News display ******************************/ -/*************************************************************************/ - -void display_news(User * u, int16 type) -{ - int msg; - - if (type == NEWS_LOGON) { - msg = NEWS_LOGON_TEXT; - } else if (type == NEWS_OPER) { - msg = NEWS_OPER_TEXT; - } else if (type == NEWS_RANDOM) { - msg = NEWS_RANDOM_TEXT; - } else { - alog("news: Invalid type (%d) to display_news()", type); - return; - } - - if (type == NEWS_RANDOM) { - static int current_news = -1; - int count = 0; - - if (!nnews) - return; - - while (count++ < nnews) { - if (++current_news >= nnews) - current_news = 0; - - if (news[current_news].type == type) { - struct tm *tm; - char timebuf[64]; - - tm = localtime(&news[current_news].time); - strftime_lang(timebuf, sizeof(timebuf), u, - STRFTIME_SHORT_DATE_FORMAT, tm); - notice_lang(s_GlobalNoticer, u, msg, timebuf, - news[current_news].text); - - return; - } - } - } else { - int i; - unsigned count = 0; - - for (i = nnews - 1; i >= 0; i--) { - if (count >= NewsCount) - break; - if (news[i].type == type) - count++; - } - while (++i < nnews) { - if (news[i].type == type) { - struct tm *tm; - char timebuf[64]; - - tm = localtime(&news[i].time); - strftime_lang(timebuf, sizeof(timebuf), u, - STRFTIME_SHORT_DATE_FORMAT, tm); - notice_lang(s_GlobalNoticer, u, msg, timebuf, - news[i].text); - } - } - } -} - -/*************************************************************************/ -/***************************** News editing ******************************/ -/*************************************************************************/ - -/* Actually add a news item. Return the number assigned to the item, or -1 - * if the news list is full (32767 items). - */ - -int add_newsitem(User * u, const char *text, short type) -{ - int i, num; - - if (nnews >= 32767) - return -1; - - if (nnews >= news_size) { - if (news_size < 8) - news_size = 8; - else - news_size *= 2; - news = static_cast<NewsItem *>(srealloc(news, sizeof(*news) * news_size)); - } - num = 0; - for (i = nnews - 1; i >= 0; i--) { - if (news[i].type == type) { - num = news[i].num; - break; - } - } - news[nnews].type = type; - news[nnews].num = num + 1; - news[nnews].text = sstrdup(text); - news[nnews].time = time(NULL); - strscpy(news[nnews].who, u->nick, NICKMAX); - nnews++; - return num + 1; -} - -/*************************************************************************/ - -/* Actually delete a news item. If `num' is 0, delete all news items of - * the given type. Returns the number of items deleted. - */ - -int del_newsitem(int num, short type) -{ - int i; - int count = 0; - - for (i = 0; i < nnews; i++) { - if (news[i].type == type && (num == 0 || news[i].num == num)) { - delete [] news[i].text; - count++; - nnews--; - if (i < nnews) - memcpy(news + i, news + i + 1, - sizeof(*news) * (nnews - i)); - i--; - } - } - return count; -} - -/*************************************************************************/ diff --git a/src/protocol/bahamut.c b/src/protocol/bahamut.c index 143cb07a0..709b1a67e 100644 --- a/src/protocol/bahamut.c +++ b/src/protocol/bahamut.c @@ -174,7 +174,6 @@ class BahamutIRCdProto : public IRCDProto if (add) { ++opcnt; if (WallOper) ircdproto->SendGlobops(s_OperServ, "\2%s\2 is now an IRC operator.", user->nick); - display_news(user, NEWS_OPER); } else --opcnt; break; diff --git a/src/protocol/inspircd11.c b/src/protocol/inspircd11.c index c6740f561..892187d1e 100644 --- a/src/protocol/inspircd11.c +++ b/src/protocol/inspircd11.c @@ -184,7 +184,6 @@ class InspIRCdProto : public IRCDProto if (add) { ++opcnt; if (WallOper) ircdproto->SendGlobops(s_OperServ, "\2%s\2 is now an IRC operator.", user->nick); - display_news(user, NEWS_OPER); } else --opcnt; break; diff --git a/src/protocol/inspircd12.cpp b/src/protocol/inspircd12.cpp index 0f4d7c42f..a700d0b69 100644 --- a/src/protocol/inspircd12.cpp +++ b/src/protocol/inspircd12.cpp @@ -189,7 +189,6 @@ class InspIRCdProto : public IRCDProto if (add) { ++opcnt; if (WallOper) ircdproto->SendGlobops(s_OperServ, "\2%s\2 is now an IRC operator.", user->nick); - display_news(user, NEWS_OPER); } else --opcnt; break; diff --git a/src/protocol/ratbox.c b/src/protocol/ratbox.c index 131279049..29aa8ef23 100644 --- a/src/protocol/ratbox.c +++ b/src/protocol/ratbox.c @@ -190,7 +190,6 @@ class RatboxProto : public IRCDTS6Proto if (add) { ++opcnt; if (WallOper) ircdproto->SendGlobops(s_OperServ, "\2%s\2 is now an IRC operator.", user->nick); - display_news(user, NEWS_OPER); } else --opcnt; } diff --git a/src/protocol/unreal32.c b/src/protocol/unreal32.c index 5c50dc8cd..86dd0004e 100644 --- a/src/protocol/unreal32.c +++ b/src/protocol/unreal32.c @@ -208,7 +208,6 @@ class UnrealIRCdProto : public IRCDProto if (add) { ++opcnt; if (WallOper) ircdproto->SendGlobops(s_OperServ, "\2%s\2 is now an IRC operator.", user->nick); - display_news(user, NEWS_OPER); } else --opcnt; break; diff --git a/src/users.c b/src/users.c index 9413b26ae..a92cd5461 100644 --- a/src/users.c +++ b/src/users.c @@ -765,9 +765,6 @@ User *do_nick(const char *source, const char *nick, const char *username, const FOREACH_MOD(I_OnUserConnect, OnUserConnect(user)); - display_news(user, NEWS_LOGON); - display_news(user, NEWS_RANDOM); - /* Now check for session limits */ if (LimitSessions && !is_ulined(server)) add_session(nick, host, ipbuf); |