mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-12 04:53:52 -06:00
fix: keep the 404 GitHub link in the repository
The hint decoded the address before building the link, so an encoded /blob/..%2F..%2Fother/x resolved to another account's page. The path is now split before it is decoded, each segment is checked and encoded, and the link is kept only under /Abdess/retrobios/.
This commit is contained in:
1 parent
baa89556d9
commit
e858e695d3
2 files changed
+64
-4
No files matched your search
@@ -700,6 +700,40 @@ def _short_unmarked(html: str) -> list[str]:
|
||||
return found
|
||||
|
||||
|
||||
class AGithubPathStaysInTheRepository(unittest.TestCase):
|
||||
"""The 404 hint linked a GitHub path typed under this site: an encoded
|
||||
/blob/..%2F..%2Fother/x resolved to another account's page."""
|
||||
|
||||
def _hrefs(self, paths: list[str]) -> list:
|
||||
source = _read(SITE_TS)
|
||||
rule = source[source.index("function githubPathHref"):source.index("// End of the GitHub path rule.")]
|
||||
out = _node_typescript(rule + f"console.log(JSON.stringify({json.dumps(paths)}.map(githubPathHref)));")
|
||||
return json.loads(out)
|
||||
|
||||
def test_a_path_of_the_repository_is_linked(self):
|
||||
self.assertEqual(self._hrefs([
|
||||
"blob/main/bios/Sony/PlayStation/scph5501.bin",
|
||||
"tree/main/bios/",
|
||||
"raw/main/bios/3D%20Realms/x.zip",
|
||||
]), [
|
||||
"https://github.com/Abdess/retrobios/blob/main/bios/Sony/PlayStation/scph5501.bin",
|
||||
"https://github.com/Abdess/retrobios/tree/main/bios",
|
||||
"https://github.com/Abdess/retrobios/blob/main/bios/3D%20Realms/x.zip",
|
||||
])
|
||||
|
||||
def test_a_path_leaving_the_repository_gets_no_link(self):
|
||||
self.assertEqual(self._hrefs([
|
||||
"blob/..%2F..%2F..%2Fother/x",
|
||||
"blob/../../../other/x",
|
||||
"blob/main/%2E%2E/%2E%2E/%2E%2E/other",
|
||||
"blob/main/a%2Fb",
|
||||
"blob/main/a%5Cb",
|
||||
"blob/main//x",
|
||||
"blob/main/%E0%A4%A",
|
||||
"issues/1",
|
||||
]), [None] * 8)
|
||||
|
||||
|
||||
class OneVerdictWhateverHash(unittest.TestCase):
|
||||
"""2.1: the SHA1 of scph5501.bin found 4 setups, its MD5 12, its SHA256
|
||||
none (V1, J4). A setup's list writes one hash of a file."""
|
||||
|
||||
@@ -1306,6 +1306,31 @@ const startDownloads = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// The GitHub page of a repository path typed under this site, or null.
|
||||
// The address is split before it is decoded, so an encoded slash stays in
|
||||
// its segment, and a segment that decodes to nothing, '.', '..' or a slash
|
||||
// gives no link: /blob/..%2F..%2Fother/x led to another account's page.
|
||||
function githubPathHref(raw: string): string | null {
|
||||
const match = raw.replace(/\/$/, '').match(/^(blob|tree|raw)\/(.+)$/);
|
||||
if (!match) return null;
|
||||
const kind = match[1] === 'raw' ? 'blob' : match[1];
|
||||
const segments: string[] = [];
|
||||
for (const piece of match[2].split('/')) {
|
||||
let segment: string;
|
||||
try {
|
||||
segment = decodeURIComponent(piece);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (!segment || segment === '.' || segment === '..' || /[\\/]/.test(segment)) return null;
|
||||
segments.push(encodeURIComponent(segment));
|
||||
}
|
||||
const prefix = `/Abdess/retrobios/${kind}/`;
|
||||
const url = new URL(`https://github.com${prefix}${segments.join('/')}`);
|
||||
return url.origin === 'https://github.com' && url.pathname.startsWith(prefix) ? url.href : null;
|
||||
}
|
||||
// End of the GitHub path rule.
|
||||
|
||||
// The 404 page: a search button, and what the address it was asked for
|
||||
// looks like. The addresses readers reached (counted, wiki/privacy.md): a
|
||||
// command pasted as a link (/i.ps1%20%7C%20iex), a file name under files/,
|
||||
@@ -1343,7 +1368,8 @@ const notFound = () => {
|
||||
const hint = document.getElementById('rb-notfound-hint');
|
||||
if (!hint) return;
|
||||
const base = siteRoot().pathname;
|
||||
let rest = location.pathname.startsWith(base) ? location.pathname.slice(base.length) : location.pathname;
|
||||
const raw = location.pathname.startsWith(base) ? location.pathname.slice(base.length) : location.pathname;
|
||||
let rest = raw;
|
||||
try {
|
||||
rest = decodeURIComponent(rest);
|
||||
} catch {
|
||||
@@ -1368,10 +1394,10 @@ const notFound = () => {
|
||||
return;
|
||||
}
|
||||
// A GitHub path: the files are browsed on the repository.
|
||||
const github = rest.match(/^(blob|tree|raw)\/(.+)$/);
|
||||
if (github) {
|
||||
const href = githubPathHref(raw);
|
||||
if (href) {
|
||||
const link = document.createElement('a');
|
||||
link.href = `https://github.com/Abdess/retrobios/${github[1] === 'raw' ? 'blob' : github[1]}/${github[2]}`;
|
||||
link.href = href;
|
||||
link.textContent = 'the same path on GitHub';
|
||||
show(hintLine('This is a path of the GitHub repository. Open ', link, '.'));
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user