summaryrefslogtreecommitdiff
path: root/src/mysql.c
diff options
context:
space:
mode:
authorsjaz <sjaz@5417fbe8-f217-4b02-8779-1006273d7864>2009-01-01 12:00:20 +0000
committersjaz <sjaz@5417fbe8-f217-4b02-8779-1006273d7864>2009-01-01 12:00:20 +0000
commitc777c8d9aa7cd5c2e9a399727a7fa9985a77fb1c (patch)
tree9e996ae4a1bbb833cec036c5cd4d87a590149e85 /src/mysql.c
Anope Stable Branch
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/stable@1902 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src/mysql.c')
-rw-r--r--src/mysql.c2058
1 files changed, 2058 insertions, 0 deletions
diff --git a/src/mysql.c b/src/mysql.c
new file mode 100644
index 000000000..c4db94252
--- /dev/null
+++ b/src/mysql.c
@@ -0,0 +1,2058 @@
+
+/* MySQL functions.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ * $Id$
+ *
+ */
+#include "services.h"
+
+/*************************************************************************/
+
+/* 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 */
+
+int mysql_is_connected = 0; /* Are we currently connected? */
+
+/*************************************************************************/
+
+/* Throw a mysql error into the logs. If severity is MYSQL_ERROR, we
+ * also exit Anope...
+ */
+void db_mysql_error(int severity, char *msg)
+{
+ static char buf[512];
+
+ 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");
+ }
+
+ log_perror(buf);
+
+ if (severity == MYSQL_ERROR) {
+ log_perror("MySQL FATAL error... aborting.");
+ exit(0);
+ }
+
+}
+
+/*************************************************************************/
+
+/* Initialize the MySQL code */
+int db_mysql_init()
+{
+
+ /* If the host is not defined, assume we don't want MySQL */
+ if (!MysqlHost) {
+ do_mysql = 0;
+ alog("MySQL: has been disabled.");
+ return 0;
+ } else {
+ do_mysql = 1;
+ alog("MySQL: has been enabled.");
+ alog("MySQL: client version %s.", mysql_get_client_info());
+ }
+
+ /* The following configuration options are required.
+ * If missing disable MySQL to avoid any problems.
+ */
+
+ if ((do_mysql) && (!MysqlName || !MysqlUser)) {
+ do_mysql = 0;
+ alog("MySQL Error: Set all required configuration options.");
+ return 0;
+ }
+
+ if (!db_mysql_open()) {
+ do_mysql = 0;
+ return 0;
+ }
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/* Open a connection to the mysql database. Return 0 on failure, or
+ * 1 on success. If this succeeds, we're guaranteed of a working
+ * mysql connection (unless something unexpected happens ofcourse...)
+ */
+int db_mysql_open()
+{
+ /* If MySQL is disabled, return 0 */
+ if (!do_mysql)
+ return 0;
+
+ /* If we are reported to be connected, ping MySQL to see if we really are
+ * still connected. (yes mysql_ping() returns 0 on success)
+ */
+ if (mysql_is_connected && !mysql_ping(mysql))
+ return 1;
+
+ mysql_is_connected = 0;
+
+ mysql = mysql_init(NULL);
+ if (mysql == NULL) {
+ db_mysql_error(MYSQL_WARNING, "Unable to create mysql object");
+ return 0;
+ }
+
+ if (!MysqlPort)
+ MysqlPort = MYSQL_DEFAULT_PORT;
+
+ if (!mysql_real_connect(mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort, MysqlSock, 0)) {
+ log_perror("MySQL Error: Cant connect to MySQL: %s\n", mysql_error(mysql));
+ return 0;
+ }
+
+ mysql_is_connected = 1;
+
+ return 1;
+
+}
+
+
+/*************************************************************************/
+
+/* Perform a MySQL query. Return 1 if the query succeeded and 0 if the
+ * query failed. Before returning failure, re-try the query a few times
+ * and die if it still fails.
+ */
+int db_mysql_query(char *sql)
+{
+ int lcv;
+
+ if (!do_mysql)
+ return 0;
+
+ if (debug)
+ alog("debug: MySQL: %s", sql);
+
+ /* Try as many times as configured in MysqlRetries */
+ for (lcv = 0; lcv < MysqlRetries; lcv++) {
+ if (db_mysql_open() && (mysql_query(mysql, sql) == 0))
+ return 1;
+
+ /* If we get here, we could not run the query */
+ log_perror("Unable to run query: %s\n", mysql_error(mysql));
+
+ /* Wait for MysqlRetryGap seconds and try again */
+ sleep(MysqlRetryGap);
+ }
+
+ /* Unable to run the query even after MysqlRetries tries */
+ db_mysql_error(MYSQL_WARNING, "query");
+
+ return 0;
+
+}
+
+/*************************************************************************/
+
+/* Quote a string to be safely included in a query. The result of this
+ * function is allocated; it MUST be freed by the caller.
+ */
+char *db_mysql_quote(char *sql)
+{
+ 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;
+
+}
+
+/**
+ * Quote a buffer to be safely included in a query.
+ * The result is allocated and needs to be freed by caller.
+ **/
+char *db_mysql_quote_buffer(char *sql, int size)
+{
+ char *ret;
+ ret = scalloc((1 + 2 * size), sizeof(char));
+
+ mysql_real_escape_string(mysql, ret, sql, size);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/* Close the MySQL database connection. */
+int db_mysql_close()
+{
+ mysql_close(mysql);
+
+ mysql_is_connected = 0;
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/* Try to execute a query and issue a warning when failed. Return 1 on
+ * success and 0 on failure.
+ */
+int db_mysql_try(const char *fmt, ...)
+{
+ va_list args;
+ static char sql[MAX_SQL_BUF];
+
+ va_start(args, fmt);
+ vsnprintf(sql, MAX_SQL_BUF, fmt, args);
+ va_end(args);
+
+ if (!db_mysql_query(sql)) {
+ log_perror("Can't create sql query: %s", sql);
+ db_mysql_error(MYSQL_WARNING, "query");
+ return 0;
+ }
+
+ return 1;
+}
+
+/*************************************************************************/
+
+/**
+ * Returns a string (buffer) to insert into a SQL query.
+ * The string will, once evaluated by MySQL, result in the given pass
+ * encoded in the encryption type selected for MysqlSecure
+ *
+ * This should be removed since Rob properly did encryption modules... -GD
+ *
+ * @param dest Destination buffer to store the password/ encryption string in. Needs to be at least size+14.
+ * @param pass The buffer containing the password to secure.
+ * @param bufsize The size of the destination buffer.
+ * @param size The size of the password-to-secure buffer.
+ * @return Returns -1 on failure, 1 if the result needs to be made MySQL safe (hash), 0 if it s ready.
+ **/
+int db_mysql_secure(char *dest, char *pass, int bufsize, int size)
+{
+ char tmp_pass[PASSMAX];
+
+ if (bufsize < size+14)
+ return -1;
+
+ /* Initialize the buffer. Bug #86 */
+ memset(tmp_pass, 0, PASSMAX);
+ memset(dest, 0, bufsize);
+
+ /* Return all zeros if no pass is set. */
+ if (!pass)
+ return 1;
+
+ /* We couldnt decrypt the pass... */
+ if (enc_decrypt(pass, tmp_pass, PASSMAX - 1) != 1) {
+ memcpy(dest, pass, size);
+ return 1;
+ } else { /* if we could decrypt the pass */
+ if ((!MysqlSecure) || (strcmp(MysqlSecure, "") == 0)) {
+ snprintf(dest, bufsize, "'%s'", tmp_pass);
+ } else if (strcmp(MysqlSecure, "des") == 0) {
+ snprintf(dest, bufsize, "ENCRYPT('%s')", tmp_pass);
+ } else if (strcmp(MysqlSecure, "md5") == 0) {
+ snprintf(dest, bufsize, "MD5('%s')", tmp_pass);
+ } else if (strcmp(MysqlSecure, "sha") == 0) {
+ snprintf(dest, bufsize, "SHA('%s')", tmp_pass);
+ } else {
+ snprintf(dest, bufsize, "ENCODE('%s','%s')", tmp_pass,
+ MysqlSecure);
+ }
+ }
+
+ return 0;
+}
+
+/*************************************************************************/
+
+/*
+ * NickServ Specific Secion
+ */
+
+/*************************************************************************/
+
+/* Save the given NickRequest into the database
+ * Return 1 on success, 0 on failure
+ * These tables are tagged and will be cleaned:
+ * - anope_ns_request
+ */
+int db_mysql_save_ns_req(NickRequest * nr)
+{
+ int ret;
+ char *q_nick, *q_passcode, *q_password, *q_email;
+
+ q_nick = db_mysql_quote(nr->nick);
+ q_passcode = db_mysql_quote(nr->passcode);
+ q_password = db_mysql_quote_buffer(nr->password, PASSMAX);
+ q_email = db_mysql_quote(nr->email);
+
+ ret = db_mysql_try("UPDATE anope_ns_request "
+ "SET passcode = '%s', password = '%s', email = '%s', requested = %d, active = 1 "
+ "WHERE nick = '%s'",
+ q_passcode, q_password, q_email, (int) nr->requested,
+ q_nick);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_ns_request "
+ "(nick, passcode, password, email, requested, active) "
+ "VALUES ('%s', '%s', '%s', '%s', %d, 1)",
+ q_nick, q_passcode, q_password, q_email,
+ (int) nr->requested);
+ }
+
+ free(q_nick);
+ free(q_passcode);
+ free(q_password);
+ free(q_email);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/* Save the given NickCore into the database
+ * Also save the access list and memo's for this user
+ * Return 1 on success, 0 on failure
+ * These tables are tagged and will be cleaned:
+ * - anope_ns_core
+ * - anope_ns_alias
+ * - anope_ns_access
+ * - anope_ms_info (serv='NICK')
+ */
+int db_mysql_save_ns_core(NickCore * nc)
+{
+ int ret, res;
+ int i;
+ char epass[PASSMAX+15];
+ char *q_display, *q_pass = NULL, *q_email, *q_greet, *q_url,
+ *q_access, *q_sender, *q_text;
+
+ q_display = db_mysql_quote(nc->display);
+ q_email = db_mysql_quote(nc->email);
+ q_greet = db_mysql_quote(nc->greet);
+ q_url = db_mysql_quote(nc->url);
+
+ /* First secure the pass, then make it MySQL safe.. - Viper */
+ res = db_mysql_secure(epass, nc->pass, PASSMAX+15, PASSMAX);
+ if (res < 0)
+ fatal("Unable to encrypt password for MySQL");
+ else if (res)
+ q_pass = db_mysql_quote_buffer(epass, PASSMAX+15);
+ else {
+ q_pass = scalloc(PASSMAX+15,sizeof(char));
+ memcpy(q_pass, epass, PASSMAX+15);
+ }
+
+ /* If it has been made MySQL safe, it still needs the 's.
+ * I know it s an ugly solution, but it works without breaking anything.. - Viper */
+ /* Let's take care of the core itself */
+ /* Update the existing records */
+ if (res)
+ ret = db_mysql_try("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'",
+ q_pass, q_email, q_greet, nc->icq, q_url, nc->flags,
+ nc->language, nc->accesscount, nc->memos.memocount,
+ nc->memos.memomax, nc->channelcount, nc->channelmax,
+ q_display);
+ else
+ ret = db_mysql_try("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'",
+ q_pass, q_email, q_greet, nc->icq, q_url, nc->flags,
+ nc->language, nc->accesscount, nc->memos.memocount,
+ nc->memos.memomax, nc->channelcount, nc->channelmax,
+ q_display);
+
+ /* Our previous UPDATE affected no rows, therefore this is a new record */
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ if (res)
+ ret = db_mysql_try("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)",
+ q_display, q_pass, q_email, q_greet, nc->icq, q_url,
+ nc->flags, nc->language, nc->accesscount,
+ nc->memos.memocount, nc->memos.memomax,
+ nc->channelcount, nc->channelmax);
+ else
+ ret = db_mysql_try("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)",
+ q_display, q_pass, q_email, q_greet, nc->icq, q_url,
+ nc->flags, nc->language, nc->accesscount,
+ nc->memos.memocount, nc->memos.memomax,
+ nc->channelcount, nc->channelmax);
+ }
+
+ /* Now let's do the access */
+ for (i = 0; ret && (i < nc->accesscount); i++) {
+ q_access = db_mysql_quote(nc->access[i]);
+/**
+ ret = db_mysql_try("UPDATE anope_ns_access "
+ "SET access = '%s' "
+ "WHERE display = '%s'",
+ q_access, q_display);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {**/
+
+ ret = db_mysql_try("INSERT DELAYED INTO anope_ns_access "
+ "(display, access) "
+ "VALUES ('%s','%s')",
+ q_display, q_access);
+/* } */
+
+ free(q_access);
+ }
+
+ /* Memos */
+ for (i = 0; ret && (i < nc->memos.memocount); i++) {
+ q_sender = db_mysql_quote(nc->memos.memos[i].sender);
+ q_text = db_mysql_quote(nc->memos.memos[i].text);
+
+ ret = db_mysql_try("UPDATE anope_ms_info "
+ "SET receiver = '%s', number = %d, flags = %d, time = %d, sender = '%s', text = '%s', active = 1 "
+ "WHERE nm_id = %d AND serv = 'NICK'",
+ q_display, nc->memos.memos[i].number,
+ nc->memos.memos[i].flags,
+ (int) nc->memos.memos[i].time, q_sender, q_text,
+ nc->memos.memos[i].id);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT INTO anope_ms_info "
+ "(receiver, number, flags, time, sender, text, serv, active) "
+ "VALUES ('%s', %d, %d, %d, '%s', '%s', 'NICK', 1)",
+ q_display, nc->memos.memos[i].number,
+ nc->memos.memos[i].flags,
+ (int) nc->memos.memos[i].time, q_sender,
+ q_text);
+
+ /* This is to make sure we can UPDATE memos instead of TRUNCATE
+ * the table each time and then INSERT them all again. Ideally
+ * everything in core would have it's dbase-id stored, but that's
+ * something for phase 3. -GD
+ */
+ if (ret)
+ nc->memos.memos[i].id = mysql_insert_id(mysql);
+ }
+
+ free(q_sender);
+ free(q_text);
+ }
+
+ free(q_display);
+ free(q_pass);
+ free(q_email);
+ free(q_greet);
+ free(q_url);
+
+ return ret;
+}
+
+
+/*************************************************************************/
+
+/* Save the given NickAlias into the database
+ * Return 1 on success, 0 on failure
+ * These tables are tagged and will be cleaned:
+ * - anope_ns_core
+ * - anope_ns_alias
+ * - anope_ns_access
+ * - anope_ms_info (serv='NICK')
+ */
+int db_mysql_save_ns_alias(NickAlias * na)
+{
+ int ret;
+ char *q_nick, *q_lastmask, *q_lastrname, *q_lastquit, *q_display;
+
+ q_nick = db_mysql_quote(na->nick);
+ q_lastmask = db_mysql_quote(na->last_usermask);
+ q_lastrname = db_mysql_quote(na->last_realname);
+ q_lastquit = db_mysql_quote(na->last_quit);
+ q_display = db_mysql_quote(na->nc->display);
+
+ ret = db_mysql_try("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'",
+ q_lastmask, q_lastrname, q_lastquit,
+ (int) na->time_registered, (int) na->last_seen,
+ (int) na->status, q_display, q_nick);
+
+ /* Our previous UPDATE affected no rows, therefore this is a new record */
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED 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)",
+ q_nick, q_lastmask, q_lastrname, q_lastquit,
+ (int) na->time_registered, (int) na->last_seen,
+ (int) na->status, q_display);
+ }
+
+ free(q_nick);
+ free(q_lastmask);
+ free(q_lastrname);
+ free(q_lastquit);
+ free(q_display);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/*
+ * ChanServ Specific Secion
+ */
+
+/*************************************************************************/
+
+/* Save the given ChannelInfo into the database
+ * Also save the access list, levels, akicks, badwords, ttb, and memo's for this channel
+ * Return 1 on success, 0 on failure
+ * These tables are tagged and will be cleaned:
+ * - anope_cs_info
+ * - anope_cs_access
+ * - anope_cs_levels
+ * - anope_cs_akicks
+ * - anope_cs_badwords
+ * - anope_cs_ttb
+ * - anope_ms_info (serv='CHAN')
+ */
+int db_mysql_save_cs_info(ChannelInfo * ci)
+{
+ int ret, res, i;
+ char epass[PASSMAX+15];
+ char *q_name;
+ char *q_founder;
+ char *q_successor;
+ char *q_pass = NULL;
+ char *q_desc;
+ char *q_url;
+ char *q_email;
+ char *q_lasttopic;
+ char *q_lasttopicsetter;
+ char *q_forbidby;
+ char *q_forbidreason;
+ char *q_mlock_key;
+ char *q_mlock_flood;
+ char *q_mlock_redirect;
+ char *q_entrymsg;
+ char *q_botnick;
+ char *q_sender;
+ char *q_text;
+ char *q_accessdisp;
+ char *q_akickdisp;
+ char *q_akickreason;
+ char *q_akickcreator;
+ char *q_badwords;
+
+ q_name = db_mysql_quote(ci->name);
+ if (ci->founder) {
+ q_founder = db_mysql_quote(ci->founder->display);
+ } else {
+ q_founder = db_mysql_quote("");
+ }
+ if (ci->successor) {
+ q_successor = db_mysql_quote(ci->successor->display);
+ } else {
+ q_successor = db_mysql_quote("");
+ }
+ q_desc = db_mysql_quote(ci->desc);
+ q_url = db_mysql_quote(ci->url);
+ q_email = db_mysql_quote(ci->email);
+ q_lasttopic = db_mysql_quote(ci->last_topic);
+ q_lasttopicsetter = db_mysql_quote(ci->last_topic_setter);
+ q_forbidby = db_mysql_quote(ci->forbidby);
+ q_forbidreason = db_mysql_quote(ci->forbidreason);
+ q_mlock_key = db_mysql_quote(ci->mlock_key);
+ q_mlock_flood = db_mysql_quote(ci->mlock_flood);
+ q_mlock_redirect = db_mysql_quote(ci->mlock_redirect);
+ q_entrymsg = db_mysql_quote(ci->entry_message);
+ if (ci->bi) {
+ q_botnick = db_mysql_quote(ci->bi->nick);
+ } else {
+ q_botnick = db_mysql_quote("");
+ }
+
+ /* First secure the pass, then make it MySQL safe.. - Viper */
+ res = db_mysql_secure(epass, ci->founderpass, PASSMAX+15, PASSMAX);
+ if (res < 0)
+ fatal("Unable to encrypt password for MySQL");
+ else if (res)
+ q_pass = db_mysql_quote_buffer(epass, PASSMAX+15);
+ else {
+ q_pass = scalloc(PASSMAX+15,sizeof(char));
+ memcpy(q_pass, epass, PASSMAX+15);
+ }
+
+ /* If it has been made MySQL safe, it still needs the 's.
+ * I know it s an ugly solution, but it works without breaking anything.. - Viper */
+ /* Let's take care of the core itself */
+ if (res)
+ ret = db_mysql_try("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, "
+ " bwcount = %d, capsmin = %d, capspercent = %d, floodlines = %d, floodsecs = %d, repeattimes = %d, active = 1 "
+ "WHERE name = '%s'",
+ q_founder, q_successor, q_pass, q_desc, q_url, q_email,
+ (int) ci->time_registered, (int) ci->last_used,
+ q_lasttopic, q_lasttopicsetter,
+ (int) ci->last_topic_time, (int) ci->flags, q_forbidby,
+ q_forbidreason, (int) ci->bantype,
+ (int) ci->accesscount, (int) ci->akickcount,
+ (int) ci->mlock_on, (int) ci->mlock_off,
+ (int) ci->mlock_limit, q_mlock_key, q_mlock_flood,
+ q_mlock_redirect, q_entrymsg, (int) ci->memos.memomax,
+ q_botnick, (int) ci->botflags, (int) ci->bwcount,
+ (int) ci->capsmin, (int) ci->capspercent,
+ (int) ci->floodlines, (int) ci->floodsecs,
+ (int) ci->repeattimes, q_name);
+ else
+ ret = db_mysql_try("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, "
+ " bwcount = %d, capsmin = %d, capspercent = %d, floodlines = %d, floodsecs = %d, repeattimes = %d, active = 1 "
+ "WHERE name = '%s'",
+ q_founder, q_successor, q_pass, q_desc, q_url, q_email,
+ (int) ci->time_registered, (int) ci->last_used,
+ q_lasttopic, q_lasttopicsetter,
+ (int) ci->last_topic_time, (int) ci->flags, q_forbidby,
+ q_forbidreason, (int) ci->bantype,
+ (int) ci->accesscount, (int) ci->akickcount,
+ (int) ci->mlock_on, (int) ci->mlock_off,
+ (int) ci->mlock_limit, q_mlock_key, q_mlock_flood,
+ q_mlock_redirect, q_entrymsg, (int) ci->memos.memomax,
+ q_botnick, (int) ci->botflags, (int) ci->bwcount,
+ (int) ci->capsmin, (int) ci->capspercent,
+ (int) ci->floodlines, (int) ci->floodsecs,
+ (int) ci->repeattimes, q_name);
+
+ /* Our previous UPDATE affected no rows, therefore this is a new record */
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ if (res)
+ ret = db_mysql_try("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)",
+ q_name, q_founder, q_successor, q_pass, q_desc,
+ q_url, q_email, (int) ci->time_registered,
+ (int) ci->last_used, q_lasttopic,
+ q_lasttopicsetter, (int) ci->last_topic_time,
+ (int) ci->flags, q_forbidby, q_forbidreason,
+ (int) ci->bantype, (int) ci->accesscount,
+ (int) ci->akickcount, (int) ci->mlock_on,
+ (int) ci->mlock_off, (int) ci->mlock_limit,
+ q_mlock_key, q_mlock_flood, q_mlock_redirect,
+ q_entrymsg, q_botnick, (int) ci->botflags,
+ (int) ci->bwcount, (int) ci->capsmin,
+ (int) ci->capspercent, (int) ci->floodlines,
+ (int) ci->floodsecs, (int) ci->repeattimes);
+ else
+ ret = db_mysql_try("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)",
+ q_name, q_founder, q_successor, q_pass, q_desc,
+ q_url, q_email, (int) ci->time_registered,
+ (int) ci->last_used, q_lasttopic,
+ q_lasttopicsetter, (int) ci->last_topic_time,
+ (int) ci->flags, q_forbidby, q_forbidreason,
+ (int) ci->bantype, (int) ci->accesscount,
+ (int) ci->akickcount, (int) ci->mlock_on,
+ (int) ci->mlock_off, (int) ci->mlock_limit,
+ q_mlock_key, q_mlock_flood, q_mlock_redirect,
+ q_entrymsg, q_botnick, (int) ci->botflags,
+ (int) ci->bwcount, (int) ci->capsmin,
+ (int) ci->capspercent, (int) ci->floodlines,
+ (int) ci->floodsecs, (int) ci->repeattimes);
+ }
+
+ /* Memos */
+ for (i = 0; ret && (i < ci->memos.memocount); i++) {
+ q_sender = db_mysql_quote(ci->memos.memos[i].sender);
+ q_text = db_mysql_quote(ci->memos.memos[i].text);
+
+ ret = db_mysql_try("UPDATE anope_ms_info "
+ "SET receiver = '%s', number = %d, flags = %d, time = %d, sender = '%s', text = '%s', active = 1 "
+ "WHERE nm_id = %d AND serv = 'CHAN'",
+ q_name, ci->memos.memos[i].number,
+ ci->memos.memos[i].flags,
+ (int) ci->memos.memos[i].time, q_sender, q_text,
+ ci->memos.memos[i].id);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT INTO anope_ms_info "
+ "(receiver, number,flags, time, sender, text, serv, active) "
+ "VALUES ('%s', %d, %d, %d, '%s', '%s', 'CHAN', 1)",
+ q_name, ci->memos.memos[i].number,
+ ci->memos.memos[i].flags,
+ (int) ci->memos.memos[i].time, q_sender,
+ q_text);
+
+ /* See comment at db_mysql_save_ns_core */
+ if (ret)
+ ci->memos.memos[i].id = mysql_insert_id(mysql);
+ }
+
+ free(q_sender);
+ free(q_text);
+ }
+
+ /* Access */
+ for (i = 0; ret && (i < ci->accesscount); i++) {
+ if (ci->access[i].in_use) {
+ q_accessdisp = db_mysql_quote(ci->access[i].nc->display);
+
+ ret = db_mysql_try("UPDATE anope_cs_access "
+ "SET in_use = %d, level = %d, last_seen = %d, active = 1 "
+ "WHERE channel = '%s' AND display = '%s'",
+ (int) ci->access[i].in_use,
+ (int) ci->access[i].level,
+ (int) ci->access[i].last_seen,
+ q_name, q_accessdisp);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_cs_access "
+ "(channel, display, in_use, level, last_seen, active) "
+ "VALUES ('%s', '%s', %d, %d, %d, 1)",
+ q_name, q_accessdisp,
+ (int) ci->access[i].in_use,
+ (int) ci->access[i].level,
+ (int) ci->access[i].last_seen);
+ }
+
+ free(q_accessdisp);
+ }
+ }
+
+ /* Levels */
+ for (i = 0; ret && (i < CA_SIZE); i++) {
+ ret = db_mysql_try("UPDATE anope_cs_levels "
+ "SET level = %d, active = 1 "
+ "WHERE channel = '%s' AND position = %d",
+ (int) ci->levels[i], q_name, i);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_cs_levels "
+ "(channel, position, level, active) "
+ "VALUES ('%s', %d, %d, 1)",
+ q_name, i, (int) ci->levels[i]);
+ }
+ }
+
+ /* Akicks */
+ for (i = 0; ret && (i < ci->akickcount); i++) {
+ if (ci->akick[i].flags & AK_USED) {
+ if (ci->akick[i].flags & AK_ISNICK)
+ q_akickdisp = db_mysql_quote(ci->akick[i].u.nc->display);
+ else
+ q_akickdisp = db_mysql_quote(ci->akick[i].u.mask);
+
+ q_akickreason = db_mysql_quote(ci->akick[i].reason);
+ q_akickcreator = db_mysql_quote(ci->akick[i].creator);
+ } else {
+ q_akickdisp = "";
+ q_akickreason = "";
+ q_akickcreator = "";
+ }
+
+ ret = db_mysql_try("UPDATE anope_cs_akicks "
+ "SET flags = %d, reason = '%s', creator = '%s', addtime = %d, active = 1 "
+ "WHERE channel = '%s' AND dmask = '%s'",
+ (int) ci->akick[i].flags, q_akickreason,
+ q_akickcreator, (ci->akick[i].flags & AK_USED ?
+ (int) ci->akick[i].addtime : 0),
+ q_name, q_akickdisp);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_cs_akicks "
+ "(channel, dmask, flags, reason, creator, addtime, active) "
+ "VALUES ('%s', '%s', %d, '%s', '%s', %d, 1)",
+ q_name, q_akickdisp, (int) ci->akick[i].flags,
+ q_akickreason, q_akickcreator,
+ (ci->akick[i].flags & AK_USED ?
+ (int) ci->akick[i].addtime : 0));
+ }
+
+ if (ci->akick[i].flags & AK_USED) {
+ free(q_akickdisp);
+ free(q_akickreason);
+ free(q_akickcreator);
+ }
+ }
+
+ /* Bad Words */
+ for (i = 0; ret && (i < ci->bwcount); i++) {
+ if (ci->badwords[i].in_use) {
+ q_badwords = db_mysql_quote(ci->badwords[i].word);
+
+ ret = db_mysql_try("UPDATE anope_cs_badwords "
+ "SET type = %d, active = 1 "
+ "WHERE channel = '%s' AND word = '%s'",
+ (int) ci->badwords[i].type, q_name,
+ q_badwords);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_cs_badwords "
+ "(channel, word, type, active) "
+ "VALUES ('%s', '%s', %d, 1)",
+ q_name, q_badwords,
+ (int) ci->badwords[i].type);
+ }
+
+ free(q_badwords);
+ }
+ }
+
+ /* TTB's */
+ for (i = 0; ret && (i < TTB_SIZE); i++) {
+ ret = db_mysql_try("UPDATE anope_cs_ttb "
+ "SET value = %d, active = 1 "
+ "WHERE channel = '%s' AND ttb_id = %d",
+ ci->ttb[i], q_name, i);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_cs_ttb "
+ "(channel, ttb_id, value, active) "
+ "VALUES ('%s', %d, %d, 1)",
+ q_name, i, ci->ttb[i]);
+ }
+ }
+
+ free(q_name);
+ free(q_founder);
+ free(q_successor);
+ free(q_pass);
+ free(q_desc);
+ free(q_url);
+ free(q_email);
+ free(q_lasttopic);
+ free(q_lasttopicsetter);
+ free(q_mlock_key);
+ free(q_mlock_flood);
+ free(q_mlock_redirect);
+ free(q_entrymsg);
+ free(q_botnick);
+ free(q_forbidby);
+ free(q_forbidreason);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+
+/*
+ * OperServ Specific Section
+ */
+
+/*************************************************************************/
+
+/* Save the OperServ database into MySQL
+ * Return 1 on success, 0 on failure
+ * These tables are tagged and will be cleaned:
+ * - anope_os_akills
+ * - anope_os_sglines
+ * - anope_os_sqlines
+ * - anope_os_szlines
+ * These tables are emptied:
+ * - anope_os_core
+ */
+
+int db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime,
+ SList * ak, SList * sgl, SList * sql, SList * szl)
+{
+ int ret;
+ int i;
+ Akill *akl;
+ SXLine *sl;
+ char *q_user;
+ char *q_host;
+ char *q_mask;
+ char *q_by;
+ char *q_reason;
+
+
+ /* First save the core info */
+ ret = db_mysql_try("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);
+
+ /* Next save all AKILLs */
+ for (i = 0; ret && (i < ak->count); i++) {
+ akl = ak->list[i];
+ q_user = db_mysql_quote(akl->user);
+ q_host = db_mysql_quote(akl->host);
+ q_by = db_mysql_quote(akl->by);
+ q_reason = db_mysql_quote(akl->reason);
+
+ ret = db_mysql_try("UPDATE anope_os_akills "
+ "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
+ "WHERE user = '%s' AND host = '%s'",
+ q_by, q_reason, (int) akl->seton,
+ (int) akl->expires, q_user, q_host);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_akills "
+ "(user, host, xby, reason, seton, expire, active) "
+ "VALUES ('%s', '%s', '%s', '%s', %d, %d, 1)",
+ q_user, q_host, q_by, q_reason,
+ (int) akl->seton, (int) akl->expires);
+ }
+
+ free(q_user);
+ free(q_host);
+ free(q_by);
+ free(q_reason);
+ }
+
+ /* Time to save the SGLINEs */
+ for (i = 0; ret && (i < sgl->count); i++) {
+ sl = sgl->list[i];
+ q_mask = db_mysql_quote(sl->mask);
+ q_by = db_mysql_quote(sl->by);
+ q_reason = db_mysql_quote(sl->reason);
+
+ ret = db_mysql_try("UPDATE anope_os_sglines "
+ "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
+ "WHERE mask = '%s'",
+ q_by, q_reason, (int) sl->seton, (int) sl->expires,
+ q_mask);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_sglines "
+ "(mask, xby, reason, seton, expire, active) "
+ "VALUES ('%s', '%s', '%s', %d, %d, 1)",
+ q_mask, q_by, q_reason, (int) sl->seton,
+ (int) sl->expires);
+ }
+
+ free(q_mask);
+ free(q_by);
+ free(q_reason);
+ }
+
+ /* Save the SQLINEs */
+ for (i = 0; ret && (i < sql->count); i++) {
+ sl = sql->list[i];
+
+ q_mask = db_mysql_quote(sl->mask);
+ q_by = db_mysql_quote(sl->by);
+ q_reason = db_mysql_quote(sl->reason);
+
+ ret = db_mysql_try("UPDATE anope_os_sqlines "
+ "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
+ "WHERE mask = '%s'",
+ q_by, q_reason, (int) sl->seton, (int) sl->expires,
+ q_mask);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_sqlines "
+ "(mask, xby, reason, seton, expire, active) "
+ "VALUES ('%s', '%s', '%s', %d, %d, 1)",
+ q_mask, q_by, q_reason, (int) sl->seton,
+ (int) sl->expires);
+ }
+
+ free(q_mask);
+ free(q_by);
+ free(q_reason);
+ }
+
+ /* Now save the SZLINEs */
+ for (i = 0; ret && (i < szl->count); i++) {
+ sl = szl->list[i];
+
+ q_mask = db_mysql_quote(sl->mask);
+ q_by = db_mysql_quote(sl->by);
+ q_reason = db_mysql_quote(sl->reason);
+
+ ret = db_mysql_try("UPDATE anope_os_szlines "
+ "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
+ "WHERE mask = '%s'",
+ q_by, q_reason, (int) sl->seton, (int) sl->expires,
+ q_mask);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_szlines "
+ "(mask, xby, reason, seton, expire, active) "
+ "VALUES ('%s', '%s', '%s', %d, %d, 1)",
+ q_mask, q_by, q_reason, (int) sl->seton,
+ (int) sl->expires);
+ }
+
+ free(q_mask);
+ free(q_by);
+ free(q_reason);
+ }
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/* Save the given NewsItem
+ * These tables are tagged and will be cleaned:
+ * - anope_os_news
+ */
+int db_mysql_save_news(NewsItem * ni)
+{
+ int ret;
+ char *q_text;
+ char *q_who;
+
+ q_text = db_mysql_quote(ni->text);
+ q_who = db_mysql_quote(ni->who);
+
+ ret = db_mysql_try("UPDATE anope_os_news "
+ "SET ntext = '%s', who = '%s', active = 1 "
+ "WHERE type = %d AND num = %d AND `time` = %d",
+ q_text, q_who, ni->type, ni->num, (int) ni->time);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_news "
+ "(type, num, ntext, who, `time`, active) "
+ "VALUES (%d, %d, '%s', '%s', %d, 1)",
+ ni->type, ni->num, q_text, q_who, (int) ni->time);
+ }
+
+ free(q_text);
+ free(q_who);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/* Save the given Exception
+ * These tables are tagged and will be cleaned:
+ * - anope_os_exceptions
+ */
+
+int db_mysql_save_exceptions(Exception * e)
+{
+ int ret;
+ char *q_mask;
+ char *q_who;
+ char *q_reason;
+
+ q_mask = db_mysql_quote(e->mask);
+ q_who = db_mysql_quote(e->who);
+ q_reason = db_mysql_quote(e->reason);
+
+ ret = db_mysql_try("UPDATE anope_os_exceptions "
+ "SET lim = %d, who = '%s', reason = '%s', `time` = %d, expires = %d, active = 1 "
+ "WHERE mask = '%s'",
+ e->limit, q_who, q_reason, (int) e->time,
+ (int) e->expires, q_mask);
+
+ if (ret && (mysql_affected_rows(mysql)) == 0) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_os_exceptions "
+ "(mask, lim, who, reason, `time`, expires, active) "
+ "VALUES ('%s', %d, '%s', '%s', %d, %d, 1)",
+ q_mask, e->limit, q_who, q_reason, (int) e->time,
+ (int) e->expires);
+ }
+
+ free(q_mask);
+ free(q_who);
+ free(q_reason);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+
+/*
+ * HostServ Specific Section
+ */
+
+/*************************************************************************/
+
+/* Save the given HostCore
+ * These tables are tagged and will be cleaned:
+ * - anope_hs_core
+ */
+
+int db_mysql_save_hs_core(HostCore * hc)
+{
+ int ret;
+ char *q_nick;
+ char *q_ident;
+ char *q_host;
+ char *q_creator;
+
+ q_nick = db_mysql_quote(hc->nick);
+ q_ident = db_mysql_quote(hc->vIdent);
+ q_host = db_mysql_quote(hc->vHost);
+ q_creator = db_mysql_quote(hc->creator);
+
+ ret = db_mysql_try("UPDATE anope_hs_core "
+ "SET vident = '%s', vhost = '%s', creator = '%s', `time` = %d, active = 1 "
+ "WHERE nick = '%s'",
+ q_ident, q_host, q_creator, (int) hc->time, q_nick);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_hs_core "
+ "(nick, vident, vhost, creator, `time`, active) "
+ "VALUES ('%s', '%s', '%s', '%s', %d, 1)",
+ q_nick, q_ident, q_host, q_creator,
+ (int) hc->time);
+ }
+
+ free(q_nick);
+ free(q_ident);
+ free(q_host);
+ free(q_creator);
+
+ return ret;
+}
+
+/*************************************************************************/
+
+/*
+ * BotServ Specific Section
+ */
+
+/*************************************************************************/
+
+int db_mysql_save_bs_core(BotInfo * bi)
+{
+ int ret;
+ char *q_nick;
+ char *q_user;
+ char *q_host;
+ char *q_real;
+
+ q_nick = db_mysql_quote(bi->nick);
+ q_user = db_mysql_quote(bi->user);
+ q_host = db_mysql_quote(bi->host);
+ q_real = db_mysql_quote(bi->real);
+
+ ret = db_mysql_try("UPDATE anope_bs_core "
+ "SET user = '%s', host = '%s', rname = '%s', flags = %d, created = %d, chancount = %d, active = 1 "
+ "WHERE nick = '%s'",
+ q_user, q_host, q_real, bi->flags, (int) bi->created,
+ bi->chancount, q_nick);
+
+ if (ret && (mysql_affected_rows(mysql) == 0)) {
+ ret = db_mysql_try("INSERT DELAYED INTO anope_bs_core "
+ "(nick, user, host, rname, flags, created, chancount, active) "
+ "VALUES ('%s', '%s', '%s', '%s', %d, %d, %d, 1)",
+ q_nick, q_user, q_host, q_real, bi->flags,
+ (int) bi->created, bi->chancount);
+ }
+
+ free(q_nick);
+ free(q_user);
+ free(q_host);
+ free(q_real);
+
+ return ret;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* Some loading code! */
+
+/*************************************************************************/
+/*************************************************************************/
+
+int db_mysql_load_bs_dbase(void)
+{
+ int ret;
+ BotInfo *bi;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT nick, user, host, rname, flags, created, chancount "
+ "FROM anope_bs_core "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+
+ 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 = strtol(mysql_row[4], (char **) NULL, 10);
+ bi->created = strtol(mysql_row[5], (char **) NULL, 10);
+ bi->chancount = strtol(mysql_row[6], (char **) NULL, 10);
+ }
+
+ mysql_free_result(mysql_res);
+
+ return 1;
+}
+
+int db_mysql_load_hs_dbase(void)
+{
+ int ret;
+ int32 time;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT nick, vident, vhost, creator, `time` "
+ "FROM anope_hs_core "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ time = strtol(mysql_row[4], (char **) NULL, 10);
+ addHostCore(mysql_row[0], mysql_row[1], mysql_row[2], mysql_row[3],
+ time);
+ }
+
+ mysql_free_result(mysql_res);
+
+ return 1;
+}
+
+int db_mysql_load_news(void)
+{
+ int ret;
+ int i;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT type, num, ntext, who, `time` "
+ "FROM anope_os_news "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_store_result(mysql);
+
+ nnews = mysql_num_rows(mysql_res);
+ if (nnews < 8) /* 2^3 */
+ news_size = 16; /* 2^4 */
+ else if (nnews >= 16384) /* 2^14 */
+ news_size = 32767; /* 2^15 - 1 */
+ else
+ news_size = 2 * nnews;
+
+ news = scalloc(news_size, sizeof(*news));
+
+ i = 0;
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ news[i].type = strtol(mysql_row[0], (char **) NULL, 10);
+ news[i].num = strtol(mysql_row[1], (char **) NULL, 10);
+ news[i].text = sstrdup(mysql_row[2]);
+ snprintf(news[i].who, NICKMAX, "%s", mysql_row[3]);
+ news[i].time = strtol(mysql_row[4], (char **) NULL, 10);
+ i++;
+ }
+
+ mysql_free_result(mysql_res);
+
+ return 1;
+}
+
+int db_mysql_load_exceptions(void)
+{
+ int ret;
+ int i;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT mask, lim, who, reason, `time`, expires "
+ "FROM anope_os_exceptions "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_store_result(mysql);
+ nexceptions = mysql_num_rows(mysql_res);
+ exceptions = scalloc(nexceptions, sizeof(Exception));
+
+ i = 0;
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ exceptions[i].mask = sstrdup(mysql_row[0]);
+ exceptions[i].limit = strtol(mysql_row[1], (char **) NULL, 10);
+ snprintf(exceptions[i].who, NICKMAX, "%s", mysql_row[2]);
+ exceptions[i].reason = sstrdup(mysql_row[3]);
+ exceptions[i].time = strtol(mysql_row[4], (char **) NULL, 10);
+ exceptions[i].expires = strtol(mysql_row[5], (char **) NULL, 10);
+ i++;
+ }
+
+ mysql_free_result(mysql_res);
+
+ return 1;
+}
+
+int db_mysql_load_os_dbase(void)
+{
+ int ret;
+ Akill *ak;
+ SXLine *sl;
+ int akc, sglc, sqlc, szlc;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT maxusercnt, maxusertime, akills_count, sglines_count, sqlines_count, szlines_count "
+ "FROM anope_os_core");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+
+ if ((mysql_row = mysql_fetch_row(mysql_res))) {
+ maxusercnt = strtol(mysql_row[0], (char **) NULL, 10);
+ maxusertime = strtol(mysql_row[1], (char **) NULL, 10);
+ /* I'm not too happy with the idea of storing thse counts in a field
+ * instead of just using mysql_num_rows on the actual tables when
+ * filling the data. For now this will do, but it's bound to give
+ * problems sooner or later... (it probably does if you are looking
+ * at this) -GD
+ */
+ akc = strtol(mysql_row[2], (char **) NULL, 10);
+ sglc = strtol(mysql_row[3], (char **) NULL, 10);
+ sqlc = strtol(mysql_row[4], (char **) NULL, 10);
+ szlc = strtol(mysql_row[5], (char **) NULL, 10);
+ } else {
+ maxusercnt = 0;
+ maxusertime = time(NULL);
+ akc = 0;
+ sglc = 0;
+ sqlc = 0;
+ szlc = 0;
+ }
+
+ mysql_free_result(mysql_res);
+
+
+ /* Load the AKILLs */
+
+ ret = db_mysql_try("SELECT user, host, xby, reason, seton, expire "
+ "FROM anope_os_akills "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+ slist_setcapacity(&akills, akc);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ ak = scalloc(1, sizeof(Akill));
+ 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 = strtol(mysql_row[4], (char **) NULL, 10);
+ ak->expires = strtol(mysql_row[5], (char **) NULL, 10);
+ slist_add(&akills, ak);
+ }
+
+ mysql_free_result(mysql_res);
+
+
+ /* Load the SGLINEs */
+
+ ret = db_mysql_try("SELECT mask, xby, reason, seton, expire "
+ "FROM anope_os_sglines "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+ slist_setcapacity(&sglines, sglc);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ sl = scalloc(1, sizeof(SXLine));
+ sl->mask = sstrdup(mysql_row[0]);
+ sl->by = sstrdup(mysql_row[1]);
+ sl->reason = sstrdup(mysql_row[2]);
+ sl->seton = strtol(mysql_row[3], (char **) NULL, 10);
+ sl->expires = strtol(mysql_row[4], (char **) NULL, 10);
+ slist_add(&sglines, sl);
+ }
+
+ mysql_free_result(mysql_res);
+
+
+ /* Load the SQLINEs */
+
+ ret = db_mysql_try("SELECT mask, xby, reason, seton, expire "
+ "FROM anope_os_sqlines "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+ slist_setcapacity(&sqlines, sqlc);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ sl = scalloc(1, sizeof(SXLine));
+ sl->mask = sstrdup(mysql_row[0]);
+ sl->by = sstrdup(mysql_row[1]);
+ sl->reason = sstrdup(mysql_row[2]);
+ sl->seton = strtol(mysql_row[3], (char **) NULL, 10);
+ sl->expires = strtol(mysql_row[4], (char **) NULL, 10);
+ slist_add(&sqlines, sl);
+ }
+
+ mysql_free_result(mysql_res);
+
+
+ /* Load the SZLINEs */
+
+ ret = db_mysql_try("SELECT mask, xby, reason, seton, expire "
+ "FROM anope_os_szlines "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+ slist_setcapacity(&szlines, szlc);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ sl = scalloc(1, sizeof(SXLine));
+ sl->mask = sstrdup(mysql_row[0]);
+ sl->by = sstrdup(mysql_row[1]);
+ sl->reason = sstrdup(mysql_row[2]);
+ sl->seton = strtol(mysql_row[3], (char **) NULL, 10);
+ sl->expires = strtol(mysql_row[4], (char **) NULL, 10);
+ slist_add(&szlines, sl);
+ }
+
+ mysql_free_result(mysql_res);
+
+ return 1;
+}
+
+int db_mysql_load_cs_dbase(void)
+{
+ int ret;
+ char *q_name;
+ ChannelInfo *ci;
+ int i;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ unsigned long *lengths;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("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, bwcount, capsmin, capspercent, floodlines, "
+ " floodsecs, repeattimes "
+ "FROM anope_cs_info "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ /* I'd really like to use mysql_use_result here, but it'd tie up with
+ * all the queries being run inside each iteration... -GD
+ */
+ mysql_res = mysql_store_result(mysql);
+
+ while (ret && (mysql_row = mysql_fetch_row(mysql_res))) {
+ /* We need to get the length of the password.. - Viper */
+ lengths = mysql_fetch_lengths(mysql_res);
+ ci = scalloc(1, sizeof(ChannelInfo));
+
+ /* Name, founder, successor, password */
+ snprintf(ci->name, CHANMAX, "%s", mysql_row[0]);
+ ci->founder = findcore(mysql_row[1]);
+ if (mysql_row[2] && *(mysql_row[2]))
+ ci->successor = findcore(mysql_row[2]);
+ else
+ ci->successor = NULL;
+
+ /* Copy the password from what we got back from the DB and
+ * keep in mind that lengths may vary. We should never
+ * use more than we have. - Viper */
+ memset(ci->founderpass, 0, PASSMAX);
+ if (lengths[3] >= PASSMAX)
+ memcpy(ci->founderpass, mysql_row[3], PASSMAX - 1);
+ else
+ memcpy(ci->founderpass, mysql_row[3], lengths[3]);
+
+ /* Description, URL, email -- scalloc() initializes to 0/NULL */
+ ci->desc = sstrdup(mysql_row[4]);
+ if (mysql_row[5] && *(mysql_row[5]))
+ ci->url = sstrdup(mysql_row[5]);
+ if (mysql_row[6] && *(mysql_row[6]))
+ ci->email = sstrdup(mysql_row[6]);
+
+ /* Time registered, last used, last topic, last topic setter + time */
+ ci->time_registered = strtol(mysql_row[7], (char **) NULL, 10);
+ ci->last_used = strtol(mysql_row[8], (char **) NULL, 10);
+ if (mysql_row[9] && *(mysql_row[9])) {
+ ci->last_topic = sstrdup(mysql_row[9]);
+ snprintf(ci->last_topic_setter, NICKMAX, "%s", mysql_row[10]);
+ ci->last_topic_time = strtol(mysql_row[11], (char **) NULL, 10);
+ }
+
+ /* Flags, forbidden by, forbid reason, bantype
+ * NOTE: CI_INHABIT will be disabled in flags!!
+ */
+ ci->flags =
+ strtol(mysql_row[12], (char **) NULL, 10) & ~CI_INHABIT;
+
+ if (mysql_row[13] && *(mysql_row[13])) {
+ ci->forbidby = sstrdup(mysql_row[13]);
+ if (mysql_row[14] && *(mysql_row[14]))
+ ci->forbidreason = sstrdup(mysql_row[14]);
+ }
+
+ ci->bantype = strtol(mysql_row[15], (char **) NULL, 10);
+
+ /* Accesscount, akickcount */
+ ci->accesscount = strtol(mysql_row[16], (char **) NULL, 10);
+ ci->akickcount = strtol(mysql_row[17], (char **) NULL, 10);
+
+ /* Mlock: on, off, limit, key, flood, redirect */
+ ci->mlock_on = strtol(mysql_row[18], (char **) NULL, 10);
+ ci->mlock_off = strtol(mysql_row[19], (char **) NULL, 10);
+ ci->mlock_limit = strtol(mysql_row[20], (char **) NULL, 10);
+ if (mysql_row[21] && *(mysql_row[21])) {
+ ci->mlock_key = sstrdup(mysql_row[21]);
+ if (mysql_row[22] && *(mysql_row[22])) {
+ ci->mlock_flood = sstrdup(mysql_row[22]);
+ }
+ if (mysql_row[23] && *(mysql_row[23])) {
+ ci->mlock_redirect = sstrdup(mysql_row[23]);
+ }
+ }
+
+ /* MemoMax, entrymessage, botinfo, botflags, badwordcount */
+ ci->memos.memomax = strtol(mysql_row[25], (char **) NULL, 10);
+ if (mysql_row[24] && *(mysql_row[24]))
+ ci->entry_message = sstrdup(mysql_row[24]);
+ ci->bi = findbot(mysql_row[26]);
+ ci->botflags = strtol(mysql_row[27], (char **) NULL, 10);
+ ci->bwcount = strtol(mysql_row[28], (char **) NULL, 10);
+
+ /* Capsmin, capspercent, floodlines, floodsecs, repeattimes */
+ ci->capsmin = strtol(mysql_row[29], (char **) NULL, 10);
+ ci->capspercent = strtol(mysql_row[30], (char **) NULL, 10);
+ ci->floodlines = strtol(mysql_row[31], (char **) NULL, 10);
+ ci->floodsecs = strtol(mysql_row[32], (char **) NULL, 10);
+ ci->repeattimes = strtol(mysql_row[33], (char **) NULL, 10);
+
+
+ /* Get info from other tables; we'll need the channel name */
+ q_name = db_mysql_quote(ci->name);
+
+ /* Get the LEVELS list */
+ ret = db_mysql_try("SELECT position, level "
+ "FROM anope_cs_levels "
+ "WHERE channel = '%s' AND active = 1",
+ q_name);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+ ci->levels = scalloc(CA_SIZE, sizeof(*ci->levels));
+ reset_levels(ci);
+
+ while ((row = mysql_fetch_row(res))) {
+ i = strtol(row[0], (char **) NULL, 10);
+ ci->levels[i] = strtol(row[1], (char **) NULL, 10);
+ }
+
+ mysql_free_result(res);
+ }
+
+ /* Get the channel ACCESS list */
+ if (ret && (ci->accesscount > 0)) {
+ ci->access = scalloc(ci->accesscount, sizeof(ChanAccess));
+
+ ret = db_mysql_try("SELECT level, display, last_seen "
+ "FROM anope_cs_access "
+ "WHERE channel = '%s' AND in_use = 1 AND active = 1",
+ q_name);
+
+ if (ret) {
+ res = mysql_store_result(mysql);
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ ci->access[i].in_use = 1;
+ ci->access[i].level = strtol(row[0], (char **) NULL, 10);
+ ci->access[i].nc = findcore(row[1]);
+ if (!(ci->access[i].nc))
+ ci->access[i].in_use = 0;
+ ci->access[i].last_seen =
+ strtol(row[2], (char **) NULL, 10);
+ i++;
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* Get the channel AKICK list */
+ if (ret && (ci->akickcount > 0)) {
+ ci->akick = scalloc(ci->akickcount, sizeof(AutoKick));
+
+ ret = db_mysql_try("SELECT flags, dmask, reason, creator, addtime "
+ "FROM anope_cs_akicks "
+ "WHERE channel = '%s' AND active = 1 AND (flags & %d) <> 0",
+ q_name, AK_USED);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ ci->akick[i].flags = strtol(row[0], (char **) NULL, 10);
+ if (ci->akick[i].flags & AK_ISNICK) {
+ ci->akick[i].u.nc = findcore(row[1]);
+ if (!(ci->akick[i].u.nc))
+ ci->akick[i].flags &= ~AK_USED;
+ } else {
+ ci->akick[i].u.mask = sstrdup(row[1]);
+ }
+ if (row[2] && *(row[2])) {
+ ci->akick[i].reason = sstrdup(row[2]);
+ }
+ ci->akick[i].creator = sstrdup(row[3]);
+ ci->akick[i].addtime = strtol(row[4], (char **) NULL, 10);
+ i++;
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ if (ret) {
+ /* Get the channel memos */
+ ret = db_mysql_try("SELECT nm_id, number, flags, time, sender, text "
+ "FROM anope_ms_info "
+ "WHERE receiver = '%s' AND serv = 'CHAN' AND active = 1",
+ q_name);
+
+ if (ret) {
+ res = mysql_store_result(mysql);
+ ci->memos.memocount = mysql_num_rows(res);
+
+ if (ci->memos.memocount > 0) {
+ Memo *memos;
+
+ memos = scalloc(ci->memos.memocount, sizeof(Memo));
+ ci->memos.memos = memos;
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ memos[i].id = strtol(row[0], (char **) NULL, 10);
+ memos[i].number = strtol(row[1], (char **) NULL, 10);
+ memos[i].flags = strtol(row[2], (char **) NULL, 10);
+ memos[i].time = strtol(row[3], (char **) NULL, 10);
+ snprintf(memos[i].sender, NICKMAX, "%s", row[4]);
+ memos[i].text = sstrdup(row[5]);
+ i++;
+ }
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* Get the TTB data */
+ if (ret) {
+ ci->ttb = scalloc(TTB_SIZE, sizeof(*ci->ttb));
+
+ ret = db_mysql_try("SELECT ttb_id, value "
+ "FROM anope_cs_ttb "
+ "WHERE channel = '%s' AND active = 1",
+ q_name);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+
+ while ((row = mysql_fetch_row(res))) {
+ i = strtol(row[0], (char **) NULL, 10);
+ /* Should we do a sanity check on the value of i? -GD */
+ ci->ttb[i] = strtol(row[1], (char **) NULL, 10);
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* Get the badwords */
+ if (ret && (ci->bwcount > 0)) {
+ ci->badwords = scalloc(ci->bwcount, sizeof(BadWord));
+
+ ret = db_mysql_try("SELECT word, type "
+ "FROM anope_cs_badwords "
+ "WHERE channel = '%s' AND active = 1",
+ q_name);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ ci->badwords[i].in_use = 1;
+ ci->badwords[i].word = sstrdup(row[0]);
+ ci->badwords[i].type = strtol(row[1], (char **) NULL, 10);
+ i++;
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* YAY! all done; free q_name and insert the channel */
+ free(q_name);
+ alpha_insert_chan(ci);
+ }
+
+ mysql_free_result(mysql_res);
+
+ /* Check to be sure that all channels still have a founder. If not,
+ * delete them. This code seems to be required in the old mysql code
+ * so i'll leave it in just to be sure. I also wonder why they didn't
+ * do that check up above immediately when it was known there was no
+ * founder... -GD
+ */
+ for (i = 0; i < 256; i++) {
+ ChannelInfo *next;
+ for (ci = chanlists[i]; 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);
+ }
+ }
+ }
+
+ return ret;
+}
+
+int db_mysql_load_ns_req_dbase(void)
+{
+ int ret;
+ NickRequest *nr;
+ unsigned long *lengths;
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT nick, passcode, password, email, requested "
+ "FROM anope_ns_request "
+ "WHERE active = 1");
+
+ if (ret) {
+ mysql_res = mysql_use_result(mysql);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ /* We need to get the length of the password.. - Viper */
+ lengths = mysql_fetch_lengths(mysql_res);
+ nr = scalloc(1, sizeof(NickRequest));
+
+ nr->nick = sstrdup(mysql_row[0]);
+ nr->passcode = sstrdup(mysql_row[1]);
+ nr->email = sstrdup(mysql_row[3]);
+ nr->requested = strtol(mysql_row[4], (char **) NULL, 10);
+
+ /* Copy the password from what we got back from the DB and
+ * keep in mind that lengths may vary. We should never
+ * use more than we have. - Viper */
+ memset(nr->password, 0, PASSMAX);
+ if (lengths[2] >= PASSMAX)
+ memcpy(nr->password, mysql_row[2], PASSMAX - 1);
+ else
+ memcpy(nr->password, mysql_row[2], lengths[2]);
+
+
+ insert_requestnick(nr);
+ }
+
+ mysql_free_result(mysql_res);
+ }
+
+ return ret;
+}
+
+int db_mysql_load_ns_dbase(void)
+{
+ int ret;
+ char *q_display;
+ NickCore *nc;
+ NickAlias *na;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int i;
+ unsigned long *lengths;
+
+
+ if (!do_mysql)
+ return 0;
+
+ ret = db_mysql_try("SELECT display, pass, email, icq, url, flags, language, accesscount, memocount, memomax, channelcount, channelmax, greet "
+ "FROM anope_ns_core "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ /* I'd really like to use mysql_use_result here, but it'd tie up with
+ * all the queries being run inside each iteration... -GD
+ */
+ mysql_res = mysql_store_result(mysql);
+
+ while (ret && (mysql_row = mysql_fetch_row(mysql_res))) {
+ /* We need to get the length of the password.. - Viper */
+ lengths = mysql_fetch_lengths(mysql_res);
+
+ nc = scalloc(1, sizeof(NickCore));
+
+ /* Display, password, email, ICQ, URL, flags */
+ nc->display = sstrdup(mysql_row[0]);
+ if (mysql_row[2] && *(mysql_row[2])) {
+ nc->email = sstrdup(mysql_row[2]);
+ }
+ nc->icq = strtol(mysql_row[3], (char **) NULL, 10);
+ if (mysql_row[4] && *(mysql_row[4])) {
+ nc->url = sstrdup(mysql_row[4]);
+ }
+ nc->flags = strtol(mysql_row[5], (char **) NULL, 10);
+
+ /* Copy the password from what we got back from the DB and
+ * keep in mind that lengths may vary. We should never
+ * use more than we have. - Viper */
+ memset(nc->pass, 0, PASSMAX);
+ if (lengths[1] >= PASSMAX)
+ memcpy(nc->pass, mysql_row[1], PASSMAX - 1);
+ else
+ memcpy(nc->pass, mysql_row[1], lengths[1]);
+
+ /* Language, accesscount, memocount, memomax */
+ nc->language = strtol(mysql_row[6], (char **) NULL, 10);
+ nc->accesscount = strtol(mysql_row[7], (char **) NULL, 10);
+ nc->memos.memocount = strtol(mysql_row[8], (char **) NULL, 10);
+ nc->memos.memomax = strtol(mysql_row[9], (char **) NULL, 10);
+
+ /* Channelcount, channelmax, greet */
+ nc->channelcount = strtol(mysql_row[10], (char **) NULL, 10);
+ nc->channelmax = strtol(mysql_row[11], (char **) NULL, 10);
+ if (mysql_row[12] && *(mysql_row[12]))
+ nc->greet = sstrdup(mysql_row[12]);
+
+ /* Don't allow KILL_IMMED if the config doesn't allow it */
+ if (!NSAllowKillImmed)
+ nc->flags &= ~NI_KILL_IMMED;
+
+ /* Check if the current user is important enough to be added to
+ * services admin or services oper lists
+ */
+ if (nc->flags & NI_SERVICES_ADMIN)
+ slist_add(&servadmins, nc);
+ if (nc->flags & NI_SERVICES_OPER)
+ slist_add(&servopers, nc);
+
+ /* Unset the SERVICES_ROOT flag; we will set it again later if this
+ * user is really a services root (checked per NickAlias) -GD
+ */
+ nc->flags &= ~NI_SERVICES_ROOT;
+
+ /* Get info from other tables; we'll need the display */
+ q_display = db_mysql_quote(nc->display);
+
+ /* Fill the accesslist */
+ if (ret && (nc->accesscount > 0)) {
+ nc->access = scalloc(nc->accesscount, sizeof(char *));
+
+ ret = db_mysql_try("SELECT access "
+ "FROM anope_ns_access "
+ "WHERE display = '%s' AND active = 1",
+ q_display);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ if (row[0] && *(row[0])) {
+ nc->access[i] = sstrdup(row[0]);
+ i++;
+ }
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* Load the memos */
+ if (ret && (nc->memos.memocount > 0)) {
+ nc->memos.memos = scalloc(nc->memos.memocount, sizeof(Memo));
+
+ ret = db_mysql_try("SELECT nm_id, number, flags, time, sender, text "
+ "FROM anope_ms_info "
+ "WHERE receiver = '%s' AND active = 1 AND serv = 'NICK' "
+ "ORDER BY number ASC",
+ q_display);
+
+ if (ret) {
+ res = mysql_use_result(mysql);
+
+ i = 0;
+ while ((row = mysql_fetch_row(res))) {
+ nc->memos.memos[i].id = strtol(row[0], (char **) NULL, 10);
+ nc->memos.memos[i].number = strtol(row[1], (char **) NULL, 10);
+ nc->memos.memos[i].flags = strtol(row[2], (char **) NULL, 10);
+ nc->memos.memos[i].time = strtol(row[3], (char **) NULL, 10);
+ snprintf(nc->memos.memos[i].sender, NICKMAX, "%s", row[4]);
+ nc->memos.memos[i].text = sstrdup(row[5]);
+
+ i++;
+ }
+
+ mysql_free_result(res);
+ }
+ }
+
+ /* Done with the core; insert it */
+ insert_core(nc);
+ }
+
+ mysql_free_result(mysql_res);
+
+ if (!ret)
+ return 0;
+
+ /* Load the nickaliases */
+ ret = db_mysql_try("SELECT nick, display, time_registered, last_seen, status, last_usermask, last_realname, last_quit "
+ "FROM anope_ns_alias "
+ "WHERE active = 1");
+
+ if (!ret)
+ return 0;
+
+ mysql_res = mysql_use_result(mysql);
+
+ while ((mysql_row = mysql_fetch_row(mysql_res))) {
+ /* First make sure this NickAlias has a NickCore; else we don't even
+ * bother adding it to the aliases at all...
+ */
+ NickCore *nc;
+
+ if (!(nc = findcore(mysql_row[1])))
+ continue;
+
+ na = scalloc(1, sizeof(NickAlias));
+
+ /* nick, time_registered, last_seen, status
+ * NOTE: remove NS_TEMPORARY from status on load
+ */
+ na->nick = sstrdup(mysql_row[0]);
+ na->nc = nc;
+ na->time_registered = strtol(mysql_row[2], (char **) NULL, 10);
+ na->last_seen = strtol(mysql_row[3], (char **) NULL, 10);
+ na->status =
+ strtol(mysql_row[4], (char **) NULL, 10) & ~NS_TEMPORARY;
+
+ /* last_usermask, last_realname, last_quit */
+ na->last_usermask = sstrdup(mysql_row[5]);
+ na->last_realname = sstrdup(mysql_row[6]);
+
+ if (mysql_row[7] && *(mysql_row[7])) {
+ na->last_quit = sstrdup(mysql_row[7]);
+ }
+
+ /* Assign to the nickcore aliases */
+ slist_add(&na->nc->aliases, na);
+
+ /* Check if this user is a services root */
+ for (i = 0; i < RootNumber; i++) {
+ if (stricmp(ServicesRoots[i], na->nick) == 0)
+ na->nc->flags |= NI_SERVICES_ROOT;
+ }
+
+ /* Last, but not least: insert the alias! */
+ alpha_insert_alias(na);
+ }
+
+ mysql_free_result(mysql_res);
+
+ return ret;
+}
+
+/* get random mysql number for the generator */
+unsigned int mysql_rand(void)
+{
+ unsigned int num = 0;
+
+ if (!do_mysql)
+ return 0;
+
+ db_mysql_try("SELECT RAND()");
+
+ mysql_res = mysql_store_result(mysql);
+
+ if (!(mysql_row = mysql_fetch_row(mysql_res))) {
+ mysql_free_result(mysql_res);
+ return 0;
+ }
+
+ num = UserKey3 * strtol(mysql_row[0], (char **) NULL, 10);
+
+ mysql_free_result(mysql_res);
+
+ return num;
+}