diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/botserv.c | 31 | ||||
-rw-r--r-- | src/chanserv.c | 50 | ||||
-rw-r--r-- | src/config.c | 2 | ||||
-rw-r--r-- | src/hostserv.c | 33 | ||||
-rw-r--r-- | src/init.c | 34 | ||||
-rw-r--r-- | src/main.c | 36 | ||||
-rw-r--r-- | src/mysql.c | 1755 | ||||
-rw-r--r-- | src/news.c | 19 | ||||
-rw-r--r-- | src/nickserv.c | 112 | ||||
-rw-r--r-- | src/operserv.c | 13 | ||||
-rw-r--r-- | src/rdb.c | 452 | ||||
-rw-r--r-- | src/sessions.c | 19 |
12 files changed, 2324 insertions, 232 deletions
diff --git a/src/botserv.c b/src/botserv.c index 15f09e5c8..4b5ce1561 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -722,6 +722,28 @@ void save_bs_dbase(void) /*************************************************************************/ +void save_bs_rdb_dbase(void) +{ +#ifdef USE_RDB + int i; + BotInfo *bi; + + if (!rdb_open()) + return; + + rdb_clear_table("anope_bs_core"); + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + rdb_save_bs_core(bi); + } + } + rdb_close(); +#endif +} + +/*************************************************************************/ + /* Inserts a bot in the bot list. I can't be much explicit mh? */ static void insert_bot(BotInfo * bi) @@ -778,7 +800,6 @@ static void change_bot_nick(BotInfo * bi, char *newnick) static int delbot(BotInfo * bi) { cs_remove_bot(bi); - rdb_bs_del_bot(bi); if (bi->next) bi->next->prev = bi->prev; @@ -826,7 +847,6 @@ static void unassign(User * u, ChannelInfo * ci) u->nick); } ci->bi->chancount--; - rdb_bs_change_bot_chancount(ci->bi); ci->bi = NULL; } @@ -1371,8 +1391,6 @@ static int do_bot(User * u) bi->real = sstrdup(real); bi->created = time(NULL); bi->chancount = 0; - - rdb_bs_add_bot(bi); /* We check whether user with this nick is online, and kill it if so */ EnforceQlinedNick(nick, s_BotServ); @@ -1499,8 +1517,6 @@ static int do_bot(User * u) /* We check whether user with this nick is online, and kill it if so */ EnforceQlinedNick(nick, s_BotServ); } - - rdb_bs_change_bot(bi, nick, user, host ,real); if (strcmp(nick, bi->nick)) change_bot_nick(bi, nick); @@ -1637,7 +1653,6 @@ static int do_assign(User * u) unassign(u, ci); ci->bi = bi; bi->chancount++; - rdb_bs_change_bot_chancount(bi); if (ci->c && ci->c->usercount >= BSMinUsers) { bot_join(ci); } @@ -1906,11 +1921,9 @@ static int do_set(User * u) if ((bi = findbot(chan))) { if (!stricmp(value, "ON")) { bi->flags |= BI_PRIVATE; - rdb_bs_change_bot_flags(bi); notice_lang(s_BotServ, u, BOT_SET_PRIVATE_ON, bi->nick); } else if (!stricmp(value, "OFF")) { bi->flags &= ~BI_PRIVATE; - rdb_bs_change_bot_flags(bi); notice_lang(s_BotServ, u, BOT_SET_PRIVATE_OFF, bi->nick); } else { syntax_error(s_BotServ, u, "SET PRIVATE", diff --git a/src/chanserv.c b/src/chanserv.c index eabfd643b..06236c547 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -1288,6 +1288,35 @@ void save_cs_dbase(void) /*************************************************************************/ +void save_cs_rdb_dbase(void) +{ +#ifdef USE_RDB + int i; + ChannelInfo *ci; + + if (!rdb_open()) + return; + + rdb_tag_table("anope_cs_info"); + rdb_scrub_table("anope_ms_info", "serv='CHAN'"); + rdb_clear_table("anope_cs_access"); + rdb_clear_table("anope_cs_levels"); + rdb_clear_table("anope_cs_akicks"); + rdb_clear_table("anope_cs_badwords"); + + for (i = 0; i < 256; i++) { + for (ci = chanlists[i]; ci; ci = ci->next) { + rdb_save_cs_info(ci); + } /* for (chanlists[i]) */ + } /* for (i) */ + + rdb_scrub_table("anope_cs_info", "active='0'"); + rdb_close(); +#endif +} + +/*************************************************************************/ + /* Check the current modes on a channel; if they conflict with a mode lock, * fix them. */ @@ -1922,6 +1951,12 @@ void cs_remove_nick(const NickCore * nc) ci->founder = nc2; ci->successor = NULL; nc2->channelcount++; +#ifdef USE_RDB + if (rdb_open()) { + rdb_cs_set_founder(ci->name, nc2->display); + rdb_close(); + } +#endif } } else { alog("%s: Deleting channel %s owned by deleted nick %s", s_ChanServ, ci->name, nc->display); @@ -1966,6 +2001,12 @@ void cs_remove_nick(const NickCore * nc) } } } +#ifdef USE_RDB + if (rdb_open()) { + rdb_cs_deluser(nc->display); + rdb_close(); + } +#endif } /*************************************************************************/ @@ -2094,6 +2135,12 @@ int delchan(ChannelInfo * ci) } ci->c->ci = NULL; } +#ifdef USE_RDB + if (rdb_open()) { + rdb_cs_delchan(ci); + rdb_close(); + } +#endif if (ci->next) ci->next->prev = ci->prev; if (ci->prev) @@ -3841,7 +3888,6 @@ static int access_del(User * u, ChanAccess * access, int *perm, int uacc) (*perm)++; return 0; } - rdb_cs_del_access(access); access->nc = NULL; access->in_use = 0; return 1; @@ -3977,7 +4023,6 @@ static int do_access(User * u) return MOD_CONT; } access->level = level; - rdb_cs_add_access(ci, access); alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, GetHost(u), ulev, access->level, na->nick, nc->display, ci->name); notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED, access->nc->display, chan, level); @@ -4007,7 +4052,6 @@ static int do_access(User * u) access->in_use = 1; access->level = level; access->last_seen = 0; - rdb_cs_add_access(ci, access); alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, GetHost(u), ulev, access->level, na->nick, nc->display, ci->name); notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display, diff --git a/src/config.c b/src/config.c index 004f5ac49..e2d09f9e3 100644 --- a/src/config.c +++ b/src/config.c @@ -297,6 +297,7 @@ char *MysqlSecure; char *MysqlSock; int MysqlRetries = 0; int MysqlRetryGap = 0; +int UseRDB = 0; int DefConLevel; int DefCon1; @@ -491,6 +492,7 @@ Directive directives[] = { {"MysqlSock", {{PARAM_STRING, PARAM_RELOAD, &MysqlSock}}}, {"MysqlRetries", {{PARAM_POSINT, PARAM_RELOAD, &MysqlRetries}}}, {"MysqlRetryGap", {{PARAM_POSINT, PARAM_RELOAD, &MysqlRetryGap}}}, + {"UseRDB", {{PARAM_SET, PARAM_RELOAD, &UseRDB}}}, {"ModuleAutoload", {{PARAM_STRING, PARAM_RELOAD, &Modules}}}, {"ModuleDelayedAutoload", {{PARAM_STRING, PARAM_RELOAD, &ModulesDelayed}}}, diff --git a/src/hostserv.c b/src/hostserv.c index d47ae32db..7c2945683 100644 --- a/src/hostserv.c +++ b/src/hostserv.c @@ -443,11 +443,25 @@ int listOut(User * u) /*************************************************************************/ void delHostCore(char *nick) { +#ifdef USE_RDB + static char clause[128]; +#endif HostCore *tmp; boolean found = false; tmp = findHostCore(head, nick, &found); if (found) { head = deleteHostCore(head, tmp); + +#ifdef USE_RDB + /* Reflect this change in the database right away. */ + if (rdb_open()) { + + snprintf(clause, sizeof(clause), "nick='%s'", nick); + rdb_scrub_table("anope_hs_core", clause); + rdb_close(); + } +#endif + } } @@ -609,6 +623,25 @@ void save_hs_dbase(void) #undef SAFE +void save_hs_rdb_dbase(void) +{ +#ifdef USE_RDB + HostCore *current; + + if (!rdb_open()) + return; + + rdb_clear_table("anope_hs_core"); + + current = head; + while (current != NULL) { + rdb_save_hs_core(current); + current = current->next; + } + rdb_close(); +#endif +} + /*************************************************************************/ /* End of Load/Save Functions */ /*************************************************************************/ diff --git a/src/init.c b/src/init.c index e8e13d862..c6daf5918 100644 --- a/src/init.c +++ b/src/init.c @@ -607,11 +607,6 @@ int init(int ac, char **av) lang_init(); if (debug) alog("debug: Loaded languages"); - - /* Initialize remote database support */ - rdb_init(); - if (debug) - alog("debug: Loaded remote databases"); /* Initialize subservices */ ns_init(); @@ -622,6 +617,10 @@ int init(int ac, char **av) hostserv_init(); helpserv_init(); +#ifdef USE_RDB + rdb_init(); +#endif + /* Initialize proxy detection */ #ifdef USE_THREADS if (ProxyDetect && !proxy_init()) { @@ -644,6 +643,12 @@ int init(int ac, char **av) #endif /* Load up databases */ +#ifdef USE_RDB + if (UseRDB) + rdb_load_dbases(); + /* Need a better way to handle this -dane */ + if (!UseRDB) { +#endif if (!skeleton) { load_ns_dbase(); if (debug) @@ -677,8 +682,25 @@ int init(int ac, char **av) if (debug) alog("debug: Loaded PreNick database (9/9)"); } +#ifdef USE_RDB + } +#endif alog("Databases loaded"); - save_databases(); + + /* Save the databases back to file/mysql to reflect any changes */ +#ifdef USE_RDB + if (!UseRDB) { /* Only save if we are not using remote databases + * to avoid floods. As a side effects our nice + * FFF databases won't get overwritten if the + * mysql db is broken (empty etc.) */ +#endif + alog("Info: Reflecting database records."); + save_databases(); +#ifdef USE_RDB + } else { + alog("Info: Not reflecting database records."); + } +#endif /* Make myself known to myself in the serverlist */ me_server = new_server(NULL, ServerName, ServerDesc, SERVER_ISME); diff --git a/src/main.c b/src/main.c index 3af7dc73c..cb9c3a009 100644 --- a/src/main.c +++ b/src/main.c @@ -48,6 +48,7 @@ int is44 = 0; /* -is44 */ #endif #ifdef USE_RDB +int do_mysql = 0; /* use mysql ? */ #endif /* Set to 1 if we are to quit */ @@ -153,6 +154,40 @@ void save_databases(void) save_news(); waiting = -18; save_exceptions(); + +#ifdef USE_RDB + if (do_mysql) { + if (debug) + alog("debug: Saving RDB databases"); + waiting = -10; + if (!skeleton) { + waiting = -11; + save_ns_rdb_dbase(); + waiting = -12; + save_cs_rdb_dbase(); + if (PreNickDBName) { + save_ns_req_rdb_dbase(); + waiting = -13; + } + /* Temporary fix to avoid unwanted timeouts... */ + send_cmd(ServerName, "PONG %s", ServerName); + if (s_BotServ) { + waiting = -14; + save_bs_rdb_dbase(); + } + if (s_HostServ) { + waiting = -15; + save_hs_rdb_dbase(); + } + waiting = -16; + save_os_rdb_dbase(); + waiting = -17; + save_rdb_news(); + waiting = -18; + save_rdb_exceptions(); + } + } +#endif } /*************************************************************************/ @@ -197,7 +232,6 @@ void do_restart_services(void) static void services_shutdown(void) { - rdb_end(); if (!quitmsg) quitmsg = "Terminating, reason unknown"; alog("%s", quitmsg); diff --git a/src/mysql.c b/src/mysql.c index 3c4541ee3..1b83502c2 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -15,231 +15,1624 @@ /*************************************************************************/ -#ifdef USE_MYSQL +/* Database Global Variables */ +MYSQL *mysql; /* MySQL Handler */ +MYSQL_RES *mysql_res; /* MySQL Result */ +MYSQL_FIELD *mysql_fields; /* MySQL Fields */ +MYSQL_ROW mysql_row; /* MySQL Row */ -MYSQL *mysql; -MYSQL_RES *mysql_res; -MYSQL_ROW mysql_row; -int do_mysql = 0; +/*************************************************************************/ -void db_mysql_init(void) +void db_mysql_error(int severity, char *msg) { - if (!MysqlPort) MysqlPort = 3306; + static char buf[512]; - if (!MysqlHost && !MysqlSock) { - alog("MySQL is disabled."); - do_mysql = 0; - return; + if (mysql_error(mysql)) { + snprintf(buf, sizeof(buf), "MySQL %s %s: %s", msg, + severity == MYSQL_WARNING ? "warning" : "error", + mysql_error(mysql)); + } else { + snprintf(buf, sizeof(buf), "MySQL %s %s", msg, + severity == MYSQL_WARNING ? "warning" : "error"); } - if (!MysqlUser || !MysqlPass) { - alog("Missing required config directives for MySQL."); + + log_perror(buf); + + if (severity == MYSQL_ERROR) { + log_perror("MySQL FATAL error... aborting."); + exit(0); + } + +} + +/*************************************************************************/ + +int db_mysql_init() +{ + + /* If the host is not defined, assume we don't want MySQL */ + if (!MysqlHost) { do_mysql = 0; - return; + alog("MySQL has been disabled."); + } else { + do_mysql = 1; + alog("MySQL has been enabled."); } - mysql = mysql_init(NULL); - if ((!mysql_real_connect(mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort, MysqlSock ? MysqlSock : NULL, 0))) { - alog("Unable to connect to MySQL database:"); - alog(mysql_error(mysql)); + /* The following configuration options are required. + * If missing disable MySQL to avoid any problems. + */ + + if (!MysqlName || !MysqlUser) { do_mysql = 0; - return; + alog("MySQL Error: Set all required configuration options."); } - - alog("MySQL enabled."); - do_mysql = 1; + + if (!db_mysql_open()) + do_mysql = 0; + + return 1; } -void db_mysql_end(void) +/*************************************************************************/ + +int db_mysql_open() { - if (do_mysql) { - mysql_close(mysql); - alog("MySQL connection closed."); + /* If MySQL is disabled, return 0 */ + if (!do_mysql) + return 0; + + mysql = mysql_init(NULL); + if (mysql == NULL) + db_mysql_error(MYSQL_WARNING, "Unable to create mysql object"); + + if (!MysqlPort) + MysqlPort = 3306; + + if (MysqlSock) { + if ((!mysql_real_connect + (mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort, + MysqlSock, 0))) { + log_perror("Cant connect to MySQL: %s\n", mysql_error(mysql)); + return 0; + } + } else { + if ((!mysql_real_connect + (mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort, + NULL, 0))) { + log_perror("Cant connect to MySQL: %s\n", mysql_error(mysql)); + return 0; + } } -} -char *db_mysql_quote(char *sql) -{ - char *quoted; - int len; - - if (!do_mysql || !sql) return sstrdup(""); - - len = strlen(sql); - quoted = malloc((2*len + 1) * sizeof(char)); - mysql_real_escape_string(mysql, quoted, sql, len); - return quoted; + return 1; + } -int db_mysql_query(char *fmt, ...) +/*************************************************************************/ + +int db_mysql_query(char *sql) { - va_list args; - char *s, *sql; - int result; - - if (!do_mysql) return MYSQL_ERR; - - va_start(args, fmt); - - sql = malloc(MAX_SQL_BUF); - vsnprintf(sql, MAX_SQL_BUF, fmt, args); - + int result, lcv; + char *s; + + if (!do_mysql) { + return -1; + } + if (debug) { s = db_mysql_quote(sql); alog(s); free(s); + } - + result = mysql_query(mysql, sql); + if (result) { - log_perror(mysql_error(mysql)); - return MYSQL_ERR; + switch (mysql_errno(mysql)) { + case CR_SERVER_GONE_ERROR: + case CR_SERVER_LOST: + + for (lcv = 0; lcv < MysqlRetries; lcv++) { + if (db_mysql_open()) { + result = mysql_query(mysql, sql); + return (result); + } + sleep(MysqlRetryGap); + } + + /* If we get here, we could not connect. */ + log_perror("Unable to reconnect to database: %s\n", + mysql_error(mysql)); + db_mysql_error(MYSQL_ERROR, "connect"); + + /* Never reached. */ + break; + + default: + /* Unhandled error. */ + return (result); + } } - va_end(args); - return MYSQL_OK; + + return (0); + } -void db_mysql_store_result(void) +/*************************************************************************/ + +char *db_mysql_quote(char *sql) { - mysql_res = mysql_store_result(mysql); + int slen; + char *quoted; + + + if (!sql) { + return sstrdup(""); + } + + slen = strlen(sql); + quoted = malloc((1 + (slen * 2)) * sizeof(char)); + + mysql_real_escape_string(mysql, quoted, sql, slen); + return quoted; + +} + +/*************************************************************************/ + +/* I don't like using res here, maybe we can pass it as a param? */ +int db_mysql_close() +{ + if (mysql_res) + mysql_free_result(mysql_res); + mysql_close(mysql); + return 1; +} + +/*************************************************************************/ + +/* + * NickServ Specific Secion + */ + +/*************************************************************************/ +void db_mysql_save_ns_req(NickRequest * nr) +{ + char *qnick, *qpasscode, *qpassword, *qemail; + char sqlcmd[MAX_SQL_BUF]; + + qnick = db_mysql_quote(nr->nick); + qpasscode = db_mysql_quote(nr->passcode); + qpassword = db_mysql_quote(nr->password); + qemail = db_mysql_quote(nr->email); + + snprintf(sqlcmd, MAX_SQL_BUF, + "REPLACE anope_ns_request (nick,passcode,password,email,requested,active)" + " VALUES ('%s','%s','%s','%s','%d','1')", + qnick, qpasscode, qpassword, qemail, (int) nr->requested); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(qnick); + free(qpasscode); + free(qpassword); + free(qemail); +} + +char *db_mysql_secure(char *pass) +{ + + char epass[BUFSIZE]; + + /* Initialize the buffer. Bug #86 */ + memset(epass, '\0', BUFSIZE); + +#ifdef USE_ENCRYPTION + /* If we use the builtin encryption don't double encrypt! */ + snprintf(epass, sizeof(epass), "'%s'", pass); +#else + + if (!pass) { + snprintf(epass, sizeof(epass), "''"); + } else if ((!MysqlSecure) || (strcmp(MysqlSecure, "") == 0)) { + snprintf(epass, sizeof(epass), "'%s'", pass); + } else if (strcmp(MysqlSecure, "des") == 0) { + snprintf(epass, sizeof(epass), "ENCRYPT('%s')", pass); + } else if (strcmp(MysqlSecure, "md5") == 0) { + snprintf(epass, sizeof(epass), "MD5('%s')", pass); + } else if (strcmp(MysqlSecure, "sha") == 0) { + snprintf(epass, sizeof(epass), "SHA('%s')", pass); + } else { + snprintf(epass, sizeof(epass), "ENCODE('%s','%s')", pass, + MysqlSecure); + } + +#endif + + return sstrdup(epass); + +} + +/*************************************************************************/ +void db_mysql_save_ns_core(NickCore * nc) +{ + char sqlcmd[MAX_SQL_BUF]; + int j; + char **access; + Memo *memos; + char *cnick, *cpass, *epass, *cemail, *cgreet, *curl, *caccess, + *msender, *mtext; + + cnick = db_mysql_quote(nc->display); + cpass = db_mysql_quote(nc->pass); + cemail = db_mysql_quote(nc->email); + cgreet = db_mysql_quote(nc->greet); + curl = db_mysql_quote(nc->url); + + epass = db_mysql_secure(cpass); + free(cpass); + + /* Let's take care of the core itself */ + /* Update the existing records */ + snprintf(sqlcmd, MAX_SQL_BUF, + "UPDATE anope_ns_core SET pass=%s,email='%s',greet='%s',icq='%d',url='%s',flags='%d'," + "language='%d',accesscount='%d',memocount='%d',memomax='%d',channelcount='%d'" + ",channelmax='%d',active='1' WHERE display='%s'", + epass, cemail, cgreet, nc->icq, curl, nc->flags, + nc->language, nc->accesscount, nc->memos.memocount, + nc->memos.memomax, nc->channelcount, nc->channelmax, cnick); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + + /* need to write a wrapper for mysql_affected_rows */ + /* Our previous UPDATE affected no rows, therefore this is a new record */ + if ((int) mysql_affected_rows(mysql) <= 0) { + + /* Let's take care of the core itself */ + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_ns_core (display,pass,email,greet,icq,url,flags," + "language,accesscount,memocount,memomax,channelcount,channelmax,active)" + " VALUES ('%s',%s,'%s','%s','%d','%s','%d','%d','%d','%d','%d','%d','%d','1')", + cnick, epass, cemail, cgreet, nc->icq, curl, nc->flags, + nc->language, nc->accesscount, nc->memos.memocount, + nc->memos.memomax, nc->channelcount, nc->channelmax); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + } + + /* Now let's do the access */ + for (j = 0, access = nc->access; j < nc->accesscount; j++, access++) { + caccess = db_mysql_quote(*access); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_ns_access (display,access) VALUES ('%s','%s')", + cnick, caccess); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(caccess); + } + + /* And... memos */ + memos = nc->memos.memos; + for (j = 0; j < nc->memos.memocount; j++, memos++) { + msender = db_mysql_quote(memos->sender); + mtext = db_mysql_quote(memos->text); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_ms_info (receiver,number,flags,time,sender,text,serv)" + " VALUES ('%s','%d','%d','%d','%s','%s','NICK')", + cnick, memos->number, memos->flags, + (int) memos->time, msender, mtext); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(msender); + free(mtext); + } + + free(cnick); + free(epass); + free(cemail); + free(cgreet); + free(curl); +} + + +/*************************************************************************/ +void db_mysql_save_ns_alias(NickAlias * na) +{ + char sqlcmd[MAX_SQL_BUF]; + char *nnick, *nlmask, *nlrname, *nlquit, *nncnick; + nnick = db_mysql_quote(na->nick); + nlmask = db_mysql_quote(na->last_usermask); + nlrname = db_mysql_quote(na->last_realname); + nlquit = db_mysql_quote(na->last_quit); + nncnick = db_mysql_quote(na->nc->display); + snprintf(sqlcmd, MAX_SQL_BUF, + "UPDATE anope_ns_alias SET last_usermask='%s',last_realname='%s',last_quit='%s',time_registered='%d',last_seen='%d',status='%d',display='%s',active='1' WHERE nick='%s'", + nlmask, nlrname, nlquit, (int) na->time_registered, + (int) na->last_seen, (int) na->status, nncnick, nnick); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + /* Our previous UPDATE affected no rows, therefore this is a new record */ + if ((int) mysql_affected_rows(mysql) <= 0) { + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT INTO anope_ns_alias (nick,last_usermask,last_realname,last_quit,time_registered,last_seen,status,display,active) VALUES ('%s','%s','%s','%s','%d','%d','%d','%s','1')", + nnick, nlmask, nlrname, nlquit, (int) na->time_registered, + (int) na->last_seen, (int) na->status, nncnick); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + } + + free(nnick); + free(nlmask); + free(nlrname); + free(nlquit); + free(nncnick); + + return; +} + +/*************************************************************************/ + +/* + * ChanServ Specific Secion + */ + +/*************************************************************************/ +void db_mysql_save_cs_info(ChannelInfo * ci) +{ + char sqlcmd[MAX_SQL_BUF]; + int j, position; + Memo *memos; + char *ciname, *cifoundernick, *cisuccessornick, *cifounderpass, + *cidesc, *ciurl, *ciemail, *cilasttopic, *cilasttopicsetter, + *ciforbidby, *ciforbidreason, *cimlock_key, *cimlock_flood, + *cimlock_redirect, *cientrymsg, *cibotnick, *msender, *mtext, + *ciaccessdisp, *ciakickdisp, *ciakickreason, *ciakickcreator, + *cbadwords, *efounderpass; + + ciname = db_mysql_quote(ci->name); + cifoundernick = + ci->founder ? db_mysql_quote(ci->founder->display) : ""; + cisuccessornick = + ci->successor ? db_mysql_quote(ci->successor->display) : ""; + cifounderpass = db_mysql_quote(ci->founderpass); + cidesc = db_mysql_quote(ci->desc); + ciurl = db_mysql_quote(ci->url); + ciemail = db_mysql_quote(ci->email); + cilasttopic = db_mysql_quote(ci->last_topic); + cilasttopicsetter = db_mysql_quote(ci->last_topic_setter); + ciforbidby = db_mysql_quote(ci->forbidby); + ciforbidreason = db_mysql_quote(ci->forbidreason); + cimlock_key = db_mysql_quote(ci->mlock_key); +#ifdef HAS_FMODE + cimlock_flood = db_mysql_quote(ci->mlock_flood); +#else + cimlock_flood = NULL; +#endif +#ifdef HAS_LMODE + cimlock_redirect = db_mysql_quote(ci->mlock_redirect); +#else + cimlock_redirect = NULL; +#endif + cientrymsg = db_mysql_quote(ci->entry_message); + cibotnick = ci->bi ? db_mysql_quote(ci->bi->nick) : ""; + + efounderpass = db_mysql_secure(cifounderpass); + free(cifounderpass); + + /* Let's take care of the core itself */ + snprintf(sqlcmd, MAX_SQL_BUF, + "UPDATE anope_cs_info SET founder='%s',successor='%s',founderpass=%s," + "descr='%s',url='%s',email='%s',time_registered='%d',last_used='%d'," + "last_topic='%s',last_topic_setter='%s',last_topic_time='%d',flags='%d'," + "forbidby='%s',forbidreason='%s',bantype='%d',accesscount='%d'," + "akickcount='%d',mlock_on='%d',mlock_off='%d',mlock_limit='%d'," + "mlock_key='%s',mlock_flood='%s',mlock_redirect='%s',entry_message='%s'," + "memomax='%d',botnick='%s',botflags='%d',ttb='%d',bwcount='%d'," + "capsmin='%d',capspercent='%d',floodlines='%d',floodsecs='%d'," + "repeattimes='%d',active='1' WHERE name='%s'", + cifoundernick, + cisuccessornick, + efounderpass, cidesc, ciurl, ciemail, + (int) ci->time_registered, (int) ci->last_used, + cilasttopic, cilasttopicsetter, + (int) ci->last_topic_time, (int) ci->flags, + ciforbidby, ciforbidreason, (int) ci->bantype, + (int) ci->accesscount, (int) ci->akickcount, + (int) ci->mlock_on, (int) ci->mlock_off, + (int) ci->mlock_limit, cimlock_key, +#ifdef HAS_FMODE + cimlock_flood, +#else + "", +#endif +#ifdef HAS_LMODE + cimlock_redirect, +#else + "", +#endif + cientrymsg, + (int) ci->memos.memomax, + cibotnick, + (int) ci->botflags, + (int) ci->ttb, + (int) ci->bwcount, + (int) ci->capsmin, + (int) ci->capspercent, + (int) ci->floodlines, + (int) ci->floodsecs, (int) ci->repeattimes, ciname); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + + /* Our previous UPDATE affected no rows, therefore this is a new record */ + if ((int) mysql_affected_rows(mysql) <= 0) { + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_cs_info (name,founder,successor,founderpass," + "descr,url,email,time_registered,last_used,last_topic,last_topic_setter" + ",last_topic_time,flags,forbidby,forbidreason,bantype,accesscount,akickcount" + ",mlock_on,mlock_off,mlock_limit,mlock_key,mlock_flood,mlock_redirect," + "entry_message,botnick,botflags,bwcount,capsmin,capspercent,floodlines," + "floodsecs,repeattimes,active) VALUES ('%s','%s','%s',%s,'%s','%s','%s'" + ",'%d','%d','%s','%s','%d','%d','%s','%s','%d','%d','%d','%d','%d','%d'," + "'%s','%s','%s','%s','%s','%d','%d','%d','%d','%d','%d','%d','1')", + ciname, + cifoundernick, + cisuccessornick, + efounderpass, cidesc, ciurl, ciemail, + (int) ci->time_registered, (int) ci->last_used, + cilasttopic, cilasttopicsetter, + (int) ci->last_topic_time, (int) ci->flags, + ciforbidby, ciforbidreason, (int) ci->bantype, + (int) ci->accesscount, (int) ci->akickcount, + (int) ci->mlock_on, (int) ci->mlock_off, + (int) ci->mlock_limit, cimlock_key, +#ifdef HAS_FMODE + cimlock_flood, +#else + "", +#endif +#ifdef HAS_LMODE + cimlock_redirect, +#else + "", +#endif + cientrymsg, + cibotnick, + (int) ci->botflags, + (int) ci->bwcount, + (int) ci->capsmin, + (int) ci->capspercent, + (int) ci->floodlines, + (int) ci->floodsecs, (int) ci->repeattimes); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + } + + /* Memos */ + memos = ci->memos.memos; + for (j = 0; j < ci->memos.memocount; j++, memos++) { + msender = db_mysql_quote(memos->sender); + mtext = db_mysql_quote(memos->text); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_ms_info (receiver,number,flags,time,sender,text,serv)" + " VALUES ('%s','%d','%d','%d','%s','%s','CHAN')", + ciname, memos->number, memos->flags, + (int) memos->time, msender, mtext); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(msender); + free(mtext); + } + + /* Access */ + for (j = 0; j < ci->accesscount; j++) { + if (ci->access[j].in_use) { + ciaccessdisp = db_mysql_quote(ci->access[j].nc->display); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_cs_access (in_use,level,display,channel,last_seen)" + " VALUES ('%d','%d','%s','%s','%d')", + (int) ci->access[j].in_use, (int) ci->access[j].level, + ciaccessdisp, ciname, (int) ci->access[j].last_seen); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(ciaccessdisp); + } + } + + /* Levels */ + position = 0; + for (j = 0; j < CA_SIZE; j++) { + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_cs_levels (channel, position, level) VALUES ('%s','%d','%d')", + ciname, position++, (int) ci->levels[j]); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + } + + /* Akicks */ + for (j = 0; j < ci->akickcount; j++) { + ciakickdisp = + ci->akick[j].flags & AK_USED ? ci->akick[j]. + flags & AK_ISNICK ? db_mysql_quote(ci->akick[j].u.nc-> + display) : + db_mysql_quote(ci->akick[j].u.mask) : ""; + ciakickreason = + ci->akick[j].flags & AK_USED ? db_mysql_quote(ci->akick[j]. + reason) : ""; + ciakickcreator = + ci->akick[j].flags & AK_USED ? db_mysql_quote(ci->akick[j]. + creator) : ""; + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_cs_akicks (channel, flags, dmask, reason, creator," + " addtime) VALUES ('%s','%d','%s','%s','%s','%d')", + ciname, (int) ci->akick[j].flags, ciakickdisp, + ciakickreason, ciakickcreator, + ci->akick[j].flags & AK_USED ? (int) ci->akick[j]. + addtime : 0); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + if (ci->akick[j].flags & AK_USED) { + free(ciakickdisp); + free(ciakickreason); + free(ciakickcreator); + } + } + + /* Bad Words */ + for (j = 0; j < ci->bwcount; j++) { + if (ci->badwords[j].in_use) { + cbadwords = db_mysql_quote(ci->badwords[j].word); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_cs_badwords (channel, word, type)" + " VALUES ('%s','%s','%d')", ciname, cbadwords, + (int) ci->badwords[j].type); + free(cbadwords); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + } + } + + free(ciname); + if (!(ci->flags & CI_VERBOTEN)) { + free(cifoundernick); + if (strlen(cisuccessornick) > 0) + free(cisuccessornick); + free(efounderpass); + free(cidesc); + free(ciurl); + free(ciemail); + free(cilasttopic); + free(cilasttopicsetter); + free(cimlock_key); + free(cimlock_flood); + free(cimlock_redirect); + free(cientrymsg); + if (ci->bi) + free(cibotnick); + } else { + free(ciforbidby); + free(ciforbidreason); + } + + return; +} + +/*************************************************************************/ + + +/* + * OperServ Specific Section + */ + +/*************************************************************************/ +void db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime, + SList * ak, SList * sgl, SList * sql, SList * szl, + HostCache * hc) +{ + char sqlcmd[MAX_SQL_BUF]; + Akill *t_ak; + SXLine *t_sl; + HostCache *t_hc; + char *takuser, *takhost, *takby, *takreason, *tslmask, *tslby, + *tslreason, *thchost; + + int i, j; + + rdb_clear_table("anope_os_core"); + + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_core (maxusercnt,maxusertime,akills_count," + "sglines_count,sqlines_count,szlines_count) VALUES " + "('%d','%d','%d','%d','%d','%d')", maxucnt, maxutime, + ak->count, sgl->count, sql->count, szl->count); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + + /* now the akills saving */ + rdb_clear_table("anope_os_akills"); + + j = ak->count; + for (i = 0; i < j; i++) { + t_ak = ak->list[i]; + takuser = db_mysql_quote(t_ak->user); + takhost = db_mysql_quote(t_ak->host); + takby = db_mysql_quote(t_ak->by); + takreason = db_mysql_quote(t_ak->reason); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_akills (user,host,xby,reason,seton,expire) VALUES ('%s','%s','%s','%s','%d','%d')", + takuser, + takhost, + takby, takreason, (int) t_ak->seton, (int) t_ak->expires); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(takuser); + free(takhost); + free(takby); + free(takreason); + } + +/* sglines save */ + rdb_clear_table("anope_os_sglines"); + + j = sgl->count; + for (i = 0; i < j; i++) { + t_sl = sgl->list[i]; + tslmask = db_mysql_quote(t_sl->mask); + tslby = db_mysql_quote(t_sl->by); + tslreason = db_mysql_quote(t_sl->reason); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_sglines (mask,xby,reason,seton,expire) VALUES" + " ('%s','%s','%s','%d','%d')", + tslmask, + tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(tslmask); + free(tslby); + free(tslreason); + } + +/* sqlines save */ + rdb_clear_table("anope_os_sqlines"); + + j = sql->count; + for (i = 0; i < j; i++) { + t_sl = sql->list[i]; + tslmask = db_mysql_quote(t_sl->mask); + tslby = db_mysql_quote(t_sl->by); + tslreason = db_mysql_quote(t_sl->reason); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_sqlines (mask,xby,reason,seton,expire) VALUES ('%s','%s','%s','%d','%d')", + tslmask, + tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(tslmask); + free(tslby); + free(tslreason); + } + +/* szlines save */ + rdb_clear_table("anope_os_szlines"); + + j = szl->count; + for (i = 0; i < j; i++) { + t_sl = szl->list[i]; + tslmask = db_mysql_quote(t_sl->mask); + tslby = db_mysql_quote(t_sl->by); + tslreason = db_mysql_quote(t_sl->reason); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_szlines (mask,xby,reason,seton,expire) VALUES" + " ('%s','%s','%s','%d','%d')", + tslmask, + tslby, tslreason, (int) t_sl->seton, (int) t_sl->expires); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(tslmask); + free(tslby); + free(tslreason); + } + +/* and finally we save hcache */ + rdb_clear_table("anope_os_hcache"); + for (i = 0; i < 1024; i++) { + for (t_hc = hcache[i]; t_hc; t_hc = t_hc->next) { + /* Don't save in-progress scans */ + if (t_hc->status < HC_NORMAL) + continue; + thchost = db_mysql_quote(t_hc->host); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_hcache (mask,status,used) VALUES ('%s','%d','%d')", + thchost, (int) t_hc->status, (int) t_hc->used); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(thchost); + } + } + + return; +} + +/*************************************************************************/ +void db_mysql_save_news(NewsItem * ni) +{ + char sqlcmd[MAX_SQL_BUF]; + char *nitext, *niwho; + nitext = db_mysql_quote(ni->text); + niwho = db_mysql_quote(ni->who); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_news (type,num,ntext,who,`time`)" + " VALUES ('%d','%d','%s','%s','%d')", + ni->type, ni->num, nitext, niwho, (int) ni->time); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(nitext); + free(niwho); + + return; } -void db_mysql_free_res(void) +/*************************************************************************/ +void db_mysql_save_exceptions(Exception * e) +{ + char sqlcmd[MAX_SQL_BUF]; + char *emask, *ewho, *ereason; + emask = db_mysql_quote(e->mask); + ewho = db_mysql_quote(e->who); + ereason = db_mysql_quote(e->reason); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_os_exceptions (mask,lim,who,reason,`time`,expires)" + " VALUES ('%s','%d','%s','%s','%d','%d')", + emask, e->limit, ewho, + ereason, (int) e->time, (int) e->expires); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(emask); + free(ewho); + free(ereason); + return; +} + +/*************************************************************************/ + + +/* + * HostServ Specific Section + */ + +/*************************************************************************/ +/* TODO: Add vident to tables! */ +void db_mysql_save_hs_core(HostCore * hc) { + char sqlcmd[MAX_SQL_BUF]; + char *hcnick, *hcvident, *hcvhost, *hccreator; + hcnick = db_mysql_quote(hc->nick); + hcvident = db_mysql_quote(hc->vIdent); + hcvhost = db_mysql_quote(hc->vHost); + hccreator = db_mysql_quote(hc->creator); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_hs_core (nick,vident,vhost,creator,`time`)" + " VALUES ('%s','%s','%s','%s','%d')", + hcnick, hcvident, hcvhost, hccreator, (int) hc->time); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(hcnick); + free(hcvident); + free(hcvhost); + free(hccreator); + + return; +} + +/*************************************************************************/ + +/* + * HostServ Specific Section + */ + +/*************************************************************************/ +void db_mysql_save_bs_core(BotInfo * bi) +{ + char sqlcmd[MAX_SQL_BUF]; + char *binick, *biuser, *bihost, *bireal; + binick = db_mysql_quote(bi->nick); + biuser = db_mysql_quote(bi->user); + bihost = db_mysql_quote(bi->host); + bireal = db_mysql_quote(bi->real); + snprintf(sqlcmd, MAX_SQL_BUF, + "INSERT DELAYED INTO anope_bs_core (nick,user,host,rname,flags,created" + ",chancount) VALUES ('%s','%s','%s','%s','%d','%d','%d')", + binick, biuser, + bihost, bireal, bi->flags, (int) bi->created, bi->chancount); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + free(binick); + free(biuser); + free(bihost); + free(bireal); +} + +/*************************************************************************/ + +void db_mysql_load_bs_dbase(void) +{ + BotInfo *bi; + char sqlcmd[MAX_SQL_BUF]; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `nick`,`user`,`host`,`rname`,`flags`,`created`,`chancount` FROM `anope_bs_core`"); + + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + while ((mysql_row = mysql_fetch_row(mysql_res))) { + bi = makebot(mysql_row[0]); + bi->user = sstrdup(mysql_row[1]); + bi->host = sstrdup(mysql_row[2]); + bi->real = sstrdup(mysql_row[3]); + bi->flags = atoi(mysql_row[4]); + bi->created = atoi(mysql_row[5]); + bi->chancount = atoi(mysql_row[6]); + } mysql_free_result(mysql_res); } -/* BotServ */ -void db_mysql_bs_add_bot(BotInfo *bi) -{ - char *nick, *user, *host, *rname; - - nick = db_mysql_quote(bi->nick); - user = db_mysql_quote(bi->user); - host = db_mysql_quote(bi->host); - rname = db_mysql_quote(bi->real); - - db_mysql_query("INSERT INTO `anope_bs_core` (`nick`,`user`,`host`,`rname`,`flags`,`created`,`chancount`) VALUES('%s','%s','%s','%s',%d,%d,%d)",nick,user,host,rname,bi->flags, bi->created, bi->chancount); - - free(nick); - free(user); - free(host); - free(rname); -} - -void db_mysql_bs_del_bot(BotInfo *bi) -{ - char *nick, *user, *host, *rname; - - nick = db_mysql_quote(bi->nick); - user = db_mysql_quote(bi->user); - host = db_mysql_quote(bi->host); - rname = db_mysql_quote(bi->real); - - db_mysql_query("DELETE FROM `anope_bs_core` WHERE `nick`='%s' AND `user`='%s' AND `host`='%s' AND `rname`='%s'",nick,user,host,rname); - - free(nick); - free(user); - free(host); - free(rname); -} - -void db_mysql_bs_chg_bot(BotInfo *bi, char *newnick, char *newuser, char *newhost, char *newreal) -{ - char *oldnick, *nick, *user, *host, *real, *sql; - - sql = malloc(MAX_SQL_BUF); - snprintf(sql, MAX_SQL_BUF, "UPDATE `anope_bs_core` SET "); - - oldnick = db_mysql_quote(bi->nick); - - if (!newnick) newnick = bi->nick; - if (!newuser) newuser = bi->user; - if (!newhost) newhost = bi->host; - if (!newreal) newreal = bi->real; - - nick = db_mysql_quote(newnick); - strcat(sql,"`nick`='"); - strcat(sql,nick); - strcat(sql,"',"); - free(nick); - - user = db_mysql_quote(newuser); - strcat(sql,"`user`='"); - strcat(sql,user); - strcat(sql,"',"); - free(user); - - host = db_mysql_quote(newhost); - strcat(sql,"`host`='"); - strcat(sql,host); - strcat(sql,"',"); - free(host); - - real = db_mysql_quote(newreal); - strcat(sql,"`rname`='"); - strcat(sql,real); - strcat(sql,"' "); - free(real); - - strcat(sql,"WHERE `nick`='"); - strcat(sql,oldnick); - strcat(sql,"'"); - db_mysql_query(sql); - free(sql); - free(oldnick); -} - -void db_mysql_bs_chg_bot_chancount(BotInfo *bi) +void db_mysql_load_hs_dbase(void) { + char sqlcmd[MAX_SQL_BUF]; char *nick; - - nick = db_mysql_quote(bi->nick); - db_mysql_query("UPDATE `anope_bs_core` SET `chancount` = %d WHERE `nick` = '%s'", bi->chancount, nick); - free(nick); + char *vHost; + char *creator; + char *vIdent; + int32 time; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `nick`,`vident`,`vhost`,`creator`,`time` FROM `anope_hs_core`"); + + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + while ((mysql_row = mysql_fetch_row(mysql_res))) { + nick = sstrdup(mysql_row[0]); + vIdent = sstrdup(mysql_row[1]); + vHost = sstrdup(mysql_row[2]); + creator = sstrdup(mysql_row[3]); + time = atoi(mysql_row[4]); + addHostCore(nick, vIdent, vHost, creator, time); + free(nick); + free(vHost); + free(creator); + free(vIdent); + } + mysql_free_result(mysql_res); } -void db_mysql_bs_chg_bot_flags(BotInfo *bi) +void db_mysql_load_news(void) { - char *nick; - - nick = db_mysql_quote(bi->nick); - db_mysql_query("UPDATE `anope_bs_core` SET `flags` = %d WHERE `nick` = '%s'", bi->flags, nick); - free(nick); -} - -/* ChanServ */ -void db_mysql_cs_add_access(ChannelInfo *ci, ChanAccess *access) -{ - char *display, *channel; - - display = db_mysql_quote(access->nc->display); - channel = db_mysql_quote(ci->name); - - /* Check if the entry already exists */ - db_mysql_query("SELECT `ca_id` FROM `anope_cs_access` WHERE `channel` = '%s' AND `display` = '%s'",channel, display); - db_mysql_store_result(); - - if (mysql_num_rows(mysql_res) >= 1) { - db_mysql_query("UPDATE `anope_cs_access` SET `in_use` = 1, `level` = %d, `last_seen` = %d WHERE `channel` = '%s' AND `display` = '%s'",access->level, access->last_seen, channel, display); + char sqlcmd[MAX_SQL_BUF]; + int j; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `type`,`num`,`ntext`,`who`,`time` FROM `anope_os_news`"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + nnews = mysql_num_rows(mysql_res); + if (nnews < 8) + news_size = 16; + else if (nnews >= 16384) + news_size = 32767; + else + news_size = 2 * nnews; + news = scalloc(sizeof(*news) * news_size, 1); + if (!nnews) { + mysql_free_result(mysql_res); + return; + } + j = 0; + while ((mysql_row = mysql_fetch_row(mysql_res))) { + news[j].type = atoi(mysql_row[0]); + news[j].num = atoi(mysql_row[1]); + news[j].text = sstrdup(mysql_row[2]); + snprintf(news[j].who, NICKMAX, "%s", mysql_row[3]); + news[j].time = atoi(mysql_row[4]); + j++; + } + mysql_free_result(mysql_res); +} + +void db_mysql_load_exceptions(void) +{ + char sqlcmd[MAX_SQL_BUF]; + int j; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `mask`,`lim`,`who`,`reason`,`time`,`expires` FROM `anope_os_exceptions`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + nexceptions = mysql_num_rows(mysql_res); + exceptions = scalloc(sizeof(Exception) * nexceptions, 1); + j = 0; + while ((mysql_row = mysql_fetch_row(mysql_res))) { + exceptions[j].mask = sstrdup(mysql_row[0]); + exceptions[j].limit = atoi(mysql_row[1]); + snprintf(exceptions[j].who, NICKMAX, "%s", mysql_row[2]); + exceptions[j].reason = sstrdup(mysql_row[3]); + exceptions[j].time = atoi(mysql_row[4]); + exceptions[j].expires = atoi(mysql_row[5]); + j++; + } + mysql_free_result(mysql_res); +} + +#define HASH(host) ((tolower((host)[0])&31)<<5 | (tolower((host)[1])&31)) + +void db_mysql_load_os_dbase(void) +{ + char sqlcmd[MAX_SQL_BUF]; + Akill *ak; + SXLine *sx; + HostCache *hc; + int akc, sgc, sqc, szc, j; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `maxusercnt`,`maxusertime`,`akills_count`,`sglines_count`,`sqlines_count`,`szlines_count` FROM `anope_os_core`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if ((mysql_row = mysql_fetch_row(mysql_res))) { + maxusercnt = atoi(mysql_row[0]); + maxusertime = atoi(mysql_row[1]); + akc = atoi(mysql_row[2]); + sgc = atoi(mysql_row[3]); + sqc = atoi(mysql_row[4]); + szc = atoi(mysql_row[5]); } else { - db_mysql_query("INSERT INTO `anope_cs_access` (`in_use`,`level`,`display`,`channel`,`last_seen`) VALUES (1, %d, '%s', '%s', %d)",access->level,display,channel,access->last_seen); + maxusercnt = 0; + maxusertime = time(NULL); + akc = sgc = sqc = szc = 0; + } + mysql_free_result(mysql_res); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `user`,`host`,`xby`,`reason`,`seton`,`expire` FROM `anope_os_akills`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); } - - db_mysql_free_res(); - free(channel); - free(display); + mysql_res = mysql_store_result(mysql); + slist_setcapacity(&akills, akc); + while ((mysql_row = mysql_fetch_row(mysql_res))) { + ak = scalloc(sizeof(Akill), 1); + ak->user = sstrdup(mysql_row[0]); + ak->host = sstrdup(mysql_row[1]); + ak->by = sstrdup(mysql_row[2]); + ak->reason = sstrdup(mysql_row[3]); + ak->seton = atoi(mysql_row[4]); + ak->expires = atoi(mysql_row[5]); + slist_add(&akills, ak); + } + mysql_free_result(mysql_res); + + slist_setcapacity(&sglines, sgc); + slist_setcapacity(&sqlines, sqc); + slist_setcapacity(&szlines, szc); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `mask`,`xby`,`reason`,`seton`,`expire` FROM `anope_os_sglines`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql statement: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + while ((mysql_row = mysql_fetch_row(mysql_res))) { + sx = scalloc(sizeof(SXLine), 1); + sx->mask = sstrdup(mysql_row[0]); + sx->by = sstrdup(mysql_row[1]); + sx->reason = sstrdup(mysql_row[2]); + sx->seton = atoi(mysql_row[3]); + sx->expires = atoi(mysql_row[4]); + slist_add(&sglines, sx); + } + mysql_free_result(mysql_res); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `mask`,`xby`,`reason`,`seton`,`expire` FROM `anope_os_sqlines`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql statement: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + while ((mysql_row = mysql_fetch_row(mysql_res))) { + sx = scalloc(sizeof(SXLine), 1); + sx->mask = sstrdup(mysql_row[0]); + sx->by = sstrdup(mysql_row[1]); + sx->reason = sstrdup(mysql_row[2]); + sx->seton = atoi(mysql_row[3]); + sx->expires = atoi(mysql_row[4]); + slist_add(&sqlines, sx); + } + mysql_free_result(mysql_res); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `mask`,`xby`,`reason`,`seton`,`expire` FROM `anope_os_szlines`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql statement: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + while ((mysql_row = mysql_fetch_row(mysql_res))) { + sx = scalloc(sizeof(SXLine), 1); + sx->mask = sstrdup(mysql_row[0]); + sx->by = sstrdup(mysql_row[1]); + sx->reason = sstrdup(mysql_row[2]); + sx->seton = atoi(mysql_row[3]); + sx->expires = atoi(mysql_row[4]); + slist_add(&szlines, sx); + } + mysql_free_result(mysql_res); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `mask`,`status`,`used` FROM `anope_os_hcache`"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + while ((mysql_row = mysql_fetch_row(mysql_res))) { + j = HASH(mysql_row[0]); + hc = scalloc(1, sizeof(HostCache)); + hc->host = sstrdup(mysql_row[0]); + hc->status = atoi(mysql_row[1]); + hc->used = atoi(mysql_row[2]); + + hc->prev = NULL; + hc->next = hcache[j]; + if (hc->next) + hc->next->prev = hc; + hcache[j] = hc; + } + mysql_free_result(mysql_res); } -void db_mysql_cs_del_access(ChannelInfo *ci, ChanAccess *access) +#undef HASH + +void db_mysql_load_cs_dbase(void) { - char *display, *channel; + char sqlcmd[MAX_SQL_BUF], *tempstr; + ChannelInfo *ci; + int n_levels, j, m; + MYSQL_RES *res; + MYSQL_ROW row; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `name`,`founder`,`successor`,`founderpass`,`descr`,`url`,`email`,`time_registered`,`last_used`,`last_topic`,`last_topic_setter`,`last_topic_time`,`flags`,`forbidby`,`forbidreason`,`bantype`,`accesscount`,`akickcount`,`mlock_on`,`mlock_off`,`mlock_limit`,`mlock_key`,`mlock_flood`,`mlock_redirect`,`entry_message`,`memomax`,`botnick`,`botflags`,`ttb`,`bwcount`,`capsmin`,`capspercent`,`floodlines`,`floodsecs`,`repeattimes` FROM `anope_cs_info`"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + while ((mysql_row = mysql_fetch_row(mysql_res))) { + ci = scalloc(sizeof(ChannelInfo), 1); + snprintf(ci->name, CHANMAX, "%s", mysql_row[0]); + ci->founder = findcore(mysql_row[1]); + ci->successor = findcore(mysql_row[2]); + snprintf(ci->founderpass, PASSMAX, "%s", mysql_row[3]); + ci->desc = sstrdup(mysql_row[4]); + ci->url = sstrdup(mysql_row[5]); + if (strlen(ci->url) == 0) { + free(ci->url); + ci->url = NULL; + } + ci->email = sstrdup(mysql_row[6]); + if (strlen(ci->email) == 0) { + free(ci->email); + ci->email = NULL; + } + ci->time_registered = atoi(mysql_row[7]); + ci->last_used = atoi(mysql_row[8]); + ci->last_topic = sstrdup(mysql_row[9]); + snprintf(ci->last_topic_setter, NICKMAX, "%s", mysql_row[10]); + ci->last_topic_time = atoi(mysql_row[11]); + ci->flags = atoi(mysql_row[12]); +#ifdef USE_ENCRYPTION + if (!(ci->flags & (CI_ENCRYPTEDPW | CI_VERBOTEN))) { + if (debug) + alog("debug: %s: encrypting password for %s on load", + s_ChanServ, ci->name); + if (encrypt_in_place(ci->founderpass, PASSMAX) < 0) + fatal("%s: load database: Can't encrypt %s password!", + s_ChanServ, ci->name); + ci->flags |= CI_ENCRYPTEDPW; + } +#else + if (ci->flags & CI_ENCRYPTEDPW) { + fatal + ("%s: load database: password for %s encrypted but encryption disabled, aborting", + s_ChanServ, ci->name); + } +#endif + ci->flags &= ~CI_INHABIT; + + ci->forbidby = sstrdup(mysql_row[13]); + ci->forbidreason = sstrdup(mysql_row[14]); + ci->bantype = atoi(mysql_row[15]); - display = db_mysql_quote(access->nc->display); - channel = db_mysql_quote(ci->name); - - db_mysql_query("DELETE FROM `anope_cs_access` WHERE `channel` = '%s' AND `display` = '%s'", channel, display); - - free(channel); - free(display); + tempstr = db_mysql_quote(ci->name); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `position`,`level` FROM `anope_cs_levels` WHERE `channel` = '%s'", + tempstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + n_levels = mysql_num_rows(res); + ci->levels = scalloc(2 * CA_SIZE, 1); + reset_levels(ci); + while ((row = mysql_fetch_row(res))) { + ci->levels[atoi(row[0])] = atoi(row[1]); + } + mysql_free_result(res); + ci->accesscount = atoi(mysql_row[16]); + if (ci->accesscount) { + ci->access = scalloc(ci->accesscount, sizeof(ChanAccess)); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `in_use`,`level`,`display`,`last_seen` FROM `anope_cs_access` WHERE `channel` = '%s'", + tempstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + j = 0; + while ((row = mysql_fetch_row(res))) { + ci->access[j].in_use = atoi(row[0]); + if (ci->access[j].in_use) { + ci->access[j].level = atoi(row[1]); + ci->access[j].nc = findcore(row[2]); + if (ci->access[j].nc == NULL) + ci->access[j].in_use = 0; + ci->access[j].last_seen = atoi(row[3]); + } + j++; + } + mysql_free_result(res); + } else { + ci->access = NULL; + } + ci->akickcount = atoi(mysql_row[17]); + if (ci->akickcount) { + ci->akick = scalloc(ci->akickcount, sizeof(AutoKick)); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `flags`,`dmask`,`reason`,`creator`,`addtime` FROM `anope_cs_akicks` WHERE `channel` = '%s'", + tempstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + j = 0; + while ((row = mysql_fetch_row(res))) { + ci->akick[j].flags = atoi(row[0]); + if (ci->akick[j].flags & AK_USED) { + if (ci->akick[j].flags & AK_ISNICK) { + ci->akick[j].u.nc = findcore(row[1]); + if (!ci->akick[j].u.nc) + ci->akick[j].flags &= ~AK_USED; + } else { + ci->akick[j].u.mask = sstrdup(row[1]); + } + ci->akick[j].reason = sstrdup(row[2]); + ci->akick[j].creator = sstrdup(row[3]); + ci->akick[j].addtime = atoi(row[4]); + } + j++; + } + mysql_free_result(res); + } else { + ci->akick = NULL; + } + ci->mlock_on = atoi(mysql_row[18]); + ci->mlock_off = atoi(mysql_row[19]); + ci->mlock_limit = atoi(mysql_row[20]); + ci->mlock_key = sstrdup(mysql_row[21]); +#ifdef HAS_FMODE + ci->mlock_flood = sstrdup(mysql_row[22]); +#endif + +#ifdef HAS_LMODE + ci->mlock_redirect = sstrdup(mysql_row[23]); +#endif + ci->memos.memomax = atoi(mysql_row[25]); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `number`,`flags`,`time`,`sender`,`text` FROM `anope_ms_info` WHERE `receiver` = '%s'", + tempstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + ci->memos.memocount = mysql_num_rows(res); + if (ci->memos.memocount) { + Memo *memos; + memos = scalloc(sizeof(Memo) * ci->memos.memocount, 1); + ci->memos.memos = memos; + while ((row = mysql_fetch_row(res))) { + memos->number = atoi(row[0]); + memos->flags = atoi(row[1]); + memos->time = atoi(row[2]); + snprintf(memos->sender, NICKMAX, "%s", row[3]); + memos->text = sstrdup(row[4]); + for (m = 0; m < MAX_CMD_HASH; m++) { + memos->moduleData[m] = NULL; + } + memos++; + } + } + mysql_free_result(res); + ci->entry_message = sstrdup(mysql_row[24]); + if (strlen(ci->entry_message) == 0) { + free(ci->entry_message); + ci->entry_message = NULL; + } + ci->c = NULL; + + ci->bi = findbot(mysql_row[26]); + ci->botflags = atoi(mysql_row[27]); + ci->ttb = scalloc(2 * TTB_SIZE, 1); + for (j = 0; j < TTB_SIZE; j++) { + ci->ttb[j] = 0; + } + ci->capsmin = atoi(mysql_row[30]); + ci->capspercent = atoi(mysql_row[31]); + ci->floodlines = atoi(mysql_row[32]); + ci->floodsecs = atoi(mysql_row[33]); + ci->repeattimes = atoi(mysql_row[34]); + + ci->bwcount = atoi(mysql_row[29]); + if (ci->bwcount) { + ci->badwords = scalloc(ci->bwcount, sizeof(BadWord)); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `word`,`type` FROM `anope_cs_badwords` WHERE `channel` = '%s'", + tempstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + j = 0; + while ((row = mysql_fetch_row(res))) { + ci->badwords[j].in_use = 1; + if (ci->badwords[j].in_use) { /* I know... but for later */ + ci->badwords[j].word = sstrdup(row[0]); + ci->badwords[j].type = atoi(row[1]); + } + j++; + } + mysql_free_result(res); + } else { + ci->badwords = NULL; + } + alpha_insert_chan(ci); + free(tempstr); + } + mysql_free_result(mysql_res); + + for (j = 0; j < 256; j++) { + ChannelInfo *next; + for (ci = chanlists[j]; ci; ci = next) { + next = ci->next; + if (!(ci->flags & CI_VERBOTEN) && !ci->founder) { + alog("%s: database load: Deleting founderless channel %s", + s_ChanServ, ci->name); + delchan(ci); + } + } + } +} + +void db_mysql_load_ns_req_dbase(void) +{ + char sqlcmd[MAX_SQL_BUF]; + NickRequest *nr; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `nick`,`passcode`,`password`,`email`,`requested`,`active` FROM `anope_ns_request`;"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + while ((mysql_row = mysql_fetch_row(mysql_res))) { + nr = scalloc(1, sizeof(NickRequest)); + nr->nick = sstrdup(mysql_row[0]); + nr->passcode = sstrdup(mysql_row[1]); + nr->password = sstrdup(mysql_row[2]); + nr->email = sstrdup(mysql_row[3]); + nr->requested = atoi(mysql_row[4]); + insert_requestnick(nr); + } + mysql_free_result(mysql_res); +} + +void db_mysql_load_ns_dbase(void) +{ + char sqlcmd[MAX_SQL_BUF], *tmpstr; + NickCore *nc; + NickAlias *na; + MYSQL_RES *res; + MYSQL_ROW row; + int i, j, m; + + if (!do_mysql) + return; + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `display`,`pass`,`email`,`icq`,`url`,`flags`,`language`,`accesscount`,`memocount`,`memomax`,`channelcount`,`channelmax`,`greet`,`active` FROM `anope_ns_core`"); + + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + if (mysql_num_rows(mysql_res) == 0) { + mysql_free_result(mysql_res); + return; + } + + while ((mysql_row = mysql_fetch_row(mysql_res))) { + nc = scalloc(1, sizeof(NickCore)); + + nc->display = sstrdup(mysql_row[0]); + nc->pass = sstrdup(mysql_row[1]); + nc->email = sstrdup(mysql_row[2]); + nc->icq = atoi(mysql_row[3]); + nc->url = sstrdup(mysql_row[4]); + nc->flags = atoi(mysql_row[5]); + nc->language = atoi(mysql_row[6]); + nc->accesscount = atoi(mysql_row[7]); + nc->memos.memocount = atoi(mysql_row[8]); + nc->memos.memomax = atoi(mysql_row[9]); + nc->channelcount = atoi(mysql_row[10]); + nc->channelmax = atoi(mysql_row[11]); + + if (mysql_row[12][0] == '\0') /* check if it's empty */ + nc->greet = NULL; + else + nc->greet = sstrdup(mysql_row[12]); + + if (!NSAllowKillImmed) + nc->flags &= ~NI_KILL_IMMED; + +#ifdef USE_ENCRYPTION + if (nc->pass && !(nc->flags & NI_ENCRYPTEDPW)) { + if (debug) + alog("debug: %s: encrypting password for `%s' on load", + s_NickServ, nc->display); + if (encrypt_in_place(nc->pass, PASSMAX) < 0) + fatal("%s: Can't encrypt `%s' nickname password!", + s_NickServ, nc->display); + + nc->flags |= NI_ENCRYPTEDPW; + } +#else + if (nc->flags & NI_ENCRYPTEDPW) + fatal + ("%s: load database: password for %s encrypted but encryption disabled, aborting", + s_NickServ, nc->display); +#endif + + if (nc->flags & NI_SERVICES_ADMIN) + slist_add(&servadmins, nc); + if (nc->flags & NI_SERVICES_OPER) + slist_add(&servopers, nc); + + if (nc->accesscount) { + char **access; + access = scalloc(sizeof(char *) * nc->accesscount, 1); + nc->access = access; + tmpstr = db_mysql_quote(nc->display); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `access` FROM `anope_ns_access` WHERE `display` = '%s'", + tmpstr); + free(tmpstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + while ((row = mysql_fetch_row(res))) { + if (strlen(row[0]) > 0) { + *access = sstrdup(row[0]); + access++; + } + } + mysql_free_result(res); + } + + if (nc->memos.memocount) { + Memo *memos; + memos = scalloc(sizeof(Memo) * nc->memos.memocount, 1); + nc->memos.memos = memos; + tmpstr = db_mysql_quote(nc->display); + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `number`,`flags`,`time`,`sender`,`text` FROM `anope_ms_info` WHERE `receiver` = '%s' ORDER BY `number` ASC", + tmpstr); + free(tmpstr); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + res = mysql_store_result(mysql); + while ((row = mysql_fetch_row(res))) { + memos->number = atoi(row[0]); + memos->flags = atoi(row[1]); + memos->time = atoi(row[2]); + snprintf(memos->sender, NICKMAX, "%s", row[3]); + memos->text = sstrdup(row[4]); + for (m = 0; m < MAX_CMD_HASH; m++) { + memos->moduleData[m] = NULL; + } + memos++; + } + mysql_free_result(res); + } + insert_core(nc); + } + mysql_free_result(mysql_res); + + snprintf(sqlcmd, MAX_SQL_BUF, + "SELECT `display`,`nick`,`time_registered`,`last_seen`,`status`,`last_usermask`,`last_realname`,`last_quit` FROM `anope_ns_alias`"); + if (db_mysql_query(sqlcmd)) { + log_perror("Can't create sql query: %s", sqlcmd); + db_mysql_error(MYSQL_WARNING, "query"); + } + mysql_res = mysql_store_result(mysql); + while ((mysql_row = mysql_fetch_row(mysql_res))) { + na = scalloc(1, sizeof(NickAlias)); + na->nick = sstrdup(mysql_row[1]); + + na->last_usermask = sstrdup(mysql_row[5]); + na->last_realname = sstrdup(mysql_row[6]); + na->last_quit = sstrdup(mysql_row[7]); + na->time_registered = atoi(mysql_row[2]); + na->last_seen = atoi(mysql_row[3]); + na->status = atoi(mysql_row[4]); + na->status &= ~NS_TEMPORARY; + tmpstr = sstrdup(mysql_row[0]); + na->nc = findcore(tmpstr); + free(tmpstr); + + if (na->nc) + slist_add(&na->nc->aliases, na); + + if (!(na->status & NS_VERBOTEN)) { + if (!na->last_usermask) + na->last_usermask = sstrdup(""); + if (!na->last_realname) + na->last_realname = sstrdup(""); + } + + if (na->nc) + na->nc->flags &= ~NI_SERVICES_ROOT; + alpha_insert_alias(na); + } + mysql_free_result(mysql_res); + + for (j = 0; j < 1024; j++) { + NickAlias *next; + for (na = nalists[j]; na; na = next) { + next = na->next; + if (!na->nc) { + alog("%s: while loading database: %s has no core! We delete it.", s_NickServ, na->nick); + delnick(na); + continue; + } + for (i = 0; i < RootNumber; i++) { + if (!stricmp(ServicesRoots[i], na->nick)) + na->nc->flags |= NI_SERVICES_ROOT; + } + } + } } -#endif /* USE_MYSQL */ diff --git a/src/news.c b/src/news.c index a14c69ce9..530a4ae35 100644 --- a/src/news.c +++ b/src/news.c @@ -238,6 +238,25 @@ void save_news() #undef SAFE +void save_rdb_news() +{ +#ifdef USE_RDB + int i; + NewsItem *ni; + + if (!rdb_open()) + return; + + rdb_clear_table("anope_os_news"); + for (i = 0; i < nnews; i++) { + ni = &news[i]; + rdb_save_news(ni); + } + + rdb_close(); +#endif +} + /*************************************************************************/ /***************************** News display ******************************/ /*************************************************************************/ diff --git a/src/nickserv.c b/src/nickserv.c index fa7fc70c0..465f14fa5 100644 --- a/src/nickserv.c +++ b/src/nickserv.c @@ -972,6 +972,64 @@ void save_ns_req_dbase(void) #undef SAFE +void save_ns_rdb_dbase(void) +{ +#ifdef USE_RDB + int i; + NickAlias *na; + NickCore *nc; + + if (!rdb_open()) + return; + + rdb_tag_table("anope_ns_core"); + rdb_tag_table("anope_ns_alias"); + rdb_scrub_table("anope_ms_info", "serv='NICK'"); + rdb_clear_table("anope_ns_access"); + + for (i = 0; i < 1024; i++) { + for (nc = nclists[i]; nc; nc = nc->next) { + rdb_save_ns_core(nc); + + } /* for (nc) */ + } /* for (i) */ + + for (i = 0; i < 1024; i++) { + for (na = nalists[i]; na; na = na->next) { + rdb_save_ns_alias(na); + + } /* for (na) */ + } /* for (i) */ + + rdb_scrub_table("anope_ns_core", "active='0'"); + rdb_scrub_table("anope_ns_alias", "active='0'"); + rdb_close(); +#endif +} + +void save_ns_req_rdb_dbase(void) +{ +#ifdef USE_RDB + int i; + NickRequest *nr; + + if (!rdb_open()) + return; + + rdb_tag_table("anope_ns_request"); + + for (i = 0; i < 1024; i++) { + for (nr = nrlists[i]; nr; nr = nr->next) { + rdb_save_ns_req(nr); + } + } + + rdb_scrub_table("anope_ns_request", "active='0'"); + rdb_close(); +#endif + +} + /*************************************************************************/ /* Check whether a user is on the access list of the nick they're using If @@ -1379,6 +1437,17 @@ static void change_core_display(NickCore * nc, char *newdisplay) alog("%s: changing %s nickname group display to %s", s_NickServ, nc->display, newdisplay); +#ifdef USE_RDB + /* Reflect this change in the database right away. This + * ensures that we know how to deal with this "new" nick + * on the next /OS UPDATE might need it on /NS DROP too... + */ + if (rdb_open()) { + rdb_ns_set_display(newdisplay, nc->display); + rdb_close(); + } +#endif + /* Remove the core from the list */ if (nc->next) nc->next->prev = nc->prev; @@ -1403,6 +1472,9 @@ static void change_core_display(NickCore * nc, char *newdisplay) static int delcore(NickCore * nc) { int i; +#ifdef USE_RDB + static char clause[128]; +#endif /* (Hopefully complete) cleanup */ cs_remove_nick(nc); os_remove_nick(nc); @@ -1418,6 +1490,23 @@ static int delcore(NickCore * nc) /* Log .. */ alog("%s: deleting nickname group %s", s_NickServ, nc->display); +#ifdef USE_RDB + /* Reflect this change in the database right away. */ + if (rdb_open()) { + + snprintf(clause, sizeof(clause), "display='%s'", nc->display); + rdb_scrub_table("anope_ns_access", clause); + rdb_scrub_table("anope_ns_core", clause); + rdb_scrub_table("anope_cs_access", clause); + /* I'm unsure how to clean up the OS ADMIN/OPER list on the db */ + /* I wish the "display" primary key would be the same on all tables */ + snprintf(clause, sizeof(clause), "receiver='%s' AND serv='NICK'", + nc->display); + rdb_scrub_table("anope_ms_info", clause); + rdb_close(); + } +#endif + /* Now we can safely free it. */ free(nc->display); if (nc->pass) @@ -1486,6 +1575,9 @@ int delnickrequest(NickRequest * nr) int delnick(NickAlias * na) { +#ifdef USE_RDB + static char clause[128]; +#endif /* First thing to do: remove any timeout belonging to the nick we're deleting */ clean_ns_timeouts(na); @@ -1529,6 +1621,16 @@ int delnick(NickAlias * na) else nalists[HASH(na->nick)] = na->next; +#ifdef USE_RDB + /* Reflect this change in the database right away. */ + if (rdb_open()) { + + snprintf(clause, sizeof(clause), "nick='%s'", na->nick); + rdb_scrub_table("anope_ns_alias", clause); + rdb_close(); + } +#endif + free(na->nick); if (na->last_usermask) free(na->last_usermask); @@ -2213,6 +2315,16 @@ static int do_group(User * u) u->na = na; na->u = u; +#ifdef USE_RDB + /* Is this really needed? Since this is a new alias it will get + * its unique id on the next update, since it was previously + * deleted by delnick. Must observe... + */ + if (rdb_open()) { + rdb_save_ns_alias(na); + rdb_close(); + } +#endif alog("%s: %s!%s@%s makes %s join group of %s (%s) (e-mail: %s)", s_NickServ, u->nick, u->username, GetHost(u), u->nick, target->nick, target->nc->display, (target->nc->email ? target->nc->email : "none")); notice_lang(s_NickServ, u, NICK_GROUP_JOINED, target->nick); diff --git a/src/operserv.c b/src/operserv.c index 1042e9c1e..d42ab7de1 100644 --- a/src/operserv.c +++ b/src/operserv.c @@ -774,6 +774,19 @@ void save_os_dbase(void) /*************************************************************************/ +void save_os_rdb_dbase(void) +{ +#ifdef USE_RDB + if (!rdb_open()) + return; + rdb_save_os_db(maxusercnt, maxusertime, &akills, &sglines, &sqlines, + &szlines, hcache[0]); + rdb_close(); +#endif +} + +/*************************************************************************/ + /* Removes the nick structure from OperServ lists. */ void os_remove_nick(NickCore * nc) @@ -13,66 +13,454 @@ */ #include "services.h" +/*************************************************************************/ + +int rdb_init() +{ + +#ifdef USE_MYSQL + return db_mysql_init(); +#endif + +} + +/*************************************************************************/ + +int rdb_open() +{ + +#ifdef USE_MYSQL + return do_mysql; // db_mysql_open(); +#endif + +} + +/*************************************************************************/ + +int rdb_close() +{ + +#ifdef USE_MYSQL + return 1; // db_mysql_close(); +#endif + +} + +/*************************************************************************/ + +int rdb_tag_table(char *table) +{ + static char buf[1024]; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), "UPDATE %s SET active='0'", table); + return db_mysql_query(buf); +#endif + + return 0; + +} + +/*************************************************************************/ + +int rdb_clear_table(char *table) +{ + static char buf[1024]; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), "TRUNCATE TABLE %s", table); + return db_mysql_query(buf); +#endif + + return 0; + +} + +/*************************************************************************/ + +int rdb_scrub_table(char *table, char *clause) +{ + + static char buf[1024]; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), "DELETE FROM %s WHERE %s", table, clause); + return db_mysql_query(buf); +#endif + + return 0; + +} + +/*************************************************************************/ + +int rdb_direct_query(char *query) +{ + +#ifdef USE_MYSQL + alog("Direct Query: %s", query); + return db_mysql_query(query); +#endif + + return 0; + +} + +/*************************************************************************/ + +/* I still don't really like doing it this way, it should really be done + * inside mysql.c and not here. So I'll revisit this later + */ +int rdb_ns_set_display(char *newnick, char *oldnick) +{ + static char buf[1024]; + +#ifdef USE_MYSQL + /* Change the display on NS_CORE */ + snprintf(buf, sizeof(buf), + "UPDATE anope_ns_core SET display='%s' WHERE display='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Change the display on NS_ALIAS for all grouped nicks */ + snprintf(buf, sizeof(buf), + "UPDATE anope_ns_alias SET display='%s' WHERE display='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Change the display on ChanServ ACCESS list */ + snprintf(buf, sizeof(buf), + "UPDATE anope_cs_access SET display='%s' WHERE display='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Change the display on ChanServ AKICK list */ + snprintf(buf, sizeof(buf), + "UPDATE anope_cs_access SET creator='%s' WHERE creator='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Change the display on MemoServ sent memos */ + snprintf(buf, sizeof(buf), + "UPDATE anope_ms_info SET sender='%s' WHERE sender='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Change the display on MemoServ received memos */ + snprintf(buf, sizeof(buf), + "UPDATE anope_ms_info SET receiver='%s' WHERE receiver='%s'", + newnick, oldnick); + db_mysql_query(buf); + + /* Need to do bwords and akills */ + +#endif + + return 0; +} + +/*************************************************************************/ + +int rdb_cs_deluser(char *nick) +{ + static char buf[1024]; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), + "UPDATE anope_cs_info SET successor=NULL WHERE successor='%s'", + nick); + db_mysql_query(buf); + + snprintf(buf, sizeof(buf), "display='%s'", nick); + rdb_scrub_table("anope_cs_access", buf); + snprintf(buf, sizeof(buf), "creator='%s'", nick); + rdb_scrub_table("anope_cs_akicks", buf); + + return 1; +#endif + + return 0; +} + +/*************************************************************************/ + +int rdb_cs_delchan(ChannelInfo * ci) +{ + static char buf[1024]; + char *channel = ci->name; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), + "UPDATE anope_cs_info SET successor=NULL WHERE name='%s'", + channel); + db_mysql_query(buf); + + snprintf(buf, sizeof(buf), "name='%s'", channel); + rdb_scrub_table("anope_cs_info", buf); + snprintf(buf, sizeof(buf), "receiver='%s' AND serv='CHAN'", channel); + rdb_scrub_table("anope_ms_info", buf); + snprintf(buf, sizeof(buf), "channel='%s'", channel); + rdb_scrub_table("anope_cs_access", buf); + rdb_scrub_table("anope_cs_akicks", buf); + rdb_scrub_table("anope_cs_levels", buf); + rdb_scrub_table("anope_cs_badwords", buf); + if (ci->founder) { + snprintf(buf, sizeof(buf), + "update anope_ns_core set channelcount=channelcount-1 where display='%s'", + ci->founder->display); + db_mysql_query(buf); + } + + return 1; +#endif + + return 0; +} + +/*************************************************************************/ + +int rdb_cs_set_founder(char *channel, char *founder) +{ + static char buf[1024]; + +#ifdef USE_MYSQL + snprintf(buf, sizeof(buf), + "UPDATE anope_cs_info SET founder='%s', successor=NULL WHERE name='%s'", + founder, channel); + db_mysql_query(buf); + + snprintf(buf, sizeof(buf), + "UPDATE anope_ns_core SET channelcount=channelcount+1 WHERE display='%s'", + founder); + db_mysql_query(buf); + + /* Do i need to scrub the access list for this channel ? */ + snprintf(buf, sizeof(buf), "display='%s' AND channel='%s'", founder, + channel); + rdb_scrub_table("anope_cs_access", buf); + + return 1; +#endif + + return 0; +} + +/*************************************************************************/ + +void rdb_save_ns_core(NickCore * nc) +{ + #ifdef USE_MYSQL -#define RDB_MYSQL(x) x -#else -#define RDB_MYSQL(x) + db_mysql_save_ns_core(nc); #endif -void rdb_init(void) +} + +/*************************************************************************/ + +void rdb_save_ns_alias(NickAlias * na) { - RDB_MYSQL(db_mysql_init()); + +#ifdef USE_MYSQL + db_mysql_save_ns_alias(na); +#endif + } -void rdb_end(void) +/*************************************************************************/ + +void rdb_save_ns_req(NickRequest * nr) { - RDB_MYSQL(db_mysql_end()); + +#ifdef USE_MYSQL + db_mysql_save_ns_req(nr); +#endif + } -/* BotServ */ -void rdb_bs_add_bot(BotInfo *bi) +/*************************************************************************/ + +void rdb_save_cs_info(ChannelInfo * ci) { - RDB_MYSQL(db_mysql_bs_add_bot(bi)); + +#ifdef USE_MYSQL + db_mysql_save_cs_info(ci); +#endif + } -void rdb_bs_del_bot(BotInfo *bi) +/*************************************************************************/ + +void rdb_save_bs_core(BotInfo * bi) { - RDB_MYSQL(db_mysql_bs_del_bot(bi)); + +#ifdef USE_MYSQL + db_mysql_save_bs_core(bi); +#endif + } -void rdb_bs_change_bot(BotInfo *bi, char *newnick, char *newuser, char *newhost, char *newreal) +/*************************************************************************/ + +void rdb_save_hs_core(HostCore * hc) { - RDB_MYSQL(db_mysql_bs_chg_bot(bi, newnick, newuser, newhost, newreal)); + +#ifdef USE_MYSQL + db_mysql_save_hs_core(hc); +#endif + } -void rdb_bs_change_bot_chancount(BotInfo *bi) +/*************************************************************************/ + +void rdb_save_os_db(unsigned int maxucnt, unsigned int maxutime, + SList * ak, SList * sgl, SList * sql, SList * szl, + HostCache * hc) { - RDB_MYSQL(db_mysql_bs_chg_bot_chancount(bi)); + +#ifdef USE_MYSQL + db_mysql_save_os_db(maxusercnt, maxusertime, ak, sgl, sql, szl, hc); +#endif + } -void rdb_bs_change_bot_flags(BotInfo *bi) +/*************************************************************************/ + +void rdb_save_news(NewsItem * ni) { - RDB_MYSQL(db_mysql_bs_chg_bot_flags(bi)); + +#ifdef USE_MYSQL + db_mysql_save_news(ni); +#endif + } -void rdb_cs_add_access(ChannelInfo *ci, ChanAccess *access) +/*************************************************************************/ + +void rdb_load_bs_dbase(void) { - RDB_MYSQL(db_mysql_cs_add_access(ci, access)); + +#ifdef USE_MYSQL + db_mysql_load_bs_dbase(); +#endif + } -void rdb_cs_del_access(ChanAccess *access) +/*************************************************************************/ + +void rdb_load_hs_dbase(void) { - ChannelInfo *ci, *found; - ChanAccess *caccess; - int i, y; - /* Need to fetch channel manually since ChanAccess has no member for it */ - for (i = 0; i < 256; i++) { - for (ci = chanlists[i]; ci; ci = ci->next) { - for (caccess = ci->access, y = 0; y < ci->accesscount; caccess++, y++) { - if (caccess == access) { found = ci; } - } + +#ifdef USE_MYSQL + db_mysql_load_hs_dbase(); +#endif + +} + +/*************************************************************************/ + +void rdb_load_ns_dbase(void) +{ + +#ifdef USE_MYSQL + db_mysql_load_ns_dbase(); +#endif +} + +/*************************************************************************/ + +void rdb_load_news(void) +{ +#ifdef USE_MYSQL + db_mysql_load_news(); +#endif +} + +/*************************************************************************/ + +void rdb_load_exceptions(void) +{ +#ifdef USE_MYSQL + db_mysql_load_exceptions(); +#endif +} + +/*************************************************************************/ + +void rdb_load_cs_dbase(void) +{ +#ifdef USE_MYSQL + db_mysql_load_cs_dbase(); +#endif +} + +/*************************************************************************/ + +void rdb_load_os_dbase(void) +{ +#ifdef USE_MYSQL + db_mysql_load_os_dbase(); +#endif +} + +/*************************************************************************/ + +void rdb_load_ns_req_dbase(void) +{ +#ifdef USE_MYSQL + db_mysql_load_ns_req_dbase(); +#endif +} + +/*************************************************************************/ + +void rdb_load_dbases(void) +{ + if (!skeleton) { + rdb_load_ns_dbase(); + if (debug) + alog("RDB: Loaded NickServ DataBase (1/8)"); + if (s_HostServ) { + rdb_load_hs_dbase(); + if (debug) + alog("RDB: Loaded HostServ DataBase (2/8)"); + } + if (s_BotServ) { + rdb_load_bs_dbase(); + if (debug) + alog("RDB: Loaded BotServ DataBase (3/8)"); } + rdb_load_cs_dbase(); + if (debug) + alog("RDB: Loaded ChanServ DataBase (4/8)"); } - if (!found) return; - RDB_MYSQL(db_mysql_cs_del_access(found, access)); + rdb_load_os_dbase(); + if (debug) + alog("RDB: Loaded OperServ DataBase (5/8)"); + rdb_load_news(); + if (debug) + alog("RDB: Loaded News DataBase (6/8)"); + rdb_load_exceptions(); + if (debug) + alog("RDB: Loaded Exception Database (7/8)"); + if (PreNickDBName) { + rdb_load_ns_req_dbase(); + if (debug) + alog("RDB: Loaded PreNick DataBase (8/8)"); + } else { + if (debug) + alog("RDB: No need to load PreNickDB (8/8)"); + } + alog("RDB: All DataBases loaded."); +} + +/*************************************************************************/ + +void rdb_save_exceptions(Exception * e) +{ + +#ifdef USE_MYSQL + db_mysql_save_exceptions(e); +#endif + } diff --git a/src/sessions.c b/src/sessions.c index 192ba3ea9..1620a2e15 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -461,6 +461,25 @@ void save_exceptions() #undef SAFE /*************************************************************************/ + +void save_rdb_exceptions() +{ +#ifdef USE_RDB + int i; + Exception *e; + + if (!rdb_open()) + return; + rdb_clear_table("anope_os_exceptions"); + for (i = 0; i < nexceptions; i++) { + e = &exceptions[i]; + rdb_save_exceptions(e); + } + rdb_close(); +#endif +} + +/*************************************************************************/ /************************ Exception Manipulation *************************/ /*************************************************************************/ |