Skip to content

Commit

Permalink
Updated time resolution
Browse files Browse the repository at this point in the history
(Using a single uint32 intead of uint16 for date and uint16 for time)
Renamed FileEntry.lastModifiedFileTime to FileEntry.lastModified
  • Loading branch information
james-pre committed May 3, 2024
1 parent 97f3864 commit 9c05c42
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 39 deletions.
21 changes: 11 additions & 10 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import { decode } from '@zenfs/core/utils.js';
* Converts the input `time` and `date` in MS-DOS format into a `Date`.
*
* MS-DOS format:
* second 5 bits
* second 5 bits (2 second-precision)
* minute 6 bits
* hour 5 bits
* day (1-31) 5 bits
* month (1-23) 4 bits
* month (1-23) 4 bits (MSDOS indexes with 1)
* year (from 1980) 7 bits
* @hidden
*/
export function msdos2date(time: number, date: number): Date {
const day = date & 31;
const month = ((date >> 5) & 15) - 1;
const year = (date >> 9) + 1980;
const second = time & 31;
const minute = (time >> 5) & 63;
const hour = time >> 11;
return new Date(year, month, day, hour, minute, second);
export function msdosDate(datetime: number): Date {
return new Date(
((datetime >> 25) & 127) + 1980, // year
((datetime >> 21) & 15) - 1, // month
(datetime >> 16) & 31, // day
(datetime >> 11) & 31, // hour
(datetime >> 5) & 63, // minute
(datetime & 31) * 2 // second
);
}

/**
Expand Down
45 changes: 16 additions & 29 deletions src/zip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ApiError, ErrorCode } from '@zenfs/core/ApiError.js';
import { FileType, Stats } from '@zenfs/core/stats.js';
import { deserialize, sizeof, struct, types as t } from 'utilium';
import { CompressionMethod, decompressionMethods } from './compression.js';
import { msdos2date, safeDecode } from './utils.js';
import { msdosDate, safeDecode } from './utils.js';

/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.2.2
Expand Down Expand Up @@ -65,21 +65,15 @@ class LocalFileHeader {
/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
@t.uint16 protected _time: number;

/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
@t.uint16 protected _date: number;
@t.uint32 protected datetime: number;

/**
* The date and time are encoded in standard MS-DOS format.
* This getter decodes the date.
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
public get lastModified(): Date {
// Time and date is in MS-DOS format.
return msdos2date(this._time, this._date);
return msdosDate(this.datetime);
}

/**
Expand Down Expand Up @@ -133,7 +127,7 @@ class LocalFileHeader {
return this.data.slice(start, start + this.extraLength);
}

public get totalSize(): number {
public get size(): number {
return 30 + this.nameLength + this.extraLength;
}
public get useUTF8(): boolean {
Expand Down Expand Up @@ -234,21 +228,15 @@ class FileEntry {
/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
@t.uint16 protected _time: number;

/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
@t.uint16 protected _date: number;
@t.uint32 protected datetime: number;

/**
* The date and time are encoded in standard MS-DOS format.
* This getter decodes the date.
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.6
*/
public get lastModifiedFileTime(): Date {
// Time and date is in MS-DOS format.
return msdos2date(this._time, this._date);
public get lastModified(): Date {
return msdosDate(this.datetime);
}

/**
Expand Down Expand Up @@ -290,7 +278,7 @@ class FileEntry {
* The number of the disk on which this file begins.
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.13
*/
@t.uint16 public diskNumberStart: number;
@t.uint16 public startDisk: number;

/**
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.14
Expand All @@ -307,8 +295,8 @@ class FileEntry {
@t.uint32 public externalAttributes: number;

/**
* This is the offset from the start of the first disk on which this file appears,
* to where the local header should be found.
* This is the offset from the start of the first disk on which
* this file appears to where the local header should be found.
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.4.16
*/
@t.uint32 public headerRelativeOffset: number;
Expand Down Expand Up @@ -378,15 +366,14 @@ class FileEntry {
* @see http://pkware.com/documents/casestudies/APPNOTE.TXT#:~:text=4.3.8
*/
public get data(): Uint8Array {
// Need to grab the local header before we can figure out where the actual compressed data starts.
const header = new LocalFileHeader(this.zipData.slice(this.headerRelativeOffset));
const data = this.zipData.slice(this.headerRelativeOffset + header.totalSize);
// Get the local header before we can figure out where the actual compressed data starts.
const { compressionMethod, size, name } = new LocalFileHeader(this.zipData.slice(this.headerRelativeOffset));
const data = this.zipData.slice(this.headerRelativeOffset + size);
// Check the compression
const { compressionMethod } = header;
const decompress = decompressionMethods[compressionMethod];
if (typeof decompress != 'function') {
const name: string = compressionMethod in CompressionMethod ? CompressionMethod[compressionMethod] : compressionMethod.toString();
throw new ApiError(ErrorCode.EINVAL, `Invalid compression method on file '${header.name}': ${name}`);
const mname: string = compressionMethod in CompressionMethod ? CompressionMethod[compressionMethod] : compressionMethod.toString();
throw new ApiError(ErrorCode.EINVAL, `Invalid compression method on file '${name}': ${mname}`);
}
return decompress(data, this.compressedSize, this.uncompressedSize, this.flag);
}
Expand All @@ -395,7 +382,7 @@ class FileEntry {
return new Stats({
mode: 0o555 | FileType.FILE,
size: this.uncompressedSize,
mtimeMs: this.lastModifiedFileTime.getTime(),
mtimeMs: this.lastModified.getTime(),
});
}
}
Expand Down

0 comments on commit 9c05c42

Please sign in to comment.