From 55b2809510dbd0f378e623adb1618abbd2880433 Mon Sep 17 00:00:00 2001 From: Kyle Sanderson Date: Wed, 16 Sep 2015 13:47:08 -0700 Subject: [PATCH] Remove Admin-SQL-Threaded.sp. --- plugins/AMBuilder | 1 - plugins/admin-sql-threaded.sp | 847 ---------------------------------- 2 files changed, 848 deletions(-) delete mode 100644 plugins/admin-sql-threaded.sp diff --git a/plugins/AMBuilder b/plugins/AMBuilder index bf9c34903..022a1cdfc 100644 --- a/plugins/AMBuilder +++ b/plugins/AMBuilder @@ -20,7 +20,6 @@ files = [ 'funvotes.sp', 'playercommands.sp', 'sounds.sp', - 'admin-sql-threaded.sp', 'basecommands.sp', 'mapchooser.sp', 'randomcycle.sp', diff --git a/plugins/admin-sql-threaded.sp b/plugins/admin-sql-threaded.sp deleted file mode 100644 index e65a1a64f..000000000 --- a/plugins/admin-sql-threaded.sp +++ /dev/null @@ -1,847 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod SQL Admins Plugin (Threaded) - * Fetches admins from an SQL database dynamically. - * - * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * As a special exception, AlliedModders LLC gives you permission to link the - * code of this program (as well as its derivative works) to "Half-Life 2," the - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software - * by the Valve Corporation. You must obey the GNU General Public License in - * all respects for all other code used. Additionally, AlliedModders LLC grants - * this exception to all derivative works. AlliedModders LLC defines further - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), - * or . - * - * Version: $Id$ - */ - -/* We like semicolons */ -#pragma semicolon 1 - -#include - -public Plugin myinfo = -{ - name = "SQL Admins (Threaded)", - author = "AlliedModders LLC", - description = "Reads admins from SQL dynamically", - version = SOURCEMOD_VERSION, - url = "http://www.sourcemod.net/" -}; - -/** - * Notes: - * - * 1) All queries in here are high priority. This is because the admin stuff - * is very important. Do not take this to mean that in your script, - * everything should be high priority. - * - * 2) All callbacks are locked with "sequence numbers." This is to make sure - * that multiple calls to sm_reloadadmins and the like do not make us - * store the results from two or more callbacks accidentally. Instead, we - * check the sequence number in each callback with the current "allowed" - * sequence number, and if it doesn't match, the callback is cancelled. - * - * 3) Sequence numbers for groups and overrides are not cleared unless there - * was a 100% success in the fetch. This is so we can potentially implement - * connection retries in the future. - * - * 4) Sequence numbers for the user cache are ignored except for being - * non-zero, which means players in-game should be re-checked for admin - * powers. - */ - -Database hDatabase = null; /** Database connection */ -int g_sequence = 0; /** Global unique sequence number */ -int ConnectLock = 0; /** Connect sequence number */ -int RebuildCachePart[3] = {0}; /** Cache part sequence numbers */ -int PlayerSeq[MAXPLAYERS+1]; /** Player-specific sequence numbers */ -bool PlayerAuth[MAXPLAYERS+1]; /** Whether a player has been "pre-authed" */ - -//#define _DEBUG - -public void OnMapEnd() -{ - /** - * Clean up on map end just so we can start a fresh connection when we need it later. - */ - delete hDatabase; -} - -public bool OnClientConnect(int client, char[] rejectmsg, int maxlen) -{ - PlayerSeq[client] = 0; - PlayerAuth[client] = false; - return true; -} - -public void OnClientDisconnect(int client) -{ - PlayerSeq[client] = 0; - PlayerAuth[client] = false; -} - -public void OnDatabaseConnect(Database db, const char[] error, any data) -{ -#if defined _DEBUG - PrintToServer("OnDatabaseConnect(%x, %d) ConnectLock=%d", db, data, ConnectLock); -#endif - - /** - * If this happens to be an old connection request, ignore it. - */ - if (data != ConnectLock || hDatabase != null) - { - delete db; - return; - } - - ConnectLock = 0; - hDatabase = db; - - /** - * See if the connection is valid. If not, don't un-mark the caches - * as needing rebuilding, in case the next connection request works. - */ - if (hDatabase == null) - { - LogError("Failed to connect to database: %s", error); - return; - } - - /** - * See if we need to get any of the cache stuff now. - */ - int sequence; - if ((sequence = RebuildCachePart[AdminCache_Overrides]) != 0) - { - FetchOverrides(hDatabase, sequence); - } - if ((sequence = RebuildCachePart[AdminCache_Groups]) != 0) - { - FetchGroups(hDatabase, sequence); - } - if ((sequence = RebuildCachePart[AdminCache_Admins]) != 0) - { - FetchUsersWeCan(hDatabase); - } -} - -void RequestDatabaseConnection() -{ - ConnectLock = ++g_sequence; - if (SQL_CheckConfig("admins")) - { - Database.Connect(OnDatabaseConnect, "admins", ConnectLock); - } else { - Database.Connect(OnDatabaseConnect, "default", ConnectLock); - } -} - -public void OnRebuildAdminCache(AdminCachePart part) -{ - /** - * Mark this part of the cache as being rebuilt. This is used by the - * callback system to determine whether the results should still be - * used. - */ - int sequence = ++g_sequence; - RebuildCachePart[part] = sequence; - - /** - * If we don't have a database connection, we can't do any lookups just yet. - */ - if (!hDatabase) - { - /** - * Ask for a new connection if we need it. - */ - if (!ConnectLock) - { - RequestDatabaseConnection(); - } - return; - } - - if (part == AdminCache_Overrides) - { - FetchOverrides(hDatabase, sequence); - } else if (part == AdminCache_Groups) { - FetchGroups(hDatabase, sequence); - } else if (part == AdminCache_Admins) { - FetchUsersWeCan(hDatabase); - } -} - -public Action OnClientPreAdminCheck(int client) -{ - PlayerAuth[client] = true; - - /** - * Play nice with other plugins. If there's no database, don't delay the - * connection process. Unfortunately, we can't attempt anything else and - * we just have to hope either the database is waiting or someone will type - * sm_reloadadmins. - */ - if (hDatabase == null) - { - return Plugin_Continue; - } - - /** - * Similarly, if the cache is in the process of being rebuilt, don't delay - * the user's normal connection flow. The database will soon auth the user - * normally. - */ - if (RebuildCachePart[AdminCache_Admins] != 0) - { - return Plugin_Continue; - } - - /** - * If someone has already assigned an admin ID (bad bad bad), don't - * bother waiting. - */ - if (GetUserAdmin(client) != INVALID_ADMIN_ID) - { - return Plugin_Continue; - } - - FetchUser(hDatabase, client); - - return Plugin_Handled; -} - -public void OnReceiveUserGroups(Database db, DBResultSet rs, const char[] error, any data) -{ - DataPack pk = view_as(data); - pk.Reset(); - - int client = pk.ReadCell(); - int sequence = pk.ReadCell(); - - /** - * Make sure it's the same client. - */ - if (PlayerSeq[client] != sequence) - { - delete pk; - return; - } - - AdminId adm = view_as(pk.ReadCell()); - - /** - * Someone could have sneakily changed the admin id while we waited. - */ - if (GetUserAdmin(client) != adm) - { - NotifyPostAdminCheck(client); - delete pk; - return; - } - - /** - * See if we got results. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving user: %s", error); - LogError("Query dump: %s", query); - NotifyPostAdminCheck(client); - delete pk; - return; - } - - char name[80]; - GroupId grp; - - while (rs.FetchRow()) - { - rs.FetchString(0, name, sizeof(name)); - - if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID) - { - continue; - } - -#if defined _DEBUG - PrintToServer("Binding user group (%d, %d, %d, %s, %d)", client, sequence, adm, name, grp); -#endif - - adm.InheritGroup(grp); - } - - /** - * We're DONE! Omg. - */ - NotifyPostAdminCheck(client); - delete pk; -} - -public void OnReceiveUser(Database db, DBResultSet rs, const char[] error, any data) -{ - DataPack pk = view_as(data); - pk.Reset(); - - int client = pk.ReadCell(); - - /** - * Check if this is the latest result request. - */ - int sequence = pk.ReadCell(); - if (PlayerSeq[client] != sequence) - { - /* Discard everything, since we're out of sequence. */ - delete pk; - return; - } - - /** - * If we need to use the results, make sure they succeeded. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving user: %s", error); - LogError("Query dump: %s", query); - RunAdminCacheChecks(client); - NotifyPostAdminCheck(client); - delete pk; - return; - } - - int num_accounts = rs.RowCount; - if (num_accounts == 0) - { - RunAdminCacheChecks(client); - NotifyPostAdminCheck(client); - delete pk; - return; - } - - char authtype[16]; - char identity[80]; - char password[80]; - char flags[32]; - char name[80]; - int immunity, id; - AdminId adm; - - /** - * Cache user info -- [0] = db id, [1] = cache id, [2] = groups - */ - int[][] user_lookup = new int[num_accounts][3]; - int total_users = 0; - - while (rs.FetchRow()) - { - id = rs.FetchInt(0); - rs.FetchString(1, authtype, sizeof(authtype)); - rs.FetchString(2, identity, sizeof(identity)); - rs.FetchString(3, password, sizeof(password)); - rs.FetchString(4, flags, sizeof(flags)); - rs.FetchString(5, name, sizeof(name)); - immunity = rs.FetchInt(7); - - /* For dynamic admins we clear anything already in the cache. */ - if ((adm = FindAdminByIdentity(authtype, identity)) != INVALID_ADMIN_ID) - { - RemoveAdmin(adm); - } - - adm = CreateAdmin(name); - if (!adm.BindIdentity(authtype, identity)) - { - LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity); - continue; - } - - user_lookup[total_users][0] = id; - user_lookup[total_users][1] = view_as(adm); - user_lookup[total_users][2] = rs.FetchInt(6); - total_users++; - -#if defined _DEBUG - PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s,%d):%d:%d", id, authtype, identity, password, flags, name, immunity, adm, user_lookup[total_users-1][2]); -#endif - - /* See if this admin wants a password */ - if (password[0] != '\0') - { - adm.SetPassword(password); - } - - adm.ImmunityLevel = immunity; - - /* Apply each flag */ - int len = strlen(flags); - AdminFlag flag; - for (int i=0; i(adm)) - { - id = user_lookup[i][0]; - group_count = user_lookup[i][2]; - break; - } - } - -#if defined _DEBUG - PrintToServer("Binding client (%d, %d) resulted in: (%d, %d, %d)", client, sequence, id, adm, group_count); -#endif - - /** - * If we can't verify that we assigned a database admin, or the user has no - * groups, don't bother doing anything. - */ - if (!id || !group_count) - { - NotifyPostAdminCheck(client); - delete pk; - return; - } - - /** - * The user has groups -- we need to fetch them! - */ - char query[255]; - Format(query, sizeof(query), "SELECT g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id WHERE ag.admin_id = %d", id); - - pk.Reset(); - pk.WriteCell(client); - pk.WriteCell(sequence); - pk.WriteCell(adm); - pk.WriteString(query); - - db.Query(OnReceiveUserGroups, query, pk, DBPrio_High); -} - -void FetchUser(Database db, int client) -{ - char name[MAX_NAME_LENGTH]; - char safe_name[(MAX_NAME_LENGTH * 2) - 1]; - char steamid[32]; - char steamidalt[32]; - char ipaddr[24]; - - /** - * Get authentication information from the client. - */ - GetClientName(client, name, sizeof(name)); - GetClientIP(client, ipaddr, sizeof(ipaddr)); - - steamid[0] = '\0'; - if (GetClientAuthId(client, AuthId_Steam2, steamid, sizeof(steamid))) - { - if (StrEqual(steamid, "STEAM_ID_LAN")) - { - steamid[0] = '\0'; - } - } - - db.Escape(name, safe_name, sizeof(safe_name)); - - /** - * Construct the query using the information the user gave us. - */ - char query[512]; - int len = 0; - - len += Format(query[len], sizeof(query)-len, "SELECT a.id, a.authtype, a.identity, a.password, a.flags, a.name, COUNT(ag.group_id), immunity"); - len += Format(query[len], sizeof(query)-len, " FROM sm_admins a LEFT JOIN sm_admins_groups ag ON a.id = ag.admin_id WHERE "); - len += Format(query[len], sizeof(query)-len, " (a.authtype = 'ip' AND a.identity = '%s')", ipaddr); - len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'name' AND a.identity = '%s')", safe_name); - if (steamid[0] != '\0') - { - strcopy(steamidalt, sizeof(steamidalt), steamid); - steamidalt[6] = (steamid[6] == '0') ? '1' : '0'; - - len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'steam' AND (a.identity = '%s' OR a.identity = '%s'))", steamid, steamidalt); - } - len += Format(query[len], sizeof(query)-len, " GROUP BY a.id"); - - /** - * Send the actual query. - */ - PlayerSeq[client] = ++g_sequence; - - DataPack pk = new DataPack(); - pk.WriteCell(client); - pk.WriteCell(PlayerSeq[client]); - pk.WriteString(query); - -#if defined _DEBUG - PrintToServer("Sending user query: %s", query); -#endif - - db.Query(OnReceiveUser, query, pk, DBPrio_High); -} - -void FetchUsersWeCan(Database db) -{ - for (int i=1; i<=MaxClients; i++) - { - if (PlayerAuth[i] && GetUserAdmin(i) == INVALID_ADMIN_ID) - { - FetchUser(db, i); - } - } - - /** - * This round of updates is done. Go in peace. - */ - RebuildCachePart[AdminCache_Admins] = 0; -} - - -public void OnReceiveGroupImmunity(Database db, DBResultSet rs, const char[] error, any data) -{ - DataPack pk = view_as(data); - pk.Reset(); - - /** - * Check if this is the latest result request. - */ - int sequence = pk.ReadCell(); - if (RebuildCachePart[AdminCache_Groups] != sequence) - { - /* Discard everything, since we're out of sequence. */ - delete pk; - return; - } - - /** - * If we need to use the results, make sure they succeeded. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving group immunity: %s", error); - LogError("Query dump: %s", query); - delete pk; - return; - } - - /* We're done with the pack forever. */ - delete pk; - - while (rs.FetchRow()) - { - char group1[80]; - char group2[80]; - GroupId grp, other; - - rs.FetchString(0, group1, sizeof(group1)); - rs.FetchString(1, group2, sizeof(group2)); - - if (((grp = FindAdmGroup(group1)) == INVALID_GROUP_ID) - || (other = FindAdmGroup(group2)) == INVALID_GROUP_ID) - { - continue; - } - - grp.AddGroupImmunity(other); -#if defined _DEBUG - PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", grp, other); -#endif - } - - /* Clear the sequence so another connect doesn't refetch */ - RebuildCachePart[AdminCache_Groups] = 0; -} - -public void OnReceiveGroupOverrides(Database db, DBResultSet rs, const char[] error, any data) -{ - DataPack pk = view_as(data); - pk.Reset(); - - /** - * Check if this is the latest result request. - */ - int sequence = pk.ReadCell(); - if (RebuildCachePart[AdminCache_Groups] != sequence) - { - /* Discard everything, since we're out of sequence. */ - delete pk; - return; - } - - /** - * If we need to use the results, make sure they succeeded. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving group overrides: %s", error); - LogError("Query dump: %s", query); - delete pk; - return; - } - - /** - * Fetch the overrides. - */ - char name[80]; - char type[16]; - char command[64]; - char access[16]; - GroupId grp; - while (rs.FetchRow()) - { - rs.FetchString(0, name, sizeof(name)); - rs.FetchString(1, type, sizeof(type)); - rs.FetchString(2, command, sizeof(command)); - rs.FetchString(3, access, sizeof(access)); - - /* Find the group. This is actually faster than doing the ID lookup. */ - if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID) - { - /* Oh well, just ignore it. */ - continue; - } - - OverrideType o_type = Override_Command; - if (StrEqual(type, "group")) - { - o_type = Override_CommandGroup; - } - - OverrideRule o_rule = Command_Deny; - if (StrEqual(access, "allow")) - { - o_rule = Command_Allow; - } - -#if defined _DEBUG - PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", grp, command, o_type, o_rule); -#endif - - grp.AddCommandOverride(command, o_type, o_rule); - } - - /** - * It's time to get the group immunity list. - */ - int len = 0; - char query[256]; - len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi"); - len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id "); - len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id"); - - pk.Reset(); - pk.WriteCell(sequence); - pk.WriteString(query); - - db.Query(OnReceiveGroupImmunity, query, pk, DBPrio_High); -} - -public void OnReceiveGroups(Database db, DBResultSet rs, const char[] error, any data) -{ - DataPack pk = view_as(data); - pk.Reset(); - - /** - * Check if this is the latest result request. - */ - int sequence = pk.ReadCell(); - if (RebuildCachePart[AdminCache_Groups] != sequence) - { - /* Discard everything, since we're out of sequence. */ - delete pk; - return; - } - - /** - * If we need to use the results, make sure they succeeded. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving groups: %s", error); - LogError("Query dump: %s", query); - delete pk; - return; - } - - /** - * Now start fetching groups. - */ - char flags[32]; - char name[128]; - int immunity; - while (rs.FetchRow()) - { - rs.FetchString(0, flags, sizeof(flags)); - rs.FetchString(1, name, sizeof(name)); - immunity = rs.FetchInt(2); - -#if defined _DEBUG - PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name); -#endif - - /* Find or create the group */ - GroupId grp; - if ((grp = FindAdmGroup(name)) == INVALID_GROUP_ID) - { - grp = CreateAdmGroup(name); - } - - /* Add flags from the database to the group */ - int num_flag_chars = strlen(flags); - for (int i=0; i(data); - pk.Reset(); - - /** - * Check if this is the latest result request. - */ - int sequence = pk.ReadCell(); - if (RebuildCachePart[AdminCache_Overrides] != sequence) - { - /* Discard everything, since we're out of sequence. */ - delete pk; - return; - } - - /** - * If we need to use the results, make sure they succeeded. - */ - if (rs == null) - { - char query[255]; - pk.ReadString(query, sizeof(query)); - LogError("SQL error receiving overrides: %s", error); - LogError("Query dump: %s", query); - delete pk; - return; - } - - /** - * We're done with you, now. - */ - delete pk; - - char type[64]; - char name[64]; - char flags[32]; - int flag_bits; - while (rs.FetchRow()) - { - rs.FetchString(0, type, sizeof(type)); - rs.FetchString(1, name, sizeof(name)); - rs.FetchString(2, flags, sizeof(flags)); - -#if defined _DEBUG - PrintToServer("Adding override (%s, %s, %s)", type, name, flags); -#endif - - flag_bits = ReadFlagString(flags); - if (StrEqual(type, "command")) - { - AddCommandOverride(name, Override_Command, flag_bits); - } else if (StrEqual(type, "group")) { - AddCommandOverride(name, Override_CommandGroup, flag_bits); - } - } - - /* Clear the sequence so another connect doesn't refetch */ - RebuildCachePart[AdminCache_Overrides] = 0; -} - -void FetchOverrides(Database db, int sequence) -{ - char query[255]; - - Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides"); - - DataPack pk = new DataPack(); - pk.WriteCell(sequence); - pk.WriteString(query); - - db.Query(OnReceiveOverrides, query, pk, DBPrio_High); -} -