mirror of
https://github.com/knutwurst/patchdl.git
synced 2026-10-06 05:00:22 +02:00
Cancel a running download (the worker aborts mid-piece and the partial file is removed) or delete a finished package, from the queue or the title card. The progress callback now returns an abort signal that reaches libcurl and the manifest merge loop. Manifest merge: bound the piece scan to the "pieces" array so a later "url" key (e.g. playgoChunkCrcUrl) can't be appended as a bogus piece, and require each piece's fileOffset to match the bytes written so far so an out-of-order manifest fails instead of silently producing a corrupt package. Report real free space on the download partition via statvfs; it was a hardcoded 0. Fixes found in review: - scan: bound the SFO entry table to the bytes actually read and require the key to be NUL-terminated before strcmp (OOB read on a crafted param.sfo from a shadow-mounted dir). - proc: bound the kinfo_proc walk and the name compare to the record and the buffer. - install: publish the API probe under the lock (data race with the MHD worker thread) and initialize rc2. - verxml: reject a truncated attribute value instead of returning it as valid. - web: keep download/install/downloaded flags across a refresh, stop the queue poll only after repeated empty results, coerce the progress number, and treat a cancelled download (HTTP 200, ok:false) as not-downloaded.
91 lines
2.3 KiB
Markdown
91 lines
2.3 KiB
Markdown
# PatchDL Web UI
|
|
|
|
Standalone static UI for the planned PS5 `patchdl.elf` web server.
|
|
|
|
Open `index.html` directly for the mock UI, or serve this directory from the
|
|
ELF web server. The JavaScript first tries the real API and falls back to demo
|
|
data when the API is not available.
|
|
|
|
The embedded ELF server serves this UI on port `12880` by default.
|
|
|
|
## Expected API
|
|
|
|
```text
|
|
GET /api/status
|
|
GET /api/config
|
|
POST /api/config
|
|
GET /api/titles
|
|
GET /api/downloads
|
|
POST /api/titles/:title_id/check
|
|
POST /api/titles/:title_id/download
|
|
POST /api/titles/:title_id/install
|
|
POST /api/titles/:title_id/enable
|
|
POST /api/titles/:title_id/disable
|
|
```
|
|
|
|
## Policy Model
|
|
|
|
The UI assumes deny-by-default behavior:
|
|
|
|
```json
|
|
{
|
|
"default_policy": "deny",
|
|
"download_dir": "/data/patchdl (internal)",
|
|
"install_after_download": false,
|
|
"delete_pkg_after_install": true,
|
|
"source_policy": {
|
|
"official": { "allow_check": true, "allow_download": true, "allow_install": true },
|
|
"external": { "allow_check": true, "allow_download": true, "allow_install": true },
|
|
"shadowmount": { "allow_check": true, "allow_download": true, "allow_install": false },
|
|
"unknown": { "allow_check": true, "allow_download": false, "allow_install": false }
|
|
},
|
|
"cdn_allowlist": [
|
|
"sgst.prod.dl.playstation.net",
|
|
"gst.prod.dl.playstation.net",
|
|
"gs2.ww.prod.dl.playstation.net"
|
|
]
|
|
}
|
|
```
|
|
|
|
Per-title modes:
|
|
|
|
```text
|
|
disabled
|
|
download_only
|
|
latest_compatible
|
|
pin
|
|
check_only
|
|
```
|
|
|
|
Per-title source fields:
|
|
|
|
```json
|
|
{
|
|
"title_id": "PPSA90001_00",
|
|
"name": "Shadowmounted Test Title",
|
|
"source_type": "shadowmount",
|
|
"source_path": "/system_ex/app/PPSA90001_00",
|
|
"mount_from": "/mnt/usb0/itemzflow/Shadowmounted Test Title",
|
|
"enabled": true,
|
|
"mode": "download_only"
|
|
}
|
|
```
|
|
|
|
Supported `source_type` values:
|
|
|
|
```text
|
|
official
|
|
external
|
|
shadowmount
|
|
unknown
|
|
```
|
|
|
|
The frontend treats `shadowmount` as download-only and `unknown` as blocked for
|
|
downloads and installs. Backend code should enforce the same policy even if a
|
|
client sends a forged request.
|
|
|
|
For PS5 game updates, the backend may turn a Sony `manifest_url` into a merged
|
|
local `.pkg` by downloading all manifest pieces. The `delta_url` `*-DP.pkg` is
|
|
not shown as a separate user action because it can bootstrap the storage/master
|
|
title instead of the installed regional target.
|