1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/configs/sql-init-scripts/admins-mysql.sql Mon Aug 13 01:46:58 2007 +0000
1.3 @@ -0,0 +1,41 @@
1.4 +
1.5 +CREATE TABLE sm_admins (
1.6 + id int(10) unsigned NOT NULL auto_increment,
1.7 + authtype enum('steam','name','ip') NOT NULL,
1.8 + identity varchar(65) NOT NULL,
1.9 + password varchar(65),
1.10 + flags varchar(30) NOT NULL,
1.11 + name varchar(65) NOT NULL,
1.12 + PRIMARY KEY (id)
1.13 +);
1.14 +
1.15 +CREATE TABLE sm_groups (
1.16 + id int(10) unsigned NOT NULL auto_increment,
1.17 + immunity enum('none','all','default') NOT NULL,
1.18 + flags varchar(30) NOT NULL,
1.19 + name varchar(120) NOT NULL,
1.20 + groups_immune varchar(255) NOT NULL,
1.21 + PRIMARY KEY (id)
1.22 +);
1.23 +
1.24 +CREATE TABLE sm_group_overrides (
1.25 + group_id int(10) unsigned NOT NULL,
1.26 + type enum('command','group') NOT NULL,
1.27 + name varchar(32) NOT NULL,
1.28 + access enum('allow','deny') NOT NULL,
1.29 + PRIMARY KEY (group_id, type, name)
1.30 +);
1.31 +
1.32 +CREATE TABLE sm_overrides (
1.33 + type enum('command','group') NOT NULL,
1.34 + name varchar(32) NOT NULL,
1.35 + flags varchar(30) NOT NULL,
1.36 + PRIMARY KEY (type,name)
1.37 +);
1.38 +
1.39 +CREATE TABLE sm_admins_groups (
1.40 + admin_id int(10) unsigned NOT NULL,
1.41 + group_id int(10) unsigned NOT NULL,
1.42 + inherit_order int(10) NOT NULL,
1.43 + PRIMARY KEY (admin_id, group_id)
1.44 +);
2.1 Binary file configs/sql-init-scripts/admins-sqlite.sq3 has changed
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/configs/sql-init-scripts/admins-sqlite.sql Mon Aug 13 01:46:58 2007 +0000
3.3 @@ -0,0 +1,41 @@
3.4 +
3.5 +CREATE TABLE sm_admins (
3.6 + id int(10) NOT NULL,
3.7 + authtype varchar(16) NOT NULL,
3.8 + identity varchar(65) NOT NULL,
3.9 + password varchar(65),
3.10 + flags varchar(30) NOT NULL,
3.11 + name varchar(65) NOT NULL,
3.12 + PRIMARY KEY (id)
3.13 +);
3.14 +
3.15 +CREATE TABLE sm_groups (
3.16 + id int(10) NOT NULL,
3.17 + immunity varchar(16) NOT NULL,
3.18 + flags varchar(30) NOT NULL,
3.19 + name varchar(120) NOT NULL,
3.20 + groups_immune varchar(255) NOT NULL,
3.21 + PRIMARY KEY (id)
3.22 +);
3.23 +
3.24 +CREATE TABLE sm_group_overrides (
3.25 + group_id int(10) NOT NULL,
3.26 + type varchar(16) NOT NULL,
3.27 + name varchar(32) NOT NULL,
3.28 + access varchar(16) NOT NULL,
3.29 + PRIMARY KEY (group_id, type, name)
3.30 +);
3.31 +
3.32 +CREATE TABLE sm_overrides (
3.33 + type varchar(16) NOT NULL,
3.34 + name varchar(32) NOT NULL,
3.35 + flags varchar(30) NOT NULL,
3.36 + PRIMARY KEY (type,name)
3.37 +);
3.38 +
3.39 +CREATE TABLE sm_admins_groups (
3.40 + admin_id int(10) NOT NULL,
3.41 + group_id int(10) NOT NULL,
3.42 + inherit_order int(10) NOT NULL,
3.43 + PRIMARY KEY (admin_id, group_id)
3.44 +);
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/plugins/admin-sql-prefetch.sp Mon Aug 13 01:46:58 2007 +0000
4.3 @@ -0,0 +1,436 @@
4.4 +/**
4.5 + * admin-sql-prefetch.sp
4.6 + * Prefetches admins from an SQL database without threading.
4.7 + * This file is part of SourceMod, Copyright (C) 2004-2007 AlliedModders LLC
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License
4.11 + * as published by the Free Software Foundation; either version 2
4.12 + * of the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
4.22 + *
4.23 + * Version: $Id$
4.24 + */
4.25 +
4.26 +/* We like semicolons */
4.27 +#pragma semicolon 1
4.28 +
4.29 +#include <sourcemod>
4.30 +
4.31 +public Plugin:myinfo =
4.32 +{
4.33 + name = "SQL Admin Prefetcher",
4.34 + author = "AlliedModders LLC",
4.35 + description = "Reads all admins from SQL",
4.36 + version = SOURCEMOD_VERSION,
4.37 + url = "http://www.sourcemod.net/"
4.38 +};
4.39 +
4.40 +public OnRebuildAdminCache(AdminCachePart:part)
4.41 +{
4.42 + /* First try to get a database connection */
4.43 + decl String:error[255];
4.44 + new Handle:db = SQL_Connect("default", true, error, sizeof(error));
4.45 + if (db == INVALID_HANDLE)
4.46 + {
4.47 + LogError("Could not connect to database \"default\": %s", error);
4.48 + return;
4.49 + }
4.50 +
4.51 + if (part == AdminCache_Overrides)
4.52 + {
4.53 + FetchOverrides(db);
4.54 + } else if (part == AdminCache_Groups) {
4.55 + FetchGroups(db);
4.56 + } else if (part == AdminCache_Admins) {
4.57 + FetchUsers(db);
4.58 + }
4.59 +
4.60 + CloseHandle(db);
4.61 +}
4.62 +
4.63 +FetchUserGroups(Handle:hQuery, AdminId:adm, id)
4.64 +{
4.65 + SQL_BindParamInt(hQuery, 0, id);
4.66 + if (!SQL_Execute(hQuery))
4.67 + {
4.68 + decl String:error[255];
4.69 + SQL_GetError(hQuery, error, sizeof(error));
4.70 + LogError("FetchUserGroups() statement execute failed: %s", error);
4.71 + return;
4.72 + }
4.73 +
4.74 + decl String:name[80];
4.75 + new GroupId:gid;
4.76 + while (SQL_FetchRow(hQuery))
4.77 + {
4.78 + SQL_FetchString(hQuery, 0, name, sizeof(name));
4.79 +
4.80 + if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
4.81 + {
4.82 + /* Group wasn't found, don't bother with it. */
4.83 + continue;
4.84 + }
4.85 +
4.86 + #if defined _DEBUG
4.87 + PrintToServer("Found admin group (%d, %d, %d)", id, gid, adm);
4.88 + #endif
4.89 +
4.90 + AdminInheritGroup(adm, gid);
4.91 + }
4.92 +}
4.93 +
4.94 +FetchUsers(Handle:db)
4.95 +{
4.96 + decl String:query[255], String:error[255];
4.97 + new Handle:hQuery, Handle:hGroupQuery;
4.98 +
4.99 + Format(query, sizeof(query), "SELECT id, authtype, identity, passwd, flags, name FROM sm_admins");
4.100 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
4.101 + {
4.102 + SQL_GetError(db, error, sizeof(error));
4.103 + LogError("FetchUsers() query failed: %s", query);
4.104 + LogError("Query error: %s", error);
4.105 + return;
4.106 + }
4.107 +
4.108 + /* If this fails it's non-fatal */
4.109 + Format(query,
4.110 + sizeof(query),
4.111 + "SELECT g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id WHERE ag.admin_id = ? ORDER BY inherit_order ASC");
4.112 + if ((hGroupQuery = SQL_PrepareQuery(db, query, error, sizeof(error))) == INVALID_HANDLE)
4.113 + {
4.114 + LogError("FetchUsers() group query preparation failed: %s", query);
4.115 + LogError("Query error: %s", error);
4.116 + }
4.117 +
4.118 + decl String:authtype[16];
4.119 + decl String:identity[80];
4.120 + decl String:password[80];
4.121 + decl String:flags[32];
4.122 + decl String:name[80];
4.123 + new AdminId:adm, id;
4.124 +
4.125 + while (SQL_FetchRow(hQuery))
4.126 + {
4.127 + id = SQL_FetchInt(hQuery, 0);
4.128 + SQL_FetchString(hQuery, 1, authtype, sizeof(authtype));
4.129 + SQL_FetchString(hQuery, 2, identity, sizeof(identity));
4.130 + SQL_FetchString(hQuery, 3, password, sizeof(password));
4.131 + SQL_FetchString(hQuery, 4, flags, sizeof(flags));
4.132 + SQL_FetchString(hQuery, 5, name, sizeof(name));
4.133 +
4.134 + /* Use a pre-existing admin if we can */
4.135 + if ((adm = FindAdminByIdentity(authtype, identity)) == INVALID_ADMIN_ID)
4.136 + {
4.137 + adm = CreateAdmin(name);
4.138 + if (!BindAdminIdentity(adm, authtype, identity))
4.139 + {
4.140 + LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
4.141 + continue;
4.142 + }
4.143 + }
4.144 +
4.145 + #if defined _DEBUG
4.146 + PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s):%d", id, authtype, identity, password, flags, name, adm);
4.147 + #endif
4.148 +
4.149 + /* See if this admin wants a password */
4.150 + if (password[0] != '\0')
4.151 + {
4.152 + SetAdminPassword(adm, password);
4.153 + }
4.154 +
4.155 + /* Apply each flag */
4.156 + new len = strlen(flags);
4.157 + new AdminFlag:flag;
4.158 + for (new i=0; i<len; i++)
4.159 + {
4.160 + if (!FindFlagByChar(flags[i], flag))
4.161 + {
4.162 + continue;
4.163 + }
4.164 + SetAdminFlag(adm, flag, true);
4.165 + }
4.166 +
4.167 + /* Look up groups */
4.168 + if (hGroupQuery != INVALID_HANDLE)
4.169 + {
4.170 + FetchUserGroups(hGroupQuery, adm, id);
4.171 + }
4.172 + }
4.173 +
4.174 + CloseHandle(hGroupQuery);
4.175 + CloseHandle(hQuery);
4.176 +}
4.177 +
4.178 +FetchGroups(Handle:db)
4.179 +{
4.180 + decl String:query[255];
4.181 + new Handle:hQuery;
4.182 +
4.183 + Format(query, sizeof(query), "SELECT id, immunity, flags, name, groups_immune FROM sm_groups");
4.184 +
4.185 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
4.186 + {
4.187 + decl String:error[255];
4.188 + SQL_GetError(db, error, sizeof(error));
4.189 + LogError("FetchGroups() query failed: %s", query);
4.190 + LogError("Query error: %s", error);
4.191 + return;
4.192 + }
4.193 +
4.194 + /* We cache basic group info so we can do reverse lookups */
4.195 + new Handle:groups = CreateArray(3);
4.196 +
4.197 + /* Now start fetching groups */
4.198 + decl String:immunity[16];
4.199 + decl String:flags[32];
4.200 + decl String:name[128];
4.201 + decl String:grp_immunity[256];
4.202 + while (SQL_FetchRow(hQuery))
4.203 + {
4.204 + new id = SQL_FetchInt(hQuery, 0);
4.205 + SQL_FetchString(hQuery, 1, immunity, sizeof(immunity));
4.206 + SQL_FetchString(hQuery, 2, flags, sizeof(flags));
4.207 + SQL_FetchString(hQuery, 3, name, sizeof(name));
4.208 + SQL_FetchString(hQuery, 4, grp_immunity, sizeof(grp_immunity));
4.209 +
4.210 +#if defined _DEBUG
4.211 + PrintToServer("Adding group (%d, %s, %s, %s, %s)", id, immunity, flags, name, grp_immunity);
4.212 +#endif
4.213 +
4.214 + /* Find or create the group */
4.215 + new GroupId:gid;
4.216 + if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
4.217 + {
4.218 + gid = CreateAdmGroup(name);
4.219 + }
4.220 +
4.221 + /* Add flags from the database to the group */
4.222 + new num_flag_chars = strlen(flags);
4.223 + for (new i=0; i<num_flag_chars; i++)
4.224 + {
4.225 + decl AdminFlag:flag;
4.226 + if (!FindFlagByChar(flags[i], flag))
4.227 + {
4.228 + continue;
4.229 + }
4.230 + SetAdmGroupAddFlag(gid, flag, true);
4.231 + }
4.232 +
4.233 + /* Set the immunity level this group has */
4.234 + if (StrEqual(immunity, "all"))
4.235 + {
4.236 + SetAdmGroupImmunity(gid, Immunity_Default, true);
4.237 + SetAdmGroupImmunity(gid, Immunity_Global, true);
4.238 + } else if (StrEqual(immunity, "default")) {
4.239 + SetAdmGroupImmunity(gid, Immunity_Default, true);
4.240 + } else if (StrEqual(immunity, "global")) {
4.241 + SetAdmGroupImmunity(gid, Immunity_Global, true);
4.242 + }
4.243 +
4.244 + new Handle:immunity_list = UTIL_ExplodeNumberString(grp_immunity);
4.245 +
4.246 + /* Now, save all this for later */
4.247 + decl data[3];
4.248 + data[0] = id;
4.249 + data[1] = _:gid;
4.250 + data[2] = _:immunity_list;
4.251 +
4.252 + PushArrayArray(groups, data);
4.253 + }
4.254 +
4.255 + CloseHandle(hQuery);
4.256 +
4.257 + /* Second pass - resolve immunity and group overrides */
4.258 + new num_groups = GetArraySize(groups);
4.259 + for (new i=0; i<num_groups; i++)
4.260 + {
4.261 + decl data[3];
4.262 + GetArrayArray(groups, i, data);
4.263 +
4.264 + new id = data[0];
4.265 + new GroupId:gid = GroupId:data[1];
4.266 + new Handle:immunity_list = Handle:data[2];
4.267 +
4.268 + /* Query to get per-group override list */
4.269 + Format(query,
4.270 + sizeof(query),
4.271 + "SELECT type, name, access FROM sm_group_overrides WHERE group_id = %d",
4.272 + id);
4.273 +
4.274 + /* Fetch the override query results */
4.275 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
4.276 + {
4.277 + decl String:error[255];
4.278 + SQL_GetError(db, error, sizeof(error));
4.279 + LogError("FetchOverrides() query failed: %s", query);
4.280 + LogError("Query error: %s", error);
4.281 + } else {
4.282 + decl String:type[16];
4.283 + decl String:cmd[64];
4.284 + decl String:access[16];
4.285 + while (SQL_FetchRow(hQuery))
4.286 + {
4.287 + SQL_FetchString(hQuery, 0, type, sizeof(type));
4.288 + SQL_FetchString(hQuery, 1, cmd, sizeof(cmd));
4.289 + SQL_FetchString(hQuery, 2, access, sizeof(access));
4.290 +
4.291 + new OverrideType:o_type = Override_Command;
4.292 + if (StrEqual(type, "group"))
4.293 + {
4.294 + o_type = Override_CommandGroup;
4.295 + }
4.296 +
4.297 + new OverrideRule:o_rule = Command_Deny;
4.298 + if (StrEqual(access, "allow"))
4.299 + {
4.300 + o_rule = Command_Allow;
4.301 + }
4.302 +
4.303 + #if defined _DEBUG
4.304 + PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", gid, cmd, o_type, o_rule);
4.305 + #endif
4.306 +
4.307 + AddAdmGroupCmdOverride(gid, cmd, o_type, o_rule);
4.308 + }
4.309 + CloseHandle(hQuery);
4.310 + }
4.311 +
4.312 + /* Lastly, resolve the immunity list if any */
4.313 + new immunity_count;
4.314 + if (immunity_list != INVALID_HANDLE
4.315 + && ((immunity_count = GetArraySize(immunity_list)) > 0))
4.316 + {
4.317 + for (new j=0; j<immunity_count; j++)
4.318 + {
4.319 + new other_id = GetArrayCell(immunity_list, j);
4.320 +
4.321 + if (other_id == id)
4.322 + {
4.323 + continue;
4.324 + }
4.325 +
4.326 + /* See if we can find this other ID */
4.327 + new GroupId:other_gid;
4.328 + if ((other_gid = UTIL_FindGroupInCache(groups, other_id)) != INVALID_GROUP_ID)
4.329 + {
4.330 + #if defined _DEBUG
4.331 + PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", gid, other_gid);
4.332 + #endif
4.333 + SetAdmGroupImmuneFrom(gid, other_gid);
4.334 + }
4.335 + }
4.336 + }
4.337 + }
4.338 +}
4.339 +
4.340 +FetchOverrides(Handle:db)
4.341 +{
4.342 + decl String:query[255];
4.343 + new Handle:hQuery;
4.344 +
4.345 + Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
4.346 +
4.347 + if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
4.348 + {
4.349 + decl String:error[255];
4.350 + SQL_GetError(db, error, sizeof(error));
4.351 + LogError("FetchOverrides() query failed: %s", query);
4.352 + LogError("Query error: %s", error);
4.353 + return;
4.354 + }
4.355 +
4.356 + decl String:type[64];
4.357 + decl String:name[64];
4.358 + decl String:flags[32];
4.359 + new flag_bits;
4.360 + while (SQL_FetchRow(hQuery))
4.361 + {
4.362 + SQL_FetchString(hQuery, 0, type, sizeof(type));
4.363 + SQL_FetchString(hQuery, 1, name, sizeof(name));
4.364 + SQL_FetchString(hQuery, 2, flags, sizeof(flags));
4.365 +
4.366 +#if defined _DEBUG
4.367 + PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
4.368 +#endif
4.369 +
4.370 + flag_bits = ReadFlagString(flags);
4.371 + if (StrEqual(type, "command"))
4.372 + {
4.373 + AddCommandOverride(name, Override_Command, flag_bits);
4.374 + } else if (StrEqual(type, "group")) {
4.375 + AddCommandOverride(name, Override_CommandGroup, flag_bits);
4.376 + }
4.377 + }
4.378 +
4.379 + CloseHandle(hQuery);
4.380 +}
4.381 +
4.382 +stock GroupId:UTIL_FindGroupInCache(Handle:group_list, id)
4.383 +{
4.384 + new size = GetArraySize(group_list);
4.385 +
4.386 + for (new i=0; i<size; i++)
4.387 + {
4.388 + decl data[3];
4.389 + GetArrayArray(group_list, i, data);
4.390 +
4.391 + if (data[0] == id)
4.392 + {
4.393 + return GroupId:data[1];
4.394 + }
4.395 + }
4.396 +
4.397 + return INVALID_GROUP_ID;
4.398 +}
4.399 +
4.400 +/**
4.401 + * Breaks a comma-delimited string into a list of numbers, returning a new
4.402 + * dynamic array.
4.403 + *
4.404 + * @param text The string to split.
4.405 + * @return A new array Handle which must be closed, or
4.406 + * INVALID_HANDLE on no strings found.
4.407 + */
4.408 +stock Handle:UTIL_ExplodeNumberString(const String:text[])
4.409 +{
4.410 + new Handle:array = INVALID_HANDLE;
4.411 + decl String:buffer[32];
4.412 + new reloc_idx, idx;
4.413 +
4.414 + while ((idx = SplitString(text[reloc_idx], ",", buffer, sizeof(buffer))) != -1)
4.415 + {
4.416 + reloc_idx += idx;
4.417 + if (text[reloc_idx] == '\0')
4.418 + {
4.419 + break;
4.420 + }
4.421 + if (array == INVALID_HANDLE)
4.422 + {
4.423 + array = CreateArray();
4.424 + }
4.425 + PushArrayCell(array, StringToInt(buffer));
4.426 + }
4.427 +
4.428 + if (text[reloc_idx] != '\0')
4.429 + {
4.430 + if (array == INVALID_HANDLE)
4.431 + {
4.432 + array = CreateArray();
4.433 + }
4.434 + PushArrayCell(array, StringToInt(text[reloc_idx]));
4.435 + }
4.436 +
4.437 + return array;
4.438 +}
4.439 +