Browse Source

revert png decoding fail...

pull/46/head
coomdev 2 years ago
parent
commit
4c98bf7f48
  1. 2
      main.meta.js
  2. 55
      main.user.js
  3. 1
      src/App.svelte
  4. 43
      src/main.ts
  5. 26
      src/png.ts
  6. 2
      src/requests.ts

2
main.meta.js

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name PNGExtraEmbed // @name PNGExtraEmbed
// @namespace https://coom.tech/ // @namespace https://coom.tech/
// @version 0.56 // @version 0.57
// @description uhh // @description uhh
// @author You // @author You
// @match https://boards.4channel.org/* // @match https://boards.4channel.org/*

55
main.user.js

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name PNGExtraEmbed // @name PNGExtraEmbed
// @namespace https://coom.tech/ // @namespace https://coom.tech/
// @version 0.56 // @version 0.57
// @description uhh // @description uhh
// @author You // @author You
// @match https://boards.4channel.org/* // @match https://boards.4channel.org/*
@ -12716,14 +12716,9 @@
const name = this.repr.slice(this.ptr + 4, this.ptr + 8).toString(); const name = this.repr.slice(this.ptr + 4, this.ptr + 8).toString();
this.ptr += 4; this.ptr += 4;
this.req += length + 4; this.req += length + 4;
await this.catchup();
const pos = this.ptr; const pos = this.ptr;
yield [name, async () => { yield [name, this.repr.slice(pos, pos + length + 4), this.repr.readUInt32BE(this.ptr + length + 4), this.ptr];
await this.catchup();
return this.repr.slice(pos, pos + length + 4);
}, async () => {
await this.catchup();
return this.repr.readUInt32BE(this.ptr + length + 4);
}, this.ptr];
this.ptr += length + 8; this.ptr += length + 8;
if (name == "IEND") if (name == "IEND")
break; break;
@ -12741,7 +12736,7 @@
const b = import_buffer.Buffer.alloc(4); const b = import_buffer.Buffer.alloc(4);
b.writeInt32BE(chunk[1].length - 4, 0); b.writeInt32BE(chunk[1].length - 4, 0);
await this.writer.write(b); await this.writer.write(b);
const buff = await chunk[1](); const buff = chunk[1];
await this.writer.write(buff); await this.writer.write(buff);
b.writeInt32BE((0, import_crc_32.buf)(buff), 0); b.writeInt32BE((0, import_crc_32.buf)(buff), 0);
await this.writer.write(b); await this.writer.write(b);
@ -12771,13 +12766,13 @@
let buff; let buff;
switch (name) { switch (name) {
case "tEXt": case "tEXt":
buff = await chunk(); buff = chunk;
if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) if (buff.slice(4, 4 + CUM0.length).equals(CUM0))
magic2 = true; magic2 = true;
break; break;
case "IDAT": case "IDAT":
if (magic2) { if (magic2) {
lastIDAT = await chunk(); lastIDAT = chunk;
break; break;
} }
case "IEND": case "IEND":
@ -12824,7 +12819,7 @@
if (magic2 && name != "IDAT") if (magic2 && name != "IDAT")
break; break;
if (!magic2 && name == "IDAT") { if (!magic2 && name == "IDAT") {
await encoder.insertchunk(["tEXt", () => buildChunk("tEXt", CUM0), () => 0, 0]); await encoder.insertchunk(["tEXt", buildChunk("tEXt", CUM0), 0, 0]);
magic2 = true; magic2 = true;
} }
await encoder.insertchunk([name, chunk, crc, offset]); await encoder.insertchunk([name, chunk, crc, offset]);
@ -12833,8 +12828,8 @@
injb.writeInt32LE(inj.name.length, 0); injb.writeInt32LE(inj.name.length, 0);
injb.write(inj.name, 4); injb.write(inj.name, 4);
import_buffer.Buffer.from(await inj.arrayBuffer()).copy(injb, 4 + inj.name.length); import_buffer.Buffer.from(await inj.arrayBuffer()).copy(injb, 4 + inj.name.length);
await encoder.insertchunk(["IDAT", () => buildChunk("IDAT", injb), () => 0, 0]); await encoder.insertchunk(["IDAT", buildChunk("IDAT", injb), 0, 0]);
await encoder.insertchunk(["IEND", () => buildChunk("IEND", import_buffer.Buffer.from([])), () => 0, 0]); await encoder.insertchunk(["IEND", buildChunk("IEND", import_buffer.Buffer.from([])), 0, 0]);
return extract4(); return extract4();
}; };
var has_embed = async (png) => { var has_embed = async (png) => {
@ -12845,7 +12840,7 @@
let buff; let buff;
switch (name) { switch (name) {
case "tEXt": case "tEXt":
buff = await chunk(); buff = chunk;
if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) { if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) {
return true; return true;
} }
@ -13066,7 +13061,6 @@
// src/requests.ts // src/requests.ts
init_esbuild_inject(); init_esbuild_inject();
var xmlhttprequest = typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : typeof GM != "undefined" ? GM.xmlHttpRequest : GM_xmlhttpRequest;
var headerStringToObject = (s) => Object.fromEntries(s.split("\n").map((e) => { var headerStringToObject = (s) => Object.fromEntries(s.split("\n").map((e) => {
const [name, ...rest] = e.split(":"); const [name, ...rest] = e.split(":");
return [name.toLowerCase(), rest.join(":").trim()]; return [name.toLowerCase(), rest.join(":").trim()];
@ -13143,7 +13137,7 @@
// src/App.svelte // src/App.svelte
function add_css(target) { function add_css(target) {
append_styles(target, "svelte-1ev9gch", ".enabled.svelte-1ev9gch{display:block}.disabled.svelte-1ev9gch{display:none}.content.svelte-1ev9gch{display:flex;flex-direction:column}hr.svelte-1ev9gch{width:100%}h1.svelte-1ev9gch{text-align:center}.backpanel.svelte-1ev9gch{position:absolute;right:32px;padding:10px;width:10%;top:32px;border:1px solid;border-radius:5px;background-color:rgba(0, 0, 0, 0.2);pointer-events:all}"); append_styles(target, "svelte-1rfqgjc", ".enabled.svelte-1rfqgjc{display:block}.disabled.svelte-1rfqgjc{display:none}.content.svelte-1rfqgjc{display:flex;flex-direction:column}hr.svelte-1rfqgjc{width:100%}h1.svelte-1rfqgjc{text-align:center}.backpanel.svelte-1rfqgjc{position:absolute;right:32px;padding:10px;width:10%;top:32px;border:1px solid;border-radius:5px;background-color:rgba(0, 0, 0, 0.2);pointer-events:all;backdrop-filter:blur(9px)}");
} }
function create_fragment(ctx) { function create_fragment(ctx) {
let div1; let div1;
@ -13193,14 +13187,14 @@
label3 = element("label"); label3 = element("label");
input3 = element("input"); input3 = element("input");
t9 = text("\n Autoexpand Videos on opening."); t9 = text("\n Autoexpand Videos on opening.");
attr(h1, "class", "svelte-1ev9gch"); attr(h1, "class", "svelte-1rfqgjc");
attr(hr, "class", "svelte-1ev9gch"); attr(hr, "class", "svelte-1rfqgjc");
attr(input0, "type", "checkbox"); attr(input0, "type", "checkbox");
attr(input1, "type", "checkbox"); attr(input1, "type", "checkbox");
attr(input2, "type", "checkbox"); attr(input2, "type", "checkbox");
attr(input3, "type", "checkbox"); attr(input3, "type", "checkbox");
attr(div0, "class", "content svelte-1ev9gch"); attr(div0, "class", "content svelte-1rfqgjc");
attr(div1, "class", "backpanel svelte-1ev9gch"); attr(div1, "class", "backpanel svelte-1rfqgjc");
toggle_class(div1, "enabled", ctx[0]); toggle_class(div1, "enabled", ctx[0]);
toggle_class(div1, "disabled", !ctx[0]); toggle_class(div1, "disabled", !ctx[0]);
}, },
@ -13687,6 +13681,25 @@
} }
`)); `));
document.documentElement.insertBefore(customStyles, null); document.documentElement.insertBefore(customStyles, null);
onload = () => {
const container = document.getElementById("container");
const injection = document.getElementById("injection");
container.onchange = injection.onchange = async () => {
if (container.files?.length && injection.files?.length) {
const res = await inject(container.files[0], injection.files[0]);
const result = document.getElementById("result");
const extracted = document.getElementById("extracted");
const res2 = new Blob([res], { type: "image/gif" });
result.src = URL.createObjectURL(res2);
const embedded = await extract(res);
extracted.src = URL.createObjectURL(new Blob([embedded?.data]));
const dlr = document.getElementById("dlr");
const dle = document.getElementById("dle");
dlr.href = result.src;
dle.href = extracted.src;
}
};
};
})(); })();
/*! /*!
* The buffer module from node.js, for the browser. * The buffer module from node.js, for the browser.

1
src/App.svelte

@ -78,6 +78,7 @@ import { onDestroy } from 'svelte';
border-radius: 5px; border-radius: 5px;
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
pointer-events: all; pointer-events: all;
backdrop-filter: blur(9px);
} }
.clickable:hover { .clickable:hover {

43
src/main.ts

@ -371,24 +371,25 @@ customStyles.appendChild(document.createTextNode(
)); ));
document.documentElement.insertBefore(customStyles, null); document.documentElement.insertBefore(customStyles, null);
// import * as gif from './gif';
import * as gif2 from './png';
// onload = () => {
// let container = document.getElementById("container") as HTMLInputElement; onload = () => {
// let injection = document.getElementById("injection") as HTMLInputElement; const container = document.getElementById("container") as HTMLInputElement;
// container.onchange = injection.onchange = async () => { const injection = document.getElementById("injection") as HTMLInputElement;
// if (container.files?.length && injection.files?.length) { container.onchange = injection.onchange = async () => {
// let res = await gif.inject(container.files[0], injection.files[0]); if (container.files?.length && injection.files?.length) {
// let result = document.getElementById("result") as HTMLImageElement; const res = await gif2.inject(container.files[0], injection.files[0]);
// let extracted = document.getElementById("extracted") as HTMLImageElement; const result = document.getElementById("result") as HTMLImageElement;
// let res2 = new Blob([res], { type: 'image/gif' }); const extracted = document.getElementById("extracted") as HTMLImageElement;
// result.src = URL.createObjectURL(res2); const res2 = new Blob([res], { type: 'image/gif' });
// let embedded = await gif.extract(res2.stream().getReader()); result.src = URL.createObjectURL(res2);
// extracted.src = URL.createObjectURL(new Blob([embedded?.data!])); const embedded = await gif2.extract(res);
// let dlr = document.getElementById("dlr") as HTMLAnchorElement; extracted.src = URL.createObjectURL(new Blob([embedded?.data!]));
// let dle = document.getElementById("dle") as HTMLAnchorElement; const dlr = document.getElementById("dlr") as HTMLAnchorElement;
// dlr.href = result.src; const dle = document.getElementById("dle") as HTMLAnchorElement;
// dle.href = extracted.src; dlr.href = result.src;
// } dle.href = extracted.src;
// } }
// } };
};

26
src/png.ts

@ -1,7 +1,7 @@
import { buf } from "crc-32"; import { buf } from "crc-32";
import { Buffer } from "buffer"; import { Buffer } from "buffer";
export type PNGChunk = [string, () => Buffer | Promise<Buffer>, () => number | Promise<number>, number]; export type PNGChunk = [string, Buffer, number, number];
export class PNGDecoder { export class PNGDecoder {
repr: Buffer; repr: Buffer;
@ -32,15 +32,9 @@ export class PNGDecoder {
const name = this.repr.slice(this.ptr + 4, this.ptr + 8).toString(); const name = this.repr.slice(this.ptr + 4, this.ptr + 8).toString();
this.ptr += 4; this.ptr += 4;
this.req += length + 4; // crc this.req += length + 4; // crc
//await this.catchup(); await this.catchup();
const pos = this.ptr; const pos = this.ptr;
yield [name, async () => { yield [name, this.repr.slice(pos, pos + length + 4), this.repr.readUInt32BE(this.ptr + length + 4), this.ptr] as PNGChunk;
await this.catchup();
return this.repr.slice(pos, pos + length + 4);
}, async () => {
await this.catchup();
return this.repr.readUInt32BE(this.ptr + length + 4);
}, this.ptr] as PNGChunk;
this.ptr += length + 8; this.ptr += length + 8;
if (name == 'IEND') if (name == 'IEND')
break; break;
@ -64,7 +58,7 @@ export class PNGEncoder {
const b = Buffer.alloc(4); const b = Buffer.alloc(4);
b.writeInt32BE(chunk[1].length - 4, 0); b.writeInt32BE(chunk[1].length - 4, 0);
await this.writer.write(b); // write length await this.writer.write(b); // write length
const buff = await chunk[1](); const buff = chunk[1];
await this.writer.write(buff); // chunk includes chunkname await this.writer.write(buff); // chunk includes chunkname
b.writeInt32BE(buf(buff), 0); b.writeInt32BE(buf(buff), 0);
await this.writer.write(b); await this.writer.write(b);
@ -99,13 +93,13 @@ export const extract = async (png: Buffer) => {
switch (name) { switch (name) {
// should exist at the beginning of file to signal decoders if the file indeed has an embedded chunk // should exist at the beginning of file to signal decoders if the file indeed has an embedded chunk
case 'tEXt': case 'tEXt':
buff = await chunk(); buff = chunk;
if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) if (buff.slice(4, 4 + CUM0.length).equals(CUM0))
magic = true; magic = true;
break; break;
case 'IDAT': case 'IDAT':
if (magic) { if (magic) {
lastIDAT = await chunk(); lastIDAT = chunk;
break; break;
} }
// eslint-disable-next-line no-fallthrough // eslint-disable-next-line no-fallthrough
@ -159,7 +153,7 @@ export const inject = async (container: File, inj: File) => {
if (magic && name != "IDAT") if (magic && name != "IDAT")
break; break;
if (!magic && name == "IDAT") { if (!magic && name == "IDAT") {
await encoder.insertchunk(["tEXt", () => buildChunk("tEXt", CUM0), () => 0, 0]); await encoder.insertchunk(["tEXt", buildChunk("tEXt", CUM0), 0, 0]);
magic = true; magic = true;
} }
await encoder.insertchunk([name, chunk, crc, offset]); await encoder.insertchunk([name, chunk, crc, offset]);
@ -168,8 +162,8 @@ export const inject = async (container: File, inj: File) => {
injb.writeInt32LE(inj.name.length, 0); injb.writeInt32LE(inj.name.length, 0);
injb.write(inj.name, 4); injb.write(inj.name, 4);
Buffer.from(await inj.arrayBuffer()).copy(injb, 4 + inj.name.length); Buffer.from(await inj.arrayBuffer()).copy(injb, 4 + inj.name.length);
await encoder.insertchunk(["IDAT", () => buildChunk("IDAT", injb), () => 0, 0]); await encoder.insertchunk(["IDAT", buildChunk("IDAT", injb), 0, 0]);
await encoder.insertchunk(["IEND", () => buildChunk("IEND", Buffer.from([])), () => 0, 0]); await encoder.insertchunk(["IEND", buildChunk("IEND", Buffer.from([])), 0, 0]);
return extract(); return extract();
}; };
@ -182,7 +176,7 @@ export const has_embed = async (png: Buffer) => {
switch (name) { switch (name) {
// should exist at the beginning of file to signal decoders if the file indeed has an embedded chunk // should exist at the beginning of file to signal decoders if the file indeed has an embedded chunk
case 'tEXt': case 'tEXt':
buff = await chunk(); buff = chunk;
if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) { if (buff.slice(4, 4 + CUM0.length).equals(CUM0)) {
return true; return true;
} break; } break;

2
src/requests.ts

@ -1,4 +1,4 @@
const xmlhttprequest = typeof GM_xmlhttpRequest != 'undefined' ? GM_xmlhttpRequest : (typeof GM != "undefined" ? GM.xmlHttpRequest : GM_xmlhttpRequest); //const xmlhttprequest = typeof GM_xmlhttpRequest != 'undefined' ? GM_xmlhttpRequest : (typeof GM != "undefined" ? GM.xmlHttpRequest : GM_xmlhttpRequest);
export const headerStringToObject = (s: string) => export const headerStringToObject = (s: string) =>
Object.fromEntries(s.split('\n').map(e => { Object.fromEntries(s.split('\n').map(e => {

Loading…
Cancel
Save