mirror of
https://github.com/MyLuxy/overdrive.git
synced 2026-10-18 18:03:47 -05:00
fix: buzzheavier through the browser with its file server captured
This commit is contained in:
1 parent
0ec08fa08b
commit
c146420192
7 files changed
+42
-15
No files matched your search
@@ -40,7 +40,7 @@ import { FocusScope, Text, View, useIsFocused } from '@ps5-react/core';
|
||||
} catch {
|
||||
}
|
||||
if (kind === "vikingfile") notes.push({ tone: "info", icon: "globe", key: "browserViking" });
|
||||
else if (kind === "browser" || kind === "datanodes") notes.push({ tone: "info", icon: "globe", key: "browserOther" });
|
||||
else if (kind === "browser" || kind === "datanodes" || kind === "buzzheavier") notes.push({ tone: "info", icon: "globe", key: "browserOther" });
|
||||
const need = requiredFirmware(release);
|
||||
if (need !== null && !isDlc(release)) notes.push({ tone: "info", icon: "cpu", key: "firmware", values: { need: `${need}.xx` } });
|
||||
return notes;
|
||||
|
||||
@@ -26,6 +26,8 @@ import { webURL } from './download-sources.js';
|
||||
// browser_url.c holds the same rules.
|
||||
function opaqueFileRoute(host, path) {
|
||||
if (/^a-[a-z0-9-]+\.1fichier\.com$/.test(host)) return /^\/[A-Za-z0-9]{10,256}$/.test(path);
|
||||
// Buzzheavier's file server, as its Download button's hx-redirect names it.
|
||||
if (/^[a-z0-9-]+\.buzzheavier\.com$/.test(host) && !host.startsWith("www.")) return /^\/d\/[A-Za-z0-9]{8,32}\?v=[A-Za-z0-9_-]{32,1024}$/.test(path);
|
||||
if (/^tunnel\d+\.dlproxy\.uk$/.test(host)) return /^\/[^/?]{8}\/[^/?]{32,1024}\?sig=[^&]+$/.test(path) && /^[!-~]+$/.test(path) && !path.includes("\\");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ import { VIKING_PAGE_PREFIX, VIKING_PREFIX, describeVikingCapture, linkPageMetad
|
||||
} : formats.artifact(release, root2);
|
||||
function reresolve(job2) {
|
||||
const source2 = job2.parts ? job2.currentSource : job2.release;
|
||||
if ((job2.reresolved || 0) >= 2 || ["direct", "browser", "datanodes", "manifest", "unavailable"].includes(sourceKind(source2))) return false;
|
||||
if ((job2.reresolved || 0) >= 2 || ["direct", "browser", "datanodes", "buzzheavier", "manifest", "unavailable"].includes(sourceKind(source2))) return false;
|
||||
job2.reresolved = (job2.reresolved || 0) + 1;
|
||||
delete job2.options;
|
||||
if (job2.parts) delete job2.parts[job2.partIndex].options;
|
||||
|
||||
@@ -127,7 +127,9 @@
|
||||
if (kind === "unavailable") throw new Error("Source unavailable: no download URL.");
|
||||
if (kind === "direct") return { url: webURL(url).url, rejectHtml: true };
|
||||
if (kind === "manifest") throw new Error("Split manifests must be resolved by the queue.");
|
||||
if (kind === "browser" || kind === "datanodes") throw new BrowserRequired(url);
|
||||
// Buzzheavier's pages sit behind a Cloudflare check only a browser passes (403 to the app,
|
||||
// 2026-10-17): its file link is captured from the console's browser, as Datanodes' is.
|
||||
if (kind === "browser" || kind === "datanodes" || kind === "buzzheavier") throw new BrowserRequired(url);
|
||||
if (kind === "filekeeper") return fileKeeper(url, signal);
|
||||
const response = await request(url, { signal });
|
||||
const base = response.url || url;
|
||||
@@ -136,18 +138,6 @@
|
||||
let candidate;
|
||||
if (kind === "mediafire") candidate = anchor(html, "downloadButton");
|
||||
if (kind === "vikingfile") candidate = anchor(html, "download-link");
|
||||
if (kind === "buzzheavier") {
|
||||
const button = (html.match(/<[a-z]+\b[^>]*>/gi) || []).find((tag) => attribute(tag, "hx-get")?.includes("/download"));
|
||||
const route = button && attribute(button, "hx-get");
|
||||
if (route) {
|
||||
const next = await request(absolute(route, base), {
|
||||
signal,
|
||||
followRedirects: false,
|
||||
headers: { "HX-Request": "true", "HX-Current-URL": base }
|
||||
});
|
||||
candidate = next.headers?.["hx-redirect"] || next.headers?.location;
|
||||
}
|
||||
}
|
||||
if (!candidate) throw new BrowserRequired(url);
|
||||
return direct(absolute(candidate, base), signal);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased — Buzzheavier's file server
|
||||
|
||||
- Anchor mode accepts Buzzheavier's file server, `<server>.buzzheavier.com/d/<id>?v=<signed token>`,
|
||||
which its Download button's `hx-redirect` answer names and which carries no file name (observed
|
||||
2026-10-17; the file's name comes in its Content-Disposition). Its pages stay on the bare domain.
|
||||
|
||||
## Unreleased — links up to 2047 bytes
|
||||
|
||||
- A captured link may be up to 2047 bytes (was 543, Orbit Store's limit): FileKeeper hands its file
|
||||
|
||||
@@ -113,6 +113,19 @@ static bool opaque_file_route(const char *host, size_t length, const char *path)
|
||||
if (!token((unsigned char)*at)) return false;
|
||||
return size >= 10 && size <= 256;
|
||||
}
|
||||
/* Buzzheavier's Download button gets an hx-redirect to its file server, ts.buzzheavier.com/d/<id>
|
||||
* ?v=<signed token>, which names no file: the answer's Content-Disposition does (observed
|
||||
* 2026-10-17). Its page sits on buzzheavier.com itself, so a subdomain is required. */
|
||||
if (host_under(host, length, "buzzheavier.com") && !host_equals(host, length, "buzzheavier.com") && !strncmp(path, "/d/", 3)) {
|
||||
const char *at = path + 3;
|
||||
size_t id = 0;
|
||||
while (token((unsigned char)at[id])) id++;
|
||||
if (id < 8 || id > 32 || strncmp(at + id, "?v=", 3)) return false;
|
||||
size_t size = 0;
|
||||
for (at += id + 3; *at; at++, size++)
|
||||
if (!token((unsigned char)*at) && *at != '-' && *at != '_') return false;
|
||||
return size >= 32 && size <= 1024;
|
||||
}
|
||||
if (host_under(host, length, "dlproxy.uk") && length > 17 && host_equals(host, 6, "tunnel")) {
|
||||
for (size_t i = 6; i < length - 11; i++)
|
||||
if (host[i] < '0' || host[i] > '9') return false;
|
||||
|
||||
@@ -197,6 +197,22 @@ int main(void) {
|
||||
assert(!strcmp(longest.url, filekeeper));
|
||||
}
|
||||
}
|
||||
// Buzzheavier's file server, as its Download button's hx-redirect answer names it (2026-10-17).
|
||||
{
|
||||
const char *buzz = "https://ts.buzzheavier.com/d/vsym6i66c6st?v=mqq2UM8yPmme6XOi01QgF6Qe7xJrqwGMtD34EAS3xFREvk1vXD7bxiLAv94SHzs6D1BV7Ai4tb_mZxkOnBw_Di69Bb2_Wv1KDh0Ns6LgpVFRX0kfPfwrwApCJRYOarUI-OVgeGHpPuBrCdZUhlzldTPZmE-hV9cBy8ALIdmNIodrM648z07x8tS-";
|
||||
assert(browser_capture_anchor_url("PPSA16901", buzz) == BROWSER_CAPTURE_UNBOUND);
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://buzzheavier.com/d/vsym6i66c6st?v=mqq2UM8yPmme6XOi01QgF6Qe7xJrqwGMtD34"));
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://buzzheavier.com/vsym6i66c6st"));
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://ts.buzzheavier.com/d/vsym6i66c6st"));
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://ts.buzzheavier.com/d/vsym6i66c6st?v=short"));
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://ts.buzzheavier.com/d/vsym6i66c6st?v=mqq2UM8yPmme6XOi01QgF6Qe7xJrqwGMtD34EAS&x=1"));
|
||||
assert(!browser_capture_anchor_url("PPSA16901", "https://ts.buzzheavier.com.evil.test/d/vsym6i66c6st?v=mqq2UM8yPmme6XOi01QgF6Qe7xJrqwGMtD34"));
|
||||
char header[400];
|
||||
snprintf(header, sizeof header, "HTTP/1.1 204 No Content\r\nhx-redirect: %s\r\n\r\n", buzz);
|
||||
BrowserMatch heard = {.prefix = "https://", .filename = "PPSA16901", .anchor = true};
|
||||
assert(browser_match(&heard, (const unsigned char *)header, strlen(header)));
|
||||
assert(!strcmp(heard.url, buzz));
|
||||
}
|
||||
// Page mode: the Vikingfile file page a LinkVault vault opens, and nothing else.
|
||||
assert(browser_capture_page_url("https://vikingfile.com/f/jjeEUkyPki"));
|
||||
assert(browser_capture_page_url("https://vik1ngfile.site/f/jjeEUkyPki"));
|
||||
|
||||
Reference in new issue
Block a user