summaryrefslogtreecommitdiff
path: root/modules/database/old.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/database/old.cpp')
-rw-r--r--modules/database/old.cpp1479
1 files changed, 1479 insertions, 0 deletions
diff --git a/modules/database/old.cpp b/modules/database/old.cpp
new file mode 100644
index 000000000..49692b8bd
--- /dev/null
+++ b/modules/database/old.cpp
@@ -0,0 +1,1479 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2003-2017 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
+ */
+
+/* Dependencies: anope_chanserv.access */
+
+#include "module.h"
+#include "modules/operserv/session.h"
+#include "modules/botserv/kick.h"
+#include "modules/chanserv/mode.h"
+#include "modules/botserv/badwords.h"
+#include "modules/operserv/news.h"
+#include "modules/operserv/forbid.h"
+#include "modules/chanserv/entrymsg.h"
+#include "modules/nickserv/suspend.h"
+#include "modules/chanserv/suspend.h"
+#include "modules/chanserv/access.h"
+#include "modules/nickserv/access.h"
+
+#define READ(x) \
+if (true) \
+{ \
+ if ((x) < 0) \
+ printf("Error, the database is broken, line %d, trying to continue... no guarantee.\n", __LINE__); \
+} \
+else \
+ static_cast<void>(0)
+
+#define getc_db(f) (fgetc((f)->fp))
+#define read_db(f, buf, len) (fread((buf), 1, (len), (f)->fp))
+#define read_buffer(buf, f) ((read_db((f), (buf), sizeof(buf)) == sizeof(buf)) ? 0 : -1)
+
+#define OLD_BI_PRIVATE 0x0001
+
+#define OLD_NI_KILLPROTECT 0x00000001 /* Kill others who take this nick */
+#define OLD_NI_SECURE 0x00000002 /* Don't recognize unless IDENTIFY'd */
+#define OLD_NI_MSG 0x00000004 /* Use PRIVMSGs instead of NOTICEs */
+#define OLD_NI_MEMO_HARDMAX 0x00000008 /* Don't allow user to change memo limit */
+#define OLD_NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */
+#define OLD_NI_MEMO_RECEIVE 0x00000020 /* Notify of new memos when sent */
+#define OLD_NI_PRIVATE 0x00000040 /* Don't show in LIST to non-servadmins */
+#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show E-mail in INFO */
+#define OLD_NI_HIDE_MASK 0x00000100 /* Don't show last seen address in INFO */
+#define OLD_NI_HIDE_QUIT 0x00000200 /* Don't show last quit message in INFO */
+#define OLD_NI_KILL_QUICK 0x00000400 /* Kill in 20 seconds instead of 60 */
+#define OLD_NI_KILL_IMMED 0x00000800 /* Kill immediately instead of in 60 sec */
+#define OLD_NI_MEMO_MAIL 0x00010000 /* User gets email on memo */
+#define OLD_NI_HIDE_STATUS 0x00020000 /* Don't show services access status */
+#define OLD_NI_SUSPENDED 0x00040000 /* Nickname is suspended */
+#define OLD_NI_AUTOOP 0x00080000 /* Autoop nickname in channels */
+
+#define OLD_NS_NO_EXPIRE 0x0004 /* nick won't expire */
+#define OLD_NS_VERBOTEN 0x0002
+
+#define OLD_CI_KEEPTOPIC 0x00000001
+#define OLD_CI_SECUREOPS 0x00000002
+#define OLD_CI_PRIVATE 0x00000004
+#define OLD_CI_TOPICLOCK 0x00000008
+#define OLD_CI_RESTRICTED 0x00000010
+#define OLD_CI_PEACE 0x00000020
+#define OLD_CI_SECURE 0x00000040
+#define OLD_CI_VERBOTEN 0x00000080
+#define OLD_CI_ENCRYPTEDPW 0x00000100
+#define OLD_CI_NO_EXPIRE 0x00000200
+#define OLD_CI_MEMO_HARDMAX 0x00000400
+#define OLD_CI_OPNOTICE 0x00000800
+#define OLD_CI_SECUREFOUNDER 0x00001000
+#define OLD_CI_SIGNKICK 0x00002000
+#define OLD_CI_SIGNKICK_LEVEL 0x00004000
+#define OLD_CI_XOP 0x00008000
+#define OLD_CI_SUSPENDED 0x00010000
+
+/* BotServ SET flags */
+#define OLD_BS_DONTKICKOPS 0x00000001
+#define OLD_BS_DONTKICKVOICES 0x00000002
+#define OLD_BS_FANTASY 0x00000004
+#define OLD_BS_SYMBIOSIS 0x00000008
+#define OLD_BS_GREET 0x00000010
+#define OLD_BS_NOBOT 0x00000020
+
+/* BotServ Kickers flags */
+#define OLD_BS_KICK_BOLDS 0x80000000
+#define OLD_BS_KICK_COLORS 0x40000000
+#define OLD_BS_KICK_REVERSES 0x20000000
+#define OLD_BS_KICK_UNDERLINES 0x10000000
+#define OLD_BS_KICK_BADWORDS 0x08000000
+#define OLD_BS_KICK_CAPS 0x04000000
+#define OLD_BS_KICK_FLOOD 0x02000000
+#define OLD_BS_KICK_REPEAT 0x01000000
+
+#define OLD_NEWS_LOGON 0
+#define OLD_NEWS_OPER 1
+#define OLD_NEWS_RANDOM 2
+
+enum
+{
+ TTB_BOLDS,
+ TTB_COLORS,
+ TTB_REVERSES,
+ TTB_UNDERLINES,
+ TTB_BADWORDS,
+ TTB_CAPS,
+ TTB_FLOOD,
+ TTB_REPEAT,
+};
+
+static struct mlock_info
+{
+ char c;
+ uint32_t m;
+} mlock_infos[] = {
+ {'i', 0x00000001},
+ {'m', 0x00000002},
+ {'n', 0x00000004},
+ {'p', 0x00000008},
+ {'s', 0x00000010},
+ {'t', 0x00000020},
+ {'R', 0x00000100},
+ {'r', 0x00000200},
+ {'c', 0x00000400},
+ {'A', 0x00000800},
+ {'K', 0x00002000},
+ {'O', 0x00008000},
+ {'Q', 0x00010000},
+ {'S', 0x00020000},
+ {'G', 0x00100000},
+ {'C', 0x00200000},
+ {'u', 0x00400000},
+ {'z', 0x00800000},
+ {'N', 0x01000000},
+ {'M', 0x04000000}
+};
+
+static Anope::string hashm;
+
+enum
+{
+ LANG_EN_US, /* United States English */
+ LANG_JA_JIS, /* Japanese (JIS encoding) */
+ LANG_JA_EUC, /* Japanese (EUC encoding) */
+ LANG_JA_SJIS, /* Japanese (SJIS encoding) */
+ LANG_ES, /* Spanish */
+ LANG_PT, /* Portugese */
+ LANG_FR, /* French */
+ LANG_TR, /* Turkish */
+ LANG_IT, /* Italian */
+ LANG_DE, /* German */
+ LANG_CAT, /* Catalan */
+ LANG_GR, /* Greek */
+ LANG_NL, /* Dutch */
+ LANG_RU, /* Russian */
+ LANG_HUN, /* Hungarian */
+ LANG_PL /* Polish */
+};
+
+static void process_mlock(ChanServ::Channel *ci, uint32_t lock, bool status, uint32_t *limit, Anope::string *key)
+{
+ ServiceReference<ModeLocks> mlocks;
+
+ if (!mlocks)
+ return;
+
+ for (unsigned i = 0; i < (sizeof(mlock_infos) / sizeof(mlock_info)); ++i)
+ if (lock & mlock_infos[i].m)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_infos[i].c);
+ if (cm)
+ {
+ if (limit && mlock_infos[i].c == 'l')
+ mlocks->SetMLock(ci, cm, status, stringify(*limit));
+ else if (key && mlock_infos[i].c == 'k')
+ mlocks->SetMLock(ci, cm, status, *key);
+ else
+ mlocks->SetMLock(ci, cm, status);
+ }
+ }
+}
+
+static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+static void my_b64_encode(const Anope::string &src, Anope::string &target)
+{
+ size_t src_pos = 0, src_len = src.length();
+ unsigned char input[3];
+
+ target.clear();
+
+ while (src_len - src_pos > 2)
+ {
+ input[0] = src[src_pos++];
+ input[1] = src[src_pos++];
+ input[2] = src[src_pos++];
+
+ target += Base64[input[0] >> 2];
+ target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)];
+ target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)];
+ target += Base64[input[2] & 0x3f];
+ }
+
+ /* Now we worry about padding */
+ if (src_pos != src_len)
+ {
+ input[0] = input[1] = input[2] = 0;
+ for (size_t i = 0; i < src_len - src_pos; ++i)
+ input[i] = src[src_pos + i];
+
+ target += Base64[input[0] >> 2];
+ target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)];
+ if (src_pos == src_len - 1)
+ target += Pad64;
+ else
+ target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)];
+ target += Pad64;
+ }
+}
+
+static Anope::string Hex(const char *data, size_t l)
+{
+ const char hextable[] = "0123456789abcdef";
+
+ std::string rv;
+ for (size_t i = 0; i < l; ++i)
+ {
+ unsigned char c = data[i];
+ rv += hextable[c >> 4];
+ rv += hextable[c & 0xF];
+ }
+ return rv;
+}
+
+static Anope::string GetLevelName(int level)
+{
+ switch (level)
+ {
+ case 0:
+ return "INVITE";
+ case 1:
+ return "AKICK";
+ case 2:
+ return "SET";
+ case 3:
+ return "UNBAN";
+ case 4:
+ return "AUTOOP";
+ case 5:
+ return "AUTODEOP";
+ case 6:
+ return "AUTOVOICE";
+ case 7:
+ return "OP";
+ case 8:
+ return "ACCESS_LIST";
+ case 9:
+ return "CLEAR";
+ case 10:
+ return "NOJOIN";
+ case 11:
+ return "ACCESS_CHANGE";
+ case 12:
+ return "MEMO";
+ case 13:
+ return "ASSIGN";
+ case 14:
+ return "BADWORDS";
+ case 15:
+ return "NOKICK";
+ case 16:
+ return "FANTASIA";
+ case 17:
+ return "SAY";
+ case 18:
+ return "GREET";
+ case 19:
+ return "VOICEME";
+ case 20:
+ return "VOICE";
+ case 21:
+ return "GETKEY";
+ case 22:
+ return "AUTOHALFOP";
+ case 23:
+ return "AUTOPROTECT";
+ case 24:
+ return "OPME";
+ case 25:
+ return "HALFOPME";
+ case 26:
+ return "HALFOP";
+ case 27:
+ return "PROTECTME";
+ case 28:
+ return "PROTECT";
+ case 29:
+ return "KICKME";
+ case 30:
+ return "KICK";
+ case 31:
+ return "SIGNKICK";
+ case 32:
+ return "BANME";
+ case 33:
+ return "BAN";
+ case 34:
+ return "TOPIC";
+ case 35:
+ return "INFO";
+ default:
+ return "INVALID";
+ }
+}
+
+static char *strscpy(char *d, const char *s, size_t len)
+{
+ char *d_orig = d;
+
+ if (!len)
+ return d;
+ while (--len && (*d++ = *s++));
+ *d = '\0';
+ return d_orig;
+}
+
+struct dbFILE
+{
+ int mode; /* 'r' for reading, 'w' for writing */
+ FILE *fp; /* The normal file descriptor */
+ char filename[1024]; /* Name of the database file */
+};
+
+static dbFILE *open_db_read(const char *service, const char *filename, int version)
+{
+ dbFILE *f;
+ FILE *fp;
+ int myversion;
+
+ f = new dbFILE;
+ strscpy(f->filename, (Anope::DataDir + "/" + filename).c_str(), sizeof(f->filename));
+ f->mode = 'r';
+ fp = fopen(f->filename, "rb");
+ if (!fp)
+ {
+ Anope::Logger.Log("Can't read {0} database {1}", service, f->filename);
+ delete f;
+ return NULL;
+ }
+ f->fp = fp;
+ myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
+ if (feof(fp))
+ {
+ Anope::Logger.Log("Error reading version number on {0}: End of file detected.", f->filename);
+ delete f;
+ return NULL;
+ }
+ else if (myversion < version)
+ {
+ Anope::Logger.Log("Unsuported database version ({0}) on {1}.", myversion, f->filename);
+ delete f;
+ return NULL;
+ }
+ return f;
+}
+
+void close_db(dbFILE *f)
+{
+ fclose(f->fp);
+ delete f;
+}
+
+static int read_int16(int16_t *ret, dbFILE *f)
+{
+ int c1, c2;
+
+ *ret = 0;
+
+ c1 = fgetc(f->fp);
+ c2 = fgetc(f->fp);
+ if (c1 == EOF || c2 == EOF)
+ return -1;
+ *ret = c1 << 8 | c2;
+ return 0;
+}
+
+static int read_uint16(uint16_t *ret, dbFILE *f)
+{
+ int c1, c2;
+
+ *ret = 0;
+
+ c1 = fgetc(f->fp);
+ c2 = fgetc(f->fp);
+ if (c1 == EOF || c2 == EOF)
+ return -1;
+ *ret = c1 << 8 | c2;
+ return 0;
+}
+
+static int read_string(Anope::string &str, dbFILE *f)
+{
+ str.clear();
+ uint16_t len;
+
+ if (read_uint16(&len, f) < 0)
+ return -1;
+ if (len == 0)
+ return 0;
+ char *s = new char[len];
+ if (len != fread(s, 1, len, f->fp))
+ {
+ delete [] s;
+ return -1;
+ }
+ str = s;
+ delete [] s;
+ return 0;
+}
+
+static int read_uint32(uint32_t *ret, dbFILE *f)
+{
+ int c1, c2, c3, c4;
+
+ *ret = 0;
+
+ c1 = fgetc(f->fp);
+ c2 = fgetc(f->fp);
+ c3 = fgetc(f->fp);
+ c4 = fgetc(f->fp);
+ if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
+ return -1;
+ *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
+ return 0;
+}
+
+int read_int32(int32_t *ret, dbFILE *f)
+{
+ int c1, c2, c3, c4;
+
+ *ret = 0;
+
+ c1 = fgetc(f->fp);
+ c2 = fgetc(f->fp);
+ c3 = fgetc(f->fp);
+ c4 = fgetc(f->fp);
+ if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
+ return -1;
+ *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
+ return 0;
+}
+
+static void LoadNicks()
+{
+ if (!NickServ::service)
+ return;
+ dbFILE *f = open_db_read("NickServ", "nick.db", 14);
+ if (f == NULL)
+ return;
+ for (int i = 0; i < 1024; ++i)
+ for (int c; (c = getc_db(f)) == 1;)
+ {
+ Anope::string buffer;
+
+ READ(read_string(buffer, f));
+
+ NickServ::Account *nc = Serialize::New<NickServ::Account *>();
+ nc->SetDisplay(buffer);
+
+ const Anope::string settings[] = { "killprotect", "kill_quick", "secure", "private", "hide_email",
+ "hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "keepmodes" };
+ for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
+ nc->UnsetS<bool>(settings[j]);
+
+ char pwbuf[32];
+ READ(read_buffer(pwbuf, f));
+ if (hashm == "plain")
+ {
+ Anope::string p;
+ my_b64_encode(pwbuf, p);
+ nc->SetPassword(p);
+ }
+ else if (hashm == "md5" || hashm == "oldmd5")
+ nc->SetPassword(Hex(pwbuf, 16));
+ else if (hashm == "sha1")
+ nc->SetPassword(Hex(pwbuf, 20));
+ else
+ nc->SetPassword(Hex(pwbuf, strlen(pwbuf)));
+ nc->SetPassword(hashm + ":" + nc->GetPassword());
+
+ READ(read_string(buffer, f));
+ nc->SetEmail(buffer);
+
+ READ(read_string(buffer, f));
+ if (!buffer.empty())
+ nc->SetGreet(buffer);
+
+ uint32_t u32;
+ READ(read_uint32(&u32, f));
+ //nc->icq = u32;
+
+ READ(read_string(buffer, f));
+ //nc->url = buffer;
+
+ READ(read_uint32(&u32, f));
+ if (u32 & OLD_NI_KILLPROTECT)
+ nc->SetKillProtect(true);
+ if (u32 & OLD_NI_SECURE)
+ nc->SetSecure(true);
+ if (u32 & OLD_NI_MSG)
+ nc->SetMsg(true);
+ if (u32 & OLD_NI_MEMO_HARDMAX)
+ if (MemoServ::MemoInfo *mi = nc->GetMemos())
+ mi->SetHardMax(true);
+ if (u32 & OLD_NI_MEMO_SIGNON)
+ nc->SetMemoSignon(true);
+ if (u32 & OLD_NI_MEMO_RECEIVE)
+ nc->SetMemoReceive(true);
+ if (u32 & OLD_NI_PRIVATE)
+ nc->SetPrivate(true);
+ if (u32 & OLD_NI_HIDE_EMAIL)
+ nc->SetHideEmail(true);
+ if (u32 & OLD_NI_HIDE_MASK)
+ nc->SetHideMask(true);
+ if (u32 & OLD_NI_HIDE_QUIT)
+ nc->SetHideQuit(true);
+ if (u32 & OLD_NI_KILL_QUICK)
+ nc->SetKillQuick(true);
+ if (u32 & OLD_NI_KILL_IMMED)
+ nc->SetKillImmed(true);
+ if (u32 & OLD_NI_MEMO_MAIL)
+ nc->SetMemoMail(true);
+ if (u32 & OLD_NI_HIDE_STATUS)
+ nc->SetHideStatus(true);
+ if (u32 & OLD_NI_SUSPENDED)
+ {
+ NSSuspendInfo *si = Serialize::New<NSSuspendInfo *>();
+ if (si)
+ {
+ si->SetAccount(nc);
+ }
+ }
+ if (!(u32 & OLD_NI_AUTOOP))
+ nc->SetAutoOp(true);
+
+ uint16_t u16;
+ READ(read_uint16(&u16, f));
+ switch (u16)
+ {
+ case LANG_ES:
+ nc->SetLanguage("es_ES.UTF-8");
+ break;
+ case LANG_PT:
+ nc->SetLanguage("pt_PT.UTF-8");
+ break;
+ case LANG_FR:
+ nc->SetLanguage("fr_FR.UTF-8");
+ break;
+ case LANG_TR:
+ nc->SetLanguage("tr_TR.UTF-8");
+ break;
+ case LANG_IT:
+ nc->SetLanguage("it_IT.UTF-8");
+ break;
+ case LANG_DE:
+ nc->SetLanguage("de_DE.UTF-8");
+ break;
+ case LANG_CAT:
+ nc->SetLanguage("ca_ES.UTF-8"); // yes, iso639 defines catalan as CA
+ break;
+ case LANG_GR:
+ nc->SetLanguage("el_GR.UTF-8");
+ break;
+ case LANG_NL:
+ nc->SetLanguage("nl_NL.UTF-8");
+ break;
+ case LANG_RU:
+ nc->SetLanguage("ru_RU.UTF-8");
+ break;
+ case LANG_HUN:
+ nc->SetLanguage("hu_HU.UTF-8");
+ break;
+ case LANG_PL:
+ nc->SetLanguage("pl_PL.UTF-8");
+ break;
+ case LANG_EN_US:
+ case LANG_JA_JIS:
+ case LANG_JA_EUC:
+ case LANG_JA_SJIS: // these seem to be unused
+ default:
+ nc->SetLanguage("en");
+ }
+
+ READ(read_uint16(&u16, f));
+ for (uint16_t j = 0; j < u16; ++j)
+ {
+ READ(read_string(buffer, f));
+
+ NickAccess *a = Serialize::New<NickAccess *>();
+ if (a)
+ {
+ a->SetAccount(nc);
+ a->SetMask(buffer);
+ }
+ }
+
+ int16_t i16;
+ READ(read_int16(&i16, f));
+ READ(read_int16(&i16, f));
+ MemoServ::MemoInfo *mi = nc->GetMemos();
+ if (mi)
+ mi->SetMemoMax(i16);
+ for (int16_t j = 0; j < i16; ++j)
+ {
+ MemoServ::Memo *m = Serialize::New<MemoServ::Memo *>();
+ READ(read_uint32(&u32, f));
+ uint16_t flags;
+ READ(read_uint16(&flags, f));
+ int32_t tmp32;
+ READ(read_int32(&tmp32, f));
+ if (m)
+ m->SetTime(tmp32);
+ char sbuf[32];
+ READ(read_buffer(sbuf, f));
+ if (m)
+ m->SetSender(sbuf);
+ Anope::string text;
+ READ(read_string(text, f));
+ if (m)
+ m->SetText(text);
+ }
+ READ(read_uint16(&u16, f));
+ READ(read_int16(&i16, f));
+
+ Anope::Logger.Debug("Loaded nickserv account {0}", nc->GetDisplay());
+ }
+
+ for (int i = 0; i < 1024; ++i)
+ for (int c; (c = getc_db(f)) == 1;)
+ {
+ Anope::string nick, last_usermask, last_realname, last_quit;
+ time_t time_registered, last_seen;
+
+ READ(read_string(nick, f));
+ READ(read_string(last_usermask, f));
+ READ(read_string(last_realname, f));
+ READ(read_string(last_quit, f));
+
+ int32_t tmp32;
+ READ(read_int32(&tmp32, f));
+ time_registered = tmp32;
+ READ(read_int32(&tmp32, f));
+ last_seen = tmp32;
+
+ uint16_t tmpu16;
+ READ(read_uint16(&tmpu16, f));
+
+ Anope::string core;
+ READ(read_string(core, f));
+ NickServ::Account *nc = NickServ::FindAccount(core);
+ if (nc == NULL)
+ {
+ Anope::Logger.Debug("Skipping coreless nick {0} with core {1}", nick, core);
+ continue;
+ }
+
+ if (tmpu16 & OLD_NS_VERBOTEN)
+ {
+ if (nc->GetDisplay().find_first_of("?*") != Anope::string::npos)
+ {
+ delete nc;
+ continue;
+ }
+
+ ForbidData *d = Serialize::New<ForbidData *>();
+ if (d)
+ {
+ d->SetMask(nc->GetDisplay());
+ d->SetCreator(last_usermask);
+ d->SetReason(last_realname);
+ d->SetType(FT_NICK);
+ }
+
+ delete nc;
+ continue;
+ }
+
+ NickServ::Nick *na = Serialize::New<NickServ::Nick *>();
+ na->SetNick(nick);
+ na->SetAccount(nc);
+ na->SetLastUsermask(last_usermask);
+ na->SetLastRealname(last_realname);
+ na->SetLastQuit(last_quit);
+ na->SetTimeRegistered(time_registered);
+ na->SetLastSeen(last_seen);
+
+ if (tmpu16 & OLD_NS_NO_EXPIRE)
+ na->SetNoExpire(true);
+
+ Anope::Logger.Debug("Loaded nick {0}", na->GetNick());
+ }
+
+ close_db(f); /* End of section Ia */
+}
+
+static void LoadVHosts()
+{
+ dbFILE *f = open_db_read("HostServ", "hosts.db", 3);
+ if (f == NULL)
+ return;
+
+ for (int c; (c = getc_db(f)) == 1;)
+ {
+ Anope::string nick, ident, host, creator;
+ int32_t vtime;
+
+ READ(read_string(nick, f));
+ READ(read_string(ident, f));
+ READ(read_string(host, f));
+ READ(read_string(creator, f));
+ READ(read_int32(&vtime, f));
+
+ NickServ::Nick *na = NickServ::FindNick(nick);
+ if (na == NULL)
+ {
+ Anope::Logger.Log("Removing vhost for non-existent nick {0}", nick);
+ continue;
+ }
+
+ HostServ::VHost *vhost = Serialize::New<HostServ::VHost *>();
+ if (vhost == nullptr)
+ continue;
+
+ vhost->SetAccount(na->GetAccount());
+ vhost->SetIdent(ident);
+ vhost->SetHost(host);
+ vhost->SetCreator(creator);
+ vhost->SetCreated(vtime);
+
+ Anope::Logger.Debug("Loaded vhost for {0}", na->GetNick());
+ }
+
+ close_db(f);
+}
+
+static void LoadBots()
+{
+ dbFILE *f = open_db_read("Botserv", "bot.db", 10);
+ if (f == NULL)
+ return;
+
+ for (int c; (c = getc_db(f)) == 1;)
+ {
+ Anope::string nick, user, host, real;
+ int16_t flags, chancount;
+ int32_t created;
+
+ READ(read_string(nick, f));
+ READ(read_string(user, f));
+ READ(read_string(host, f));
+ READ(read_string(real, f));
+ READ(read_int16(&flags, f));
+ READ(read_int32(&created, f));
+ READ(read_int16(&chancount, f));
+
+ ServiceBot *bi = ServiceBot::Find(nick, true);
+ if (!bi)
+ bi = new ServiceBot(nick, user, host, real);
+
+ if (bi->bi == nullptr)
+ bi->bi = Serialize::New<BotInfo *>();
+
+ bi->bi->SetCreated(created);
+
+ if (flags & OLD_BI_PRIVATE)
+ bi->bi->SetOperOnly(true);
+
+ Anope::Logger.Debug("Loaded bot {0}", bi->nick);
+ }
+
+ close_db(f);
+}
+
+static void LoadChannels()
+{
+ ServiceReference<BadWords> badwords;
+ ServiceReference<ChanServ::ChanServService> chanserv;
+
+ if (!chanserv)
+ return;
+
+ ServiceReference<ForbidService> forbid;
+ dbFILE *f = open_db_read("ChanServ", "chan.db", 16);
+ if (f == NULL)
+ return;
+
+ for (int i = 0; i < 256; ++i)
+ for (int c; (c = getc_db(f)) == 1;)
+ {
+ Anope::string buffer;
+ char namebuf[64];
+ READ(read_buffer(namebuf, f));
+ ChanServ::Channel *ci = Serialize::New<ChanServ::Channel *>();
+ ci->SetName(namebuf);
+
+ const Anope::string settings[] = { "keeptopic", "peace", "private", "restricted", "secure", "secureops", "securefounder",
+ "signkick", "signkick_level", "topiclock", "persist", "noautoop", "keepmodes" };
+ for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
+ ci->UnsetS<bool>(settings[j]);
+
+ READ(read_string(buffer, f));
+ ci->SetFounder(NickServ::FindAccount(buffer));
+
+ READ(read_string(buffer, f));
+ ci->SetSuccessor(NickServ::FindAccount(buffer));
+
+ char pwbuf[32];
+ READ(read_buffer(pwbuf, f));
+
+ Anope::string desc;
+ READ(read_string(desc, f));
+ ci->SetDesc(desc);
+ READ(read_string(buffer, f));
+ READ(read_string(buffer, f));
+
+ int32_t tmp32;
+ READ(read_int32(&tmp32, f));
+ ci->SetTimeRegistered(tmp32);
+
+ READ(read_int32(&tmp32, f));
+ ci->SetLastUsed(tmp32);
+
+ Anope::string last_topic;
+ READ(read_string(last_topic, f));
+ ci->SetLastTopic(last_topic);
+
+ READ(read_buffer(pwbuf, f));
+ ci->SetLastTopicSetter(pwbuf);
+
+ READ(read_int32(&tmp32, f));
+ ci->SetLastTopicTime(tmp32);
+
+ uint32_t tmpu32;
+ READ(read_uint32(&tmpu32, f));
+ // Temporary flags cleanup
+ tmpu32 &= ~0x80000000;
+ if (tmpu32 & OLD_CI_KEEPTOPIC)
+ ci->SetKeepTopic(true);
+ if (tmpu32 & OLD_CI_SECUREOPS)
+ ci->SetSecureOps(true);
+ if (tmpu32 & OLD_CI_PRIVATE)
+ ci->SetPrivate(true);
+ if (tmpu32 & OLD_CI_TOPICLOCK)
+ ci->SetTopicLock(true);
+ if (tmpu32 & OLD_CI_RESTRICTED)
+ ci->SetRestricted(true);
+ if (tmpu32 & OLD_CI_PEACE)
+ ci->SetPeace(true);
+ if (tmpu32 & OLD_CI_SECURE)
+ ci->SetSecure(true);
+ if (tmpu32 & OLD_CI_NO_EXPIRE)
+ ci->SetNoExpire(true);
+ if (tmpu32 & OLD_CI_MEMO_HARDMAX)
+ if (MemoServ::MemoInfo *mi = ci->GetMemos())
+ mi->SetHardMax(true);
+ if (tmpu32 & OLD_CI_SECUREFOUNDER)
+ ci->SetSecureFounder(true);
+ if (tmpu32 & OLD_CI_SIGNKICK)
+ ci->SetSignKick(true);
+ if (tmpu32 & OLD_CI_SIGNKICK_LEVEL)
+ ci->SetSignKickLevel(true);
+
+ Anope::string forbidby, forbidreason;
+ READ(read_string(forbidby, f));
+ READ(read_string(forbidreason, f));
+ if (tmpu32 & OLD_CI_SUSPENDED)
+ {
+ CSSuspendInfo *si = Serialize::New<CSSuspendInfo *>();
+ if (si)
+ {
+ si->SetChannel(ci);
+ si->SetBy(forbidby);
+ }
+ }
+ bool forbid_chan = tmpu32 & OLD_CI_VERBOTEN;
+
+ int16_t tmp16;
+ READ(read_int16(&tmp16, f));
+ ci->SetBanType(tmp16);
+
+ READ(read_int16(&tmp16, f));
+ if (tmp16 > 36)
+ tmp16 = 36;
+ for (int16_t j = 0; j < tmp16; ++j)
+ {
+ int16_t level;
+ READ(read_int16(&level, f));
+
+ if (level == ChanServ::ACCESS_INVALID)
+ level = ChanServ::ACCESS_FOUNDER;
+
+ if (j == 10 && level < 0) // NOJOIN
+ ci->SetRestricted(false);
+
+ ci->SetLevel(GetLevelName(j), level);
+ }
+
+ bool xop = tmpu32 & OLD_CI_XOP;
+ uint16_t tmpu16;
+ READ(read_uint16(&tmpu16, f));
+ for (uint16_t j = 0; j < tmpu16; ++j)
+ {
+ uint16_t in_use;
+ READ(read_uint16(&in_use, f));
+ if (in_use)
+ {
+ ChanServ::ChanAccess *access = NULL;
+
+ if (xop)
+ {
+ access = Serialize::New<XOPChanAccess *>();
+ }
+ else
+ {
+ access = Serialize::New<AccessChanAccess *>();
+ }
+
+ if (access)
+ access->SetChannel(ci);
+
+ int16_t level;
+ READ(read_int16(&level, f));
+ if (access)
+ {
+ if (xop)
+ {
+ switch (level)
+ {
+ case 3:
+ access->AccessUnserialize("VOP");
+ break;
+ case 4:
+ access->AccessUnserialize("HOP");
+ break;
+ case 5:
+ access->AccessUnserialize("AOP");
+ break;
+ case 10:
+ access->AccessUnserialize("SOP");
+ break;
+ }
+ }
+ else
+ access->AccessUnserialize(stringify(level));
+ }
+
+ Anope::string mask;
+ READ(read_string(mask, f));
+ if (access)
+ {
+ access->SetMask(mask);
+ NickServ::Nick *na = NickServ::FindNick(mask);
+ if (na)
+ na->SetAccount(na->GetAccount());
+ }
+
+ READ(read_int32(&tmp32, f));
+ if (access)
+ {
+ access->SetLastSeen(tmp32);
+ access->SetCreator("Unknown");
+ access->SetCreated(Anope::CurTime);
+ }
+ }
+ }
+
+ READ(read_uint16(&tmpu16, f));
+ for (uint16_t j = 0; j < tmpu16; ++j)
+ {
+ uint16_t flags;
+ READ(read_uint16(&flags, f));
+ if (flags & 0x0001)
+ {
+ Anope::string mask, reason, creator;
+ READ(read_string(mask, f));
+ READ(read_string(reason, f));
+ READ(read_string(creator, f));
+ READ(read_int32(&tmp32, f));
+
+ ci->AddAkick(creator, mask, reason, tmp32);
+ }
+ }
+
+ READ(read_uint32(&tmpu32, f)); // mlock on
+ ci->Extend<uint32_t>("mlock_on", tmpu32);
+ READ(read_uint32(&tmpu32, f)); // mlock off
+ ci->Extend<uint32_t>("mlock_off", tmpu32);
+ READ(read_uint32(&tmpu32, f)); // mlock limit
+ ci->Extend<uint32_t>("mlock_limit", tmpu32);
+ READ(read_string(buffer, f)); // key
+ ci->Extend<Anope::string>("mlock_key", buffer);
+ READ(read_string(buffer, f)); // +f
+ READ(read_string(buffer, f)); // +L
+
+ READ(read_int16(&tmp16, f));
+ READ(read_int16(&tmp16, f));
+ MemoServ::MemoInfo *mi = ci->GetMemos();
+ if (mi)
+ mi->SetMemoMax(tmp16);
+ for (int16_t j = 0; j < tmp16; ++j)
+ {
+ READ(read_uint32(&tmpu32, f));
+ READ(read_uint16(&tmpu16, f));
+ MemoServ::Memo *m = Serialize::New<MemoServ::Memo *>();
+ READ(read_int32(&tmp32, f));
+ if (m)
+ m->SetTime(tmp32);
+ char sbuf[32];
+ READ(read_buffer(sbuf, f));
+ if (m)
+ m->SetSender(sbuf);
+ Anope::string text;
+ READ(read_string(text, f));
+ if (m)
+ m->SetText(text);
+ }
+
+ READ(read_string(buffer, f));
+ if (!buffer.empty())
+ {
+ EntryMsg *e = Serialize::New<EntryMsg *>();
+ if (e)
+ {
+ e->SetChannel(ci);
+ e->SetCreator("Unknown");
+ e->SetMessage(buffer);
+ e->SetWhen(Anope::CurTime);
+ }
+ }
+
+ READ(read_string(buffer, f));
+ ci->SetBot(ServiceBot::Find(buffer, true));
+
+ READ(read_int32(&tmp32, f));
+ if (tmp32 & OLD_BS_DONTKICKOPS)
+ ci->SetS<bool>("BS_DONTKICKOPS", true);
+ if (tmp32 & OLD_BS_DONTKICKVOICES)
+ ci->SetS<bool>("BS_DONTKICKVOICES", true);
+ if (tmp32 & OLD_BS_FANTASY)
+ ci->SetFantasy(true);
+ if (tmp32 & OLD_BS_GREET)
+ ci->SetGreet(true);
+ if (tmp32 & OLD_BS_NOBOT)
+ ci->SetS<bool>("BS_NOBOT", true);
+
+ KickerData *kd = GetKickerData(ci);
+ if (kd)
+ {
+ kd->SetBolds(tmp32 & OLD_BS_KICK_BOLDS);
+ kd->SetColors(tmp32 & OLD_BS_KICK_COLORS);
+ kd->SetReverses(tmp32 & OLD_BS_KICK_REVERSES);
+ kd->SetUnderlines(tmp32 & OLD_BS_KICK_UNDERLINES);
+ kd->SetBadwords(tmp32 & OLD_BS_KICK_BADWORDS);
+ kd->SetCaps(tmp32 & OLD_BS_KICK_CAPS);
+ kd->SetFlood(tmp32 & OLD_BS_KICK_FLOOD);
+ kd->SetRepeat(tmp32 & OLD_BS_KICK_REPEAT);
+ }
+
+ READ(read_int16(&tmp16, f));
+ for (int16_t j = 0; j < tmp16; ++j)
+ {
+ int16_t ttb;
+ READ(read_int16(&ttb, f));
+ switch (j)
+ {
+ case TTB_BOLDS:
+ kd->SetTTBBolds(ttb);
+ break;
+ case TTB_COLORS:
+ kd->SetTTBColors(ttb);
+ break;
+ case TTB_REVERSES:
+ kd->SetTTBReverses(ttb);
+ break;
+ case TTB_UNDERLINES:
+ kd->SetTTBUnderlines(ttb);
+ break;
+ case TTB_BADWORDS:
+ kd->SetTTBBadwords(ttb);
+ break;
+ case TTB_CAPS:
+ kd->SetTTBCaps(ttb);
+ break;
+ case TTB_FLOOD:
+ kd->SetTTBFlood(ttb);
+ break;
+ case TTB_REPEAT:
+ kd->SetTTBRepeat(ttb);
+ break;
+ }
+ }
+
+ READ(read_int16(&tmp16, f));
+ if (kd)
+ kd->SetCapsMin(tmp16);
+ READ(read_int16(&tmp16, f));
+ if (kd)
+ kd->SetCapsPercent(tmp16);
+ READ(read_int16(&tmp16, f));
+ if (kd)
+ kd->SetFloodLines(tmp16);
+ READ(read_int16(&tmp16, f));
+ if (kd)
+ kd->SetFloodSecs(tmp16);
+ READ(read_int16(&tmp16, f));
+ if (kd)
+ kd->SetRepeatTimes(tmp16);
+
+ READ(read_uint16(&tmpu16, f));
+ for (uint16_t j = 0; j < tmpu16; ++j)
+ {
+ uint16_t in_use;
+ READ(read_uint16(&in_use, f));
+ if (in_use)
+ {
+ READ(read_string(buffer, f));
+ uint16_t type;
+ READ(read_uint16(&type, f));
+
+ BadWordType bwtype = BW_ANY;
+ if (type == 1)
+ bwtype = BW_SINGLE;
+ else if (type == 2)
+ bwtype = BW_START;
+ else if (type == 3)
+ bwtype = BW_END;
+
+ if (badwords)
+ badwords->AddBadWord(ci, buffer, bwtype);
+ }
+ }
+
+ if (forbid_chan)
+ {
+ if (ci->GetName().find_first_of("?*") != Anope::string::npos)
+ {
+ delete ci;
+ continue;
+ }
+
+ ForbidData *d = Serialize::New<ForbidData *>();
+ if (d)
+ {
+ d->SetMask(ci->GetName());
+ d->SetCreator(forbidby);
+ d->SetReason(forbidreason);
+ d->SetType(FT_CHAN);
+ }
+
+ delete ci;
+ continue;
+ }
+
+ Anope::Logger.Debug("Loaded channel {0}", ci->GetName());
+ }
+
+ close_db(f);
+}
+
+static void LoadOper()
+{
+ dbFILE *f = open_db_read("OperServ", "oper.db", 13);
+ if (f == NULL)
+ return;
+
+ XLineManager *akill, *sqline, *snline, *szline;
+ akill = sqline = snline = szline = NULL;
+
+ for (XLineManager *xl : XLineManager::XLineManagers)
+ {
+ if (xl->Type() == 'G')
+ akill = xl;
+ else if (xl->Type() == 'Q')
+ sqline = xl;
+ else if (xl->Type() == 'N')
+ snline = xl;
+ else if (xl->Type() == 'Z')
+ szline = xl;
+ }
+
+ int32_t tmp32;
+ READ(read_int32(&tmp32, f));
+ READ(read_int32(&tmp32, f));
+
+ int16_t capacity;
+ read_int16(&capacity, f); // AKill count
+ for (int16_t i = 0; i < capacity; ++i)
+ {
+ Anope::string user, host, by, reason;
+ int32_t seton, expires;
+
+ READ(read_string(user, f));
+ READ(read_string(host, f));
+ READ(read_string(by, f));
+ READ(read_string(reason, f));
+ READ(read_int32(&seton, f));
+ READ(read_int32(&expires, f));
+
+ if (!akill)
+ continue;
+
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(user + "@" + host);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
+ akill->AddXLine(x);
+ }
+
+ read_int16(&capacity, f); // SNLines
+ for (int16_t i = 0; i < capacity; ++i)
+ {
+ Anope::string mask, by, reason;
+ int32_t seton, expires;
+
+ READ(read_string(mask, f));
+ READ(read_string(by, f));
+ READ(read_string(reason, f));
+ READ(read_int32(&seton, f));
+ READ(read_int32(&expires, f));
+
+ if (!snline)
+ continue;
+
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
+ snline->AddXLine(x);
+ }
+
+ read_int16(&capacity, f); // SQLines
+ for (int16_t i = 0; i < capacity; ++i)
+ {
+ Anope::string mask, by, reason;
+ int32_t seton, expires;
+
+ READ(read_string(mask, f));
+ READ(read_string(by, f));
+ READ(read_string(reason, f));
+ READ(read_int32(&seton, f));
+ READ(read_int32(&expires, f));
+
+ if (!sqline)
+ continue;
+
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
+ sqline->AddXLine(x);
+ }
+
+ read_int16(&capacity, f); // SZLines
+ for (int16_t i = 0; i < capacity; ++i)
+ {
+ Anope::string mask, by, reason;
+ int32_t seton, expires;
+
+ READ(read_string(mask, f));
+ READ(read_string(by, f));
+ READ(read_string(reason, f));
+ READ(read_int32(&seton, f));
+ READ(read_int32(&expires, f));
+
+ if (!szline)
+ continue;
+
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
+ szline->AddXLine(x);
+ }
+
+ close_db(f);
+}
+
+static void LoadExceptions()
+{
+ dbFILE *f = open_db_read("OperServ", "exception.db", 9);
+ if (f == NULL)
+ return;
+
+ int16_t num;
+ READ(read_int16(&num, f));
+ for (int i = 0; i < num; ++i)
+ {
+ Anope::string mask, reason;
+ int16_t limit;
+ char who[32];
+ int32_t time, expires;
+
+ READ(read_string(mask, f));
+ READ(read_int16(&limit, f));
+ READ(read_buffer(who, f));
+ READ(read_string(reason, f));
+ READ(read_int32(&time, f));
+ READ(read_int32(&expires, f));
+
+ Exception *e = Serialize::New<Exception *>();
+ if (e)
+ {
+ e->SetMask(mask);
+ e->SetLimit(limit);
+ e->SetWho(who);
+ e->SetTime(time);
+ e->SetExpires(expires);
+ e->SetReason(reason);
+ }
+ }
+
+ close_db(f);
+}
+
+static void LoadNews()
+{
+ dbFILE *f = open_db_read("OperServ", "news.db", 9);
+
+ if (f == NULL)
+ return;
+
+ int16_t n;
+ READ(read_int16(&n, f));
+
+ for (int16_t i = 0; i < n; i++)
+ {
+ int16_t type;
+ NewsItem *ni = Serialize::New<NewsItem *>();
+
+ if (!ni)
+ break;
+
+ READ(read_int16(&type, f));
+
+ switch (type)
+ {
+ case OLD_NEWS_LOGON:
+ ni->SetNewsType(NEWS_LOGON);
+ break;
+ case OLD_NEWS_OPER:
+ ni->SetNewsType(NEWS_OPER);
+ break;
+ case OLD_NEWS_RANDOM:
+ ni->SetNewsType(NEWS_RANDOM);
+ break;
+ }
+
+ int32_t unused;
+ READ(read_int32(&unused, f));
+
+ Anope::string text;
+ READ(read_string(text, f));
+ ni->SetText(text);
+
+ char who[32];
+ READ(read_buffer(who, f));
+ ni->SetWho(who);
+
+ int32_t tmp;
+ READ(read_int32(&tmp, f));
+ ni->SetTime(tmp);
+ }
+
+ close_db(f);
+}
+
+class DBOld : public Module
+ , public EventHook<Event::LoadDatabase>
+ , public EventHook<Event::UplinkSync>
+{
+ ExtensibleItem<uint32_t> mlock_on, mlock_off, mlock_limit; // XXX these are no longer required because of confmodes
+ ExtensibleItem<Anope::string> mlock_key;
+
+ public:
+ DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ , EventHook<Event::LoadDatabase>(this)
+ , EventHook<Event::UplinkSync>(this)
+ , mlock_on(this, "mlock_on")
+ , mlock_off(this, "mlock_off")
+ , mlock_limit(this, "mlock_limit")
+ , mlock_key(this, "mlock_key")
+ {
+ hashm = Config->GetModule(this)->Get<Anope::string>("hash");
+
+ if (hashm != "md5" && hashm != "oldmd5" && hashm != "sha1" && hashm != "plain" && hashm != "sha256")
+ throw ModuleException("Invalid hash method");
+ }
+
+ EventReturn OnLoadDatabase() override
+ {
+ LoadNicks();
+ LoadVHosts();
+ LoadBots();
+ LoadChannels();
+ LoadOper();
+ LoadExceptions();
+ LoadNews();
+
+ return EVENT_STOP;
+ }
+
+ void OnUplinkSync(Server *s) override
+ {
+ if (!ChanServ::service)
+ return;
+ for (auto& it : ChanServ::service->GetChannels())
+ {
+ ChanServ::Channel *ci = it.second;
+ uint32_t *limit = mlock_limit.Get(ci);
+ Anope::string *key = mlock_key.Get(ci);
+
+ uint32_t *u = mlock_on.Get(ci);
+ if (u)
+ {
+ process_mlock(ci, *u, true, limit, key);
+ mlock_on.Unset(ci);
+ }
+
+ u = mlock_off.Get(ci);
+ if (u)
+ {
+ process_mlock(ci, *u, false, limit, key);
+ mlock_off.Unset(ci);
+ }
+
+ mlock_limit.Unset(ci);
+ mlock_key.Unset(ci);
+
+ if (ci->c)
+ ci->c->CheckModes();
+ }
+ }
+};
+
+template<> void ModuleInfo<DBOld>(ModuleDef *def)
+{
+ def->Depends("chanserv.access");
+}
+
+MODULE_INIT(DBOld)
+