add lz77 decompression

This commit is contained in:
GEEKiDoS
2024-01-08 20:38:12 +08:00
parent b3899f3ae7
commit 66f4f891d6
3 changed files with 69 additions and 0 deletions
+2
View File
@@ -9,6 +9,7 @@ import { Logger } from "@cordisjs/logger";
import { crypto } from "./middlewares/crypto.js";
import { binaryBody } from "./middlewares/binarybody.js";
import { parseKxml } from "./middlewares/parseKxml.js";
import { decompress } from "./middlewares/decompress.js";
function tryResolve<T>(token: InjectionToken<T>): T | undefined {
if (!container.isRegistered(token))
@@ -33,6 +34,7 @@ async function main() {
const app = new Koa<DefaultState, ILaochanContext>()
.use(binaryBody)
.use(crypto)
.use(decompress)
.use(parseKxml)
.use(async (ctx, next) => {
if (typeof ctx.query.f !== 'string') {
+27
View File
@@ -0,0 +1,27 @@
import { Next } from "koa";
import { Context } from "../types.js";
import { lz77Decode } from "../utils/lz77.js";
export async function decompress(ctx: Context, next: Next) {
if (!(ctx.request.body instanceof Buffer)) {
return next();
}
if (typeof ctx.request.headers['x-compress'] !== 'string') {
return next();
}
// no compression for response
ctx.set('X-Compress', 'none');
if (ctx.request.headers['x-compress'] == 'none') {
return next();
}
if (ctx.request.headers['x-compress'] != 'lz77') {
throw new Error('unsupported compression mehotd');
}
ctx.request.body = lz77Decode(ctx.request.body);
return next();
}
+40
View File
@@ -0,0 +1,40 @@
export function lz77Decode(data: Buffer): Buffer {
let offset = 0;
const output: number[] = [];
while (offset < data.length) {
const flag = data[offset];
offset += 1;
for (let bit = 0; bit < 8; bit++) {
if (flag & (1 << bit)) {
output.push(data[offset]);
offset += 1;
} else {
if (offset >= data.length)
break;
const lookbackFlag = data.readUInt16BE(offset);
const lookbackLength = (lookbackFlag & 0x000f) + 3;
const lookbackOffset = lookbackFlag >> 4;
offset += 2;
if (lookbackFlag == 0)
break;
for (let i = 0; i < lookbackLength; i++) {
let loffset = output.length - lookbackOffset;
if (loffset <= 0 || loffset >= output.length) {
output.push(0);
} else {
output.push(output[loffset]);
}
}
}
}
}
return Buffer.from(output);
}