main funcions fixes

This commit is contained in:
2025-09-29 22:06:11 +09:00
parent 40e016e128
commit c8c3274527
7995 changed files with 1517998 additions and 1057 deletions

126
desktop-operator/node_modules/resedit/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,126 @@
# Changelog
## v1.7.2
- Same update for [v2.0.3](https://github.com/jet2jet/resedit-js/releases/tag/v2.0.3)
- Fix icon item image size to ignore biImageSize when biCompression is BI_RGB (#56)
## v1.7.1
- Same update for [v2.0.1](https://github.com/jet2jet/resedit-js/releases/tag/v2.0.1):
- Add nullish check for some fields
- Add demo page link to README
- Same update for [v2.0.2](https://github.com/jet2jet/resedit-js/releases/tag/v2.0.2):
- Update pe-library
## v1.7.0
- Add support for ES module loading in Node.js environment
- Update pe-library
## v1.6.1
- Fix width byte calculation (#30)
## v1.6.0
- Update pe-library
## v1.5.0
- Update pe-library
## v1.4.1
- Remove more unused functions/files
## v1.4.0
- resedit now uses [pe-library](https://www.npmjs.com/package/pe-library) to parsing/generating PE binaries
- `ResEdit.NtExecutable` and some classes are now aliases of pe-library's classes.
## v1.3.0
- Add `signData` method to `SignerObject`
## v1.2.0
- Add 'setFileVersion' and 'setProductVersion' methods to VersionInfo (#23)
## v1.1.0
- Add options to generateResourceData/outputResource (#21)
## v1.0.0
- Add `sizeImage` on `BitmapInfo` to keep original values
- Change icon mask to be non-null data
- Add BigInt support for `ImageOptionalHeader64`
- Add `getResourceEntriesAsString`, `replaceResourceEntryFromString`, and `removeResourceEntry` methods in `NtExecutableResource`
- Drop Node.js v10
## v0.7.0
- Add `NtExecutable.createEmpty` which creates 'empty' executable data
- Add ESM (ES Module) support
- Fix some minor bugs
## v0.6.0
- Add support for extra data, which is not a part of any sections, on parsing/generating executables
- Add `alignment` parameter for `generateExecutableWithSign`
## v0.5.2
- Add predefined digest algorithms and support OIDs for `getDigestAlgorithm` and `getEncryptionAlgorithm`
- Fix calculating executable digest for binaries which previously contained signed information
## v0.5.1
- Rename `getPublicKeyData` to `getCertificateData`
- `getPublicKeyData` can still be used now, but will be no longer called in the future.
- Re-export types used by `SignerObject`
## v0.5.0
- Improve usability for some classes, such as `VersionInfo` and `IconGroupEntry`
- Update descriptions for some types / methods
- Add support for multiple certificates on `SignerObject.getPublicKeyData`
## v0.4.0
- Added signing process function (#14), which enables to generate signed executable binaries
- Additionally, signed executables are now supported on `NtExecutable.from` with explicit option. (On `NtExecutable.generate` signed information will be lost.)
- Support for `ArrayBufferView` as an input data for some methods (e.g. `NtExecutable.from` and `IconFile.from`)
- TypedArray (e.g. `Uint8Array`), `DataView`, and Node.js `Buffer` class are subclasses of `ArrayBufferView`, so these classes now can be used as input data directly.
## v0.3.1
- Added missing string table rounding up for `VersionInfo` (#13, thanks to @AlexanderOMara)
## v0.3.0
- Throw error if specified executable binary is signed (#10)
- Implemented PE checksum calculation (#8, thanks to @AlexanderOMara)
- (Internal change) Updated package dependencies for developments
- TypeScript version is updated to 3.7.x, so the type definitions might be incompatible for older version of TypeScript (especially <3.4.x)
## v0.2.2
- Fix width and height usage for icon group, especially when loading from an icon file (#5)
## v0.2.1
- Fix the build paths to match package.json file (#3, thanks to @AlexanderOMara)
## v0.2.0
- Fix some bugs as followings:
- Fix adding new section entry to executable
- Fix changing section addresses on replacement
- Fix parsing icon resource data and icon file data
- Add `is32bit` method for `NtExecutable` and `removeAllStrings` method for `VersionInfo`
## v0.1.0
- Initial version

21
desktop-operator/node_modules/resedit/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 jet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

127
desktop-operator/node_modules/resedit/README.md generated vendored Normal file
View File

@@ -0,0 +1,127 @@
[![NPM version](https://badge.fury.io/js/resedit.svg)](https://www.npmjs.com/package/resedit)
[![Build Status](https://github.com/jet2jet/resedit-js/actions/workflows/main-ci.yml/badge.svg)](https://github.com/jet2jet/resedit-js)
# resedit-js
resedit-js is a library that manipulates resouces contained by Windows Executable files. All implementations are written in JavaScript (TypeScript), so there are no further restrictions for running environment.
This library is not tested well for modifying and/or signing executables yet. Please be careful with the emitted binaries.
To use in command line, consider using [resedit-js-cli](https://www.npmjs.com/package/resedit-cli).
The demo page: [resedit demo](https://www.pg-fl.jp/program/resedit/index.en.htm)
- [Install](#install)
- [Supported formats](#supported-formats)
- [Parsing signed executables](#parsing-signed-executables)
- [Signing executables with resedit-js](#signing-executables-with-resedit-js)
- [Notes](#notes)
- [Examples](#examples)
- [License](#license)
## Install
```
npm install resedit
```
## Supported formats
- Windows Executables (PE Format, such as `.exe` and `.dll`), both 32-bit and 64-bit, are supported.
- Executables for 16-bit Windows is not supported.
- `.res` file is not supported now.
- PNG-based icon data is supported on `require('resedit').Resource.IconGroupEntry` class.
## Parsing signed executables
- Parsing signed executables (by using Authenticode or etc.) is not allowed by default and an exception will be thrown if `NtExecutable.from` receives a signed binary.
- To parse signed, `{ ignoreCert: true }` object must be passed to the second argument of `NtExecutable.from`.
- Although the base executable data is signed, `NtExecutable.generate` will generate unsigned executable binary. If you want to re-sign it, you must use generate-function with signing (see below) or any other signing tool such as Microsoft `signtool`.
## Signing executables with resedit-js
resedit-js provides basic signing process `generateExecutableWithSign` function, which is based on [Authenticode specification](https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/authenticode_pe.docx) and related RFCs.
To keep resedit-js generic library, the followings are required to use signing process.
- Encryption / calculating hash (digest) process (e.g. Node.js built-in `crypto` module)
- A private key data is implicitly required to encrypt data.
- DER-format certificate binary (such as `*.cer` file data or `*.p7b` file data with DER-format), which is paired with the private key used by encryption process.
- (optional) Generating timestamp data, especially communicating with TSA server (e.g. HTTP/HTTPS API)
These requirements are represented as [`SignerObject`](./src/main/sign/SignerObject.ts). The caller of `generateExecutableWithSign` function must implement this object to sign executables.
An example code is here: [signTest.js](./examples/sign/signTest.js)
Note that resedit-js only provides basic signing process, and provides as beta version. For example adding more attributes/informations to certificates are not supported now.
> Some digest algorithms, such as SHA3 algorithms, might not be supported by current Windows.
## Notes
- **It is not strongly recommended that the destination executable file is equal to the source executable file (which is not an intermediate data).**
## Examples
For more APIs, please see `dist` directory of the package. And, [some test codes](./src/test) may help you for usages.
```js
import * as PELibrary from 'pe-library';
import * as ResEdit from 'resedit';
import * as fs from 'fs';
// load and parse data
const data = fs.readFileSync('MyApp.exe');
// (the Node.js Buffer instance can be specified directly to NtExecutable.from)
const exe = PELibrary.NtExecutable.from(data);
const res = PELibrary.NtExecutableResource.from(exe);
// rewrite resources
// - You can use helper classes as followings:
// - ResEdit.Resource.IconGroupEntry: access icon resource data
// - ResEdit.Resource.StringTable: access string resource data
// - ResEdit.Resource.VersionInfo: access version info data
// -- replace icons
// load icon data from file
// (you can use ResEdit.Data.IconFile to parse icon data)
const iconFile = ResEdit.Data.IconFile.from(fs.readFileSync('MyIcon.ico'));
ResEdit.Resource.IconGroupEntry.replaceIconsForResource(
// destEntries
res.entries,
// iconGroupID
101,
// lang ('lang: 1033' means 'en-US')
1033,
// icons (map IconFileItem to IconItem/RawIconItem)
iconFile.icons.map((item) => item.data)
);
// -- replace version
const viList = ResEdit.Resource.VersionInfo.fromEntries(res.entries);
const vi = viList[0];
// setFileVersion will set `vi.fixedInfo.fileVersionMS`/`fileVersionLS` and 'FileVersion' string value
// ('1033' means 'en-US')
vi.setFileVersion(1, 0, 0, 0, 1033);
// ('lang: 1033' means 'en-US', 'codepage: 1200' is the default codepage)
vi.setStringValues(
{ lang: 1033, codepage: 1200 },
{
FileDescription: 'My application',
ProductName: 'My product',
}
);
vi.outputToResourceEntries(res.entries);
// write to another binary
res.outputResource(exe);
const newBinary = exe.generate();
fs.writeFileSync('MyApp_modified.exe', Buffer.from(newBinary));
```
## License
[MIT License](./LICENSE)

View File

@@ -0,0 +1,17 @@
export default interface BitmapInfo {
width: number;
height: number;
planes: number;
bitCount: number;
compression: number;
sizeImage: number;
xPelsPerMeter: number;
yPelsPerMeter: number;
colorUsed: number;
colorImportant: number;
colors: Array<{
r: number;
g: number;
b: number;
}>;
}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,21 @@
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
/**
* All fields except for 'data' is optional.
* Missing fields are replaced by 'data' values when generating binary.
*/
export interface IconFileItem {
width?: number;
height?: number;
colors?: number;
planes?: number;
bitCount?: number;
data: IconItem | RawIconItem;
}
export default class IconFile {
/** Containing icons */
icons: IconFileItem[];
constructor();
static from(bin: ArrayBuffer | ArrayBufferView): IconFile;
generate(): ArrayBuffer;
}

View File

@@ -0,0 +1,141 @@
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
import { readUint8WithLastOffset, readUint16WithLastOffset, readUint32WithLastOffset, copyBuffer, createDataView, } from '../util/functions.js';
function generateEntryBinary(icons) {
var count = icons.length;
/* istanbul ignore if */
if (count > 65535) {
count = 65535;
}
var tmpIcons = icons.map(function (item) {
if (item.data.isIcon()) {
return {
item: item,
bin: item.data.generate(),
offset: 0,
};
}
else {
return {
item: item,
bin: item.data.bin,
offset: 0,
};
}
});
var size = tmpIcons.reduce(function (p, icon) {
icon.offset = p;
return p + icon.bin.byteLength;
}, 6 + 16 * count);
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, 0, true); // reserved
view.setUint16(2, 1, true); // icon type
view.setUint16(4, count, true);
var offset = 6;
tmpIcons.forEach(function (icon) {
var item = icon.item;
var width;
var height;
var colors;
var planes;
var bitCount;
if (item.data.isIcon()) {
var bi = item.data.bitmapInfo;
width =
typeof item.width !== 'undefined'
? item.width
: Math.abs(bi.width);
height =
typeof item.height !== 'undefined'
? item.height
: Math.abs(bi.height / 2);
colors =
typeof item.colors !== 'undefined'
? item.colors
: bi.colorUsed || bi.colors.length;
planes =
typeof item.planes !== 'undefined' ? item.planes : bi.planes;
bitCount =
typeof item.bitCount !== 'undefined'
? item.bitCount
: bi.bitCount;
}
else {
width =
typeof item.width !== 'undefined'
? item.width
: Math.abs(item.data.width);
height =
typeof item.height !== 'undefined'
? item.height
: Math.abs(item.data.height);
colors = typeof item.colors !== 'undefined' ? item.colors : 0;
planes = typeof item.planes !== 'undefined' ? item.planes : 1;
bitCount =
typeof item.bitCount !== 'undefined'
? item.bitCount
: item.data.bitCount;
}
var dataSize = icon.bin.byteLength;
view.setUint8(offset, width >= 256 ? 0 : width);
view.setUint8(offset + 1, height >= 256 ? 0 : height);
view.setUint8(offset + 2, colors >= 256 ? 0 : colors);
view.setUint8(offset + 3, 0);
view.setUint16(offset + 4, planes, true);
view.setUint16(offset + 6, bitCount, true);
view.setUint32(offset + 8, dataSize, true);
view.setUint32(offset + 12, icon.offset, true);
offset += 16;
copyBuffer(bin, icon.offset, icon.bin, 0, dataSize);
});
return bin;
}
var IconFile = /** @class */ (function () {
function IconFile(bin) {
if (!bin) {
this.icons = [];
return;
}
var view = createDataView(bin);
var totalSize = view.byteLength;
var icons = [];
/* istanbul ignore else */
if (view.getUint16(2, true) === 1) {
var count = view.getUint16(4, true);
var offset = 6;
for (var i = 0; i < count; ++i) {
var dataSize = readUint32WithLastOffset(view, offset + 8, totalSize);
var dataOffset = readUint32WithLastOffset(view, offset + 12, totalSize);
var width = readUint8WithLastOffset(view, offset, totalSize);
var height = readUint8WithLastOffset(view, offset + 1, totalSize);
var bitCount = readUint8WithLastOffset(view, offset + 6, totalSize);
var data = void 0;
if (view.getUint32(dataOffset, true) === 0x28) {
data = IconItem.from(width, height, bin, dataOffset, dataSize);
}
else {
data = RawIconItem.from(bin, width || 256, height || 256, bitCount, dataOffset, dataSize);
}
icons.push({
width: width,
height: height,
colors: readUint8WithLastOffset(view, offset + 2, totalSize),
planes: readUint16WithLastOffset(view, offset + 4, totalSize),
bitCount: bitCount,
data: data,
});
offset += 16;
}
}
this.icons = icons;
}
IconFile.from = function (bin) {
return new IconFile(bin);
};
IconFile.prototype.generate = function () {
return generateEntryBinary(this.icons);
};
return IconFile;
}());
export default IconFile;

View File

@@ -0,0 +1,58 @@
import BitmapInfo from './BitmapInfo.js';
export default class IconItem {
/**
* Bitmap header data (`BITMAPINFOHEADER`)
*/
readonly bitmapInfo: BitmapInfo;
/**
* Horizontal size of the icon in pixel (overrides `bitmapInfo.width`).
* If `null` is specified, `bitmapInfo.width` will be used.
*/
width: number | null;
/**
* Vertical size of the icon in pixel (overrides `bitmapInfo.height`).
* If `null` is specified, `bitmapInfo.height` will be used.
*/
height: number | null;
/**
* Bitmap pixel data used for mask
* (the data will be appended immediately after `pixels` when generating icon binary)
*/
masks: ArrayBuffer;
/**
* Bitmap pixel data
*/
private _pixels;
private constructor();
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
get pixels(): ArrayBuffer;
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
set pixels(newValue: ArrayBuffer);
/**
* Generates `IconItem` instance from bitmap data binary.
* @param bin binary data containing the bitmap data
* @param byteOffset byte offset of `bin` referring the bitmap data
* @param byteLength available byte length for `bin` (from the offset `byteOffset`)
*/
static from(bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): IconItem;
/**
* Generates `IconItem` instance from bitmap data binary width actual icon size (width and height).
* @param width icon width
* @param height icon height
* @param bin binary data containing the bitmap data
* @param byteOffset byte offset of `bin` referring the bitmap data
* @param byteLength available byte length for `bin` (from the offset `byteOffset`)
*/
static from(width: number, height: number, bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): IconItem;
isIcon(): this is IconItem;
isRaw(): false;
generate(): ArrayBuffer;
}

View File

@@ -0,0 +1,164 @@
import { allocatePartialBinary, copyBuffer, createDataView, readInt32WithLastOffset, readUint8WithLastOffset, readUint16WithLastOffset, readUint32WithLastOffset, roundUp, } from '../util/functions.js';
function calcMaskSize(width, height) {
// round up to 4 bytes (32 bit)
// (mask pixels is 1-bit bitmap)
var actualWidthBytes = roundUp(Math.abs(width), 32) / 8;
return actualWidthBytes * Math.abs(height);
}
var IconItem = /** @class */ (function () {
function IconItem(width, height, bin, byteOffset, byteLength) {
var view = createDataView(bin, byteOffset, byteLength);
var totalSize = view.byteLength;
var headerSize = view.getUint32(0, true);
if (headerSize > totalSize) {
headerSize = totalSize;
}
var sizeImage = readUint32WithLastOffset(view, 20, headerSize);
var bi = {
width: readInt32WithLastOffset(view, 4, headerSize),
height: readInt32WithLastOffset(view, 8, headerSize),
planes: readUint16WithLastOffset(view, 12, headerSize),
bitCount: readUint16WithLastOffset(view, 14, headerSize),
compression: readUint32WithLastOffset(view, 16, headerSize),
sizeImage: sizeImage,
xPelsPerMeter: readInt32WithLastOffset(view, 24, headerSize),
yPelsPerMeter: readInt32WithLastOffset(view, 28, headerSize),
colorUsed: readUint32WithLastOffset(view, 32, headerSize),
colorImportant: readUint32WithLastOffset(view, 36, headerSize),
colors: [],
};
var offset = 40;
var colors = bi.colorUsed;
if (!colors) {
switch (bi.bitCount) {
case 1:
colors = 2;
break;
case 4:
colors = 16;
break;
case 8:
colors = 256;
break;
}
}
for (var i = 0; i < colors; ++i) {
bi.colors.push({
b: readUint8WithLastOffset(view, offset, totalSize),
g: readUint8WithLastOffset(view, offset + 1, totalSize),
r: readUint8WithLastOffset(view, offset + 2, totalSize),
});
offset += 4;
}
this.width = width;
this.height = height;
this.bitmapInfo = bi;
// round up to 4 bytes (32 bit)
var widthBytes = roundUp(bi.bitCount * Math.abs(bi.width), 32) / 8;
var absActualHeight = Math.abs(bi.height) / 2;
// sizeImage may be weird if compression is 0 (BI_RGB), so
// we calculate actual bitmap size from width and height
var size = bi.compression !== 0 && sizeImage !== 0
? sizeImage
: widthBytes * absActualHeight;
if (size + offset > totalSize) {
throw new Error("Unexpected bitmap data in icon: bitmap size " + size + " is larger than " + totalSize + " - " + offset);
}
this._pixels = allocatePartialBinary(view, offset, size);
offset += size;
var maskSize = calcMaskSize(bi.width, absActualHeight);
if (maskSize + offset <= totalSize) {
this.masks = allocatePartialBinary(view, offset, maskSize);
}
else {
// create a zero buffer (no mask is not allowed)
this.masks = new ArrayBuffer(maskSize);
}
}
Object.defineProperty(IconItem.prototype, "pixels", {
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
get: function () {
return this._pixels;
},
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
set: function (newValue) {
this._pixels = newValue;
if (this.bitmapInfo.sizeImage !== 0) {
this.bitmapInfo.sizeImage = newValue.byteLength;
}
},
enumerable: false,
configurable: true
});
IconItem.from = function (arg1, arg2, arg3, byteOffset, byteLength) {
var width;
var height;
var bin;
if (typeof arg3 === 'object') {
// second overload
width = arg1;
height = arg2;
bin = arg3;
}
else {
// first overload
width = null;
height = null;
bin = arg1;
byteOffset = arg2;
byteLength = arg3;
}
return new IconItem(width, height, bin, byteOffset, byteLength);
};
IconItem.prototype.isIcon = function () {
return true;
};
IconItem.prototype.isRaw = function () {
return false;
};
IconItem.prototype.generate = function () {
var bi = this.bitmapInfo;
var absWidth = Math.abs(bi.width);
// round up to 4 bytes (32 bit)
var absWidthBytes = roundUp(bi.bitCount * absWidth, 32) / 8;
var absActualHeight = Math.abs(bi.height) / 2;
var actualSizeImage = absWidthBytes * absActualHeight;
var sizeMask = calcMaskSize(bi.width, absActualHeight);
var colorCount = bi.colors.length;
var totalSize = 40 + 4 * colorCount + actualSizeImage + sizeMask;
var bin = new ArrayBuffer(totalSize);
var view = new DataView(bin);
view.setUint32(0, 40, true);
view.setInt32(4, bi.width, true);
view.setInt32(8, bi.height, true);
view.setUint16(12, bi.planes, true);
view.setUint16(14, bi.bitCount, true);
view.setUint32(16, bi.compression, true);
// image size
view.setUint32(20, bi.sizeImage, true);
view.setInt32(24, bi.xPelsPerMeter, true);
view.setInt32(28, bi.yPelsPerMeter, true);
view.setUint32(32, bi.colorUsed, true);
view.setUint32(36, bi.colorImportant > colorCount ? colorCount : bi.colorImportant, true);
var offset = 40;
bi.colors.forEach(function (c) {
view.setUint8(offset, c.b);
view.setUint8(offset + 1, c.g);
view.setUint8(offset + 2, c.r);
offset += 4;
});
copyBuffer(bin, offset, this.pixels, 0, actualSizeImage);
copyBuffer(bin, offset + actualSizeImage, this.masks, 0, sizeMask);
return bin;
};
return IconItem;
}());
export default IconItem;

View File

@@ -0,0 +1,13 @@
/**
* Represents the raw-graphic icon item, such as PNG data.
*/
export default class RawIconItem {
width: number;
height: number;
bitCount: number;
bin: ArrayBuffer;
constructor(bin: ArrayBuffer | ArrayBufferView, width: number, height: number, bitCount: number, byteOffset?: number, byteLength?: number);
static from(bin: ArrayBuffer | ArrayBufferView, width: number, height: number, bitCount: number, byteOffset?: number, byteLength?: number): RawIconItem;
isIcon(): false;
isRaw(): this is RawIconItem;
}

View File

@@ -0,0 +1,30 @@
import { allocatePartialBinary } from '../util/functions.js';
/**
* Represents the raw-graphic icon item, such as PNG data.
*/
var RawIconItem = /** @class */ (function () {
function RawIconItem(bin, width, height, bitCount, byteOffset, byteLength) {
this.width = width;
this.height = height;
this.bitCount = bitCount;
if (typeof byteOffset !== 'number') {
byteOffset = 0;
byteLength = bin.byteLength;
}
else if (typeof byteLength !== 'number') {
byteLength = bin.byteLength - byteOffset;
}
this.bin = allocatePartialBinary(bin, byteOffset, byteLength);
}
RawIconItem.from = function (bin, width, height, bitCount, byteOffset, byteLength) {
return new RawIconItem(bin, width, height, bitCount, byteOffset, byteLength);
};
RawIconItem.prototype.isIcon = function () {
return false;
};
RawIconItem.prototype.isRaw = function () {
return true;
};
return RawIconItem;
}());
export default RawIconItem;

View File

@@ -0,0 +1,5 @@
import BitmapInfo from './BitmapInfo.js';
import IconFile, { IconFileItem } from './IconFile.js';
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
export { BitmapInfo, IconFile, IconFileItem, IconItem, RawIconItem };

View File

@@ -0,0 +1,4 @@
import IconFile from './IconFile.js';
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
export { IconFile, IconItem, RawIconItem };

View File

@@ -0,0 +1,6 @@
import { NtExecutable, NtExecutableResource, Format } from 'pe-library';
import version from './version.js';
import * as Data from './data/index.js';
import * as Resource from './resource/index.js';
import { generateExecutableWithSign, SignerObject, DigestAlgorithmType, EncryptionAlgorithmType } from './sign/index.js';
export { NtExecutable, NtExecutableResource, version, Data, Format, Resource, generateExecutableWithSign, SignerObject, DigestAlgorithmType, EncryptionAlgorithmType, };

View File

@@ -0,0 +1,6 @@
import { NtExecutable, NtExecutableResource, Format } from 'pe-library';
import version from './version.js';
import * as Data from './data/index.js';
import * as Resource from './resource/index.js';
import { generateExecutableWithSign, } from './sign/index.js';
export { NtExecutable, NtExecutableResource, version, Data, Format, Resource, generateExecutableWithSign, };

View File

@@ -0,0 +1,45 @@
import { Type } from 'pe-library';
import IconItem from '../data/IconItem.js';
import RawIconItem from '../data/RawIconItem.js';
export interface IconGroupItem {
width: number;
height: number;
colors: number;
planes: number;
bitCount: number;
dataSize: number;
iconID: number;
}
/**
* A class that treats icon-group resource data (`RT_ICON_GROUP`).
* Note that this class does not treat `RT_ICON` data.
*
* - To pick all icons, use `IconGroupEntry.fromEntries`
* and `IconGroupEntry.prototype.getIconItemsFromEntries`.
* - The easiest way to add/replace icons is using `IconGroupEntry.replaceIconsForResource`,
* which treats both `RT_ICON_GROUP` and `RT_ICON` entries.
*/
export default class IconGroupEntry {
id: string | number;
lang: string | number;
readonly icons: IconGroupItem[];
private constructor();
static fromEntries(entries: readonly Type.ResourceEntry[]): IconGroupEntry[];
generateEntry(): Type.ResourceEntry;
/**
* Return an array of `IconItem` / `RawIconItem`, which are in the group of this `IconGroupEntry` instance,
* from specified resource entries.
*/
getIconItemsFromEntries(entries: readonly Type.ResourceEntry[]): Array<IconItem | RawIconItem>;
/**
* Add or replace icon resource entries with specified icon data.
* The IDs of individual icon resources (`RT_ICON`) are calculated automatically.
* @param destEntries base (destination) resource entries.
* @param iconGroupID the icon ID for the new resource data.
* If the icon-group resource of the ID and 'lang' value already exists,
* the resource data is replaced; otherwise the resource data is appended.
* @param lang the language for specified icons (0 for neutral, 0x409 for en-US)
* @param icons the icons to replace
*/
static replaceIconsForResource(destEntries: Type.ResourceEntry[], iconGroupID: string | number, lang: string | number, icons: Array<IconItem | RawIconItem>): void;
}

View File

@@ -0,0 +1,292 @@
import IconItem from '../data/IconItem.js';
import RawIconItem from '../data/RawIconItem.js';
import { readUint8WithLastOffset, readUint16WithLastOffset, readUint32WithLastOffset, } from '../util/functions.js';
function generateEntryBinary(icons) {
var count = icons.length;
if (count > 65535) {
count = 65535;
}
var size = 6 + 14 * icons.length;
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, 0, true); // reserved
view.setUint16(2, 1, true); // icon type
view.setUint16(4, count, true);
var offset = 6;
icons.forEach(function (icon) {
view.setUint8(offset, icon.width >= 256 ? 0 : icon.width);
view.setUint8(offset + 1, icon.height >= 256 ? 0 : icon.height);
view.setUint8(offset + 2, icon.colors >= 256 ? 0 : icon.colors);
view.setUint8(offset + 3, 0);
view.setUint16(offset + 4, icon.planes, true);
view.setUint16(offset + 6, icon.bitCount, true);
view.setUint32(offset + 8, icon.dataSize, true);
view.setUint16(offset + 12, icon.iconID, true);
offset += 14;
});
return bin;
}
function findUnusedIconID(entries, lang, isCursor) {
var type = isCursor ? 1 : 3;
// (ignore string id)
var filteredIDs = entries
.filter(function (e) { return e.type === type && e.lang === lang && typeof e.id === 'number'; })
.map(function (e) { return e.id; })
.sort(function (a, b) { return a - b; });
var idCurrent = 1;
for (var _i = 0, filteredIDs_1 = filteredIDs; _i < filteredIDs_1.length; _i++) {
var id = filteredIDs_1[_i];
if (idCurrent < id) {
return {
id: idCurrent,
last: false,
};
}
else if (idCurrent === id) {
++idCurrent;
}
}
return {
id: idCurrent,
last: true,
};
}
/**
* A class that treats icon-group resource data (`RT_ICON_GROUP`).
* Note that this class does not treat `RT_ICON` data.
*
* - To pick all icons, use `IconGroupEntry.fromEntries`
* and `IconGroupEntry.prototype.getIconItemsFromEntries`.
* - The easiest way to add/replace icons is using `IconGroupEntry.replaceIconsForResource`,
* which treats both `RT_ICON_GROUP` and `RT_ICON` entries.
*/
var IconGroupEntry = /** @class */ (function () {
function IconGroupEntry(groupEntry) {
var view = new DataView(groupEntry.bin);
var totalSize = view.byteLength;
var icons = [];
if (view.getUint16(2, true) === 1) {
var count = view.getUint16(4, true);
var offset = 6;
for (var i = 0; i < count; ++i) {
icons.push({
width: readUint8WithLastOffset(view, offset, totalSize),
height: readUint8WithLastOffset(view, offset + 1, totalSize),
colors: readUint8WithLastOffset(view, offset + 2, totalSize),
planes: readUint16WithLastOffset(view, offset + 4, totalSize),
bitCount: readUint16WithLastOffset(view, offset + 6, totalSize),
dataSize: readUint32WithLastOffset(view, offset + 8, totalSize),
iconID: readUint16WithLastOffset(view, offset + 12, totalSize),
});
offset += 14; // 16 for .ico file, but 14 for resource data
}
}
this.id = groupEntry.id;
this.lang = groupEntry.lang;
this.icons = icons;
}
IconGroupEntry.fromEntries = function (entries) {
return entries
.filter(function (e) { return e.type === 14; })
.map(function (e) { return new IconGroupEntry(e); });
};
IconGroupEntry.prototype.generateEntry = function () {
var bin = generateEntryBinary(this.icons);
return {
type: 14,
id: this.id,
lang: this.lang,
codepage: 0,
bin: bin,
};
};
/**
* Return an array of `IconItem` / `RawIconItem`, which are in the group of this `IconGroupEntry` instance,
* from specified resource entries.
*/
IconGroupEntry.prototype.getIconItemsFromEntries = function (entries) {
var _this = this;
return entries
.map(function (e) {
if (e.type !== 3 || e.lang !== _this.lang) {
return null;
}
var c = _this.icons
.filter(function (icon) { return e.id === icon.iconID; })
.shift();
if (!c) {
return null;
}
return {
entry: e,
icon: c,
};
})
.filter(function (item) { return !!item; })
.map(function (item) {
var bin = item.entry.bin;
var view = new DataView(bin);
if (view.getUint32(0, true) === 0x28) {
return IconItem.from(bin);
}
else {
var c = item.icon;
return RawIconItem.from(bin, c.width, c.height, c.bitCount);
}
});
};
/**
* Add or replace icon resource entries with specified icon data.
* The IDs of individual icon resources (`RT_ICON`) are calculated automatically.
* @param destEntries base (destination) resource entries.
* @param iconGroupID the icon ID for the new resource data.
* If the icon-group resource of the ID and 'lang' value already exists,
* the resource data is replaced; otherwise the resource data is appended.
* @param lang the language for specified icons (0 for neutral, 0x409 for en-US)
* @param icons the icons to replace
*/
IconGroupEntry.replaceIconsForResource = function (destEntries, iconGroupID, lang, icons) {
// find existing entry
var entry = destEntries
.filter(function (e) { return e.type === 14 && e.id === iconGroupID && e.lang === lang; })
.shift();
var tmpIconArray = icons.map(function (icon) {
if (icon.isIcon()) {
var width = icon.width, height = icon.height;
if (width === null) {
width = icon.bitmapInfo.width;
}
if (height === null) {
height = icon.bitmapInfo.height;
// if mask is specified, the icon height must be the half of bitmap height
if (icon.masks !== null) {
height = Math.floor(height / 2);
}
}
return {
base: icon,
bm: {
width: width,
height: height,
planes: icon.bitmapInfo.planes,
bitCount: icon.bitmapInfo.bitCount,
},
bin: icon.generate(),
id: 0,
};
}
else {
return {
base: icon,
bm: {
width: icon.width,
height: icon.height,
planes: 1,
bitCount: icon.bitCount,
},
bin: icon.bin,
id: 0,
};
}
});
if (entry) {
// remove unused icon data
for (var i = destEntries.length - 1; i >= 0; --i) {
var e = destEntries[i];
if (e != null && e.type === 3) {
// RT_ICON
if (!isIconUsed(e, destEntries, entry)) {
destEntries.splice(i, 1);
}
}
}
}
else {
// create new entry
entry = {
type: 14,
id: iconGroupID,
lang: lang,
codepage: 0,
// set later
bin: null,
};
destEntries.push(entry);
}
// append icons
var idInfo;
tmpIconArray.forEach(function (icon) {
if (!(idInfo === null || idInfo === void 0 ? void 0 : idInfo.last)) {
idInfo = findUnusedIconID(destEntries, lang, false);
}
else {
++idInfo.id;
}
destEntries.push({
type: 3,
id: idInfo.id,
lang: lang,
codepage: 0,
bin: icon.bin,
});
// set 'id' field to use in generateEntryBinary
icon.id = idInfo.id;
});
var binEntry = generateEntryBinary(tmpIconArray.map(function (icon) {
var width = Math.abs(icon.bm.width);
if (width >= 256) {
width = 0;
}
var height = Math.abs(icon.bm.height);
if (height >= 256) {
height = 0;
}
var colors = 0;
if (icon.base.isIcon()) {
var bmBase = icon.base.bitmapInfo;
colors = bmBase.colorUsed || bmBase.colors.length;
if (!colors) {
switch (bmBase.bitCount) {
case 1:
colors = 2;
break;
case 4:
colors = 16;
break;
// case 8:
// colors = 256;
// break;
}
}
if (colors >= 256) {
colors = 0;
}
}
return {
width: width,
height: height,
colors: colors,
planes: icon.bm.planes,
bitCount: icon.bm.bitCount,
dataSize: icon.bin.byteLength,
iconID: icon.id,
};
}));
// rewrite entry
entry.bin = binEntry;
function isIconUsed(icon, allEntries, excludeGroup) {
return allEntries.some(function (e) {
if (e.type !== 14 ||
(e.id === excludeGroup.id && e.lang === excludeGroup.lang)) {
return false;
}
var g = new IconGroupEntry(e);
return g.icons.some(function (c) {
return c.iconID === icon.id;
});
});
}
};
return IconGroupEntry;
}());
export default IconGroupEntry;

View File

@@ -0,0 +1,30 @@
import { NtExecutableResource, Type } from 'pe-library';
/** Utility class to create / parse String Table resource */
export default class StringTable {
/** Language value */
lang: string | number;
private items;
constructor();
/** Create StringTable instance from resource entries, with specified language. */
static fromEntries(lang: string | number, entries: readonly Type.ResourceEntry[]): StringTable;
/** Return all string entries. */
getAllStrings(): Array<{
id: number;
text: string;
}>;
/** Return the string data for ID value, which can be used for Win32API LoadString. */
getById(id: number): string | null;
/**
* Set/overwide the string data for ID value, which can be used for Win32API LoadString.
* @param id data ID
* @param text string data (entry will be removed if null or empty string is specified)
*/
setById(id: number, text: string | null): void;
/** Generates an array of Entry for resource processings */
generateEntries(): Type.ResourceEntry[];
/**
* Replace all string entries for NtExecutableResource with containing resource data.
* The only entries of same language are replaced.
*/
replaceStringEntriesForExecutable(res: NtExecutableResource): void;
}

View File

@@ -0,0 +1,130 @@
import StringTableItem from './StringTableItem.js';
/** Utility class to create / parse String Table resource */
var StringTable = /** @class */ (function () {
function StringTable() {
this.lang = 0;
this.items = [];
}
/** Create StringTable instance from resource entries, with specified language. */
StringTable.fromEntries = function (lang, entries) {
var r = new StringTable();
entries.forEach(function (e) {
// 6: RT_STRING
if (e.type !== 6 ||
e.lang !== lang ||
typeof e.id !== 'number' ||
e.id <= 0) {
return;
}
r.items[e.id - 1] = StringTableItem.fromEntry(e.bin, 0, e.bin.byteLength);
});
r.lang = lang;
return r;
};
/** Return all string entries. */
StringTable.prototype.getAllStrings = function () {
return this.items
.map(function (e, i) {
return e
.getAll()
.map(function (x, j) {
return x !== null && x !== ''
? { id: (i << 4) + j, text: x }
: null;
})
.filter(function (x) { return !!x; });
})
.reduce(function (p, c) { return p.concat(c); }, []);
};
/** Return the string data for ID value, which can be used for Win32API LoadString. */
StringTable.prototype.getById = function (id) {
var _a;
if (id < 0) {
return null;
}
var entryIndex = id >> 4;
var entryPos = id & 15;
var e = this.items[entryIndex];
return (_a = e === null || e === void 0 ? void 0 : e.get(entryPos)) !== null && _a !== void 0 ? _a : null;
};
/**
* Set/overwide the string data for ID value, which can be used for Win32API LoadString.
* @param id data ID
* @param text string data (entry will be removed if null or empty string is specified)
*/
StringTable.prototype.setById = function (id, text) {
if (id < 0) {
return;
}
var entryIndex = id >> 4;
var entryPos = id & 15;
var e = this.items[entryIndex];
if (!e) {
this.items[entryIndex] = e = new StringTableItem();
}
e.set(entryPos, text);
};
/** Generates an array of Entry for resource processings */
StringTable.prototype.generateEntries = function () {
var _this = this;
return this.items
.map(function (e, i) {
var len = e.calcByteLength();
var bin = new ArrayBuffer(len);
e.generate(bin, 0);
return {
type: 6,
id: i + 1,
lang: _this.lang,
codepage: 1200,
bin: bin,
};
})
.filter(function (e) { return !!e; });
};
/**
* Replace all string entries for NtExecutableResource with containing resource data.
* The only entries of same language are replaced.
*/
StringTable.prototype.replaceStringEntriesForExecutable = function (res) {
var entries = this.generateEntries();
var dest = res.entries;
// first try -- replace same type and same language
for (var i = 0; i < dest.length; ++i) {
var e = dest[i];
if (e != null && e.type === 6 && e.lang === this.lang) {
for (var j = dest.length - 1; j >= i; --j) {
var e2 = dest[j];
if (e2 != null && e2.type === 6 && e2.lang === this.lang) {
dest.splice(j, 1);
}
}
var f = dest.splice.bind(dest, i, 0);
f.apply(void 0, entries);
return;
}
}
// second try -- add entries next to previous language
for (var i = 0; i < dest.length; ++i) {
var e = dest[i];
if (e != null && e.type === 6 && e.lang < this.lang) {
var f = dest.splice.bind(dest, i + 1, 0);
f.apply(void 0, entries);
return;
}
}
// third try -- add entries next to the last 'String' entry
for (var i = dest.length - 1; i >= 0; --i) {
var e = dest[i];
if (e != null && e.type === 6) {
var f = dest.splice.bind(dest, i + 1, 0);
f.apply(void 0, entries);
return;
}
}
// otherwise -- add entries to the last
dest.push.apply(dest, entries);
};
return StringTable;
}());
export default StringTable;

View File

@@ -0,0 +1,11 @@
export default class StringTableItem {
readonly length = 16;
private _a;
constructor();
static fromEntry(bin: ArrayBuffer, offset: number, byteLength: number): StringTableItem;
get(index: number): string | null;
getAll(): Array<string | null>;
set(index: number, val: string | null): void;
calcByteLength(): number;
generate(bin: ArrayBuffer, offset: number): number;
}

View File

@@ -0,0 +1,71 @@
// StringTable entry:
// 16-times of {<WORD length> [<UTF-16 string>]}
var StringTableItem = /** @class */ (function () {
function StringTableItem() {
this.length = 16;
this._a = [];
this._a.length = 16;
for (var i = 0; i < 16; ++i) {
this._a[i] = '';
}
}
StringTableItem.fromEntry = function (bin, offset, byteLength) {
var view = new DataView(bin, offset, byteLength);
var ret = new StringTableItem();
var o = 0;
for (var i = 0; i < 16; ++i) {
var len = view.getUint16(o, true);
o += 2;
var s = '';
for (var j = 0; j < len; ++j) {
s += String.fromCharCode(view.getUint16(o, true));
o += 2;
}
ret._a[i] = s;
}
return ret;
};
StringTableItem.prototype.get = function (index) {
var value = this._a[index];
return value != null && value !== '' ? value : null;
};
StringTableItem.prototype.getAll = function () {
return this._a.map(function (s) { return s || null; });
};
StringTableItem.prototype.set = function (index, val) {
this._a[index] = ("" + (val !== null && val !== void 0 ? val : '')).substr(0, 4097); // length must be no longer than 4097
};
StringTableItem.prototype.calcByteLength = function () {
var len = 0;
for (var i = 0; i < 16; ++i) {
var item = this._a[i];
len += 2;
if (item != null) {
len += 2 * item.length; // UTF-16 length
}
}
// 16 alignment
return Math.floor((len + 15) / 16) * 16;
};
StringTableItem.prototype.generate = function (bin, offset) {
var out = new DataView(bin, offset);
var len = 0;
for (var i = 0; i < 16; ++i) {
var s = this._a[i];
var l = s == null ? 0 : s.length > 4097 ? 4097 : s.length;
out.setUint16(len, l, true);
len += 2;
if (s != null) {
for (var j = 0; j < l; ++j) {
// output as UTF-16
out.setUint16(len, s.charCodeAt(j), true);
len += 2;
}
}
}
// 16 alignment
return Math.floor((len + 15) / 16) * 16;
};
return StringTableItem;
}());
export default StringTableItem;

View File

@@ -0,0 +1,13 @@
/**
* Flag values used by VersionEntry.fixedInfo field.
* Zero or more enum values are stored (with OR operator).
*/
declare enum VersionFileFlags {
Debug = 1,
Prerelease = 2,
Patched = 4,
PrivateBuild = 8,
InfoInferred = 16,
SpecialBuild = 32
}
export default VersionFileFlags;

View File

@@ -0,0 +1,14 @@
/**
* Flag values used by VersionEntry.fixedInfo field.
* Zero or more enum values are stored (with OR operator).
*/
var VersionFileFlags;
(function (VersionFileFlags) {
VersionFileFlags[VersionFileFlags["Debug"] = 1] = "Debug";
VersionFileFlags[VersionFileFlags["Prerelease"] = 2] = "Prerelease";
VersionFileFlags[VersionFileFlags["Patched"] = 4] = "Patched";
VersionFileFlags[VersionFileFlags["PrivateBuild"] = 8] = "PrivateBuild";
VersionFileFlags[VersionFileFlags["InfoInferred"] = 16] = "InfoInferred";
VersionFileFlags[VersionFileFlags["SpecialBuild"] = 32] = "SpecialBuild";
})(VersionFileFlags || (VersionFileFlags = {}));
export default VersionFileFlags;

View File

@@ -0,0 +1,20 @@
/**
* OS values used by VersionEntry.fixedInfo field.
*/
declare enum VersionFileOS {
Unknown = 0,
_Windows16 = 1,
_PM16 = 2,
_PM32 = 3,
_Windows32 = 4,
DOS = 65536,
OS2_16 = 131072,
OS2_32 = 196608,
NT = 262144,
DOS_Windows16 = 65537,
DOS_Windows32 = 65540,
NT_Windows32 = 262148,
OS2_16_PM16 = 131074,
OS2_32_PM32 = 196611
}
export default VersionFileOS;

View File

@@ -0,0 +1,21 @@
/**
* OS values used by VersionEntry.fixedInfo field.
*/
var VersionFileOS;
(function (VersionFileOS) {
VersionFileOS[VersionFileOS["Unknown"] = 0] = "Unknown";
VersionFileOS[VersionFileOS["_Windows16"] = 1] = "_Windows16";
VersionFileOS[VersionFileOS["_PM16"] = 2] = "_PM16";
VersionFileOS[VersionFileOS["_PM32"] = 3] = "_PM32";
VersionFileOS[VersionFileOS["_Windows32"] = 4] = "_Windows32";
VersionFileOS[VersionFileOS["DOS"] = 65536] = "DOS";
VersionFileOS[VersionFileOS["OS2_16"] = 131072] = "OS2_16";
VersionFileOS[VersionFileOS["OS2_32"] = 196608] = "OS2_32";
VersionFileOS[VersionFileOS["NT"] = 262144] = "NT";
VersionFileOS[VersionFileOS["DOS_Windows16"] = 65537] = "DOS_Windows16";
VersionFileOS[VersionFileOS["DOS_Windows32"] = 65540] = "DOS_Windows32";
VersionFileOS[VersionFileOS["NT_Windows32"] = 262148] = "NT_Windows32";
VersionFileOS[VersionFileOS["OS2_16_PM16"] = 131074] = "OS2_16_PM16";
VersionFileOS[VersionFileOS["OS2_32_PM32"] = 196611] = "OS2_32_PM32";
})(VersionFileOS || (VersionFileOS = {}));
export default VersionFileOS;

View File

@@ -0,0 +1,20 @@
export declare enum VersionFileDriverSubtype {
Unknown = 0,
Printer = 1,
Keyboard = 2,
Language = 3,
Display = 4,
Mouse = 5,
Network = 6,
System = 7,
Installable = 8,
Sound = 9,
Comm = 10,
VersionedPrinter = 12
}
export declare enum VersionFileFontSubtype {
Unknown = 0,
Raster = 1,
Vector = 2,
TrueType = 3
}

View File

@@ -0,0 +1,22 @@
export var VersionFileDriverSubtype;
(function (VersionFileDriverSubtype) {
VersionFileDriverSubtype[VersionFileDriverSubtype["Unknown"] = 0] = "Unknown";
VersionFileDriverSubtype[VersionFileDriverSubtype["Printer"] = 1] = "Printer";
VersionFileDriverSubtype[VersionFileDriverSubtype["Keyboard"] = 2] = "Keyboard";
VersionFileDriverSubtype[VersionFileDriverSubtype["Language"] = 3] = "Language";
VersionFileDriverSubtype[VersionFileDriverSubtype["Display"] = 4] = "Display";
VersionFileDriverSubtype[VersionFileDriverSubtype["Mouse"] = 5] = "Mouse";
VersionFileDriverSubtype[VersionFileDriverSubtype["Network"] = 6] = "Network";
VersionFileDriverSubtype[VersionFileDriverSubtype["System"] = 7] = "System";
VersionFileDriverSubtype[VersionFileDriverSubtype["Installable"] = 8] = "Installable";
VersionFileDriverSubtype[VersionFileDriverSubtype["Sound"] = 9] = "Sound";
VersionFileDriverSubtype[VersionFileDriverSubtype["Comm"] = 10] = "Comm";
VersionFileDriverSubtype[VersionFileDriverSubtype["VersionedPrinter"] = 12] = "VersionedPrinter";
})(VersionFileDriverSubtype || (VersionFileDriverSubtype = {}));
export var VersionFileFontSubtype;
(function (VersionFileFontSubtype) {
VersionFileFontSubtype[VersionFileFontSubtype["Unknown"] = 0] = "Unknown";
VersionFileFontSubtype[VersionFileFontSubtype["Raster"] = 1] = "Raster";
VersionFileFontSubtype[VersionFileFontSubtype["Vector"] = 2] = "Vector";
VersionFileFontSubtype[VersionFileFontSubtype["TrueType"] = 3] = "TrueType";
})(VersionFileFontSubtype || (VersionFileFontSubtype = {}));

View File

@@ -0,0 +1,13 @@
/**
* File type values used by VersionEntry.fixedInfo field.
*/
declare enum VersionFileType {
Unknown = 0,
App = 1,
DLL = 2,
Driver = 3,
Font = 4,
VxD = 5,
StaticLibrary = 7
}
export default VersionFileType;

View File

@@ -0,0 +1,14 @@
/**
* File type values used by VersionEntry.fixedInfo field.
*/
var VersionFileType;
(function (VersionFileType) {
VersionFileType[VersionFileType["Unknown"] = 0] = "Unknown";
VersionFileType[VersionFileType["App"] = 1] = "App";
VersionFileType[VersionFileType["DLL"] = 2] = "DLL";
VersionFileType[VersionFileType["Driver"] = 3] = "Driver";
VersionFileType[VersionFileType["Font"] = 4] = "Font";
VersionFileType[VersionFileType["VxD"] = 5] = "VxD";
VersionFileType[VersionFileType["StaticLibrary"] = 7] = "StaticLibrary";
})(VersionFileType || (VersionFileType = {}));
export default VersionFileType;

View File

@@ -0,0 +1,197 @@
import { Type } from 'pe-library';
/**
* String values for the version information.
* In most cases predefined names are used for the key names (such as 'FileDescription', 'FileVersion', etc.)
* Note that the key names are case-sensitive; this library does not convert keys
* (e.g. `'fileVersion'` --> `'FileVersion'`).
*/
export declare type VersionStringValues = Record<string, string>;
/** Used by `VersionInfo.create` */
export interface VersionStringTable {
lang: number;
codepage: number;
/** Any string values */
values: VersionStringValues;
}
/** Translation information, containing LANGID and codepage value. */
export interface VersionTranslation {
lang: number;
/** Almost all cases are set to 1200 (Unicode) */
codepage: number;
}
/** Fixed version info, containing file version, product version, etc. (`VS_FIXEDFILEINFO`) */
export interface VersionFixedInfo {
/** usually major version in HIWORD(fileVersionMS), minor version in LOWORD(fileVersionMS) */
fileVersionMS: number;
/** usually patch version in HIWORD(fileVersionLS), revision in LOWORD(fileVersionLS) */
fileVersionLS: number;
productVersionMS: number;
productVersionLS: number;
/** valid values of fileFlags */
fileFlagsMask: number;
/** zero or more VersionFileFlags values, masked by fileFlagsMask */
fileFlags: number;
/** VersionFileOS value */
fileOS: number;
/** VersionFileType value */
fileType: number;
/**
* subtype values depended on fileType, such as
* `VersionFileDriverSubtype` or `VersionFileFontSubtype`.
* (if no suitable value, zero is stored)
*/
fileSubtype: number;
fileDateMS: number;
fileDateLS: number;
}
export interface VersionInfoCreateParam {
lang: string | number;
/** This field can be as a partial object; default values (zero) are used for all unspecified field. */
fixedInfo: Partial<Readonly<VersionFixedInfo>>;
strings: readonly VersionStringTable[];
}
/**
* Treats 'Version information' (`VS_VERSIONINFO`) resource data.
*/
export default class VersionInfo {
private readonly data;
private constructor();
/** Returns new `VersionInfo` instance with empty data. */
static createEmpty(): VersionInfo;
/**
* Returns new `VersionInfo` instance with specified parameters.
* `fixedInfo` can be specified as a partial object;
* default values (zero) are used for all unspecified field.
*/
static create(lang: string | number, fixedInfo: Partial<Readonly<VersionFixedInfo>>, strings: readonly VersionStringTable[]): VersionInfo;
/** Returns new `VersionInfo` instance with specified parameters. */
static create(param: Readonly<VersionInfoCreateParam>): VersionInfo;
/** Pick up all version-info entries */
static fromEntries(entries: readonly Type.ResourceEntry[]): VersionInfo[];
/** A language value for this resource entry. */
get lang(): string | number;
set lang(value: string | number);
/**
* The property of fixed version info, containing file version, product version, etc.
* (data: `VS_FIXEDFILEINFO`)
*
* Although this property is read-only, you can rewrite
* each child fields directly to apply data.
*/
get fixedInfo(): VersionFixedInfo;
/**
* Returns all languages that the executable supports. (data: `VarFileInfo`)
*
* Usually the returned array is equal to the one returned by `getAllLanguagesForStringValues`,
* but some resource-generating tools doesn't generate same values.
*/
getAvailableLanguages(): VersionTranslation[];
/**
* Replaces all languages that the executable supports.
*/
replaceAvailableLanguages(languages: readonly VersionTranslation[]): void;
/**
* Returns all string values for the specified language. (data: values in lang-charset block of `StringFileInfo`)
*/
getStringValues(language: VersionTranslation): VersionStringValues;
/**
* Returns all languages used by string values. (data: lang-charset name of `StringFileInfo`)
*
* Usually the returned array is equal to the one returned by `getAvailableLanguages`,
* but some resource-generating tools doesn't generate same values.
*/
getAllLanguagesForStringValues(): VersionTranslation[];
/**
* Add or replace the string values.
* @param language language info
* @param values string values (key-value pairs)
* @param addToAvailableLanguage set `true` to add `language` into available languages
* if not existing in `getAvailableLanguages()` (default: `true`)
*/
setStringValues(language: VersionTranslation, values: VersionStringValues, addToAvailableLanguage?: boolean): void;
/**
* Add or replace the string value.
* @param language language info
* @param key the key name of string value
* @param value the string value
* @param addToAvailableLanguage set `true` to add `language` into available languages
* if not existing in `getAvailableLanguages()` (default: `true`)
*/
setStringValue(language: VersionTranslation, key: string, value: string, addToAvailableLanguage?: boolean): void;
/**
* Remove all string values for specified language.
* @param language language info
* @param removeFromAvailableLanguage set `true` to remove `language` from available languages
* if existing in `getAvailableLanguages()` (default: `true`)
*/
removeAllStringValues(language: VersionTranslation, removeFromAvailableLanguage?: boolean): void;
/**
* Remove specified string value for specified language.
* @param language language info
* @param key the key name of string value to be removed
* @param removeFromAvailableLanguage set `true` to remove `language` from available languages
* if no more string values exist for `language` (default: `true`)
*/
removeStringValue(language: VersionTranslation, key: string, removeFromAvailableLanguage?: boolean): void;
/**
* Creates `Type.ResourceEntry` object for this instance.
* Usually `outputToResourceEntries` is suitable for generating resource data
* into executables, but you can use this method if necessary.
*/
generateResource(): Type.ResourceEntry;
/**
* Generates version info resource data (using `generateResource()`) and emits into `entries` array.
* If version info resource already exists in `entries`, this method replaces it with the new one.
* @param entries resource entry array for output
*/
outputToResourceEntries(entries: Type.ResourceEntry[]): void;
private getDefaultVersionLang;
/**
* Sets 'FileVersion' property with specified values.
* This methods writes `fixedInfo.fileVersionMS` and `fixedInfo.fileVersionLS` fields,
* and writes `FileVersion` string with the value `<major>.<minor>.<micro>.<revision>`.
* @param major The major version (clamped between 0 and 65535)
* @param minor The minor version (clamped between 0 and 65535)
* @param micro The micro version (clamped between 0 and 65535; default is 0)
* @param revision The revision value (clamped between 0 and 65535; default is 0)
* @param lang The language (default: this.lang -> picked from existings -> 1033)
* @note
* If you want to use 'Neutral' language for the version string, specify `lang` parameter to 0 explicitly
*/
setFileVersion(major: number, minor: number, micro?: number, revision?: number, lang?: number): void;
/**
* Sets 'FileVersion' property with specified values.
* This methods writes `fixedInfo.fileVersionMS` and `fixedInfo.fileVersionLS` fields,
* and writes `FileVersion` string with the value `<major>.<minor>.<micro>.<revision>`.
* @param version The version string value (should be `x.x.x.x` format; each integer clamped between 0 and 65535)
* @param lang The language (default: this.lang -> picked from existings -> 1033)
* @note
* If you want to use 'Neutral' language for the version string, specify `lang` parameter to 0 explicitly
*/
setFileVersion(version: string, lang?: number): void;
private setFileVersionImpl;
/**
* Sets 'ProductVersion' property with specified values.
* This methods writes `fixedInfo.productVersionMS` and `fixedInfo.productVersionLS` fields,
* and writes `ProductVersion` string with the value `<major>.<minor>.<micro>.<revision>`.
* @param major The major version (clamped between 0 and 65535)
* @param minor The minor version (clamped between 0 and 65535)
* @param micro The micro version (clamped between 0 and 65535; default is 0)
* @param revision The revision value (clamped between 0 and 65535; default is 0)
* @param lang The language (default: this.lang -> picked from existings -> 1033)
* @note
* If you want to use 'Neutral' language for the version string, specify `lang` parameter to 0 explicitly
*/
setProductVersion(major: number, minor: number, micro?: number, revision?: number, lang?: number): void;
/**
* Sets 'ProductVersion' property with specified values.
* This methods writes `fixedInfo.productVersionMS` and `fixedInfo.productVersionLS` fields,
* and writes `ProductVersion` string with the value `<major>.<minor>.<micro>.<revision>`.
* @param version The version string value (should be `x.x.x.x` format; each integer clamped between 0 and 65535)
* @param lang The language (default: this.lang -> picked from existings -> 1033)
* @note
* If you want to use 'Neutral' language for the version string, specify `lang` parameter to 0 explicitly
*/
setProductVersion(version: string, lang?: number): void;
private setProductVersionImpl;
}

View File

@@ -0,0 +1,739 @@
import { allocatePartialBinary, cloneObject, copyBuffer, readUint32WithLastOffset, roundUp, } from '../util/functions.js';
function readStringToNullChar(view, offset, last) {
var r = '';
while (offset + 2 <= last) {
var c = view.getUint16(offset, true);
if (!c) {
break;
}
r += String.fromCharCode(c);
offset += 2;
}
return r;
}
function writeStringWithNullChar(view, offset, value) {
for (var i = 0; i < value.length; ++i) {
view.setUint16(offset, value.charCodeAt(i), true);
offset += 2;
}
view.setUint16(offset, 0, true);
return offset + 2;
}
function createFixedInfo() {
return {
fileVersionMS: 0,
fileVersionLS: 0,
productVersionMS: 0,
productVersionLS: 0,
fileFlagsMask: 0,
fileFlags: 0,
fileOS: 0,
fileType: 0,
fileSubtype: 0,
fileDateMS: 0,
fileDateLS: 0,
};
}
////////////////////////////////////////////////////////////////////////////////
// parsings
// returns offset and structure
function parseStringTable(view, offset, last) {
var tableLen = view.getUint16(offset, true);
var valueLen = view.getUint16(offset + 2, true);
if (offset + tableLen < last) {
last = offset + tableLen;
}
// value type check is not needed; because no value is needed
var tableName = readStringToNullChar(view, offset + 6, last);
offset += roundUp(6 + 2 * (tableName.length + 1), 4);
var langAndCp = parseInt(tableName, 16);
if (isNaN(langAndCp)) {
throw new Error('Invalid StringTable data format');
}
// this should be zero
offset += roundUp(valueLen, 4);
var r = {
lang: Math.floor(langAndCp / 0x10000),
codepage: langAndCp & 0xffff,
values: {},
};
while (offset < last) {
// String structure
var childDataLen = view.getUint16(offset, true);
var childValueLen = view.getUint16(offset + 2, true);
// value type must be string; if not, skip it
if (view.getUint16(offset + 4, true) !== 1) {
offset += childDataLen;
continue;
}
var childDataLast = offset + childDataLen;
if (childDataLast > last) {
childDataLast = last;
}
var name_1 = readStringToNullChar(view, offset + 6, childDataLast);
offset = roundUp(offset + 6 + 2 * (name_1.length + 1), 4);
var childValueLast = offset + childValueLen * 2;
if (childValueLast > childDataLast) {
childValueLast = childDataLast;
}
var value = readStringToNullChar(view, offset, childValueLast);
offset = roundUp(childValueLast, 4);
r.values[name_1] = value;
}
// return 'last' instead of 'offset'
return [last, r];
}
function parseStringFileInfo(view, offset, last) {
var valueLen = view.getUint16(offset + 2, true);
// value type check is not needed; because no value is needed
offset += 36; // roundUp(6 + ByteLenWithNull(L'StringFileInfo'), 4)
// this should be zero
offset += roundUp(valueLen, 4);
var r = [];
var _loop_1 = function () {
// StringTable structure
var childData = parseStringTable(view, offset, last);
var table = childData[1];
var a = r.filter(function (e) { return e.lang === table.lang && e.codepage === table.codepage; });
if (a.length === 0) {
r.push(table);
}
else {
// merge values
for (var key in table.values) {
var value = table.values[key];
if (value != null) {
a[0].values[key] = value;
}
}
}
offset = roundUp(childData[0], 4);
};
while (offset < last) {
_loop_1();
}
return r;
}
function parseVarFileInfo(view, offset, last) {
var valueLen = view.getUint16(offset + 2, true);
// value type check is not needed; because no value is needed
offset += 32; // roundUp(6 + ByteLenWithNull(L'VarFileInfo'), 4)
// this should be zero
offset += roundUp(valueLen, 4);
var r = [];
while (offset < last) {
// Var structure
var childDataLen = view.getUint16(offset, true);
var childValueLen = view.getUint16(offset + 2, true);
// value type must be binary; if not, skip it
if (view.getUint16(offset + 4, true) !== 0) {
offset += roundUp(childDataLen, 4);
continue;
}
var childDataLast = offset + childDataLen;
if (childDataLast > last) {
childDataLast = last;
}
var name_2 = readStringToNullChar(view, offset + 6, childDataLast);
offset = roundUp(offset + 6 + 2 * (name_2.length + 1), 4);
if (name_2 !== 'Translation' || childValueLen % 4 !== 0) {
// unknown entry
offset = roundUp(childDataLast, 4);
continue;
}
var _loop_2 = function (child) {
if (offset + 4 > childDataLast) {
return "break";
}
var lang = view.getUint16(offset, true);
var codepage = view.getUint16(offset + 2, true);
offset += 4;
if (r.filter(function (e) { return e.lang === lang && e.codepage === codepage; })
.length === 0) {
r.push({ lang: lang, codepage: codepage });
}
};
for (var child = 0; child < childValueLen; child += 4) {
var state_1 = _loop_2(child);
if (state_1 === "break")
break;
}
offset = roundUp(childDataLast, 4);
}
return r;
}
function parseVersionEntry(view, entry) {
var totalLen = view.getUint16(0, true);
var dataLen = view.getUint16(2, true);
// value type must be binary
if (view.getUint16(4, true) !== 0) {
throw new Error('Invalid version data format');
}
// 40 === roundUp(6 + ByteLenWithNull(L'VS_VERSION_INFO'), 4)
if (totalLen < dataLen + 40) {
throw new Error('Invalid version data format');
}
if (readStringToNullChar(view, 6, totalLen) !== 'VS_VERSION_INFO') {
throw new Error('Invalid version data format');
}
var d = {
lang: entry.lang,
fixedInfo: createFixedInfo(),
strings: [],
translations: [],
unknowns: [],
};
var offset = 38; // without padding
if (dataLen) {
dataLen += 40; // with padding
var sig = readUint32WithLastOffset(view, 40, dataLen);
var sVer = readUint32WithLastOffset(view, 44, dataLen);
// check signature
if (sig === 0xfeef04bd && sVer <= 0x10000) {
d.fixedInfo = {
fileVersionMS: readUint32WithLastOffset(view, 48, dataLen),
fileVersionLS: readUint32WithLastOffset(view, 52, dataLen),
productVersionMS: readUint32WithLastOffset(view, 56, dataLen),
productVersionLS: readUint32WithLastOffset(view, 60, dataLen),
fileFlagsMask: readUint32WithLastOffset(view, 64, dataLen),
fileFlags: readUint32WithLastOffset(view, 68, dataLen),
fileOS: readUint32WithLastOffset(view, 72, dataLen),
fileType: readUint32WithLastOffset(view, 76, dataLen),
fileSubtype: readUint32WithLastOffset(view, 80, dataLen),
fileDateMS: readUint32WithLastOffset(view, 84, dataLen),
fileDateLS: readUint32WithLastOffset(view, 88, dataLen),
};
}
offset = dataLen;
}
offset = roundUp(offset, 4);
// parse children
while (offset < totalLen) {
var childLen = view.getUint16(offset, true);
var childLast = offset + childLen;
// failsafe
if (childLast > totalLen) {
childLast = totalLen;
}
var name_3 = readStringToNullChar(view, offset + 6, childLast);
switch (name_3) {
case 'StringFileInfo':
d.strings = d.strings.concat(parseStringFileInfo(view, offset, childLast));
break;
case 'VarFileInfo':
d.translations = d.translations.concat(parseVarFileInfo(view, offset, childLast));
break;
default:
// unknown or unsupported type
d.unknowns.push({
name: name_3,
entireBin: allocatePartialBinary(view, offset, childLen),
});
break;
}
offset += roundUp(childLen, 4);
}
return d;
}
////////////////////////////////////////////////////////////////////////////////
// serializings
function generateStringTable(table) {
// estimate size
var size = 24; // roundUp(6 + ByteLenWithNull(L'xxxxxxxx'), 4)
var keys = Object.keys(table.values);
size = keys.reduce(function (prev, key) {
var value = table.values[key];
if (value == null) {
return prev;
}
var childHeaderSize = roundUp(6 + 2 * (key.length + 1), 4);
var newSize = roundUp(prev + childHeaderSize + 2 * (value.length + 1), 4);
// limit to 65532 because the table size is restricted to 16-bit value
return newSize > 65532 ? prev : newSize;
}, size);
// generate binary
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, size, true);
view.setUint16(2, 0, true); // no value length
view.setUint16(4, 1, true);
var langAndCp = ((table.lang & 0xffff) * 0x10000 +
(table.codepage & 0xffff))
.toString(16)
.toLowerCase();
// fixed length
if (langAndCp.length < 8) {
var l = 8 - langAndCp.length;
langAndCp = '00000000'.substr(0, l) + langAndCp;
}
var offset = roundUp(writeStringWithNullChar(view, 6, langAndCp), 4);
keys.forEach(function (key) {
var value = table.values[key];
if (value == null) {
return;
}
var childHeaderSize = roundUp(6 + 2 * (key.length + 1), 4);
var newSize = roundUp(childHeaderSize + 2 * (value.length + 1), 4);
if (offset + newSize <= 65532) {
view.setUint16(offset, newSize, true);
view.setUint16(offset + 2, value.length + 1, true); // value length is in character count
view.setUint16(offset + 4, 1, true);
offset = roundUp(writeStringWithNullChar(view, offset + 6, key), 4);
offset = roundUp(writeStringWithNullChar(view, offset, value), 4);
}
});
return bin;
}
function generateStringTableInfo(tables) {
// estimate size
var size = 36; // roundUp(6 + ByteLenWithNull(L'StringFileInfo'), 4)
var tableBins = tables.map(function (table) { return generateStringTable(table); });
// (all table sizes are rounded up)
size += tableBins.reduce(function (p, c) { return p + c.byteLength; }, 0);
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, size, true);
view.setUint16(2, 0, true); // no value length
view.setUint16(4, 1, true);
var offset = roundUp(writeStringWithNullChar(view, 6, 'StringFileInfo'), 4);
tableBins.forEach(function (table) {
var len = table.byteLength;
copyBuffer(bin, offset, table, 0, len);
offset += len;
});
return bin;
}
function generateVarFileInfo(translations) {
// estimate size
var size = 32; // roundUp(6 + ByteLenWithNull(L'VarFileInfo'), 4)
// (translation data is fixed length)
var translationsValueSize = translations.length * 4;
size += 32 + translationsValueSize;
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, size, true);
view.setUint16(2, 0, true); // no value length
view.setUint16(4, 1, true);
var offset = roundUp(writeStringWithNullChar(view, 6, 'VarFileInfo'), 4);
view.setUint16(offset, 32 + translationsValueSize, true);
view.setUint16(offset + 2, translationsValueSize, true);
view.setUint16(offset + 4, 0, true);
offset = roundUp(writeStringWithNullChar(view, offset + 6, 'Translation'), 4);
translations.forEach(function (translation) {
view.setUint16(offset, translation.lang, true);
view.setUint16(offset + 2, translation.codepage, true);
offset += 4;
});
return bin;
}
function generateVersionEntryBinary(entry) {
var size = 92; // roundUp(6 + ByteLenWithNull(L'VS_VERSION_INFO'), 4) + 52 (sizeof VS_FIXEDFILEINFO)
var stringTableInfoBin = generateStringTableInfo(entry.strings);
var stringTableInfoLen = stringTableInfoBin.byteLength;
size += stringTableInfoLen;
var varFileInfoBin = generateVarFileInfo(entry.translations);
var varFileInfoLen = varFileInfoBin.byteLength;
size += varFileInfoLen;
size = entry.unknowns.reduce(function (p, data) { return p + roundUp(data.entireBin.byteLength, 4); }, size);
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, size, true);
view.setUint16(2, 52, true);
view.setUint16(4, 0, true); // value is binary
var offset = roundUp(writeStringWithNullChar(view, 6, 'VS_VERSION_INFO'), 4);
view.setUint32(offset, 0xfeef04bd, true); // signature
view.setUint32(offset + 4, 0x10000, true); // structure version
view.setUint32(offset + 8, entry.fixedInfo.fileVersionMS, true);
view.setUint32(offset + 12, entry.fixedInfo.fileVersionLS, true);
view.setUint32(offset + 16, entry.fixedInfo.productVersionMS, true);
view.setUint32(offset + 20, entry.fixedInfo.productVersionLS, true);
view.setUint32(offset + 24, entry.fixedInfo.fileFlagsMask, true);
view.setUint32(offset + 28, entry.fixedInfo.fileFlags, true);
view.setUint32(offset + 32, entry.fixedInfo.fileOS, true);
view.setUint32(offset + 36, entry.fixedInfo.fileType, true);
view.setUint32(offset + 40, entry.fixedInfo.fileSubtype, true);
view.setUint32(offset + 44, entry.fixedInfo.fileDateMS, true);
view.setUint32(offset + 48, entry.fixedInfo.fileDateLS, true);
offset += 52;
copyBuffer(bin, offset, stringTableInfoBin, 0, stringTableInfoLen);
offset += stringTableInfoLen;
copyBuffer(bin, offset, varFileInfoBin, 0, varFileInfoLen);
offset += varFileInfoLen;
entry.unknowns.forEach(function (e) {
var len = e.entireBin.byteLength;
copyBuffer(bin, offset, e.entireBin, 0, len);
offset += roundUp(len, 4);
});
return bin;
}
////////////////////////////////////////////////////////////////////////////////
function clampInt(val, min, max) {
if (isNaN(val) || val < min) {
return min;
}
else if (val >= max) {
return max;
}
return Math.floor(val);
}
function parseVersionArguments(arg1, arg2, arg3, arg4, arg5) {
var _a;
var major;
var minor;
var micro;
var revision;
var lang;
if (typeof arg1 === 'string' &&
(typeof arg2 === 'undefined' || typeof arg2 === 'number') &&
typeof arg3 === 'undefined') {
_a = arg1
.split('.')
.map(function (token) { return clampInt(Number(token), 0, 65535); })
// add zeros for missing fields
.concat(0, 0, 0), major = _a[0], minor = _a[1], micro = _a[2], revision = _a[3];
lang = arg2;
}
else {
major = clampInt(Number(arg1), 0, 65535);
minor = clampInt(Number(arg2), 0, 65535);
micro = clampInt(typeof arg3 === 'undefined' ? 0 : Number(arg3), 0, 65535);
revision = clampInt(typeof arg4 === 'undefined' ? 0 : Number(arg4), 0, 65535);
lang = arg5;
}
return [major, minor, micro, revision, lang];
}
////////////////////////////////////////////////////////////////////////////////
/**
* Treats 'Version information' (`VS_VERSIONINFO`) resource data.
*/
var VersionInfo = /** @class */ (function () {
function VersionInfo(entry) {
if (!entry) {
this.data = {
lang: 0,
fixedInfo: createFixedInfo(),
strings: [],
translations: [],
unknowns: [],
};
}
else {
var view = new DataView(entry.bin);
this.data = parseVersionEntry(view, entry);
}
}
/** Returns new `VersionInfo` instance with empty data. */
VersionInfo.createEmpty = function () {
return new VersionInfo();
};
VersionInfo.create = function (arg1, fixedInfo, strings) {
var lang;
if (typeof arg1 === 'object') {
lang = arg1.lang;
fixedInfo = arg1.fixedInfo;
strings = arg1.strings;
}
else {
lang = arg1;
}
var vi = new VersionInfo();
vi.data.lang = lang;
// copy all specified values
// (if unspecified, use default value set by `createFixedInfo`)
for (var _fixedInfoKey in fixedInfo) {
var fixedInfoKey = _fixedInfoKey;
if (fixedInfoKey in fixedInfo) {
var value = fixedInfo[fixedInfoKey];
if (value != null) {
vi.data.fixedInfo[fixedInfoKey] = value;
}
}
}
vi.data.strings = strings.map(function (_a) {
var lang = _a.lang, codepage = _a.codepage, values = _a.values;
return ({
lang: lang,
codepage: codepage,
values: cloneObject(values),
});
});
vi.data.translations = strings.map(function (_a) {
var lang = _a.lang, codepage = _a.codepage;
return ({ lang: lang, codepage: codepage });
});
return vi;
};
/** Pick up all version-info entries */
VersionInfo.fromEntries = function (entries) {
return entries
.filter(function (e) { return e.type === 16; })
.map(function (e) { return new VersionInfo(e); });
};
Object.defineProperty(VersionInfo.prototype, "lang", {
/** A language value for this resource entry. */
get: function () {
return this.data.lang;
},
set: function (value) {
this.data.lang = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(VersionInfo.prototype, "fixedInfo", {
/**
* The property of fixed version info, containing file version, product version, etc.
* (data: `VS_FIXEDFILEINFO`)
*
* Although this property is read-only, you can rewrite
* each child fields directly to apply data.
*/
get: function () {
return this.data.fixedInfo;
},
enumerable: false,
configurable: true
});
/**
* Returns all languages that the executable supports. (data: `VarFileInfo`)
*
* Usually the returned array is equal to the one returned by `getAllLanguagesForStringValues`,
* but some resource-generating tools doesn't generate same values.
*/
VersionInfo.prototype.getAvailableLanguages = function () {
return this.data.translations.slice(0);
};
/**
* Replaces all languages that the executable supports.
*/
VersionInfo.prototype.replaceAvailableLanguages = function (languages) {
this.data.translations = languages.slice(0);
};
/**
* Returns all string values for the specified language. (data: values in lang-charset block of `StringFileInfo`)
*/
VersionInfo.prototype.getStringValues = function (language) {
var a = this.data.strings
.filter(function (e) {
return e.lang === language.lang && e.codepage === language.codepage;
})
.map(function (e) { return e.values; });
return a.length > 0 ? a[0] : {};
};
/**
* Returns all languages used by string values. (data: lang-charset name of `StringFileInfo`)
*
* Usually the returned array is equal to the one returned by `getAvailableLanguages`,
* but some resource-generating tools doesn't generate same values.
*/
VersionInfo.prototype.getAllLanguagesForStringValues = function () {
return this.data.strings.map(function (_a) {
var codepage = _a.codepage, lang = _a.lang;
return ({ codepage: codepage, lang: lang });
});
};
/**
* Add or replace the string values.
* @param language language info
* @param values string values (key-value pairs)
* @param addToAvailableLanguage set `true` to add `language` into available languages
* if not existing in `getAvailableLanguages()` (default: `true`)
*/
VersionInfo.prototype.setStringValues = function (language, values, addToAvailableLanguage) {
if (addToAvailableLanguage === void 0) { addToAvailableLanguage = true; }
var a = this.data.strings.filter(function (e) { return e.lang === language.lang && e.codepage === language.codepage; });
var table;
if (a.length === 0) {
table = {
lang: language.lang,
codepage: language.codepage,
values: {},
};
this.data.strings.push(table);
}
else {
table = a[0];
}
for (var key in values) {
var value = values[key];
if (value != null) {
table.values[key] = value;
}
}
if (addToAvailableLanguage) {
// if no translation is available, then add it
var t = this.data.translations.filter(function (e) {
return e.lang === language.lang && e.codepage === language.codepage;
});
if (t.length === 0) {
this.data.translations.push({
lang: language.lang,
codepage: language.codepage,
});
}
}
};
/**
* Add or replace the string value.
* @param language language info
* @param key the key name of string value
* @param value the string value
* @param addToAvailableLanguage set `true` to add `language` into available languages
* if not existing in `getAvailableLanguages()` (default: `true`)
*/
VersionInfo.prototype.setStringValue = function (language, key, value, addToAvailableLanguage) {
var _a;
if (addToAvailableLanguage === void 0) { addToAvailableLanguage = true; }
this.setStringValues(language, (_a = {}, _a[key] = value, _a), addToAvailableLanguage);
};
/**
* Remove all string values for specified language.
* @param language language info
* @param removeFromAvailableLanguage set `true` to remove `language` from available languages
* if existing in `getAvailableLanguages()` (default: `true`)
*/
VersionInfo.prototype.removeAllStringValues = function (language, removeFromAvailableLanguage) {
if (removeFromAvailableLanguage === void 0) { removeFromAvailableLanguage = true; }
var strings = this.data.strings;
var len = strings.length;
for (var i = 0; i < len; ++i) {
var e = strings[i];
if (e != null &&
e.lang === language.lang &&
e.codepage === language.codepage) {
strings.splice(i, 1);
if (removeFromAvailableLanguage) {
var translations = this.data.translations;
for (var j = 0; j < translations.length; j++) {
var t = translations[j];
if (t != null &&
t.lang === language.lang &&
t.codepage === language.codepage) {
translations.splice(j, 1);
break;
}
}
}
break;
}
}
};
/**
* Remove specified string value for specified language.
* @param language language info
* @param key the key name of string value to be removed
* @param removeFromAvailableLanguage set `true` to remove `language` from available languages
* if no more string values exist for `language` (default: `true`)
*/
VersionInfo.prototype.removeStringValue = function (language, key, removeFromAvailableLanguage) {
if (removeFromAvailableLanguage === void 0) { removeFromAvailableLanguage = true; }
var strings = this.data.strings;
var len = strings.length;
for (var i = 0; i < len; ++i) {
var e = strings[i];
if (e != null &&
e.lang === language.lang &&
e.codepage === language.codepage) {
try {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete e.values[key];
}
catch (_ex) { }
if (removeFromAvailableLanguage &&
Object.keys(e.values).length === 0) {
// if no entries are left, remove table and translations
strings.splice(i, 1);
var translations = this.data.translations;
for (var j = 0; j < translations.length; j++) {
var t = translations[j];
if (t != null &&
t.lang === language.lang &&
t.codepage === language.codepage) {
translations.splice(j, 1);
break;
}
}
}
break;
}
}
};
/**
* Creates `Type.ResourceEntry` object for this instance.
* Usually `outputToResourceEntries` is suitable for generating resource data
* into executables, but you can use this method if necessary.
*/
VersionInfo.prototype.generateResource = function () {
var bin = generateVersionEntryBinary(this.data);
return {
type: 16,
id: 1,
lang: this.lang,
codepage: 1200,
bin: bin,
};
};
/**
* Generates version info resource data (using `generateResource()`) and emits into `entries` array.
* If version info resource already exists in `entries`, this method replaces it with the new one.
* @param entries resource entry array for output
*/
VersionInfo.prototype.outputToResourceEntries = function (entries) {
var res = this.generateResource();
var len = entries.length;
for (var i = 0; i < len; ++i) {
var e = entries[i];
if (e != null &&
e.type === 16 &&
e.id === res.id &&
e.lang === res.lang) {
entries[i] = res;
return;
}
}
entries.push(res);
};
// utility methods
VersionInfo.prototype.getDefaultVersionLang = function (propName) {
// first, use `this.lang` if it is a numeric value
var num = Number(this.lang);
if (this.lang !== '' && !isNaN(num)) {
return num;
}
// second, use lang value for propName if there is only one language
var a = this.data.strings
.filter(function (e) { return propName in e.values && e.values[propName] != null; })
.map(function (e) { return e.lang; });
if (a.length === 1) {
return a[0];
}
// use English language
return 1033;
};
VersionInfo.prototype.setFileVersion = function (arg1, arg2, arg3, arg4, arg5) {
this.setFileVersionImpl.apply(this, parseVersionArguments(arg1, arg2, arg3, arg4, arg5));
};
VersionInfo.prototype.setFileVersionImpl = function (major, minor, micro, revision, lang) {
lang =
typeof lang !== 'undefined'
? lang
: this.getDefaultVersionLang('FileVersion');
this.fixedInfo.fileVersionMS = (major << 16) | minor;
this.fixedInfo.fileVersionLS = (micro << 16) | revision;
this.setStringValue({ lang: lang, codepage: 1200 }, 'FileVersion', major + "." + minor + "." + micro + "." + revision, true);
};
VersionInfo.prototype.setProductVersion = function (arg1, arg2, arg3, arg4, arg5) {
this.setProductVersionImpl.apply(this, parseVersionArguments(arg1, arg2, arg3, arg4, arg5));
};
VersionInfo.prototype.setProductVersionImpl = function (major, minor, micro, revision, lang) {
lang =
typeof lang !== 'undefined'
? lang
: this.getDefaultVersionLang('ProductVersion');
this.fixedInfo.productVersionMS = (major << 16) | minor;
this.fixedInfo.productVersionLS = (micro << 16) | revision;
this.setStringValue({ lang: lang, codepage: 1200 }, 'ProductVersion', major + "." + minor + "." + micro + "." + revision, true);
};
return VersionInfo;
}());
export default VersionInfo;

View File

@@ -0,0 +1,11 @@
import { Type } from 'pe-library';
import IconGroupEntry, { IconGroupItem } from './IconGroupEntry.js';
import StringTable from './StringTable.js';
import VersionFileFlags from './VersionFileFlags.js';
import VersionFileOS from './VersionFileOS.js';
import { VersionFileDriverSubtype, VersionFileFontSubtype } from './VersionFileSubtypes.js';
import VersionFileType from './VersionFileType.js';
import VersionInfo, { VersionInfoCreateParam, VersionFixedInfo, VersionStringTable, VersionStringValues, VersionTranslation } from './VersionInfo.js';
declare type ResourceEntry = Type.ResourceEntry;
declare type ResourceEntryBaseType<TType extends string | number, TID extends string | number, TLang extends string | number> = Type.ResourceEntryBaseType<TType, TID, TLang>;
export { IconGroupEntry, IconGroupItem, ResourceEntry, ResourceEntryBaseType, StringTable, VersionInfoCreateParam, VersionFileFlags, VersionFileOS, VersionFileDriverSubtype, VersionFileFontSubtype, VersionFileType, VersionFixedInfo, VersionInfo, VersionStringTable, VersionStringValues, VersionTranslation, };

View File

@@ -0,0 +1,8 @@
import IconGroupEntry from './IconGroupEntry.js';
import StringTable from './StringTable.js';
import VersionFileFlags from './VersionFileFlags.js';
import VersionFileOS from './VersionFileOS.js';
import { VersionFileDriverSubtype, VersionFileFontSubtype, } from './VersionFileSubtypes.js';
import VersionFileType from './VersionFileType.js';
import VersionInfo from './VersionInfo.js';
export { IconGroupEntry, StringTable, VersionFileFlags, VersionFileOS, VersionFileDriverSubtype, VersionFileFontSubtype, VersionFileType, VersionInfo, };

View File

@@ -0,0 +1,71 @@
/** Predefined algorithm types */
export declare type DigestAlgorithmType = 'sha1' | 'sha224' | 'sha256' | 'sha384' | 'sha512' | 'sha512-224' | 'sha512-256' | 'sha3-224' | 'sha3-256' | 'sha3-384' | 'sha3-512' | 'shake128' | 'shake256' | 'SHA1' | 'SHA224' | 'SHA256' | 'SHA384' | 'SHA512' | 'SHA512-224' | 'SHA512-256' | 'SHA3-224' | 'SHA3-256' | 'SHA3-384' | 'SHA3-512' | 'SHAKE128' | 'SHAKE256';
export declare type EncryptionAlgorithmType = 'rsa' | 'dsa' | 'RSA' | 'DSA';
export default interface SignerObject {
/**
* Returns the digest algorithm used in `digestData`.
* To use the algorithm other than defined in `DigestAlgorithmType`,
* return an integer array of values from OID string.
* (e.g. [1,3,14,3,2,26] for 'sha1')
*
* @note
* The newer digest algorithm (including SHA224, SHA512-256, SHA3 algorithms, etc.)
* might not be supported by Windows.
*/
getDigestAlgorithm(): DigestAlgorithmType | number[];
/**
* Returns the encryption algorithm used in `encryptData`.
* To use the algorithm other than defined in `EncryptionAlgorithmType`,
* return an integer array of values from OID string.
* (e.g. [1,2,840,113549,1,1,1] for 'rsa')
*/
getEncryptionAlgorithm(): EncryptionAlgorithmType | number[];
/**
* Returns the certificate data, which format is DER binary (X.509 certificate data
* or '.p7b' file data which is based on DER and contains certificates).
*
* You can return an `Array` (not an `ArrayLike`), which contains one or more certificates in format above.
* In this case, each certificates are stored to signed data in order.
* Note that this library does not sort certificates, so the implementation should have responsible for the order of certificates.
*/
getCertificateData(): ArrayBuffer | ArrayBufferView | Array<ArrayBuffer | ArrayBufferView>;
/**
* Returns the public key data, which format is DER binary (X.509 Public Key or '.p7b' file data which is based on DER).
*
* You can return an `Array` (not an `ArrayLike`), which contains one or more public keys in format above.
* In this case, each public keys are stored to signed data in order.
* Note that this library does not sort public keys, so the implementation should have responsible for the order of keys.
*
* @deprecated This method is renamed to {@link getCertificateData} due to the actual purpose of this method
* and `getPublicKeyData` will no longer be used in the future.
*/
getPublicKeyData?(): ArrayBuffer | ArrayBufferView | Array<ArrayBuffer | ArrayBufferView>;
/**
* Digests specified data. The digest algorithm type must be same as the result of `getDigestAlgorithm`.
* Must pick all data from `dataIterator` (until `dataIterator.next().done` is `true`).
*/
digestData(dataIterator: Iterator<ArrayBuffer, void>): PromiseLike<ArrayBuffer | ArrayBufferView>;
/**
* Encrypts specified data with **private key** (i.e. can be verified with the public key from `getCertificateData`). The private key type (algorithm) must be same as the result of `getEncryptionAlgorithm`.
* Must pick all data from `dataIterator` (until `dataIterator.next().done` is `true`).
*
* This method must be implemented if `signData` is not implemented.
*/
encryptData?(dataIterator: Iterator<ArrayBuffer, void>): PromiseLike<ArrayBuffer | ArrayBufferView>;
/**
* Signs specified data with **private key** (i.e. can be verified with the public key from `getCertificateData`).
* The private key type (algorithm) must be same as the result of `getEncryptionAlgorithm`, and the digest algorithm must be same as the result of `getDigestAlgorithm`.
* Must pick all data from `dataIterator` (until `dataIterator.next().done` is `true`).
*
* This method must be implemented if `encryptData` is not implemented.
*
* Note that even if `signData` is implemented, `digestData` must be implemented.
*/
signData?(dataIterator: Iterator<ArrayBuffer, void>): PromiseLike<ArrayBuffer | ArrayBufferView>;
/**
* Make 'timestamp' data, generated by TSA, from specified data (omit this method if not using timestamp).
* Must return entire timestamp response data.
* @param reqData timestamp request data (`TimeStampReq`) to send to TSA
*/
timestampData?(reqData: ArrayBuffer): PromiseLike<ArrayBuffer | ArrayBufferView>;
}

View File

@@ -0,0 +1,2 @@
export {};
/* eslint-enable @typescript-eslint/method-signature-style */

View File

@@ -0,0 +1,7 @@
import DERObject from './data/DERObject.js';
export declare function toUint8Array(bin: ArrayBuffer | ArrayBufferView): Uint8Array;
/** @return [length, afterOffset] */
export declare function calculateDERLength(data: number[] | Uint8Array, offset: number): [number, number];
/** @return [issuer, serialNumber] */
export declare function pickIssuerAndSerialNumberDERFromCert(bin: ArrayBuffer | ArrayBufferView | Array<ArrayBuffer | ArrayBufferView>): [number[], number[]];
export declare function certBinToCertificatesDER(bin: ArrayBuffer | ArrayBufferView | Array<ArrayBuffer | ArrayBufferView>): DERObject[];

View File

@@ -0,0 +1,246 @@
import { RawDERObject } from './data/DERObject.js';
import { OID_SIGNED_DATA } from './data/KnownOids.js';
export function toUint8Array(bin) {
if ('buffer' in bin) {
return new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
return new Uint8Array(bin);
}
}
/** @return [length, afterOffset] */
export function calculateDERLength(data, offset) {
var actualLength = 0;
var value = data[offset];
if (value == null) {
throw new Error('Invalid "offset" value');
}
else if (value < 0x80) {
actualLength = value;
++offset;
}
else if (value === 0x80) {
throw new Error('Not supported certificate data (variable length)');
}
else {
var c = value & 0x7f;
++offset;
while (c--) {
if (offset >= data.length) {
throw new Error('Invalid certificate data (invalid sequence length)');
}
actualLength <<= 8;
actualLength |= data[offset];
++offset;
}
}
return [actualLength, offset];
}
function skipField(data, offsetOfDataHead) {
var _a = calculateDERLength(data, offsetOfDataHead + 1), len = _a[0], off = _a[1];
return off + len;
}
function pickCertificatesIfDERHasSignedData(ub, offset) {
var _a, _b, _c, _d, _e;
if (ub.length < offset + 2) {
return null;
}
if (ub[offset] !== 0x30) {
return null;
}
var tempLength;
_a = calculateDERLength(ub, offset + 1), tempLength = _a[0], offset = _a[1];
if (tempLength > ub.length - offset) {
throw new Error('Invalid certificate data (insufficient data length)');
}
// if the first item is not contentType, then return
if (ub[offset] !== 0x6) {
return null;
}
var signedDataOid = OID_SIGNED_DATA.toDER();
for (var i = 0; i < signedDataOid.length; ++i) {
if (ub[offset + i] !== signedDataOid[i]) {
return null;
}
}
// if contentType is OID_SIGNED_DATA, then check sequence format
// ContentInfo.content
offset += signedDataOid.length;
// [0] IMPLICIT
if (ub[offset] !== 0xa0) {
throw new Error('Invalid certificate data (no content in contentInfo)');
}
_b = calculateDERLength(ub, offset + 1), tempLength = _b[0], offset = _b[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for content)');
}
// sequence
if (ub[offset] !== 0x30) {
throw new Error('Invalid certificate data (unexpected signedData)');
}
_c = calculateDERLength(ub, offset + 1), tempLength = _c[0], offset = _c[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData)');
}
// version
if (ub[offset] !== 0x2 ||
ub[offset + 1] !== 0x1 ||
ub[offset + 2] !== 0x1) {
throw new Error('Invalid certificate data (unexpected signedData.version)');
}
offset += 3;
// digestAlgorithms (skip)
if (ub[offset] !== 0x31) {
throw new Error('Invalid certificate data (no signedData.digestAlgorithms)');
}
_d = calculateDERLength(ub, offset + 1), tempLength = _d[0], offset = _d[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.digestAlgorithms)');
}
offset += tempLength;
// contentInfo (skip)
if (ub[offset] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.contentInfo)');
}
_e = calculateDERLength(ub, offset + 1), tempLength = _e[0], offset = _e[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.contentInfo)');
}
offset += tempLength;
// certificates
if (ub[offset] !== 0xa0) {
throw new Error('Invalid certificate data (no signedData.certificates)');
}
var _f = calculateDERLength(ub, offset + 1), certsLength = _f[0], newOffset = _f[1];
if (newOffset + certsLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
return ub.subarray(offset, newOffset + certsLength);
}
/** @return [issuer, serialNumber] */
export function pickIssuerAndSerialNumberDERFromCert(bin) {
var _a, _b;
if (Array.isArray(bin)) {
// use first one and call again
if (bin.length === 0) {
throw new Error('No data is specified.');
}
return pickIssuerAndSerialNumberDERFromCert(bin[0]);
}
var ub = toUint8Array(bin);
if (ub.length < 2) {
throw new Error('Invalid certificate data');
}
if (ub[0] !== 0x30) {
throw new Error('Not supported certificate data (non-`Certificate`-format data)');
}
var certsBin = pickCertificatesIfDERHasSignedData(ub, 0);
if (certsBin) {
// certificates
var _c = calculateDERLength(certsBin, 1), tempLength_1 = _c[0], eaten_1 = _c[1];
if (eaten_1 + tempLength_1 > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
// pick first certificate and call again
if (certsBin[eaten_1] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.certificates[0])');
}
var _d = calculateDERLength(certsBin, eaten_1 + 1), certLength = _d[0], tempOffset = _d[1];
if (tempOffset + certLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates[0])');
}
return pickIssuerAndSerialNumberDERFromCert(certsBin.subarray(eaten_1, tempOffset + certLength));
}
var tempLength;
var eaten;
_a = calculateDERLength(ub, 1), tempLength = _a[0], eaten = _a[1];
if (tempLength > ub.length - eaten) {
throw new Error('Invalid certificate data (insufficient data length)');
}
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (missing tbsCertificate)');
}
// Certificate
var tbsCertificateLen;
_b = calculateDERLength(ub, eaten + 1), tbsCertificateLen = _b[0], eaten = _b[1];
if (tbsCertificateLen > ub.length - eaten) {
throw new Error('Invalid certificate data (invalid tbsCertificate length)');
}
var tbsOffsetLast = eaten + tbsCertificateLen;
// TBSCertificate
// :skip version
if (ub[eaten] === 0xa0) {
eaten = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after version)');
}
}
// pick serialNumber
if (ub[eaten] !== 2) {
throw new Error('Invalid certificate data (invalid serialNumber)');
}
var offsetAfterSerialNumber = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after serialNumber)');
}
var serialNumberDER = [].slice.call(ub, eaten, offsetAfterSerialNumber);
eaten = offsetAfterSerialNumber;
// :skip algorithmIdentifier
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (invalid algorithmIdentifier)');
}
eaten = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after serialNumber)');
}
// pick issuer
// Name ::= CHOICE { RDNSequence }
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (invalid issuer)');
}
var offsetAfterIssuer = skipField(ub, eaten);
if (offsetAfterIssuer > tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: issuer)');
}
return [
// return entire issuer sequence
[].slice.call(ub, eaten, offsetAfterIssuer),
serialNumberDER,
];
}
export function certBinToCertificatesDER(bin) {
if (Array.isArray(bin)) {
// use all items, map with `certBinToCertificatesDER`, and concat all
return bin
.map(certBinToCertificatesDER)
.reduce(function (prev, cur) { return prev.concat(cur); }, []);
}
var ub = toUint8Array(bin);
var certsBin = pickCertificatesIfDERHasSignedData(ub, 0);
if (certsBin) {
// certificates
var _a = calculateDERLength(certsBin, 1), tempLength = _a[0], eaten = _a[1];
if (eaten + tempLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
var offsetLast = eaten + tempLength;
var rawData = [];
for (var offset = eaten; offset < offsetLast;) {
// pick certificates
if (certsBin[offset] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.certificates[*])');
}
var _b = calculateDERLength(certsBin, offset + 1), certLength = _b[0], tempOffset = _b[1];
if (tempOffset + certLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates[*])');
}
rawData.push(new RawDERObject(certsBin.subarray(offset, tempOffset + certLength)));
offset = tempOffset + certLength;
}
return rawData;
}
else {
return [new RawDERObject(ub)];
}
}

View File

@@ -0,0 +1,7 @@
import DERObject from './DERObject.js';
import ObjectIdentifier from './ObjectIdentifier.js';
export default class AlgorithmIdentifier implements DERObject {
algorithm: ObjectIdentifier;
constructor(algorithm: ObjectIdentifier);
toDER(): number[];
}

View File

@@ -0,0 +1,14 @@
import { makeDERSequence } from './derUtil.js';
var AlgorithmIdentifier = /** @class */ (function () {
function AlgorithmIdentifier(algorithm) {
this.algorithm = algorithm;
}
AlgorithmIdentifier.prototype.toDER = function () {
var r = this.algorithm.toDER();
return makeDERSequence(r.concat(
// parameters is not used now
[0x05, 0x00]));
};
return AlgorithmIdentifier;
}());
export default AlgorithmIdentifier;

View File

@@ -0,0 +1,8 @@
import DERObject from './DERObject.js';
import ObjectIdentifier from './ObjectIdentifier.js';
export default class Attribute implements DERObject {
attrType: ObjectIdentifier;
attrValues: DERObject[];
constructor(attrType: ObjectIdentifier, attrValues: DERObject[]);
toDER(): number[];
}

View File

@@ -0,0 +1,12 @@
import { makeDERSequence, arrayToDERSet } from './derUtil.js';
var Attribute = /** @class */ (function () {
function Attribute(attrType, attrValues) {
this.attrType = attrType;
this.attrValues = attrValues;
}
Attribute.prototype.toDER = function () {
return makeDERSequence(this.attrType.toDER().concat(arrayToDERSet(this.attrValues)));
};
return Attribute;
}());
export default Attribute;

View File

@@ -0,0 +1,4 @@
import ContentInfo from './ContentInfo.js';
import SignedData from './SignedData.js';
export default class CertificateDataRoot extends ContentInfo<SignedData> {
}

View File

@@ -0,0 +1,24 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import ContentInfo from './ContentInfo.js';
var CertificateDataRoot = /** @class */ (function (_super) {
__extends(CertificateDataRoot, _super);
function CertificateDataRoot() {
return _super !== null && _super.apply(this, arguments) || this;
}
return CertificateDataRoot;
}(ContentInfo));
export default CertificateDataRoot;

View File

@@ -0,0 +1,8 @@
import DERObject from './DERObject.js';
import ObjectIdentifier from './ObjectIdentifier.js';
export default class ContentInfo<TContent extends DERObject = DERObject> implements DERObject {
contentType: ObjectIdentifier;
content: TContent;
constructor(contentType: ObjectIdentifier, content: TContent);
toDER(): number[];
}

View File

@@ -0,0 +1,15 @@
import { makeDERSequence, makeDERTaggedData } from './derUtil.js';
// abstract
var ContentInfo = /** @class */ (function () {
function ContentInfo(contentType, content) {
this.contentType = contentType;
this.content = content;
}
ContentInfo.prototype.toDER = function () {
return makeDERSequence(this.contentType
.toDER()
.concat(makeDERTaggedData(0, this.content.toDER())));
};
return ContentInfo;
}());
export default ContentInfo;

View File

@@ -0,0 +1,8 @@
export default interface DERObject {
toDER: () => number[];
}
export declare class RawDERObject implements DERObject {
data: number[] | Uint8Array;
constructor(data: number[] | Uint8Array);
toDER(): number[];
}

View File

@@ -0,0 +1,10 @@
var RawDERObject = /** @class */ (function () {
function RawDERObject(data) {
this.data = data;
}
RawDERObject.prototype.toDER = function () {
return [].slice.call(this.data);
};
return RawDERObject;
}());
export { RawDERObject };

View File

@@ -0,0 +1,8 @@
import AlgorithmIdentifier from './AlgorithmIdentifier.js';
import DERObject from './DERObject.js';
export default class DigestInfo implements DERObject {
digestAlgorithm: AlgorithmIdentifier;
digest: ArrayBuffer | ArrayBufferView;
constructor(digestAlgorithm: AlgorithmIdentifier, digest: ArrayBuffer | ArrayBufferView);
toDER(): number[];
}

View File

@@ -0,0 +1,23 @@
import { makeDERSequence, makeDEROctetString } from './derUtil.js';
var DigestInfo = /** @class */ (function () {
function DigestInfo(digestAlgorithm, digest) {
this.digestAlgorithm = digestAlgorithm;
this.digest = digest;
}
DigestInfo.prototype.toDER = function () {
var digest = this.digest;
var digestArray;
if ('buffer' in digest) {
digestArray = new Uint8Array(digest.buffer, digest.byteOffset, digest.byteLength);
}
else {
digestArray = new Uint8Array(digest);
}
var derData = this.digestAlgorithm
.toDER()
.concat(makeDEROctetString(digestArray));
return makeDERSequence(derData);
};
return DigestInfo;
}());
export default DigestInfo;

View File

@@ -0,0 +1,7 @@
import DERObject from './DERObject.js';
export default class IssuerAndSerialNumber implements DERObject {
issuer: DERObject;
serialNumber: DERObject;
constructor(issuer: DERObject, serialNumber: DERObject);
toDER(): number[];
}

View File

@@ -0,0 +1,12 @@
import { makeDERSequence } from './derUtil.js';
var IssuerAndSerialNumber = /** @class */ (function () {
function IssuerAndSerialNumber(issuer, serialNumber) {
this.issuer = issuer;
this.serialNumber = serialNumber;
}
IssuerAndSerialNumber.prototype.toDER = function () {
return makeDERSequence(this.issuer.toDER().concat(this.serialNumber.toDER()));
};
return IssuerAndSerialNumber;
}());
export default IssuerAndSerialNumber;

View File

@@ -0,0 +1,23 @@
import ObjectIdentifier from './ObjectIdentifier.js';
export declare const OID_SHA1_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA256_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA384_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA512_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA224_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA512_224_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA512_256_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA3_224_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA3_256_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA3_384_NO_SIGN: ObjectIdentifier;
export declare const OID_SHA3_512_NO_SIGN: ObjectIdentifier;
export declare const OID_SHAKE128_NO_SIGN: ObjectIdentifier;
export declare const OID_SHAKE256_NO_SIGN: ObjectIdentifier;
export declare const OID_RSA: ObjectIdentifier;
export declare const OID_DSA: ObjectIdentifier;
export declare const OID_SIGNED_DATA: ObjectIdentifier;
export declare const OID_CONTENT_TYPE: ObjectIdentifier;
export declare const OID_MESSAGE_DIGEST: ObjectIdentifier;
export declare const OID_SPC_STATEMENT_TYPE_OBJID: ObjectIdentifier;
export declare const OID_SPC_SP_OPUS_INFO_OBJID: ObjectIdentifier;
export declare const OID_SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID: ObjectIdentifier;
export declare const OID_RFC3161_COUNTER_SIGNATURE: ObjectIdentifier;

View File

@@ -0,0 +1,67 @@
import ObjectIdentifier from './ObjectIdentifier.js';
// 1.3.14.3.2.26
// prettier-ignore
export var OID_SHA1_NO_SIGN = new ObjectIdentifier([1, 3, 14, 3, 2, 26]);
// 2.16.840.1.101.3.4.2.1
// prettier-ignore
export var OID_SHA256_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 1]);
// 2.16.840.1.101.3.4.2.2
// prettier-ignore
export var OID_SHA384_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 2]);
// 2.16.840.1.101.3.4.2.3
// prettier-ignore
export var OID_SHA512_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 3]);
// 2.16.840.1.101.3.4.2.4
// prettier-ignore
export var OID_SHA224_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 4]);
// 2.16.840.1.101.3.4.2.5
// prettier-ignore
export var OID_SHA512_224_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 5]);
// 2.16.840.1.101.3.4.2.6
// prettier-ignore
export var OID_SHA512_256_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 6]);
// 2.16.840.1.101.3.4.2.7
// prettier-ignore
export var OID_SHA3_224_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 7]);
// 2.16.840.1.101.3.4.2.8
// prettier-ignore
export var OID_SHA3_256_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 8]);
// 2.16.840.1.101.3.4.2.9
// prettier-ignore
export var OID_SHA3_384_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 9]);
// 2.16.840.1.101.3.4.2.10
// prettier-ignore
export var OID_SHA3_512_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 10]);
// 2.16.840.1.101.3.4.2.11
// prettier-ignore
export var OID_SHAKE128_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 11]);
// 2.16.840.1.101.3.4.2.12
// prettier-ignore
export var OID_SHAKE256_NO_SIGN = new ObjectIdentifier([2, 16, 840, 1, 101, 3, 4, 2, 12]);
// 1.2.840.113549.1.1.1
// prettier-ignore
export var OID_RSA = new ObjectIdentifier([1, 2, 840, 113549, 1, 1, 1]);
// 1.2.840.10040.4.1
// prettier-ignore
export var OID_DSA = new ObjectIdentifier([1, 2, 840, 10040, 4, 1]);
// 1.2.840.113549.1.7.2
// prettier-ignore
export var OID_SIGNED_DATA = new ObjectIdentifier([1, 2, 840, 113549, 1, 7, 2]);
// 1.2.840.113549.1.9.3
// prettier-ignore
export var OID_CONTENT_TYPE = new ObjectIdentifier([1, 2, 840, 113549, 1, 9, 3]);
// 1.2.840.113549.1.9.4
// prettier-ignore
export var OID_MESSAGE_DIGEST = new ObjectIdentifier([1, 2, 840, 113549, 1, 9, 4]);
// 1.3.6.1.4.1.311.2.1.11
// prettier-ignore
export var OID_SPC_STATEMENT_TYPE_OBJID = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 2, 1, 11]);
// 1.3.6.1.4.1.311.2.1.12
// prettier-ignore
export var OID_SPC_SP_OPUS_INFO_OBJID = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 2, 1, 12]);
// 1.3.6.1.4.1.311.2.1.21
// prettier-ignore
export var OID_SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 2, 1, 21]);
// 1.3.6.1.4.1.311.3.3.1
// prettier-ignore
export var OID_RFC3161_COUNTER_SIGNATURE = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 3, 3, 1]);

View File

@@ -0,0 +1,6 @@
import DERObject from './DERObject.js';
export default class ObjectIdentifier implements DERObject {
value: number[];
constructor(value: number[] | string);
toDER(): number[];
}

View File

@@ -0,0 +1,41 @@
import { makeDERLength } from './derUtil.js';
var ObjectIdentifier = /** @class */ (function () {
function ObjectIdentifier(value) {
if (typeof value === 'string') {
this.value = value.split(/\./g).map(function (s) { return Number(s); });
}
else {
this.value = value;
}
}
ObjectIdentifier.prototype.toDER = function () {
var id = this.value;
var r = [];
if (id.length < 2) {
throw new Error("Unexpected 'value' field");
}
// first byte will be (x * 40 + y) for 'x.y.****'
r.push(id[0] * 40 + id[1]);
for (var i = 2; i < id.length; ++i) {
// store as variable-length value
var val = id[i];
var isFirst = true;
var insertPos = r.length;
while (true) {
var v = val & 0x7f;
if (!isFirst) {
v += 0x80;
}
r.splice(insertPos, 0, v);
if (val < 0x80) {
break;
}
isFirst = false;
val = Math.floor(val / 0x80);
}
}
return [0x06].concat(makeDERLength(r.length)).concat(r);
};
return ObjectIdentifier;
}());
export default ObjectIdentifier;

View File

@@ -0,0 +1,13 @@
import DigestAlgorithmIdentifier from './AlgorithmIdentifier.js';
import ContentInfo from './ContentInfo.js';
import DERObject from './DERObject.js';
export default class SignedData implements DERObject {
version: number;
digestAlgorithms: DigestAlgorithmIdentifier[];
contentInfo: ContentInfo;
signerInfos: DERObject[];
certificates?: DERObject[] | undefined;
crls?: DERObject[] | undefined;
constructor(version: number, digestAlgorithms: DigestAlgorithmIdentifier[], contentInfo: ContentInfo, signerInfos: DERObject[], certificates?: DERObject[] | undefined, crls?: DERObject[] | undefined);
toDER(): number[];
}

View File

@@ -0,0 +1,29 @@
import { arrayToDERSet, makeDERSequence, makeDERTaggedData, } from './derUtil.js';
var SignedData = /** @class */ (function () {
function SignedData(version, digestAlgorithms, contentInfo, signerInfos, certificates, crls) {
this.version = version;
this.digestAlgorithms = digestAlgorithms;
this.contentInfo = contentInfo;
this.signerInfos = signerInfos;
this.certificates = certificates;
this.crls = crls;
}
SignedData.prototype.toDER = function () {
var r = [0x02, 0x01, this.version & 0xff]
.concat(arrayToDERSet(this.digestAlgorithms))
.concat(this.contentInfo.toDER());
if (this.certificates && this.certificates.length > 0) {
var allCertsDER = arrayToDERSet(this.certificates);
// IMPLICIT SET
allCertsDER[0] = 0xa0;
r = r.concat(allCertsDER);
}
if (this.crls) {
r = r.concat(makeDERTaggedData(1, arrayToDERSet(this.crls)));
}
r = r.concat(arrayToDERSet(this.signerInfos));
return makeDERSequence(r);
};
return SignedData;
}());
export default SignedData;

View File

@@ -0,0 +1,15 @@
import DERObject from './DERObject.js';
import IssuerAndSerialNumber from './IssuerAndSerialNumber.js';
import AlgorithmIdentifier from './AlgorithmIdentifier.js';
import Attribute from './Attribute.js';
export default class SignerInfo implements DERObject {
version: number;
issuerAndSerialNumber: IssuerAndSerialNumber;
digestAlgorithm: AlgorithmIdentifier;
digestEncryptionAlgorithm: AlgorithmIdentifier;
encryptedDigest: Uint8Array;
authenticatedAttributes?: Attribute[] | undefined;
unauthenticatedAttributes?: Attribute[] | undefined;
constructor(version: number, issuerAndSerialNumber: IssuerAndSerialNumber, digestAlgorithm: AlgorithmIdentifier, digestEncryptionAlgorithm: AlgorithmIdentifier, encryptedDigest: Uint8Array, authenticatedAttributes?: Attribute[] | undefined, unauthenticatedAttributes?: Attribute[] | undefined);
toDER(): number[];
}

View File

@@ -0,0 +1,37 @@
import { makeDERSequence, arrayToDERSet, makeDEROctetString, } from './derUtil.js';
var SignerInfo = /** @class */ (function () {
function SignerInfo(version, issuerAndSerialNumber, digestAlgorithm, digestEncryptionAlgorithm, encryptedDigest, authenticatedAttributes, unauthenticatedAttributes) {
this.version = version;
this.issuerAndSerialNumber = issuerAndSerialNumber;
this.digestAlgorithm = digestAlgorithm;
this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
this.encryptedDigest = encryptedDigest;
this.authenticatedAttributes = authenticatedAttributes;
this.unauthenticatedAttributes = unauthenticatedAttributes;
}
SignerInfo.prototype.toDER = function () {
var r = [0x02, 0x01, this.version & 0xff]
.concat(this.issuerAndSerialNumber.toDER())
.concat(this.digestAlgorithm.toDER());
if (this.authenticatedAttributes &&
this.authenticatedAttributes.length > 0) {
var a = arrayToDERSet(this.authenticatedAttributes);
// [0] IMPLICIT
a[0] = 0xa0;
r = r.concat(a);
}
r = r
.concat(this.digestEncryptionAlgorithm.toDER())
.concat(makeDEROctetString(this.encryptedDigest));
if (this.unauthenticatedAttributes &&
this.unauthenticatedAttributes.length > 0) {
var u = arrayToDERSet(this.unauthenticatedAttributes);
// [1] IMPLICIT
u[0] = 0xa1;
r = r.concat(u);
}
return makeDERSequence(r);
};
return SignerInfo;
}());
export default SignerInfo;

View File

@@ -0,0 +1,21 @@
import ContentInfo from './ContentInfo.js';
import DigestInfo from './DigestInfo.js';
import ObjectIdentifier from './ObjectIdentifier.js';
import DERObject from './DERObject.js';
export declare const SPC_INDIRECT_DATA_OBJID: ObjectIdentifier;
export declare class SpcAttributeTypeAndOptionalValue<TValue extends DERObject = DERObject> {
type: ObjectIdentifier;
value: TValue;
constructor(type: ObjectIdentifier, value: TValue);
toDER(): number[];
}
export default class SpcIndirectDataContent implements DERObject {
data: SpcAttributeTypeAndOptionalValue;
messageDigest: DigestInfo;
constructor(data: SpcAttributeTypeAndOptionalValue, messageDigest: DigestInfo);
toDER(): number[];
toDERWithoutHeader(): number[];
}
export declare class SpcIndirectDataContentInfo extends ContentInfo<SpcIndirectDataContent> {
constructor(content: SpcIndirectDataContent);
}

View File

@@ -0,0 +1,54 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import ContentInfo from './ContentInfo.js';
import ObjectIdentifier from './ObjectIdentifier.js';
import { makeDERSequence } from './derUtil.js';
// prettier-ignore
export var SPC_INDIRECT_DATA_OBJID = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 2, 1, 4]);
var SpcAttributeTypeAndOptionalValue = /** @class */ (function () {
function SpcAttributeTypeAndOptionalValue(type, value) {
this.type = type;
this.value = value;
}
SpcAttributeTypeAndOptionalValue.prototype.toDER = function () {
return makeDERSequence(this.type.toDER().concat(this.value.toDER()));
};
return SpcAttributeTypeAndOptionalValue;
}());
export { SpcAttributeTypeAndOptionalValue };
var SpcIndirectDataContent = /** @class */ (function () {
function SpcIndirectDataContent(data, messageDigest) {
this.data = data;
this.messageDigest = messageDigest;
}
SpcIndirectDataContent.prototype.toDER = function () {
return makeDERSequence(this.toDERWithoutHeader());
};
// this is used for calculating 'messageDigest'
SpcIndirectDataContent.prototype.toDERWithoutHeader = function () {
return this.data.toDER().concat(this.messageDigest.toDER());
};
return SpcIndirectDataContent;
}());
export default SpcIndirectDataContent;
var SpcIndirectDataContentInfo = /** @class */ (function (_super) {
__extends(SpcIndirectDataContentInfo, _super);
function SpcIndirectDataContentInfo(content) {
return _super.call(this, SPC_INDIRECT_DATA_OBJID, content) || this;
}
return SpcIndirectDataContentInfo;
}(ContentInfo));
export { SpcIndirectDataContentInfo };

View File

@@ -0,0 +1,16 @@
import DERObject from './DERObject.js';
/**
* Abstract data SpcLink. Must use either `SpcLinkUrl` or `SpcLinkFile` instead.
*/
export default abstract class SpcLink implements DERObject {
private readonly tag;
value: DERObject;
constructor(tag: number, value: DERObject);
toDER(): number[];
}
export declare class SpcLinkUrl extends SpcLink {
constructor(url: string);
}
export declare class SpcLinkFile extends SpcLink {
constructor(file: string);
}

View File

@@ -0,0 +1,62 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { RawDERObject } from './DERObject.js';
import { makeDERTaggedData, makeDERIA5String, makeDERBMPString, } from './derUtil.js';
/**
* Abstract data SpcLink. Must use either `SpcLinkUrl` or `SpcLinkFile` instead.
*/
var SpcLink = /** @class */ (function () {
function SpcLink(tag, value) {
this.tag = tag;
this.value = value;
}
SpcLink.prototype.toDER = function () {
var v = this.value.toDER();
if (this.tag === 2) {
// EXPLICIT
return makeDERTaggedData(this.tag, v);
}
else {
// IMPLICIT
v[0] = 0x80 + this.tag;
return v;
}
};
return SpcLink;
}());
export default SpcLink;
var SpcLinkUrl = /** @class */ (function (_super) {
__extends(SpcLinkUrl, _super);
function SpcLinkUrl(url) {
return _super.call(this, 0, new RawDERObject(makeDERIA5String(url))) || this;
}
return SpcLinkUrl;
}(SpcLink));
export { SpcLinkUrl };
// moniker is not supported now (currently unused)
var SpcLinkFile = /** @class */ (function (_super) {
__extends(SpcLinkFile, _super);
function SpcLinkFile(file) {
var _this = this;
var v = makeDERBMPString(file);
// [0] IMPLICIT BMPSTRING
v[0] = 0x80;
_this = _super.call(this, 2, new RawDERObject(v)) || this;
return _this;
}
return SpcLinkFile;
}(SpcLink));
export { SpcLinkFile };

View File

@@ -0,0 +1,19 @@
import DERObject from './DERObject.js';
import ObjectIdentifier from './ObjectIdentifier.js';
import { SpcAttributeTypeAndOptionalValue } from './SpcIndirectDataContent.js';
import SpcLink from './SpcLink.js';
export declare const SPC_PE_IMAGE_DATA_OBJID: ObjectIdentifier;
export declare const enum SpcPeImageFlags {
IncludeResources = 0,
IncludeDebugInfo = 1,
IncludeImportAddressTable = 2
}
export default class SpcPeImageData implements DERObject {
flags: SpcPeImageFlags;
file: SpcLink;
constructor(flags: SpcPeImageFlags, file: SpcLink);
toDER(): number[];
}
export declare class SpcPeImageAttributeTypeAndOptionalValue extends SpcAttributeTypeAndOptionalValue<SpcPeImageData> {
constructor(value: SpcPeImageData);
}

View File

@@ -0,0 +1,41 @@
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import ObjectIdentifier from './ObjectIdentifier.js';
import { SpcAttributeTypeAndOptionalValue } from './SpcIndirectDataContent.js';
import { makeDERSequence, makeDERTaggedData } from './derUtil.js';
// prettier-ignore
export var SPC_PE_IMAGE_DATA_OBJID = new ObjectIdentifier([1, 3, 6, 1, 4, 1, 311, 2, 1, 15]);
var SpcPeImageData = /** @class */ (function () {
function SpcPeImageData(flags, file) {
this.flags = flags;
this.file = file;
}
SpcPeImageData.prototype.toDER = function () {
return makeDERSequence([0x03, 0x01, this.flags & 0xff].concat(
// undocumented -- SpcLink must be tagged
makeDERTaggedData(0, this.file.toDER())));
};
return SpcPeImageData;
}());
export default SpcPeImageData;
var SpcPeImageAttributeTypeAndOptionalValue = /** @class */ (function (_super) {
__extends(SpcPeImageAttributeTypeAndOptionalValue, _super);
function SpcPeImageAttributeTypeAndOptionalValue(value) {
return _super.call(this, SPC_PE_IMAGE_DATA_OBJID, value) || this;
}
return SpcPeImageAttributeTypeAndOptionalValue;
}(SpcAttributeTypeAndOptionalValue));
export { SpcPeImageAttributeTypeAndOptionalValue };

View File

@@ -0,0 +1,8 @@
import DERObject from './DERObject.js';
export declare function makeDERLength(length: number): number[];
export declare function makeDERIA5String(text: string): number[];
export declare function makeDERBMPString(text: string): number[];
export declare function makeDEROctetString(bin: number[] | Uint8Array): number[];
export declare function makeDERTaggedData(tag: number, body: number[]): number[];
export declare function makeDERSequence(body: number[]): number[];
export declare function arrayToDERSet(items: Array<DERObject | number[]>): number[];

View File

@@ -0,0 +1,56 @@
export function makeDERLength(length) {
if (length < 0x80) {
return [length];
}
var r = [];
while (true) {
r.push(length & 0xff);
if (length < 0x100) {
break;
}
length >>= 8;
}
r.push(0x80 + r.length);
return r.reverse();
}
export function makeDERIA5String(text) {
// convert to char-code array and filter to [0-127]
var r = [].map
.call(text, function (c) { return c.charCodeAt(0); })
.filter(function (n) { return n < 128; });
return [0x16].concat(makeDERLength(r.length)).concat(r);
}
export function makeDERBMPString(text) {
// convert to char-code array
// NOTE: In ECMAScript `charCodeAt` returns surrogate pair for >=0x10000 codes,
// and surrogate pair is valid for BMPString data
var r = [].map.call(text, function (c) { return c.charCodeAt(0); });
var ua = new Uint8Array(r.length * 2);
var dv = new DataView(ua.buffer);
// store codes as big-endian
r.forEach(function (v, i) {
dv.setUint16(i * 2, v, false);
});
return [0x1e].concat(makeDERLength(ua.length)).concat(
// convert Uint8Array to number[] (not using spread operator)
[].slice.call(ua));
}
export function makeDEROctetString(bin) {
if (!(bin instanceof Array)) {
// convert Uint8Array to number[] (not using spread operator)
bin = [].slice.call(bin);
}
return [0x04].concat(makeDERLength(bin.length)).concat(bin);
}
export function makeDERTaggedData(tag, body) {
return [0xa0 + tag].concat(makeDERLength(body.length)).concat(body);
}
export function makeDERSequence(body) {
return [0x30].concat(makeDERLength(body.length)).concat(body);
}
export function arrayToDERSet(items) {
var r = items.reduce(function (prev, item) {
return prev.concat(item instanceof Array ? item : item.toDER());
}, []);
return [0x31].concat(makeDERLength(r.length)).concat(r);
}

View File

@@ -0,0 +1,13 @@
import { NtExecutable } from 'pe-library';
import SignerObject, { DigestAlgorithmType, EncryptionAlgorithmType } from './SignerObject.js';
/**
* Generates the executable binary data with signed info.
* This function is like an extension of `generate` method of `NtExecutable`.
* @param executable a valid instance of `NtExecutable`
* @param signer user-defined `SignerObject` instance for signing
* @param alignment alignment value for placing certificate data
* (using `executable.getFileAlignment()` if omitted)
* @return Promise-like (Thenable) object which will resolve with generated executable binary
*/
export declare function generateExecutableWithSign(executable: NtExecutable, signer: SignerObject, alignment?: number): PromiseLike<ArrayBuffer>;
export { SignerObject, DigestAlgorithmType, EncryptionAlgorithmType };

View File

@@ -0,0 +1,396 @@
// refs.
// - Windows Authenticode Portable Executable Signature Format
// https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/authenticode_pe.docx
// - RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5
// https://tools.ietf.org/html/rfc2315
// - RFC 3280 - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
// https://tools.ietf.org/html/rfc3280
// - Object IDs associated with Microsoft cryptography
// https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography
// - OID repository
// http://oid-info.com/
// - RFC 3161 - Internet X.509 Public Key Infrastructure Time-Stamp Protocol (TSP)
// https://tools.ietf.org/html/rfc3161
// - mono/AuthenticodeDeformatter.cs
// https://github.com/mono/mono/blob/master/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { Format, calculateCheckSumForPE } from 'pe-library';
import { allocatePartialBinary, cloneToArrayBuffer, copyBuffer, roundUp, } from '../util/functions.js';
import { certBinToCertificatesDER, pickIssuerAndSerialNumberDERFromCert, toUint8Array, } from './certUtil.js';
import AlgorithmIdentifier from './data/AlgorithmIdentifier.js';
import CertificateDataRoot from './data/CertificateDataRoot.js';
import { RawDERObject } from './data/DERObject.js';
import DigestInfo from './data/DigestInfo.js';
import IssuerAndSerialNumber from './data/IssuerAndSerialNumber.js';
import * as KnownOids from './data/KnownOids.js';
import SignedData from './data/SignedData.js';
import SignerInfo from './data/SignerInfo.js';
import SpcIndirectDataContent, { SpcIndirectDataContentInfo, SPC_INDIRECT_DATA_OBJID, } from './data/SpcIndirectDataContent.js';
import SpcPeImageData, { SpcPeImageAttributeTypeAndOptionalValue, } from './data/SpcPeImageData.js';
import { SpcLinkFile } from './data/SpcLink.js';
import Attribute from './data/Attribute.js';
import { arrayToDERSet, makeDEROctetString, makeDERSequence, } from './data/derUtil.js';
import ContentInfo from './data/ContentInfo.js';
import ObjectIdentifier from './data/ObjectIdentifier.js';
import { createTimestampRequest, pickSignedDataFromTimestampResponse, } from './timestamp.js';
function makeSimpleIterator(data) {
var done = false;
return {
next: function () {
if (done) {
return {
done: true,
value: undefined,
};
}
else {
done = true;
return {
done: false,
value: data,
};
}
},
};
}
function validateSignerObject(signer) {
if (!signer.encryptData && !signer.signData) {
throw new Error('Signer object must implement either `encryptData` or `signData`.');
}
}
function calculateExecutableDigest(executable, signer, alignment) {
function inner() {
var checkSumOffset, certificateTableOffset, rawHeader, targetSections, sectionCount, sectionStartOffset, sectionEndOffset, sectionHeadersSize, secHeader, secArray_1, off, _i, targetSections_1, section, exData, alignedLength, diff;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
checkSumOffset = executable.dosHeader.newHeaderAddress + 88;
certificateTableOffset = executable.dosHeader.newHeaderAddress +
executable.newHeader.getDataDirectoryOffset() +
Format.ImageDataDirectoryArray.itemSize *
Format.ImageDirectoryEntry.Certificate;
rawHeader = executable.getRawHeader();
targetSections = executable.getAllSections();
sectionCount = targetSections.length;
sectionStartOffset = rawHeader.byteLength;
sectionEndOffset = roundUp(sectionStartOffset +
sectionCount * Format.ImageSectionHeaderArray.itemSize, executable.getFileAlignment());
sectionHeadersSize = sectionEndOffset - sectionStartOffset;
secHeader = new ArrayBuffer(sectionHeadersSize);
{
secArray_1 = Format.ImageSectionHeaderArray.from(secHeader, sectionCount);
targetSections.forEach(function (sec, i) {
secArray_1.set(i, sec.info);
});
}
// pick from head to immediately before checksum
return [4 /*yield*/, allocatePartialBinary(rawHeader, 0, checkSumOffset)];
case 1:
// pick from head to immediately before checksum
_a.sent();
// pick from the end of checksum to immediately before 'Certificate Table' header
return [4 /*yield*/, allocatePartialBinary(rawHeader, checkSumOffset + 4, certificateTableOffset - (checkSumOffset + 4))];
case 2:
// pick from the end of checksum to immediately before 'Certificate Table' header
_a.sent();
off = certificateTableOffset +
Format.ImageDataDirectoryArray.itemSize;
return [4 /*yield*/, allocatePartialBinary(executable.getRawHeader(), off, executable.getTotalHeaderSize() - off)];
case 3:
_a.sent();
// pick section header
return [4 /*yield*/, secHeader];
case 4:
// pick section header
_a.sent();
_i = 0, targetSections_1 = targetSections;
_a.label = 5;
case 5:
if (!(_i < targetSections_1.length)) return [3 /*break*/, 8];
section = targetSections_1[_i];
if (!section.data) return [3 /*break*/, 7];
return [4 /*yield*/, section.data];
case 6:
_a.sent();
_a.label = 7;
case 7:
_i++;
return [3 /*break*/, 5];
case 8:
exData = executable.getExtraData();
if (!(exData !== null)) return [3 /*break*/, 11];
return [4 /*yield*/, exData];
case 9:
_a.sent();
alignedLength = roundUp(exData.byteLength, alignment);
diff = alignedLength - exData.byteLength;
if (!(diff !== 0)) return [3 /*break*/, 11];
return [4 /*yield*/, new Uint8Array(diff).buffer];
case 10:
_a.sent();
_a.label = 11;
case 11: return [2 /*return*/];
}
});
}
return signer.digestData(inner());
}
function getAlgorithmIdentifierObject(type) {
if (typeof type !== 'string') {
return new AlgorithmIdentifier(new ObjectIdentifier(type));
}
switch (type) {
case 'sha1':
case 'SHA1':
return new AlgorithmIdentifier(KnownOids.OID_SHA1_NO_SIGN);
case 'sha256':
case 'SHA256':
return new AlgorithmIdentifier(KnownOids.OID_SHA256_NO_SIGN);
case 'sha384':
case 'SHA384':
return new AlgorithmIdentifier(KnownOids.OID_SHA384_NO_SIGN);
case 'sha512':
case 'SHA512':
return new AlgorithmIdentifier(KnownOids.OID_SHA512_NO_SIGN);
case 'sha224':
case 'SHA224':
return new AlgorithmIdentifier(KnownOids.OID_SHA224_NO_SIGN);
case 'sha512-224':
case 'SHA512-224':
return new AlgorithmIdentifier(KnownOids.OID_SHA512_224_NO_SIGN);
case 'sha512-256':
case 'SHA512-256':
return new AlgorithmIdentifier(KnownOids.OID_SHA512_256_NO_SIGN);
case 'sha3-224':
case 'SHA3-224':
return new AlgorithmIdentifier(KnownOids.OID_SHA3_224_NO_SIGN);
case 'sha3-256':
case 'SHA3-256':
return new AlgorithmIdentifier(KnownOids.OID_SHA3_256_NO_SIGN);
case 'sha3-384':
case 'SHA3-384':
return new AlgorithmIdentifier(KnownOids.OID_SHA3_384_NO_SIGN);
case 'sha3-512':
case 'SHA3-512':
return new AlgorithmIdentifier(KnownOids.OID_SHA3_512_NO_SIGN);
case 'shake128':
case 'SHAKE128':
return new AlgorithmIdentifier(KnownOids.OID_SHAKE128_NO_SIGN);
case 'shake256':
case 'SHAKE256':
return new AlgorithmIdentifier(KnownOids.OID_SHAKE256_NO_SIGN);
default:
throw new Error('Invalid or unsupported digest algorithm');
}
}
function doSign(signer, digestAlgorithm, dataIterator) {
if (signer.signData) {
return signer.signData(dataIterator);
}
else {
return signer.digestData(dataIterator).then(function (digestAttributes) {
// encrypting DigestInfo with digest of 'attributes' set
var digestInfoBin = new Uint8Array(new DigestInfo(digestAlgorithm, digestAttributes).toDER()).buffer;
// (eencryptData should be defined here)
return signer.encryptData(makeSimpleIterator(digestInfoBin));
});
}
}
/**
* Generates the executable binary data with signed info.
* This function is like an extension of `generate` method of `NtExecutable`.
* @param executable a valid instance of `NtExecutable`
* @param signer user-defined `SignerObject` instance for signing
* @param alignment alignment value for placing certificate data
* (using `executable.getFileAlignment()` if omitted)
* @return Promise-like (Thenable) object which will resolve with generated executable binary
*/
export function generateExecutableWithSign(executable, signer, alignment) {
validateSignerObject(signer);
var certAlignment;
if (typeof alignment === 'number') {
if (alignment <= 0) {
throw new Error('Invalid alignment value');
}
certAlignment = alignment;
}
else {
certAlignment = executable.getFileAlignment();
}
var digestAlgorithm = getAlgorithmIdentifierObject(signer.getDigestAlgorithm());
var digestEncryptionAlgorithm;
var a = signer.getEncryptionAlgorithm();
if (typeof a !== 'string') {
digestEncryptionAlgorithm = new AlgorithmIdentifier(new ObjectIdentifier(a));
}
else {
switch (a) {
case 'rsa':
case 'RSA':
digestEncryptionAlgorithm = new AlgorithmIdentifier(KnownOids.OID_RSA);
break;
case 'dsa':
case 'DSA':
digestEncryptionAlgorithm = new AlgorithmIdentifier(KnownOids.OID_DSA);
break;
default:
throw new Error('Invalid or unsupported digest encryption algorithm');
}
}
// (for compatibility)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
var cert = signer.getCertificateData
? signer.getCertificateData()
: signer.getPublicKeyData();
var _a = pickIssuerAndSerialNumberDERFromCert(cert), issuer = _a[0], serialNumber = _a[1];
return (
// calculate digest
calculateExecutableDigest(executable, signer, certAlignment)
// make content, content's digest, and sign
.then(function (digest) {
var content = new SpcIndirectDataContent(new SpcPeImageAttributeTypeAndOptionalValue(new SpcPeImageData(0 /* IncludeResources */, new SpcLinkFile(''))), new DigestInfo(digestAlgorithm, digest));
return (signer
.digestData(makeSimpleIterator(new Uint8Array(content.toDERWithoutHeader())
.buffer))
// make sign
.then(function (contentDigest) {
var attributes = [
new Attribute(KnownOids.OID_SPC_SP_OPUS_INFO_OBJID,
// (SpcSpOpusInfo) null sequence
[new RawDERObject([0x30, 0x00])]),
new Attribute(KnownOids.OID_CONTENT_TYPE, [
SPC_INDIRECT_DATA_OBJID,
]),
new Attribute(KnownOids.OID_SPC_STATEMENT_TYPE_OBJID, [
new RawDERObject(makeDERSequence(KnownOids.OID_SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID.toDER())),
]),
new Attribute(KnownOids.OID_MESSAGE_DIGEST, [
new RawDERObject(makeDEROctetString(toUint8Array(contentDigest))),
]),
];
// get digest of 'attributes' set
var attrBin = new Uint8Array(arrayToDERSet(attributes)).buffer;
return doSign(signer, digestAlgorithm, makeSimpleIterator(attrBin)).then(function (signed) {
return [content, attributes, signed];
});
}));
})
// make cert bin
.then(function (_a) {
var content = _a[0], attributes = _a[1], signed = _a[2];
var signerInfo = new SignerInfo(
// version
1,
// issuerAndSerialNumber
new IssuerAndSerialNumber(new RawDERObject(issuer), new RawDERObject(serialNumber)),
// digestAlgorithm
digestAlgorithm,
// digestEncryptionAlgorithm
digestEncryptionAlgorithm,
// encryptedDigest
toUint8Array(signed),
// authenticatedAttributes
attributes);
if (!signer.timestampData) {
return [content, signerInfo];
}
// timestamp
return (signer
// make digest of encrypted data for make timestamp
.digestData(makeSimpleIterator(cloneToArrayBuffer(signed)))
.then(function (digestEncryptedBase) {
var digestEncrypted = createTimestampRequest(digestEncryptedBase, digestAlgorithm);
// request timestamp
return signer.timestampData(digestEncrypted).then(function (timestamp) {
// pick up signedData
var timestampSignedData = pickSignedDataFromTimestampResponse(timestamp);
// add timestamp to 'unauthenticatedAttributes'
signerInfo.unauthenticatedAttributes = [
new Attribute(KnownOids.OID_RFC3161_COUNTER_SIGNATURE, [
new ContentInfo(KnownOids.OID_SIGNED_DATA, new RawDERObject(toUint8Array(timestampSignedData))),
]),
];
return [content, signerInfo];
});
}));
})
.then(function (_a) {
var content = _a[0], signerInfo = _a[1];
// make certificate data
var root = new CertificateDataRoot(KnownOids.OID_SIGNED_DATA, new SignedData(
// version
1,
// digestAlgorithms
[digestAlgorithm],
// contentInfo
new SpcIndirectDataContentInfo(content),
// signerInfos
[signerInfo],
// certificates
certBinToCertificatesDER(cert)));
var certBin = new Uint8Array(root.toDER());
var resultBin = new ArrayBuffer(8 + certBin.length);
// make WIN_CERTIFICATE
var resultView = new DataView(resultBin);
// dwLength
resultView.setUint32(0, certBin.length + 8, true);
// wRevision : 0x0200 (revision 2)
resultView.setUint16(4, 0x200, true);
// wCertificateType : 0x0002
resultView.setUint16(6, 0x2, true);
copyBuffer(resultBin, 8, certBin, 0, certBin.byteLength);
return resultBin;
})
.then(function (certBin) {
var alignedSize = roundUp(certBin.byteLength, certAlignment);
// NOTE: The certificate data must follow the extra data.
// To achieve this, the another size between them must be added to the padding size.
// (The extra data may not be aligned, but the certificate data should be aligned.)
var paddingSize = alignedSize;
var exData = executable.getExtraData();
if (exData !== null) {
var diffSize = roundUp(exData.byteLength, certAlignment) -
exData.byteLength;
paddingSize += diffSize;
}
var newBin = executable.generate(paddingSize);
var certOffset = newBin.byteLength - alignedSize;
var dirArray = Format.ImageDataDirectoryArray.from(newBin, executable.dosHeader.newHeaderAddress +
executable.newHeader.getDataDirectoryOffset());
dirArray.set(Format.ImageDirectoryEntry.Certificate, {
size: alignedSize,
virtualAddress: certOffset,
});
// recalculate checksum
calculateCheckSumForPE(newBin, true);
// write Certificate section data
copyBuffer(newBin, certOffset, certBin, 0, certBin.byteLength);
return newBin;
}));
}

View File

@@ -0,0 +1,3 @@
import AlgorithmIdentifier from './data/AlgorithmIdentifier.js';
export declare function createTimestampRequest(data: ArrayBuffer | ArrayBufferView, algorithmIdentifier: AlgorithmIdentifier): ArrayBufferLike;
export declare function pickSignedDataFromTimestampResponse(data: ArrayBuffer | ArrayBufferView): ArrayBuffer;

View File

@@ -0,0 +1,117 @@
import { allocatePartialBinary } from '../util/functions.js';
import { calculateDERLength, toUint8Array } from './certUtil.js';
import { makeDEROctetString, makeDERSequence } from './data/derUtil.js';
import { OID_SIGNED_DATA } from './data/KnownOids.js';
export function createTimestampRequest(data, algorithmIdentifier) {
return new Uint8Array(makeDERSequence(
// version
[0x2, 0x1, 0x1]
// messageImprint
.concat(makeDERSequence(algorithmIdentifier
.toDER()
.concat(makeDEROctetString(toUint8Array(data)))))
// certReq
.concat([0x01, 0x01, 0xff]))).buffer;
}
export function pickSignedDataFromTimestampResponse(data) {
var _a, _b, _c, _d, _e, _f;
var ub = toUint8Array(data);
if (ub.length < 2 || ub[0] !== 0x30) {
throw new Error('Invalid or unexpected timestamp response');
}
var len;
var offset;
_a = calculateDERLength(ub, 1), len = _a[0], offset = _a[1];
if (len > ub.length - offset) {
throw new Error('Invalid or unexpected timestamp response (insufficient buffer)');
}
var dataLast = offset + len;
// status PKIStatusInfo
if (ub[offset] !== 0x30) {
throw new Error('Invalid or unexpected timestamp response (no PKIStatusInfo)');
}
_b = calculateDERLength(ub, offset + 1), len = _b[0], offset = _b[1];
if (offset >= dataLast) {
throw new Error('Invalid or unexpected timestamp response (invalid length for PKIStatusInfo)');
}
var timeStampTokenOffset = offset + len;
// PKIStatusInfo.status
if (ub[offset] !== 0x2 || ub[offset + 1] !== 0x1) {
throw new Error('Invalid or unexpected timestamp response (invalid PKIStatusInfo.status)');
}
var status = ub[offset + 2];
switch (status) {
case 0: // granted
case 1: // grantedWithMods
break;
case 2: // rejection
case 3: // waiting
case 4: // revocationWarning
case 5: /* revocationNotification */ {
var msg = "Timestamp response has error status " + status;
// PKIStatusInfo.statusString
if (offset + 3 < timeStampTokenOffset && ub[offset + 3] === 0x30) {
_c = calculateDERLength(ub, offset + 4), len = _c[0], offset = _c[1];
if (offset + len <= timeStampTokenOffset &&
ub[offset] === 0xc) {
_d = calculateDERLength(ub, offset + 1), len = _d[0], offset = _d[1];
if (offset + len <= timeStampTokenOffset) {
var statusString =
// pick UTF8String body
[].slice
.call(ub, offset, offset + len)
// map 0x20<=x<=0x7e values to chars, and other values to '%xx' to be parsed by decodeURIComponent
.map(function (val) {
if (val >= 0x20 && val <= 0x7e) {
return String.fromCharCode(val);
}
else {
var s = val.toString(16);
if (s.length === 1) {
s = '0' + s;
}
return '%' + s;
}
})
.join('');
msg += ', text = ' + decodeURIComponent(statusString);
}
}
}
throw new Error(msg);
}
default:
throw new Error("Unexpected PKIStatusInfo.status: " + (status !== null && status !== void 0 ? status : '(unknown)'));
}
// TimeStampToken ::= ContentInfo
if (timeStampTokenOffset + 1 >= dataLast ||
ub[timeStampTokenOffset] !== 0x30) {
throw new Error('Invalid or unexpected timestamp response (no TimeStampToken)');
}
_e = calculateDERLength(ub, timeStampTokenOffset + 1), len = _e[0], offset = _e[1];
if (offset + len > dataLast) {
throw new Error('Invalid or unexpected timestamp response (insufficient data for TimeStampToken)');
}
// ContentInfo.contentType
var signedDataOid = OID_SIGNED_DATA.toDER();
if (ub[offset] !== 0x6) {
throw new Error('Invalid or unexpected timestamp response (no contentType in TimeStampToken)');
}
for (var i = 0; i < signedDataOid.length; ++i) {
if (ub[offset + i] !== signedDataOid[i]) {
throw new Error('Invalid or unexpected timestamp response (unexpected TimeStampToken.contentType octet)');
}
}
// ContentInfo.content
offset += signedDataOid.length;
// [0] IMPLICIT
if (ub[offset] !== 0xa0) {
throw new Error('Invalid or unexpected timestamp response (no content in TimeStampToken)');
}
_f = calculateDERLength(ub, offset + 1), len = _f[0], offset = _f[1];
if (offset + len > dataLast) {
throw new Error('Invalid or unexpected timestamp response (invalid length for TimeStampToken.content)');
}
// return content data (=== SignedData)
return allocatePartialBinary(ub, offset, len);
}

View File

@@ -0,0 +1,16 @@
/// <reference lib="dom" />
export declare function cloneObject<T extends object>(object: Readonly<T>): T;
export declare function cloneObject<T extends object>(object: T): T;
export declare function createDataView(bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): DataView;
export declare function roundUp(val: number, align: number): number;
export declare function copyBuffer(dest: ArrayBuffer | ArrayBufferView, destOffset: number, src: ArrayBuffer | ArrayBufferView, srcOffset: number, length: number): void;
export declare function allocatePartialBinary(binBase: ArrayBuffer | ArrayBufferView, offset: number, length: number): ArrayBuffer;
export declare function cloneToArrayBuffer(binBase: ArrayBuffer | ArrayBufferView): ArrayBuffer;
export declare function readInt32WithLastOffset(view: DataView, offset: number, last: number): number;
export declare function readUint8WithLastOffset(view: DataView, offset: number, last: number): number;
export declare function readUint16WithLastOffset(view: DataView, offset: number, last: number): number;
export declare function readUint32WithLastOffset(view: DataView, offset: number, last: number): number;
export declare function binaryToString(bin: ArrayBuffer | ArrayBufferView): string;
export declare function stringToBinary(string: string): ArrayBuffer;
export declare function getFixedString(view: DataView, offset: number, length: number): string;
export declare function setFixedString(view: DataView, offset: number, length: number, text: string): void;

View File

@@ -0,0 +1,235 @@
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference lib='dom' />
export function cloneObject(object) {
var r = {};
Object.keys(object).forEach(function (key) {
r[key] = object[key];
});
return r;
}
/* eslint-enable @typescript-eslint/ban-types */
export function createDataView(bin, byteOffset, byteLength) {
if ('buffer' in bin) {
var newOffset = bin.byteOffset;
var newLength = bin.byteLength;
if (typeof byteOffset !== 'undefined') {
newOffset += byteOffset;
newLength -= byteOffset;
}
if (typeof byteLength !== 'undefined') {
newLength = byteLength;
}
return new DataView(bin.buffer, newOffset, newLength);
}
else {
return new DataView(bin, byteOffset, byteLength);
}
}
export function roundUp(val, align) {
return Math.floor((val + align - 1) / align) * align;
}
export function copyBuffer(dest, destOffset, src, srcOffset, length) {
var ua8Dest = 'buffer' in dest
? new Uint8Array(dest.buffer, dest.byteOffset + (destOffset || 0), length)
: new Uint8Array(dest, destOffset, length);
var ua8Src = 'buffer' in src
? new Uint8Array(src.buffer, src.byteOffset + (srcOffset || 0), length)
: new Uint8Array(src, srcOffset, length);
ua8Dest.set(ua8Src);
}
export function allocatePartialBinary(binBase, offset, length) {
var b = new ArrayBuffer(length);
copyBuffer(b, 0, binBase, offset, length);
return b;
}
export function cloneToArrayBuffer(binBase) {
if ('buffer' in binBase) {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase.buffer, binBase.byteOffset, binBase.byteLength));
return b;
}
else {
var b = new ArrayBuffer(binBase.byteLength);
new Uint8Array(b).set(new Uint8Array(binBase));
return b;
}
}
export function readInt32WithLastOffset(view, offset, last) {
return offset + 4 <= last ? view.getInt32(offset, true) : 0;
}
export function readUint8WithLastOffset(view, offset, last) {
return offset < last ? view.getUint8(offset) : 0;
}
export function readUint16WithLastOffset(view, offset, last) {
return offset + 2 <= last ? view.getUint16(offset, true) : 0;
}
export function readUint32WithLastOffset(view, offset, last) {
return offset + 4 <= last ? view.getUint32(offset, true) : 0;
}
export function binaryToString(bin) {
if (typeof TextDecoder !== 'undefined') {
var dec = new TextDecoder();
return dec.decode(bin);
}
else if (typeof Buffer !== 'undefined') {
var b = void 0;
if ('buffer' in bin) {
b = Buffer.from(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
b = Buffer.from(bin);
}
return b.toString('utf8');
}
else {
var view = void 0;
if ('buffer' in bin) {
view = new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
view = new Uint8Array(bin);
}
if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < view.length; ++i) {
var c = view[i];
s += String.fromCharCode(c);
}
return s;
}
}
}
export function stringToBinary(string) {
if (typeof TextEncoder !== 'undefined') {
var enc = new TextEncoder();
return cloneToArrayBuffer(enc.encode(string));
}
else if (typeof Buffer !== 'undefined') {
return cloneToArrayBuffer(Buffer.from(string, 'utf8'));
}
else if (typeof encodeURIComponent !== 'undefined') {
var data = encodeURIComponent(string);
var len = 0;
for (var i = 0; i < data.length; ++len) {
var c = data.charCodeAt(i);
if (c === 37) {
i += 3;
}
else {
++i;
}
}
var bin = new ArrayBuffer(len);
var view = new Uint8Array(bin);
for (var i = 0, j = 0; i < data.length; ++j) {
var c = data.charCodeAt(i);
if (c === 37) {
var n = parseInt(data.substring(i + 1, i + 3), 16);
view[j] = n;
i += 3;
}
else {
view[j] = c;
++i;
}
}
return bin;
}
else {
var bin = new ArrayBuffer(string.length);
new Uint8Array(bin).set([].map.call(string, function (c) {
return c.charCodeAt(0);
}));
return bin;
}
}
export function getFixedString(view, offset, length) {
var actualLen = 0;
for (var i = 0; i < length; ++i) {
if (view.getUint8(offset + i) === 0) {
break;
}
++actualLen;
}
if (typeof Buffer !== 'undefined') {
return Buffer.from(view.buffer, view.byteOffset + offset, actualLen).toString('utf8');
}
else if (typeof decodeURIComponent !== 'undefined') {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
if (c < 16) {
s += '%0' + c.toString(16);
}
else {
s += '%' + c.toString(16);
}
}
return decodeURIComponent(s);
}
else {
var s = '';
for (var i = 0; i < actualLen; ++i) {
var c = view.getUint8(offset + i);
s += String.fromCharCode(c);
}
return s;
}
}
export function setFixedString(view, offset, length, text) {
if (typeof Buffer !== 'undefined') {
var u = new Uint8Array(view.buffer, view.byteOffset + offset, length);
// fill by zero
u.set(new Uint8Array(length));
u.set(Buffer.from(text, 'utf8').subarray(0, length));
}
else if (typeof encodeURIComponent !== 'undefined') {
var s = encodeURIComponent(text);
for (var i = 0, j = 0; i < length; ++i) {
if (j >= s.length) {
view.setUint8(i + offset, 0);
}
else {
var c = s.charCodeAt(j);
if (c === 37) {
// '%'
var n = parseInt(s.substr(j + 1, 2), 16);
if (typeof n === 'number' && !isNaN(n)) {
view.setUint8(i + offset, n);
}
else {
view.setUint8(i + offset, 0);
}
j += 3;
}
else {
view.setUint8(i + offset, c);
}
}
}
}
else {
for (var i = 0, j = 0; i < length; ++i) {
if (j >= text.length) {
view.setUint8(i + offset, 0);
}
else {
var c = text.charCodeAt(j);
view.setUint8(i + offset, c & 0xff);
}
}
}
}

View File

@@ -0,0 +1,2 @@
declare const _default: "1.7.2";
export default _default;

View File

@@ -0,0 +1 @@
export default '1.7.2';

View File

@@ -0,0 +1,17 @@
export default interface BitmapInfo {
width: number;
height: number;
planes: number;
bitCount: number;
compression: number;
sizeImage: number;
xPelsPerMeter: number;
yPelsPerMeter: number;
colorUsed: number;
colorImportant: number;
colors: Array<{
r: number;
g: number;
b: number;
}>;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,21 @@
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
/**
* All fields except for 'data' is optional.
* Missing fields are replaced by 'data' values when generating binary.
*/
export interface IconFileItem {
width?: number;
height?: number;
colors?: number;
planes?: number;
bitCount?: number;
data: IconItem | RawIconItem;
}
export default class IconFile {
/** Containing icons */
icons: IconFileItem[];
constructor();
static from(bin: ArrayBuffer | ArrayBufferView): IconFile;
generate(): ArrayBuffer;
}

View File

@@ -0,0 +1,143 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var IconItem_js_1 = require("./IconItem.js");
var RawIconItem_js_1 = require("./RawIconItem.js");
var functions_js_1 = require("../util/functions.js");
function generateEntryBinary(icons) {
var count = icons.length;
/* istanbul ignore if */
if (count > 65535) {
count = 65535;
}
var tmpIcons = icons.map(function (item) {
if (item.data.isIcon()) {
return {
item: item,
bin: item.data.generate(),
offset: 0,
};
}
else {
return {
item: item,
bin: item.data.bin,
offset: 0,
};
}
});
var size = tmpIcons.reduce(function (p, icon) {
icon.offset = p;
return p + icon.bin.byteLength;
}, 6 + 16 * count);
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, 0, true); // reserved
view.setUint16(2, 1, true); // icon type
view.setUint16(4, count, true);
var offset = 6;
tmpIcons.forEach(function (icon) {
var item = icon.item;
var width;
var height;
var colors;
var planes;
var bitCount;
if (item.data.isIcon()) {
var bi = item.data.bitmapInfo;
width =
typeof item.width !== 'undefined'
? item.width
: Math.abs(bi.width);
height =
typeof item.height !== 'undefined'
? item.height
: Math.abs(bi.height / 2);
colors =
typeof item.colors !== 'undefined'
? item.colors
: bi.colorUsed || bi.colors.length;
planes =
typeof item.planes !== 'undefined' ? item.planes : bi.planes;
bitCount =
typeof item.bitCount !== 'undefined'
? item.bitCount
: bi.bitCount;
}
else {
width =
typeof item.width !== 'undefined'
? item.width
: Math.abs(item.data.width);
height =
typeof item.height !== 'undefined'
? item.height
: Math.abs(item.data.height);
colors = typeof item.colors !== 'undefined' ? item.colors : 0;
planes = typeof item.planes !== 'undefined' ? item.planes : 1;
bitCount =
typeof item.bitCount !== 'undefined'
? item.bitCount
: item.data.bitCount;
}
var dataSize = icon.bin.byteLength;
view.setUint8(offset, width >= 256 ? 0 : width);
view.setUint8(offset + 1, height >= 256 ? 0 : height);
view.setUint8(offset + 2, colors >= 256 ? 0 : colors);
view.setUint8(offset + 3, 0);
view.setUint16(offset + 4, planes, true);
view.setUint16(offset + 6, bitCount, true);
view.setUint32(offset + 8, dataSize, true);
view.setUint32(offset + 12, icon.offset, true);
offset += 16;
functions_js_1.copyBuffer(bin, icon.offset, icon.bin, 0, dataSize);
});
return bin;
}
var IconFile = /** @class */ (function () {
function IconFile(bin) {
if (!bin) {
this.icons = [];
return;
}
var view = functions_js_1.createDataView(bin);
var totalSize = view.byteLength;
var icons = [];
/* istanbul ignore else */
if (view.getUint16(2, true) === 1) {
var count = view.getUint16(4, true);
var offset = 6;
for (var i = 0; i < count; ++i) {
var dataSize = functions_js_1.readUint32WithLastOffset(view, offset + 8, totalSize);
var dataOffset = functions_js_1.readUint32WithLastOffset(view, offset + 12, totalSize);
var width = functions_js_1.readUint8WithLastOffset(view, offset, totalSize);
var height = functions_js_1.readUint8WithLastOffset(view, offset + 1, totalSize);
var bitCount = functions_js_1.readUint8WithLastOffset(view, offset + 6, totalSize);
var data = void 0;
if (view.getUint32(dataOffset, true) === 0x28) {
data = IconItem_js_1.default.from(width, height, bin, dataOffset, dataSize);
}
else {
data = RawIconItem_js_1.default.from(bin, width || 256, height || 256, bitCount, dataOffset, dataSize);
}
icons.push({
width: width,
height: height,
colors: functions_js_1.readUint8WithLastOffset(view, offset + 2, totalSize),
planes: functions_js_1.readUint16WithLastOffset(view, offset + 4, totalSize),
bitCount: bitCount,
data: data,
});
offset += 16;
}
}
this.icons = icons;
}
IconFile.from = function (bin) {
return new IconFile(bin);
};
IconFile.prototype.generate = function () {
return generateEntryBinary(this.icons);
};
return IconFile;
}());
exports.default = IconFile;

View File

@@ -0,0 +1,58 @@
import BitmapInfo from './BitmapInfo.js';
export default class IconItem {
/**
* Bitmap header data (`BITMAPINFOHEADER`)
*/
readonly bitmapInfo: BitmapInfo;
/**
* Horizontal size of the icon in pixel (overrides `bitmapInfo.width`).
* If `null` is specified, `bitmapInfo.width` will be used.
*/
width: number | null;
/**
* Vertical size of the icon in pixel (overrides `bitmapInfo.height`).
* If `null` is specified, `bitmapInfo.height` will be used.
*/
height: number | null;
/**
* Bitmap pixel data used for mask
* (the data will be appended immediately after `pixels` when generating icon binary)
*/
masks: ArrayBuffer;
/**
* Bitmap pixel data
*/
private _pixels;
private constructor();
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
get pixels(): ArrayBuffer;
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
set pixels(newValue: ArrayBuffer);
/**
* Generates `IconItem` instance from bitmap data binary.
* @param bin binary data containing the bitmap data
* @param byteOffset byte offset of `bin` referring the bitmap data
* @param byteLength available byte length for `bin` (from the offset `byteOffset`)
*/
static from(bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): IconItem;
/**
* Generates `IconItem` instance from bitmap data binary width actual icon size (width and height).
* @param width icon width
* @param height icon height
* @param bin binary data containing the bitmap data
* @param byteOffset byte offset of `bin` referring the bitmap data
* @param byteLength available byte length for `bin` (from the offset `byteOffset`)
*/
static from(width: number, height: number, bin: ArrayBuffer | ArrayBufferView, byteOffset?: number, byteLength?: number): IconItem;
isIcon(): this is IconItem;
isRaw(): false;
generate(): ArrayBuffer;
}

View File

@@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var functions_js_1 = require("../util/functions.js");
function calcMaskSize(width, height) {
// round up to 4 bytes (32 bit)
// (mask pixels is 1-bit bitmap)
var actualWidthBytes = functions_js_1.roundUp(Math.abs(width), 32) / 8;
return actualWidthBytes * Math.abs(height);
}
var IconItem = /** @class */ (function () {
function IconItem(width, height, bin, byteOffset, byteLength) {
var view = functions_js_1.createDataView(bin, byteOffset, byteLength);
var totalSize = view.byteLength;
var headerSize = view.getUint32(0, true);
if (headerSize > totalSize) {
headerSize = totalSize;
}
var sizeImage = functions_js_1.readUint32WithLastOffset(view, 20, headerSize);
var bi = {
width: functions_js_1.readInt32WithLastOffset(view, 4, headerSize),
height: functions_js_1.readInt32WithLastOffset(view, 8, headerSize),
planes: functions_js_1.readUint16WithLastOffset(view, 12, headerSize),
bitCount: functions_js_1.readUint16WithLastOffset(view, 14, headerSize),
compression: functions_js_1.readUint32WithLastOffset(view, 16, headerSize),
sizeImage: sizeImage,
xPelsPerMeter: functions_js_1.readInt32WithLastOffset(view, 24, headerSize),
yPelsPerMeter: functions_js_1.readInt32WithLastOffset(view, 28, headerSize),
colorUsed: functions_js_1.readUint32WithLastOffset(view, 32, headerSize),
colorImportant: functions_js_1.readUint32WithLastOffset(view, 36, headerSize),
colors: [],
};
var offset = 40;
var colors = bi.colorUsed;
if (!colors) {
switch (bi.bitCount) {
case 1:
colors = 2;
break;
case 4:
colors = 16;
break;
case 8:
colors = 256;
break;
}
}
for (var i = 0; i < colors; ++i) {
bi.colors.push({
b: functions_js_1.readUint8WithLastOffset(view, offset, totalSize),
g: functions_js_1.readUint8WithLastOffset(view, offset + 1, totalSize),
r: functions_js_1.readUint8WithLastOffset(view, offset + 2, totalSize),
});
offset += 4;
}
this.width = width;
this.height = height;
this.bitmapInfo = bi;
// round up to 4 bytes (32 bit)
var widthBytes = functions_js_1.roundUp(bi.bitCount * Math.abs(bi.width), 32) / 8;
var absActualHeight = Math.abs(bi.height) / 2;
// sizeImage may be weird if compression is 0 (BI_RGB), so
// we calculate actual bitmap size from width and height
var size = bi.compression !== 0 && sizeImage !== 0
? sizeImage
: widthBytes * absActualHeight;
if (size + offset > totalSize) {
throw new Error("Unexpected bitmap data in icon: bitmap size " + size + " is larger than " + totalSize + " - " + offset);
}
this._pixels = functions_js_1.allocatePartialBinary(view, offset, size);
offset += size;
var maskSize = calcMaskSize(bi.width, absActualHeight);
if (maskSize + offset <= totalSize) {
this.masks = functions_js_1.allocatePartialBinary(view, offset, maskSize);
}
else {
// create a zero buffer (no mask is not allowed)
this.masks = new ArrayBuffer(maskSize);
}
}
Object.defineProperty(IconItem.prototype, "pixels", {
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
get: function () {
return this._pixels;
},
/**
* Bitmap pixel data.
* @note
* On set, if `bitmapInfo.sizeImage` is non-zero, `bitmapInfo.sizeImage` will be updated.
*/
set: function (newValue) {
this._pixels = newValue;
if (this.bitmapInfo.sizeImage !== 0) {
this.bitmapInfo.sizeImage = newValue.byteLength;
}
},
enumerable: false,
configurable: true
});
IconItem.from = function (arg1, arg2, arg3, byteOffset, byteLength) {
var width;
var height;
var bin;
if (typeof arg3 === 'object') {
// second overload
width = arg1;
height = arg2;
bin = arg3;
}
else {
// first overload
width = null;
height = null;
bin = arg1;
byteOffset = arg2;
byteLength = arg3;
}
return new IconItem(width, height, bin, byteOffset, byteLength);
};
IconItem.prototype.isIcon = function () {
return true;
};
IconItem.prototype.isRaw = function () {
return false;
};
IconItem.prototype.generate = function () {
var bi = this.bitmapInfo;
var absWidth = Math.abs(bi.width);
// round up to 4 bytes (32 bit)
var absWidthBytes = functions_js_1.roundUp(bi.bitCount * absWidth, 32) / 8;
var absActualHeight = Math.abs(bi.height) / 2;
var actualSizeImage = absWidthBytes * absActualHeight;
var sizeMask = calcMaskSize(bi.width, absActualHeight);
var colorCount = bi.colors.length;
var totalSize = 40 + 4 * colorCount + actualSizeImage + sizeMask;
var bin = new ArrayBuffer(totalSize);
var view = new DataView(bin);
view.setUint32(0, 40, true);
view.setInt32(4, bi.width, true);
view.setInt32(8, bi.height, true);
view.setUint16(12, bi.planes, true);
view.setUint16(14, bi.bitCount, true);
view.setUint32(16, bi.compression, true);
// image size
view.setUint32(20, bi.sizeImage, true);
view.setInt32(24, bi.xPelsPerMeter, true);
view.setInt32(28, bi.yPelsPerMeter, true);
view.setUint32(32, bi.colorUsed, true);
view.setUint32(36, bi.colorImportant > colorCount ? colorCount : bi.colorImportant, true);
var offset = 40;
bi.colors.forEach(function (c) {
view.setUint8(offset, c.b);
view.setUint8(offset + 1, c.g);
view.setUint8(offset + 2, c.r);
offset += 4;
});
functions_js_1.copyBuffer(bin, offset, this.pixels, 0, actualSizeImage);
functions_js_1.copyBuffer(bin, offset + actualSizeImage, this.masks, 0, sizeMask);
return bin;
};
return IconItem;
}());
exports.default = IconItem;

View File

@@ -0,0 +1,13 @@
/**
* Represents the raw-graphic icon item, such as PNG data.
*/
export default class RawIconItem {
width: number;
height: number;
bitCount: number;
bin: ArrayBuffer;
constructor(bin: ArrayBuffer | ArrayBufferView, width: number, height: number, bitCount: number, byteOffset?: number, byteLength?: number);
static from(bin: ArrayBuffer | ArrayBufferView, width: number, height: number, bitCount: number, byteOffset?: number, byteLength?: number): RawIconItem;
isIcon(): false;
isRaw(): this is RawIconItem;
}

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var functions_js_1 = require("../util/functions.js");
/**
* Represents the raw-graphic icon item, such as PNG data.
*/
var RawIconItem = /** @class */ (function () {
function RawIconItem(bin, width, height, bitCount, byteOffset, byteLength) {
this.width = width;
this.height = height;
this.bitCount = bitCount;
if (typeof byteOffset !== 'number') {
byteOffset = 0;
byteLength = bin.byteLength;
}
else if (typeof byteLength !== 'number') {
byteLength = bin.byteLength - byteOffset;
}
this.bin = functions_js_1.allocatePartialBinary(bin, byteOffset, byteLength);
}
RawIconItem.from = function (bin, width, height, bitCount, byteOffset, byteLength) {
return new RawIconItem(bin, width, height, bitCount, byteOffset, byteLength);
};
RawIconItem.prototype.isIcon = function () {
return false;
};
RawIconItem.prototype.isRaw = function () {
return true;
};
return RawIconItem;
}());
exports.default = RawIconItem;

View File

@@ -0,0 +1,5 @@
import BitmapInfo from './BitmapInfo.js';
import IconFile, { IconFileItem } from './IconFile.js';
import IconItem from './IconItem.js';
import RawIconItem from './RawIconItem.js';
export { BitmapInfo, IconFile, IconFileItem, IconItem, RawIconItem };

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RawIconItem = exports.IconItem = exports.IconFile = void 0;
var IconFile_js_1 = require("./IconFile.js");
exports.IconFile = IconFile_js_1.default;
var IconItem_js_1 = require("./IconItem.js");
exports.IconItem = IconItem_js_1.default;
var RawIconItem_js_1 = require("./RawIconItem.js");
exports.RawIconItem = RawIconItem_js_1.default;

View File

@@ -0,0 +1,6 @@
import { NtExecutable, NtExecutableResource, Format } from 'pe-library';
import version from './version.js';
import * as Data from './data/index.js';
import * as Resource from './resource/index.js';
import { generateExecutableWithSign, SignerObject, DigestAlgorithmType, EncryptionAlgorithmType } from './sign/index.js';
export { NtExecutable, NtExecutableResource, version, Data, Format, Resource, generateExecutableWithSign, SignerObject, DigestAlgorithmType, EncryptionAlgorithmType, };

15
desktop-operator/node_modules/resedit/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,15 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateExecutableWithSign = exports.Resource = exports.Format = exports.Data = exports.version = exports.NtExecutableResource = exports.NtExecutable = void 0;
var pe_library_1 = require("pe-library");
Object.defineProperty(exports, "NtExecutable", { enumerable: true, get: function () { return pe_library_1.NtExecutable; } });
Object.defineProperty(exports, "NtExecutableResource", { enumerable: true, get: function () { return pe_library_1.NtExecutableResource; } });
Object.defineProperty(exports, "Format", { enumerable: true, get: function () { return pe_library_1.Format; } });
var version_js_1 = require("./version.js");
exports.version = version_js_1.default;
var Data = require("./data/index.js");
exports.Data = Data;
var Resource = require("./resource/index.js");
exports.Resource = Resource;
var index_js_1 = require("./sign/index.js");
Object.defineProperty(exports, "generateExecutableWithSign", { enumerable: true, get: function () { return index_js_1.generateExecutableWithSign; } });

21
desktop-operator/node_modules/resedit/dist/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const {
NtExecutable,
NtExecutableResource,
version,
Data,
Format,
Resource,
generateExecutableWithSign,
} = require('./index.js');
export {
NtExecutable,
NtExecutableResource,
version,
Data,
Format,
Resource,
generateExecutableWithSign,
};

View File

@@ -0,0 +1,45 @@
import { Type } from 'pe-library';
import IconItem from '../data/IconItem.js';
import RawIconItem from '../data/RawIconItem.js';
export interface IconGroupItem {
width: number;
height: number;
colors: number;
planes: number;
bitCount: number;
dataSize: number;
iconID: number;
}
/**
* A class that treats icon-group resource data (`RT_ICON_GROUP`).
* Note that this class does not treat `RT_ICON` data.
*
* - To pick all icons, use `IconGroupEntry.fromEntries`
* and `IconGroupEntry.prototype.getIconItemsFromEntries`.
* - The easiest way to add/replace icons is using `IconGroupEntry.replaceIconsForResource`,
* which treats both `RT_ICON_GROUP` and `RT_ICON` entries.
*/
export default class IconGroupEntry {
id: string | number;
lang: string | number;
readonly icons: IconGroupItem[];
private constructor();
static fromEntries(entries: readonly Type.ResourceEntry[]): IconGroupEntry[];
generateEntry(): Type.ResourceEntry;
/**
* Return an array of `IconItem` / `RawIconItem`, which are in the group of this `IconGroupEntry` instance,
* from specified resource entries.
*/
getIconItemsFromEntries(entries: readonly Type.ResourceEntry[]): Array<IconItem | RawIconItem>;
/**
* Add or replace icon resource entries with specified icon data.
* The IDs of individual icon resources (`RT_ICON`) are calculated automatically.
* @param destEntries base (destination) resource entries.
* @param iconGroupID the icon ID for the new resource data.
* If the icon-group resource of the ID and 'lang' value already exists,
* the resource data is replaced; otherwise the resource data is appended.
* @param lang the language for specified icons (0 for neutral, 0x409 for en-US)
* @param icons the icons to replace
*/
static replaceIconsForResource(destEntries: Type.ResourceEntry[], iconGroupID: string | number, lang: string | number, icons: Array<IconItem | RawIconItem>): void;
}

View File

@@ -0,0 +1,294 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var IconItem_js_1 = require("../data/IconItem.js");
var RawIconItem_js_1 = require("../data/RawIconItem.js");
var functions_js_1 = require("../util/functions.js");
function generateEntryBinary(icons) {
var count = icons.length;
if (count > 65535) {
count = 65535;
}
var size = 6 + 14 * icons.length;
var bin = new ArrayBuffer(size);
var view = new DataView(bin);
view.setUint16(0, 0, true); // reserved
view.setUint16(2, 1, true); // icon type
view.setUint16(4, count, true);
var offset = 6;
icons.forEach(function (icon) {
view.setUint8(offset, icon.width >= 256 ? 0 : icon.width);
view.setUint8(offset + 1, icon.height >= 256 ? 0 : icon.height);
view.setUint8(offset + 2, icon.colors >= 256 ? 0 : icon.colors);
view.setUint8(offset + 3, 0);
view.setUint16(offset + 4, icon.planes, true);
view.setUint16(offset + 6, icon.bitCount, true);
view.setUint32(offset + 8, icon.dataSize, true);
view.setUint16(offset + 12, icon.iconID, true);
offset += 14;
});
return bin;
}
function findUnusedIconID(entries, lang, isCursor) {
var type = isCursor ? 1 : 3;
// (ignore string id)
var filteredIDs = entries
.filter(function (e) { return e.type === type && e.lang === lang && typeof e.id === 'number'; })
.map(function (e) { return e.id; })
.sort(function (a, b) { return a - b; });
var idCurrent = 1;
for (var _i = 0, filteredIDs_1 = filteredIDs; _i < filteredIDs_1.length; _i++) {
var id = filteredIDs_1[_i];
if (idCurrent < id) {
return {
id: idCurrent,
last: false,
};
}
else if (idCurrent === id) {
++idCurrent;
}
}
return {
id: idCurrent,
last: true,
};
}
/**
* A class that treats icon-group resource data (`RT_ICON_GROUP`).
* Note that this class does not treat `RT_ICON` data.
*
* - To pick all icons, use `IconGroupEntry.fromEntries`
* and `IconGroupEntry.prototype.getIconItemsFromEntries`.
* - The easiest way to add/replace icons is using `IconGroupEntry.replaceIconsForResource`,
* which treats both `RT_ICON_GROUP` and `RT_ICON` entries.
*/
var IconGroupEntry = /** @class */ (function () {
function IconGroupEntry(groupEntry) {
var view = new DataView(groupEntry.bin);
var totalSize = view.byteLength;
var icons = [];
if (view.getUint16(2, true) === 1) {
var count = view.getUint16(4, true);
var offset = 6;
for (var i = 0; i < count; ++i) {
icons.push({
width: functions_js_1.readUint8WithLastOffset(view, offset, totalSize),
height: functions_js_1.readUint8WithLastOffset(view, offset + 1, totalSize),
colors: functions_js_1.readUint8WithLastOffset(view, offset + 2, totalSize),
planes: functions_js_1.readUint16WithLastOffset(view, offset + 4, totalSize),
bitCount: functions_js_1.readUint16WithLastOffset(view, offset + 6, totalSize),
dataSize: functions_js_1.readUint32WithLastOffset(view, offset + 8, totalSize),
iconID: functions_js_1.readUint16WithLastOffset(view, offset + 12, totalSize),
});
offset += 14; // 16 for .ico file, but 14 for resource data
}
}
this.id = groupEntry.id;
this.lang = groupEntry.lang;
this.icons = icons;
}
IconGroupEntry.fromEntries = function (entries) {
return entries
.filter(function (e) { return e.type === 14; })
.map(function (e) { return new IconGroupEntry(e); });
};
IconGroupEntry.prototype.generateEntry = function () {
var bin = generateEntryBinary(this.icons);
return {
type: 14,
id: this.id,
lang: this.lang,
codepage: 0,
bin: bin,
};
};
/**
* Return an array of `IconItem` / `RawIconItem`, which are in the group of this `IconGroupEntry` instance,
* from specified resource entries.
*/
IconGroupEntry.prototype.getIconItemsFromEntries = function (entries) {
var _this = this;
return entries
.map(function (e) {
if (e.type !== 3 || e.lang !== _this.lang) {
return null;
}
var c = _this.icons
.filter(function (icon) { return e.id === icon.iconID; })
.shift();
if (!c) {
return null;
}
return {
entry: e,
icon: c,
};
})
.filter(function (item) { return !!item; })
.map(function (item) {
var bin = item.entry.bin;
var view = new DataView(bin);
if (view.getUint32(0, true) === 0x28) {
return IconItem_js_1.default.from(bin);
}
else {
var c = item.icon;
return RawIconItem_js_1.default.from(bin, c.width, c.height, c.bitCount);
}
});
};
/**
* Add or replace icon resource entries with specified icon data.
* The IDs of individual icon resources (`RT_ICON`) are calculated automatically.
* @param destEntries base (destination) resource entries.
* @param iconGroupID the icon ID for the new resource data.
* If the icon-group resource of the ID and 'lang' value already exists,
* the resource data is replaced; otherwise the resource data is appended.
* @param lang the language for specified icons (0 for neutral, 0x409 for en-US)
* @param icons the icons to replace
*/
IconGroupEntry.replaceIconsForResource = function (destEntries, iconGroupID, lang, icons) {
// find existing entry
var entry = destEntries
.filter(function (e) { return e.type === 14 && e.id === iconGroupID && e.lang === lang; })
.shift();
var tmpIconArray = icons.map(function (icon) {
if (icon.isIcon()) {
var width = icon.width, height = icon.height;
if (width === null) {
width = icon.bitmapInfo.width;
}
if (height === null) {
height = icon.bitmapInfo.height;
// if mask is specified, the icon height must be the half of bitmap height
if (icon.masks !== null) {
height = Math.floor(height / 2);
}
}
return {
base: icon,
bm: {
width: width,
height: height,
planes: icon.bitmapInfo.planes,
bitCount: icon.bitmapInfo.bitCount,
},
bin: icon.generate(),
id: 0,
};
}
else {
return {
base: icon,
bm: {
width: icon.width,
height: icon.height,
planes: 1,
bitCount: icon.bitCount,
},
bin: icon.bin,
id: 0,
};
}
});
if (entry) {
// remove unused icon data
for (var i = destEntries.length - 1; i >= 0; --i) {
var e = destEntries[i];
if (e != null && e.type === 3) {
// RT_ICON
if (!isIconUsed(e, destEntries, entry)) {
destEntries.splice(i, 1);
}
}
}
}
else {
// create new entry
entry = {
type: 14,
id: iconGroupID,
lang: lang,
codepage: 0,
// set later
bin: null,
};
destEntries.push(entry);
}
// append icons
var idInfo;
tmpIconArray.forEach(function (icon) {
if (!(idInfo === null || idInfo === void 0 ? void 0 : idInfo.last)) {
idInfo = findUnusedIconID(destEntries, lang, false);
}
else {
++idInfo.id;
}
destEntries.push({
type: 3,
id: idInfo.id,
lang: lang,
codepage: 0,
bin: icon.bin,
});
// set 'id' field to use in generateEntryBinary
icon.id = idInfo.id;
});
var binEntry = generateEntryBinary(tmpIconArray.map(function (icon) {
var width = Math.abs(icon.bm.width);
if (width >= 256) {
width = 0;
}
var height = Math.abs(icon.bm.height);
if (height >= 256) {
height = 0;
}
var colors = 0;
if (icon.base.isIcon()) {
var bmBase = icon.base.bitmapInfo;
colors = bmBase.colorUsed || bmBase.colors.length;
if (!colors) {
switch (bmBase.bitCount) {
case 1:
colors = 2;
break;
case 4:
colors = 16;
break;
// case 8:
// colors = 256;
// break;
}
}
if (colors >= 256) {
colors = 0;
}
}
return {
width: width,
height: height,
colors: colors,
planes: icon.bm.planes,
bitCount: icon.bm.bitCount,
dataSize: icon.bin.byteLength,
iconID: icon.id,
};
}));
// rewrite entry
entry.bin = binEntry;
function isIconUsed(icon, allEntries, excludeGroup) {
return allEntries.some(function (e) {
if (e.type !== 14 ||
(e.id === excludeGroup.id && e.lang === excludeGroup.lang)) {
return false;
}
var g = new IconGroupEntry(e);
return g.icons.some(function (c) {
return c.iconID === icon.id;
});
});
}
};
return IconGroupEntry;
}());
exports.default = IconGroupEntry;

View File

@@ -0,0 +1,30 @@
import { NtExecutableResource, Type } from 'pe-library';
/** Utility class to create / parse String Table resource */
export default class StringTable {
/** Language value */
lang: string | number;
private items;
constructor();
/** Create StringTable instance from resource entries, with specified language. */
static fromEntries(lang: string | number, entries: readonly Type.ResourceEntry[]): StringTable;
/** Return all string entries. */
getAllStrings(): Array<{
id: number;
text: string;
}>;
/** Return the string data for ID value, which can be used for Win32API LoadString. */
getById(id: number): string | null;
/**
* Set/overwide the string data for ID value, which can be used for Win32API LoadString.
* @param id data ID
* @param text string data (entry will be removed if null or empty string is specified)
*/
setById(id: number, text: string | null): void;
/** Generates an array of Entry for resource processings */
generateEntries(): Type.ResourceEntry[];
/**
* Replace all string entries for NtExecutableResource with containing resource data.
* The only entries of same language are replaced.
*/
replaceStringEntriesForExecutable(res: NtExecutableResource): void;
}

View File

@@ -0,0 +1,132 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var StringTableItem_js_1 = require("./StringTableItem.js");
/** Utility class to create / parse String Table resource */
var StringTable = /** @class */ (function () {
function StringTable() {
this.lang = 0;
this.items = [];
}
/** Create StringTable instance from resource entries, with specified language. */
StringTable.fromEntries = function (lang, entries) {
var r = new StringTable();
entries.forEach(function (e) {
// 6: RT_STRING
if (e.type !== 6 ||
e.lang !== lang ||
typeof e.id !== 'number' ||
e.id <= 0) {
return;
}
r.items[e.id - 1] = StringTableItem_js_1.default.fromEntry(e.bin, 0, e.bin.byteLength);
});
r.lang = lang;
return r;
};
/** Return all string entries. */
StringTable.prototype.getAllStrings = function () {
return this.items
.map(function (e, i) {
return e
.getAll()
.map(function (x, j) {
return x !== null && x !== ''
? { id: (i << 4) + j, text: x }
: null;
})
.filter(function (x) { return !!x; });
})
.reduce(function (p, c) { return p.concat(c); }, []);
};
/** Return the string data for ID value, which can be used for Win32API LoadString. */
StringTable.prototype.getById = function (id) {
var _a;
if (id < 0) {
return null;
}
var entryIndex = id >> 4;
var entryPos = id & 15;
var e = this.items[entryIndex];
return (_a = e === null || e === void 0 ? void 0 : e.get(entryPos)) !== null && _a !== void 0 ? _a : null;
};
/**
* Set/overwide the string data for ID value, which can be used for Win32API LoadString.
* @param id data ID
* @param text string data (entry will be removed if null or empty string is specified)
*/
StringTable.prototype.setById = function (id, text) {
if (id < 0) {
return;
}
var entryIndex = id >> 4;
var entryPos = id & 15;
var e = this.items[entryIndex];
if (!e) {
this.items[entryIndex] = e = new StringTableItem_js_1.default();
}
e.set(entryPos, text);
};
/** Generates an array of Entry for resource processings */
StringTable.prototype.generateEntries = function () {
var _this = this;
return this.items
.map(function (e, i) {
var len = e.calcByteLength();
var bin = new ArrayBuffer(len);
e.generate(bin, 0);
return {
type: 6,
id: i + 1,
lang: _this.lang,
codepage: 1200,
bin: bin,
};
})
.filter(function (e) { return !!e; });
};
/**
* Replace all string entries for NtExecutableResource with containing resource data.
* The only entries of same language are replaced.
*/
StringTable.prototype.replaceStringEntriesForExecutable = function (res) {
var entries = this.generateEntries();
var dest = res.entries;
// first try -- replace same type and same language
for (var i = 0; i < dest.length; ++i) {
var e = dest[i];
if (e != null && e.type === 6 && e.lang === this.lang) {
for (var j = dest.length - 1; j >= i; --j) {
var e2 = dest[j];
if (e2 != null && e2.type === 6 && e2.lang === this.lang) {
dest.splice(j, 1);
}
}
var f = dest.splice.bind(dest, i, 0);
f.apply(void 0, entries);
return;
}
}
// second try -- add entries next to previous language
for (var i = 0; i < dest.length; ++i) {
var e = dest[i];
if (e != null && e.type === 6 && e.lang < this.lang) {
var f = dest.splice.bind(dest, i + 1, 0);
f.apply(void 0, entries);
return;
}
}
// third try -- add entries next to the last 'String' entry
for (var i = dest.length - 1; i >= 0; --i) {
var e = dest[i];
if (e != null && e.type === 6) {
var f = dest.splice.bind(dest, i + 1, 0);
f.apply(void 0, entries);
return;
}
}
// otherwise -- add entries to the last
dest.push.apply(dest, entries);
};
return StringTable;
}());
exports.default = StringTable;

View File

@@ -0,0 +1,11 @@
export default class StringTableItem {
readonly length = 16;
private _a;
constructor();
static fromEntry(bin: ArrayBuffer, offset: number, byteLength: number): StringTableItem;
get(index: number): string | null;
getAll(): Array<string | null>;
set(index: number, val: string | null): void;
calcByteLength(): number;
generate(bin: ArrayBuffer, offset: number): number;
}

View File

@@ -0,0 +1,73 @@
"use strict";
// StringTable entry:
// 16-times of {<WORD length> [<UTF-16 string>]}
Object.defineProperty(exports, "__esModule", { value: true });
var StringTableItem = /** @class */ (function () {
function StringTableItem() {
this.length = 16;
this._a = [];
this._a.length = 16;
for (var i = 0; i < 16; ++i) {
this._a[i] = '';
}
}
StringTableItem.fromEntry = function (bin, offset, byteLength) {
var view = new DataView(bin, offset, byteLength);
var ret = new StringTableItem();
var o = 0;
for (var i = 0; i < 16; ++i) {
var len = view.getUint16(o, true);
o += 2;
var s = '';
for (var j = 0; j < len; ++j) {
s += String.fromCharCode(view.getUint16(o, true));
o += 2;
}
ret._a[i] = s;
}
return ret;
};
StringTableItem.prototype.get = function (index) {
var value = this._a[index];
return value != null && value !== '' ? value : null;
};
StringTableItem.prototype.getAll = function () {
return this._a.map(function (s) { return s || null; });
};
StringTableItem.prototype.set = function (index, val) {
this._a[index] = ("" + (val !== null && val !== void 0 ? val : '')).substr(0, 4097); // length must be no longer than 4097
};
StringTableItem.prototype.calcByteLength = function () {
var len = 0;
for (var i = 0; i < 16; ++i) {
var item = this._a[i];
len += 2;
if (item != null) {
len += 2 * item.length; // UTF-16 length
}
}
// 16 alignment
return Math.floor((len + 15) / 16) * 16;
};
StringTableItem.prototype.generate = function (bin, offset) {
var out = new DataView(bin, offset);
var len = 0;
for (var i = 0; i < 16; ++i) {
var s = this._a[i];
var l = s == null ? 0 : s.length > 4097 ? 4097 : s.length;
out.setUint16(len, l, true);
len += 2;
if (s != null) {
for (var j = 0; j < l; ++j) {
// output as UTF-16
out.setUint16(len, s.charCodeAt(j), true);
len += 2;
}
}
}
// 16 alignment
return Math.floor((len + 15) / 16) * 16;
};
return StringTableItem;
}());
exports.default = StringTableItem;

View File

@@ -0,0 +1,13 @@
/**
* Flag values used by VersionEntry.fixedInfo field.
* Zero or more enum values are stored (with OR operator).
*/
declare enum VersionFileFlags {
Debug = 1,
Prerelease = 2,
Patched = 4,
PrivateBuild = 8,
InfoInferred = 16,
SpecialBuild = 32
}
export default VersionFileFlags;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Flag values used by VersionEntry.fixedInfo field.
* Zero or more enum values are stored (with OR operator).
*/
var VersionFileFlags;
(function (VersionFileFlags) {
VersionFileFlags[VersionFileFlags["Debug"] = 1] = "Debug";
VersionFileFlags[VersionFileFlags["Prerelease"] = 2] = "Prerelease";
VersionFileFlags[VersionFileFlags["Patched"] = 4] = "Patched";
VersionFileFlags[VersionFileFlags["PrivateBuild"] = 8] = "PrivateBuild";
VersionFileFlags[VersionFileFlags["InfoInferred"] = 16] = "InfoInferred";
VersionFileFlags[VersionFileFlags["SpecialBuild"] = 32] = "SpecialBuild";
})(VersionFileFlags || (VersionFileFlags = {}));
exports.default = VersionFileFlags;

View File

@@ -0,0 +1,20 @@
/**
* OS values used by VersionEntry.fixedInfo field.
*/
declare enum VersionFileOS {
Unknown = 0,
_Windows16 = 1,
_PM16 = 2,
_PM32 = 3,
_Windows32 = 4,
DOS = 65536,
OS2_16 = 131072,
OS2_32 = 196608,
NT = 262144,
DOS_Windows16 = 65537,
DOS_Windows32 = 65540,
NT_Windows32 = 262148,
OS2_16_PM16 = 131074,
OS2_32_PM32 = 196611
}
export default VersionFileOS;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* OS values used by VersionEntry.fixedInfo field.
*/
var VersionFileOS;
(function (VersionFileOS) {
VersionFileOS[VersionFileOS["Unknown"] = 0] = "Unknown";
VersionFileOS[VersionFileOS["_Windows16"] = 1] = "_Windows16";
VersionFileOS[VersionFileOS["_PM16"] = 2] = "_PM16";
VersionFileOS[VersionFileOS["_PM32"] = 3] = "_PM32";
VersionFileOS[VersionFileOS["_Windows32"] = 4] = "_Windows32";
VersionFileOS[VersionFileOS["DOS"] = 65536] = "DOS";
VersionFileOS[VersionFileOS["OS2_16"] = 131072] = "OS2_16";
VersionFileOS[VersionFileOS["OS2_32"] = 196608] = "OS2_32";
VersionFileOS[VersionFileOS["NT"] = 262144] = "NT";
VersionFileOS[VersionFileOS["DOS_Windows16"] = 65537] = "DOS_Windows16";
VersionFileOS[VersionFileOS["DOS_Windows32"] = 65540] = "DOS_Windows32";
VersionFileOS[VersionFileOS["NT_Windows32"] = 262148] = "NT_Windows32";
VersionFileOS[VersionFileOS["OS2_16_PM16"] = 131074] = "OS2_16_PM16";
VersionFileOS[VersionFileOS["OS2_32_PM32"] = 196611] = "OS2_32_PM32";
})(VersionFileOS || (VersionFileOS = {}));
exports.default = VersionFileOS;

View File

@@ -0,0 +1,20 @@
export declare enum VersionFileDriverSubtype {
Unknown = 0,
Printer = 1,
Keyboard = 2,
Language = 3,
Display = 4,
Mouse = 5,
Network = 6,
System = 7,
Installable = 8,
Sound = 9,
Comm = 10,
VersionedPrinter = 12
}
export declare enum VersionFileFontSubtype {
Unknown = 0,
Raster = 1,
Vector = 2,
TrueType = 3
}

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VersionFileFontSubtype = exports.VersionFileDriverSubtype = void 0;
var VersionFileDriverSubtype;
(function (VersionFileDriverSubtype) {
VersionFileDriverSubtype[VersionFileDriverSubtype["Unknown"] = 0] = "Unknown";
VersionFileDriverSubtype[VersionFileDriverSubtype["Printer"] = 1] = "Printer";
VersionFileDriverSubtype[VersionFileDriverSubtype["Keyboard"] = 2] = "Keyboard";
VersionFileDriverSubtype[VersionFileDriverSubtype["Language"] = 3] = "Language";
VersionFileDriverSubtype[VersionFileDriverSubtype["Display"] = 4] = "Display";
VersionFileDriverSubtype[VersionFileDriverSubtype["Mouse"] = 5] = "Mouse";
VersionFileDriverSubtype[VersionFileDriverSubtype["Network"] = 6] = "Network";
VersionFileDriverSubtype[VersionFileDriverSubtype["System"] = 7] = "System";
VersionFileDriverSubtype[VersionFileDriverSubtype["Installable"] = 8] = "Installable";
VersionFileDriverSubtype[VersionFileDriverSubtype["Sound"] = 9] = "Sound";
VersionFileDriverSubtype[VersionFileDriverSubtype["Comm"] = 10] = "Comm";
VersionFileDriverSubtype[VersionFileDriverSubtype["VersionedPrinter"] = 12] = "VersionedPrinter";
})(VersionFileDriverSubtype = exports.VersionFileDriverSubtype || (exports.VersionFileDriverSubtype = {}));
var VersionFileFontSubtype;
(function (VersionFileFontSubtype) {
VersionFileFontSubtype[VersionFileFontSubtype["Unknown"] = 0] = "Unknown";
VersionFileFontSubtype[VersionFileFontSubtype["Raster"] = 1] = "Raster";
VersionFileFontSubtype[VersionFileFontSubtype["Vector"] = 2] = "Vector";
VersionFileFontSubtype[VersionFileFontSubtype["TrueType"] = 3] = "TrueType";
})(VersionFileFontSubtype = exports.VersionFileFontSubtype || (exports.VersionFileFontSubtype = {}));

Some files were not shown because too many files have changed in this diff Show More