1.1 --- a/plugins/admin-sql-threaded.sp Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,855 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod SQL Admins Plugin (Threaded)
1.8 - * Fetches admins from an SQL database dynamically.
1.9 - *
1.10 - * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
1.11 - * =============================================================================
1.12 - *
1.13 - * This program is free software; you can redistribute it and/or modify it under
1.14 - * the terms of the GNU General Public License, version 3.0, as published by the
1.15 - * Free Software Foundation.
1.16 - *
1.17 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.18 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.19 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.20 - * details.
1.21 - *
1.22 - * You should have received a copy of the GNU General Public License along with
1.23 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.24 - *
1.25 - * As a special exception, AlliedModders LLC gives you permission to link the
1.26 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.27 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.28 - * by the Valve Corporation. You must obey the GNU General Public License in
1.29 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.30 - * this exception to all derivative works. AlliedModders LLC defines further
1.31 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.32 - * or <http://www.sourcemod.net/license.php>.
1.33 - *
1.34 - * Version: $Id$
1.35 - */
1.36 -
1.37 -/* We like semicolons */
1.38 -#pragma semicolon 1
1.39 -
1.40 -#include <sourcemod>
1.41 -
1.42 -public Plugin:myinfo =
1.43 -{
1.44 - name = "SQL Admins (Threaded)",
1.45 - author = "AlliedModders LLC",
1.46 - description = "Reads admins from SQL dynamically",
1.47 - version = SOURCEMOD_VERSION,
1.48 - url = "http://www.sourcemod.net/"
1.49 -};
1.50 -
1.51 -/**
1.52 - * Notes:
1.53 - *
1.54 - * 1) All queries in here are high priority. This is because the admin stuff
1.55 - * is very important. Do not take this to mean that in your script,
1.56 - * everything should be high priority.
1.57 - *
1.58 - * 2) All callbacks are locked with "sequence numbers." This is to make sure
1.59 - * that multiple calls to sm_reloadadmins and the like do not make us
1.60 - * store the results from two or more callbacks accidentally. Instead, we
1.61 - * check the sequence number in each callback with the current "allowed"
1.62 - * sequence number, and if it doesn't match, the callback is cancelled.
1.63 - *
1.64 - * 3) Sequence numbers for groups and overrides are not cleared unless there
1.65 - * was a 100% success in the fetch. This is so we can potentially implement
1.66 - * connection retries in the future.
1.67 - *
1.68 - * 4) Sequence numbers for the user cache are ignored except for being
1.69 - * non-zero, which means players in-game should be re-checked for admin
1.70 - * powers.
1.71 - */
1.72 -
1.73 -new Handle:hDatabase = INVALID_HANDLE; /** Database connection */
1.74 -new g_sequence = 0; /** Global unique sequence number */
1.75 -new ConnectLock = 0; /** Connect sequence number */
1.76 -new RebuildCachePart[3] = {0}; /** Cache part sequence numbers */
1.77 -new PlayerSeq[MAXPLAYERS+1]; /** Player-specific sequence numbers */
1.78 -new bool:PlayerAuth[MAXPLAYERS+1]; /** Whether a player has been "pre-authed" */
1.79 -
1.80 -#define _DEBUG
1.81 -
1.82 -public OnMapEnd()
1.83 -{
1.84 - /**
1.85 - * Clean up on map end just so we can start a fresh connection when we need it later.
1.86 - */
1.87 - if (hDatabase != INVALID_HANDLE)
1.88 - {
1.89 - CloseHandle(hDatabase);
1.90 - hDatabase = INVALID_HANDLE;
1.91 - }
1.92 -}
1.93 -
1.94 -public bool:OnClientConnect(client, String:rejectmsg[], maxlen)
1.95 -{
1.96 - PlayerSeq[client] = 0;
1.97 - PlayerAuth[client] = false;
1.98 - return true;
1.99 -}
1.100 -
1.101 -public OnClientDisconnect(client)
1.102 -{
1.103 - PlayerSeq[client] = 0;
1.104 - PlayerAuth[client] = false;
1.105 -}
1.106 -
1.107 -public OnDatabaseConnect(Handle:owner, Handle:hndl, const String:error[], any:data)
1.108 -{
1.109 -#if defined _DEBUG
1.110 - PrintToServer("OnDatabaseConnect(%x,%x,%d) ConnectLock=%d", owner, hndl, data, ConnectLock);
1.111 -#endif
1.112 -
1.113 - /**
1.114 - * If this happens to be an old connection request, ignore it.
1.115 - */
1.116 - if (data != ConnectLock || hDatabase != INVALID_HANDLE)
1.117 - {
1.118 - if (hndl != INVALID_HANDLE)
1.119 - {
1.120 - CloseHandle(hndl);
1.121 - }
1.122 - return;
1.123 - }
1.124 -
1.125 - ConnectLock = 0;
1.126 - hDatabase = hndl;
1.127 -
1.128 - /**
1.129 - * See if the connection is valid. If not, don't un-mark the caches
1.130 - * as needing rebuilding, in case the next connection request works.
1.131 - */
1.132 - if (hDatabase == INVALID_HANDLE)
1.133 - {
1.134 - LogError("Failed to connect to database: %s", error);
1.135 - return;
1.136 - }
1.137 -
1.138 - /**
1.139 - * See if we need to get any of the cache stuff now.
1.140 - */
1.141 - new sequence;
1.142 - if ((sequence = RebuildCachePart[_:AdminCache_Overrides]) != 0)
1.143 - {
1.144 - FetchOverrides(hDatabase, sequence);
1.145 - }
1.146 - if ((sequence = RebuildCachePart[_:AdminCache_Groups]) != 0)
1.147 - {
1.148 - FetchGroups(hDatabase, sequence);
1.149 - }
1.150 - if ((sequence = RebuildCachePart[_:AdminCache_Admins]) != 0)
1.151 - {
1.152 - FetchUsersWeCan(hDatabase);
1.153 - }
1.154 -}
1.155 -
1.156 -RequestDatabaseConnection()
1.157 -{
1.158 - ConnectLock = ++g_sequence;
1.159 - if (SQL_CheckConfig("admins"))
1.160 - {
1.161 - SQL_TConnect(OnDatabaseConnect, "admins", ConnectLock);
1.162 - } else {
1.163 - SQL_TConnect(OnDatabaseConnect, "default", ConnectLock);
1.164 - }
1.165 -}
1.166 -
1.167 -public OnRebuildAdminCache(AdminCachePart:part)
1.168 -{
1.169 - /**
1.170 - * Mark this part of the cache as being rebuilt. This is used by the
1.171 - * callback system to determine whether the results should still be
1.172 - * used.
1.173 - */
1.174 - new sequence = ++g_sequence;
1.175 - RebuildCachePart[_:part] = sequence;
1.176 -
1.177 - /**
1.178 - * If we don't have a database connection, we can't do any lookups just yet.
1.179 - */
1.180 - if (!hDatabase)
1.181 - {
1.182 - /**
1.183 - * Ask for a new connection if we need it.
1.184 - */
1.185 - if (!ConnectLock)
1.186 - {
1.187 - RequestDatabaseConnection();
1.188 - }
1.189 - return;
1.190 - }
1.191 -
1.192 - if (part == AdminCache_Overrides)
1.193 - {
1.194 - FetchOverrides(hDatabase, sequence);
1.195 - } else if (part == AdminCache_Groups) {
1.196 - FetchGroups(hDatabase, sequence);
1.197 - } else if (part == AdminCache_Admins) {
1.198 - FetchUsersWeCan(hDatabase);
1.199 - }
1.200 -}
1.201 -
1.202 -public Action:OnClientPreAdminCheck(client)
1.203 -{
1.204 - PlayerAuth[client] = true;
1.205 -
1.206 - /**
1.207 - * Play nice with other plugins. If there's no database, don't delay the
1.208 - * connection process. Unfortunately, we can't attempt anything else and
1.209 - * we just have to hope either the database is waiting or someone will type
1.210 - * sm_reloadadmins.
1.211 - */
1.212 - if (hDatabase == INVALID_HANDLE)
1.213 - {
1.214 - return Plugin_Continue;
1.215 - }
1.216 -
1.217 - /**
1.218 - * Similarly, if the cache is in the process of being rebuilt, don't delay
1.219 - * the user's normal connection flow. The database will soon auth the user
1.220 - * normally.
1.221 - */
1.222 - if (RebuildCachePart[_:AdminCache_Admins] != 0)
1.223 - {
1.224 - return Plugin_Continue;
1.225 - }
1.226 -
1.227 - /**
1.228 - * If someone has already assigned an admin ID (bad bad bad), don't
1.229 - * bother waiting.
1.230 - */
1.231 - if (GetUserAdmin(client) != INVALID_ADMIN_ID)
1.232 - {
1.233 - return Plugin_Continue;
1.234 - }
1.235 -
1.236 - FetchUser(hDatabase, client);
1.237 -
1.238 - return Plugin_Handled;
1.239 -}
1.240 -
1.241 -public OnReceiveUserGroups(Handle:owner, Handle:hndl, const String:error[], any:data)
1.242 -{
1.243 - new Handle:pk = Handle:data;
1.244 - ResetPack(pk);
1.245 -
1.246 - new client = ReadPackCell(pk);
1.247 - new sequence = ReadPackCell(pk);
1.248 -
1.249 - /**
1.250 - * Make sure it's the same client.
1.251 - */
1.252 - if (PlayerSeq[client] != sequence)
1.253 - {
1.254 - CloseHandle(pk);
1.255 - return;
1.256 - }
1.257 -
1.258 - new AdminId:adm = AdminId:ReadPackCell(pk);
1.259 -
1.260 - /**
1.261 - * Someone could have sneakily changed the admin id while we waited.
1.262 - */
1.263 - if (GetUserAdmin(client) != adm)
1.264 - {
1.265 - NotifyPostAdminCheck(client);
1.266 - CloseHandle(pk);
1.267 - return;
1.268 - }
1.269 -
1.270 - /**
1.271 - * See if we got results.
1.272 - */
1.273 - if (hndl == INVALID_HANDLE)
1.274 - {
1.275 - decl String:query[255];
1.276 - ReadPackString(pk, query, sizeof(query));
1.277 - LogError("SQL error receiving user: %s", error);
1.278 - LogError("Query dump: %s", query);
1.279 - NotifyPostAdminCheck(client);
1.280 - CloseHandle(pk);
1.281 - return;
1.282 - }
1.283 -
1.284 - decl String:name[80];
1.285 - new GroupId:gid;
1.286 -
1.287 - while (SQL_FetchRow(hndl))
1.288 - {
1.289 - SQL_FetchString(hndl, 0, name, sizeof(name));
1.290 -
1.291 - if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
1.292 - {
1.293 - continue;
1.294 - }
1.295 -
1.296 -#if defined _DEBUG
1.297 - PrintToServer("Binding user group (%d, %d, %d, %s, %d)", client, sequence, adm, name, gid);
1.298 -#endif
1.299 -
1.300 - AdminInheritGroup(adm, gid);
1.301 - }
1.302 -
1.303 - /**
1.304 - * We're DONE! Omg.
1.305 - */
1.306 - NotifyPostAdminCheck(client);
1.307 - CloseHandle(pk);
1.308 -}
1.309 -
1.310 -public OnReceiveUser(Handle:owner, Handle:hndl, const String:error[], any:data)
1.311 -{
1.312 - new Handle:pk = Handle:data;
1.313 - ResetPack(pk);
1.314 -
1.315 - new client = ReadPackCell(pk);
1.316 -
1.317 - /**
1.318 - * Check if this is the latest result request.
1.319 - */
1.320 - new sequence = ReadPackCell(pk);
1.321 - if (PlayerSeq[client] != sequence)
1.322 - {
1.323 - /* Discard everything, since we're out of sequence. */
1.324 - CloseHandle(pk);
1.325 - return;
1.326 - }
1.327 -
1.328 - /**
1.329 - * If we need to use the results, make sure they succeeded.
1.330 - */
1.331 - if (hndl == INVALID_HANDLE)
1.332 - {
1.333 - decl String:query[255];
1.334 - ReadPackString(pk, query, sizeof(query));
1.335 - LogError("SQL error receiving user: %s", error);
1.336 - LogError("Query dump: %s", query);
1.337 - RunAdminCacheChecks(client);
1.338 - NotifyPostAdminCheck(client);
1.339 - CloseHandle(pk);
1.340 - return;
1.341 - }
1.342 -
1.343 - new num_accounts = SQL_GetRowCount(hndl);
1.344 - if (num_accounts == 0)
1.345 - {
1.346 - RunAdminCacheChecks(client);
1.347 - NotifyPostAdminCheck(client);
1.348 - CloseHandle(pk);
1.349 - return;
1.350 - }
1.351 -
1.352 - decl String:authtype[16];
1.353 - decl String:identity[80];
1.354 - decl String:password[80];
1.355 - decl String:flags[32];
1.356 - decl String:name[80];
1.357 - new AdminId:adm, id;
1.358 - new immunity;
1.359 -
1.360 - /**
1.361 - * Cache user info -- [0] = db id, [1] = cache id, [2] = groups
1.362 - */
1.363 - decl user_lookup[num_accounts][3];
1.364 - new total_users = 0;
1.365 -
1.366 - while (SQL_FetchRow(hndl))
1.367 - {
1.368 - id = SQL_FetchInt(hndl, 0);
1.369 - SQL_FetchString(hndl, 1, authtype, sizeof(authtype));
1.370 - SQL_FetchString(hndl, 2, identity, sizeof(identity));
1.371 - SQL_FetchString(hndl, 3, password, sizeof(password));
1.372 - SQL_FetchString(hndl, 4, flags, sizeof(flags));
1.373 - SQL_FetchString(hndl, 5, name, sizeof(name));
1.374 - immunity = SQL_FetchInt(hndl, 7);
1.375 -
1.376 - /* For dynamic admins we clear anything already in the cache. */
1.377 - if ((adm = FindAdminByIdentity(authtype, identity)) != INVALID_ADMIN_ID)
1.378 - {
1.379 - RemoveAdmin(adm);
1.380 - }
1.381 -
1.382 - adm = CreateAdmin(name);
1.383 - if (!BindAdminIdentity(adm, authtype, identity))
1.384 - {
1.385 - LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
1.386 - continue;
1.387 - }
1.388 -
1.389 - user_lookup[total_users][0] = id;
1.390 - user_lookup[total_users][1] = _:adm;
1.391 - user_lookup[total_users][2] = SQL_FetchInt(hndl, 6);
1.392 - total_users++;
1.393 -
1.394 -#if defined _DEBUG
1.395 - 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]);
1.396 -#endif
1.397 -
1.398 - /* See if this admin wants a password */
1.399 - if (password[0] != '\0')
1.400 - {
1.401 - SetAdminPassword(adm, password);
1.402 - }
1.403 -
1.404 - SetAdminImmunityLevel(adm, immunity);
1.405 -
1.406 - /* Apply each flag */
1.407 - new len = strlen(flags);
1.408 - new AdminFlag:flag;
1.409 - for (new i=0; i<len; i++)
1.410 - {
1.411 - if (!FindFlagByChar(flags[i], flag))
1.412 - {
1.413 - continue;
1.414 - }
1.415 - SetAdminFlag(adm, flag, true);
1.416 - }
1.417 - }
1.418 -
1.419 - /**
1.420 - * Try binding the user.
1.421 - */
1.422 - new group_count = 0;
1.423 - RunAdminCacheChecks(client);
1.424 - adm = GetUserAdmin(client);
1.425 - id = 0;
1.426 -
1.427 -
1.428 - for (new i=0; i<total_users; i++)
1.429 - {
1.430 - if (user_lookup[i][1] == _:adm)
1.431 - {
1.432 - id = user_lookup[i][0];
1.433 - group_count = user_lookup[i][2];
1.434 - break;
1.435 - }
1.436 - }
1.437 -
1.438 -#if defined _DEBUG
1.439 - PrintToServer("Binding client (%d, %d) resulted in: (%d, %d, %d)", client, sequence, id, adm, group_count);
1.440 -#endif
1.441 -
1.442 - /**
1.443 - * If we can't verify that we assigned a database admin, or the user has no
1.444 - * groups, don't bother doing anything.
1.445 - */
1.446 - if (!id || !group_count)
1.447 - {
1.448 - NotifyPostAdminCheck(client);
1.449 - CloseHandle(pk);
1.450 - return;
1.451 - }
1.452 -
1.453 - /**
1.454 - * The user has groups -- we need to fetch them!
1.455 - */
1.456 - decl String:query[255];
1.457 - 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);
1.458 -
1.459 - ResetPack(pk);
1.460 - WritePackCell(pk, client);
1.461 - WritePackCell(pk, sequence);
1.462 - WritePackCell(pk, _:adm);
1.463 - WritePackString(pk, query);
1.464 -
1.465 - SQL_TQuery(owner, OnReceiveUserGroups, query, pk, DBPrio_High);
1.466 -}
1.467 -
1.468 -FetchUser(Handle:db, client)
1.469 -{
1.470 - decl String:name[65];
1.471 - decl String:safe_name[140];
1.472 - decl String:steamid[32];
1.473 - decl String:ipaddr[24];
1.474 -
1.475 - /**
1.476 - * Get authentication information from the client.
1.477 - */
1.478 - GetClientName(client, name, sizeof(name));
1.479 - GetClientIP(client, ipaddr, sizeof(ipaddr));
1.480 -
1.481 - steamid[0] = '\0';
1.482 - if (GetClientAuthString(client, steamid, sizeof(steamid)))
1.483 - {
1.484 - if (StrEqual(steamid, "STEAM_ID_LAN"))
1.485 - {
1.486 - steamid[0] = '\0';
1.487 - }
1.488 - }
1.489 -
1.490 - SQL_QuoteString(db, name, safe_name, sizeof(safe_name));
1.491 -
1.492 - /**
1.493 - * Construct the query using the information the user gave us.
1.494 - */
1.495 - decl String:query[512];
1.496 - new len = 0;
1.497 -
1.498 - 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");
1.499 - len += Format(query[len], sizeof(query)-len, " FROM sm_admins a LEFT JOIN sm_admins_groups ag ON a.id = ag.admin_id WHERE ");
1.500 - len += Format(query[len], sizeof(query)-len, " (a.authtype = 'ip' AND a.identity = '%s')", ipaddr);
1.501 - len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'name' AND a.identity = '%s')", safe_name);
1.502 - if (steamid[0] != '\0')
1.503 - {
1.504 - len += Format(query[len], sizeof(query)-len, " OR (a.authtype = 'steam' AND a.identity = '%s')", steamid);
1.505 - }
1.506 - len += Format(query[len], sizeof(query)-len, " GROUP BY a.id");
1.507 -
1.508 - /**
1.509 - * Send the actual query.
1.510 - */
1.511 - PlayerSeq[client] = ++g_sequence;
1.512 -
1.513 - new Handle:pk;
1.514 - pk = CreateDataPack();
1.515 - WritePackCell(pk, client);
1.516 - WritePackCell(pk, PlayerSeq[client]);
1.517 - WritePackString(pk, query);
1.518 -
1.519 -#if defined _DEBUG
1.520 - PrintToServer("Sending user query: %s", query);
1.521 -#endif
1.522 -
1.523 - SQL_TQuery(db, OnReceiveUser, query, pk, DBPrio_High);
1.524 -}
1.525 -
1.526 -FetchUsersWeCan(Handle:db)
1.527 -{
1.528 - new max_clients = GetMaxClients();
1.529 -
1.530 - for (new i=1; i<=max_clients; i++)
1.531 - {
1.532 - if (PlayerAuth[i] && GetUserAdmin(i) == INVALID_ADMIN_ID)
1.533 - {
1.534 - FetchUser(db, i);
1.535 - }
1.536 - }
1.537 -
1.538 - /**
1.539 - * This round of updates is done. Go in peace.
1.540 - */
1.541 - RebuildCachePart[_:AdminCache_Admins] = 0;
1.542 -}
1.543 -
1.544 -
1.545 -public OnReceiveGroupImmunity(Handle:owner, Handle:hndl, const String:error[], any:data)
1.546 -{
1.547 - new Handle:pk = Handle:data;
1.548 - ResetPack(pk);
1.549 -
1.550 - /**
1.551 - * Check if this is the latest result request.
1.552 - */
1.553 - new sequence = ReadPackCell(pk);
1.554 - if (RebuildCachePart[_:AdminCache_Groups] != sequence)
1.555 - {
1.556 - /* Discard everything, since we're out of sequence. */
1.557 - CloseHandle(pk);
1.558 - return;
1.559 - }
1.560 -
1.561 - /**
1.562 - * If we need to use the results, make sure they succeeded.
1.563 - */
1.564 - if (hndl == INVALID_HANDLE)
1.565 - {
1.566 - decl String:query[255];
1.567 - ReadPackString(pk, query, sizeof(query));
1.568 - LogError("SQL error receiving group immunity: %s", error);
1.569 - LogError("Query dump: %s", query);
1.570 - CloseHandle(pk);
1.571 - return;
1.572 - }
1.573 -
1.574 - /* We're done with the pack forever. */
1.575 - CloseHandle(pk);
1.576 -
1.577 - while (SQL_FetchRow(hndl))
1.578 - {
1.579 - decl String:group1[80];
1.580 - decl String:group2[80];
1.581 - new GroupId:gid1, GroupId:gid2;
1.582 -
1.583 - SQL_FetchString(hndl, 0, group1, sizeof(group1));
1.584 - SQL_FetchString(hndl, 1, group2, sizeof(group2));
1.585 -
1.586 - if (((gid1 = FindAdmGroup(group1)) == INVALID_GROUP_ID)
1.587 - || (gid2 = FindAdmGroup(group2)) == INVALID_GROUP_ID)
1.588 - {
1.589 - continue;
1.590 - }
1.591 -
1.592 - SetAdmGroupImmuneFrom(gid1, gid2);
1.593 -#if defined _DEBUG
1.594 - PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", gid1, gid2);
1.595 -#endif
1.596 - }
1.597 -
1.598 - /* Clear the sequence so another connect doesn't refetch */
1.599 - RebuildCachePart[_:AdminCache_Groups] = 0;
1.600 -}
1.601 -
1.602 -public OnReceiveGroupOverrides(Handle:owner, Handle:hndl, const String:error[], any:data)
1.603 -{
1.604 - new Handle:pk = Handle:data;
1.605 - ResetPack(pk);
1.606 -
1.607 - /**
1.608 - * Check if this is the latest result request.
1.609 - */
1.610 - new sequence = ReadPackCell(pk);
1.611 - if (RebuildCachePart[_:AdminCache_Groups] != sequence)
1.612 - {
1.613 - /* Discard everything, since we're out of sequence. */
1.614 - CloseHandle(pk);
1.615 - return;
1.616 - }
1.617 -
1.618 - /**
1.619 - * If we need to use the results, make sure they succeeded.
1.620 - */
1.621 - if (hndl == INVALID_HANDLE)
1.622 - {
1.623 - decl String:query[255];
1.624 - ReadPackString(pk, query, sizeof(query));
1.625 - LogError("SQL error receiving group overrides: %s", error);
1.626 - LogError("Query dump: %s", query);
1.627 - CloseHandle(pk);
1.628 - return;
1.629 - }
1.630 -
1.631 - /**
1.632 - * Fetch the overrides.
1.633 - */
1.634 - decl String:name[80];
1.635 - decl String:type[16];
1.636 - decl String:command[64];
1.637 - decl String:access[16];
1.638 - new GroupId:gid;
1.639 - while (SQL_FetchRow(hndl))
1.640 - {
1.641 - SQL_FetchString(hndl, 0, name, sizeof(name));
1.642 - SQL_FetchString(hndl, 1, type, sizeof(type));
1.643 - SQL_FetchString(hndl, 2, command, sizeof(command));
1.644 - SQL_FetchString(hndl, 3, access, sizeof(access));
1.645 -
1.646 - /* Find the group. This is actually faster than doing the ID lookup. */
1.647 - if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
1.648 - {
1.649 - /* Oh well, just ignore it. */
1.650 - continue;
1.651 - }
1.652 -
1.653 - new OverrideType:o_type = Override_Command;
1.654 - if (StrEqual(type, "group"))
1.655 - {
1.656 - o_type = Override_CommandGroup;
1.657 - }
1.658 -
1.659 - new OverrideRule:o_rule = Command_Deny;
1.660 - if (StrEqual(access, "allow"))
1.661 - {
1.662 - o_rule = Command_Allow;
1.663 - }
1.664 -
1.665 -#if defined _DEBUG
1.666 - PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", gid, command, o_type, o_rule);
1.667 -#endif
1.668 -
1.669 - AddAdmGroupCmdOverride(gid, command, o_type, o_rule);
1.670 - }
1.671 -
1.672 - /**
1.673 - * It's time to get the group immunity list.
1.674 - */
1.675 - new len = 0;
1.676 - decl String:query[256];
1.677 - len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
1.678 - len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
1.679 - len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
1.680 -
1.681 - ResetPack(pk);
1.682 - WritePackCell(pk, sequence);
1.683 - WritePackString(pk, query);
1.684 -
1.685 - SQL_TQuery(owner, OnReceiveGroupImmunity, query, pk, DBPrio_High);
1.686 -}
1.687 -
1.688 -public OnReceiveGroups(Handle:owner, Handle:hndl, const String:error[], any:data)
1.689 -{
1.690 - new Handle:pk = Handle:data;
1.691 - ResetPack(pk);
1.692 -
1.693 - /**
1.694 - * Check if this is the latest result request.
1.695 - */
1.696 - new sequence = ReadPackCell(pk);
1.697 - if (RebuildCachePart[_:AdminCache_Groups] != sequence)
1.698 - {
1.699 - /* Discard everything, since we're out of sequence. */
1.700 - CloseHandle(pk);
1.701 - return;
1.702 - }
1.703 -
1.704 - /**
1.705 - * If we need to use the results, make sure they succeeded.
1.706 - */
1.707 - if (hndl == INVALID_HANDLE)
1.708 - {
1.709 - decl String:query[255];
1.710 - ReadPackString(pk, query, sizeof(query));
1.711 - LogError("SQL error receiving groups: %s", error);
1.712 - LogError("Query dump: %s", query);
1.713 - CloseHandle(pk);
1.714 - return;
1.715 - }
1.716 -
1.717 - /**
1.718 - * Now start fetching groups.
1.719 - */
1.720 - decl String:flags[32];
1.721 - decl String:name[128];
1.722 - new immunity;
1.723 - while (SQL_FetchRow(hndl))
1.724 - {
1.725 - SQL_FetchString(hndl, 0, flags, sizeof(flags));
1.726 - SQL_FetchString(hndl, 1, name, sizeof(name));
1.727 - immunity = SQL_FetchInt(hndl, 2);
1.728 -
1.729 -#if defined _DEBUG
1.730 - PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name);
1.731 -#endif
1.732 -
1.733 - /* Find or create the group */
1.734 - new GroupId:gid;
1.735 - if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
1.736 - {
1.737 - gid = CreateAdmGroup(name);
1.738 - }
1.739 -
1.740 - /* Add flags from the database to the group */
1.741 - new num_flag_chars = strlen(flags);
1.742 - for (new i=0; i<num_flag_chars; i++)
1.743 - {
1.744 - decl AdminFlag:flag;
1.745 - if (!FindFlagByChar(flags[i], flag))
1.746 - {
1.747 - continue;
1.748 - }
1.749 - SetAdmGroupAddFlag(gid, flag, true);
1.750 - }
1.751 -
1.752 - SetAdmGroupImmunityLevel(gid, immunity);
1.753 - }
1.754 -
1.755 - /**
1.756 - * It's time to get the group override list.
1.757 - */
1.758 - decl String:query[255];
1.759 - Format(query,
1.760 - sizeof(query),
1.761 - "SELECT g.name, og.type, og.name, og.access FROM sm_group_overrides og JOIN sm_groups g ON og.group_id = g.id ORDER BY g.id DESC");
1.762 -
1.763 - ResetPack(pk);
1.764 - WritePackCell(pk, sequence);
1.765 - WritePackString(pk, query);
1.766 -
1.767 - SQL_TQuery(owner, OnReceiveGroupOverrides, query, pk, DBPrio_High);
1.768 -}
1.769 -
1.770 -FetchGroups(Handle:db, sequence)
1.771 -{
1.772 - decl String:query[255];
1.773 - new Handle:pk;
1.774 -
1.775 - Format(query, sizeof(query), "SELECT flags, name, immunity_level FROM sm_groups");
1.776 -
1.777 - pk = CreateDataPack();
1.778 - WritePackCell(pk, sequence);
1.779 - WritePackString(pk, query);
1.780 -
1.781 - SQL_TQuery(db, OnReceiveGroups, query, pk, DBPrio_High);
1.782 -}
1.783 -
1.784 -public OnReceiveOverrides(Handle:owner, Handle:hndl, const String:error[], any:data)
1.785 -{
1.786 - new Handle:pk = Handle:data;
1.787 - ResetPack(pk);
1.788 -
1.789 - /**
1.790 - * Check if this is the latest result request.
1.791 - */
1.792 - new sequence = ReadPackCell(pk);
1.793 - if (RebuildCachePart[_:AdminCache_Overrides] != sequence)
1.794 - {
1.795 - /* Discard everything, since we're out of sequence. */
1.796 - CloseHandle(pk);
1.797 - return;
1.798 - }
1.799 -
1.800 - /**
1.801 - * If we need to use the results, make sure they succeeded.
1.802 - */
1.803 - if (hndl == INVALID_HANDLE)
1.804 - {
1.805 - decl String:query[255];
1.806 - ReadPackString(pk, query, sizeof(query));
1.807 - LogError("SQL error receiving overrides: %s", error);
1.808 - LogError("Query dump: %s", query);
1.809 - CloseHandle(pk);
1.810 - return;
1.811 - }
1.812 -
1.813 - /**
1.814 - * We're done with you, now.
1.815 - */
1.816 - CloseHandle(pk);
1.817 -
1.818 - decl String:type[64];
1.819 - decl String:name[64];
1.820 - decl String:flags[32];
1.821 - new flag_bits;
1.822 - while (SQL_FetchRow(hndl))
1.823 - {
1.824 - SQL_FetchString(hndl, 0, type, sizeof(type));
1.825 - SQL_FetchString(hndl, 1, name, sizeof(name));
1.826 - SQL_FetchString(hndl, 2, flags, sizeof(flags));
1.827 -
1.828 -#if defined _DEBUG
1.829 - PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
1.830 -#endif
1.831 -
1.832 - flag_bits = ReadFlagString(flags);
1.833 - if (StrEqual(type, "command"))
1.834 - {
1.835 - AddCommandOverride(name, Override_Command, flag_bits);
1.836 - } else if (StrEqual(type, "group")) {
1.837 - AddCommandOverride(name, Override_CommandGroup, flag_bits);
1.838 - }
1.839 - }
1.840 -
1.841 - /* Clear the sequence so another connect doesn't refetch */
1.842 - RebuildCachePart[_:AdminCache_Overrides] = 0;
1.843 -}
1.844 -
1.845 -FetchOverrides(Handle:db, sequence)
1.846 -{
1.847 - decl String:query[255];
1.848 - new Handle:pk;
1.849 -
1.850 - Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
1.851 -
1.852 - pk = CreateDataPack();
1.853 - WritePackCell(pk, sequence);
1.854 - WritePackString(pk, query);
1.855 -
1.856 - SQL_TQuery(db, OnReceiveOverrides, query, pk, DBPrio_High);
1.857 -}
1.858 -