diff --git a/build-chrome.js b/build-chrome.js index 3ecbbf2..9691c80 100644 --- a/build-chrome.js +++ b/build-chrome.js @@ -22,6 +22,7 @@ const domains = [ "https://*.coom.tech/*", "https://*.4chan.org/*", "https://*.4channel.org/*", + "https://*.4plebs.org/*", "https://*.pomf.cat/*", "https://pomf.cat/*", "https://desuarchive.org/*", diff --git a/chrome/_metadata/generated_indexed_rulesets/_ruleset1 b/chrome/_metadata/generated_indexed_rulesets/_ruleset1 index 114673e..45e11a6 100644 Binary files a/chrome/_metadata/generated_indexed_rulesets/_ruleset1 and b/chrome/_metadata/generated_indexed_rulesets/_ruleset1 differ diff --git a/chrome/manifest.json b/chrome/manifest.json index 2c7689e..83aac1e 100644 --- a/chrome/manifest.json +++ b/chrome/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "PngExtraEmbedder", "description": "Discover embedded files on 4chan and archives!", - "version": "0.241", + "version": "0.245", "icons": { "64": "1449696017588.png" }, @@ -13,6 +13,7 @@ "https://*.coom.tech/*", "https://*.4chan.org/*", "https://*.4channel.org/*", + "https://*.4plebs.org/*", "https://*.pomf.cat/*", "https://pomf.cat/*", "https://desuarchive.org/*", @@ -66,6 +67,7 @@ "https://*.coom.tech/*", "https://*.4chan.org/*", "https://*.4channel.org/*", + "https://*.4plebs.org/*", "https://*.pomf.cat/*", "https://pomf.cat/*", "https://desuarchive.org/*", diff --git a/firefox_update.json b/firefox_update.json index 3388035..758b06b 100644 --- a/firefox_update.json +++ b/firefox_update.json @@ -1 +1 @@ -{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.242","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.241.xpi"}]}}} \ No newline at end of file +{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.245","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.241.xpi"}]}}} \ No newline at end of file diff --git a/main.meta.js b/main.meta.js index 1333946..8d022d2 100644 --- a/main.meta.js +++ b/main.meta.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.242 +// @version 0.245 // @description uhh // @author You // @match https://boards.4channel.org/* diff --git a/main.user.js b/main.user.js index ebfbe9d..fc72d03 100644 --- a/main.user.js +++ b/main.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.242 +// @version 0.245 // @description uhh // @author You // @match https://boards.4channel.org/* @@ -89,7 +89,7 @@ const _DOMParser = DOMParser; var define_BUILD_VERSION_default; var init_define_BUILD_VERSION = __esm({ ""() { - define_BUILD_VERSION_default = [0, 242]; + define_BUILD_VERSION_default = [0, 245]; } }); @@ -16189,6 +16189,7 @@ const _DOMParser = DOMParser; csettings2 = b; }); var CUM3 = import_buffer3.Buffer.from("doo\0m"); + var CUM4 = import_buffer3.Buffer.from("voo\0m"); var BufferReadStream = (b) => { const ret = new ReadableStream({ pull(cont) { @@ -16198,6 +16199,15 @@ const _DOMParser = DOMParser; }); return ret; }; + var password = import_buffer3.Buffer.from("NOA"); + var xor = (a, p) => { + let n = 0; + for (let i = 0; i < a.byteLength; ++i) { + a[i] ^= p[n]; + n++; + n %= p.byteLength; + } + }; var extract = async (png) => { const reader = BufferReadStream(png).getReader(); const sneed = new PNGDecoder(reader); @@ -16212,6 +16222,12 @@ const _DOMParser = DOMParser; const k = await decodeCoom3Payload(buff.slice(4 + CUM3.length)); ret.push(...k.filter((e) => e).map((e) => e)); } + if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) { + const passed = buff.slice(4 + CUM4.length); + xor(passed, password); + const k = await decodeCoom3Payload(passed); + ret.push(...k.filter((e) => e).map((e) => e)); + } break; case "IDAT": case "IEND": @@ -16250,7 +16266,9 @@ const _DOMParser = DOMParser; if (magic2 && name != "IDAT") break; if (!magic2 && name == "IDAT") { - await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", import_buffer3.Buffer.concat([CUM3, injb])), () => Promise.resolve(0), 0]); + const passed = import_buffer3.Buffer.from(injb); + xor(passed, password); + await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", import_buffer3.Buffer.concat([CUM4, passed])), () => Promise.resolve(0), 0]); magic2 = true; } await encoder.insertchunk([name, chunk, crc, offset]); @@ -16278,6 +16296,8 @@ const _DOMParser = DOMParser; buff = await chunk(); if (buff.slice(4, 4 + CUM3.length).equals(CUM3)) return true; + if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) + return true; break; case "IDAT": case "IEND": @@ -16304,7 +16324,7 @@ const _DOMParser = DOMParser; init_esbuild_inject(); var import_buffer4 = __toESM(require_buffer(), 1); var ebml = __toESM(require_lib2(), 1); - var password = import_buffer4.Buffer.from("NOA"); + var password2 = import_buffer4.Buffer.from("NOA"); var findEnclosingTag = (ch, name) => { const first = ch.findIndex((e) => e.type == "m" && e.name == name); if (first < 0) @@ -16708,8 +16728,9 @@ const _DOMParser = DOMParser; cache[b.domain][hex] = tran; return tran; } catch (e) { - console.error("The following error might be expected"); - console.error(e); + const error = e; + if (!error.message.includes("Unexpected end of JSON input")) + console.error(e); return []; } }; @@ -24012,12 +24033,17 @@ const _DOMParser = DOMParser; } } }; - if (shouldUseCache()) { - res2 = await getEmbedsFromCache(qp.getCurrentBoard(), +qp.getCurrentThread(), post.id); - } - if (!res2) { - res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink); - res2 = res2?.filter((e) => e); + try { + if (shouldUseCache()) { + res2 = await getEmbedsFromCache(qp.getCurrentBoard(), +qp.getCurrentThread(), post.id); + } + if (!res2) { + res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink); + res2 = res2?.filter((e) => e); + } + } catch (e) { + console.error(e); + return; } if (!res2 || res2.length == 0) return; @@ -24285,7 +24311,6 @@ const _DOMParser = DOMParser; })); }; if (location.host.startsWith("boards.4chan")) { - setTimeout(() => startup(false), 2e3); document.addEventListener("4chanParsingDone", () => startup(false), { once: true }); } document.addEventListener("4chanXInitFinished", () => startup(true), { once: true }); diff --git a/src/background.ts b/src/background.ts index 875e5b6..2865071 100644 --- a/src/background.ts +++ b/src/background.ts @@ -95,74 +95,86 @@ const bgCorsFetch = async (c: MessagePort, id: number, input: string, init?: Req input = 'https:' + input; if (init?.body && execution_mode == "chrome_api") init.body = await deserialize(init.body); - const k = await fetch(input, init); - let headersStr = ''; - const headerObj = {} as any; - k.headers.forEach((v, k) => { - headerObj[k] = v; - headersStr += `${k}: ${v}\n`; - }); - c.postMessage({ - id, setRes: true, - ok: k.ok, - headers: headerObj, - responseHeaders: headersStr, - redirected: k.redirected, - type: k.type, - url: k.url, - status: k.status, - bodyUsed: k.bodyUsed, - statusText: k.statusText, - }); + try { + const k = await fetch(input, init); + + let headersStr = ''; + const headerObj = {} as any; + k.headers.forEach((v, k) => { + headerObj[k] = v; + headersStr += `${k}: ${v}\n`; + }); + c.postMessage({ + id, setRes: true, + ok: k.ok, + headers: headerObj, + responseHeaders: headersStr, + redirected: k.redirected, + type: k.type, + url: k.url, + status: k.status, + bodyUsed: k.bodyUsed, + statusText: k.statusText, + }); - pendingFetches.set(c, { - [id]: { - fetchFully: false - }, - ...(pendingFetches.get(c) || {}) - }); + pendingFetches.set(c, { + [id]: { + fetchFully: false + }, + ...(pendingFetches.get(c) || {}) + }); - let buff: Buffer[] = []; - - const ctotal = +headerObj['content-length'] || 0; // content total - let ltotal = 0; // loaded total - - // sequence number, required to reorder messages client-side - // if they get processed out of order - let s = 0; - const e = { - write(chunk: Uint8Array) { - ltotal += chunk.byteLength; - c.postMessage({ id, progress: [ltotal, ctotal] }); - if (!pendingFetches.get(c)![id].fetchFully) { - //const url = new Blob([chunk]); - c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); - } else { - buff.push(Buffer.from(chunk)); - } - }, - close() { - if (buff.length > 0) { - const chunk = Buffer.concat(buff); - c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); - buff = []; + let buff: Buffer[] = []; + + const ctotal = +headerObj['content-length'] || 0; // content total + let ltotal = 0; // loaded total + + // sequence number, required to reorder messages client-side + // if they get processed out of order + let s = 0; + const e = { + write(chunk: Uint8Array) { + ltotal += chunk.byteLength; + c.postMessage({ id, progress: [ltotal, ctotal] }); + if (!pendingFetches.get(c)![id].fetchFully) { + //const url = new Blob([chunk]); + c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); + } else { + buff.push(Buffer.from(chunk)); + } + }, + close() { + if (buff.length > 0) { + const chunk = Buffer.concat(buff); + c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); + buff = []; + } + const obj = pendingFetches.get(c)!; + delete obj[id]; + if (Object.keys(obj).length == 0) + pendingFetches.delete(c); + c.postMessage({ id, s: s++, pushData: {} }); } - const obj = pendingFetches.get(c)!; - delete obj[id]; - if (Object.keys(obj).length == 0) - pendingFetches.delete(c); - c.postMessage({ id, s: s++, pushData: {} }); + }; + const reader = k.body?.getReader(); + let res: ReadableStreamDefaultReadResult; + for (; ;) { + res = await reader!.read(); + if (res.done) break; + e.write(res.value); } - }; - const reader = k.body?.getReader(); - let res: ReadableStreamDefaultReadResult; - for (; ;) { - res = await reader!.read(); - if (res.done) break; - e.write(res.value); + e.close(); + reader?.releaseLock(); + } catch(e) { + const err = e as Error; + c.postMessage({ + id, + setRes: true, + ok: false, + url: input, + status: err.message + }); } - e.close(); - reader?.releaseLock(); }; const meself = new URL(obj.runtime.getURL('')).origin; @@ -170,7 +182,7 @@ const meself = new URL(obj.runtime.getURL('')).origin; const waitConnect = (cb: any) => { window.addEventListener("message", (msg) => { //if (msg.origin === meself) { - cb(msg.ports[0]); + cb(msg.ports[0]); //} }); }; diff --git a/src/main.ts b/src/main.ts index ae9bbec..92c00e6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -211,12 +211,17 @@ const processPost = async (post: HTMLDivElement) => { } }; - if (shouldUseCache()) { - res2 = await getEmbedsFromCache(qp.getCurrentBoard(), +qp.getCurrentThread()!, post.id); - } - if (!res2) { - res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink); - res2 = res2?.filter(e => e); + try { + if (shouldUseCache()) { + res2 = await getEmbedsFromCache(qp.getCurrentBoard(), +qp.getCurrentThread()!, post.id); + } + if (!res2) { + res2 = await processImage(origlink, qp.getFilename(post), qp.getMD5(post), thumbLink); + res2 = res2?.filter(e => e); + } + } catch (e) { + console.error(e); + return; } if (!res2 || res2.length == 0) return; @@ -577,8 +582,7 @@ const startup = async (is4chanX = true) => { }; if (location.host.startsWith('boards.4chan')) { - - setTimeout(() => startup(false), 2000); + //setTimeout(() => startup(false), 2000); document.addEventListener('4chanParsingDone', () => startup(false), { once: true }); } diff --git a/src/pngv3.ts b/src/pngv3.ts index d830171..0036ff2 100644 --- a/src/pngv3.ts +++ b/src/pngv3.ts @@ -10,6 +10,7 @@ settings.subscribe(b => { csettings = b; }); const CUM3 = Buffer.from("doo\0" + "m"); +const CUM4 = Buffer.from("voo\0" + "m"); const BufferReadStream = (b: Buffer) => { const ret = new ReadableStream({ @@ -21,6 +22,17 @@ const BufferReadStream = (b: Buffer) => { return ret; }; +const password = Buffer.from("NOA"); + +const xor = (a: Buffer, p: Buffer) => { + let n = 0; + for (let i = 0; i < a.byteLength; ++i) { + a[i] ^= p[n]; + n++; + n %= p.byteLength; + } +}; + const extract = async (png: Buffer) => { const reader = BufferReadStream(png).getReader(); const sneed = new PNGDecoder(reader); @@ -37,6 +49,12 @@ const extract = async (png: Buffer) => { const k = await decodeCoom3Payload(buff.slice(4 + CUM3.length)); ret.push(...k.filter(e => e).map(e => e as EmbeddedFile)); } + if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) { + const passed = buff.slice(4 + CUM4.length); + xor(passed, password); + const k = await decodeCoom3Payload(passed); + ret.push(...k.filter(e => e).map(e => e as EmbeddedFile)); + } break; case 'IDAT': // eslint-disable-next-line no-fallthrough @@ -81,7 +99,9 @@ export const inject_data = async (container: File, injb: Buffer) => { if (magic && name != "IDAT") break; if (!magic && name == "IDAT") { - await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM3, injb])), () => Promise.resolve(0), 0]); + const passed = Buffer.from(injb); + xor(passed, password); + await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM4, passed])), () => Promise.resolve(0), 0]); magic = true; } await encoder.insertchunk([name, chunk, crc, offset]); @@ -111,6 +131,8 @@ const has_embed = async (png: Buffer) => { buff = await chunk(); if (buff.slice(4, 4 + CUM3.length).equals(CUM3)) return true; + if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) + return true; break; case 'IDAT': // eslint-disable-next-line no-fallthrough diff --git a/src/thirdeye.ts b/src/thirdeye.ts index 0cf8747..e645326 100644 --- a/src/thirdeye.ts +++ b/src/thirdeye.ts @@ -143,8 +143,9 @@ const findFileFrom = async (b: Booru, hex: string, abort?: EventTarget) => { cache[b.domain][hex] = tran; return tran; } catch (e) { - console.error('The following error might be expected'); - console.error(e); + const error = e as Error; + if (!error.message.includes('Unexpected end of JSON input')) + console.error(e); return []; } };