HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. #include <amxmodx>
  2. #include <amxmisc>
  3.  
  4. // my logs directory function
  5. stock get_logsdir(output[], len) {
  6. return get_localinfo("amxx_logs", output, len);
  7. }
  8.  
  9. #define DEBUG
  10.  
  11. #define TASK_ID_REMOVE 14325
  12.  
  13. new gCaseSensitive;
  14. #define IsCaseSensitive(%1) (gCaseSensitive & (1 << (%1 & 31)))
  15. #define SetCaseSensitive(%1) gCaseSensitive |= (1 << (%1 & 31))
  16. #define ClearCaseSensitive(%1) gCaseSensitive &= ~(1 << (%1 & 31))
  17.  
  18. // admin data stored
  19. enum _:AdminData {
  20. Admin_Auth[44],
  21. Admin_Password[32],
  22. Admin_Access,
  23. Admin_Flags
  24. };
  25.  
  26. // array holding admin data
  27. new Array:gAdminData;
  28. // auth key pointing to index of array
  29. new Trie:gAuthIndex;
  30. // size of array
  31. new gNumAdmins;
  32.  
  33. // file where admins are loaded
  34. new gAdminFile[64];
  35.  
  36. // default amxx cvars
  37. new amx_mode;
  38. new amx_password_field;
  39. new amx_default_access;
  40.  
  41. // kick command
  42. new gKickCommand[32];
  43.  
  44. #if defined DEBUG
  45. new gLogFile[64];
  46.  
  47. #define DebugLog(%1) log_to_file(gLogFile, %1)
  48.  
  49. new const gSeparator[] = "===========================================================";
  50. #else
  51. stock DebugLog(any:...) { }
  52. stock gSeparator;
  53. #endif
  54.  
  55. public plugin_init() {
  56. register_plugin("Admin Custom", "0.0.2", "Exolent");
  57.  
  58. #if defined DEBUG
  59. // locate log file directory
  60. get_logsdir(gLogFile, charsmax(gLogFile));
  61. new l = add(gLogFile, charsmax(gLogFile), "/admin_custom");
  62.  
  63. // check if log directory exists
  64. if(!dir_exists(gLogFile)) {
  65. // make directory
  66. mkdir(gLogFile);
  67. }
  68.  
  69. // get the log file
  70. get_time("/%Y-%m-%d.log", gLogFile[l], charsmax(gLogFile) - l);
  71. #endif
  72.  
  73. // grab default amxx cvars
  74. // registering will grab pointer if exists
  75. amx_mode = register_cvar("amx_mode", "1");
  76. amx_password_field = register_cvar("amx_password_field", "_pw");
  77. amx_default_access = register_cvar("amx_default_access", "");
  78.  
  79. // register kick command
  80. formatex(gKickCommand, charsmax(gKickCommand), "amxauthcustom%c%c%c%c", random_num('A', 'Z'), random_num('A', 'Z'), random_num('A', 'Z'), random_num('A', 'Z'));
  81. register_clcmd(gKickCommand, "CmdKick");
  82.  
  83. // locate admin file
  84. get_configsdir(gAdminFile, charsmax(gAdminFile));
  85. add(gAdminFile, charsmax(gAdminFile), "/users_custom.ini");
  86.  
  87. // create array and trie
  88. gAdminData = ArrayCreate(AdminData);
  89. gAuthIndex = TrieCreate();
  90.  
  91. // load admins
  92. LoadAdmins();
  93.  
  94. // grab current time
  95. new hour, minute, second;
  96. time(hour, minute, second);
  97.  
  98. // subtract current time from day length to get time left for today
  99. // add 5 seconds into the next day to be sure the day changed
  100. new timeLeft = 86400 - (hour * 3600) - (minute * 60) - second + 5;
  101.  
  102. // set task to refresh admins when tomorrow starts for expiration checking and day checking
  103. set_task(float(timeLeft), "TaskRefreshAdmins");
  104. }
  105.  
  106. public TaskRefreshAdmins() {
  107. #if defined DEBUG
  108. // grab last '/' position
  109. new slash, last = -1;
  110. while((slash = contain(gLogFile[last + 1], "/")) >= 0) {
  111. last = slash;
  112. }
  113.  
  114. // get the log file
  115. get_time("/%Y-%m-%d.log", gLogFile[last], charsmax(gLogFile) - last);
  116. #endif
  117. // reload admins
  118. LoadAdmins();
  119.  
  120. // grab all players
  121. new players[32], pnum;
  122. get_players(players, pnum);
  123.  
  124. // loop through all players
  125. while(pnum--) {
  126. // check admin for player
  127. checkAdmin(players[pnum]);
  128. }
  129.  
  130. // refresh admins next day
  131. set_task(86400.0, "TaskRefreshAdmins");
  132. }
  133.  
  134. public plugin_end() {
  135. // clear the memory
  136. ArrayDestroy(gAdminData);
  137. TrieDestroy(gAuthIndex);
  138. }
  139.  
  140. public client_connect(id) {
  141. // set that name checks are case insensitive
  142. ClearCaseSensitive(id);
  143. }
  144.  
  145. public client_authorized(id) {
  146. // check if admin is turned on
  147. if(get_pcvar_num(amx_mode)) {
  148. DebugLog("%s", gSeparator);
  149. DebugLog("User authorized %d", id);
  150.  
  151. // check admin for this user
  152. checkAdmin(id);
  153. }
  154. }
  155.  
  156. public client_putinserver(id) {
  157. // for listen servers, check host access
  158. if(get_pcvar_num(amx_mode) && !is_dedicated_server() && id == 1) {
  159. DebugLog("%s", gSeparator);
  160. DebugLog("Host connected %d", id);
  161.  
  162. // check admin for host
  163. checkAdmin(id);
  164. }
  165. }
  166.  
  167. public client_infochanged(id) {
  168. // check if player is connected and admin is turned on
  169. if(is_user_connected(id) && get_pcvar_num(amx_mode)) {
  170. // grab new and old name
  171. new oldName[32], newName[32];
  172. get_user_name(id, oldName, charsmax(oldName));
  173. get_user_info(id, "name", newName, charsmax(newName));
  174.  
  175. // check if names changed based on case sensitive flag
  176. if(strcmp(oldName, newName, !IsCaseSensitive(id)) == 0) {
  177. DebugLog("%s", gSeparator);
  178. DebugLog("Changed name (%d) case sensitive: %d", id, !!IsCaseSensitive(id));
  179.  
  180. // name changed, check admin
  181. checkAdmin(id, newName);
  182. }
  183. }
  184. }
  185.  
  186. public CmdKick(id) {
  187. // kick player from server
  188. server_cmd("kick #%d", get_user_userid(id));
  189.  
  190. // hide command from console
  191. return PLUGIN_HANDLED;
  192. }
  193.  
  194. public TaskRemoveAuth(auth[]) {
  195. // grab index of admins where auth is
  196. new index;
  197. if(!TrieGetCell(gAuthIndex, auth, index)) {
  198. return;
  199. }
  200.  
  201. // delete from admins
  202. ArrayDeleteItem(gAdminData, index);
  203. TrieDeleteKey(gAuthIndex, auth);
  204. gNumAdmins--;
  205.  
  206. // loop through all admins and update indexes
  207. new admin[AdminData];
  208. while(index < gNumAdmins) {
  209. // grab auth from this index
  210. ArrayGetArray(gAdminData, index, admin);
  211.  
  212. // update index for this admin
  213. TrieSetCell(gAuthIndex, admin[Admin_Auth], index);
  214. }
  215.  
  216. // grab all players
  217. new players[32], pnum;
  218. get_players(players, pnum);
  219.  
  220. // loop through all players
  221. while(pnum--) {
  222. // check admin for player
  223. checkAdmin(players[pnum]);
  224. }
  225. }
  226.  
  227. checkAdmin(id, name[32] = "") {
  228. DebugLog("Checking admin for %d", id);
  229.  
  230. // remove any existing flags
  231. remove_user_flags(id);
  232.  
  233. // check if no name was passed
  234. if(!name[0]) {
  235. // grab current name
  236. get_user_name(id, name, charsmax(name));
  237. }
  238.  
  239. // set name to not be case sensitive
  240. ClearCaseSensitive(id);
  241.  
  242. // grab SteamID and IP as well
  243. new steamID[35], ip[32];
  244. get_user_authid(id, steamID, charsmax(steamID));
  245. get_user_ip(id, ip, charsmax(ip), 1);
  246.  
  247. DebugLog("Grabbed all player data for admin check: ^"%s^" ^"%s^" ^"%s^"", name, steamID, ip);
  248.  
  249. // create variables we need for admin checking
  250. new admin[AdminData];
  251. new temp;
  252. new bool:found = false;
  253.  
  254. DebugLog("Checking normal admin list");
  255.  
  256. // loop through normal admin list before checking custom
  257. for(new i = admins_num() - 1; i >= 0; i--) {
  258. DebugLog("Checking normal admin index #%d", i);
  259.  
  260. // grab the auth, password, access, and flags
  261. admins_lookup(i, AdminProp_Auth , admin[Admin_Auth ], charsmax(admin[Admin_Auth ]));
  262. admins_lookup(i, AdminProp_Password, admin[Admin_Password], charsmax(admin[Admin_Password]));
  263. admin[Admin_Access] = admins_lookup(i, AdminProp_Access);
  264. admin[Admin_Flags ] = admins_lookup(i, AdminProp_Flags );
  265.  
  266. // check if player matches this admin
  267. if((found = adminMatch(id, name, steamID, ip, admin))) {
  268. break;
  269. }
  270. }
  271.  
  272. // check if player was not found in the normal admin list
  273. if(!found) {
  274. DebugLog("Not found in normal admin list, checking custom");
  275.  
  276. // loop through custom admin list
  277. for(new i = 0; i < gNumAdmins; i++) {
  278. // grab admin data
  279. ArrayGetArray(gAdminData, i, admin);
  280.  
  281. // check if player matches this admin
  282. if((found = adminMatch(id, name, steamID, ip, admin))) {
  283. break;
  284. }
  285. }
  286. }
  287.  
  288. // check if player was found for any admin at all
  289. if(found) {
  290. // check if this requires a password
  291. if(~admin[Admin_Flags] & FLAG_NOPASS) {
  292. DebugLog("Admin requires a password");
  293.  
  294. // grab password field and player's password
  295. new field[32], password[32];
  296. get_pcvar_string(amx_password_field, field, charsmax(field));
  297. get_user_info(id, field, password, charsmax(password));
  298.  
  299. // check if passwords don't match
  300. if(!equal(admin[Admin_Password], password)) {
  301. DebugLog("Passwords don't match");
  302.  
  303. // check if this should kick players
  304. if(admin[Admin_Flags] & FLAG_KICK) {
  305. DebugLog("Admin flags specify to kick player");
  306.  
  307. // kick player
  308. client_cmd(id, "%s", gKickCommand);
  309. }
  310.  
  311. // don't give access
  312. return;
  313. }
  314. }
  315.  
  316. new flags[27];
  317. get_flags(admin[Admin_Access], flags, charsmax(flags));
  318.  
  319. DebugLog("Player authorized as admin: %s", flags);
  320.  
  321. // give player admin access
  322. set_user_flags(id, admin[Admin_Access]);
  323. }
  324. // check if non-admins should be kicked
  325. else if(get_pcvar_num(amx_mode) == 2) {
  326. DebugLog("Not found in any admin list");
  327. DebugLog("amx_mode is 2, kicking player");
  328.  
  329. // kick player
  330. client_cmd(id, "%s", gKickCommand);
  331. }
  332. // give default flags
  333. else {
  334. DebugLog("Not found in any admin list");
  335.  
  336. // get default flags
  337. new flags[27];
  338. get_pcvar_string(amx_default_access, flags, charsmax(flags));
  339. temp = read_flags(flags);
  340.  
  341. // check if no flags are given
  342. if(!temp) {
  343. // give user flag
  344. temp = ADMIN_USER;
  345. }
  346.  
  347. get_flags(temp, flags, charsmax(flags));
  348.  
  349. DebugLog("Giving default flags: %s", flags);
  350.  
  351. // give player flags
  352. set_user_flags(id, temp);
  353. }
  354. }
  355.  
  356. bool:adminMatch(id, const name[], const steamID[], const ip[], const admin[AdminData]) {
  357. // create variables we need
  358. new temp;
  359. new bool:found = false;
  360.  
  361. // check if this is a SteamID
  362. if(admin[Admin_Flags] & FLAG_AUTHID) {
  363. DebugLog("Admin flags specify SteamID");
  364.  
  365. // check if SteamIDs match
  366. if(equal(steamID, admin[Admin_Auth])) {
  367. DebugLog("SteamIDs match");
  368.  
  369. // we found the admin
  370. found = true;
  371. }
  372. }
  373. // check if this is an IP
  374. else if(admin[Admin_Flags] & FLAG_IP) {
  375. DebugLog("Admin flags specify IP");
  376.  
  377. // grab length of ip in list
  378. temp = strlen(admin[Admin_Auth]);
  379.  
  380. // check if ends in a '.' for range checks
  381. if(admin[Admin_Auth][temp - 1] != '.') {
  382. DebugLog("Full IP given, no range");
  383.  
  384. // set length to 0 to match whole string
  385. temp = 0;
  386. } else {
  387. DebugLog("IP Range given");
  388. }
  389.  
  390. // check if ip's match
  391. if(equal(ip, admin[Admin_Auth], temp)) {
  392. DebugLog("IPs match");
  393.  
  394. // we found the admin
  395. found = true;
  396. }
  397. }
  398. // check if this is a tag
  399. else if(admin[Admin_Flags] & FLAG_TAG) {
  400. DebugLog("Admin flags specify Tag");
  401.  
  402. // cache if this is case sensitive admin name
  403. temp = admin[Admin_Flags] & FLAG_CASE_SENSITIVE;
  404.  
  405. DebugLog("Case sensitive: %d", !!temp);
  406.  
  407. // check if tag is in name based on case sensitivity flag from admin list
  408. if(strfind(name, admin[Admin_Auth], !temp) >= 0) {
  409. DebugLog("Tag found inside name");
  410.  
  411. // set case sensitive flag if admin list has it
  412. if(temp) {
  413. SetCaseSensitive(id);
  414. }
  415.  
  416. // we found the admin
  417. found = true;
  418. }
  419. }
  420. // then this should be an admin name
  421. else {
  422. DebugLog("Admin flags specify Name");
  423.  
  424. // cache if this is case sensitive admin name
  425. temp = admin[Admin_Flags] & FLAG_CASE_SENSITIVE;
  426.  
  427. DebugLog("Case sensitive: %d", !!temp);
  428.  
  429. // check if names match based on case sensitivity flag from admin list
  430. if(strcmp(name, admin[Admin_Auth], !temp) == 0) {
  431. DebugLog("Names match");
  432.  
  433. // set case sensitive flag if admin list has it
  434. if(temp) {
  435. SetCaseSensitive(id);
  436. }
  437.  
  438. // we found the admin
  439. found = true;
  440. }
  441. }
  442.  
  443. // return if we found admin
  444. return found;
  445. }
  446.  
  447. LoadAdmins() {
  448. DebugLog("%s", gSeparator);
  449. DebugLog("Loading admins");
  450.  
  451. // check if admins have been loaded already
  452. if(gNumAdmins) {
  453. // clear out old stored data
  454. ArrayClear(gAdminData);
  455. TrieClear(gAuthIndex);
  456. gNumAdmins = 0;
  457.  
  458. DebugLog("Cleared out existing admins");
  459. }
  460.  
  461. // calculate lines in admin file
  462. new fileSize = file_size(gAdminFile, 1);
  463.  
  464. // check if no lines exist
  465. if(fileSize < 1) {
  466. DebugLog("No lines inside admin file");
  467. // don't read file
  468. return;
  469. }
  470.  
  471. // grab current day of the week
  472. new data[256];
  473. get_time("%w", data, charsmax(data));
  474.  
  475. // store current day as a bit
  476. new currentDay = 1 << str_to_num(data);
  477.  
  478. // prepare variables for reading the admin file
  479. new admin[AdminData];
  480. new accessString[27];
  481. new flagString[27];
  482. new activityString[8];
  483. new expireString[32];
  484. new activity;
  485. new expireTime;
  486. new temp;
  487. new currentTime = get_systime();
  488.  
  489. // iterate through all lines
  490. for(new line = 0; line < fileSize; line++) {
  491. // read current line
  492. read_file(gAdminFile, line, data, charsmax(data), expireTime);
  493. // trim any white space
  494. trim(data);
  495.  
  496. DebugLog("Found line: #%d -> %s", line, data);
  497.  
  498. // check if this is a valid line
  499. if(!data[0] || data[0] == ';' || data[0] == '/' && data[1] == '/') {
  500. DebugLog("Line is empty");
  501. continue;
  502. }
  503.  
  504. // parse out all the pieces of the line
  505. parse(data,
  506. admin[Admin_Auth], charsmax(admin[Admin_Auth]),
  507. admin[Admin_Password], charsmax(admin[Admin_Password]),
  508. accessString, charsmax(accessString),
  509. flagString, charsmax(flagString),
  510. activityString, charsmax(activityString),
  511. expireString, charsmax(expireString)
  512. );
  513.  
  514. // convert access and flags to bits and init activity to all days
  515. admin[Admin_Access] = read_flags(accessString);
  516. admin[Admin_Flags] = read_flags(flagString);
  517. activity = 0;
  518.  
  519. DebugLog("Parsed access (%d) and flags (%d)", admin[Admin_Access], admin[Admin_Flags]);
  520.  
  521. // using expireTime as an index for activity string
  522. expireTime = 0;
  523. // loop through all characters in activity string
  524. while((temp = activityString[expireTime])) {
  525. // check if this is a valid weekday number
  526. if('1' <= temp <= '7') {
  527. // add to activity bitsum
  528. activity |= (1 << (temp - '1'));
  529. }
  530.  
  531. // increase index for activity string
  532. expireTime++;
  533. }
  534.  
  535. DebugLog("Parsed activity: %d", activity);
  536.  
  537. // check if this admin has specific days set and cannot have admin for today
  538. if(activity && (~activity & currentDay)) {
  539. DebugLog("Admin not enabled for today (%d)", currentDay);
  540. // don't add admin to list
  541. continue;
  542. }
  543.  
  544. // check if expiration date is set
  545. if(expireString[0]) {
  546. DebugLog("Found expiration date");
  547. // parse out "day.month.year" format
  548. // using accessString for day, flagString for month, expireString for year
  549. strtok(expireString, accessString, charsmax(accessString), expireString, charsmax(expireString), '.');
  550. strtok(expireString, flagString, charsmax(flagString), expireString, charsmax(expireString), '.');
  551.  
  552. // convert parsed values to integers
  553. activity = str_to_num(accessString); // day
  554. expireTime = str_to_num(flagString); // month
  555. temp = str_to_num(expireString); // year
  556.  
  557. DebugLog("Parsed expiration date: day (%d) month (%d) year (%d)", activity, expireTime, temp);
  558.  
  559. // grab this expiration date's timestamp for when the day starts
  560. expireTime = TimeToUnix(temp, expireTime, activity, 0, 0, 0);
  561.  
  562. DebugLog("Parsed expiration timestamp: %d", expireTime);
  563.  
  564. // calculate the time left before this expires
  565. expireTime -= currentTime;
  566.  
  567. DebugLog("Seconds before expiration: %d", expireTime);
  568.  
  569. // if time is 0 or negative, then it already expired
  570. if(expireTime <= 0) {
  571. DebugLog("Expired, commenting out line");
  572.  
  573. // expired, so set line to be a comment and add a comment on the end saying it expired
  574. format(data, charsmax(data), ";%s ; Expired already", data);
  575.  
  576. // replace current line with commented data
  577. write_file(gAdminFile, data, line);
  578.  
  579. // don't add to admin list
  580. continue;
  581. }
  582.  
  583. // set a task for this admin to expire
  584. set_task(float(expireTime), "TaskRemoveAuth", TASK_ID_REMOVE, admin[Admin_Auth], sizeof(admin[Admin_Auth]));
  585. }
  586.  
  587. DebugLog("Added to admin list");
  588.  
  589. // add to admin list
  590. ArrayPushString(gAdminData, admin);
  591. // keep track of where it is in the list
  592. TrieSetCell(gAuthIndex, admin[Admin_Auth], gNumAdmins);
  593. // increase array size
  594. gNumAdmins++;
  595. }
  596.  
  597. DebugLog("Loaded %d admin%s", gNumAdmins, (gNumAdmins == 1) ? "" : "s");
  598. }
  599.  
  600. // Code from Bugsy's unixtime.inc
  601. stock const YearSeconds[2] =
  602. {
  603. 31536000, //Normal year
  604. 31622400 //Leap year
  605. };
  606.  
  607. stock const MonthSeconds[12] =
  608. {
  609. 2678400, //January 31
  610. 2419200, //February 28
  611. 2678400, //March 31
  612. 2592000, //April 30
  613. 2678400, //May 31
  614. 2592000, //June 30
  615. 2678400, //July 31
  616. 2678400, //August 31
  617. 2592000, //September 30
  618. 2678400, //October 31
  619. 2592000, //November 30
  620. 2678400 //December 31
  621. };
  622.  
  623. stock const DaySeconds = 86400;
  624. stock const HourSeconds = 3600;
  625. stock const MinuteSeconds = 60;
  626.  
  627. stock TimeToUnix( const iYear , const iMonth , const iDay , const iHour , const iMinute , const iSecond )
  628. {
  629. new i;
  630. new iTimeStamp;
  631.  
  632. for ( i = 1970 ; i < iYear ; i++ )
  633. iTimeStamp += YearSeconds[ IsLeapYear(i) ];
  634.  
  635. for ( i = 1 ; i < iMonth ; i++ )
  636. iTimeStamp += SecondsInMonth( iYear , i );
  637.  
  638. iTimeStamp += ( ( iDay - 1 ) * DaySeconds );
  639. iTimeStamp += ( iHour * HourSeconds );
  640. iTimeStamp += ( iMinute * MinuteSeconds );
  641. iTimeStamp += iSecond;
  642.  
  643. return iTimeStamp;
  644. }
  645.  
  646. stock SecondsInMonth( const iYear , const iMonth )
  647. {
  648. return ( ( IsLeapYear( iYear ) && ( iMonth == 2 ) ) ? ( MonthSeconds[iMonth - 1] + DaySeconds ) : MonthSeconds[iMonth - 1] );
  649. }
  650.  
  651. stock IsLeapYear( const iYear )
  652. {
  653. return ( ( (iYear % 4) == 0) && ( ( (iYear % 100) != 0) || ( (iYear % 400) == 0 ) ) );
  654. }
  655.