revo-jailbreak/autoloads/ngio.gd

108 lines
3.2 KiB
GDScript

extends Node
const GATEWAY_URI: String = "https://newgrounds.io/gateway_v3.php"
var app_id: String = "" # app id on newgrounds
var aes_key := PoolByteArray([]) # AES-128/Base64 encryption key
var keys_loaded: bool = false # whether id and key have been loaded from ini file
var http := HTTPRequest.new() # http request node
var aes := AESContext.new() # aes encryption
var rng := RandomNumberGenerator.new()
var _response: Dictionary = {}
func _ready() -> void:
# load app id from ngio.ini
var ini = ConfigFile.new()
var err = ini.load("res://ngio.ini")
if err != OK:
push_error("Failed to load ngio data. Will not be able to access scoreboards.")
return
app_id = ini.get_value("ngio", "id", "")
if app_id == "":
push_error("Failed to load ngio data. Will not be able to access scoreboards.")
keys_loaded = false
else:
keys_loaded = true
# attempt to load aes key
var key = Marshalls.base64_to_raw(ini.get_value("ngio", "key", ""))
if key.size() == 16:
aes_key = key
# initialize HTTPRequest
add_child(http)
http.connect("request_completed", self, "_http_request_completed")
# initialize rng for encryption
rng.randomize()
func _test_http() -> void:
print(yield(request_execute("Gateway.getDatetime"), "completed"))
## requests the provided component be executed, do not call async :/
# may call with either single or multiple components
func request_execute(component: String, parameters: Dictionary = {}, session_id: String = "", echo: String = "", encrypt: bool = false) -> Dictionary:
# build request headers
var headers = [
"Content-Type: application/x-www-form-urlencoded",
]
# build execute object
var execute = {
component = component,
parameters = parameters,
echo = echo,
}
# use encryption if a valid key is available
# TODO: implementation messed up in some way. encryption is fine, but
# formatting is wrong in some way that newgrounds can not understand
# if encrypt and aes_key.size() == 16:
if false:
# convert to bytes
var data = to_json(execute).to_utf8()
# pad to 16 bytes alignment
var padding = PoolByteArray([])
padding.resize((16 - data.size() % 16) % 16)
padding.fill(0)
data.append_array(padding)
# generate random initialization vector
var iv = PoolByteArray([])
iv.resize(16)
for i in iv.size():
iv[i] = rng.randi() % 0xFF
# encrypt data
aes.start(AESContext.MODE_CBC_ENCRYPT, aes_key, iv)
var encrypted = aes.update(data)
aes.finish()
# compose secure execute object
execute = {
secure = Marshalls.raw_to_base64(iv + encrypted)
}
# compose request body
var request = {
app_id = app_id,
session_id = session_id,
execute = execute,
}
var body = "input=" + to_json(request).percent_encode()
# make request
var err = http.request(GATEWAY_URI, headers, true, HTTPClient.METHOD_POST, body)
# yield response
yield(http, "request_completed")
return _response
## called when the HTTPRequest gets a responce
func _http_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void:
if response_code == 200:
var dict = parse_json(body.get_string_from_utf8())
if typeof(dict) == TYPE_DICTIONARY:
_response = dict
return
_response = {success = false}