· 5 years ago · Mar 29, 2020, 01:12 AM
1#include <amxmodx>
2#include <amxmisc>
3#include <regex>
4#include <sqlx>
5
6#define MAX_PLAYERS 32
7
8//#define BACKWARDS_COMPAT
9
10enum _:Auths {
11 Auth_Name,
12 Auth_SteamID,
13 Auth_IP,
14 Auth_Tag
15};
16
17enum _:AuthData {
18 Auth_Type,
19 Auth_Key[35],
20 Auth_Password[32],
21 Auth_RemoveTime,
22 Auth_Flags
23};
24
25enum _:AddData {
26 Data_Type,
27 Data_Auth[35],
28 Data_Password[32],
29 Data_Flags[27],
30 Data_RemoveDate[32]
31};
32
33#define getBit(%1,%2) (%1 & (1 << (%2 & 31)))
34#define setBit(%1,%2) %1 |= (1 << (%2 & 31))
35#define delBit(%1,%2) %1 &= ~(1 << (%2 & 31))
36
37new gVIP;
38#define is_vip(%1) getBit(gVIP, %1)
39#define set_vip(%1) setBit(gVIP, %1)
40#define remove_vip(%1) delBit(gVIP, %1)
41
42new gFlags[MAX_PLAYERS + 1];
43
44new Handle:gSqlTuple = Empty_Handle;
45new gUsersFile[64];
46
47new gCvarSql;
48new gCvarHost;
49new gCvarUser;
50new gCvarPass;
51new gCvarDb;
52new gCvarAuthFlags;
53new gCvarDefaultFlags;
54new gCvarDeleteExpired;
55new gCvarPasswordField;
56
57new gForwardAuth;
58new gForwardPutinserver;
59new gForwardDisconnect;
60new gReturnFromForward;
61
62new Trie:gAuthKeys;
63
64new Array:gAuthData;
65new Trie:gAuthToIndex[Auths];
66new gNumAuths;
67
68new Regex:gDatePattern;
69
70public plugin_init() {
71 register_plugin("VIP Manager", "0.0.6", "Exolent");
72
73 register_concmd("vip_adduser", "CmdAddUser", ADMIN_RCON, "<name, #userid, authid> <type> [password] [flags] [days] -- <type> can be 'name', 'steamid', or 'ip'");
74 register_concmd("vip_addauth", "CmdAddAuth", ADMIN_RCON, "<type> <auth> [password] [flags] [days] -- <type> can be 'name', 'steamid', 'ip', or 'tag'");
75 register_concmd("vip_reload", "CmdReload", ADMIN_RCON, "-- reloads the VIP users list for the vip_users.ini");
76
77 gCvarSql = register_cvar("vip_sql", "0");
78 gCvarHost = register_cvar("vip_sql_host", "");
79 gCvarUser = register_cvar("vip_sql_user", "");
80 gCvarPass = register_cvar("vip_sql_pass", "");
81 gCvarDb = register_cvar("vip_sql_db", "");
82 gCvarAuthFlags = register_cvar("vip_auth_flags", "b");
83 gCvarDefaultFlags = register_cvar("vip_default_flags", "");
84 gCvarDeleteExpired = register_cvar("vip_delete_expired", "0");
85 gCvarPasswordField = register_cvar("vip_password_field", "_vip_pw");
86
87 gForwardAuth = CreateMultiForward("vip_authorized", ET_IGNORE, FP_CELL);
88 gForwardPutinserver = CreateMultiForward("vip_putinserver", ET_IGNORE, FP_CELL);
89 gForwardDisconnect = CreateMultiForward("vip_disconnect", ET_IGNORE, FP_CELL);
90
91 gAuthKeys = TrieCreate();
92 TrieSetCell(gAuthKeys, "name", Auth_Name);
93 TrieSetCell(gAuthKeys, "steam", Auth_SteamID);
94 TrieSetCell(gAuthKeys, "steamid", Auth_SteamID);
95 TrieSetCell(gAuthKeys, "authid", Auth_SteamID);
96 TrieSetCell(gAuthKeys, "ip", Auth_IP);
97 TrieSetCell(gAuthKeys, "tag", Auth_Tag);
98
99 gAuthData = ArrayCreate(AuthData);
100
101 for(new i = 0; i < Auths; i++) {
102 gAuthToIndex[i] = TrieCreate();
103 }
104
105 gDatePattern = regex_compile("\d{4}-\d{1,2}-\d{1,2}", gReturnFromForward, "", 0);
106
107 get_configsdir(gUsersFile, charsmax(gUsersFile));
108 add(gUsersFile, charsmax(gUsersFile), "/vip_users.ini");
109
110 LoadConfig();
111}
112
113public plugin_end() {
114 TrieDestroy(gAuthKeys);
115
116 ArrayDestroy(gAuthData);
117
118 for(new i = 0; i < Auths; i++) {
119 TrieDestroy(gAuthToIndex[i]);
120 }
121
122 regex_free(gDatePattern);
123}
124
125public plugin_natives() {
126 register_library("vip");
127
128 register_native("is_user_vip", "_is_user_vip");
129 register_native("get_vip_flags", "_get_vip_flags");
130}
131
132public _is_user_vip(plugin, params) {
133 return is_vip(get_param(1)) ? 1 : 0;
134}
135
136public _get_vip_flags(plugin, params) {
137 new id = get_param(1);
138
139 return is_vip(id) ? gFlags[id] : 0;
140}
141
142public client_authorized(id) {
143 CheckAuth(id, gForwardAuth);
144}
145
146public client_putinserver(id) {
147 CheckAuth(id, gForwardPutinserver);
148}
149
150public client_infochanged(id) {
151 if(!is_user_connected(id)) return;
152
153 new oldName[32], newName[32];
154 get_user_name(id, oldName, charsmax(oldName));
155 get_user_info(id, "name", newName, charsmax(newName));
156
157 if(!equal(oldName, newName)) {
158 CheckAuth(id, gForwardAuth, newName);
159 }
160}
161
162public client_disconnect(id) {
163 if(is_vip(id)) {
164 ExecuteForward(gForwardDisconnect, gReturnFromForward, id);
165
166 remove_vip(id);
167 gFlags[id] = 0;
168
169 remove_task(id);
170 }
171}
172
173public CmdAddUser(id, level, cid) {
174 if(!cmd_access(id, level, cid, 3)) {
175 return PLUGIN_HANDLED;
176 }
177
178 new auth[35];
179 read_argv(1, auth, charsmax(auth));
180
181 new target = cmd_target(id, auth, CMDTARGET_NO_BOTS);
182 if(!target) {
183 return PLUGIN_HANDLED;
184 }
185
186 new type[16];
187 read_argv(2, type, charsmax(type));
188 strtolower(type);
189
190 new typeNum;
191 if(!TrieGetCell(gAuthKeys, type, typeNum) || typeNum == Auth_Tag) {
192 console_print(id, "Invalid type! Only 'name', 'steamid', and 'ip' are valid types!");
193 return PLUGIN_HANDLED;
194 }
195
196 switch(typeNum) {
197 case Auth_SteamID: {
198 get_user_authid(target, auth, charsmax(auth));
199 }
200 case Auth_IP: {
201 get_user_ip(target, auth, charsmax(auth), 1);
202 }
203 default: {
204 get_user_name(target, auth, charsmax(auth));
205 }
206 }
207
208 new password[32];
209 new flagString[27], flags;
210 new remove, removeDate[32];
211
212 new argCount = read_argc();
213 if(argCount > 3) {
214 read_argv(3, password, charsmax(password));
215
216 if(argCount > 4) {
217 read_argv(4, flagString, charsmax(flagString));
218
219 flags = read_flags(flagString);
220
221 // fix flagString in case it wasn't 100% proper
222 get_flags(flags, flagString, charsmax(flagString));
223
224 if(argCount > 5) {
225 new days[12];
226 read_argv(5, days, charsmax(days));
227
228 if(!is_str_num(days) || (remove = str_to_num(days)) < 0) {
229 console_print(id, "Days must be a positive integer, or 0 for no expiring!");
230 return PLUGIN_HANDLED;
231 }
232
233 if(remove) {
234 remove = get_systime() + (remove * 86400);
235
236 format_time(removeDate, charsmax(removeDate), "%Y-%m-%d", remove);
237 }
238 }
239 }
240 }
241
242 new f = fopen(gUsersFile, "a+");
243
244 if(f) {
245 fprintf(f, "^n^"%s^" ^"%s^" ^"%s^" ^"%s^" ^"%s^"", type, auth, password, flagString, removeDate);
246 fclose(f);
247 }
248
249 if(gSqlTuple != Empty_Handle) {
250 new data[AddData];
251 data[Data_Type] = typeNum;
252 copy(data[Data_Auth], charsmax(data[Data_Auth]), auth);
253 copy(data[Data_Password], charsmax(data[Data_Password]), password);
254 copy(data[Data_Flags], charsmax(data[Data_Flags]), flagString);
255 copy(data[Data_RemoveDate], charsmax(data[Data_RemoveDate]), remove ? removeDate : "0000-00-00");
256
257 new query[128];
258 formatex(query, charsmax(query), "SELECT COUNT(*) FROM `vip_users` WHERE `auth_type` = %d AND `auth` = ^"%s^";", typeNum, auth);
259
260 SQL_ThreadQuery(gSqlTuple, "QueryCheckAddUser", query, data, AddData);
261 }
262
263 if(typeNum != Auth_Name) {
264 get_user_name(target, auth, charsmax(auth));
265 }
266
267
268 console_print(id, "Added user to VIP: <%s> <%s>", type, auth);
269
270 return PLUGIN_HANDLED;
271}
272
273public QueryCheckAddUser(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
274 if(failstate == TQUERY_CONNECT_FAILED) {
275 log_amx("Failed connecting to check add user (%d): %s", errcode, error);
276 }
277 else if(failstate == TQUERY_QUERY_FAILED) {
278 log_amx("Failed query on check add user (%d): %s", errcode, error);
279 }
280 else if(!SQL_ReadResult(query, 0)) {
281 new queryString[256];
282 formatex(queryString, charsmax(queryString), "INSERT INTO `vip_users` (`auth_type`, `auth`, `password`, `flags`, `date_remove`) VALUES (%d, ^"%s^", ^"%s^", ^"%s^", ^"%s^");",
283 data[Data_Type], data[Data_Auth], data[Data_Password], data[Data_Flags], data[Data_RemoveDate]);
284
285 SQL_ThreadQuery(gSqlTuple, "QueryAddUser", queryString);
286 }
287}
288
289public QueryAddUser(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
290 if(failstate == TQUERY_CONNECT_FAILED) {
291 log_amx("Failed connecting to add user (%d): %s", errcode, error);
292 }
293 else if(failstate == TQUERY_QUERY_FAILED) {
294 log_amx("Failed query on add user (%d): %s", errcode, error);
295 }
296}
297
298public CmdAddAuth(id, level, cid) {
299 if(!cmd_access(id, level, cid, 3)) {
300 return PLUGIN_HANDLED;
301 }
302
303 new type[16], auth[35];
304 read_argv(1, type, charsmax(type));
305 read_argv(2, auth, charsmax(auth));
306
307 strtolower(type);
308
309 new typeNum;
310 if(!TrieGetCell(gAuthKeys, type, typeNum)) {
311 console_print(id, "Invalid type! Only 'name', 'steamid', 'ip', and 'tag' are valid types!");
312 return PLUGIN_HANDLED;
313 }
314
315 new password[32];
316 new flagString[27], flags;
317 new remove, removeDate[32];
318
319 new argCount = read_argc();
320 if(argCount > 3) {
321 read_argv(3, password, charsmax(password));
322
323 if(argCount > 4) {
324 read_argv(4, flagString, charsmax(flagString));
325
326 flags = read_flags(flagString);
327
328 // fix flagString in case it wasn't 100% proper
329 get_flags(flags, flagString, charsmax(flagString));
330
331 if(argCount > 5) {
332 new days[12];
333 read_argv(5, days, charsmax(days));
334
335 if(!is_str_num(days) || (remove = str_to_num(days)) < 0) {
336 console_print(id, "Days must be a positive integer, or 0 for no expiring!");
337 return PLUGIN_HANDLED;
338 }
339
340 if(remove) {
341 remove = get_systime() + (remove * 86400);
342
343 format_time(removeDate, charsmax(removeDate), "%Y-%m-%d", remove);
344 }
345 }
346 }
347 }
348
349 new f = fopen(gUsersFile, "a+");
350
351 if(f) {
352 fprintf(f, "^n^"%s^" ^"%s^" ^"%s^" ^"%s^" ^"%s^"", type, auth, password, flagString, removeDate);
353 fclose(f);
354 }
355
356 if(gSqlTuple != Empty_Handle) {
357 new data[AddData];
358 data[Data_Type] = typeNum;
359 copy(data[Data_Auth], charsmax(data[Data_Auth]), auth);
360 copy(data[Data_Password], charsmax(data[Data_Password]), password);
361 copy(data[Data_Flags], charsmax(data[Data_Flags]), flagString);
362 copy(data[Data_RemoveDate], charsmax(data[Data_RemoveDate]), remove ? removeDate : "0000-00-00");
363
364 new query[128];
365 formatex(query, charsmax(query), "SELECT COUNT(*) FROM `vip_users` WHERE `auth_type` = %d AND `auth` = ^"%s^";", typeNum, auth);
366
367 SQL_ThreadQuery(gSqlTuple, "QueryCheckAddAuth", query, data, AddData);
368 }
369
370 console_print(id, "Added user to VIP: <%s> <%s>", type, auth);
371
372 return PLUGIN_HANDLED;
373}
374
375public QueryCheckAddAuth(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
376 if(failstate == TQUERY_CONNECT_FAILED) {
377 log_amx("Failed connecting to check add auth (%d): %s", errcode, error);
378 }
379 else if(failstate == TQUERY_QUERY_FAILED) {
380 log_amx("Failed query on check add auth (%d): %s", errcode, error);
381 }
382 else if(!SQL_ReadResult(query, 0)) {
383 new queryString[256];
384 formatex(queryString, charsmax(queryString), "INSERT INTO `vip_users` (`auth_type`, `auth`, `password`, `flags`, `date_remove`) VALUES (%d, ^"%s^", ^"%s^", ^"%s^", ^"%s^");",
385 data[Data_Type], data[Data_Auth], data[Data_Password], data[Data_Flags], data[Data_RemoveDate]);
386
387 SQL_ThreadQuery(gSqlTuple, "QueryAddAuth", queryString);
388 }
389}
390
391public QueryAddAuth(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
392 if(failstate == TQUERY_CONNECT_FAILED) {
393 log_amx("Failed connecting to add auth (%d): %s", errcode, error);
394 }
395 else if(failstate == TQUERY_QUERY_FAILED) {
396 log_amx("Failed query on add auth (%d): %s", errcode, error);
397 }
398}
399
400public CmdReload(id, level, cid) {
401 if(!cmd_access(id, level, cid, 1)) {
402 return PLUGIN_HANDLED;
403 }
404
405 LoadConfig();
406
407 new players[32], num;
408 get_players(players, num, "ch");
409
410 while(num) {
411 CheckAuth(players[--num], gForwardAuth);
412 }
413
414 console_print(id, "Reloaded VIP users list");
415
416 return PLUGIN_HANDLED;
417}
418
419LoadConfig() {
420 static bool:alreadyLoaded;
421
422 if(alreadyLoaded) {
423 gSqlTuple = Empty_Handle;
424
425 ArrayClear(gAuthData);
426 gNumAuths = 0;
427 }
428
429 new config[64];
430 get_configsdir(config, charsmax(config));
431 add(config, charsmax(config), "/vip.cfg");
432
433 if(file_exists(config)) {
434 server_cmd("exec %s", config);
435 server_exec();
436 }
437
438 if(!get_pcvar_num(gCvarSql) || !LoadSql(alreadyLoaded)) {
439 LoadFile();
440 }
441
442 alreadyLoaded = true;
443}
444
445LoadFile() {
446
447 new f = fopen(gUsersFile, "rt");
448
449 if(!f) return;
450
451 new data[64];
452 new type[16];
453 new typeNum;
454 new auth[32];
455 new flagString[32];
456 new removeDate[32];
457 new remove, curTime = get_systime();
458 new authData[AuthData];
459 new deleteExpired = get_pcvar_num(gCvarDeleteExpired);
460 new Trie:linesExpired, line;
461
462#if defined BACKWARDS_COMPAT
463 new Trie:linesToFix = TrieCreate(), bool:fixLines = false;
464#endif
465
466 new tmpFile[64];
467 formatex(tmpFile, charsmax(tmpFile), "%s.tmp", gUsersFile);
468
469 if(deleteExpired) {
470 linesExpired = TrieCreate();
471 }
472
473 while(!feof(f)) {
474 fgets(f, data, charsmax(data));
475 trim(data);
476 line++;
477
478 if(!data[0] || data[0] == ';' || data[0] == '/' && data[1] == '/') continue;
479
480 if(parse(data, type, charsmax(type), auth, charsmax(auth), flagString, charsmax(flagString), removeDate, charsmax(removeDate)) < 2) continue;
481
482 strtolower(type);
483
484 if(!TrieGetCell(gAuthKeys, type, typeNum) || TrieKeyExists(gAuthToIndex[typeNum], auth)) continue;
485
486#if defined BACKWARDS_COMPAT
487 if(!removeDate[0]) {
488 // there are only 3 params
489 // check if the 3rd is a date instead of flags
490 // this is for backwards compatibility for older versions without flags
491 if(flagString[0] && regex_match_c(flagString, gDatePattern, gReturnFromForward) > 0) {
492 // this flag string is really a date string
493 // switch the strings
494 copy(data, charsmax(data), removeDate);
495 copy(removeDate, charsmax(removeDate), flagString);
496 copy(flagString, charsmax(flagString), data);
497
498 // say we want to fix lines later
499 fixLines = true;
500
501 // add specific line to be fixed
502 num_to_str(line, data, charsmax(data));
503 TrieSetCell(linesToFix, data, line);
504 }
505 }
506#endif
507
508 remove = DateToUnix(removeDate);
509
510 if(remove && remove <= curTime) {
511 if(deleteExpired) {
512 num_to_str(line, type, charsmax(type));
513 TrieSetCell(linesExpired, type, line);
514 }
515 continue;
516 }
517
518 authData[Auth_Type] = typeNum;
519 copy(authData[Auth_Key], charsmax(authData[Auth_Key]), auth);
520 authData[Auth_Flags] = read_flags(flagString);
521 authData[Auth_RemoveTime] = remove;
522
523 ArrayPushArray(gAuthData, authData);
524 TrieSetCell(gAuthToIndex[typeNum], auth, gNumAuths);
525 gNumAuths++;
526 }
527
528#if defined BACKWARDS_COMPAT
529 if(deleteExpired || fixLines) {
530#else
531 if(deleteExpired) {
532#endif
533 fseek(f, 0, SEEK_SET);
534
535 new t = fopen(tmpFile, "wt");
536 line = 0;
537
538 while(!feof(f)) {
539 num_to_str(++line, type, charsmax(type));
540 fgets(f, data, charsmax(data));
541
542 if(deleteExpired && TrieKeyExists(linesExpired, type)) continue;
543
544#if defined BACKWARDS_COMPAT
545 if(TrieKeyExists(linesToFix, type)) {
546 parse(data, type, charsmax(type), auth, charsmax(auth), flagString, charsmax(flagString), removeDate, charsmax(removeDate));
547
548 // switch date and flag string since they are backwards
549 formatex(data, charsmax(data), "^"%s^" ^"%s^" ^"%s^" ^"%s^"^n", type, auth, removeDate, flagString);
550 }
551#endif
552
553 fputs(t, data);
554 }
555
556 fclose(t);
557
558 TrieDestroy(linesExpired);
559 }
560
561#if defined BACKWARDS_COMPAT
562 TrieDestroy(linesToFix);
563#endif
564
565 fclose(f);
566
567#if defined BACKWARDS_COMPAT
568 if(deleteExpired || fixLines) {
569#else
570 if(deleteExpired) {
571#endif
572 rename_file(tmpFile, gUsersFile, 1);
573 }
574}
575
576DateToUnix(const dateString[]) {
577 if(!dateString[0] || regex_match_c(dateString, gDatePattern, gReturnFromForward) <= 0 || equal(dateString, "0000-00-00")) {
578 return 0;
579 }
580
581 new year[5], month[3], rest[32];
582 strtok(dateString, year, charsmax(year), rest, charsmax(rest), '-');
583 strtok(rest, month, charsmax(month), rest, charsmax(rest), '-');
584
585 return TimeToUnix(str_to_num(year), str_to_num(month), str_to_num(rest), 0, 0, 0);
586}
587
588LoadSql(bool:threadQueries) {
589 new host[32], user[32], pass[32], db[32];
590 get_pcvar_string(gCvarHost, host, charsmax(host));
591 get_pcvar_string(gCvarUser, user, charsmax(user));
592 get_pcvar_string(gCvarPass, pass, charsmax(pass));
593 get_pcvar_string(gCvarDb, db, charsmax(db));
594
595 gSqlTuple = SQL_MakeDbTuple(host, user, pass, db);
596
597 if(gSqlTuple == Empty_Handle) {
598 log_amx("Failed to create SQL tuple.");
599 return 0;
600 }
601
602 new const queryString[] = "CREATE TABLE IF NOT EXISTS `vip_users` (\
603 `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\
604 `auth_type` INT NOT NULL DEFAULT '0',\
605 `auth` VARCHAR(32) NOT NULL,\
606 `password` VARCHAR(32) NOT NULL,\
607 `flags` VARCHAR(26) NOT NULL,\
608 `date_remove` DATE NOT NULL DEFAULT '0000-00-00');";
609
610 if(threadQueries) {
611 SQL_ThreadQuery(gSqlTuple, "QueryCreateTable", queryString);
612 } else {
613 new errcode, error[128];
614 new Handle:link = SQL_Connect(gSqlTuple, errcode, error, charsmax(error));
615
616 if(link == Empty_Handle) {
617 gSqlTuple = Empty_Handle;
618
619 log_amx("Failed to connect to database (%d): %s", errcode, error);
620 return 0;
621 }
622
623 new Handle:query = SQL_PrepareQuery(link, "%s", queryString);
624
625 // Added `date_remove` field to table
626 //
627 // Fix for v0.0.1 to v0.0.2
628 // ALTER TABLE `vip_users` ADD `date_remove` DATE NOT NULL DEFAULT '0000-00-00';
629
630 // Added `flags` field to table
631 //
632 // Fix for v0.0.1 to v0.0.4
633 // ALTER TABLE `vip_users` ADD `date_remove` DATE NOT NULL DEFAULT '0000-00-00', ADD `flags` VARCHAR(26) NOT NULL DEFAULT '';
634 //
635 // Fix for v0.0.2 to v0.0.4
636 // ALTER TABLE `vip_users` ADD `flags` VARCHAR(26) NOT NULL DEFAULT '';
637
638 // Added `password` field to table
639 //
640 // Fix for v0.0.1 to v0.0.5
641 // ALTER TABLE `vip_users` ADD `date_remove` DATE NOT NULL DEFAULT '0000-00-00', ADD `flags` VARCHAR(26) NOT NULL DEFAULT '', ADD `password` VARCHAR(32) NOT NULL DEFAULT '';
642 //
643 // Fix for v0.0.2 to v0.0.5
644 // ALTER TABLE `vip_users` ADD `flags` VARCHAR(26) NOT NULL DEFAULT '', ADD `password` VARCHAR(32) NOT NULL DEFAULT '';
645 //
646 // Fix for v0.0.4 to v0.0.5
647 // ALTER TABLE `vip_users` ADD `password` VARCHAR(32) NOT NULL DEFAULT '';
648
649 if(!SQL_Execute(query)) {
650 gSqlTuple = Empty_Handle;
651
652 SQL_QueryError(query, error, charsmax(error));
653 log_amx("Error creating table: %s", error);
654 }
655
656 SQL_FreeHandle(query);
657 SQL_FreeHandle(link);
658
659 if(gSqlTuple != Empty_Handle) {
660 LoadFromSql();
661 } else {
662 return 0;
663 }
664 }
665
666 return 1;
667}
668
669public QueryCreateTable(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
670 if(failstate == TQUERY_CONNECT_FAILED) {
671 log_amx("Failed connecting to create table (%d): %s", errcode, error);
672
673 LoadFile();
674 }
675 else if(failstate == TQUERY_QUERY_FAILED) {
676 log_amx("Failed query on create table (%d): %s", errcode, error);
677
678 LoadFile();
679 }
680 else {
681 LoadFromSql();
682 }
683}
684
685LoadFromSql() {
686 new curDate[11];
687 get_time("%Y-%m-%d", curDate, charsmax(curDate));
688
689 new queryString[94];
690 // SELECT * FROM `vip_users` WHERE `date_remove` = '0000-00-00' OR `date_remove` > '2012-02-09';
691 // 0123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
692
693 if(get_pcvar_num(gCvarDeleteExpired)) {
694 formatex(queryString, charsmax(queryString), "DELETE FROM `vip_users` WHERE `date_remove` > '%s';", curDate);
695
696 SQL_ThreadQuery(gSqlTuple, "QueryDeleteExpired", queryString);
697 }
698
699 formatex(queryString, charsmax(queryString), "SELECT * FROM `vip_users` WHERE `date_remove` = '0000-00-00' OR `date_remove` > '%s';", curDate);
700
701 SQL_ThreadQuery(gSqlTuple, "QueryLoadUsers", queryString);
702}
703
704public QueryDeleteExpired(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
705 if(failstate == TQUERY_CONNECT_FAILED) {
706 log_amx("Failed connecting to delete expired (%d): %s", errcode, error);
707 }
708 else if(failstate == TQUERY_QUERY_FAILED) {
709 log_amx("Failed query on delete expired (%d): %s", errcode, error);
710 }
711}
712
713public QueryLoadUsers(failstate, Handle:query, error[], errcode, data[], size, Float:queueTime) {
714 if(failstate == TQUERY_CONNECT_FAILED) {
715 log_amx("Failed connecting to load users (%d): %s", errcode, error);
716
717 LoadFile();
718 }
719 else if(failstate == TQUERY_QUERY_FAILED) {
720 log_amx("Failed query on load users (%d): %s", errcode, error);
721
722 LoadFile();
723 }
724 else if(SQL_NumResults(query)) {
725 new fieldAuth = SQL_FieldNameToNum(query, "auth");
726 new fieldType = SQL_FieldNameToNum(query, "auth_type");
727 new fieldPassword = SQL_FieldNameToNum(query, "password");
728 new fieldFlags = SQL_FieldNameToNum(query, "flags");
729 new fieldRemove = SQL_FieldNameToNum(query, "date_remove");
730
731 new flagString[27];
732 new removeDate[11];
733 new curTime = get_systime();
734 new authData[AuthData];
735
736 do {
737 SQL_ReadResult(query, fieldRemove, removeDate, charsmax(removeDate));
738
739 authData[Auth_RemoveTime] = DateToUnix(removeDate);
740
741 if(!authData[Auth_RemoveTime] || authData[Auth_RemoveTime] > curTime) {
742 SQL_ReadResult(query, fieldAuth, authData[Auth_Key], charsmax(authData[Auth_Key]));
743 authData[Auth_Type] = SQL_ReadResult(query, fieldType);
744
745 SQL_ReadResult(query, fieldPassword, authData[Auth_Password], charsmax(authData[Auth_Password]));
746
747 SQL_ReadResult(query, fieldFlags, flagString, charsmax(flagString));
748 authData[Auth_Flags] = read_flags(flagString);
749
750 ArrayPushArray(gAuthData, authData);
751 TrieSetCell(gAuthToIndex[authData[Auth_Type]], authData[Auth_Key], gNumAuths);
752 gNumAuths++;
753 }
754
755 SQL_NextRow(query);
756 }
757 while(SQL_MoreResults(query));
758 }
759}
760
761CheckAuth(id, forwardHandle, forceName[] = "") {
762 new wasVip = is_vip(id);
763 remove_vip(id);
764 gFlags[id] = 0;
765
766 remove_task(id);
767
768 new flags[27];
769 get_pcvar_string(gCvarAuthFlags, flags, charsmax(flags));
770
771 if(flags[0] && has_all_flags(id, flags)) {
772 gFlags[id] = read_flags(flags) | read_pcvar_flags(gCvarDefaultFlags);
773 AuthUser(id, wasVip, forwardHandle);
774 return;
775 }
776
777 new name[32], steamid[32], ip[32];
778 if(forceName[0]) {
779 copy(name, charsmax(name), forceName);
780 } else {
781 get_user_name(id, name, charsmax(name));
782 }
783 get_user_authid(id, steamid, charsmax(steamid));
784 get_user_ip(id, ip, charsmax(ip), 1);
785
786 new curTime = get_systime();
787
788 new authData[AuthData], index;
789
790 if(!TrieGetCell(Trie:gAuthToIndex[Auth_Name], name, index)
791 && !TrieGetCell(Trie:gAuthToIndex[Auth_SteamID], steamid, index)
792 && !TrieGetCell(Trie:gAuthToIndex[Auth_IP], ip, index)) {
793 index = -1;
794
795 for(new i = 0; i < gNumAuths; i++) {
796 ArrayGetArray(gAuthData, i, authData);
797
798 if(authData[Auth_Type] == Auth_Tag
799 && (0 < authData[Auth_RemoveTime] <= curTime)
800 && containi(name, authData[Auth_Key]) != -1) {
801 index = i;
802 break;
803 }
804 }
805
806 if(index == -1) return;
807 }
808
809 if(authData[Auth_Password][0]) {
810 new field[32], password[32];
811 get_pcvar_string(gCvarPasswordField, field, charsmax(field));
812 get_user_info(id, field, password, charsmax(password));
813
814 if(!equal(authData[Auth_Password], password)) return;
815 }
816
817 gFlags[id] = authData[Auth_Flags] | read_pcvar_flags(gCvarDefaultFlags);
818 AuthUser(id, wasVip, forwardHandle, authData[Auth_RemoveTime] - curTime);
819}
820
821AuthUser(id, wasVip, forwardHandle, remove = 0) {
822 set_vip(id);
823
824 if(!wasVip) {
825 ExecuteForward(forwardHandle, wasVip, id);
826 }
827
828 if(remove > 0) {
829 set_task(float(remove), "TaskCheckAuth", id);
830 }
831}
832
833public TaskCheckAuth(id) {
834 CheckAuth(id, gForwardAuth);
835}
836
837read_pcvar_flags(cvar) {
838 new flags[27];
839 get_pcvar_string(cvar, flags, charsmax(flags));
840 return read_flags(flags);
841}
842
843// CODE BELOW IS FROM BUGSY'S UNIX TO TIME CONVERSION INCLUDE
844// https://forums.alliedmods.net/showthread.php?t=91915
845
846stock const YearSeconds[2] =
847{
848 31536000, //Normal year
849 31622400 //Leap year
850};
851
852stock const MonthSeconds[12] =
853{
854 2678400, //January 31
855 2419200, //February 28
856 2678400, //March 31
857 2592000, //April 30
858 2678400, //May 31
859 2592000, //June 30
860 2678400, //July 31
861 2678400, //August 31
862 2592000, //September 30
863 2678400, //October 31
864 2592000, //November 30
865 2678400 //December 31
866};
867
868stock const DaySeconds = 86400;
869stock const HourSeconds = 3600;
870stock const MinuteSeconds = 60;
871
872stock TimeToUnix( const iYear , const iMonth , const iDay , const iHour , const iMinute , const iSecond /*, TimeZones:tzTimeZone=UT_TIMEZONE_UTC*/)
873{
874 new i , iTimeStamp;
875
876 for ( i = 1970 ; i < iYear ; i++ )
877 iTimeStamp += YearSeconds[ IsLeapYear(i) ];
878
879 for ( i = 1 ; i < iMonth ; i++ )
880 iTimeStamp += SecondsInMonth( iYear , i );
881
882 iTimeStamp += ( ( iDay - 1 ) * DaySeconds );
883 iTimeStamp += ( iHour * HourSeconds );
884 iTimeStamp += ( iMinute * MinuteSeconds );
885 iTimeStamp += iSecond;
886
887 /*if ( tzTimeZone == UT_TIMEZONE_SERVER )
888 tzTimeZone = GetTimeZone();
889
890 return ( iTimeStamp + TimeZoneOffset[ tzTimeZone ] );*/
891
892 return iTimeStamp;
893}
894
895stock SecondsInMonth( const iYear , const iMonth )
896{
897 return ( ( IsLeapYear( iYear ) && ( iMonth == 2 ) ) ? ( MonthSeconds[iMonth - 1] + DaySeconds ) : MonthSeconds[iMonth - 1] );
898}
899
900stock IsLeapYear( const iYear )
901{
902 return ( ( (iYear % 4) == 0) && ( ( (iYear % 100) != 0) || ( (iYear % 400) == 0 ) ) );
903}