mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 17:02:28 +00:00
Add form magnet normalizer and tests
This commit is contained in:
1 parent
5795a7e7d4
commit
3b4bb7f0df
2 files changed
+171
-13
No files matched your search
+164
-13
@@ -1,19 +1,170 @@
|
||||
import { WSS_TRACKERS } from "./constants.js";
|
||||
import { normalizeAndAugmentMagnet as normalizeLegacy } from "./magnetUtils.js";
|
||||
|
||||
export function normalizeAndAugmentMagnet(rawValue, { ws = "", xs = "" } = {}) {
|
||||
const trimmedInput = typeof rawValue === "string" ? rawValue.trim() : "";
|
||||
const trimmedWs = typeof ws === "string" ? ws.trim() : "";
|
||||
const trimmedXs = typeof xs === "string" ? xs.trim() : "";
|
||||
const HEX_INFO_HASH = /^[0-9a-f]{40}$/i;
|
||||
const ENCODED_BTih_PATTERN = /xt=urn%3Abtih%3A([0-9a-z]+)/gi;
|
||||
|
||||
const webSeeds = trimmedWs ? [trimmedWs] : [];
|
||||
function getOriginProtocol() {
|
||||
if (typeof window !== "undefined" && window.location?.protocol) {
|
||||
return window.location.protocol.toLowerCase();
|
||||
}
|
||||
return "https:";
|
||||
}
|
||||
|
||||
const result = normalizeLegacy(trimmedInput, {
|
||||
webSeed: webSeeds,
|
||||
torrentUrl: trimmedXs,
|
||||
xs: trimmedXs,
|
||||
extraTrackers: WSS_TRACKERS,
|
||||
});
|
||||
function decodeLoose(value) {
|
||||
if (typeof value !== "string") {
|
||||
return "";
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
return decodeURIComponent(trimmed);
|
||||
} catch (err) {
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
return result.magnet;
|
||||
function normalizeForComparison(value) {
|
||||
if (typeof value !== "string") {
|
||||
return "";
|
||||
}
|
||||
return value.trim().replace(/\/+$/, "").toLowerCase();
|
||||
}
|
||||
|
||||
function tryFormatAbsoluteUrl(candidate) {
|
||||
if (typeof candidate !== "string") {
|
||||
return "";
|
||||
}
|
||||
const trimmed = candidate.trim();
|
||||
if (!trimmed) {
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
const parsed = new URL(trimmed);
|
||||
return parsed.toString();
|
||||
} catch (err) {
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize and enrich a magnet string entered in the upload form so that it
|
||||
* always produces a WebTorrent-friendly URI. The logic mirrors the behaviour of
|
||||
* the legacy magnetUtils helper but returns a plain string for ease of use.
|
||||
*/
|
||||
export function normalizeAndAugmentMagnet(rawValue, { ws = "", xs = "" } = {}) {
|
||||
const initial = typeof rawValue === "string" ? rawValue.trim() : "";
|
||||
if (!initial) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let working = initial;
|
||||
|
||||
if (HEX_INFO_HASH.test(working)) {
|
||||
working = `magnet:?xt=urn:btih:${working.toLowerCase()}`;
|
||||
}
|
||||
|
||||
working = working.replace(ENCODED_BTih_PATTERN, (_, hash) => `xt=urn:btih:${hash}`);
|
||||
|
||||
if (!/^magnet:/i.test(working)) {
|
||||
return working;
|
||||
}
|
||||
|
||||
let fragment = "";
|
||||
const hashIndex = working.indexOf("#");
|
||||
if (hashIndex !== -1) {
|
||||
fragment = working.slice(hashIndex);
|
||||
working = working.slice(0, hashIndex);
|
||||
}
|
||||
|
||||
const [, queryPart = ""] = working.split("?", 2);
|
||||
const normalizedScheme = "magnet:";
|
||||
const rawParams = queryPart
|
||||
.split("&")
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
const params = [];
|
||||
|
||||
for (const rawParam of rawParams) {
|
||||
const [rawKey, rawVal = ""] = rawParam.split("=", 2);
|
||||
const key = rawKey.trim();
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
let value = rawVal.trim();
|
||||
if (key.toLowerCase() === "xt" && value) {
|
||||
const decoded = decodeLoose(value);
|
||||
if (decoded) {
|
||||
value = decoded;
|
||||
}
|
||||
}
|
||||
params.push({
|
||||
key,
|
||||
value,
|
||||
lowerKey: key.toLowerCase(),
|
||||
compareValue: normalizeForComparison(value),
|
||||
});
|
||||
}
|
||||
|
||||
const appendUniqueParam = (key, value) => {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
const trimmedValue = value.trim();
|
||||
if (!trimmedValue) {
|
||||
return;
|
||||
}
|
||||
const lowerKey = key.toLowerCase();
|
||||
const compareValue = normalizeForComparison(trimmedValue);
|
||||
if (compareValue) {
|
||||
const exists = params.some(
|
||||
(param) => param.lowerKey === lowerKey && param.compareValue === compareValue
|
||||
);
|
||||
if (exists) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
params.push({
|
||||
key,
|
||||
value: trimmedValue,
|
||||
lowerKey,
|
||||
compareValue,
|
||||
});
|
||||
};
|
||||
|
||||
for (const tracker of WSS_TRACKERS) {
|
||||
if (typeof tracker !== "string") {
|
||||
continue;
|
||||
}
|
||||
const trimmedTracker = tracker.trim();
|
||||
if (!/^wss:\/\//i.test(trimmedTracker)) {
|
||||
continue;
|
||||
}
|
||||
appendUniqueParam("tr", trimmedTracker);
|
||||
}
|
||||
|
||||
const normalizedXs = typeof xs === "string" ? xs.trim() : "";
|
||||
if (normalizedXs) {
|
||||
appendUniqueParam("xs", normalizedXs);
|
||||
}
|
||||
|
||||
const originProtocol = getOriginProtocol();
|
||||
const rawWs = typeof ws === "string" ? ws.trim() : "";
|
||||
if (rawWs) {
|
||||
const formattedWs = tryFormatAbsoluteUrl(rawWs);
|
||||
const lowerWs = formattedWs.toLowerCase();
|
||||
const isHttpSeed = lowerWs.startsWith("http://");
|
||||
const allowHttpSeed = originProtocol === "http:";
|
||||
if (!isHttpSeed || allowHttpSeed) {
|
||||
appendUniqueParam("ws", formattedWs);
|
||||
}
|
||||
}
|
||||
|
||||
const queryString = params
|
||||
.map(({ key, value }) => (value ? `${key}=${value}` : key))
|
||||
.join("&");
|
||||
|
||||
return `${normalizedScheme}${queryString ? `?${queryString}` : ""}${fragment}`;
|
||||
}
|
||||
@@ -135,6 +135,13 @@ function getParamValues(magnet, key) {
|
||||
["https://cdn.example.com/video.torrent"],
|
||||
"Expected xs hint to be appended"
|
||||
);
|
||||
const trackers = parsed.searchParams.getAll("tr");
|
||||
for (const tracker of WSS_TRACKERS) {
|
||||
assert.ok(
|
||||
trackers.includes(tracker),
|
||||
`Expected helper to append tracker ${tracker}`
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
||||
(function testFormHelperSkipsInsecureWsOnHttpsOrigin() {
|
||||
|
||||
Reference in new issue
Block a user