Skip to content

Instantly share code, notes, and snippets.

@xyb
Last active January 11, 2022 04:07
Show Gist options
  • Save xyb/bebbcd214268fc28a208afc834ade6ed to your computer and use it in GitHub Desktop.
Save xyb/bebbcd214268fc28a208afc834ade6ed to your computer and use it in GitHub Desktop.
Convert CRX to zip file
# Convert CRX to zip file.
# Inspired by https://github.com/peerigon/unzip-crx/blob/master/src/index.js
# nim c -d:release --gc:none --stackTrace:off --lineTrace:off --opt:size uncrx.nim
import system
import os
import streams
import strutils
const
zipMagicNumber = "PK\x03\x04"
crxMagicNumber = "Cr24"
proc skipCrxHeader(stream: FileStream) =
let magicNumber = stream.peekStr(4)
if magicNumber == zipMagicNumber:
return
if magicNumber != crxMagicNumber:
raise newException(ValueError,
"Invalid header: Does not start with Cr24")
discard stream.readStr(4)
let version = stream.readStr(4)
var zip_start_offset: uint32
if version == "\2\0\0\0":
let
public_key_length = stream.readUInt32()
signature_length = stream.readUInt32()
zip_start_offset = 16 + public_key_length + signatureLength
elif version == "\3\0\0\0":
let
header_size = stream.readUInt32()
zip_start_offset = 12 + header_size
else:
raise newException(ValueError,
"Unexpected crx format version number.")
stream.setPosition(int(zip_start_offset))
proc crx2zip() =
proc usage() =
echo "Save or print zip content of a CRX (Chrome Extension) file"
echo ""
echo "Usage:"
echo " crx2zip <crx_filename> [<zip_filename> | -]"
quit()
var args = commandLineParams()
if len(args) == 0:
usage()
let crxFile = args[0]
let destFilename =
if len(args) > 1:
args[1]
else:
if len(crxFile) >= 4 and toLowerAscii(crxFile)[^4 .. ^1] == ".crx":
crxFile[0 .. ^5] & ".zip"
else:
crxFile & ".zip"
if not fileExists(crxFile):
echo "file not found"
quit(1)
var crx = newFileStream(crxFile, fmRead)
var destFile =
if destFilename == "-":
newFileStream(stdout)
else:
newFileStream(destFilename, fmWrite)
try:
skipCrxHeader(crx)
except ValueError as ex:
echo ex.msg
quit(2)
const bufferSize = 1024
var buffer: string
buffer.setLen(bufferSize)
while true:
let readBytes = crx.readDataStr(buffer, 0..<bufferSize)
if readBytes == 0:
break
destFile.write(buffer[0..readBytes-1])
when isMainModule:
crx2zip()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment