From f881682de4a8516fe8baa66866a4804ffddf32b0 Mon Sep 17 00:00:00 2001 From: kuwoyuki Date: Fri, 10 Jul 2026 15:03:57 +0600 Subject: [PATCH 1/2] fix: Fictioneer --- plugin/js/Util.js | 10 +++++- plugin/js/parsers/FictioneerParser.js | 49 ++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/plugin/js/Util.js b/plugin/js/Util.js index ae9414010..bf97831ca 100644 --- a/plugin/js/Util.js +++ b/plugin/js/Util.js @@ -1069,6 +1069,13 @@ const util = (function() { } } + function rot13(str) { + return str.replace(/[a-z]/gi, c => { + const base = c <= "Z" ? 65 : 97; + return String.fromCharCode((c.charCodeAt(0) - base + 13) % 26 + base); + }); + } + function sanitize(dirty) { let savedBaseURI = dirty.baseURI; const clean = DOMPurify.sanitize(dirty); @@ -1262,6 +1269,7 @@ const util = (function() { replaceSemanticInlineStylesWithTags: replaceSemanticInlineStylesWithTags, wrapInnerContentInTag: wrapInnerContentInTag, getDefaultExtensionByMime: getDefaultExtensionByMime, - detectMimeType: detectMimeType + detectMimeType: detectMimeType, + rot13: rot13 }; })(); diff --git a/plugin/js/parsers/FictioneerParser.js b/plugin/js/parsers/FictioneerParser.js index 164ec1ebc..f719cd51e 100644 --- a/plugin/js/parsers/FictioneerParser.js +++ b/plugin/js/parsers/FictioneerParser.js @@ -112,18 +112,49 @@ class FictioneerParser extends Parser { } preprocessRawDom(chapterDom) { - let antiScrape = chapterDom.querySelector(".tiv-anti-scrape")?.parentNode; - if (!antiScrape) return; + this.processGhostContent(chapterDom); - let payloadEl = antiScrape.querySelector("script"); + const payloadHost = chapterDom.querySelector(".tiv-anti-scrape")?.parentNode; + if (!payloadHost) return; + + const payloadEl = payloadHost.querySelector("script"); if (!payloadEl) return; - let data = JSON.parse(payloadEl.textContent || payloadEl.innerText || "{}"); - antiScrape.replaceChildren(); - let cryptNode = chapterDom.createElement("p"); - cryptNode.className = "encryptedPayload"; - cryptNode.textContent = data.data; - antiScrape.appendChild(cryptNode); + const data = JSON.parse(payloadEl.textContent || payloadEl.innerText || "{}"); + payloadHost.replaceChildren(); + const payloadNode = chapterDom.createElement("p"); + payloadNode.className = "obfuscatedPayload"; + payloadNode.textContent = data.data; + payloadHost.appendChild(payloadNode); + } + + processGhostContent(chapterDom) { + const ghostScript = chapterDom.querySelector("script[data-poly]"); + if (!ghostScript) return; + + const poly = ghostScript.getAttribute("data-poly"); + const total = parseInt(ghostScript.getAttribute("data-total") || "0", 10); + if (!poly || total <= 0) return; + + const encoded = Array.from({ length: total }, (_, i) => + ghostScript.getAttribute(`data-${poly}-${i}`) || "" + ).join(""); + if (!encoded) return; + + let plain; + try { + plain = decodeURIComponent(atob(util.rot13(encoded))); + } catch { + return; + } + + const host = chapterDom.querySelector("#cherry-content-host"); + if (host) { + const temp = chapterDom.createElement("div"); + temp.innerHTML = plain; + host.replaceWith(...temp.childNodes); + } + ghostScript.remove(); } customRawDomToContentStep(chapter, content) { From 01677c38f54e773826c118042aa75543420001a7 Mon Sep 17 00:00:00 2001 From: kuwoyuki Date: Fri, 10 Jul 2026 15:13:38 +0600 Subject: [PATCH 2/2] fix: don't invoke regex+callback for rot13 for no reason --- plugin/js/Util.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugin/js/Util.js b/plugin/js/Util.js index bf97831ca..934671008 100644 --- a/plugin/js/Util.js +++ b/plugin/js/Util.js @@ -1070,10 +1070,19 @@ const util = (function() { } function rot13(str) { - return str.replace(/[a-z]/gi, c => { - const base = c <= "Z" ? 65 : 97; - return String.fromCharCode((c.charCodeAt(0) - base + 13) % 26 + base); - }); + let result = ""; + + for (let i = 0; i < str.length; i++) { + const code = str.charCodeAt(i); + if (code >= 65 && code <= 90) { + result += String.fromCharCode((code - 65 + 13) % 26 + 65); + } else if (code >= 97 && code <= 122) { + result += String.fromCharCode((code - 97 + 13) % 26 + 97); + } else { + result += str[i]; + } + } + return result; } function sanitize(dirty) {