Skip to content

Commit

Permalink
Move some common type definitions into archive/common.js and some com…
Browse files Browse the repository at this point in the history
…ments.
  • Loading branch information
codedread committed Jan 21, 2024
1 parent 4fc0c3d commit 45fdedd
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 83 deletions.
29 changes: 27 additions & 2 deletions archive/common.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
/**
* common.js
*
* Provides common functionality for compressing and decompressing.
* Provides common definitions or functionality needed by multiple modules.
*
* Licensed under the MIT License
*
* Copyright(c) 2023 Google Inc.
*/

// Requires the following JavaScript features: MessageChannel, MessagePort, and dynamic imports.
/**
* @typedef FileInfo An object that is sent to the implementation representing a file to compress.
* @property {string} fileName The name of the file. TODO: Includes the path?
* @property {number} lastModTime The number of ms since the Unix epoch (1970-01-01 at midnight).
* @property {Uint8Array} fileData The bytes of the file.
*/

/**
* @typedef Implementation
Expand Down Expand Up @@ -51,3 +56,23 @@ export async function getConnectedPort(implFilename) {
});
});
}

// Zip-specific things.

export const LOCAL_FILE_HEADER_SIG = 0x04034b50;
export const CENTRAL_FILE_HEADER_SIG = 0x02014b50;
export const END_OF_CENTRAL_DIR_SIG = 0x06054b50;
export const CRC32_MAGIC_NUMBER = 0xedb88320;
export const ARCHIVE_EXTRA_DATA_SIG = 0x08064b50;
export const DIGITAL_SIGNATURE_SIG = 0x05054b50;
export const END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50;
export const DATA_DESCRIPTOR_SIG = 0x08074b50;

/**
* @readonly
* @enum {number}
*/
export const ZipCompressionMethod = {
STORE: 0, // Default.
DEFLATE: 8, // As per http://tools.ietf.org/html/rfc1951.
};
18 changes: 4 additions & 14 deletions archive/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Copyright(c) 2023 Google Inc.
*/

import { getConnectedPort } from './common.js';
import { ZipCompressionMethod, getConnectedPort } from './common.js';

// NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK!

Expand All @@ -19,15 +19,6 @@ import { getConnectedPort } from './common.js';
* @property {Uint8Array} fileData The bytes of the file.
*/

/**
* @readonly
* @enum {number}
*/
export const ZipCompressionMethod = {
STORE: 0, // Default.
// DEFLATE: 8,
};

// export const DeflateCompressionMethod = {
// NO_COMPRESSION: 0,
// COMPRESSION_FIXED_HUFFMAN: 1,
Expand All @@ -36,17 +27,15 @@ export const ZipCompressionMethod = {

/**
* Data elements are packed into bytes in order of increasing bit number within the byte,
i.e., starting with the least-significant bit of the byte.
* i.e., starting with the least-significant bit of the byte.
* Data elements other than Huffman codes are packed starting with the least-significant bit of the
data element.
* data element.
* Huffman codes are packed starting with the most-significant bit of the code.
*/

/**
* @typedef CompressorOptions
* @property {ZipCompressionMethod} zipCompressionMethod
* @property {DeflateCompressionMethod=} deflateCompressionMethod Only present if
* zipCompressionMethod is set to DEFLATE.
*/

/**
Expand Down Expand Up @@ -91,6 +80,7 @@ export class Zipper {
* @private
*/
this.zipCompressionMethod = options.zipCompressionMethod || ZipCompressionMethod.STORE;
if (this.zipCompressionMethod === ZipCompressionMethod.DEFLATE) throw `DEFLATE not supported.`;

/**
* @type {CompressStatus}
Expand Down
34 changes: 10 additions & 24 deletions archive/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export const UnarchiveEventType = {
ERROR: 'error'
};

/**
* An unarchive event.
*/
// TODO: Use CustomEvent and a @template and remove these boilerplate events.

/** An unarchive event. */
export class UnarchiveEvent extends Event {
/**
* @param {string} type The event type.
Expand All @@ -31,9 +31,7 @@ export class UnarchiveEvent extends Event {
}
}

/**
* Updates all Archiver listeners that an append has occurred.
*/
/** Updates all Unarchiver listeners that an append has occurred. */
export class UnarchiveAppendEvent extends UnarchiveEvent {
/**
* @param {number} numBytes The number of bytes appended.
Expand All @@ -49,9 +47,7 @@ export class UnarchiveAppendEvent extends UnarchiveEvent {
}
}

/**
* Useful for passing info up to the client (for debugging).
*/
/** Useful for passing info up to the client (for debugging). */
export class UnarchiveInfoEvent extends UnarchiveEvent {
/**
* @param {string} msg The info message.
Expand All @@ -67,9 +63,7 @@ export class UnarchiveInfoEvent extends UnarchiveEvent {
}
}

/**
* An unrecoverable error has occured.
*/
/** An unrecoverable error has occured. */
export class UnarchiveErrorEvent extends UnarchiveEvent {
/**
* @param {string} msg The error message.
Expand All @@ -85,18 +79,14 @@ export class UnarchiveErrorEvent extends UnarchiveEvent {
}
}

/**
* Start event.
*/
/** Start event. */
export class UnarchiveStartEvent extends UnarchiveEvent {
constructor() {
super(UnarchiveEventType.START);
}
}

/**
* Finish event.
*/
/** Finish event. */
export class UnarchiveFinishEvent extends UnarchiveEvent {
/**
* @param {Object} metadata A collection fo metadata about the archive file.
Expand All @@ -108,9 +98,7 @@ export class UnarchiveFinishEvent extends UnarchiveEvent {
}

// TODO(bitjs): Fully document these. They are confusing.
/**
* Progress event.
*/
/** Progress event. */
export class UnarchiveProgressEvent extends UnarchiveEvent {
/**
* @param {string} currentFilename
Expand All @@ -136,9 +124,7 @@ export class UnarchiveProgressEvent extends UnarchiveEvent {
}
}

/**
* Extract event.
*/
/** Extract event. */
export class UnarchiveExtractEvent extends UnarchiveEvent {
/**
* @param {UnarchivedFile} unarchivedFile
Expand Down
1 change: 1 addition & 0 deletions archive/unrar.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ let hostPort;

// State - consider putting these into a class.
let unarchiveState = UnarchiveState.NOT_STARTED;
/** @type {ByteStream} */
let bytestream = null;
let allLocalFiles = null;
let logToConsole = false;
Expand Down
1 change: 1 addition & 0 deletions archive/untar.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ let hostPort;

// State - consider putting these into a class.
let unarchiveState = UnarchiveState.NOT_STARTED;
/** @type {ByteStream} */
let bytestream = null;
let allLocalFiles = null;
let logToConsole = false;
Expand Down
36 changes: 15 additions & 21 deletions archive/unzip.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import { BitStream } from '../io/bitstream.js';
import { ByteBuffer } from '../io/bytebuffer.js';
import { ByteStream } from '../io/bytestream.js';
import { ARCHIVE_EXTRA_DATA_SIG, CENTRAL_FILE_HEADER_SIG, CRC32_MAGIC_NUMBER,
DATA_DESCRIPTOR_SIG, DIGITAL_SIGNATURE_SIG, END_OF_CENTRAL_DIR_SIG,
LOCAL_FILE_HEADER_SIG } from './common.js';

const UnarchiveState = {
NOT_STARTED: 0,
Expand All @@ -28,6 +31,7 @@ let hostPort;

// State - consider putting these into a class.
let unarchiveState = UnarchiveState.NOT_STARTED;
/** @type {ByteStream} */
let bytestream = null;
let allLocalFiles = null;
let logToConsole = false;
Expand Down Expand Up @@ -60,24 +64,14 @@ const postProgress = function () {
});
};

const zLocalFileHeaderSignature = 0x04034b50;
const zArchiveExtraDataSignature = 0x08064b50;
const zCentralFileHeaderSignature = 0x02014b50;
const zDigitalSignatureSignature = 0x05054b50;
const zEndOfCentralDirSignature = 0x06054b50;
const zEndOfCentralDirLocatorSignature = 0x07064b50;
const zDataDescriptorSignature = 0x08074b50;

// mask for getting the Nth bit (zero-based)
const BIT = [0x01, 0x02, 0x04, 0x08,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000];

class ZipLocalFile {
/**
* @param {ByteStream} bstream
*/
/** @param {ByteStream} bstream */
constructor(bstream) {
if (typeof bstream != typeof {} || !bstream.readNumber || typeof bstream.readNumber != typeof function () { }) {
return null;
Expand Down Expand Up @@ -125,9 +119,9 @@ class ZipLocalFile {
let foundDataDescriptor = false;
let numBytesSeeked = 0;
while (!foundDataDescriptor) {
while (bstream.peekNumber(4) !== zLocalFileHeaderSignature &&
bstream.peekNumber(4) !== zArchiveExtraDataSignature &&
bstream.peekNumber(4) !== zCentralFileHeaderSignature) {
while (bstream.peekNumber(4) !== LOCAL_FILE_HEADER_SIG &&
bstream.peekNumber(4) !== ARCHIVE_EXTRA_DATA_SIG &&
bstream.peekNumber(4) !== CENTRAL_FILE_HEADER_SIG) {
numBytesSeeked++;
bstream.readBytes(1);
}
Expand All @@ -143,7 +137,7 @@ class ZipLocalFile {

// From the PKZIP App Note: "The signature value 0x08074b50 is also used by some ZIP
// implementations as a marker for the Data Descriptor record".
if (maybeDescriptorSig === zDataDescriptorSignature) {
if (maybeDescriptorSig === DATA_DESCRIPTOR_SIG) {
if (maybeCompressedSize === (numBytesSeeked - 16)) {
foundDataDescriptor = true;
descriptorSize = 16;
Expand Down Expand Up @@ -606,7 +600,7 @@ function archiveUnzip() {
let bstream = bytestream.tee();

// loop until we don't see any more local files or we find a data descriptor.
while (bstream.peekNumber(4) == zLocalFileHeaderSignature) {
while (bstream.peekNumber(4) == LOCAL_FILE_HEADER_SIG) {
// Note that this could throw an error if the bstream overflows, which is caught in the
// message handler.
const oneLocalFile = new ZipLocalFile(bstream);
Expand Down Expand Up @@ -636,7 +630,7 @@ function archiveUnzip() {
totalFilesInArchive = allLocalFiles.length;

// archive extra data record
if (bstream.peekNumber(4) == zArchiveExtraDataSignature) {
if (bstream.peekNumber(4) == ARCHIVE_EXTRA_DATA_SIG) {
if (logToConsole) {
info(' Found an Archive Extra Data Signature');
}
Expand All @@ -649,13 +643,13 @@ function archiveUnzip() {

// central directory structure
// TODO: handle the rest of the structures (Zip64 stuff)
if (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
if (bstream.peekNumber(4) == CENTRAL_FILE_HEADER_SIG) {
if (logToConsole) {
info(' Found a Central File Header');
}

// read all file headers
while (bstream.peekNumber(4) == zCentralFileHeaderSignature) {
while (bstream.peekNumber(4) == CENTRAL_FILE_HEADER_SIG) {
bstream.readNumber(4); // signature
const cdfh = {
versionMadeBy: bstream.readNumber(2),
Expand Down Expand Up @@ -688,7 +682,7 @@ function archiveUnzip() {
}

// digital signature
if (bstream.peekNumber(4) == zDigitalSignatureSignature) {
if (bstream.peekNumber(4) == DIGITAL_SIGNATURE_SIG) {
if (logToConsole) {
info(' Found a Digital Signature');
}
Expand All @@ -699,7 +693,7 @@ function archiveUnzip() {
}

let metadata = {};
if (bstream.peekNumber(4) == zEndOfCentralDirSignature) {
if (bstream.peekNumber(4) == END_OF_CENTRAL_DIR_SIG) {
bstream.readNumber(4); // signature
const eocds = {
numberOfThisDisk: bstream.readNumber(2),
Expand Down
Loading

0 comments on commit 45fdedd

Please sign in to comment.