New generation style!
* More dynamic: Includes version in the index.html * Still no external dependencies. * Added lockpick and TegraExplorer
This commit is contained in:
parent
6eabfb88b7
commit
bb4a6362dd
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,4 @@
|
||||
hekate.bin.js
|
||||
lockpick.bin.js
|
||||
tegraexplorer.bin.js
|
||||
index.html
|
||||
|
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
generate_files:
|
||||
@python gen_contents.py
|
||||
|
||||
clean:
|
||||
@rm hekate.bin.js
|
||||
@rm lockpick.bin.js
|
||||
@rm tegraexplorer.bin.js
|
||||
@rm index.html
|
||||
|
||||
.PHONY: help
|
||||
|
||||
help:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.DEFAULT_GOAL := help
|
@ -1,85 +0,0 @@
|
||||
import requests
|
||||
import io
|
||||
import shutil
|
||||
import zipfile
|
||||
|
||||
API_URL = "https://api.github.com/repos/CTCaer/hekate/releases/latest"
|
||||
BIN_NAME = "hekate_ctcaer_"
|
||||
SERIALIZED_FILENAME = "hekate.bin.js"
|
||||
|
||||
### BASIC FILE STUFF, DO NOT EDIT
|
||||
DEFAULT_SERIALIZED_CONTENTS = """
|
||||
const hekate = new Uint8Array([
|
||||
{}
|
||||
]);
|
||||
"""
|
||||
|
||||
## Script that downloads the latest bin from hekate and serializes it as a .bin.js file.
|
||||
|
||||
def download_file_to_bytes_io(url) -> io.BytesIO:
|
||||
r = requests.get(url)
|
||||
filedata = io.BytesIO()
|
||||
if r.status_code == 200:
|
||||
filedata.write(r.content)
|
||||
filedata.seek(0)
|
||||
return filedata
|
||||
|
||||
def extract_specific_file_from_zip(zip_file) -> io.BytesIO:
|
||||
filename = None
|
||||
filedata = io.BytesIO()
|
||||
with zipfile.ZipFile(zip_file) as z:
|
||||
for zinfo in z.infolist():
|
||||
if zinfo.filename.startswith(BIN_NAME):
|
||||
filename = zinfo.filename
|
||||
break
|
||||
if filename is None:
|
||||
raise Exception("Zipfile does not contain required match.")
|
||||
|
||||
with z.open(filename) as zfile:
|
||||
shutil.copyfileobj(zfile, filedata)
|
||||
filedata.seek(0)
|
||||
return filedata
|
||||
|
||||
def fetch_hekate_zip() -> io.BytesIO:
|
||||
r = requests.get(API_URL)
|
||||
jdata = r.json()
|
||||
return download_file_to_bytes_io([d for d in jdata["assets"] if d["name"].startswith("hekate_ctcaer")][0]["browser_download_url"])
|
||||
|
||||
def get_hekate_payload(hekate_zip: io.BytesIO) -> io.BytesIO:
|
||||
return extract_specific_file_from_zip(hekate_zip)
|
||||
|
||||
def serialize_to_js(hekate_payload: io.BytesIO, filename: str):
|
||||
hekate_payload = hekate_payload.read()
|
||||
|
||||
# List so we can loop byte for byte
|
||||
serialized = [bytes([b]) for b in hekate_payload]
|
||||
final_str = []
|
||||
|
||||
# Formatting
|
||||
max_ctr = 16
|
||||
str_on_line = 0
|
||||
|
||||
# Special check to ensure that a comma isn't placed on the end
|
||||
last_byte = len(serialized) - 1
|
||||
for idx, byte in enumerate(serialized):
|
||||
if idx != last_byte:
|
||||
final_str.append(f"0x{byte.hex()}, ")
|
||||
else:
|
||||
final_str.append(f"0x{byte.hex()}")
|
||||
|
||||
# More readable
|
||||
str_on_line += 1
|
||||
if str_on_line >= max_ctr:
|
||||
str_on_line = 0
|
||||
final_str.append("\n ")
|
||||
|
||||
final_str = "".join(final_str)
|
||||
|
||||
out_string = DEFAULT_SERIALIZED_CONTENTS.format(final_str)
|
||||
with open(filename, "w") as outfile:
|
||||
outfile.write(out_string)
|
||||
|
||||
if __name__ == "__main__":
|
||||
api_response = fetch_hekate_zip()
|
||||
payload = get_hekate_payload(api_response)
|
||||
serialize_to_js(payload, SERIALIZED_FILENAME)
|
148
gen_contents.py
Normal file
148
gen_contents.py
Normal file
@ -0,0 +1,148 @@
|
||||
import requests
|
||||
import io
|
||||
import shutil
|
||||
import zipfile
|
||||
|
||||
bin_files = {
|
||||
"hekate": {
|
||||
"API_URL": "https://api.github.com/repos/CTCaer/hekate/releases/latest", # API version url
|
||||
"BIN_NAME": "hekate_ctcaer", # BIN_NAME -> used to determine what file to extract from zip or what to download from API
|
||||
"SERIALIZED_FILENAME": "hekate.bin.js", # File to store serialized contents in.
|
||||
"SHORT_NAME": "hekate",
|
||||
"zipped": True # Do we need to extract a zip or is it just a raw payload.
|
||||
},
|
||||
"tegraexplorer": {
|
||||
"API_URL": "https://api.github.com/repos/suchmememanyskill/TegraExplorer/releases/latest",
|
||||
"BIN_NAME": "TegraExplorer",
|
||||
"SERIALIZED_FILENAME": "tegraexplorer.bin.js",
|
||||
"SHORT_NAME": "tegraexplorer",
|
||||
"zipped": False,
|
||||
},
|
||||
"lockpick": {
|
||||
"API_URL": "https://api.github.com/repos/shchmue/Lockpick_RCM/releases/latest",
|
||||
"BIN_NAME": "Lockpick_RCM",
|
||||
"SERIALIZED_FILENAME": "lockpick.bin.js",
|
||||
"SHORT_NAME": "lockpick",
|
||||
"zipped": False,
|
||||
},
|
||||
}
|
||||
|
||||
### BASIC FILE STUFF, DO NOT EDIT
|
||||
DEFAULT_SERIALIZED_CONTENTS = """
|
||||
const {} = new Uint8Array([
|
||||
{}
|
||||
]);
|
||||
"""
|
||||
|
||||
## Script that downloads the latest bin from hekate and serializes it as a .bin.js file.
|
||||
|
||||
def download_file_to_bytes_io(url) -> io.BytesIO:
|
||||
r = requests.get(url)
|
||||
filedata = io.BytesIO()
|
||||
if r.status_code == 200:
|
||||
filedata.write(r.content)
|
||||
filedata.seek(0)
|
||||
return filedata
|
||||
|
||||
def extract_specific_file_from_zip(zip_file, bin_name) -> io.BytesIO:
|
||||
filename = None
|
||||
filedata = io.BytesIO()
|
||||
with zipfile.ZipFile(zip_file) as z:
|
||||
for zinfo in z.infolist():
|
||||
if zinfo.filename.startswith(bin_name):
|
||||
filename = zinfo.filename
|
||||
break
|
||||
if filename is None:
|
||||
raise Exception("Zipfile does not contain required match.")
|
||||
|
||||
with z.open(filename) as zfile:
|
||||
shutil.copyfileobj(zfile, filedata)
|
||||
filedata.seek(0)
|
||||
return filedata
|
||||
|
||||
def fetch_hekate_zip(api_url) -> io.BytesIO:
|
||||
r = requests.get(api_url)
|
||||
jdata = r.json()
|
||||
return download_file_to_bytes_io([d for d in jdata["assets"] if d["name"].startswith("hekate_ctcaer")][0]["browser_download_url"])
|
||||
|
||||
def fetch_github_repo_file(api_url, filename) -> io.BytesIO:
|
||||
r = requests.get(api_url)
|
||||
jdata = r.json()
|
||||
return download_file_to_bytes_io([d for d in jdata["assets"] if d["name"].startswith(filename)][0]["browser_download_url"])
|
||||
|
||||
def fetch_github_latest_tag(api_url) -> io.BytesIO:
|
||||
r = requests.get(api_url)
|
||||
jdata = r.json()
|
||||
return jdata["tag_name"]
|
||||
|
||||
def serialize_to_js(short_name: str, payload: io.BytesIO, filename: str):
|
||||
payload = payload.read()
|
||||
|
||||
# List so we can loop byte for byte
|
||||
serialized = [bytes([b]) for b in payload]
|
||||
final_str = []
|
||||
|
||||
# Formatting
|
||||
max_ctr = 16
|
||||
str_on_line = 0
|
||||
|
||||
# Special check to ensure that a comma isn't placed on the end
|
||||
last_byte = len(serialized) - 1
|
||||
for idx, byte in enumerate(serialized):
|
||||
if idx != last_byte:
|
||||
final_str.append(f"0x{byte.hex()}, ")
|
||||
else:
|
||||
final_str.append(f"0x{byte.hex()}")
|
||||
|
||||
# More readable
|
||||
str_on_line += 1
|
||||
if str_on_line >= max_ctr:
|
||||
str_on_line = 0
|
||||
final_str.append("\n ")
|
||||
|
||||
final_str = "".join(final_str)
|
||||
|
||||
out_string = DEFAULT_SERIALIZED_CONTENTS.format(short_name, final_str)
|
||||
with open(filename, "w") as outfile:
|
||||
outfile.write(out_string)
|
||||
|
||||
def generate_js(program: str):
|
||||
api_response = fetch_github_repo_file(bin_files[program]["API_URL"], bin_files[program]["BIN_NAME"])
|
||||
if bin_files[program]["zipped"]:
|
||||
payload = extract_specific_file_from_zip(api_response, bin_files[program]["BIN_NAME"])
|
||||
else:
|
||||
payload = api_response
|
||||
serialize_to_js(bin_files[program]["SHORT_NAME"], payload, bin_files[program]["SERIALIZED_FILENAME"])
|
||||
|
||||
def generate_html():
|
||||
with open("html/preface.html", "r") as preface_file:
|
||||
preface = preface_file.read()
|
||||
|
||||
with open("html/core.html", 'r') as template_file:
|
||||
core = template_file.read()
|
||||
|
||||
with open("html/post.html", "r") as post_file:
|
||||
post = post_file.read()
|
||||
|
||||
html_data_list = []
|
||||
html_data_list.append(preface)
|
||||
html_data_list.append(core.format(
|
||||
fetch_github_latest_tag(bin_files["hekate"]["API_URL"]),
|
||||
fetch_github_latest_tag(bin_files["tegraexplorer"]["API_URL"]),
|
||||
fetch_github_latest_tag(bin_files["lockpick"]["API_URL"]),
|
||||
))
|
||||
html_data_list.append(post)
|
||||
|
||||
|
||||
out_string = "".join(html_data_list)
|
||||
with open("index.html", "w") as indexfile:
|
||||
indexfile.write(out_string)
|
||||
|
||||
def main():
|
||||
generate_js("hekate")
|
||||
generate_js("tegraexplorer")
|
||||
generate_js("lockpick")
|
||||
generate_html()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
28
html/core.html
Normal file
28
html/core.html
Normal file
@ -0,0 +1,28 @@
|
||||
<h3>Payload:</h3>
|
||||
<div>
|
||||
<form id="mainForm">
|
||||
<p>
|
||||
<input type="radio" name="payload" id="fusee.bin" value="fusee.bin" checked>
|
||||
<label for="fusee.bin">Example payload (fusee.bin)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="payload" id="hekate.bin" value="hekate.bin" checked>
|
||||
<label for="fusee.bin">Hekate {} - (hekate_ctcaer.bin)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="payload" id="tegraexplorer.bin" value="tegraexplorer.bin" checked>
|
||||
<label for="fusee.bin">TegraExplorer v{} - (tegraexplorer.bin)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="payload" id="lockpick.bin" value="lockpick.bin" checked>
|
||||
<label for="fusee.bin">Lockpick_RCM {} - (lockpick.bin)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="payload" id="uploaded" value="uploaded">
|
||||
<label for="uploaded">Upload payload:</label>
|
||||
<input type="file" id="payloadUpload">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<button id="goButton">Do the thing!</button>
|
||||
</div>
|
12
html/post.html
Normal file
12
html/post.html
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
<h3>Result:</h3>
|
||||
<textarea cols="80" rows="12" id="output"></textarea>
|
||||
|
||||
<script src="fusee.bin.js"></script>
|
||||
<script src="hekate.bin.js"></script>
|
||||
<script src="lockpick.bin.js"></script>
|
||||
<script src="tegraexplorer.bin.js"></script>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,74 +1,43 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebFG</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Web Fusée Launcher</h1>
|
||||
<p>Fusee Launcher ported to JavaScript using WebUSB.</p>
|
||||
<p>
|
||||
Source can be found on <a href="https://github.com/atlas44/web-fusee-launcher">GitHub</a> (or by hitting view source, there is no backend!).
|
||||
Ported from <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.
|
||||
Thanks to ktemkin and ReSwitched for Fusée Gelée and a ton of other things!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>Instructions:</h4>
|
||||
<ol>
|
||||
<li>Put the Switch in RCM, and connect it to your device.</li>
|
||||
<li>Select either the example payload, or upload one.</li>
|
||||
<li>Press 'Do the thing!'</li>
|
||||
<li>On the consent screen that appears, select 'APX' and hit confirm.</li>
|
||||
<li>If all goes well, the payload will launch!</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>Random stuff:</h4>
|
||||
<ul>
|
||||
<li>This is pretty poorly tested. I just kind wrote it and whatever. I'm not responsible if anything goes wrong!</li>
|
||||
<li>This does NOT work on Windows due to a limitation in the Chrome implementation of WebUSB (and probably other reasons!)</li>
|
||||
<li>This does NOT currently work on any browser but Chrome, because they don't implement WebUSB.</li>
|
||||
<li>On Linux, you might get an access denied error!
|
||||
If you do, you can try creating a file at <code>/etc/udev/rules.d/50-switch.rules</code>
|
||||
<div>With the following contents:</div>
|
||||
<div><code>SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="plugdev"</code></div>
|
||||
</li>
|
||||
<li>This has been tested and appears to work on Linux, OSX, Android (unrooted) and Chromebooks. Your mileage may vary.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3>Payload:</h3>
|
||||
<div>
|
||||
<form id="mainForm">
|
||||
<p>
|
||||
<input type="radio" name="payload" id="fusee.bin" value="fusee.bin" checked>
|
||||
<label for="fusee.bin">Example payload (fusee.bin)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input type="radio" name="payload" id="hekate.bin" value="hekate.bin" checked>
|
||||
<label for="fusee.bin">Latest hekate (hekate_ctcaer.bin)</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="radio" name="payload" id="uploaded" value="uploaded">
|
||||
<label for="uploaded">Upload payload:</label>
|
||||
<input type="file" id="payloadUpload">
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<button id="goButton">Do the thing!</button>
|
||||
</div>
|
||||
|
||||
<h3>Result:</h3>
|
||||
<textarea cols="80" rows="12" id="output"></textarea>
|
||||
|
||||
<script src="fusee.bin.js"></script>
|
||||
<script src="hekate.bin.js"></script>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WebFG</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Web Fusée Launcher</h1>
|
||||
<p>Fusee Launcher ported to JavaScript using WebUSB.</p>
|
||||
<p>
|
||||
Source can be found on <a href="https://github.com/atlas44/web-fusee-launcher">GitHub</a> (or by hitting view source, there is no backend!).
|
||||
Ported from <a href="https://github.com/reswitched/fusee-launcher">fusee-launcher</a>.
|
||||
Thanks to ktemkin and ReSwitched for Fusée Gelée and a ton of other things!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>Instructions:</h4>
|
||||
<ol>
|
||||
<li>Put the Switch in RCM, and connect it to your device.</li>
|
||||
<li>Select either the example payload, or upload one.</li>
|
||||
<li>Press 'Do the thing!'</li>
|
||||
<li>On the consent screen that appears, select 'APX' and hit confirm.</li>
|
||||
<li>If all goes well, the payload will launch!</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<h4>Random stuff:</h4>
|
||||
<ul>
|
||||
<li>This is pretty poorly tested. I just kind wrote it and whatever. I'm not responsible if anything goes wrong!</li>
|
||||
<li>This does NOT work on Windows due to a limitation in the Chrome implementation of WebUSB (and probably other reasons!)</li>
|
||||
<li>This does NOT currently work on any browser but Chrome, because they don't implement WebUSB.</li>
|
||||
<li>On Linux, you might get an access denied error!
|
||||
If you do, you can try creating a file at <code>/etc/udev/rules.d/50-switch.rules</code>
|
||||
<div>With the following contents:</div>
|
||||
<div><code>SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="plugdev"</code></div>
|
||||
</li>
|
||||
<li>This has been tested and appears to work on Linux, OSX, Android (unrooted) and Chromebooks. Your mileage may vary.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
4
main.js
4
main.js
@ -117,6 +117,10 @@ document.getElementById("goButton").addEventListener("click", async () => {
|
||||
payload = fusee;
|
||||
} else if (payloadType === "hekate.bin") {
|
||||
payload = hekate;
|
||||
} else if (payloadType === "tegraexplorer.bin") {
|
||||
payload = tegraexplorer;
|
||||
} else if (payloadType === "lockpick.bin") {
|
||||
payload = lockpick;
|
||||
} else if (payloadType === "uploaded") {
|
||||
const file = document.getElementById("payloadUpload").files[0];
|
||||
if (!file) {
|
||||
|
Loading…
Reference in New Issue
Block a user