Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support CRX Package Format #118

Closed
silverwind opened this issue May 18, 2019 · 4 comments · Fixed by #119
Closed

Support CRX Package Format #118

silverwind opened this issue May 18, 2019 · 4 comments · Fixed by #119

Comments

@silverwind
Copy link

silverwind commented May 18, 2019

Chrome extensions in CRX format are zips but with a special header that makes them incompatible with unzipper. Attempting to extract a CRX file like this one results in a FILE_ENDED error.

Details on the format are here, would be great if support for this format could be added.

There is the unzip-crx module which handles the format, but I'm looking for something that can do in-memory extraction, like unzipper. I guess the function that strips this header could be easily ported to unzipper.

@ZJONSSON
Copy link
Owner

Providing support in the streaming version is easy, please see a quick implementation here: 48428ba

You can check it out by installing: npm install zjonsson/node-unzipper#crx

The Open methods would involve specifically opening up the start of the file to find out where the actual zip file starts and then adding this startOffset to all methods that read from the file. If you use an open method with a Buffer you can manually find out where the zip file starts and create a new buffer that contains only the zipfile

@silverwind
Copy link
Author

Thanks! I was specifically looking to use Open.buffer. Does that mean I have to manually find this startOffset when using Open? Can't it be detected there as well?

@ZJONSSON
Copy link
Owner

Yes absolutely. You could do something like:

// with `buffer` as the buffered data
var signature = buffer.readUInt32LE(0);
if (signature === 0x34327243) {
  const baseHeaderLength = 4*4;
  var h = binary.parse(buffer)
    .word32lu('signature')
    .word32lu('version')
    .word32lu('pubKeyLength')
    .word32lu('signatureLength')
    .vars;

  buffer = buffer.slice(baseHeaderLength +  h.pubKeyLength + h.signatureLength);
}
var directory = await unzipper.Open.buffer(buffer);

I added this check to the Open.buffer method on the crx branch b9bd05d

@ZJONSSON ZJONSSON mentioned this issue May 20, 2019
Merged
@silverwind
Copy link
Author

Awesome, can confirm it working:

const unzipper = require("unzipper");
const fetch = require("make-fetch-happen");

async function main() {
  const id = "hlepfoohegkhhmjieoechaddaejaokhf";
  const res = await fetch(`https://clients2.google.com/service/update2/crx?response=redirect&prodversion=74.0&x=id%3D${id}%26installsource%3Dondemand%26uc`);
  const buffer = await res.buffer();
  const dir = await unzipper.Open.buffer(buffer);
  console.log(dir.files.map(file => file.path));
}

main();

In case you're wondering about my use case: I'm pulling CSS files out of released chrome extensions, see here. Once your patch is released, I can drop two dependencies and do it all in-memory. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants