@equicord/unzip-crx
Version:
unzip chrome extension files (*.crx)
69 lines (68 loc) • 2.19 kB
JavaScript
// src/index.ts
import fs from "fs/promises";
import path from "path";
import jszip from "jszip";
function mkdirp(path2) {
return fs.mkdir(path2, { recursive: true });
}
function crxToZip(buf) {
function calcLength(a, b, c, d) {
let length = 0;
length += a << 0;
length += b << 8;
length += c << 16;
length += d << 24 >>> 0;
return length;
}
if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4) {
return buf;
}
if (buf[0] !== 67 || buf[1] !== 114 || buf[2] !== 50 || buf[3] !== 52) {
throw new Error("Invalid header: Does not start with Cr24");
}
const isV3 = buf[4] === 3;
const isV2 = buf[4] === 2;
if (!isV2 && !isV3 || buf[5] || buf[6] || buf[7]) {
throw new Error("Unexpected crx format version number.");
}
if (isV2) {
const publicKeyLength = calcLength(buf[8], buf[9], buf[10], buf[11]);
const signatureLength = calcLength(buf[12], buf[13], buf[14], buf[15]);
const zipStartOffset2 = 16 + publicKeyLength + signatureLength;
return buf.slice(zipStartOffset2, buf.length);
}
const headerSize = calcLength(buf[8], buf[9], buf[10], buf[11]);
const zipStartOffset = 12 + headerSize;
return buf.slice(zipStartOffset, buf.length);
}
async function unzip(crxFilePath, destination) {
const filePath = path.resolve(crxFilePath);
let dest;
if (destination) {
dest = destination;
} else {
const extname = path.extname(crxFilePath);
const basename = path.basename(crxFilePath, extname);
const dirname = path.dirname(crxFilePath);
dest = path.resolve(dirname, basename);
}
const buf = await fs.readFile(filePath);
const { files } = await jszip.loadAsync(crxToZip(buf));
return Promise.all(
Object.keys(files).map(async (filename) => {
const isFile = !files[filename].dir;
const fullPath = path.join(dest, filename);
const directory = isFile && path.dirname(fullPath) || fullPath;
await mkdirp(directory);
if (isFile) {
const content = await files[filename].async("nodebuffer");
await fs.writeFile(fullPath, content);
}
})
);
}
var src_default = unzip;
export {
src_default as default,
unzip
};