Release v1.4.20 with comprehensive audit fixes (140 issues) and expanded test coverage
- Speed calculation: raised minimum elapsed floor to 0.5s preventing unrealistic spikes - Reconnect: exponential backoff with consecutive counter, clock regression protection - Download engine: retry byte tracking (itemContributedBytes), mkdir before createWriteStream, content-length validation - Fire-and-forget promises: all void promises now have .catch() error handlers - Session recovery: normalize stale active statuses to queued on crash recovery, clear speedBps - Storage: config backup (.bak) before overwrite, EXDEV cross-device rename fallback with type guard - IPC security: input validation on all string/array IPC handlers, CSP headers in production - Main process: clipboard memory limit (50KB), installer timing increased to 800ms - Debrid: attribute-order-independent meta tag regex for Rapidgator filename extraction - Constants: named constants for magic numbers (MAX_MANIFEST_FILE_BYTES, MAX_LINK_ARTIFACT_BYTES, etc.) - Extractor/integrity: use shared constants, document password visibility and TOCTOU limitations - Tests: 103 tests total (55 new), covering utils, storage, integrity, cleanup, extractor, debrid, update Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
556f0672dc
commit
63fd402083
+100
-1
@@ -1,6 +1,6 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { defaultSettings } from "../src/main/constants";
|
||||
import { DebridService } from "../src/main/debrid";
|
||||
import { DebridService, extractRapidgatorFilenameFromHtml, filenameFromRapidgatorUrlPath, normalizeResolvedFilename } from "../src/main/debrid";
|
||||
|
||||
const originalFetch = globalThis.fetch;
|
||||
|
||||
@@ -368,3 +368,102 @@ describe("debrid service", () => {
|
||||
]));
|
||||
});
|
||||
});
|
||||
|
||||
describe("normalizeResolvedFilename", () => {
|
||||
it("strips HTML entities", () => {
|
||||
expect(normalizeResolvedFilename("Show.S01E01.German.DL.720p.part01.rar")).toBe("Show.S01E01.German.DL.720p.part01.rar");
|
||||
expect(normalizeResolvedFilename("File&Name.part1.rar")).toBe("File&Name.part1.rar");
|
||||
expect(normalizeResolvedFilename("File"Name".part1.rar")).toBe('File"Name".part1.rar');
|
||||
});
|
||||
|
||||
it("strips HTML tags and collapses whitespace", () => {
|
||||
// Tags are replaced by spaces, then multiple spaces collapsed
|
||||
const result = normalizeResolvedFilename("<b>Show.S01E01</b>.part01.rar");
|
||||
expect(result).toBe("Show.S01E01 .part01.rar");
|
||||
|
||||
// Entity decoding happens before tag removal, so <...> becomes <...> then gets stripped
|
||||
const entityTagResult = normalizeResolvedFilename("File<Tag>.part1.rar");
|
||||
expect(entityTagResult).toBe("File .part1.rar");
|
||||
});
|
||||
|
||||
it("strips 'download file' prefix", () => {
|
||||
expect(normalizeResolvedFilename("Download file Show.S01E01.part01.rar")).toBe("Show.S01E01.part01.rar");
|
||||
expect(normalizeResolvedFilename("download file Movie.2024.mkv")).toBe("Movie.2024.mkv");
|
||||
});
|
||||
|
||||
it("strips Rapidgator suffix", () => {
|
||||
expect(normalizeResolvedFilename("Show.S01E01.part01.rar - Rapidgator")).toBe("Show.S01E01.part01.rar");
|
||||
expect(normalizeResolvedFilename("Movie.mkv | Rapidgator.net")).toBe("Movie.mkv");
|
||||
});
|
||||
|
||||
it("returns empty for opaque or non-filename values", () => {
|
||||
expect(normalizeResolvedFilename("")).toBe("");
|
||||
expect(normalizeResolvedFilename("just some text")).toBe("");
|
||||
expect(normalizeResolvedFilename("e51f6809bb6ca615601f5ac5db433737")).toBe("");
|
||||
expect(normalizeResolvedFilename("download.bin")).toBe("");
|
||||
});
|
||||
|
||||
it("handles combined transforms", () => {
|
||||
// "Download file" prefix stripped, & decoded to &, "- Rapidgator" suffix stripped
|
||||
expect(normalizeResolvedFilename("Download file Show.S01E01.part01.rar - Rapidgator"))
|
||||
.toBe("Show.S01E01.part01.rar");
|
||||
});
|
||||
});
|
||||
|
||||
describe("filenameFromRapidgatorUrlPath", () => {
|
||||
it("extracts filename from standard rapidgator URL", () => {
|
||||
expect(filenameFromRapidgatorUrlPath("https://rapidgator.net/file/abc123/Show.S01E01.part01.rar.html"))
|
||||
.toBe("Show.S01E01.part01.rar");
|
||||
});
|
||||
|
||||
it("extracts filename without .html suffix", () => {
|
||||
expect(filenameFromRapidgatorUrlPath("https://rapidgator.net/file/abc123/Movie.2024.mkv"))
|
||||
.toBe("Movie.2024.mkv");
|
||||
});
|
||||
|
||||
it("returns empty for hash-only URL paths", () => {
|
||||
expect(filenameFromRapidgatorUrlPath("https://rapidgator.net/file/e51f6809bb6ca615601f5ac5db433737"))
|
||||
.toBe("");
|
||||
});
|
||||
|
||||
it("returns empty for invalid URLs", () => {
|
||||
expect(filenameFromRapidgatorUrlPath("not-a-url")).toBe("");
|
||||
expect(filenameFromRapidgatorUrlPath("")).toBe("");
|
||||
});
|
||||
|
||||
it("handles URL-encoded path segments", () => {
|
||||
expect(filenameFromRapidgatorUrlPath("https://rapidgator.net/file/id/Show%20Name.S01E01.part01.rar.html"))
|
||||
.toBe("Show Name.S01E01.part01.rar");
|
||||
});
|
||||
});
|
||||
|
||||
describe("extractRapidgatorFilenameFromHtml", () => {
|
||||
it("extracts filename from title tag", () => {
|
||||
const html = "<html><head><title>Download file Show.S01E01.German.DL.720p.part01.rar - Rapidgator</title></head></html>";
|
||||
expect(extractRapidgatorFilenameFromHtml(html)).toBe("Show.S01E01.German.DL.720p.part01.rar");
|
||||
});
|
||||
|
||||
it("extracts filename from og:title meta tag", () => {
|
||||
const html = '<html><head><meta property="og:title" content="Movie.2024.German.DL.1080p.mkv"></head></html>';
|
||||
expect(extractRapidgatorFilenameFromHtml(html)).toBe("Movie.2024.German.DL.1080p.mkv");
|
||||
});
|
||||
|
||||
it("extracts filename from reversed og:title attribute order", () => {
|
||||
const html = '<html><head><meta content="Movie.2024.German.DL.1080p.mkv" property="og:title"></head></html>';
|
||||
expect(extractRapidgatorFilenameFromHtml(html)).toBe("Movie.2024.German.DL.1080p.mkv");
|
||||
});
|
||||
|
||||
it("returns empty for HTML without recognizable filenames", () => {
|
||||
const html = "<html><head><title>Rapidgator: Fast, Pair and Unlimited</title></head><body>No file here</body></html>";
|
||||
expect(extractRapidgatorFilenameFromHtml(html)).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty for empty HTML", () => {
|
||||
expect(extractRapidgatorFilenameFromHtml("")).toBe("");
|
||||
});
|
||||
|
||||
it("extracts from File name label in page body", () => {
|
||||
const html = '<html><body>File name: <b>Show.S02E03.720p.part01.rar</b></body></html>';
|
||||
expect(extractRapidgatorFilenameFromHtml(html)).toBe("Show.S02E03.720p.part01.rar");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user