coomdev
2 years ago
9 changed files with 9595 additions and 34 deletions
@ -0,0 +1,3 @@ |
|||
{ |
|||
"typescript.tsdk": "node_modules/typescript/lib" |
|||
} |
@ -0,0 +1,119 @@ |
|||
#include <stdio.h> |
|||
#include <sys/mman.h> |
|||
#include <sys/stat.h> |
|||
#include <sys/fcntl.h> |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
|
|||
typedef unsigned char u8; |
|||
|
|||
u8 *map_file(const char *file, size_t *sz) { |
|||
struct stat fs; |
|||
int fd = open(file, O_RDONLY); |
|||
fstat(fd, &fs); |
|||
*sz = fs.st_size; |
|||
u8 *filecontent = mmap(0, *sz, PROT_READ, MAP_PRIVATE, fd, 0); |
|||
return filecontent; |
|||
} |
|||
|
|||
char sign[14] = "!\xFF\x0B""COOMTECH0.1"; |
|||
|
|||
void write_gif_embedding(const u8 *data, size_t size) { |
|||
write(1, sign, sizeof(sign)); |
|||
u8 ws; |
|||
while (size) { |
|||
ws = size >= 255 ? 255 : size; |
|||
write(1, &ws, 1); |
|||
write(1, data, ws); |
|||
data += ws; |
|||
size -= ws; |
|||
} |
|||
ws = 0; |
|||
write(1, &ws, 1); |
|||
} |
|||
|
|||
void extract_from_gif(const u8 *data, size_t size, |
|||
void **outdata, size_t *osize) { |
|||
const u8 *ptr = data; |
|||
|
|||
u8 field = ptr[10]; |
|||
u8 gcte = !!(field & (1 << 7)); |
|||
const u8 *end = ptr + 13; |
|||
if (gcte) { |
|||
int gcts = 1 << ((field & 7) + 1); |
|||
end += 3 * gcts; |
|||
} |
|||
// skip
|
|||
while (*end == '!') { |
|||
if (memcmp(end, sign, sizeof(sign))) { |
|||
end += 3 + end[2]; |
|||
while (1) { |
|||
u8 v = *end++; |
|||
if (!v) |
|||
break; |
|||
end += v; |
|||
} |
|||
} else { |
|||
const u8 *count = end + sizeof(sign); |
|||
size_t t = 0; |
|||
while (*count) { |
|||
t += *count; |
|||
count += *count + 1; |
|||
} |
|||
void *buff = malloc(t); |
|||
count = end + 14; |
|||
t = 0; |
|||
while (*count) { |
|||
memcpy(buff + t, count + 1, *count); |
|||
t += *count; |
|||
count += *count + 1; |
|||
} |
|||
*osize = t; |
|||
*outdata = buff; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#if 1 |
|||
|
|||
int main(int argc, char *argv[argc]) { |
|||
size_t size; |
|||
u8 *file = map_file(argv[1], &size); |
|||
u8 *ptr = file; |
|||
|
|||
u8 field = ptr[10]; |
|||
u8 gcte = !!(field & (1 << 7)); |
|||
u8 *end = ptr + 13; |
|||
if (gcte) { |
|||
int gcts = 1 << ((field & 7) + 1); |
|||
end += 3 * gcts; |
|||
} |
|||
// skip
|
|||
if (memcmp(end, "!\xFF\x0BNETSCAPE2.0\x03\x01\x00\x00\x00", 19) == 0) |
|||
end += 19; |
|||
write(1, file, end - file); |
|||
|
|||
size_t size2; |
|||
u8 *file2 = map_file(argv[2], &size2); |
|||
|
|||
write_gif_embedding(file2, size2); |
|||
write(1, end, size - (end - file)); |
|||
return 0; |
|||
} |
|||
|
|||
#else |
|||
|
|||
int main(int argc, char *argv[argc]) { |
|||
printf("%zu\n", sizeof(sign)); |
|||
size_t size, sz; |
|||
u8 *file = map_file(argv[1], &size); |
|||
u8 *ptr = file; |
|||
void *ext; |
|||
extract_from_gif(file, size, &ext, &sz); |
|||
printf("extracted (%zu bytes) %s\n", sz, ext); |
|||
return 0; |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,116 @@ |
|||
#include <stdio.h> |
|||
#include <sys/mman.h> |
|||
#include <sys/stat.h> |
|||
#include <sys/fcntl.h> |
|||
#include <unistd.h> |
|||
#include <string.h> |
|||
#include <stdlib.h> |
|||
|
|||
typedef unsigned char u8; |
|||
|
|||
u8 *map_file(const char *file, size_t *sz) { |
|||
struct stat fs; |
|||
int fd = open(file, O_RDONLY); |
|||
fstat(fd, &fs); |
|||
*sz = fs.st_size; |
|||
u8 *filecontent = mmap(0, *sz, PROT_READ, MAP_PRIVATE, fd, 0); |
|||
return filecontent; |
|||
} |
|||
|
|||
char sign[14] = "!\xFF\x0B""COOMTECH0.1"; |
|||
|
|||
void write_gif_embedding(const u8 *data, size_t size) { |
|||
write(1, sign, sizeof(sign)); |
|||
u8 ws; |
|||
while (size) { |
|||
ws = size >= 255 ? 255 : size; |
|||
write(1, &ws, 1); |
|||
write(1, data, ws); |
|||
data += ws; |
|||
size -= ws; |
|||
} |
|||
ws = 0; |
|||
write(1, &ws, 1); |
|||
} |
|||
|
|||
void extract_from_gif(const u8 *data, size_t size, |
|||
void **outdata, size_t *osize) { |
|||
const u8 *ptr = data; |
|||
|
|||
u8 field = ptr[10]; |
|||
u8 gcte = !!(field & (1 << 7)); |
|||
const u8 *end = ptr + 13; |
|||
if (gcte) { |
|||
int gcts = 1 << ((field & 7) + 1); |
|||
end += 3 * gcts; |
|||
} |
|||
// skip
|
|||
while (*end == '!') { |
|||
if (memcmp(end, sign, sizeof(sign))) { |
|||
end += 3 + end[2]; |
|||
while (1) { |
|||
u8 v = *end++; |
|||
if (!v) |
|||
break; |
|||
end += v; |
|||
} |
|||
} else { |
|||
const u8 *count = end + sizeof(sign); |
|||
size_t t = 0; |
|||
while (*count) { |
|||
t += *count; |
|||
count += *count + 1; |
|||
} |
|||
void *buff = malloc(t); |
|||
count = end + 14; |
|||
t = 0; |
|||
while (*count) { |
|||
memcpy(buff + t, count + 1, *count); |
|||
t += *count; |
|||
count += *count + 1; |
|||
} |
|||
*osize = t; |
|||
*outdata = buff; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
#if 0 |
|||
|
|||
int main(int argc, char *argv[argc]) { |
|||
size_t size; |
|||
u8 *file = map_file(argv[1], &size); |
|||
u8 *ptr = file; |
|||
|
|||
u8 field = ptr[10]; |
|||
u8 gcte = !!(field & (1 << 7)); |
|||
u8 *end = ptr + 13; |
|||
if (gcte) { |
|||
int gcts = 1 << ((field & 7) + 1); |
|||
end += 3 * gcts; |
|||
} |
|||
// skip
|
|||
if (memcmp(end, "!\xFF\x0BNETSCAPE2.0\x03\x01\x00\x00\x00", 19) == 0) |
|||
end += 19; |
|||
write(1, file, end - file); |
|||
const char *str = "IM GOING TO COOM AAAAAAAAAAAA"; |
|||
write_gif_embedding(str, strlen(str)); |
|||
write(1, end, size - (end - file)); |
|||
return 0; |
|||
} |
|||
|
|||
#else |
|||
|
|||
int main(int argc, char *argv[argc]) { |
|||
printf("%zu\n", sizeof(sign)); |
|||
size_t size, sz; |
|||
u8 *file = map_file(argv[1], &size); |
|||
u8 *ptr = file; |
|||
void *ext; |
|||
extract_from_gif(file, size, &ext, &sz); |
|||
printf("extracted (%zu bytes) %s\n", sz, ext); |
|||
return 0; |
|||
} |
|||
|
|||
#endif |
@ -0,0 +1,199 @@ |
|||
|
|||
function readVint(buff: ArrayBuffer, start = 0) { |
|||
const buffer = new Uint8Array(buff); |
|||
const length = 8 - Math.floor(Math.log2(buffer[start])); |
|||
if (length > 8) { |
|||
throw new Error(`Unrepresentable length`); |
|||
} |
|||
|
|||
if (start + length > buffer.length) { |
|||
return; |
|||
} |
|||
|
|||
let value = buffer[start] & ((1 << (8 - length)) - 1); |
|||
for (let i = 1; i < length; i += 1) { |
|||
if (i === 7) { |
|||
if (value >= 2 ** 8 && buffer[start + 7] > 0) { |
|||
return { length, value: -1 }; |
|||
} |
|||
} |
|||
value *= 2 ** 8; |
|||
value += buffer[start + i]; |
|||
} |
|||
|
|||
return { length, value }; |
|||
} |
|||
|
|||
enum DecoderState { |
|||
Tag, Size, Content |
|||
} |
|||
|
|||
const schema = new Map([ |
|||
[ |
|||
0x1a45dfa3, |
|||
{ |
|||
name: 'EBML', |
|||
type: 'm', |
|||
}, |
|||
], [ |
|||
0x1654ae6b, |
|||
{ |
|||
name: 'Tracks', |
|||
type: 'm', |
|||
}, |
|||
], [ |
|||
0x4485, |
|||
{ |
|||
name: 'TagBinary', |
|||
type: 'b', |
|||
}, |
|||
], |
|||
[ |
|||
0x4487, |
|||
{ |
|||
name: 'TagString', |
|||
type: '8', |
|||
}, |
|||
], |
|||
[ |
|||
0x63c0, |
|||
{ |
|||
name: 'Targets', |
|||
type: 'm', |
|||
}, |
|||
], |
|||
[ |
|||
0x7373, |
|||
{ |
|||
name: 'Tag', |
|||
type: 'm', |
|||
}, |
|||
], |
|||
[ |
|||
0x1254c367, |
|||
{ |
|||
name: 'Tags', |
|||
type: 'm', |
|||
}, |
|||
], |
|||
[ |
|||
0x45a3, |
|||
{ |
|||
name: 'TagName', |
|||
type: '8', |
|||
}, |
|||
], |
|||
[ |
|||
0x67c8, |
|||
{ |
|||
name: 'SimpleTag', |
|||
type: 'm', |
|||
}, |
|||
]]); |
|||
|
|||
type Tag = [id: number, type: string, name: string, ln: number, pos: number, size?: number] |
|||
|
|||
export const decodeEBML = (arr: ArrayBuffer): { |
|||
tag: Tag; |
|||
isEnd?: true | undefined; |
|||
data?: ArrayBuffer | undefined; |
|||
}[] => { |
|||
let ptr = 0; |
|||
const buffer = new Uint8Array(arr); |
|||
const dw = new DataView(arr); |
|||
let total = 0; |
|||
let stack: Tag[] = []; |
|||
let ret: { tag: Tag, isEnd?: true, data?: ArrayBuffer }[] = []; |
|||
let state: number = DecoderState.Tag; |
|||
|
|||
const readTag = () => { |
|||
if (ptr >= arr.byteLength) |
|||
return; |
|||
const vint = readVint(arr, ptr); |
|||
if (!vint) |
|||
return; |
|||
let v = 0; |
|||
switch (vint.length) { |
|||
case 1: |
|||
v = dw.getInt8(ptr); |
|||
break; |
|||
case 2: |
|||
v = dw.getInt16(ptr); |
|||
break; |
|||
case 3: |
|||
v = dw.getInt32(ptr) & 0xFFFFFF; |
|||
break; |
|||
case 4: |
|||
v = dw.getInt32(ptr); |
|||
break; |
|||
default: |
|||
throw "Unexpected v size"; |
|||
} |
|||
const elem = schema.get(v); |
|||
const start = total; |
|||
total += vint.length; |
|||
const tag = [v, elem?.type, elem?.name, vint.length, start] as Tag; |
|||
stack.push(tag); |
|||
state = DecoderState.Size; |
|||
return true; |
|||
}; |
|||
|
|||
const readSize = () => { |
|||
const lasttag = stack.slice(-1)[0]; |
|||
if (ptr >= arr.byteLength) |
|||
return; |
|||
const size = readVint(arr, ptr); |
|||
if (!size) |
|||
return; |
|||
ptr += size.length; |
|||
total += size.length; |
|||
lasttag[5] = size?.value; |
|||
if (lasttag[5] == -1) |
|||
lasttag[3] = -1; |
|||
else |
|||
lasttag[3] += size.length + size.value; |
|||
state = DecoderState.Content; |
|||
return true; |
|||
}; |
|||
|
|||
const readContent = () => { |
|||
const lasttag = stack.slice(-1)[0]; |
|||
if (lasttag[1] == "m") { |
|||
state = DecoderState.Tag; |
|||
return true; |
|||
} |
|||
if (arr.byteLength < ptr + lasttag[5]!) |
|||
return; |
|||
const data = arr.slice(ptr, ptr + lasttag[5]!); |
|||
total += data.byteLength; |
|||
arr = arr.slice(ptr + lasttag[5]!); |
|||
ptr = 0; |
|||
state = DecoderState.Tag; |
|||
ret.push({ tag: lasttag, data }); |
|||
stack.pop(); |
|||
while (stack.length > 0) { |
|||
const top = stack.pop(); |
|||
if (!top) |
|||
break; |
|||
if (total < top[4] + top[3]) { |
|||
stack.push(top); |
|||
break; |
|||
} |
|||
ret.push({ tag: lasttag, data, isEnd: true }); |
|||
} |
|||
}; |
|||
|
|||
while (ptr < buffer.length) { |
|||
if (state == DecoderState.Tag) { |
|||
if (!readTag()) |
|||
break; |
|||
} else if (state == DecoderState.Size) { |
|||
if (!readSize()) |
|||
break; |
|||
} else if (state == DecoderState.Content) { |
|||
if (!readContent()) |
|||
break; |
|||
} |
|||
} |
|||
return ret; |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,4 @@ |
|||
import { |
|||
require_readable_browser |
|||
} from "./chunk-TZ2VUZSL.js"; |
|||
export default require_readable_browser(); |
Loading…
Reference in new issue