32bitsBin

 

Dynamic Paste Search
Recent pastes
vacbans.sp
  1. /*
  2. *
  3. * VAC Status Checker
  4. * http://forums.alliedmods.net/showthread.php?t=80942
  5. *
  6. * Description:
  7. * Looks up VAC Status of connecting clients using the Steam
  8. * Community and takes the desired action. Useful for admins who want to
  9. * block access to people caught cheating on another engine.
  10. *
  11. * Requires Socket Extension by sfPlayer
  12. * (http://forums.alliedmods.net/showthread.php?t=67640)
  13. *
  14. * Credits:
  15. *       voogru - finding the relationship between SteamIDs and friendIDs
  16. *   StrontiumDog - the fixed function that converts SteamIDs
  17. *       berni - the original function that converts SteamIDs
  18. *       Sillium - German translation
  19. *       jack_wade - Spanish translation
  20. *       Tournevis_man - French translation
  21. *       OziOn - Danish translation
  22. *   danielsumi - Portuguese translation
  23. *   Archangel_Dm - Russian translation
  24. *   lhffan - Swedish translation
  25. *   ZuCChiNi - Turkish translation
  26. *
  27. * Changelog
  28. * Nov 15, 2013 - v.1.3.6:
  29. *               [*] Fixed DataPack operation out of bounds errors
  30. * Mar 27, 2013 - v.1.3.5:
  31. *               [*] Fixed bans firing too early
  32. * Sep 04, 2011 - v.1.3.4:
  33. *               [*] Fixed some race conditions
  34. * Feb 09, 2010 - v.1.3.3:
  35. *                               [+] Added filter for bots on client checks
  36. * Jul 24, 2009 - v.1.3.2:
  37. *                               [*] Fixed logging error
  38. * Jul 18, 2009 - v.1.3.1:
  39. *                               [*] Removed format from translations to fix odd error
  40. * May 25, 2009 - v.1.3.0:
  41. *                               [+] Added support for other named database configs
  42. * Apr 13, 2009 - v.1.2.1:
  43. *                               [*] Fixed conversion of long SteamIDs (StrontiumDog)
  44. * Mar 26, 2009 - v.1.2.0:
  45. *                               [+] Added whitelist support
  46. *                               [*] Changed some messages to reflect the plugin name
  47. * Mar 19, 2009 - v.1.1.1:
  48. *                               [*] Fixed bans triggering before client is in-game
  49. *                               [-] Removed dependency on the regex extension
  50. *                               [+] Added logging to vacbans.log for all action settings
  51. * Feb 23, 2009 - v.1.1.0:
  52. *                               [*] Now uses DataPacks instead of files for data storage
  53. *                               [+] Added RegEx to scan raw downloaded data
  54. *                               [+] Verifies client against original ID after scanning profile
  55. *                               [*] Now uses FriendID instead of SteamID for the database keys
  56. *                               [*] Various code organization improvements
  57. *                               [+] Added command to reset the local cache database
  58. * Feb 19, 2009 - v.1.0.1:
  59. *                               [*] Changed file naming to avoid conflicts
  60. * Nov 24, 2008 - v.1.0.0:
  61. *                               [*] Initial Release
  62. *
  63. */
  64.  
  65. #pragma semicolon 1
  66. #include <sourcemod>
  67. #include <socket>
  68.  
  69. #define PLUGIN_VERSION "1.3.6"
  70.  
  71. public plugin:myinfo =
  72. {
  73.         name = "VAC Status Checker",
  74.         author = "Stevo.TVR",
  75.         description = "Looks up VAC status of connecting clients and takes desired action",
  76.         version = PLUGIN_VERSION,
  77.         url = "http://www.theville.org"
  78. }
  79.  
  80. new handle:hDatabase = INVALID_HANDLE;
  81.  
  82. new handle:sm_vacbans_db = INVALID_HANDLE;
  83. new handle:sm_vacbans_cachetime = INVALID_HANDLE;
  84. new handle:sm_vacbans_action = INVALID_HANDLE;
  85.  
  86. public onpluginstart()
  87. {
  88.         createconvar("sm_vacbans_version", PLUGIN_VERSION, "VAC Ban Checker plugin version", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
  89.         sm_vacbans_db = createconvar("sm_vacbans_db", "storage-local", "The named database config to use for caching");
  90.         sm_vacbans_cachetime = createconvar("sm_vacbans_cachetime", "30", "How long in days before re-checking the same client for VAC status", _, true, 0.0);
  91.         sm_vacbans_action = createconvar("sm_vacbans_action", "0", "Action to take on VAC banned clients (0 = ban, 1 = kick, 2 = log to file)", _, true, 0.0, true, 2.0);
  92.         autoexecconfig(true, "vacbans");
  93.        
  94.         regconsolecmd("sm_vacbans_reset", Command_Reset);
  95.         regconsolecmd("sm_vacbans_whitelist", Command_Whitelist);
  96.        
  97.         loadtranslations("vacbans.phrases");
  98. }
  99.  
  100. {
  101.         decl string:db[64];
  102.         getconvarstring(sm_vacbans_db, db, sizeof(db));
  103.         sql_tconnect(T_DBConnect, db);
  104. }
  105.  
  106. public onclientpostadmincheck(client)
  107. {
  108.         if(!isfakeclient(client))
  109.         {
  110.                 decl string:query[1024];
  111.                 decl string:steamID[64];
  112.                 decl string:friendID[32];
  113.                
  114.                 getclientauthstring(client, steamID, sizeof(steamID));
  115.                
  116.                 if(GetFriendID(steamID, friendID, sizeof(friendID)))
  117.                 {
  118.                         new handle:hPack = createdatapack();
  119.                         writepackcell(hPack, client);
  120.                         writepackstring(hPack, friendID);
  121.                        
  122.                         format(query, sizeof(query), "SELECT * FROM `vacbans` WHERE `steam_id` = '%s' AND (`expire` > %d OR `expire` = 0) LIMIT 1;", friendID, gettime());
  123.                         sql_tquery(hDatabase, T_PlayerLookup, query, hPack);
  124.                 }
  125.         }
  126. }
  127.  
  128. public OnSocketConnected(handle:hSock, any:hPack)
  129. {
  130.         new string:friendID[32];
  131.         decl string:requestStr[128];
  132.        
  133.         setpackposition(hPack, 16);
  134.         readpackstring(hPack, friendID, sizeof(friendID));
  135.        
  136.         format(requestStr, sizeof(requestStr), "GET /profiles/%s?xml=1 HTTP/1.0rnHost: %srnConnection: closernrn", friendID, "steamcommunity.com");
  137.         SocketSend(hSock, requestStr);
  138. }
  139.  
  140. public OnSocketConnected2(handle:hSock, any:hPack)
  141. {
  142.         decl string:redirURL[64];
  143.         decl string:requestStr[512];
  144.        
  145.         setpackposition(hPack, 8);
  146.         new handle:hData = handle:readpackcell(hPack);
  147.        
  148.         resetpack(hData);
  149.         readpackstring(hData, redirURL, sizeof(redirURL));
  150.         resetpack(hData, true);
  151.        
  152.         format(requestStr, sizeof(requestStr), "GET %s?xml=1 HTTP/1.0rnHost: %srnConnection: closernrn", redirURL, "steamcommunity.com");
  153.         SocketSend(hSock, requestStr);
  154. }
  155.  
  156. public OnSocketReceive(handle:hSock, string:receiveData[], const dataSize, any:hPack)
  157. {
  158.         setpackposition(hPack, 8);
  159.         new handle:hData = handle:readpackcell(hPack);
  160.        
  161.         writepackstring(hData, receiveData);
  162. }
  163.  
  164. public OnSocketDisconnected(handle:hSock, any:hPack)
  165. {
  166.         new string:XMLData[4096];
  167.        
  168.         closehandle(hSock);
  169.        
  170.         resetpack(hPack);
  171.         new client = readpackcell(hPack);
  172.         new handle:hData = handle:readpackcell(hPack);
  173.        
  174.         resetpack(hData);
  175.         decl string:buffer[4096];
  176.         while(ispackreadable(hData, 1)) {
  177.                 readpackstring(hData, buffer, sizeof(buffer));
  178.                 StrCat(XMLData, sizeof(XMLData), buffer);
  179.         }
  180.        
  181.         new pos;
  182.         if((pos = strcontains(XMLData, "Location: http://steamcommunity.com", false)) >= 0)
  183.         {
  184.                 decl string:redirURL[64];
  185.                 splitstring(XMLData[pos+35], "r", redirURL, sizeof(redirURL));
  186.                
  187.                 resetpack(hData, true);
  188.                 writepackstring(hData, redirURL);
  189.                
  190.                 // Create a second socket because the original is invalid for some reason
  191.                 hSock = SocketCreate(SOCKET_TCP, OnSocketError);
  192.                 SocketSetArg(hSock, hPack);
  193.                 SocketConnect(hSock, OnSocketConnected2, OnSocketReceive, OnSocketDisconnected, "steamcommunity.com", 80);
  194.         }
  195.         else if((pos = strcontains(XMLData, "<vacBanned>")) >= 0)
  196.         {
  197.                 decl string:friendID[32];
  198.                 readpackstring(hPack, friendID, sizeof(friendID));
  199.                 new string:banned[2];
  200.                 strcopy(banned, sizeof(banned), XMLData[pos+11]);
  201.                
  202.                 HandleClient(client, friendID, StrEqual(banned, "1"));
  203.                
  204.                 closehandle(hData);
  205.                 closehandle(hPack);
  206.         }
  207.         else
  208.         {
  209.                 closehandle(hData);
  210.                 closehandle(hPack);
  211.         }
  212. }
  213.  
  214. public OnSocketError(handle:hSock, const errorType, const errorNum, any:hPack)
  215. {
  216.         logerror("Socket error %d (errno %d)", errorType, errorNum);
  217.        
  218.         closehandle(hPack);
  219.         closehandle(hSock);
  220. }
  221.  
  222. public action:Command_Reset(client, args)
  223. {
  224.         if(client == 0 || ((getuserflagbits(client) & ADMFLAG_RCON) == ADMFLAG_RCON))
  225.         {
  226.                 sql_fastquery(hDatabase, "DELETE FROM `vacbans` WHERE `expire` != 0;");
  227.                 replytocommand(client, "[SM] Local VAC Status Checker cache has been reset.");
  228.         }
  229.         return Plugin_Handled;
  230. }
  231.  
  232. public action:Command_Whitelist(client, args)
  233. {
  234.         if(client == 0 || ((getuserflagbits(client) & ADMFLAG_RCON) == ADMFLAG_RCON))
  235.         {
  236.                 if(args >= 2)
  237.                 {
  238.                         decl string:argString[72];
  239.                         decl string:action[8];
  240.                         decl string:steamID[64];
  241.                         decl string:friendID[64];
  242.                        
  243.                         getcmdargstring(argString, sizeof(argString));
  244.                         new pos = breakstring(argString, action, sizeof(action));
  245.                         strcopy(steamID, sizeof(steamID), argString[pos]);
  246.                        
  247.                        
  248.                         if(GetFriendID(steamID, friendID, sizeof(friendID)))
  249.                         {
  250.                                 decl string:query[1024];
  251.                                 if(StrEqual(action, "add"))
  252.                                 {
  253.                                         format(query, sizeof(query), "REPLACE INTO `vacbans` VALUES('%s', '0', '0');", friendID);
  254.                                         sql_tquery(hDatabase, T_FastQuery, query);
  255.                                        
  256.                                         replytocommand(client, "[SM] STEAM_%s added to the VAC Status Checker whitelist.", steamID);
  257.                                        
  258.                                         return Plugin_Handled;
  259.                                 }
  260.                                 if(StrEqual(action, "remove"))
  261.                                 {
  262.                                         format(query, sizeof(query), "DELETE FROM `vacbans` WHERE `steam_id` = '%s';", friendID);
  263.                                         sql_tquery(hDatabase, T_FastQuery, query);
  264.                                        
  265.                                         replytocommand(client, "[SM] STEAM_%s removed from the VAC Status Checker whitelist.", steamID);
  266.                                        
  267.                                         return Plugin_Handled;
  268.                                 }
  269.                         }
  270.                 }
  271.                 else if(args == 1)
  272.                 {
  273.                         decl string:action[8];
  274.                        
  275.                         getcmdarg(1, action, sizeof(action));
  276.                        
  277.                         if(StrEqual(action, "clear"))
  278.                         {
  279.                                 sql_tquery(hDatabase, T_FastQuery, "DELETE FROM `vacbans` WHERE `expire` = 0;");
  280.                                
  281.                                 replytocommand(client, "[SM] VAC Status Checker whitelist cleared.");
  282.                                
  283.                                 return Plugin_Handled;
  284.                         }
  285.                 }
  286.                
  287.                 replytocommand(client, "Usage: sm_vacbans_whitelist <add|remove|clear> [SteamID]");
  288.         }
  289.         return Plugin_Handled;
  290. }
  291.  
  292. HandleClient(client, const string:friendID[], bool:vacBanned)
  293. {
  294.         if(isclientauthorized(client))
  295.         {
  296.                 // Check to make sure this is the same client that originally connected
  297.                 decl string:steamID[64];
  298.                 getclientauthstring(client, steamID, sizeof(steamID));
  299.                 decl string:clientFriendID[32];
  300.                 if(!GetFriendID(steamID, clientFriendID, sizeof(clientFriendID)) || !StrEqual(friendID, clientFriendID))
  301.                 {
  302.                         return;
  303.                 }
  304.                
  305.                 new banned = 0;
  306.                 new expire = gettime() + (getconvarint(sm_vacbans_cachetime)*86400);
  307.                 new action = getconvarint(sm_vacbans_action);
  308.                
  309.                 if(vacBanned)
  310.                 {
  311.                         banned = 1;
  312.                         switch(action)
  313.                         {
  314.                                 case 0:
  315.                                 {
  316.                                         decl string:userformat[64];
  317.                                         format(userformat, sizeof(userformat), "%L", client);
  318.                                         logaction(0, client, "%s %T", userformat, "Banned_Server", LANG_SERVER);
  319.                                        
  320.                                         servercommand("sm_ban #%d 0 "[VAC Status Checker] %T"", getclientuserid(client), "Banned", client);
  321.                                 }
  322.                                 case 1:
  323.                                 {
  324.                                         kickclient(client, "[VAC Bans] %t", "Kicked");
  325.                                 }
  326.                         }
  327.                         decl string:path[PLATFORM_MAX_PATH];
  328.                         buildpath(PathType:Path_SM, path, sizeof(path), "logs/vacbans.log");
  329.                         logtofile(path, "Player %L is VAC Banned", client);
  330.                 }
  331.                
  332.                 decl string:query[1024];
  333.                 format(query, sizeof(query), "REPLACE INTO `vacbans` VALUES('%s', '%d', '%d');", friendID, banned, expire);
  334.                 sql_tquery(hDatabase, T_FastQuery, query);
  335.         }
  336. }
  337.  
  338. bool:GetFriendID(string:AuthID[], string:FriendID[], size)
  339. {
  340.         replacestring(AuthID, strlen(AuthID), "STEAM_", "");
  341.         if (StrEqual(AuthID, "ID_LAN"))
  342.         {
  343.                 FriendID[0] = '';
  344.                 return false;
  345.         }
  346.         decl string:toks[3][16];
  347.         new upper = 765611979;
  348.         new string:temp[12], string:carry[12];
  349.  
  350.         ExplodeString(AuthID, ":", toks, sizeof(toks), sizeof(toks[]));
  351.         new iServer = stringtoint(toks[1]);
  352.         new iAuthID = stringtoint(toks[2]);
  353.         new iFriendID = (iAuthID*2) + 60265728 + iServer;
  354.  
  355.         if (iFriendID >= 100000000)
  356.         {
  357.                 format(temp, sizeof(temp), "%d", iFriendID);
  358.                 format(carry, 2, "%s", temp);
  359.                 new icarry = stringtoint(carry[0]);
  360.                 upper += icarry;
  361.  
  362.                 format(temp, sizeof(temp), "%d", iFriendID);
  363.                 format(FriendID, size, "%d%s", upper, temp[1]);
  364.         }
  365.         else
  366.         {
  367.                 format(FriendID, size, "765611979%d", iFriendID);
  368.         }
  369.  
  370.         return true;
  371. }
  372.  
  373. // Threaded DB stuff
  374. public T_DBConnect(handle:owner, handle:hndl, const string:error[], any:data)
  375. {
  376.         if(hndl == INVALID_HANDLE)
  377.         {
  378.                 setfailstate(error);
  379.         }
  380.         hDatabase = hndl;
  381.         sql_tquery(hDatabase, T_FastQuery, "CREATE TABLE IF NOT EXISTS `vacbans` (`steam_id` VARCHAR(64) NOT NULL, `banned` BOOL NOT NULL, `expire` INT(11) NOT NULL, PRIMARY KEY (`steam_id`));");
  382. }
  383.  
  384. public T_PlayerLookup(handle:owner, handle:hQuery, const string:error[], any:hPack)
  385. {
  386.         new bool:checked = false;
  387.        
  388.         resetpack(hPack);
  389.         new client = readpackcell(hPack);
  390.         decl string:friendID[32];
  391.         readpackstring(hPack, friendID, sizeof(friendID));
  392.         closehandle(hPack);
  393.        
  394.         if(hQuery != INVALID_HANDLE)
  395.         {
  396.                 if(sql_getrowcount(hQuery) > 0)
  397.                 {
  398.                         checked = true;
  399.                         while(sql_fetchrow(hQuery))
  400.                         {
  401.                                 if(sql_fetchint(hQuery, 1) > 0)
  402.                                 {
  403.                                         HandleClient(client, friendID, true);
  404.                                 }
  405.                         }
  406.                 }
  407.         }
  408.        
  409.         if(!checked)
  410.         {
  411.                 new handle:hPack2 = createdatapack();
  412.                 new handle:hData = createdatapack();
  413.                 new handle:hSock = SocketCreate(SOCKET_TCP, OnSocketError);
  414.                
  415.                 writepackcell(hPack2, client);
  416.                 writepackcell(hPack2, _:hData);
  417.                 writepackstring(hPack2, friendID);
  418.                
  419.                 SocketSetArg(hSock, hPack2);
  420.                 SocketConnect(hSock, OnSocketConnected, OnSocketReceive, OnSocketDisconnected, "steamcommunity.com", 80);
  421.         }
  422. }
  423.  
  424. public T_FastQuery(handle:owner, handle:hndl, const string:error[], any:data)
  425. {
  426.         // Nothing to do
  427. }
  428.  
  429. // You're crazy, man...
Parsed in 0.452 seconds