/* * * * * * * * * * * * * * * * 
 * 	 ______     __  __     ______     __  __     ______     ______     __  __    
 *	/\  __ \   /\ \/\ \   /\  == \   /\ \_\ \   /\  __ \   /\  ___\   /\ \/ /    
 *	\ \ \/\ \  \ \ \_\ \  \ \  __<   \ \  __ \  \ \  __ \  \ \ \____  \ \  _"-.  
 *	 \ \_____\  \ \_____\  \ \_____\  \ \_\ \_\  \ \_\ \_\  \ \_____\  \ \_\ \_\ 
 *	  \/_____/   \/_____/   \/_____/   \/_/\/_/   \/_/\/_/   \/_____/   \/_/\/_/ 
 *
 *  - Version : 3L
 *  - By Oubliette
 * * * * * * * * * * * * * * * */

#include "oubhack.h"

#include "oubhack_sock.h"
#include "steam/isteamclient.h"
#include "steam\steamclientpublic.h"

#include <malloc.h>
#include "md5.h"
#include "hex.h"

class OubHack* oubhack;

// Temp function definitions
void DoRequestScripts();
void DoRequestKeys();
void DoRegistration( uint64 );
void DoAuth();

/* ========================================
	Name : Hooked_CreateLuaInterface
	Desc : Gets decryption keys from the 
	Master server
=========================================== */
void DoRequestKeys(){

	while ( true ){

		ISocket* sock = new ISocket( oubhack->m_ccIP );

		if ( !sock->IsValid() ){

			oubhack->Error("Couldn't connect to authserver, retrying .. ");
			Sleep(2000);
			continue;

		}

		sock->WriteShort(0x07);

		sock->WriteI64(oubhack->m_l64SessionID);

		if (!sock->ReadBool()){

			oubhack->Error("Bad session ID!");
		
		}
		else {

			int iKeySize = sock->ReadInt();

			memcpy(oubhack->m_bDecKey, sock->ReadBytes(iKeySize), iKeySize );

			int iIVSize = sock->ReadInt();

			memcpy(oubhack->m_bDecIV, sock->ReadBytes(iIVSize), iIVSize );

			DoRequestScripts();

		}

		sock->Shutdown();
		break;

	}

}

/* ========================================
	Name : Hooked_CreateLuaInterface
	Desc : Gets cached script files from 
	The master server
=========================================== */

void DoRequestScripts(){

	while ( true ){

		ISocket* sock = new ISocket( oubhack->m_ccIP );

		if ( !sock->IsValid() ){

			oubhack->Error("Couldn't connect to authserver, retrying .. ");
			Sleep(2000);
			continue;

		}

		sock->WriteShort(0x08);

		sock->WriteI64(oubhack->m_l64SessionID);

		if (!sock->ReadBool()){

			oubhack->Error("Bad session ID!");
		
		}
		else {

			std::string sFilename = sock->ReadString().c_str();

			while( sFilename.length() != 0 ){

				sock->ReadString();

				sock->WriteBool(true);

				// Read all bytes

				int iChunkSize = sock->ReadInt();
				int iSize = sock->ReadInt();
				int iRemaining = iSize;

				std::string sCur = "";
			   
				// Start writing all bytes, using a 1024 byte buffer
				while (iRemaining > 0)
				{
					sCur += sock->ReadByte();

					iRemaining --;
				}

				oubhack->mapDataCache.insert( std::pair<std::string, std::string>( sFilename, sCur ) );

				oubhack->Debug("%s downloaded", sFilename.c_str());

				sFilename = sock->ReadString();
				
			}

			oubhack->OnAuthed();

		}

		sock->Shutdown();
		break;

	}

}

/* ========================================
	Name : Hooked_CreateLuaInterface
	Desc : Attempts to authorize SteamID
=========================================== */
void DoAuth(){
	while ( true ){

		ISocket* sock = new ISocket( oubhack->m_ccIP );

		if ( !sock->IsValid() ){

			oubhack->Error("Couldn't connect to authserver, retrying .. ");
			Sleep(2000);
			continue;

		}

		sock->WriteShort(0x06);

		sock->WriteI64(oubhack->m_l64SessionID);

		if (!sock->ReadBool()){

			oubhack->Error("Bad session ID!");
			return;

		}
		else {

			long long llSteamID64 = sock->ReadI64();

			oubhack->m_sUsername = sock->ReadString();

			HSteamPipe hPipe = oubhack->Interfaces.pSteamClient->CreateSteamPipe();
			HSteamUser hUser = oubhack->Interfaces.pSteamClient->ConnectToGlobalUser(hPipe);

			ISteamUser* SteamUser = oubhack->Interfaces.pSteamClient->GetISteamUser( hUser, hPipe, "SteamUser016");

			CSteamID steamid = SteamUser->GetSteamID();

			oubhack->Interfaces.pSteamClient->BReleaseSteamPipe(hPipe);

			if (steamid.ConvertToUint64() != llSteamID64 && llSteamID64 != 0){

				oubhack->Error("Bad SteamID!");
				return;

			}
			else if (llSteamID64 == 0){

				// Files would have been sent encrypted with 0 as the SteamID if 0 was sent as our SteamID at login
				oubhack->m_llSteamID64 = 0;

				// Register this user's steam ID.
				DoRegistration( steamid.ConvertToUint64() );

			}
			else {

				DoRequestKeys();
				oubhack->m_llSteamID64 = llSteamID64;

			}

		}

		sock->Shutdown();
		break;

	}
}

/* ========================================
	Name : Hooked_CreateLuaInterface
	Desc : Attempts to send SID to server if 
	This was the first login.
=========================================== */
void DoRegistration( uint64 ll64SteamID ){
	while ( true ){

		ISocket* sock = new ISocket( oubhack->m_ccIP );

		if ( !sock->IsValid() ){

			oubhack->Error("Couldn't connect to authserver, retrying .. ");
			Sleep(2000);
			continue;

		}

		sock->WriteShort(0x09);

		sock->WriteI64(oubhack->m_l64SessionID);
		sock->WriteI64(ll64SteamID);

		if (!sock->ReadBool()){

			oubhack->Error("sID registration failure!");
		
		}
		else {

			oubhack->Log( Color( 0, 200, 100, 255 ), "Registration completed!" );
			DoRequestKeys();

		}

		sock->Shutdown();
		break;

	}
}

/* ========================================
	Name : OubHack::LoadAuthListener
	Returns : void
=========================================== */

void OubHack::LoadAuthListener(){

	this->m_AuthThread = CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)DoAuth, 0, 0, 0 ); 

}