2017-02-26 00:25:51 +01:00
# pragma dynamic 4194304 // Increases stack space to 4mb, needed for encryption
# include <sourcemod>
# include <regex>
// Core includes
# include "steamcore/bigint.sp"
# include "steamcore/rsa.sp"
# define AUTOLOAD_EXTENSIONS
# define REQUIRE_EXTENSIONS
# include <SteamWorks>
# define PLUGIN_URL ""
2017-04-24 16:01:51 +02:00
# define PLUGIN_VERSION "1.7.1"
2017-02-26 00:25:51 +01:00
# define PLUGIN_NAME "SteamCore"
# define PLUGIN_AUTHOR "Statik"
public Plugin : myinfo =
{
name = PLUGIN_NAME ,
author = PLUGIN_AUTHOR ,
description = " Sourcemod natives to interact with Steam functions. " ,
version = PLUGIN_VERSION ,
url = PLUGIN_URL
}
new bool : DEBUG = false ;
new const TIMER_UPDATE_TIME = 6 ;
new const TOKEN_LIFETIME = 50 ;
new const Float : TIMEOUT_TIME = 10.0 ;
new Handle : cvarUsername ;
new Handle : cvarPassword ;
new Handle : cvarDebug ;
new String : username [ 32 ] = " " ;
new String : passphrase [ 32 ] = " " ;
new String : sessionToken [ 32 ] = " " ;
new String : sessionCookie [ 256 ] = " " ;
new bool : isLogged = false ;
new bool : isBusy = false ;
new Handle : request ;
new caller ;
new timeSinceLastLogin ;
new Handle : hTimeIncreaser ;
new Handle : timeoutTimer ;
new bool : connectionInterrupted ;
new Handle : callbackHandle ;
new Handle : callbackPlugin ;
new Function : callbackFunction ;
new Handle : finalRequest ;
new SteamWorksHTTPRequestCompleted : finalFunction ;
// ===================================================================================
// ===================================================================================
public APLRes : AskPluginLoad2 ( Handle : plugin , bool : late , String : error [ ] , err_max )
{
// Native creation
CreateNative ( " IsSteamCoreBusy " , nativeIsSteamCoreBusy ) ;
CreateNative ( " SteamGroupAnnouncement " , nativeGroupAnnouncement ) ;
CreateNative ( " SteamGroupInvite " , nativeGroupInvite ) ;
RegPluginLibrary ( " steamcore " ) ;
return APLRes_Success ;
}
public OnPluginStart ( )
{
// Callbacks
callbackHandle = CreateForward ( ET_Ignore , Param_Cell , Param_Cell , Param_Cell , Param_Cell ) ;
// Timers
hTimeIncreaser = CreateTimer ( TIMER_UPDATE_TIME * 60.0 , timeIncreaser , INVALID_HANDLE , TIMER_REPEAT ) ;
// Convars
CreateConVar ( " steamcore_version " , PLUGIN_VERSION , " SteamCore Version " , FCVAR_SPONLY | FCVAR_DONTRECORD | FCVAR_NOTIFY ) ;
cvarUsername = CreateConVar ( " sc_username " , " " , " Steam login username. " , FCVAR_PROTECTED ) ;
cvarPassword = CreateConVar ( " sc_password " , " " , " Steam login password. " , FCVAR_PROTECTED ) ;
cvarDebug = CreateConVar ( " sc_debug " , " 0 " , " Toggles debugging. " , 0 , true , 0.0 , true , 1.0 ) ;
HookConVarChange ( cvarUsername , OnLoginInfoChange ) ;
HookConVarChange ( cvarPassword , OnLoginInfoChange ) ;
HookConVarChange ( cvarDebug , OnDebugStatusChange ) ;
timeSinceLastLogin = TOKEN_LIFETIME ;
2017-04-24 16:01:51 +02:00
AutoExecConfig ( true , " plugin.steamcore " ) ;
2017-02-26 00:25:51 +01:00
}
public OnLoginInfoChange ( Handle : cvar , const String : oldVal [ ] , const String : newVal [ ] )
{
isLogged = false ;
}
public OnDebugStatusChange ( Handle : cvar , const String : oldVal [ ] , const String : newVal [ ] )
{
DEBUG = bool : StringToInt ( newVal ) ;
}
public Action : timeIncreaser ( Handle : timer )
{
timeSinceLastLogin + = TIMER_UPDATE_TIME ;
PrintDebug ( 0 , " \n ============================================================================ \n " ) ;
PrintDebug ( 0 , " Time since last login: %i minutes. " , timeSinceLastLogin ) ;
if ( timeSinceLastLogin > = TOKEN_LIFETIME )
{
isLogged = false ;
PrintDebug ( 0 , " Expired token lifetime (%i) " , TOKEN_LIFETIME ) ;
}
return Plugin_Continue ;
}
public OnConfigsExecuted ( )
{
DEBUG = GetConVarBool ( FindConVar ( " sc_debug " ) ) ;
if ( timeSinceLastLogin > 10 )
{
PrintDebug ( 0 , " \n ============================================================================ \n " ) ;
PrintDebug ( 0 , " Logging in to keep login alive... " ) ;
startRequest ( 0 , INVALID_HANDLE , INVALID_FUNCTION , INVALID_HANDLE , INVALID_FUNCTION ) ; // Starts an empty login request
}
}
// ===================================================================================
// ===================================================================================
public nativeIsSteamCoreBusy ( Handle : plugin , numParams )
{
return _ : isBusy ;
}
public nativeGroupAnnouncement ( Handle : plugin , numParams )
{
decl String : title [ 256 ] ;
decl String : body [ 1024 ] ;
decl String : groupID [ 64 ] ;
new client = GetNativeCell ( 1 ) ;
GetNativeString ( 2 , title , sizeof ( title ) ) ;
GetNativeString ( 3 , body , sizeof ( body ) ) ;
GetNativeString ( 4 , groupID , sizeof ( groupID ) ) ;
decl String : URL [ 128 ] ;
Format ( URL , sizeof ( URL ) , " http://steamcommunity.com/gid/%s/announcements " , groupID ) ;
PrintDebug ( client , " \n ============================================================================ \n " ) ;
PrintDebug ( client , " Preparing request to: \n %s... " , URL ) ;
PrintDebug ( client , " Title: \n %s " , title ) ;
PrintDebug ( client , " Body: \n %s " , body ) ;
PrintDebug ( client , " Verifying login... " ) ;
new Handle : _finalRequest = SteamWorks_CreateHTTPRequest ( k_EHTTPMethodPOST , URL ) ;
SteamWorks_SetHTTPRequestHeaderValue ( _finalRequest , " Cookie " , sessionCookie ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " action " , " post " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " sessionID " , sessionToken ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " headline " , title ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " body " , body ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " languages[0][headline] " , title ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " languages[0][body] " , body ) ;
startRequest ( client , _finalRequest , cbkGroupAnnouncement , plugin , GetNativeFunction ( 5 ) ) ;
}
public nativeGroupInvite ( Handle : plugin , numParams )
{
decl String : invitee [ 64 ] ;
decl String : groupID [ 64 ] ;
new client = GetNativeCell ( 1 ) ;
GetNativeString ( 2 , invitee , sizeof invitee ) ;
GetNativeString ( 3 , groupID , sizeof groupID ) ;
decl String : URL [ ] = " http://steamcommunity.com/actions/GroupInvite " ;
PrintDebug ( client , " \n ============================================================================ \n " ) ;
PrintDebug ( client , " Preparing request to: \n %s... " , URL ) ;
PrintDebug ( client , " Invitee community ID: \n %s " , invitee ) ;
PrintDebug ( client , " Group community ID: \n %s " , groupID ) ;
PrintDebug ( client , " Verifying login... " ) ;
new Handle : _finalRequest = SteamWorks_CreateHTTPRequest ( k_EHTTPMethodGET , URL ) ;
SteamWorks_SetHTTPRequestHeaderValue ( _finalRequest , " Accept " , " */* " ) ;
SteamWorks_SetHTTPRequestHeaderValue ( _finalRequest , " Accept-Encoding " , " gzip, deflate " ) ;
SteamWorks_SetHTTPRequestHeaderValue ( _finalRequest , " User-Agent " , " Mozilla/5.0 (Windows NT 6.3; WOW64) " ) ;
SteamWorks_SetHTTPRequestHeaderValue ( _finalRequest , " Cookie " , sessionCookie ) ;
//SteamWorks_SetHTTPRequestGetOrPostParameter(_finalRequest, "json", "1");
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " type " , " groupInvite " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " sessionID " , sessionToken ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " group " , groupID ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( _finalRequest , " invitee " , invitee ) ;
startRequest ( client , _finalRequest , cbkGroupInvite , plugin , GetNativeFunction ( 4 ) ) ;
}
// ===================================================================================
// ===================================================================================
startRequest ( client , Handle : _finalRequest , SteamWorksHTTPRequestCompleted : _finalFunction , Handle : _callbackPlugin , Function : _callbackFunction )
{
if ( isBusy )
{
PrintDebug ( client , " \n ============================================================================ \n " ) ;
PrintDebug ( client , " Plugin is busy with other task at this time, rejecting request... " ) ;
if ( _callbackFunction ! = INVALID_FUNCTION ) // There is an actual function callback
{
new pluginIteratorNumber = GetPluginIteratorNumber ( _callbackPlugin ) ;
new Handle : datapack ;
CreateDataTimer ( 0.1 , tmrBusyCallback , datapack ) ;
WritePackCell ( datapack , client ) ;
WritePackCell ( datapack , pluginIteratorNumber ) ;
WritePackFunction ( datapack , Function : _callbackFunction ) ;
CloseHandle ( _finalRequest ) ;
}
return ;
}
isBusy = true ;
connectionInterrupted = false ;
caller = client ;
finalRequest = _finalRequest ;
finalFunction = _finalFunction ;
callbackPlugin = _callbackPlugin ;
callbackFunction = _callbackFunction ;
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
if ( callbackFunction ! = INVALID_FUNCTION ) // There is an actual function callback
{
AddToForward ( callbackHandle , callbackPlugin , callbackFunction ) ;
if ( isLogged )
{
PrintDebug ( caller , " Already logged in, executing request... " ) ;
SteamWorks_SetHTTPCallbacks ( finalRequest , finalFunction )
SteamWorks_SendHTTPRequest ( finalRequest ) ;
startTimeoutTimer ( ) ;
return ;
}
}
GetConVarString ( cvarUsername , username , sizeof ( username ) ) ;
GetConVarString ( cvarPassword , passphrase , sizeof ( passphrase ) ) ;
if ( StrEqual ( username , " " ) | | StrEqual ( passphrase , " " ) )
{
PrintDebug ( caller , " Invalid login information, check cvars. ABORTED. " ) ;
onRequestResult ( caller , false , 0x03 ) ; // Invalid login information
return ;
}
request = SteamWorks_CreateHTTPRequest ( k_EHTTPMethodGET , " http://steamcommunity.com/login/getrsakey/ " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " username " , username ) ;
SteamWorks_SetHTTPCallbacks ( request , cbkRsaKeyRequest ) ;
SteamWorks_SendHTTPRequest ( request ) ;
startTimeoutTimer ( ) ;
PrintDebug ( caller , " Obtaining RSA Key from steamcommunity.com/login/getrsakey... " ) ;
}
startTimeoutTimer ( )
{
stopTimeoutTimer ( ) ;
timeoutTimer = CreateTimer ( TIMEOUT_TIME , tmrTimeout ) ;
}
stopTimeoutTimer ( )
{
if ( timeoutTimer ! = INVALID_HANDLE )
{
KillTimer ( timeoutTimer ) ;
timeoutTimer = INVALID_HANDLE ;
}
}
public Action : tmrTimeout ( Handle : timer )
{
PrintDebug ( caller , " Connection timed out. " ) ;
connectionInterrupted = true ;
onRequestResult ( caller , false , 0x02 ) ;
timeoutTimer = INVALID_HANDLE ;
}
public Action : tmrBusyCallback ( Handle : timer , Handle : pack )
{
ResetPack ( pack ) ;
new client = ReadPackCell ( pack ) ;
new pluginIteratorNumber = ReadPackCell ( pack ) ;
new Handle : callbackPl = FindPluginFromNumber ( pluginIteratorNumber ) ;
new Function : callbackFunc = ReadPackFunction ( pack ) ;
new bool : success = RemoveFromForward ( callbackHandle , callbackPlugin , callbackFunction ) ;
new functionCount = GetForwardFunctionCount ( callbackHandle ) ;
PrintDebug ( caller , " Removing main callback from forward - Result: %i, - Forward Function Count: %i " , success , functionCount ) ;
success = AddToForward ( callbackHandle , callbackPl , callbackFunc ) ;
functionCount = GetForwardFunctionCount ( callbackHandle ) ;
PrintDebug ( caller , " Adding temporal callback from forward - Result: %i, - Forward Function Count: %i " , success , functionCount ) ;
// Start function call
Call_StartForward ( callbackHandle ) ;
// Push parameters one at a time
Call_PushCell ( client ) ;
Call_PushCell ( false ) ;
Call_PushCell ( 0x01 ) ; // Plugin is busy
Call_PushCell ( 0 ) ;
// Finish the call
new result = Call_Finish ( ) ;
PrintDebug ( caller , " Temporal callback calling error code: %i (0: Success) " , result ) ;
success = RemoveFromForward ( callbackHandle , callbackPl , callbackFunc ) ;
functionCount = GetForwardFunctionCount ( callbackHandle ) ;
PrintDebug ( caller , " Removing temporal callback from forward - Result: %i, - Forward Function Count: %i " , success , functionCount ) ;
success = AddToForward ( callbackHandle , callbackPlugin , callbackFunction ) ;
functionCount = GetForwardFunctionCount ( callbackHandle ) ;
PrintDebug ( caller , " Re-adding main callback from forward - Result: %i, - Forward Function Count: %i " , success , functionCount ) ;
callbackPl = INVALID_HANDLE ;
callbackFunc = INVALID_FUNCTION ;
PrintDebug ( caller , " Task rejected. " ) ;
}
public cbkRsaKeyRequest ( Handle : response , bool : failure , bool : requestSuccessful , EHTTPStatusCode : statusCode )
{
stopTimeoutTimer ( ) ;
if ( connectionInterrupted )
{
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
if ( response = = INVALID_HANDLE | | ! requestSuccessful | | statusCode ! = k_EHTTPStatusCode200OK )
{
PrintDebug ( caller , " RSA Key request failed (%i). Status Code: %i. ABORTED " , requestSuccessful , statusCode ) ;
onRequestResult ( caller , false , 0x04 ) ; // Failed http RSA Key request
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
new bodySize ;
SteamWorks_GetHTTPResponseBodySize ( request , bodySize ) ;
decl String : responseBody [ bodySize ] ;
SteamWorks_GetHTTPResponseBodyData ( request , responseBody , bodySize ) ;
PrintDebug ( caller , responseBody ) ;
if ( StrContains ( responseBody , " \" success \" :true " , false ) = = - 1 )
{
PrintDebug ( caller , " Could not get RSA Key, aborting... " ) ;
onRequestResult ( caller , false , 0x05 ) ; // RSA Key response failed, unknown reason
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
new Handle : regex ;
regex = CompileRegex ( " \" publickey_mod \" : \" (.*?) \" " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : rsaPublicMod [ 1024 ] ;
GetRegexSubString ( regex , 1 , rsaPublicMod , sizeof ( rsaPublicMod ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
PrintDebug ( caller , " RSA KEY MODULUS (%i): \n %s " , strlen ( rsaPublicMod ) , rsaPublicMod ) ;
regex = CompileRegex ( " \" publickey_exp \" : \" (.*?) \" " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : rsaPublicExp [ 16 ] ;
GetRegexSubString ( regex , 1 , rsaPublicExp , sizeof ( rsaPublicExp ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
PrintDebug ( caller , " RSA KEY EXPONENT (%i): %s " , strlen ( rsaPublicExp ) , rsaPublicExp ) ;
regex = CompileRegex ( " \" timestamp \" : \" (.*?) \" " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : steamTimestamp [ 16 ] ;
GetRegexSubString ( regex , 1 , steamTimestamp , sizeof ( steamTimestamp ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
PrintDebug ( caller , " STEAM TIMESTAMP (%i): %s " , strlen ( steamTimestamp ) , steamTimestamp ) ;
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
PrintDebug ( caller , " Encrypting passphrase ******** with RSA public key... " ) ;
decl String : encryptedPassword [ 1024 ] ;
rsaEncrypt ( rsaPublicMod , rsaPublicExp , passphrase , encryptedPassword , sizeof ( encryptedPassword ) ) ;
PrintDebug ( caller , " Encrypted passphrase with RSA cryptosystem (%i): \n %s " , strlen ( encryptedPassword ) , encryptedPassword ) ;
decl numericPassword [ 1024 ] ;
hexString2BigInt ( encryptedPassword , numericPassword , sizeof ( numericPassword ) ) ;
encodeBase64 ( numericPassword , strlen ( rsaPublicMod ) , encryptedPassword , sizeof ( encryptedPassword ) ) ;
PrintDebug ( caller , " Encoded encrypted passphrase with base64 algorithm (%i): \n %s " , strlen ( encryptedPassword ) , encryptedPassword ) ;
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
PrintDebug ( caller , " Logging in to steamcommunity.com/login/dologin/... " ) ;
request = SteamWorks_CreateHTTPRequest ( k_EHTTPMethodGET , " https://steamcommunity.com/login/dologin/ " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " password " , encryptedPassword ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " username " , username ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " twofactorcode " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " emailauth " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " loginfriendlyname " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " captchagid " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " captcha_text " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " emailsteamid " , " " ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " rsatimestamp " , steamTimestamp ) ;
SteamWorks_SetHTTPRequestGetOrPostParameter ( request , " remember_login " , " false " ) ;
SteamWorks_SetHTTPCallbacks ( request , cbkLoginRequest ) ;
SteamWorks_SendHTTPRequest ( request ) ;
startTimeoutTimer ( ) ;
}
public cbkLoginRequest ( Handle : response , bool : failure , bool : requestSuccessful , EHTTPStatusCode : statusCode )
{
stopTimeoutTimer ( ) ;
if ( connectionInterrupted )
{
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
if ( response = = INVALID_HANDLE | | ! requestSuccessful | | statusCode ! = k_EHTTPStatusCode200OK )
{
PrintDebug ( caller , " Login request failed (%i). Status Code: %i. ABORTED " , requestSuccessful , statusCode ) ;
onRequestResult ( caller , false , 0x06 ) ; // Failed htpps login request
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
new bodySize ;
SteamWorks_GetHTTPResponseBodySize ( response , bodySize ) ;
decl String : responseBody [ bodySize ] ;
SteamWorks_GetHTTPResponseBodyData ( response , responseBody , bodySize ) ;
new Handle : regex ;
regex = CompileRegex ( " \" success \" :(.*?), " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : successString [ 20 ] ;
GetRegexSubString ( regex , 1 , successString , sizeof ( successString ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
if ( strcmp ( successString , " true " ) ! = 0 ) // successString != true
{
PrintDebug ( caller , " Aborted logging, incorrect response body (%i): \n %s " , strlen ( responseBody ) , responseBody ) ;
onRequestResult ( caller , false , 0x07 ) ; // Incorrect login data, required captcha or e-mail confirmation (Steam Guard)
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
new cookieSize ;
SteamWorks_GetHTTPResponseHeaderSize ( response , " Set-Cookie " , cookieSize ) ;
SteamWorks_GetHTTPResponseHeaderValue ( response , " Set-Cookie " , sessionCookie , cookieSize ) ;
// Cleaning cookie
ReplaceString ( sessionCookie , sizeof sessionCookie , " path=/, " , " " ) ;
ReplaceString ( sessionCookie , sizeof sessionCookie , " path=/; httponly, " , " " ) ;
ReplaceString ( sessionCookie , sizeof sessionCookie , " path=/; secure; httponly " , " " ) ;
PrintDebug ( caller , " Success, got response (%i): \n %s " , strlen ( responseBody ) , responseBody ) ;
PrintDebug ( caller , " Stored Cookie (%i): \n %s " , strlen ( sessionCookie ) , sessionCookie ) ;
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
PrintDebug ( caller , " Logging successful, obtaining session token... " ) ;
request = SteamWorks_CreateHTTPRequest ( k_EHTTPMethodGET , " http://steamcommunity.com/profiles/RedirectToHome " ) ;
SteamWorks_SetHTTPRequestHeaderValue ( request , " Cookie " , sessionCookie ) ;
SteamWorks_SetHTTPCallbacks ( request , cbkTokenRequest ) ;
SteamWorks_SendHTTPRequest ( request ) ;
startTimeoutTimer ( ) ;
}
public cbkTokenRequest ( Handle : response , bool : failure , bool : requestSuccessful , EHTTPStatusCode : statusCode )
{
stopTimeoutTimer ( ) ;
if ( connectionInterrupted )
{
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
if ( response = = INVALID_HANDLE | | ! requestSuccessful | | statusCode ! = k_EHTTPStatusCode200OK )
{
PrintDebug ( caller , " Session Token request failed (%i). Status Code: %i. ABORTED " , requestSuccessful , statusCode ) ;
onRequestResult ( caller , false , 0x08 ) ; // Failed http token request
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
new bodySize ;
SteamWorks_GetHTTPResponseBodySize ( response , bodySize ) ;
decl String : responseBody [ bodySize ] ;
SteamWorks_GetHTTPResponseBodyData ( response , responseBody , bodySize ) ;
new Handle : regex ;
regex = CompileRegex ( " g_steamID = (.*?); " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : steamId [ 20 ] ;
GetRegexSubString ( regex , 1 , steamId , sizeof ( steamId ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
regex = CompileRegex ( " g_sessionID = \" (.*?) \" " ) ;
MatchRegex ( regex , responseBody ) ;
GetRegexSubString ( regex , 1 , sessionToken , sizeof ( sessionToken ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
if ( strcmp ( steamId , " false " ) = = 0 ) // steamId == false
{
PrintDebug ( caller , " Could not get session token. Got: \" %s \" . Incorrect Cookie? " , steamId ) ;
onRequestResult ( caller , false , 0x09 ) ; // Invalid session token. Incorrect cookie?
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
return ;
}
isLogged = true ;
// Cleaning cookie
ReplaceString ( sessionCookie , sizeof sessionCookie , " path=/; httponly, " , " " ) ;
ReplaceString ( sessionCookie , sizeof sessionCookie , " path=/; secure; httponly " , " " ) ;
Format ( sessionCookie , sizeof sessionCookie , " Steam_Language=english; sessionid=%s; %s " , sessionToken , sessionCookie ) ;
PrintDebug ( caller , " Session token successfully acquired (%i): %s " , strlen ( sessionToken ) , sessionToken ) ;
PrintDebug ( caller , " Current session for Steam ID (%i): %s " , strlen ( steamId ) , steamId ) ;
PrintDebug ( caller , " Appended session token to clean cookie, actual cookie (%i): \n %s " , strlen ( sessionCookie ) , sessionCookie ) ;
if ( finalRequest ! = INVALID_HANDLE )
{
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
PrintDebug ( caller , " Executing final request... " ) ;
SteamWorks_SetHTTPCallbacks ( finalRequest , finalFunction ) ;
SteamWorks_SendHTTPRequest ( finalRequest ) ;
startTimeoutTimer ( ) ;
}
else
{
PrintDebug ( caller , " There is no final request, logged in successfully. " ) ;
onRequestResult ( caller , true ) ;
}
CloseHandle ( request ) ;
request = INVALID_HANDLE ;
}
public cbkGroupAnnouncement ( Handle : response , bool : failure , bool : requestSuccessful , EHTTPStatusCode : statusCode )
{
stopTimeoutTimer ( ) ;
if ( connectionInterrupted )
{
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
if ( response = = INVALID_HANDLE | | ! requestSuccessful | | statusCode ! = k_EHTTPStatusCode200OK )
{
PrintDebug ( caller , " Group announcement request failed (%i). Status Code: %i " , requestSuccessful , statusCode ) ;
onRequestResult ( caller , false , 0x10 ) ; // Failed http group announcement request
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
new cookieSize ;
SteamWorks_GetHTTPResponseHeaderSize ( response , " Set-Cookie " , cookieSize ) ;
decl String : cookie [ cookieSize ] ;
SteamWorks_GetHTTPResponseHeaderValue ( response , " Set-Cookie " , cookie , cookieSize ) ;
new bodySize ;
SteamWorks_GetHTTPResponseBodySize ( response , bodySize ) ;
decl String : responseBody [ bodySize ] ;
SteamWorks_GetHTTPResponseBodyData ( response , responseBody , bodySize ) ;
new Handle : regex ;
regex = CompileRegex ( " steamLogin=(.*?); " ) ;
MatchRegex ( regex , cookie ) ;
decl String : steamLogin [ 20 ] ;
GetRegexSubString ( regex , 1 , steamLogin , sizeof ( steamLogin ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
regex = CompileRegex ( " <title>(.*?)</title> " ) ;
MatchRegex ( regex , responseBody ) ;
decl String : title [ 40 ] ;
GetRegexSubString ( regex , 1 , title , sizeof ( title ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
if ( strcmp ( steamLogin , " deleted " ) = = 0 )
{
isLogged = false ;
PrintDebug ( caller , " Invalid steam login token. " ) ;
onRequestResult ( caller , false , 0x11 ) ; // Invalid steam login token
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
if ( strcmp ( title , " Steam Community :: Error " ) = = 0 )
{
PrintDebug ( caller , " Form error on request. " ) ;
onRequestResult ( caller , false , 0x12 ) ; // Form error on request
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
onRequestResult ( caller , true ) ;
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
}
public cbkGroupInvite ( Handle : response , bool : failure , bool : requestSuccessful , EHTTPStatusCode : statusCode )
{
stopTimeoutTimer ( ) ;
if ( connectionInterrupted )
{
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
if ( response = = INVALID_HANDLE | | ! requestSuccessful | | statusCode ! = k_EHTTPStatusCode200OK )
{
PrintDebug ( caller , " Group invite request failed (%i). Status Code: %i " , requestSuccessful , statusCode ) ;
onRequestResult ( caller , false , 0x20 ) ; // Failed http group invite request
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
return ;
}
new bodySize ;
SteamWorks_GetHTTPResponseBodySize ( response , bodySize ) ;
decl String : responseBody [ bodySize ] ;
SteamWorks_GetHTTPResponseBodyData ( response , responseBody , bodySize ) ;
new Handle : regex ;
regex = CompileRegex ( " <results><! \\ [CDATA \\ [(.*?) \\ ] \\ ]>< \\ /results> " , PCRE_DOTALL ) ;
MatchRegex ( regex , responseBody ) ;
decl String : result [ 2048 ] ;
GetRegexSubString ( regex , 1 , result , sizeof ( result ) ) ;
CloseHandle ( regex ) ;
regex = INVALID_HANDLE ;
if ( ! StrEqual ( result , " OK " ) )
{
2017-04-24 16:01:51 +02:00
PrintDebug ( caller , " Error: " ) ;
PrintDebug ( caller , result ) ;
2017-02-26 00:25:51 +01:00
if ( StrEqual ( result , " The invitation to that player failed. Please try again. \n \n Error code: 19 " ) )
{
PrintDebug ( caller , " Invite failed. Incorrect invitee id on request or another error. " ) ;
onRequestResult ( caller , false , 0x21 ) ; // Incorrect invitee or another error
}
else if ( StrEqual ( result , " Missing Data " ) )
{
PrintDebug ( caller , " Invite failed. Incorrect group id or missing data on request. " ) ;
onRequestResult ( caller , false , 0x22 ) ; // Incorrect Group ID or missing data.
}
else if ( StrEqual ( result , " Missing or invalid form session key " ) )
{
isLogged = false ;
PrintDebug ( caller , " Invite failed. Plugin is not logged in. Try again to login. " ) ;
onRequestResult ( caller , false , 0x23 ) ; // Logged out. Retry to login
}
else if ( StrEqual ( result , " You do not have permission to invite to the group specified. " ) )
{
PrintDebug ( caller , " Invite failed. Inviter account is not a member of the group or does not have permissions to invite. " ) ;
onRequestResult ( caller , false , 0x24 ) ; // Account does not have permissions to invite.
}
else if ( StrEqual ( result , " Your account does not meet the requirements to use this feature. <a class= \" whiteLink \" target= \" _blank \" href= \" https://support.steampowered.com/kb_article.php?ref=3330-IAGK-7663 \" >Visit Steam Support</a> for more information. " ) )
{
PrintDebug ( caller , " Invite failed. Account is limited, only full Steam accounts can send group invites. " ) ;
onRequestResult ( caller , false , 0x25 ) ; // Limited account. Only full Steam accounts can send Steam group invites
}
else
{
PrintDebug ( caller , " Invite failed. Unknown error response received when sending the group invite. " ) ;
onRequestResult ( caller , false , 0x26 ) ; // Unknown error
}
}
else
{
if ( StrContains ( responseBody , " <duplicate><![CDATA[1]]></duplicate> " ) ! = - 1 )
{
PrintDebug ( caller , " Invite failed. Invitee has already received an invite or is already on the group. " ) ;
onRequestResult ( caller , false , 0x27 ) ; // Invitee has already received an invite or is already on the group.
}
else
{
PrintDebug ( caller , " Group invite sent. " ) ;
onRequestResult ( caller , true ) ; // Success
}
}
PrintDebug ( caller , " Response body (%i): \n %s " , strlen ( responseBody ) , responseBody ) ;
CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
}
onRequestResult ( client , bool : success , errorCode = 0 , any : data = 0 )
{
isBusy = false ;
PrintDebug ( caller , " \n ============================================================================ \n " ) ;
PrintDebug ( caller , " Final request result: %i - Error Code : %i " , success , errorCode ) ;
if ( success )
{
timeSinceLastLogin = 0 ;
KillTimer ( hTimeIncreaser ) ;
hTimeIncreaser = CreateTimer ( TIMER_UPDATE_TIME * 60.0 , timeIncreaser , INVALID_HANDLE , TIMER_REPEAT ) ;
}
// In case there was an error before the last request was executed, they are freed.
else if ( errorCode > 0 & & errorCode < = 0x0A )
{
if ( finalRequest ! = INVALID_HANDLE ) CloseHandle ( finalRequest ) ;
finalRequest = INVALID_HANDLE ;
finalFunction = INVALID_FUNCTION ;
}
if ( callbackFunction ! = INVALID_FUNCTION )
{
PrintDebug ( caller , " Calling callback... " ) ;
// Start function call
Call_StartForward ( callbackHandle ) ;
// Push parameters one at a time
Call_PushCell ( client ) ; // Client
Call_PushCell ( success ) ; // Success
Call_PushCell ( errorCode ) ; // Error code
Call_PushCell ( data ) ; // Extra data, in this case nothing
// Finish the call
new result = Call_Finish ( ) ;
PrintDebug ( caller , " Callback calling error code: %i (0: Success) " , result ) ;
removeCallback ( ) ;
}
caller = 0 ;
}
removeCallback ( )
{
new bool : removed = RemoveFromForward ( callbackHandle , callbackPlugin , callbackFunction ) ;
new functionCount = GetForwardFunctionCount ( callbackHandle ) ;
PrintDebug ( caller , " Removing callback from forward - Result: %i, - Forward Function Count: %i " , removed , functionCount ) ;
callbackFunction = INVALID_FUNCTION ;
}
// ===================================================================================
// ===================================================================================
// Obtains the plugin index in a plugin iterator
GetPluginIteratorNumber ( Handle : plugin )
{
new pluginNumber = 0 ;
decl String : pluginName [ 256 ] ;
decl String : auxPluginName [ 256 ] ;
GetPluginFilename ( plugin , pluginName , sizeof ( pluginName ) ) ;
new Handle : pluginIterator = GetPluginIterator ( ) ;
while ( MorePlugins ( pluginIterator ) )
{
pluginNumber + + ;
GetPluginFilename ( ReadPlugin ( pluginIterator ) , auxPluginName , sizeof ( auxPluginName ) ) ;
if ( StrEqual ( pluginName , auxPluginName ) ) break ;
}
CloseHandle ( pluginIterator ) ;
pluginIterator = INVALID_HANDLE ;
return pluginNumber ;
}
Handle : FindPluginFromNumber ( pluginNumber )
{
new Handle : pluginIterator = GetPluginIterator ( ) ;
new Handle : plugin ;
for ( new i = 0 ; i < pluginNumber ; i + + )
{
if ( ! MorePlugins ( pluginIterator ) )
{
plugin = INVALID_HANDLE ;
break ;
}
plugin = ReadPlugin ( pluginIterator ) ;
}
CloseHandle ( pluginIterator ) ;
pluginIterator = INVALID_HANDLE ;
return plugin ;
}
// ===================================================================================
// ===================================================================================
PrintDebug ( client , const String : format [ ] , any : . . . )
{
if ( DEBUG )
{
decl String : text [ 1024 ] ;
VFormat ( text , sizeof ( text ) , format , 3 ) ;
if ( client = = 0 ) PrintToServer ( text ) ;
else if ( IsClientInGame ( client ) ) PrintToConsole ( client , text ) ;
}
}
stock GetCaller ( )
{
return caller ;
}