initial commit, migrating from private git server

This commit is contained in:
CrafterPika 2024-10-26 11:58:27 +02:00
commit 1cc52c8424
Signed by: crafterpika
GPG key ID: B4E0BA4B52B201DC
16 changed files with 746 additions and 0 deletions

11
.github/script.py vendored Normal file
View file

@ -0,0 +1,11 @@
import json
import os
with open(f"{os.getcwd()}/config.json", "r") as f:
jc = json.load(f)
jc["docker"] = True
with open(f"{os.getcwd()}/config.json", "w") as f:
f.write(json.dumps(jc))

61
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,61 @@
name: Create and publish a Docker image
# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
push:
tags: '*'
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
permissions:
contents: read
packages: write
attestations: write
id-token: write
#
steps:
- name: Checkout repository
uses: actions/checkout@v4
# ensure it will run in docker mode
- name: Update config.json
run: python3 .github/script.py && cat config.json
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name: Log in to the Container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

164
.gitignore vendored Normal file
View file

@ -0,0 +1,164 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
reports.db
reports/*

7
Dockerfile Normal file
View file

@ -0,0 +1,7 @@
FROM python:3.13
WORKDIR /syscheck_receiver
COPY . /syscheck_receiver
RUN pip install --no-cache-dir -r requirements.txt
RUN mkdir -p /data/reports
EXPOSE 6969/tcp
ENTRYPOINT ["python", "app.py"]

11
LICENSE Normal file
View file

@ -0,0 +1,11 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# syscheck_receiver
A server that saves SysCheck report uploads WIP

185
app.py Normal file
View file

@ -0,0 +1,185 @@
# modules
import flask
import json
import os
import string
import random
import sqlite3
import time
import html
import zipfile
from argparse import ArgumentParser
from flask import Flask, request, render_template, send_file
from datetime import datetime
from io import BytesIO
# stuff
with open(f"{os.getcwd()}/config.json", "r") as f:
config = json.load(f)
parser = ArgumentParser()
parser.add_argument("-d", "--debug", dest="debug")
args = parser.parse_args()
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def get_console_id(txt):
array = txt.split("\n")
for ln in array:
if ln.startswith("Console ID: "):
return ln.split(":")[1][1:]
return "0"
# docker
if config["docker"]:
report_dir = "/data/reports"
db_dir = "/data/reports.db"
else:
report_dir = f"{os.getcwd()}/reports"
db_dir = f"{os.getcwd()}/reports.db"
# sever code
app = Flask('syscheck_receiver')
@app.route("/")
def index():
# Get data
db = sqlite3.connect(db_dir)
cursor = db.cursor()
uploads = cursor.execute("SELECT * FROM reports ORDER BY ROWID DESC LIMIT 15").fetchall()
report_count = cursor.execute("SELECT COUNT(*) FROM reports").fetchall()
db.close()
# Make HTML Page
uploadIndex=""
for upload in uploads:
upload_time = datetime.fromtimestamp(upload[1])
uploadIndex+="ID: <a href='http://{}/view_report?id={}' target='_blank'>{}</a> -- Uploaded at {}!<br>".format(config["domain"], upload[0], upload[0], upload_time)
return render_template("index.html", uploadIndex=uploadIndex, report_count=report_count[0][0]), 200
@app.route("/syscheck_send.php", methods=["POST"]) # SysCheck2.1.0b.19
@app.route("/syscheck_receiver.php", methods=["POST"]) # literally anything else
def syscheck_report():
form_data = request.form.to_dict(flat=False)
report_txt = form_data["syscheck"][0]
console_id = get_console_id(report_txt)
if console_id == "0":
return "ERROR: Not a valid sysCheck!", 200
console_id_censor = "Console ID: "+console_id[:-4]+"***"
timestamp = int(time.time())
report_id = id_generator(6, 'AaBbCcDdFfeEgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWXxYyZz1234567890')
if form_data["password"][0] in config["upload_passwords"]:
try:
with open(f"{report_dir}/{report_id}.csv", "a+") as report:
report.write(report_txt.replace(f"Console ID: {console_id}", "Console ID: {}".format(console_id_censor)))
db = sqlite3.connect(db_dir)
cursor = db.cursor()
cursor.execute("INSERT INTO reports VALUES ('{}', {}, {})".format(report_id, timestamp, console_id))
db.commit()
db.close()
return f"Success! Report ID: {report_id}", 200
except:
return "ERROR: Failed to save SysCheck report!", 200
else:
return "ERROR: Unauthorized", 200
@app.route("/view_report", methods=["GET"])
def view_report():
report_id = request.args.get("id")
if os.path.isfile(f"{report_dir}/{report_id}.csv"):
with open(f"{report_dir}/{report_id}.csv", "r") as report:
return render_template("view_report.html", report_id=report_id, report_content=html.escape(report.read())), 200
else:
return "Report does not exist.", 404
@app.route("/syscheck2", methods=["GET"])
def syscheck():
if len("http://syscheck.softwii.de/syscheck_receiver.php") < len(config["replace_str"]):
return "Replacement host has to be exactly 48 characters; Specified URL is too long!", 400
elif len("http://syscheck.softwii.de/syscheck_receiver.php") > len(config["replace_str"]):
return "Replacement host has to be exactly 48 characters; Specified URL is too short!", 400
dol = BytesIO()
zip = BytesIO()
# hex edit boot.dol
dol2 = open(f"{os.getcwd()}/static/syscheck2/boot.dol", "rb")
dol.write(dol2.read().replace("http://syscheck.softwii.de/syscheck_receiver.php".encode("utf-8"), config["replace_str"].encode("utf-8")))
dol.seek(0)
dol2.close()
zf = zipfile.ZipFile(zip, "w", zipfile.ZIP_DEFLATED, False)
zf.writestr("apps/syscheck2/boot.dol", dol.read())
dol.close()
zf.write(f"{os.getcwd()}/static/syscheck2/icon.png", "apps/syscheck2/icon.png")
zf.write(f"{os.getcwd()}/static/syscheck2/meta.xml", "apps/syscheck2/meta.xml")
zf.close()
zip.seek(0)
# send zipfile
return send_file(zip, mimetype="application/zip", as_attachment=True, download_name="syscheck2.1.0.b19v2.zip"), 200
# handle errors
@app.errorhandler(400)
@app.errorhandler(404)
@app.errorhandler(405)
@app.errorhandler(502)
def errorhandler(e):
if e.code == 400:
jsonstring = {"message": "Bad Request.", "code": 400, "error": True}
resp = flask.Response(json.dumps(jsonstring))
resp.headers["Content-Type"] = "application/json"
return resp, 400
elif e.code == 404:
jsonstring = {"message": "Not found.", "code": 404, "error": True}
resp = flask.Response(json.dumps(jsonstring))
resp.headers["Content-Type"] = "application/json"
return resp, 404
elif e.code == 405:
jsonstring = {"message": "Method not allowed.", "code": 405, "error": True}
resp = flask.Response(json.dumps(jsonstring))
resp.headers["Content-Type"] = "application/json"
return resp, 405
elif e.code == 502:
jsonstring = {"message": "Bad Gateway.", "code": 502, "error": True}
resp = flask.Response(json.dumps(jsonstring))
resp.headers["Content-Type"] = "application/json"
return resp, 502
# run server
if __name__ == "__main__":
from waitress import serve
print("syscheck_receiver v1.0.2")
# check if sqlite db exist if not make one
if not os.path.isfile(db_dir):
print("reports.db missing generating new one...")
db = sqlite3.connect(db_dir)
cursor = db.cursor()
cursor.execute("""CREATE TABLE reports (
report_id TEXT,
timestamp INTEGER,
console_id INTEGER
)""")
db.commit()
db.close()
if config["docker"]:
print("Docker is TRUE")
# start server
if args.debug == "1":
print("Debug mode: on")
app.run(host=config["ip"], port=config["port"], debug=True)
else:
print(f"Server is running at http://{config['ip']}:{config['port']}/")
serve(app, host=config["ip"], port=config["port"])

11
config.json Normal file
View file

@ -0,0 +1,11 @@
{
"ip": "0.0.0.0",
"domain": "syscheck.crafterpika.cc",
"port": "6969",
"upload_passwords": [
"d2wRuTEObSAN",
"B277eNGp789a"
],
"replace_str": "http://syscheck.crafterpika.cc/syscheck_send.php",
"docker": false
}

2
requirements.txt Normal file
View file

@ -0,0 +1,2 @@
Flask==3.0.3
waitress==3.0.0

47
static/main.css Normal file
View file

@ -0,0 +1,47 @@
html {
background-color: #222831;
color: #f0f0f0;
font-family: Arial;
}
a {
color:#7694b8;
text-decoration:underline
}
a:hover {
color: #6495ED;
text-decoration:none
}
.content {
margin: 4px, 4px;
padding: 4px;
background-color: #393e46;
width: 425px;
height: 110px;
overflow-x: hidden;
overflow-y: auto;
text-align: justify;
border-radius: 15px;
border-style: solid;
border-color: #455d7a;
}
.topnav {
overflow: hidden;
background-color: #393e46;
}
.topnav a {
float: left;
color: #f0f0f0;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #f0f0f0;
color: black;
}

5
static/main.js Normal file
View file

@ -0,0 +1,5 @@
function openReport() {
let report_id = document.getElementById("report_id").value;
window.open(`/view_report?id=${report_id}`, '_blank').focus();
};
document.getElementById("submit-btn").addEventListener("click", openReport);

BIN
static/syscheck2/boot.dol Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
static/syscheck2/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

190
static/syscheck2/meta.xml Normal file
View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1">
<name>sysCheck</name>
<coder>Double_A, R2-D2199 and Nano</coder>
<version>2.1.0.b19v2</version>
<release_date>20121227000000</release_date>
<short_description>System Checker</short_description>
<long_description>Homebrew application which does several checks on installed IOS and custom IOS:
- Base IOS Detection
- IOS Stub;
- Fake signature (aka Trucha Bug);
- ES_DiVerify (aka ES_Identify);
- Flash Access;
- NAND Access;
- Boot2 Access;
- USB 2.0.
sysCheck generates a report on the root of the SD card (sd:/sysCheck.csv).
The author can not be held responsible for any damage sysCheck might cause!
------------------
Changelog
Version 2.1.0.b19v2
* Fixed broken server url with a hex editor
P.S. you should only use this version of sysCheck on a Wii Mini (because every other sysCheck version crashes on the console)
Version 2.1.0.b19
* Fixed HBC 1.1.x detection, thanks Nano
* Added HBF detection, thanks Nano
* Added DIOS MIOS detection
Version 2.1.0.b18
* Fixed HBC 1.1.0 detection
* Compiled with libogc 1.8.9 (this should fix the newer wii motes)
Version 2.1.0.b17
* Fixed bug in stub detection / changed stub detection
* Added some debug outputs
* New Italian translation by Roberto Boriotti
Version 2.1.0.b16
* Changed HTTP GET to HTTP POST request in sysCheck transmission
* Added debug log file option (in meta.xml change parameter "--debug=false" to "--debug=true")
* Hopefully fixed crash when no HW_AHBPROT is available
* Some bugfixes and improvements
Version 2.1.0.b15
* Changed drive detection to drive date detection
* Report upload feature
* Some bugfixes in base IOS detection
* Fixed some typos in some languages
* Added detection for region changed Wiis, thanks Joostinonline
Version 2.1.0.b14
* Added drive detection
* Compiled with libOGC 1.8.8
Version 2.1.0.b13
* Improved Base IOS detection
* Added PreFiix detection
* Added IOS252 (bootcb2) detection
Version 2.1.0.b12
* Fixed "Priiloader NAND Access Bug", thanks BoehserOnkel
* Fixed HW_AHBPROT Bug, thanks davebaol
* Improved Base IOS Detection, thanks Black.Pearl
* Added Gecko output/debugging
* Added update function
Version 2.1.0.b11
* Code improvements
Version 2.1.0.b10
* Added HW_AHBPROT to use the new Base IOS Detection faster
* Improved Base IOS Detection
* Added Indetification for IOS patched with SIP
Version 2.1.0.b9
* Improved Base IOS Detection
* Added new Base IOS Detection (thanks to WiiPower)
* Integrated IOSinfo Tool
* Added Priiloader Detection
Version 2.1.0.b8
* Improved Base IOS Detection
* New Stub Detection
* New Page scroll function in syscheck viewer
* fixed french language, thanks to rlelamer
Version 2.1.0.b7
* Improved Base IOS Detection
* Prepared USB Support
Version 2.1.0.b6
* Improved Base IOS Detection
* Added IOS58 USB2.0 Detection
* Added IOS253 NANDEmu Detection
Version 2.1.0.b5
* Bugfixes
Version 2.1.0.b4
* Improved Base IOS Detection (cIOSX rev21)
* Added Systemmenue Detection by IOS
Version 2.1.0.b3
* Bugfixes
* Improved Base IOS Detection
* Added HBC Detection
Version 2.1.0.b2
* Bugfixes
* Improved Base IOS Detection
Version 2.1.0.b
* Base IOS Detection
Version 2.0.1
* Fixed Bug in English System Menu version (v-2145571844)
* Shows which IOS is beeing tested
* Added French translation (thx Attila)
Version 2.0
* Added a very nice GUI (thx NeoRame)
* Improved report text (no Enabled/Disabled anymore)
* Added BC and MIOS check
* Report can be displayed without SD
* Fixed some bugs
* Easy to translate (language file in source)
Version 1.6.3
* Automatically detect the language settings (supports English and German only);
* Possible to select individual IOS to check;
* Select "back to HBC", "back to System Menu" or "shutdown" at the end;
* Option to read the report directly on Wii at the end.
Version 1.6.2
* Automatically detect the language settings (supports English and French only);
* Improve IOS stubs detection;
* Recompiled with the latest version of DevkitPro;
* Code cleanup.
Version 1.6.1
* Fix BootMii as IOS issue.
Version 1.6
* Improve IOS Stubs detection;
* Improve Fake Signature check;
* Check for NAND Access;
* Display Hollywood GPU version;
* Display Console ID;
* Display Boot2 version.
Version 1.5
* Fix IOS202 issue;
* Improve IOS stubs detection;
* Error handling corrections;
* Wii Light is turn on when generating the CSV report;
* Code cleanup.
Version 1.4
* Check for USB 2.0 IOS Tree;
* Display the current date and time in the report;
* Recompiled with the latest version of DevkitPro;
* Code cleanup.
Version 1.3 (unreleased)
* Detect the console region;
* Error handling corrections.
Version 1.2 (unreleased)
* Check for Flash Access;
* Check for Boot2 Access.
Version 1.1
* Fix IOS stubs detection;
* Fix IOS revision number displayed on Reload;
* Code cleanup.
Version 1.0
* Initial public release
</long_description>
<arguments>
<arg>--debug=false</arg>
</arguments>
<no_ios_reload/>
</app>

29
templates/index.html Normal file
View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en_US">
<head>
<title>SysCheck: Index</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='main.css') }}"/>
</head>
<body>
<div class="topnav">
<a href="/syscheck2">Download sysCheck2 (Wii Mini)</a>
</div>
<center>
<h1>Last 15 SysCheck Uploads:</h1>
<div class="content">
{{ uploadIndex|safe }}
</div>
<p>There are currently {{ report_count }} SysCheck(s) on this server.</p>
<br>
<p>or....</p>
<br>
<p>Enter you're SysCheck report ID here: <input type="text" id="report_id" placeholder="example"> <button type="button" id="submit-btn">Submit</button></p>
<br>
<br>
SysCheck server written by CrafterPika! <a href='https://git.crafterpika.cc/CrafterPika/syscheck_reciever' target='_blank'>Source Code</a>
</center>
<script src="{{ url_for('static', filename='main.js') }}"></script>
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en_US">
<head>
<title>SysCheck Report: {{ report_id }}</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='main.css') }}"/>
</head>
<body>
<pre>
{{ report_content }}
</pre>
<br>
<br>
<center>
<p>SysCheck server written by CrafterPika! <a href='https://git.crafterpika.cc/CrafterPika/syscheck_reciever' target='_blank'>Source Code</a></p>
</center>
</body>
</html>