plugins/admin-sql-prefetch.sp
author David Anderson <dvander@alliedmods.net>
Mon Aug 12 00:22:54 2013 +0100 (2013-08-12)
changeset 3990 c7fb79059d7a
parent 2641 f56dd4215df6
permissions -rw-r--r--
Eliminate InfoVars::cip (bug 5844 part 7, r=ds).
dvander@1316
     1
/**
ds@1330
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
ds@1330
     4
 * SourceMod SQL Admins Plugin (Prefetch)
dvander@1316
     5
 * Prefetches admins from an SQL database without threading.
ds@1330
     6
 *
ds@1947
     7
 * SourceMod (C)2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     8
 * =============================================================================
dvander@1316
     9
 *
ds@1330
    10
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
    11
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    12
 * Free Software Foundation.
ds@1330
    13
 * 
ds@1330
    14
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    17
 * details.
dvander@1316
    18
 *
ds@1330
    19
 * You should have received a copy of the GNU General Public License along with
ds@1330
    20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
ds@1330
    21
 *
ds@1330
    22
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    23
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    24
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    25
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    26
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    27
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    28
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    29
 * or <http://www.sourcemod.net/license.php>.
dvander@1316
    30
 *
dvander@1316
    31
 * Version: $Id$
dvander@1316
    32
 */
dvander@1316
    33
dvander@1316
    34
/* We like semicolons */
dvander@1316
    35
#pragma semicolon 1
dvander@1316
    36
dvander@1316
    37
#include <sourcemod>
dvander@1316
    38
dvander@1316
    39
public Plugin:myinfo = 
dvander@1316
    40
{
dvander@1317
    41
	name = "SQL Admins (Prefetch)",
dvander@1316
    42
	author = "AlliedModders LLC",
dvander@1316
    43
	description = "Reads all admins from SQL",
dvander@1316
    44
	version = SOURCEMOD_VERSION,
dvander@1316
    45
	url = "http://www.sourcemod.net/"
dvander@1316
    46
};
dvander@1316
    47
dvander@1316
    48
public OnRebuildAdminCache(AdminCachePart:part)
dvander@1316
    49
{
dvander@1316
    50
	/* First try to get a database connection */
dvander@1316
    51
	decl String:error[255];
dvander@1324
    52
	new Handle:db;
dvander@1324
    53
	
dvander@1324
    54
	if (SQL_CheckConfig("admins"))
dvander@1324
    55
	{
dvander@1324
    56
		db = SQL_Connect("admins", true, error, sizeof(error));
dvander@1324
    57
	} else {
dvander@1324
    58
		db = SQL_Connect("default", true, error, sizeof(error));
dvander@1324
    59
	}
dvander@1324
    60
	
dvander@1316
    61
	if (db == INVALID_HANDLE)
dvander@1316
    62
	{
dvander@1316
    63
		LogError("Could not connect to database \"default\": %s", error);
dvander@1316
    64
		return;
dvander@1316
    65
	}
dvander@1316
    66
	
dvander@1316
    67
	if (part == AdminCache_Overrides)
dvander@1316
    68
	{
dvander@1316
    69
		FetchOverrides(db);
dvander@1316
    70
	} else if (part == AdminCache_Groups) {
dvander@1316
    71
		FetchGroups(db);
dvander@1316
    72
	} else if (part == AdminCache_Admins) {
dvander@1316
    73
		FetchUsers(db);
dvander@1316
    74
	}
dvander@1316
    75
	
dvander@1316
    76
	CloseHandle(db);
dvander@1316
    77
}
dvander@1316
    78
dvander@1316
    79
FetchUsers(Handle:db)
dvander@1316
    80
{
dvander@1316
    81
	decl String:query[255], String:error[255];
floormaster@2641
    82
	new Handle:hQuery;
floormaster@2641
    83
dvander@1403
    84
	Format(query, sizeof(query), "SELECT id, authtype, identity, password, flags, name, immunity FROM sm_admins");
dvander@1316
    85
	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
dvander@1316
    86
	{
dvander@1316
    87
		SQL_GetError(db, error, sizeof(error));
dvander@1316
    88
		LogError("FetchUsers() query failed: %s", query);
dvander@1316
    89
		LogError("Query error: %s", error);
dvander@1316
    90
		return;
dvander@1316
    91
	}
floormaster@2641
    92
dvander@1316
    93
	decl String:authtype[16];
dvander@1316
    94
	decl String:identity[80];
dvander@1316
    95
	decl String:password[80];
dvander@1316
    96
	decl String:flags[32];
dvander@1316
    97
	decl String:name[80];
dvander@1403
    98
	new immunity;
dvander@1316
    99
	new AdminId:adm, id;
floormaster@2641
   100
	new GroupId:gid;
floormaster@2641
   101
floormaster@2641
   102
	/* Keep track of a mapping from admin DB IDs to internal AdminIds to
floormaster@2641
   103
	 * enable group lookups en masse */
floormaster@2641
   104
	new Handle:htAdmins = CreateTrie();
floormaster@2641
   105
	decl String:key[16];
dvander@1316
   106
	
dvander@1316
   107
	while (SQL_FetchRow(hQuery))
dvander@1316
   108
	{
dvander@1316
   109
		id = SQL_FetchInt(hQuery, 0);
floormaster@2641
   110
		IntToString(id, key, sizeof(key));
dvander@1316
   111
		SQL_FetchString(hQuery, 1, authtype, sizeof(authtype));
dvander@1316
   112
		SQL_FetchString(hQuery, 2, identity, sizeof(identity));
dvander@1316
   113
		SQL_FetchString(hQuery, 3, password, sizeof(password));
dvander@1316
   114
		SQL_FetchString(hQuery, 4, flags, sizeof(flags));
dvander@1316
   115
		SQL_FetchString(hQuery, 5, name, sizeof(name));
dvander@1403
   116
		immunity = SQL_FetchInt(hQuery, 6);
dvander@1316
   117
		
dvander@1316
   118
		/* Use a pre-existing admin if we can */
dvander@1316
   119
		if ((adm = FindAdminByIdentity(authtype, identity)) == INVALID_ADMIN_ID)
dvander@1316
   120
		{
dvander@1316
   121
			adm = CreateAdmin(name);
dvander@1316
   122
			if (!BindAdminIdentity(adm, authtype, identity))
dvander@1316
   123
			{
dvander@1316
   124
				LogError("Could not bind prefetched SQL admin (authtype \"%s\") (identity \"%s\")", authtype, identity);
dvander@1316
   125
				continue;
dvander@1316
   126
			}
dvander@1316
   127
		}
floormaster@2641
   128
floormaster@2641
   129
		SetTrieValue(htAdmins, key, adm);
dvander@1316
   130
		
dvander@1316
   131
		#if defined _DEBUG
dvander@1403
   132
		PrintToServer("Found SQL admin (%d,%s,%s,%s,%s,%s,%d):%d", id, authtype, identity, password, flags, name, immunity, adm);
dvander@1316
   133
		#endif
dvander@1316
   134
		
dvander@1316
   135
		/* See if this admin wants a password */
dvander@1316
   136
		if (password[0] != '\0')
dvander@1316
   137
		{
dvander@1316
   138
			SetAdminPassword(adm, password);
dvander@1316
   139
		}
dvander@1316
   140
		
dvander@1316
   141
		/* Apply each flag */
dvander@1316
   142
		new len = strlen(flags);
dvander@1316
   143
		new AdminFlag:flag;
dvander@1316
   144
		for (new i=0; i<len; i++)
dvander@1316
   145
		{
dvander@1316
   146
			if (!FindFlagByChar(flags[i], flag))
dvander@1316
   147
			{
dvander@1316
   148
				continue;
dvander@1316
   149
			}
dvander@1316
   150
			SetAdminFlag(adm, flag, true);
dvander@1316
   151
		}
dvander@1403
   152
dvander@1403
   153
		SetAdminImmunityLevel(adm, immunity);
floormaster@2641
   154
	}
floormaster@2641
   155
floormaster@2641
   156
	new Handle:hGroupQuery;
floormaster@2641
   157
	Format(query, sizeof(query), "SELECT ag.admin_id AS id, g.name FROM sm_admins_groups ag JOIN sm_groups g ON ag.group_id = g.id  ORDER BY id, inherit_order ASC");
floormaster@2641
   158
	if ((hGroupQuery = SQL_Query(db, query)) == INVALID_HANDLE)
floormaster@2641
   159
	{
floormaster@2641
   160
		SQL_GetError(db, error, sizeof(error));
floormaster@2641
   161
		LogError("FetchUsers() query failed: %s", query);
floormaster@2641
   162
		LogError("Query error: %s", error);
floormaster@2641
   163
		return;
floormaster@2641
   164
	}
floormaster@2641
   165
floormaster@2641
   166
	decl String:group[80];
floormaster@2641
   167
	while (SQL_FetchRow(hGroupQuery))
floormaster@2641
   168
	{
floormaster@2641
   169
		IntToString(SQL_FetchInt(hGroupQuery, 0), key, sizeof(key));
floormaster@2641
   170
		SQL_FetchString(hGroupQuery, 1, group, sizeof(group));
floormaster@2641
   171
floormaster@2641
   172
		if (GetTrieValue(htAdmins, key, adm))
dvander@1316
   173
		{
floormaster@2641
   174
			if ((gid = FindAdmGroup(group)) == INVALID_GROUP_ID)
floormaster@2641
   175
			{
floormaster@2641
   176
				/* Group wasn't found, don't bother with it.  */
floormaster@2641
   177
				continue;
floormaster@2641
   178
			}
floormaster@2641
   179
floormaster@2641
   180
			AdminInheritGroup(adm, gid);
dvander@1316
   181
		}
dvander@1316
   182
	}
dvander@1316
   183
	
floormaster@2641
   184
	CloseHandle(hQuery);
dvander@1316
   185
	CloseHandle(hGroupQuery);
floormaster@2641
   186
	CloseHandle(htAdmins);
dvander@1316
   187
}
dvander@1316
   188
dvander@1316
   189
FetchGroups(Handle:db)
dvander@1316
   190
{
dvander@1316
   191
	decl String:query[255];
dvander@1316
   192
	new Handle:hQuery;
dvander@1316
   193
	
dvander@1403
   194
	Format(query, sizeof(query), "SELECT flags, name, immunity_level FROM sm_groups");
dvander@1316
   195
dvander@1316
   196
	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
dvander@1316
   197
	{
dvander@1316
   198
		decl String:error[255];
dvander@1316
   199
		SQL_GetError(db, error, sizeof(error));
dvander@1316
   200
		LogError("FetchGroups() query failed: %s", query);
dvander@1316
   201
		LogError("Query error: %s", error);
dvander@1316
   202
		return;
dvander@1316
   203
	}
dvander@1316
   204
	
dvander@1316
   205
	/* Now start fetching groups */
dvander@1316
   206
	decl String:flags[32];
dvander@1316
   207
	decl String:name[128];
dvander@1403
   208
	new immunity;
dvander@1316
   209
	while (SQL_FetchRow(hQuery))
dvander@1316
   210
	{
dvander@1403
   211
		SQL_FetchString(hQuery, 0, flags, sizeof(flags));
dvander@1403
   212
		SQL_FetchString(hQuery, 1, name, sizeof(name));
dvander@1403
   213
		immunity = SQL_FetchInt(hQuery, 2);
dvander@1316
   214
		
dvander@1316
   215
#if defined _DEBUG
dvander@1403
   216
		PrintToServer("Adding group (%d, %s, %s)", immunity, flags, name);
dvander@1316
   217
#endif
dvander@1316
   218
		
dvander@1316
   219
		/* Find or create the group */
dvander@1316
   220
		new GroupId:gid;
dvander@1316
   221
		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
dvander@1316
   222
		{
dvander@1316
   223
			gid = CreateAdmGroup(name);
dvander@1316
   224
		}
dvander@1316
   225
		
dvander@1316
   226
		/* Add flags from the database to the group */
dvander@1316
   227
		new num_flag_chars = strlen(flags);
dvander@1316
   228
		for (new i=0; i<num_flag_chars; i++)
dvander@1316
   229
		{
dvander@1316
   230
			decl AdminFlag:flag;
dvander@1316
   231
			if (!FindFlagByChar(flags[i], flag))
dvander@1316
   232
			{
dvander@1316
   233
				continue;
dvander@1316
   234
			}
dvander@1316
   235
			SetAdmGroupAddFlag(gid, flag, true);
dvander@1316
   236
		}
dvander@1316
   237
		
dvander@1316
   238
		/* Set the immunity level this group has */
dvander@1403
   239
		SetAdmGroupImmunityLevel(gid, immunity);
dvander@1326
   240
	}
dvander@1326
   241
	
dvander@1326
   242
	CloseHandle(hQuery);
dvander@1326
   243
	
dvander@1326
   244
	/** 
dvander@1326
   245
	 * Get immunity in a big lump.  This is a nasty query but it gets the job done.
dvander@1326
   246
	 */
dvander@1326
   247
	new len = 0;
dvander@1326
   248
	len += Format(query[len], sizeof(query)-len, "SELECT g1.name, g2.name FROM sm_group_immunity gi");
dvander@1326
   249
	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g1 ON g1.id = gi.group_id ");
dvander@1326
   250
	len += Format(query[len], sizeof(query)-len, " LEFT JOIN sm_groups g2 ON g2.id = gi.other_id");
dvander@1326
   251
	
dvander@1326
   252
	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
dvander@1326
   253
	{
dvander@1326
   254
		decl String:error[255];
dvander@1326
   255
		SQL_GetError(db, error, sizeof(error));
dvander@1326
   256
		LogError("FetchGroups() query failed: %s", query);
dvander@1326
   257
		LogError("Query error: %s", error);
dvander@1326
   258
		return;
dvander@1326
   259
	}
dvander@1326
   260
	
dvander@1326
   261
	while (SQL_FetchRow(hQuery))
dvander@1326
   262
	{
dvander@1326
   263
		decl String:group1[80];
dvander@1326
   264
		decl String:group2[80];
dvander@1326
   265
		new GroupId:gid1, GroupId:gid2;
dvander@1316
   266
		
dvander@1326
   267
		SQL_FetchString(hQuery, 0, group1, sizeof(group1));
dvander@1326
   268
		SQL_FetchString(hQuery, 1, group2, sizeof(group2));
dvander@1316
   269
		
dvander@1326
   270
		if (((gid1 = FindAdmGroup(group1)) == INVALID_GROUP_ID)
dvander@1326
   271
			|| (gid2 = FindAdmGroup(group2)) == INVALID_GROUP_ID)
dvander@1326
   272
		{
dvander@1326
   273
			continue;
dvander@1326
   274
		}
dvander@1326
   275
		
dvander@1326
   276
		SetAdmGroupImmuneFrom(gid1, gid2);
dvander@1326
   277
#if defined _DEBUG
dvander@1326
   278
		PrintToServer("SetAdmGroupImmuneFrom(%d, %d)", gid1, gid2);
dvander@1326
   279
#endif
dvander@1316
   280
	}
dvander@1316
   281
	
dvander@1316
   282
	CloseHandle(hQuery);
dvander@1316
   283
	
dvander@1326
   284
	/**
dvander@1326
   285
	 * Fetch overrides in a lump query.
dvander@1326
   286
	 */
dvander@1326
   287
	Format(query, sizeof(query), "SELECT g.name, go.type, go.name, go.access FROM sm_group_overrides go LEFT JOIN sm_groups g ON go.group_id = g.id");
dvander@1326
   288
	
dvander@1326
   289
	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
dvander@1316
   290
	{
dvander@1326
   291
		decl String:error[255];
dvander@1326
   292
		SQL_GetError(db, error, sizeof(error));
dvander@1326
   293
		LogError("FetchGroups() query failed: %s", query);
dvander@1326
   294
		LogError("Query error: %s", error);
dvander@1326
   295
		return;
dvander@1326
   296
	}
dvander@1326
   297
	
dvander@1326
   298
	decl String:type[16];
dvander@1326
   299
	decl String:cmd[64];
dvander@1326
   300
	decl String:access[16];
dvander@1326
   301
	while (SQL_FetchRow(hQuery))
dvander@1326
   302
	{
dvander@1326
   303
		SQL_FetchString(hQuery, 0, name, sizeof(name));
dvander@1326
   304
		SQL_FetchString(hQuery, 1, type, sizeof(type));
dvander@1326
   305
		SQL_FetchString(hQuery, 2, cmd, sizeof(cmd));
dvander@1326
   306
		SQL_FetchString(hQuery, 3, access, sizeof(access));
dvander@1316
   307
		
dvander@1326
   308
		new GroupId:gid;
dvander@1326
   309
		if ((gid = FindAdmGroup(name)) == INVALID_GROUP_ID)
dvander@1316
   310
		{
dvander@1326
   311
			continue;
dvander@1326
   312
		}
dvander@1316
   313
				
dvander@1326
   314
		new OverrideType:o_type = Override_Command;
dvander@1326
   315
		if (StrEqual(type, "group"))
dvander@1326
   316
		{
dvander@1326
   317
			o_type = Override_CommandGroup;
dvander@1316
   318
		}
dvander@1316
   319
		
dvander@1326
   320
		new OverrideRule:o_rule = Command_Deny;
dvander@1326
   321
		if (StrEqual(access, "allow"))
dvander@1316
   322
		{
dvander@1326
   323
			o_rule = Command_Allow;
dvander@1326
   324
		}
dvander@1316
   325
				
dvander@1326
   326
		#if defined _DEBUG
dvander@1326
   327
		PrintToServer("AddAdmGroupCmdOverride(%d, %s, %d, %d)", gid, cmd, o_type, o_rule);
dvander@1326
   328
		#endif
dvander@1319
   329
		
dvander@1326
   330
		AddAdmGroupCmdOverride(gid, cmd, o_type, o_rule);
dvander@1316
   331
	}
dvander@1318
   332
	
dvander@1326
   333
	CloseHandle(hQuery);
dvander@1316
   334
}
dvander@1316
   335
dvander@1316
   336
FetchOverrides(Handle:db)
dvander@1316
   337
{
dvander@1316
   338
	decl String:query[255];
dvander@1316
   339
	new Handle:hQuery;
dvander@1316
   340
	
dvander@1316
   341
	Format(query, sizeof(query), "SELECT type, name, flags FROM sm_overrides");
dvander@1316
   342
dvander@1316
   343
	if ((hQuery = SQL_Query(db, query)) == INVALID_HANDLE)
dvander@1316
   344
	{
dvander@1316
   345
		decl String:error[255];
dvander@1316
   346
		SQL_GetError(db, error, sizeof(error));
dvander@1316
   347
		LogError("FetchOverrides() query failed: %s", query);
dvander@1316
   348
		LogError("Query error: %s", error);
dvander@1316
   349
		return;
dvander@1316
   350
	}
dvander@1316
   351
	
dvander@1316
   352
	decl String:type[64];
dvander@1316
   353
	decl String:name[64];
dvander@1316
   354
	decl String:flags[32];
dvander@1316
   355
	new flag_bits;
dvander@1316
   356
	while (SQL_FetchRow(hQuery))
dvander@1316
   357
	{
dvander@1316
   358
		SQL_FetchString(hQuery, 0, type, sizeof(type));
dvander@1316
   359
		SQL_FetchString(hQuery, 1, name, sizeof(name));
dvander@1316
   360
		SQL_FetchString(hQuery, 2, flags, sizeof(flags));
dvander@1316
   361
		
dvander@1316
   362
#if defined _DEBUG
dvander@1316
   363
		PrintToServer("Adding override (%s, %s, %s)", type, name, flags);
dvander@1316
   364
#endif
dvander@1316
   365
		
dvander@1316
   366
		flag_bits = ReadFlagString(flags);
dvander@1316
   367
		if (StrEqual(type, "command"))
dvander@1316
   368
		{
dvander@1316
   369
			AddCommandOverride(name, Override_Command, flag_bits);
dvander@1316
   370
		} else if (StrEqual(type, "group")) {
dvander@1316
   371
			AddCommandOverride(name, Override_CommandGroup, flag_bits);
dvander@1316
   372
		}
dvander@1316
   373
	}
dvander@1316
   374
	
dvander@1316
   375
	CloseHandle(hQuery);
dvander@1316
   376
}
dvander@1403
   377