From 66f4f891d63557b6900068189d0a6ecdc35bdd02 Mon Sep 17 00:00:00 2001 From: GEEKiDoS Date: Mon, 8 Jan 2024 20:38:12 +0800 Subject: [PATCH] add lz77 decompression --- src/main.ts | 2 ++ src/middlewares/decompress.ts | 27 +++++++++++++++++++++++ src/utils/lz77.ts | 40 +++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 src/utils/lz77.ts diff --git a/src/main.ts b/src/main.ts index bc6d1f0..db052fe 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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(token: InjectionToken): T | undefined { if (!container.isRegistered(token)) @@ -33,6 +34,7 @@ async function main() { const app = new Koa() .use(binaryBody) .use(crypto) + .use(decompress) .use(parseKxml) .use(async (ctx, next) => { if (typeof ctx.query.f !== 'string') { diff --git a/src/middlewares/decompress.ts b/src/middlewares/decompress.ts index e69de29..58f2aa9 100644 --- a/src/middlewares/decompress.ts +++ b/src/middlewares/decompress.ts @@ -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(); +} diff --git a/src/utils/lz77.ts b/src/utils/lz77.ts new file mode 100644 index 0000000..5d8b8c6 --- /dev/null +++ b/src/utils/lz77.ts @@ -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); +}