summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/extern.h91
-rw-r--r--include/services.h2
-rw-r--r--src/botserv.c31
-rw-r--r--src/chanserv.c50
-rw-r--r--src/config.c2
-rw-r--r--src/hostserv.c33
-rw-r--r--src/init.c34
-rw-r--r--src/main.c36
-rw-r--r--src/mysql.c1755
-rw-r--r--src/news.c19
-rw-r--r--src/nickserv.c112
-rw-r--r--src/operserv.c13
-rw-r--r--src/rdb.c452
-rw-r--r--src/sessions.c19
-rw-r--r--version.log6
15 files changed, 2418 insertions, 237 deletions
diff --git a/include/extern.h b/include/extern.h
index b24193718..fe02b446b 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -16,7 +16,6 @@
#define EXTERN_H
#include "slist.h"
-#include "rdb.h"
#define E extern
@@ -43,6 +42,7 @@ E void botmsgs(User *u, BotInfo *bi, char *buf);
E void botchanmsgs(User *u, ChannelInfo *ci, char *buf);
E void load_bs_dbase(void);
E void save_bs_dbase(void);
+E void save_bs_rdb_dbase(void);
E BotInfo *makebot(char *nick);
E BotInfo *findbot(char *nick);
@@ -101,6 +101,7 @@ E void cs_init(void);
E void chanserv(User * u, char *buf);
E void load_cs_dbase(void);
E void save_cs_dbase(void);
+E void save_cs_rdb_dbase(void);
E void expire_chans(void);
E void cs_remove_nick(const NickCore * nc);
E void cs_remove_bot(const BotInfo * bi);
@@ -228,6 +229,7 @@ E char *desc_HostServ;
E char *s_HostServ;
E void load_hs_dbase(void);
E void save_hs_dbase(void);
+E void save_hs_rdb_dbase(void);
E int do_on_id(User * u);
E void delHostCore(char *nick);
E void hostserv(User * u, char *buf);
@@ -420,6 +422,50 @@ E char *ExceptionDBName;
E char *SessionLimitDetailsLoc;
E char *SessionLimitExceeded;
+#ifdef USE_RDB
+E int rdb_init();
+E int rdb_open();
+E int rdb_close();
+E int rdb_tag_table(char *table);
+E int rdb_tag_table(char *table);
+E int rdb_clear_table(char *table);
+E int rdb_scrub_table(char *table, char *clause);
+E int rdb_direct_query(char *query);
+E int rdb_ns_set_display(char *newnick, char *oldnick);
+E int rdb_cs_set_founder(char *channel, char *founder);
+E int rdb_cs_deluser(char *nick);
+E int rdb_cs_delchan(ChannelInfo * ci);
+E void rdb_save_ns_core(NickCore * nc);
+E void rdb_save_ns_alias(NickAlias * na);
+E void rdb_save_ns_req(NickRequest * nr);
+E void rdb_save_cs_info(ChannelInfo * ci);
+E void rdb_save_bs_core(BotInfo * bi);
+E void rdb_save_bs_rdb_core(BotInfo * bi);
+E void rdb_save_hs_core(HostCore * hc);
+E void rdb_save_os_db(unsigned int maxucnt, unsigned int maxutime,
+ SList * ak, SList * sgl, SList * sql, SList * szl,
+ HostCache * hc);
+E void rdb_save_news(NewsItem * ni);
+E void rdb_save_exceptions(Exception * e);
+E void rdb_load_bs_dbase(void);
+E void rdb_load_hs_dbase(void);
+E void rdb_load_ns_dbase(void);
+E void rdb_load_dbases(void);
+#endif
+
+#ifdef USE_MYSQL
+E char *MysqlHost;
+E char *MysqlUser;
+E char *MysqlPass;
+E char *MysqlName;
+E int MysqlPort;
+E char *MysqlSock;
+E char *MysqlSecure;
+E int MysqlRetries;
+E int MysqlRetryGap;
+E int UseRDB;
+#endif
+
E int read_config(int reload);
E int DefConLevel;
@@ -504,6 +550,10 @@ E int nofork;
E int forceload;
E int noexpire;
+#ifdef USE_RDB
+E int do_mysql;
+#endif
+
E int is44;
E int quitting;
@@ -573,6 +623,7 @@ E NewsItem *news;
E void get_news_stats(long *nrec, long *memuse);
E void load_news(void);
E void save_news(void);
+E void save_rdb_news(void);
E void display_news(User * u, int16 type);
E int do_logonnews(User * u);
E int do_opernews(User * u);
@@ -600,6 +651,8 @@ E void load_ns_dbase(void);
E void load_ns_req_db(void);
E void save_ns_dbase(void);
E void save_ns_req_dbase(void);
+E void save_ns_rdb_dbase(void);
+E void save_ns_req_rdb_dbase(void);
E int validate_user(User * u);
E void cancel_user(User * u);
E int nick_identified(User * u);
@@ -635,6 +688,7 @@ E void operserv(User *u, char *buf);
E void os_init(void);
E void load_os_dbase(void);
E void save_os_dbase(void);
+E void save_os_rdb_dbase(void);
E void os_remove_nick(NickCore *nc);
E int is_services_root(User *u);
@@ -768,6 +822,7 @@ E void del_session(const char *host);
E void load_exceptions(void);
E void save_exceptions(void);
+E void save_rdb_exceptions(void);
E int do_exception(User *u);
E void expire_exceptions(void);
@@ -829,8 +884,42 @@ E void split_usermask(const char *mask, char **nick, char **user,
char **host);
E char *create_mask(User * u);
+#ifdef USE_MYSQL
+/**** mysql.c ****/
+E MYSQL *mysql;
+E MYSQL_RES *mysql_res;
+E MYSQL_FIELD *mysql_fields;
+E MYSQL_ROW mysql_row;
+
+E int db_mysql_init();
+E int db_mysql_open();
+E int db_mysql_close();
+E int db_mysql_query(char *sql);
+E char *db_mysql_quote(char *sql);
+E void db_mysql_save_ns_core(NickCore * nc);
+E void db_mysql_save_ns_alias(NickAlias * na);
+E void db_mysql_save_ns_req(NickRequest * nr);
+E void db_mysql_save_cs_info(ChannelInfo * ci);
+E void db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime,
+ SList * ak, SList * sgl, SList * sql,
+ SList * szl, HostCache * hc);
+E void db_mysql_save_news(NewsItem * ni);
+E void db_mysql_save_exceptions(Exception * e);
+E void db_mysql_save_hs_core(HostCore * hc);
+E void db_mysql_save_bs_core(BotInfo * bi);
+E void db_mysql_load_bs_dbase(void);
+E void db_mysql_load_hs_dbase(void);
+E void db_mysql_load_ns_dbase(void);
+E void db_mysql_load_ns_req_dbase(void);
+E void db_mysql_load_cs_dbase(void);
+E void db_mysql_load_os_dbase(void);
+E void db_mysql_load_exceptions(void);
+E void db_mysql_load_news(void);
+#endif
+
#ifdef USE_ENCRYPTION
extern int encrypt_in_place(char *buf, int size);
#endif
+
#endif /* EXTERN_H */
diff --git a/include/services.h b/include/services.h
index a6d61a19b..5a2a6dd6b 100644
--- a/include/services.h
+++ b/include/services.h
@@ -58,7 +58,7 @@
# define MYSQL_WARNING 2
# define MYSQL_ERROR 4
-#include <mysql.h>
+#include "mysql.h"
#include "errmsg.h"
#endif
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)