mysql.c

Go to the documentation of this file.
00001 
00002 /* MySQL functions.
00003  *
00004  * (C) 2003-2007 Anope Team
00005  * Contact us at info@anope.org
00006  *
00007  * Please read COPYING and README for further details.
00008  *
00009  * Based on the original code of Epona by Lara.
00010  * Based on the original code of Services by Andy Church. 
00011  * 
00012  * $Id: mysql.c 1272 2007-08-27 17:09:18Z drstein $ 
00013  *
00014  */
00015 #include "services.h"
00016 
00017 /*************************************************************************/
00018 
00019 /* Database Global Variables */
00020 MYSQL *mysql;                   /* MySQL Handler */
00021 MYSQL_RES *mysql_res;           /* MySQL Result  */
00022 MYSQL_FIELD *mysql_fields;      /* MySQL Fields  */
00023 MYSQL_ROW mysql_row;            /* MySQL Row     */
00024 
00025 int mysql_is_connected = 0;     /* Are we currently connected? */
00026 
00027 /*************************************************************************/
00028 
00029 /* Throw a mysql error into the logs. If severity is MYSQL_ERROR, we
00030  * also exit Anope...
00031  */
00032 void db_mysql_error(int severity, char *msg)
00033 {
00034     static char buf[512];
00035 
00036     if (mysql_error(mysql)) {
00037         snprintf(buf, sizeof(buf), "MySQL %s %s: %s", msg,
00038                  severity == MYSQL_WARNING ? "warning" : "error",
00039                  mysql_error(mysql));
00040     } else {
00041         snprintf(buf, sizeof(buf), "MySQL %s %s", msg,
00042                  severity == MYSQL_WARNING ? "warning" : "error");
00043     }
00044 
00045     log_perror(buf);
00046 
00047     if (severity == MYSQL_ERROR) {
00048         log_perror("MySQL FATAL error... aborting.");
00049         exit(0);
00050     }
00051 
00052 }
00053 
00054 /*************************************************************************/
00055 
00056 /* Initialize the MySQL code */
00057 int db_mysql_init()
00058 {
00059 
00060     /* If the host is not defined, assume we don't want MySQL */
00061     if (!MysqlHost) {
00062         do_mysql = 0;
00063         alog("MySQL: has been disabled.");
00064         return 0;
00065     } else {
00066         do_mysql = 1;
00067         alog("MySQL: has been enabled.");
00068         alog("MySQL: client version %s.", mysql_get_client_info());
00069     }
00070 
00071     /* The following configuration options are required.
00072      * If missing disable MySQL to avoid any problems.   
00073      */
00074 
00075     if ((do_mysql) && (!MysqlName || !MysqlUser)) {
00076         do_mysql = 0;
00077         alog("MySQL Error: Set all required configuration options.");
00078         return 0;
00079     }
00080 
00081     if (!db_mysql_open()) {
00082         do_mysql = 0;
00083         return 0;
00084     }
00085 
00086     return 1;
00087 }
00088 
00089 /*************************************************************************/
00090 
00091 /* Open a connection to the mysql database. Return 0 on failure, or
00092  * 1 on success. If this succeeds, we're guaranteed of a working
00093  * mysql connection (unless something unexpected happens ofcourse...)
00094  */
00095 int db_mysql_open()
00096 {
00097     /* If MySQL is disabled, return 0 */
00098     if (!do_mysql)
00099         return 0;
00100 
00101     /* If we are reported to be connected, ping MySQL to see if we really are
00102      * still connected. (yes mysql_ping() returns 0 on success)
00103      */
00104     if (mysql_is_connected && !mysql_ping(mysql))
00105         return 1;
00106     
00107     mysql_is_connected = 0;
00108     
00109     mysql = mysql_init(NULL);
00110     if (mysql == NULL) {
00111         db_mysql_error(MYSQL_WARNING, "Unable to create mysql object");
00112         return 0;
00113     }
00114 
00115     if (!MysqlPort)
00116         MysqlPort = MYSQL_DEFAULT_PORT;
00117     
00118     if (!mysql_real_connect(mysql, MysqlHost, MysqlUser, MysqlPass, MysqlName, MysqlPort, MysqlSock, 0)) {
00119         log_perror("MySQL Error: Cant connect to MySQL: %s\n", mysql_error(mysql));
00120         return 0;
00121     }
00122 
00123     mysql_is_connected = 1;
00124 
00125     return 1;
00126 
00127 }
00128 
00129 
00130 /*************************************************************************/
00131 
00132 /* Perform a MySQL query. Return 1 if the query succeeded and 0 if the
00133  * query failed. Before returning failure, re-try the query a few times
00134  * and die if it still fails.
00135  */
00136 int db_mysql_query(char *sql)
00137 {
00138     int lcv;
00139 
00140     if (!do_mysql)
00141         return 0;
00142 
00143     if (debug)
00144         alog("debug: MySQL: %s", sql);
00145 
00146     /* Try as many times as configured in MysqlRetries */
00147     for (lcv = 0; lcv < MysqlRetries; lcv++) {
00148         if (db_mysql_open() && (mysql_query(mysql, sql) == 0))
00149             return 1;
00150 
00151         /* If we get here, we could not run the query */
00152         log_perror("Unable to run query: %s\n", mysql_error(mysql));
00153 
00154         /* Wait for MysqlRetryGap seconds and try again */
00155         sleep(MysqlRetryGap);
00156     }
00157 
00158     /* Unable to run the query even after MysqlRetries tries */
00159     db_mysql_error(MYSQL_WARNING, "query");
00160 
00161     return 0;
00162 
00163 }
00164 
00165 /*************************************************************************/
00166 
00167 /* Quote a string to be safely included in a query. The result of this
00168  * function is allocated; it MUST be freed by the caller.
00169  */
00170 char *db_mysql_quote(char *sql)
00171 {
00172     int slen;
00173     char *quoted;
00174 
00175 
00176     if (!sql)
00177         return sstrdup("");
00178 
00179     slen = strlen(sql);
00180     quoted = malloc((1 + (slen * 2)) * sizeof(char));
00181 
00182     mysql_real_escape_string(mysql, quoted, sql, slen);
00183     
00184     return quoted;
00185 
00186 }
00187 
00188 /*************************************************************************/
00189 
00190 /* Close the MySQL database connection. */
00191 int db_mysql_close()
00192 {
00193     mysql_close(mysql);
00194 
00195     mysql_is_connected = 0;
00196 
00197     return 1;
00198 }
00199 
00200 /*************************************************************************/
00201 
00202 /* Try to execute a query and issue a warning when failed. Return 1 on
00203  * success and 0 on failure.
00204  */
00205 int db_mysql_try(const char *fmt, ...)
00206 {
00207     va_list args;
00208     static char sql[MAX_SQL_BUF];
00209 
00210     va_start(args, fmt);
00211     vsnprintf(sql, MAX_SQL_BUF, fmt, args);
00212     va_end(args);
00213 
00214     if (!db_mysql_query(sql)) {
00215         log_perror("Can't create sql query: %s", sql);
00216         db_mysql_error(MYSQL_WARNING, "query");
00217         return 0;
00218     }
00219     
00220     return 1;
00221 }
00222 
00223 /*************************************************************************/
00224 
00225 /* Return a string to insert into a SQL query. The string will, once
00226  * evaluated by MySQL, result in a the given pass encoded in the encryption
00227  * type selected for MysqlSecure
00228  *
00229  * This should be removed since Rob properly did encryption modules... -GD
00230  */
00231 char *db_mysql_secure(char *pass)
00232 {
00233     char epass[BUFSIZE];
00234     char tmp_pass[PASSMAX];
00235 
00236     /* Initialize the buffer. Bug #86 */
00237     memset(epass, '\0', BUFSIZE);
00238     memset(tmp_pass, '\0', PASSMAX);
00239 
00240     /* We couldnt decrypt the pass... */
00241     if (enc_decrypt(pass, tmp_pass, PASSMAX) != 1) {
00242         snprintf(epass, sizeof(epass), "'%s'", pass);
00243     } else {                    /* if we could decrypt the pass */
00244         if (!pass) {
00245             snprintf(epass, sizeof(epass), "''");
00246         } else if ((!MysqlSecure) || (strcmp(MysqlSecure, "") == 0)) {
00247             snprintf(epass, sizeof(epass), "'%s'", tmp_pass);
00248         } else if (strcmp(MysqlSecure, "des") == 0) {
00249             snprintf(epass, sizeof(epass), "ENCRYPT('%s')", tmp_pass);
00250         } else if (strcmp(MysqlSecure, "md5") == 0) {
00251             snprintf(epass, sizeof(epass), "MD5('%s')", tmp_pass);
00252         } else if (strcmp(MysqlSecure, "sha") == 0) {
00253             snprintf(epass, sizeof(epass), "SHA('%s')", tmp_pass);
00254         } else {
00255             snprintf(epass, sizeof(epass), "ENCODE('%s','%s')", tmp_pass,
00256                      MysqlSecure);
00257         }
00258     }
00259     return sstrdup(epass);
00260 }
00261 
00262 /*************************************************************************/
00263 
00264 /*
00265  * NickServ Specific Secion
00266  */
00267 
00268 /*************************************************************************/
00269 
00270 /* Save the given NickRequest into the database
00271  * Return 1 on success, 0 on failure
00272  * These tables are tagged and will be cleaned:
00273  * - anope_ns_request
00274  */
00275 int db_mysql_save_ns_req(NickRequest * nr)
00276 {
00277     int ret;
00278     char *q_nick, *q_passcode, *q_password, *q_email;
00279 
00280     q_nick = db_mysql_quote(nr->nick);
00281     q_passcode = db_mysql_quote(nr->passcode);
00282     q_password = db_mysql_quote(nr->password);
00283     q_email = db_mysql_quote(nr->email);
00284 
00285     ret = db_mysql_try("UPDATE anope_ns_request "
00286                        "SET passcode = '%s', password = '%s', email = '%s', requested = %d, active = 1 "
00287                        "WHERE nick = '%s'",
00288                        q_passcode, q_password, q_email, (int) nr->requested,
00289                        q_nick);
00290 
00291     if (ret && (mysql_affected_rows(mysql) == 0)) {
00292         ret = db_mysql_try("INSERT DELAYED INTO anope_ns_request "
00293                            "(nick, passcode, password, email, requested, active) "
00294                            "VALUES ('%s', '%s', '%s', '%s', %d, 1)",
00295                            q_nick, q_passcode, q_password, q_email, 
00296                            (int) nr->requested);
00297     }
00298 
00299     free(q_nick);
00300     free(q_passcode);
00301     free(q_password);
00302     free(q_email);
00303     
00304     return ret;
00305 }
00306 
00307 /*************************************************************************/
00308 
00309 /* Save the given NickCore into the database
00310  * Also save the access list and memo's for this user
00311  * Return 1 on success, 0 on failure
00312  * These tables are tagged and will be cleaned:
00313  * - anope_ns_core
00314  * - anope_ns_alias
00315  * - anope_ns_access
00316  * - anope_ms_info (serv='NICK')
00317  */
00318 int db_mysql_save_ns_core(NickCore * nc)
00319 {
00320     int ret;
00321     int i;
00322     char *q_display, *q_pass, *epass, *q_email, *q_greet, *q_url,
00323         *q_access, *q_sender, *q_text;
00324 
00325     q_display = db_mysql_quote(nc->display);
00326     q_pass = db_mysql_quote(nc->pass);
00327     q_email = db_mysql_quote(nc->email);
00328     q_greet = db_mysql_quote(nc->greet);
00329     q_url = db_mysql_quote(nc->url);
00330 
00331     epass = db_mysql_secure(q_pass);
00332     free(q_pass);
00333 
00334     /* Let's take care of the core itself */
00335     /* Update the existing records */
00336     ret = db_mysql_try("UPDATE anope_ns_core "
00337                        "SET pass = %s, email = '%s', greet = '%s', icq = %d, url = '%s', flags = %d, language = %d, accesscount = %d, memocount = %d, "
00338                        "    memomax = %d, channelcount = %d, channelmax = %d, active = 1 "
00339                        "WHERE display = '%s'",
00340                        epass, q_email, q_greet, nc->icq, q_url, nc->flags,
00341                        nc->language, nc->accesscount, nc->memos.memocount,
00342                        nc->memos.memomax, nc->channelcount, nc->channelmax,
00343                        q_display);
00344 
00345     /* Our previous UPDATE affected no rows, therefore this is a new record */
00346     if (ret && (mysql_affected_rows(mysql) == 0)) {
00347         ret = db_mysql_try("INSERT DELAYED INTO anope_ns_core "
00348                            "(display, pass, email, greet, icq, url, flags, language, accesscount, memocount, memomax, channelcount, channelmax, active) "
00349                            "VALUES ('%s', %s, '%s', '%s', %d, '%s', %d, %d, %d, %d, %d, %d, %d, 1)",
00350                            q_display, epass, q_email, q_greet, nc->icq, q_url,
00351                            nc->flags, nc->language, nc->accesscount,
00352                            nc->memos.memocount, nc->memos.memomax,
00353                            nc->channelcount, nc->channelmax);
00354     }
00355 
00356     /* Now let's do the access */
00357     for (i = 0; ret && (i < nc->accesscount); i++) {
00358         q_access = db_mysql_quote(nc->access[i]);
00359 
00360         ret = db_mysql_try("UPDATE anope_ns_access "
00361                            "SET access = '%s' "
00362                            "WHERE display = '%s'",
00363                            q_access, q_display);
00364 
00365         if (ret && (mysql_affected_rows(mysql) == 0)) {
00366             ret = db_mysql_try("INSERT DELAYED INTO anope_ns_access "
00367                                "(display, access) "
00368                                "VALUES ('%s','%s')",
00369                                q_display, q_access);
00370         }
00371 
00372         free(q_access);
00373     }
00374 
00375     /* Memos */
00376     for (i = 0; ret && (i < nc->memos.memocount); i++) {
00377         q_sender = db_mysql_quote(nc->memos.memos[i].sender);
00378         q_text = db_mysql_quote(nc->memos.memos[i].text);
00379 
00380         ret = db_mysql_try("UPDATE anope_ms_info "
00381                            "SET receiver = '%s', number = %d, flags = %d, time = %d, sender = '%s', text = '%s', active = 1 "
00382                            "WHERE  nm_id = %d AND serv = 'NICK'",
00383                            q_display, nc->memos.memos[i].number,
00384                            nc->memos.memos[i].flags,
00385                            (int) nc->memos.memos[i].time, q_sender, q_text,
00386                            nc->memos.memos[i].id);
00387         
00388         if (ret && (mysql_affected_rows(mysql) == 0)) {
00389             ret = db_mysql_try("INSERT INTO anope_ms_info "
00390                                "(receiver, number, flags, time, sender, text, serv, active) "
00391                                "VALUES ('%s', %d, %d, %d, '%s', '%s', 'NICK', 1)",
00392                                q_display, nc->memos.memos[i].number,
00393                                nc->memos.memos[i].flags,
00394                                (int) nc->memos.memos[i].time, q_sender,
00395                                q_text);
00396 
00397             /* This is to make sure we can UPDATE memos instead of TRUNCATE
00398              * the table each time and then INSERT them all again. Ideally
00399              * everything in core would have it's dbase-id stored, but that's
00400              * something for phase 3. -GD
00401              */
00402             if (ret)
00403                 nc->memos.memos[i].id = mysql_insert_id(mysql);
00404         }
00405 
00406         free(q_sender);
00407         free(q_text);
00408     }
00409 
00410     free(q_display);
00411     free(epass);
00412     free(q_email);
00413     free(q_greet);
00414     free(q_url);
00415     
00416     return ret;
00417 }
00418 
00419 
00420 /*************************************************************************/
00421 
00422 /* Save the given NickAlias into the database
00423  * Return 1 on success, 0 on failure
00424  * These tables are tagged and will be cleaned:
00425  * - anope_ns_core
00426  * - anope_ns_alias
00427  * - anope_ns_access
00428  * - anope_ms_info (serv='NICK')
00429  */
00430 int db_mysql_save_ns_alias(NickAlias * na)
00431 {
00432     int ret;
00433     char *q_nick, *q_lastmask, *q_lastrname, *q_lastquit, *q_display;
00434 
00435     q_nick = db_mysql_quote(na->nick);
00436     q_lastmask = db_mysql_quote(na->last_usermask);
00437     q_lastrname = db_mysql_quote(na->last_realname);
00438     q_lastquit = db_mysql_quote(na->last_quit);
00439     q_display = db_mysql_quote(na->nc->display);
00440 
00441     ret = db_mysql_try("UPDATE anope_ns_alias "
00442                        "SET last_usermask = '%s', last_realname = '%s', last_quit = '%s', time_registered = %d, last_seen = %d, status = %d, "
00443                        "    display = '%s', active = 1 "
00444                        "WHERE nick = '%s'",
00445                        q_lastmask, q_lastrname, q_lastquit,
00446                        (int) na->time_registered, (int) na->last_seen,
00447                        (int) na->status, q_display, q_nick);
00448 
00449     /* Our previous UPDATE affected no rows, therefore this is a new record */
00450     if (ret && (mysql_affected_rows(mysql) == 0)) {
00451         ret = db_mysql_try("INSERT DELAYED INTO anope_ns_alias "
00452                            "(nick, last_usermask, last_realname, last_quit, time_registered, last_seen, status, display, active) "
00453                            "VALUES ('%s', '%s', '%s', '%s', %d, %d, %d, '%s', 1)",
00454                            q_nick, q_lastmask, q_lastrname, q_lastquit,
00455                            (int) na->time_registered, (int) na->last_seen,
00456                            (int) na->status, q_display);
00457     }
00458 
00459     free(q_nick);
00460     free(q_lastmask);
00461     free(q_lastrname);
00462     free(q_lastquit);
00463     free(q_display);
00464     
00465     return ret;
00466 }
00467 
00468 /*************************************************************************/
00469 
00470 /*
00471  * ChanServ Specific Secion
00472  */
00473 
00474 /*************************************************************************/
00475 
00476 /* Save the given ChannelInfo into the database
00477  * Also save the access list, levels, akicks, badwords, ttb, and memo's for this channel
00478  * Return 1 on success, 0 on failure
00479  * These tables are tagged and will be cleaned:
00480  * - anope_cs_info
00481  * - anope_cs_access
00482  * - anope_cs_levels
00483  * - anope_cs_akicks
00484  * - anope_cs_badwords
00485  * - anope_cs_ttb
00486  * - anope_ms_info (serv='CHAN')
00487  */
00488 int db_mysql_save_cs_info(ChannelInfo * ci)
00489 {
00490     int ret;
00491     int i;
00492     char *q_name;
00493     char *q_founder;
00494     char *q_successor;
00495     char *q_pass;
00496     char *e_pass;
00497     char *q_desc;
00498     char *q_url;
00499     char *q_email;
00500     char *q_lasttopic;
00501     char *q_lasttopicsetter;
00502     char *q_forbidby;
00503     char *q_forbidreason;
00504     char *q_mlock_key;
00505     char *q_mlock_flood;
00506     char *q_mlock_redirect;
00507     char *q_entrymsg;
00508     char *q_botnick;
00509     char *q_sender;
00510     char *q_text;
00511     char *q_accessdisp;
00512     char *q_akickdisp;
00513     char *q_akickreason;
00514     char *q_akickcreator;
00515     char *q_badwords;
00516 
00517     q_name = db_mysql_quote(ci->name);
00518     if (ci->founder) {
00519         q_founder = db_mysql_quote(ci->founder->display);
00520     } else {
00521         q_founder = db_mysql_quote("");
00522     }
00523     if (ci->successor) {
00524         q_successor = db_mysql_quote(ci->successor->display);
00525     } else {
00526         q_successor = db_mysql_quote("");
00527     }
00528     q_pass = db_mysql_quote(ci->founderpass);
00529     q_desc = db_mysql_quote(ci->desc);
00530     q_url = db_mysql_quote(ci->url);
00531     q_email = db_mysql_quote(ci->email);
00532     q_lasttopic = db_mysql_quote(ci->last_topic);
00533     q_lasttopicsetter = db_mysql_quote(ci->last_topic_setter);
00534     q_forbidby = db_mysql_quote(ci->forbidby);
00535     q_forbidreason = db_mysql_quote(ci->forbidreason);
00536     q_mlock_key = db_mysql_quote(ci->mlock_key);
00537     q_mlock_flood = db_mysql_quote(ci->mlock_flood);
00538     q_mlock_redirect = db_mysql_quote(ci->mlock_redirect);
00539     q_entrymsg = db_mysql_quote(ci->entry_message);
00540     if (ci->bi) {
00541         q_botnick = db_mysql_quote(ci->bi->nick);
00542     } else {
00543         q_botnick = db_mysql_quote("");
00544     }
00545 
00546     e_pass = db_mysql_secure(q_pass);
00547     free(q_pass);
00548 
00549     /* Let's take care of the core itself */
00550     ret = db_mysql_try("UPDATE anope_cs_info "
00551                        "SET founder = '%s', successor = '%s', founderpass = %s, descr = '%s', url = '%s', email = '%s', time_registered = %d, "
00552                        "    last_used = %d, last_topic = '%s', last_topic_setter = '%s', last_topic_time = %d, flags = %d, forbidby = '%s', "
00553                        "    forbidreason = '%s', bantype = %d, accesscount = %d, akickcount = %d, mlock_on = %d,  mlock_off = %d, mlock_limit = %d, "
00554                        "    mlock_key = '%s', mlock_flood = '%s', mlock_redirect = '%s', entry_message = '%s', memomax = %d, botnick = '%s', botflags = %d, "
00555                        "    bwcount = %d, capsmin = %d, capspercent = %d, floodlines = %d, floodsecs = %d, repeattimes = %d, active = 1 "
00556                        "WHERE name = '%s'",
00557                        q_founder, q_successor, e_pass, q_desc, q_url, q_email,
00558                        (int) ci->time_registered, (int) ci->last_used,
00559                        q_lasttopic, q_lasttopicsetter,
00560                        (int) ci->last_topic_time, (int) ci->flags, q_forbidby,
00561                        q_forbidreason, (int) ci->bantype,
00562                        (int) ci->accesscount, (int) ci->akickcount,
00563                        (int) ci->mlock_on, (int) ci->mlock_off,
00564                        (int) ci->mlock_limit, q_mlock_key, q_mlock_flood,
00565                        q_mlock_redirect, q_entrymsg, (int) ci->memos.memomax,
00566                        q_botnick, (int) ci->botflags, (int) ci->bwcount,
00567                        (int) ci->capsmin, (int) ci->capspercent,
00568                        (int) ci->floodlines, (int) ci->floodsecs,
00569                        (int) ci->repeattimes, q_name);
00570 
00571     /* Our previous UPDATE affected no rows, therefore this is a new record */
00572     if (ret && (mysql_affected_rows(mysql) == 0)) {
00573         ret = db_mysql_try("INSERT DELAYED INTO anope_cs_info "
00574                            "(name, founder, successor, founderpass, descr, url, email, time_registered, last_used,  last_topic, last_topic_setter, "
00575                            "    last_topic_time, flags, forbidby, forbidreason, bantype, accesscount, akickcount, mlock_on, mlock_off, mlock_limit, "
00576                            "    mlock_key, mlock_flood, mlock_redirect, entry_message, botnick, botflags, bwcount, capsmin, capspercent, floodlines, "
00577                            "    floodsecs, repeattimes, active) "
00578                            "VALUES ('%s', '%s', '%s', %s, '%s', '%s', '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', %d, %d, %d, %d, %d, %d, '%s', '%s', "
00579                            "        '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, %d, 1)",
00580                            q_name, q_founder, q_successor, e_pass, q_desc,
00581                            q_url, q_email, (int) ci->time_registered,
00582                            (int) ci->last_used, q_lasttopic,
00583                            q_lasttopicsetter, (int) ci->last_topic_time,
00584                            (int) ci->flags, q_forbidby, q_forbidreason,
00585                            (int) ci->bantype, (int) ci->accesscount,
00586                            (int) ci->akickcount, (int) ci->mlock_on,
00587                            (int) ci->mlock_off, (int) ci->mlock_limit,
00588                            q_mlock_key, q_mlock_flood, q_mlock_redirect,
00589                            q_entrymsg, q_botnick, (int) ci->botflags,
00590                            (int) ci->bwcount, (int) ci->capsmin,
00591                            (int) ci->capspercent, (int) ci->floodlines,
00592                            (int) ci->floodsecs, (int) ci->repeattimes);
00593     }
00594 
00595     /* Memos */
00596     for (i = 0; ret && (i < ci->memos.memocount); i++) {
00597         q_sender = db_mysql_quote(ci->memos.memos[i].sender);
00598         q_text = db_mysql_quote(ci->memos.memos[i].text);
00599 
00600         ret = db_mysql_try("UPDATE anope_ms_info "
00601                            "SET receiver = '%s', number = %d, flags = %d, time = %d, sender = '%s', text = '%s', active = 1 "
00602                            "WHERE nm_id = %d AND serv = 'CHAN'",
00603                            q_name, ci->memos.memos[i].number,
00604                            ci->memos.memos[i].flags,
00605                            (int) ci->memos.memos[i].time, q_sender, q_text,
00606                            ci->memos.memos[i].id);
00607         
00608         if (ret && (mysql_affected_rows(mysql) == 0)) {
00609             ret = db_mysql_try("INSERT INTO anope_ms_info "
00610                                "(receiver, number,flags, time, sender, text, serv, active) "
00611                                "VALUES ('%s', %d, %d, %d, '%s', '%s', 'CHAN', 1)",
00612                                q_name, ci->memos.memos[i].number,
00613                                ci->memos.memos[i].flags,
00614                                (int) ci->memos.memos[i].time, q_sender,
00615                                q_text);
00616 
00617             /* See comment at db_mysql_save_ns_core */
00618             if (ret)
00619                 ci->memos.memos[i].id = mysql_insert_id(mysql);
00620         }
00621 
00622         free(q_sender);
00623         free(q_text);
00624     }
00625 
00626     /* Access */
00627     for (i = 0; ret && (i < ci->accesscount); i++) {
00628         if (ci->access[i].in_use) {
00629             q_accessdisp = db_mysql_quote(ci->access[i].nc->display);
00630             
00631             ret = db_mysql_try("UPDATE anope_cs_access "
00632                                "SET in_use = %d, level = %d, last_seen = %d, active = 1 "
00633                                "WHERE channel = '%s' AND display = '%s'",
00634                                (int) ci->access[i].in_use,
00635                                (int) ci->access[i].level,
00636                                (int) ci->access[i].last_seen,
00637                                q_name, q_accessdisp);
00638             
00639             if (ret && (mysql_affected_rows(mysql) == 0)) {
00640                 ret = db_mysql_try("INSERT DELAYED INTO anope_cs_access "
00641                                    "(channel, display, in_use, level, last_seen, active) "
00642                                    "VALUES ('%s', '%s', %d, %d, %d, 1)",
00643                                    q_name, q_accessdisp,
00644                                    (int) ci->access[i].in_use,
00645                                    (int) ci->access[i].level,
00646                                    (int) ci->access[i].last_seen);
00647             }
00648             
00649             free(q_accessdisp);
00650         }
00651     }
00652 
00653     /* Levels */
00654     for (i = 0; ret && (i < CA_SIZE); i++) {
00655         ret = db_mysql_try("UPDATE anope_cs_levels "
00656                            "SET level = %d, active = 1 "
00657                            "WHERE channel = '%s' AND position = %d",
00658                            (int) ci->levels[i], q_name, i);
00659         
00660         if (ret && (mysql_affected_rows(mysql) == 0)) {
00661             ret = db_mysql_try("INSERT DELAYED INTO anope_cs_levels "
00662                                "(channel, position, level, active) "
00663                                "VALUES ('%s', %d, %d, 1)",
00664                                q_name, i, (int) ci->levels[i]);
00665         }
00666     }
00667 
00668     /* Akicks */
00669     for (i = 0; ret && (i < ci->akickcount); i++) {
00670         if (ci->akick[i].flags & AK_USED) {
00671             if (ci->akick[i].flags & AK_ISNICK)
00672                 q_akickdisp = db_mysql_quote(ci->akick[i].u.nc->display);
00673             else
00674                 q_akickdisp = db_mysql_quote(ci->akick[i].u.mask);
00675 
00676             q_akickreason = db_mysql_quote(ci->akick[i].reason);
00677             q_akickcreator = db_mysql_quote(ci->akick[i].creator);
00678         } else {
00679             q_akickdisp = "";
00680             q_akickreason = "";
00681             q_akickcreator = "";
00682         }
00683 
00684         ret = db_mysql_try("UPDATE anope_cs_akicks "
00685                            "SET flags = %d, reason = '%s', creator = '%s', addtime = %d, active = 1 "
00686                            "WHERE channel = '%s' AND dmask = '%s'",
00687                            (int) ci->akick[i].flags, q_akickreason,
00688                            q_akickcreator, (ci->akick[i].flags & AK_USED ?
00689                                              (int) ci->akick[i].addtime : 0),
00690                            q_name, q_akickdisp);
00691         
00692         if (ret && (mysql_affected_rows(mysql) == 0)) {
00693             ret = db_mysql_try("INSERT DELAYED INTO anope_cs_akicks "
00694                                "(channel, dmask, flags, reason, creator, addtime, active) "
00695                                "VALUES ('%s', '%s', %d, '%s', '%s', %d, 1)",
00696                                q_name, q_akickdisp, (int) ci->akick[i].flags,
00697                                q_akickreason, q_akickcreator,
00698                                (ci->akick[i].flags & AK_USED ?
00699                                  (int) ci->akick[i].addtime : 0));
00700         }
00701 
00702         if (ci->akick[i].flags & AK_USED) {
00703             free(q_akickdisp);
00704             free(q_akickreason);
00705             free(q_akickcreator);
00706         }
00707     }
00708 
00709     /* Bad Words */
00710     for (i = 0; ret && (i < ci->bwcount); i++) {
00711         if (ci->badwords[i].in_use) {
00712             q_badwords = db_mysql_quote(ci->badwords[i].word);
00713 
00714             ret = db_mysql_try("UPDATE anope_cs_badwords "
00715                                "SET type = %d, active = 1 "
00716                                "WHERE channel = '%s' AND word = '%s'",
00717                                (int) ci->badwords[i].type, q_name,
00718                                q_badwords);
00719             
00720             if (ret && (mysql_affected_rows(mysql) == 0)) {
00721                 ret = db_mysql_try("INSERT DELAYED INTO anope_cs_badwords "
00722                                    "(channel, word, type, active) "
00723                                    "VALUES ('%s', '%s', %d, 1)",
00724                                    q_name, q_badwords,
00725                                    (int) ci->badwords[i].type);
00726             }
00727 
00728             free(q_badwords);
00729         }
00730     }
00731 
00732     /* TTB's */
00733     for (i = 0; ret && (i < TTB_SIZE); i++) {
00734         ret = db_mysql_try("UPDATE anope_cs_ttb "
00735                            "SET value = %d, active = 1 "
00736                            "WHERE channel = '%s' AND ttb_id = %d",
00737                            ci->ttb[i], q_name, i);
00738         
00739         if (ret && (mysql_affected_rows(mysql) == 0)) {
00740             ret = db_mysql_try("INSERT DELAYED INTO anope_cs_ttb "
00741                                "(channel, ttb_id, value, active) "
00742                                "VALUES ('%s', %d, %d, 1)",
00743                                q_name, i, ci->ttb[i]);
00744         }
00745     }
00746 
00747     free(q_name);
00748     free(q_founder);
00749     free(q_successor);
00750     free(e_pass);
00751     free(q_desc);
00752     free(q_url);
00753     free(q_email);
00754     free(q_lasttopic);
00755     free(q_lasttopicsetter);
00756     free(q_mlock_key);
00757     free(q_mlock_flood);
00758     free(q_mlock_redirect);
00759     free(q_entrymsg);
00760     free(q_botnick);
00761     free(q_forbidby);
00762     free(q_forbidreason);
00763     
00764     return ret;
00765 }
00766 
00767 /*************************************************************************/
00768 
00769 
00770 /*
00771  * OperServ Specific Section
00772  */
00773 
00774 /*************************************************************************/
00775 
00776 /* Save the OperServ database into MySQL
00777  * Return 1 on success, 0 on failure
00778  * These tables are tagged and will be cleaned:
00779  * - anope_os_akills
00780  * - anope_os_sglines
00781  * - anope_os_sqlines
00782  * - anope_os_szlines
00783  * These tables are emptied:
00784  * - anope_os_core
00785  */
00786 
00787 int db_mysql_save_os_db(unsigned int maxucnt, unsigned int maxutime,
00788                          SList * ak, SList * sgl, SList * sql, SList * szl)
00789 {
00790     int ret;
00791     int i;
00792     Akill *akl;
00793     SXLine *sl;
00794     char *q_user;
00795     char *q_host;
00796     char *q_mask;
00797     char *q_by;
00798     char *q_reason;
00799 
00800 
00801     /* First save the core info */
00802     ret = db_mysql_try("INSERT DELAYED INTO anope_os_core "
00803                        "(maxusercnt, maxusertime, akills_count, sglines_count, sqlines_count, szlines_count) "
00804                        "VALUES (%d, %d, %d, %d, %d, %d)",
00805                        maxucnt, maxutime, ak->count, sgl->count, sql->count,
00806                        szl->count);
00807 
00808     /* Next save all AKILLs */
00809     for (i = 0; ret && (i < ak->count); i++) {
00810         akl = ak->list[i];
00811         q_user = db_mysql_quote(akl->user);
00812         q_host = db_mysql_quote(akl->host);
00813         q_by = db_mysql_quote(akl->by);
00814         q_reason = db_mysql_quote(akl->reason);
00815 
00816         ret = db_mysql_try("UPDATE anope_os_akills "
00817                            "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
00818                            "WHERE user = '%s' AND host = '%s'",
00819                            q_by, q_reason, (int) akl->seton,
00820                            (int) akl->expires, q_user, q_host);
00821         
00822         if (ret && (mysql_affected_rows(mysql) == 0)) {
00823             ret = db_mysql_try("INSERT DELAYED INTO anope_os_akills "
00824                                "(user, host, xby, reason, seton, expire, active) "
00825                                "VALUES ('%s', '%s', '%s', '%s', %d, %d, 1)",
00826                                 q_user, q_host, q_by, q_reason,
00827                                 (int) akl->seton, (int) akl->expires);
00828         }
00829 
00830         free(q_user);
00831         free(q_host);
00832         free(q_by);
00833         free(q_reason);
00834     }
00835 
00836     /* Time to save the SGLINEs */
00837     for (i = 0; ret && (i < sgl->count); i++) {
00838         sl = sgl->list[i];
00839         q_mask = db_mysql_quote(sl->mask);
00840         q_by = db_mysql_quote(sl->by);
00841         q_reason = db_mysql_quote(sl->reason);
00842 
00843         ret = db_mysql_try("UPDATE anope_os_sglines "
00844                            "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
00845                            "WHERE mask = '%s'",
00846                            q_by, q_reason, (int) sl->seton, (int) sl->expires,
00847                            q_mask);
00848         
00849         if (ret && (mysql_affected_rows(mysql) == 0)) {
00850             ret = db_mysql_try("INSERT DELAYED INTO anope_os_sglines "
00851                                "(mask, xby, reason, seton, expire, active) "
00852                                "VALUES ('%s', '%s', '%s', %d, %d, 1)",
00853                                q_mask, q_by, q_reason, (int) sl->seton,
00854                                (int) sl->expires);
00855         }
00856 
00857         free(q_mask);
00858         free(q_by);
00859         free(q_reason);
00860     }
00861 
00862     /* Save the SQLINEs */
00863     for (i = 0; ret && (i < sql->count); i++) {
00864         sl = sql->list[i];
00865 
00866         q_mask = db_mysql_quote(sl->mask);
00867         q_by = db_mysql_quote(sl->by);
00868         q_reason = db_mysql_quote(sl->reason);
00869 
00870         ret = db_mysql_try("UPDATE anope_os_sqlines "
00871                            "SET xby = '%s', reason = '%s',  seton = %d, expire = %d, active = 1 "
00872                            "WHERE mask = '%s'",
00873                            q_by, q_reason, (int) sl->seton, (int) sl->expires,
00874                            q_mask);
00875         
00876         if (ret && (mysql_affected_rows(mysql) == 0)) {
00877             ret = db_mysql_try("INSERT DELAYED INTO anope_os_sqlines "
00878                                "(mask, xby, reason, seton, expire, active) "
00879                                "VALUES ('%s', '%s', '%s', %d, %d, 1)",
00880                                q_mask, q_by, q_reason, (int) sl->seton,
00881                                (int) sl->expires);
00882         }
00883 
00884         free(q_mask);
00885         free(q_by);
00886         free(q_reason);
00887     }
00888 
00889     /* Now save the SZLINEs */
00890     for (i = 0; ret && (i < szl->count); i++) {
00891         sl = szl->list[i];
00892 
00893         q_mask = db_mysql_quote(sl->mask);
00894         q_by = db_mysql_quote(sl->by);
00895         q_reason = db_mysql_quote(sl->reason);
00896 
00897         ret = db_mysql_try("UPDATE anope_os_szlines "
00898                            "SET xby = '%s', reason = '%s', seton = %d, expire = %d, active = 1 "
00899                            "WHERE mask = '%s'",
00900                            q_by, q_reason, (int) sl->seton, (int) sl->expires,
00901                            q_mask);
00902         
00903         if (ret && (mysql_affected_rows(mysql) == 0)) {
00904             ret = db_mysql_try("INSERT DELAYED INTO anope_os_szlines "
00905                                "(mask, xby, reason, seton, expire, active) "
00906                                "VALUES ('%s', '%s', '%s', %d, %d, 1)",
00907                                q_mask, q_by, q_reason, (int) sl->seton,
00908                                (int) sl->expires);
00909         }
00910 
00911         free(q_mask);
00912         free(q_by);
00913         free(q_reason);
00914     }
00915     
00916     return ret;
00917 }
00918 
00919 /*************************************************************************/
00920 
00921 /* Save the given NewsItem
00922  * These tables are tagged and will be cleaned:
00923  * - anope_os_news
00924  */
00925 int db_mysql_save_news(NewsItem * ni)
00926 {
00927     int ret;
00928     char *q_text;
00929     char *q_who;
00930 
00931     q_text = db_mysql_quote(ni->text);
00932     q_who = db_mysql_quote(ni->who);
00933 
00934     ret = db_mysql_try("UPDATE anope_os_news "
00935                        "SET ntext = '%s', who = '%s', active = 1 "
00936                        "WHERE type = %d AND num = %d AND `time` = %d",
00937                        q_text, q_who, ni->type, ni->num, (int) ni->time);
00938     
00939     if (ret && (mysql_affected_rows(mysql) == 0)) {
00940         ret = db_mysql_try("INSERT DELAYED INTO anope_os_news "
00941                            "(type, num, ntext, who, `time`, active) "
00942                            "VALUES (%d, %d, '%s', '%s', %d, 1)",
00943                            ni->type, ni->num, q_text, q_who, (int) ni->time);
00944     }
00945 
00946     free(q_text);
00947     free(q_who);
00948     
00949     return ret;
00950 }
00951 
00952 /*************************************************************************/
00953 
00954 /* Save the given Exception
00955  * These tables are tagged and will be cleaned:
00956  * - anope_os_exceptions
00957  */
00958 
00959 int db_mysql_save_exceptions(Exception * e)
00960 {
00961     int ret;
00962     char *q_mask;
00963     char *q_who;
00964     char *q_reason;
00965 
00966     q_mask = db_mysql_quote(e->mask);
00967     q_who = db_mysql_quote(e->who);
00968     q_reason = db_mysql_quote(e->reason);
00969 
00970     ret = db_mysql_try("UPDATE anope_os_exceptions "
00971                        "SET lim = %d, who = '%s', reason = '%s', `time` = %d, expires = %d, active = 1 "
00972                        "WHERE mask = '%s'",
00973                        e->limit, q_who, q_reason, (int) e->time,
00974                        (int) e->expires, q_mask);
00975     
00976     if (ret && (mysql_affected_rows(mysql)) == 0) {
00977         ret = db_mysql_try("INSERT DELAYED INTO anope_os_exceptions "
00978                            "(mask, lim, who, reason, `time`, expires, active) "
00979                            "VALUES ('%s', %d, '%s', '%s', %d, %d, 1)",
00980                            q_mask, e->limit, q_who, q_reason, (int) e->time,
00981                            (int) e->expires);
00982     }
00983 
00984     free(q_mask);
00985     free(q_who);
00986     free(q_reason);
00987     
00988     return ret;
00989 }
00990 
00991 /*************************************************************************/
00992 
00993 
00994 /*
00995  * HostServ Specific Section
00996  */
00997 
00998 /*************************************************************************/
00999 
01000 /* Save the given HostCore
01001  * These tables are tagged and will be cleaned:
01002  * - anope_hs_core
01003  */
01004 
01005 int db_mysql_save_hs_core(HostCore * hc)
01006 {
01007     int ret;
01008     char *q_nick;
01009     char *q_ident;
01010     char *q_host;
01011     char *q_creator;
01012 
01013     q_nick = db_mysql_quote(hc->nick);
01014     q_ident = db_mysql_quote(hc->vIdent);
01015     q_host = db_mysql_quote(hc->vHost);
01016     q_creator = db_mysql_quote(hc->creator);
01017 
01018     ret = db_mysql_try("UPDATE anope_hs_core "
01019                        "SET vident = '%s', vhost = '%s', creator = '%s', `time` = %d, active = 1 "
01020                        "WHERE nick = '%s'",
01021                        q_ident, q_host, q_creator, (int) hc->time, q_nick);
01022     
01023     if (ret && (mysql_affected_rows(mysql) == 0)) {
01024         ret = db_mysql_try("INSERT DELAYED INTO anope_hs_core "
01025                            "(nick, vident, vhost, creator, `time`, active) "
01026                            "VALUES ('%s', '%s', '%s', '%s', %d, 1)",
01027                            q_nick, q_ident, q_host, q_creator,
01028                            (int) hc->time);
01029     }
01030 
01031     free(q_nick);
01032     free(q_ident);
01033     free(q_host);
01034     free(q_creator);
01035     
01036     return ret;
01037 }
01038 
01039 /*************************************************************************/
01040 
01041 /*
01042  * BotServ Specific Section
01043  */
01044 
01045 /*************************************************************************/
01046 
01047 int db_mysql_save_bs_core(BotInfo * bi)
01048 {
01049     int ret;
01050     char *q_nick;
01051     char *q_user;
01052     char *q_host;
01053     char *q_real;
01054 
01055     q_nick = db_mysql_quote(bi->nick);
01056     q_user = db_mysql_quote(bi->user);
01057     q_host = db_mysql_quote(bi->host);
01058     q_real = db_mysql_quote(bi->real);
01059 
01060     ret = db_mysql_try("UPDATE anope_bs_core "
01061                        "SET user = '%s', host = '%s', rname = '%s', flags = %d, created = %d, chancount = %d, active = 1 "
01062                        "WHERE nick = '%s'",
01063                        q_user, q_host, q_real, bi->flags, (int) bi->created,
01064                        bi->chancount, q_nick);
01065     
01066     if (ret && (mysql_affected_rows(mysql) == 0)) {
01067         ret = db_mysql_try("INSERT DELAYED INTO anope_bs_core "
01068                            "(nick, user, host, rname, flags, created, chancount, active) "
01069                            "VALUES ('%s', '%s', '%s', '%s', %d, %d, %d, 1)",
01070                            q_nick, q_user, q_host, q_real, bi->flags,
01071                            (int) bi->created, bi->chancount);
01072     }
01073 
01074     free(q_nick);
01075     free(q_user);
01076     free(q_host);
01077     free(q_real);
01078     
01079     return ret;
01080 }
01081 
01082 /*************************************************************************/
01083 /*************************************************************************/
01084 
01085 /* Some loading code! */
01086