-/* DBHelper.c - NeonServ v5.0
- * Copyright (C) 2011 Philipp Kreil (pk910)
+/* DBHelper.c - NeonServ v5.5
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "mysqlConn.h"
#include "lang.h"
#include "tools.h"
+#include "IRCEvents.h"
+#include "HandleInfoHandler.h"
+#include "ClientSocket.h"
+#include "bots.h"
+#include "ConfigParser.h"
void _loadUserSettings(struct UserNode *user) {
+ SYNCHRONIZE(cache_sync);
MYSQL_RES *res;
MYSQL_ROW row;
- printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ printf_mysql_query("SELECT `user_lang`, `user_reply_privmsg`, `user_god`, `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
res = mysql_use();
if ((row = mysql_fetch_row(res)) != NULL) {
user->language = get_language_by_tag(row[0]);
user->flags |= USERFLAG_REPLY_PRIVMSG;
if(strcmp(row[2], "0"))
user->flags |= USERFLAG_GOD_MODE;
+ user->user_id = atoi(row[3]);
+ user->flags |= USERFLAG_HAS_USERID;
} else
user->language = get_default_language();
user->flags |= USERFLAG_LOADED_SETTINGS;
+ DESYNCHRONIZE(cache_sync);
}
int isGodMode(struct UserNode *user) {
return (user->flags & USERFLAG_GOD_MODE);
}
-int getChannelAccess(struct UserNode *user, struct ChanNode *chan, int override) {
+int getChannelAccess(struct UserNode *user, struct ChanNode *chan) {
if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
loadChannelSettings(chan);
if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
MYSQL_RES *res;
MYSQL_ROW row;
int caccess = 0;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- if(strcmp(row[2], "0") && override)
- caccess = atoi(row[1]);
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
- //
+ int userid;
+ if(user->flags & USERFLAG_HAS_USERID)
+ userid = user->user_id;
+ else {
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
res = mysql_use();
if ((row = mysql_fetch_row(res)) != NULL) {
- int cflags = atoi(row[1]);
- if(!(cflags & DB_CHANUSER_SUSPENDED) && atoi(row[0]) > caccess)
- caccess = atoi(row[0]);
- }
- return caccess;
+ userid = atoi(row[0]);
+ user->user_id = userid;
+ user->flags |= USERFLAG_HAS_USERID;
+ } else
+ return 0;
}
- return 0;
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%d' AND `chanuser_cid` = '%d'", userid, chan->channel_id);
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int cflags = atoi(row[1]);
+ if(!(cflags & DB_CHANUSER_SUSPENDED) && atoi(row[0]) > caccess)
+ caccess = atoi(row[0]);
+ }
+ return caccess;
}
char *getChanDefault(char *channel_setting) {
return row[0];
}
-int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_override, int allow_501) {
+int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_501) {
loadChannelSettings(chan);
if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return 0;
if((user->flags & USERFLAG_ISIRCOP)) return 1;
if(require_access == 0) return 1;
if(!(user->flags & USERFLAG_ISAUTHED)) return 0;
int caccess = 0;
- printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
- res = mysql_use();
- if ((row = mysql_fetch_row(res)) != NULL) {
- printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%s' AND `chanuser_cid` = '%d'", row[0], chan->channel_id);
+ int userid;
+ if(user->flags & USERFLAG_HAS_USERID)
+ userid = user->user_id;
+ else {
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ userid = atoi(row[0]);
+ user->user_id = userid;
+ user->flags |= USERFLAG_HAS_USERID;
+ } else
+ userid = -1;
+ }
+ if(userid > -1) {
+ printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%d' AND `chanuser_cid` = '%d'", userid, chan->channel_id);
res = mysql_use();
if ((row = mysql_fetch_row(res)) != NULL) {
int cflags = atoi(row[1]);
}
void _loadChannelSettings(struct ChanNode *chan) {
+ SYNCHRONIZE(cache_sync);
MYSQL_RES *res;
MYSQL_ROW row;
printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name));
chan->channel_id = atoi(row[0]);
}
chan->flags |= CHANFLAG_REQUESTED_CHANINFO;
+ DESYNCHRONIZE(cache_sync);
}
//TODO: fix performance: we should cache the user access
if(protection == 3) return 0;
/* Don't protect if the victim isn't added to the channel, unless we are to protect non-users also. */
- int victim_access = getChannelAccess(victim, chan, 0);
+ int victim_access = getChannelAccess(victim, chan);
if (!victim_access && protection != 0) return 0;
/* Protect if the aggressor isn't a user because at this point, the aggressor can only be less than or equal to the victim. */
- int issuer_access = getChannelAccess(issuer, chan, 0);
+ int issuer_access = getChannelAccess(issuer, chan);
if (!issuer_access) return 1;
/* If the aggressor was a user, then the victim can't be helped. */
}
return NULL;
}
+
+int renameAccount(char *oldauth, char *newauth) {
+ MYSQL_RES *res, *res2;
+ MYSQL_ROW row, row2;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(oldauth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ int userid = atoi(row[0]);
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(newauth));
+ res = mysql_use();
+ if((row = mysql_fetch_row(res)) != NULL) {
+ //merge
+ int newuid = atoi(row[0]);
+ printf_mysql_query("SELECT `chanuser_id`, `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%d'", newuid);
+ res = mysql_use();
+ while((row = mysql_fetch_row(res)) != NULL) {
+ printf_mysql_query("SELECT `chanuser_id`, `chanuser_access`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_uid` = '%d'", userid);
+ res2 = mysql_use();
+ if((row2 = mysql_fetch_row(res2)) != NULL) {
+ if(atoi(row[0]) > atoi(row2[0])) {
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%s' WHERE `chanuser_id` = '%s'", row[0], row2[0]);
+ }
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[0]);
+ } else
+ printf_mysql_query("UPDATE `chanusers` SET `chanuser_uid` = '%d' WHERE `chanuser_id` = '%s'", userid, row[0]);
+ }
+ printf_mysql_query("UPDATE `channels` SET `channel_registrator` = '%d' WHERE `channel_registrator` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `bans` SET `ban_owner` = '%d' WHERE `ban_owner` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `events` SET `auth` = '%s' WHERE `auth` = '%s'", escape_string(newauth), escape_string(oldauth));
+ printf_mysql_query("UPDATE `godlog` SET `godlog_uid` = '%d' WHERE `godlog_uid` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `owner_history` SET `owner_history_to_uid` = '%d' WHERE `owner_history_to_uid` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `owner_history` SET `owner_history_from_uid` = '%d' WHERE `owner_history_from_uid` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `owner_history` SET `owner_history_from_uid` = '%d' WHERE `owner_history_from_uid` = '%d'", userid, newuid);
+ printf_mysql_query("UPDATE `noinvite` SET `uid` = '%d' WHERE `uid` = '%d'", userid, newuid);
+ printf_mysql_query("DELETE FROM `users` WHERE `chanuser_id` = '%d'", newuid);
+ } else {
+ //simply rename the account
+ printf_mysql_query("UPDATE `users` SET `user_user` = '%s' WHERE `user_id` = '%d'", escape_string(newauth), userid);
+ }
+ char *alertchan = get_string_field("General.CheckAuths.alertchan");
+ if(alertchan) {
+ struct ChanNode *alertchan_chan = getChanByName(alertchan);
+ struct ClientSocket *alertclient;
+ if(alertchan_chan && (alertclient = getChannelBot(alertchan_chan, 0)) != NULL) {
+ putsock(alertclient, "PRIVMSG %s :Renamed User %s to %s", alertchan_chan->name, oldauth, newauth);
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static AUTHLOOKUP_CALLBACK(event_user_registered_auth_lookup);
+
+struct event_user_registered_cache {
+ struct UserNode *user;
+ char *oldauth;
+};
+
+static void event_user_registered(struct UserNode *user, char *new_mask) {
+ //check if there is a fakehost on both sides...
+ //extract host from new_mask
+ char *new_host = strchr(new_mask, '@');
+ if(new_host)
+ new_host++;
+ else
+ return;
+ if(!isFakeHost(user->host) || !isFakeHost(new_host))
+ return;
+ //extract user names
+ char oldauth[AUTHLEN], newauth[AUTHLEN];
+ char *p;
+ if((p = strstr(user->host, "."))) {
+ *p = '\0';
+ strcpy(oldauth, user->host);
+ *p = '.';
+ }
+ if((p = strstr(new_host, "."))) {
+ *p = '\0';
+ strcpy(newauth, new_host);
+ *p = '.';
+ }
+ if(!stricmp(oldauth, newauth))
+ return;
+ //check if we know this user; then check the new auth
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(oldauth));
+ res = mysql_use();
+ if ((row = mysql_fetch_row(res)) != NULL) {
+ struct event_user_registered_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->user = user;
+ cache->oldauth = strdup(oldauth);
+ lookup_authname(newauth, 0, event_user_registered_auth_lookup, cache);
+ }
+ return;
+}
+
+static AUTHLOOKUP_CALLBACK(event_user_registered_auth_lookup) {
+ struct event_user_registered_cache *cache = data;
+ if(exists) {
+ renameAccount(cache->oldauth, auth);
+ strcpy(cache->user->auth, auth);
+ cache->user->flags |= USERFLAG_ISAUTHED;
+ }
+ free(cache->oldauth);
+ free(cache);
+}
+
+void deleteUser(int userid) {
+ //simply delete the user
+ MYSQL_RES *res, *res2;
+ MYSQL_ROW row, row2;
+ printf_mysql_query("SELECT a.`chanuser_access`, a.`chanuser_cid`, (SELECT COUNT(*) FROM `chanusers` AS b WHERE b.`chanuser_cid` = a.`chanuser_cid` AND b.`chanuser_access` = 500) FROM `chanusers` AS a WHERE a.`chanuser_uid` = '%d'", userid);
+ res = mysql_use();
+ while((row = mysql_fetch_row(res))) {
+ if(!strcmp(row[0], "500") && !strcmp(row[2], "1")) {
+ //unregister channel
+ printf_mysql_query("SELECT `botid`, `channel_name` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `chanid` = '%s' AND `suspended` = '0'", row[1]);
+ res2 = mysql_use();
+ while((row2 = mysql_fetch_row(res2))) {
+ struct ClientSocket *bot;
+ int clientid = atoi(row2[0]);
+ for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+ if(bot->clientid == clientid)
+ putsock(bot, "PART %s :Channel unregistered.", row2[1]);
+ }
+ }
+ printf_mysql_query("DELETE FROM `bot_channels` WHERE `chanid` = '%s'", row[1]);
+ }
+ }
+ printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_uid` = '%d'", userid);
+ printf_mysql_query("UPDATE `bans` SET `ban_owner` = 0 WHERE `ban_owner` = '%d'", userid);
+ printf_mysql_query("UPDATE `donotregister` SET `dnr_user` = 0 WHERE `dnr_user` = '%d'", userid);
+ printf_mysql_query("UPDATE `bans` SET `ban_owner` = 0 WHERE `ban_owner` = '%d'", userid);
+ printf_mysql_query("UPDATE `godlog` SET `godlog_uid` = 0 WHERE `godlog_uid` = '%d'", userid);
+ printf_mysql_query("DELETE FROM `noinvite` WHERE `uid` = '%d'", userid);
+ printf_mysql_query("UPDATE `owner_history` SET `owner_history_to_uid` = 0 WHERE `owner_history_to_uid` = '%d'", userid);
+ printf_mysql_query("UPDATE `owner_history` SET `owner_history_from_uid` = 0 WHERE `owner_history_from_uid` = '%d'", userid);
+ printf_mysql_query("UPDATE `channels` SET `channel_registrator` = 0 WHERE `channel_registrator` = '%d'", userid);
+ printf_mysql_query("DELETE FROM `users` WHERE `user_id` = '%d'", userid);
+ struct UserNode *user;
+ for(user = getAllUsers(NULL); user; user = getAllUsers(user)) {
+ if(user->flags & USERFLAG_HAS_USERID)
+ user->flags &= ~USERFLAG_HAS_USERID;
+ }
+}
+
+void init_DBHelper() {
+ bind_registered(event_user_registered, 0);
+}
+