diff --git a/PEE-chrome.crx b/PEE-chrome.crx
index a472ff4..e4c0a22 100644
Binary files a/PEE-chrome.crx and b/PEE-chrome.crx differ
diff --git a/README.md b/README.md
index 9ce9125..201e7e1 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ Note: 4chanX isn't a hard requirement, just recommended because it's overall a n
## The newer way (WIP)
- [Install 4chanX (recommended)](https://www.4chan-x.net/builds/4chan-X.user.js)
-- Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/coomdev/PEE/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.210-an+fx.xpi) or [Chrome-based](https://git.coom.tech/coomdev/PEE/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/PEE-chrome.crx))
+- Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/coomdev/PEE/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.211-an+fx.xpi) or [Chrome-based](https://git.coom.tech/coomdev/PEE/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/PEE-chrome.crx))
How to Build
============
diff --git a/build-chrome.js b/build-chrome.js
index cf25a43..741ad92 100644
--- a/build-chrome.js
+++ b/build-chrome.js
@@ -133,7 +133,7 @@ const manif = {
define: {
global: 'window',
execution_mode: '"chrome_api"',
- isBackground: 'false',
+ isBackground: 'true',
BUILD_VERSION: JSON.stringify([0, rev])
},
inject: ['./esbuild.inject.js'],
diff --git a/build-ff.js b/build-ff.js
index d2cce66..b625b7b 100644
--- a/build-ff.js
+++ b/build-ff.js
@@ -132,7 +132,7 @@ const manif = {
define: {
global: 'window',
execution_mode: '"ff_api"',
- isBackground: 'false',
+ isBackground: 'true',
BUILD_VERSION: JSON.stringify([0, rev])
},
inject: ['./esbuild.inject.js'],
diff --git a/chrome/manifest.json b/chrome/manifest.json
index e31871a..2fe83be 100644
--- a/chrome/manifest.json
+++ b/chrome/manifest.json
@@ -3,7 +3,7 @@
"update_url": "https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/chrome_update.xml",
"name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!",
- "version": "0.210",
+ "version": "0.211",
"icons": {
"64": "1449696017588.png"
},
diff --git a/chrome_update.xml b/chrome_update.xml
index 06fe8c0..2e1cd47 100644
--- a/chrome_update.xml
+++ b/chrome_update.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/firefox/manifest.json b/firefox/manifest.json
index 74c8119..e9279bb 100644
--- a/firefox/manifest.json
+++ b/firefox/manifest.json
@@ -7,7 +7,7 @@
},
"name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!",
- "version": "0.210",
+ "version": "0.211",
"icons": {
"64": "1449696017588.png"
},
diff --git a/firefox_update.json b/firefox_update.json
index 1c065a0..815693b 100644
--- a/firefox_update.json
+++ b/firefox_update.json
@@ -1 +1 @@
-{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.210","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pee-firefox.zip"}]}}}
\ No newline at end of file
+{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.211","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pee-firefox.zip"}]}}}
\ No newline at end of file
diff --git a/pngextraembedder-0.210-an+fx.xpi b/pngextraembedder-0.210-an+fx.xpi
deleted file mode 100644
index 4cb9e94..0000000
Binary files a/pngextraembedder-0.210-an+fx.xpi and /dev/null differ
diff --git a/pngextraembedder-0.211-an+fx.xpi b/pngextraembedder-0.211-an+fx.xpi
new file mode 100644
index 0000000..bc4e0ac
Binary files /dev/null and b/pngextraembedder-0.211-an+fx.xpi differ
diff --git a/src/Components/PostOptions.svelte b/src/Components/PostOptions.svelte
index b400ee3..f0ec030 100644
--- a/src/Components/PostOptions.svelte
+++ b/src/Components/PostOptions.svelte
@@ -32,9 +32,10 @@
}
// This is an event to signal a change in the container file
+ let inhibit = false;
document.addEventListener("PEEFile", async (e) => {
let file = (e as any).detail as File;
- if (currentEmbed?.file != file) {
+ if (currentEmbed?.file != file && !inhibit) {
original = file;
if ($settings.auto_embed && $appState.client) {
const tags = $settings.auto_tags
@@ -49,6 +50,8 @@
const nlinks = await uploadFiles(files);
links = [...links, ...nlinks];
}
+ inhibit = true;
+ setTimeout(() => inhibit = false, 500); // hack around 4chan(X)(?) inconsistent getFile
embedContent(e);
}
});
diff --git a/src/background.ts b/src/background.ts
index 3881418..3730709 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -102,6 +102,38 @@ obj.webRequest.onBeforeRequest.addListener((details) => {
}, filts, ['blocking']);
*/
+async function deserialize(src: any): Promise {
+ switch (src.cls) {
+ case 'FormData': {
+ const ret = new FormData();
+ for (const [key, items] of src.value) {
+ for (const item of items) {
+ ret.append(key, await deserialize(item));
+ }
+ }
+ return ret;
+ }
+ case 'File': {
+ return new File([await (await fetch(src.value)).blob()], src.name, {
+ lastModified: src.lastModified,
+ type: src.type
+ });
+ }
+ case 'Blob': {
+ return new Blob([await (await fetch(src.value)).blob()], {
+ type: src.type
+ });
+ }
+ case 'Object': {
+ const ret = {} as any;
+ for (const prop in src.value) {
+ ret[prop] = await deserialize(src.value[prop]);
+ }
+ return ret;
+ }
+ }
+}
+
const pendingFetches = new Map();
const bgCorsFetch = async (c: browser.runtime.Port, id: number, input: string, init?: RequestInit) => {
@@ -113,6 +145,8 @@ const bgCorsFetch = async (c: browser.runtime.Port, id: number, input: string, i
if (input.startsWith('//')) // wtf fireshit??
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;
diff --git a/src/main.ts b/src/main.ts
index e46bbb9..148f216 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -422,18 +422,20 @@ const startup = async (is4chanX = true) => {
registerPlugin('quote', postQuote);
if (!is4chanX && location.host.startsWith('boards.4chan')) {
- (async () => {
- while (!('QR' in window))
- await new Promise(_ => setTimeout(_, 250));
- const qr = QR;
- const show = qr.show.bind(qr);
- qr.show = (...args: any[]) => {
- show(...args);
- document.dispatchEvent(new CustomEvent("QRDialogCreation", {
- detail: document.getElementById('quickReply')
- }));
- };
- })();
+ const QRObs = new MutationObserver(rec => {
+ rec.forEach(m => {
+ m.addedNodes.forEach(no => {
+ if ((no as HTMLElement).id != "quickReply") {
+ return;
+ }
+ document.dispatchEvent(new CustomEvent("QRDialogCreation", {
+ detail: no
+ }));
+ });
+ });
+ });
+ // only need immediate children of body
+ QRObs.observe(document.body, { childList: true });
document.addEventListener("QRGetFile", (e) => {
const qr = document.getElementById('qrFile') as HTMLInputElement | null;
diff --git a/src/platform.ts b/src/platform.ts
index e3bf656..f9a4d12 100644
--- a/src/platform.ts
+++ b/src/platform.ts
@@ -69,6 +69,42 @@ const extrBlob = async (url: string) => {
return new Uint8Array(ret);
};
+async function serialize(src: any): Promise {
+ if (src instanceof FormData) {
+ const value = [];
+ for (const kv of src)
+ value.push([kv[0], await Promise.all(src.getAll(kv[0]).map(serialize))]);
+ return {
+ cls: 'FormData', value,
+ };
+ }
+ if (src instanceof File) {
+ const { name, type, lastModified } = src;
+ const value = URL.createObjectURL(src);
+ return {
+ cls: 'File',
+ name, type, lastModified, value,
+ };
+ }
+ if (src instanceof Blob) {
+ const { type } = src;
+ const value = URL.createObjectURL(src);
+ return {
+ cls: 'Blob', type, value,
+ };
+ }
+ if (src === null || src === undefined || typeof src != "object")
+ return src;
+ const ret = {
+ cls: 'Object',
+ value: {}
+ } as any;
+ for (const prop in src) {
+ ret.value[prop] = await serialize(src[prop]);
+ }
+ return ret;
+}
+
export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTarget) => {
const id = gid++;
@@ -82,6 +118,13 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa
}
}*/
+ if (init?.body) {
+ // Chrom* can't pass around FormData and File/Blobs between
+ // the content and bg scripts, so the data is passed through bloburls
+ if (execution_mode == "chrome_api")
+ init.body = await serialize(init.body);
+ }
+
const prom = new Promise>>((_, rej) => {
let gcontroller: ReadableStreamController | undefined;
let buffer: Uint8Array[] = [];
diff --git a/src/utils.ts b/src/utils.ts
index 3fe5112..afdce1a 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -63,7 +63,37 @@ const generateThumbnail = async (f: File): Promise => {
return Buffer.from(await blob.arrayBuffer());
};
+export const buildPeeFileFF = async (f: File) => {
+ let thumbnail = new Uint8Array();
+ const te = new TextEncoder();
+ thumbnail = await generateThumbnail(f);
+ const namebuf = te.encode(f.name);
+ const ret = new Uint8Array(4 /* Magic */ +
+ 1 /* Flags */ + namebuf.byteLength + 1 +
+ (thumbnail.byteLength != 0 ? (4 + thumbnail.byteLength) : 0) /* TSize + Thumbnail */ +
+ f.size /*Teh file*/);
+ const ret32 = new DataView(ret.buffer);
+ let ptr = 0;
+ ret.set(te.encode('PEE\0'), 0);
+ ptr += 4;
+ ret[ptr++] = 1 | ((+(thumbnail.length != 0)) << 2);
+ ret.set(namebuf, ptr);
+ ptr += namebuf.byteLength;
+ ret[ptr++] = 0;
+ if (thumbnail.length > 0) {
+ ret32.setUint32(ptr, thumbnail.byteLength, true);
+ ptr += 4;
+ ret.set(thumbnail, ptr);
+ ptr += thumbnail.byteLength;
+ }
+ const content = await f.arrayBuffer();
+ ret.set(new Uint8Array(content), ptr);
+ return new Blob([ret]);
+};
+
export const buildPeeFile = async (f: File) => {
+ if (execution_mode == "ff_api")
+ return buildPeeFileFF(f);
//const isMemeBrowser = navigator.userAgent.indexOf("Chrome") == -1;
let thumbnail = Buffer.alloc(0);
thumbnail = await generateThumbnail(f);
@@ -85,7 +115,8 @@ export const buildPeeFile = async (f: File) => {
thumbnail.copy(ret, ptr);
ptr += thumbnail.byteLength;
}
- Buffer.from(await f.arrayBuffer()).copy(ret, ptr);
+ const content = await f.arrayBuffer();
+ Buffer.from(content).copy(ret, ptr);
return new Blob([ret]);
};
@@ -200,7 +231,8 @@ export const uploadFiles = async (injs: File[]) => {
let total = 0;
fireNotification('info', `Uploading ${injs.length} files...`);
return await Promise.all(injs.map(async inj => {
- const ret = await filehosts[csettings.fhost || 0].uploadFile(await buildPeeFile(inj));
+ const peefile = await buildPeeFile(inj);
+ const ret = await filehosts[csettings.fhost || 0].uploadFile(peefile);
fireNotification('info', `Uploaded files [${++total}/${injs.length}] ${ret}`);
return ret;
}));
diff --git a/update.xml b/update.xml
deleted file mode 100644
index fea80b6..0000000
--- a/update.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file