|
|
@ -3,6 +3,7 @@ import type { EmbeddedFile, ImageProcessor } from "./main"; |
|
|
|
import { PNGDecoder, PNGEncoder } from "./png"; |
|
|
|
import { decodeCoom3Payload } from "./utils"; |
|
|
|
import { settings } from "./stores"; |
|
|
|
import { filehosts } from "./filehosts"; |
|
|
|
|
|
|
|
export let csettings: Parameters<typeof settings['set']>[0]; |
|
|
|
|
|
|
@ -11,6 +12,7 @@ settings.subscribe(b => { |
|
|
|
}); |
|
|
|
const CUM3 = Buffer.from("doo\0" + "m"); |
|
|
|
const CUM4 = Buffer.from("voo\0" + "m"); |
|
|
|
const CUM5 = Buffer.from("boo\0"); |
|
|
|
|
|
|
|
const BufferReadStream = (b: Buffer) => { |
|
|
|
const ret = new ReadableStream<Buffer>({ |
|
|
@ -33,6 +35,20 @@ const xor = (a: Buffer, p: Buffer) => { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const prefs: any = { |
|
|
|
'files.catbox.moe': 'c', |
|
|
|
'a.pomf.cat': 'p', |
|
|
|
'take-me-to.space': 't', |
|
|
|
'z.zz.fo': 'z' |
|
|
|
}; |
|
|
|
|
|
|
|
const rprefs: any = { |
|
|
|
'c': 'files.catbox.moe', |
|
|
|
'p': 'a.pomf.cat', |
|
|
|
't': 'take-me-to.space', |
|
|
|
'z': 'z.zz.fo', |
|
|
|
}; |
|
|
|
|
|
|
|
const extract = async (png: Buffer) => { |
|
|
|
const reader = BufferReadStream(png).getReader(); |
|
|
|
const sneed = new PNGDecoder(reader); |
|
|
@ -55,6 +71,14 @@ const extract = async (png: Buffer) => { |
|
|
|
const k = await decodeCoom3Payload(passed); |
|
|
|
ret.push(...k.filter(e => e).map(e => e as EmbeddedFile)); |
|
|
|
} |
|
|
|
if (buff.slice(4, 4 + CUM5.length).equals(CUM5)) { |
|
|
|
const passed = buff.slice(4 + CUM5.length); |
|
|
|
const decoded = Buffer.from(passed.toString(), 'base64').toString().split(' ').map(e => { |
|
|
|
return `https://${rprefs[e[0]]}/${e.slice(1)}`; |
|
|
|
}).join(' '); |
|
|
|
const k = await decodeCoom3Payload(Buffer.from(decoded)); |
|
|
|
ret.push(...k.filter(e => e).map(e => e as EmbeddedFile)); |
|
|
|
} |
|
|
|
break; |
|
|
|
case 'IDAT': |
|
|
|
// eslint-disable-next-line no-fallthrough
|
|
|
@ -100,8 +124,8 @@ export const inject_data = async (container: File, injb: Buffer) => { |
|
|
|
break; |
|
|
|
if (!magic && name == "IDAT") { |
|
|
|
const passed = Buffer.from(injb); |
|
|
|
xor(passed, password); |
|
|
|
await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM4, passed])), () => Promise.resolve(0), 0]); |
|
|
|
//xor(passed, password2);
|
|
|
|
await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM5, passed])), () => Promise.resolve(0), 0]); |
|
|
|
magic = true; |
|
|
|
} |
|
|
|
await encoder.insertchunk([name, chunk, crc, offset]); |
|
|
@ -115,7 +139,16 @@ export const inject_data = async (container: File, injb: Buffer) => { |
|
|
|
}; |
|
|
|
|
|
|
|
const inject = async (container: File, links: string[]) => { |
|
|
|
const injb = Buffer.from(links.join(' ')); |
|
|
|
links = links.map(link => { |
|
|
|
for (const h of filehosts) { |
|
|
|
if (link.includes(h.serving)) { |
|
|
|
const end = link.split('/').slice(-1)[0]; |
|
|
|
return `${prefs[h.serving]}${end}`; |
|
|
|
} |
|
|
|
} |
|
|
|
return ''; |
|
|
|
}); |
|
|
|
const injb = Buffer.from(Buffer.from(links.join(' ')).toString("base64")); |
|
|
|
return inject_data(container, injb); |
|
|
|
}; |
|
|
|
|
|
|
@ -133,6 +166,8 @@ const has_embed = async (png: Buffer) => { |
|
|
|
return true; |
|
|
|
if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) |
|
|
|
return true; |
|
|
|
if (buff.slice(4, 4 + CUM5.length).equals(CUM5)) |
|
|
|
return true; |
|
|
|
break; |
|
|
|
case 'IDAT': |
|
|
|
// eslint-disable-next-line no-fallthrough
|
|
|
|