@syncfusion/ej2-pdf
Version:
Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.
1,250 lines (1,249 loc) • 48.6 kB
JavaScript
import { _padStart, _stringToBytes } from '../../../utils';
import { _ConstructionType, _TagClassType, _UniversalType } from './enumerator';
import { _PdfObjectIdentifier } from './identifier-mapping';
import { _bufferToInteger, _convertBytesToText, _integerToBuffer, _packBits } from './utils';
import { _isGeneralCharacter, _isGraphicCharacter, _isPrintableCharacter, _validateDate, _validateDateTime, _validateTime, isNumericString } from './syntax-verifier';
/**
* Represents an abstract ASN.1 syntax element with utilities for encoding, decoding, validation and serialization.
*
* @private
*/
var _PdfAbstractSyntaxElement = /** @class */ (function () {
function _PdfAbstractSyntaxElement() {
/**
* Internal recursion tracker used to prevent excessive recursion during parsing.
*
* @private
*/
this._recursionCount = 0;
/**
* Maximum allowed nesting depth to protect against overly deep ASN.1 structures.
*
* @private
*/
this._nestingRecursionLimit = 5;
/**
* Optional element name used for error messages and diagnostics.
*
* @private
*/
this._name = '';
/**
* The ASN.1 tag class for the element (universal, application, context, or private).
*
* @private
*/
this._tagClass = _TagClassType.universal;
/**
* Indicates whether the element is primitive or constructed.
*
* @private
*/
this._construction = _ConstructionType.primitive;
/**
* Internal storage for the element tag number.
*/
this._tagNumber = 0;
}
/**
* Returns the numeric tag number for this ASN.1 element.
*
* @returns {number} The tag number.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getTagNumber = function () {
return this._tagNumber;
};
/**
* Sets the numeric tag number for this ASN.1 element.
*
* @param {number} value non-negative tag number to assign.
* @returns {void} nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setTagNumber = function (value) {
if (!Number.isSafeInteger(value) || value < 0) {
throw new Error("Tag " + value + " was not a non-negative number.");
}
this._tagNumber = value;
};
/**
* Returns the length in bytes of this element's encoded value.
*
* @returns {number} The length of the encoded value.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getLength = function () {
var value = this._getValue();
return value.length;
};
/**
* Calculates how many bytes are needed to encode the tag for this element.
*
* @returns {number} The number of bytes used for the tag encoding.
* @private
*/
_PdfAbstractSyntaxElement.prototype._tagLength = function () {
var tagNumber = this._getTagNumber();
if (tagNumber < 31) {
return 1;
}
var n = tagNumber;
var digits = 0;
while (n !== 0) {
n >>>= 7;
digits++;
}
return 1 + digits;
};
/**
* Concatenates this element's buffers into a single `Uint8Array`.
*
* @returns {Uint8Array} The serialized bytes for this element.
* @private
*/
_PdfAbstractSyntaxElement.prototype._toBytes = function () {
var buffers = this._toBuffers();
var totalLength = buffers.reduce(function (sum, arr) { return sum + arr.length; }, 0);
var result = new Uint8Array(totalLength);
var offset = 0;
for (var _i = 0, buffers_1 = buffers; _i < buffers_1.length; _i++) {
var buffer = buffers_1[_i];
result.set(buffer, offset);
offset += buffer.length;
}
return result;
};
/**
* Validates that a size lies within the inclusive `[min, max]` bounds.
*
* @param {string} name human-readable name used in error messages.
* @param {string} units string used in error messages.
* @param {number} actualSize measured size.
* @param {number} min allowed size.
* @param {number} max allowed size.
* @returns {void} Nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._validateSize = function (name, units, actualSize, min, max) {
var effectiveMax = typeof max === 'undefined' ? Infinity : max;
if (actualSize < min) {
throw new Error(name + " must be at least " + min + " " + units + ", but was " + actualSize + " " + units + ".");
}
if (actualSize > effectiveMax) {
throw new Error(name + " must not exceed " + effectiveMax + " " + units + ", but was " + actualSize + " " + units + ".");
}
};
/**
* Validates that a numeric value lies within the inclusive `[min, max]` range.
*
* @param {string} name used in error messages.
* @param {bigint | number} actualValue to validate.
* @param {bigint} min allowed value.
* @param {bigint} [max] maximum allowed value.
* @returns {void}
* @private
*/
_PdfAbstractSyntaxElement.prototype._validateRange = function (name, actualValue, min, max) {
if (actualValue < min) {
throw new Error(name + " must be at least " + min + ", but was " + actualValue + ".");
}
if (typeof max !== 'undefined' && max !== null && actualValue > max) {
throw new Error(name + " must not exceed " + max + ", but was " + actualValue + ".");
}
};
/**
* Returns a bit string constrained to the given size bounds.
*
* @param {number} min allowed length in bits.
* @param {number} [max] maximum allowed length in bits.
* @returns {Uint8ClampedArray} The constrained bit string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedString = function (min, max) {
var bitString = this._getBitString();
var ret = bitString;
this._validateSize(this._name || 'Bit string', 'bits', ret.length, min, max);
return ret;
};
/**
* Returns a UTF-8 string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained UTF-8 string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedUtf8String = function (min, max) {
var utf8String = this._getUtf8String();
var ret = utf8String;
this._validateSize(this._name || 'Unicode string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a `SEQUENCE OF` constrained by element count.
*
* @param {number} min allowed elements.
* @param {number} [max] maximum allowed elements.
* @returns {_PdfAbstractSyntaxElement} The constrained sequence-of elements.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedSequenceOf = function (min, max) {
var sequenceOf = this._getSequenceOf();
var ret = sequenceOf;
this._validateSize(this._name || 'Sequence of', 'elements', ret.length, min, max);
return ret;
};
/**
* Returns a `SET OF` constrained by element count.
*
* @param {number} min allowed elements.
* @param {number} [max] maximum allowed elements.
* @returns {_PdfAbstractSyntaxElement} The constrained set-of elements.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedSetOf = function (min, max) {
var sequenceOf = this._getSequenceOf();
this._validateSize(this._name || 'Set of', 'elements', sequenceOf.length, min, max);
return sequenceOf;
};
/**
* Returns a numeric string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained numeric string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedNumericString = function (min, max) {
var ret = this._getNumericString();
this._validateSize(this._name || 'Numeric string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a printable ASCII string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained printable string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedPrintableString = function (min, max) {
var ret = this._getPrintableString();
this._validateSize(this._name || 'Printable ASCII string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a legacy encoded text string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained text string bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedTextString = function (min, max) {
var ret = this._getTeleprinterText();
this._validateSize(this._name || 'Legacy encoded string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a videotex string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained videotex bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedVideoString = function (min, max) {
var ret = this._getVideoTextInformation();
this._validateSize(this._name || 'Videotex string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns an IA5 (ASCII) string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained IA5 string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedIA5String = function (min, max) {
var ret = this._getInternationalAlphabetString();
this._validateSize(this._name || 'ASCII string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a graphic string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained graphic string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedGraphicString = function (min, max) {
var ret = this._getGraphicString();
this._validateSize(this._name || 'Graphic string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a visible string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained visible string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedVisibleString = function (min, max) {
var ret = this._getVisibleString();
this._validateSize(this._name || 'Visible string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns a universal string constrained by character count.
*
* @param {number} min allowed characters.
* @param {number} [max] maximum allowed characters.
* @returns {string} The constrained universal string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sizeConstrainedUniversalString = function (min, max) {
var ret = this._getUniversalString();
this._validateSize(this._name || 'Unicode string', 'characters', ret.length, min, max);
return ret;
};
/**
* Returns an integer value constrained by the specified numeric range.
*
* @param {bigint} min allowed value.
* @param {bigint} [max] maximum allowed value.
* @returns {number} The constrained number.
* @private
*/
_PdfAbstractSyntaxElement.prototype._rangeConstrainedNumber = function (min, max) {
var ret = this._getInteger();
this._validateRange(this._name || 'Number', ret, min, max);
return ret;
};
/**
* Validates this element's tag against permitted classes, constructions and numbers.
*
* @param {_TagClassType} permittedClasses Allowed tag classes.
* @param {_ConstructionType} permittedConstruction Allowed construction types.
* @param {number[]} permittedNumbers Allowed tag numbers.
* @returns {number} if valid or a negative error code.
* @private
*/
_PdfAbstractSyntaxElement.prototype._validateTag = function (permittedClasses, permittedConstruction, permittedNumbers) {
if (permittedClasses.indexOf(this._tagClass) === -1) {
return -1;
}
else if (permittedConstruction.indexOf(this._construction) === -1) {
return -2;
}
else if (permittedNumbers.indexOf(this._getTagNumber()) === -1) {
return -3;
}
else {
return 0;
}
};
/**
* Returns this object as an ASN.1 element instance.
*
* @returns {_PdfAbstractSyntaxElement} This instance.
* @private
*/
_PdfAbstractSyntaxElement.prototype._toElement = function () {
return this;
};
/**
* Copies tag and value information from another element into this one.
*
* @param {_PdfAbstractSyntaxElement} el The source element to copy from.
* @returns {void} Nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._fromElement = function (el) {
this._tagClass = el._tagClass;
this._construction = el._construction;
var tagNumber = el._getTagNumber();
this._setTagNumber(tagNumber);
var value = el._getValue();
this._setValue(value);
};
/**
* Produces a human-readable string representation for this element.
*
* @returns {string} A string describing the element and its value.
* @private
*/
_PdfAbstractSyntaxElement.prototype._toString = function () {
if (this._tagClass === _TagClassType.universal) {
var tagNumber = this._getTagNumber();
switch (tagNumber) {
case _UniversalType.endOfContent: return 'END-OF-CONTENT';
case _UniversalType.abstractSyntaxBoolean: return this._getBooleanValue() ? 'TRUE' : 'FALSE';
case _UniversalType.integer: return this._getInteger().toString();
case _UniversalType.octetString:
return "'" + Array
.from(this._getOctetString())
.map(function (byte) { return _padStart(byte.toString(16), 2, '0'); })
.join('') + "'H";
case _UniversalType.nullValue: return 'NULL';
case _UniversalType.objectIdentifier: return this._getObjectIdentifier()._getAbstractSyntaxNotation();
case _UniversalType.objectDescriptor: return "\"" + this._getObjectDescriptor() + "\"";
case _UniversalType.external: return '_PdfExternal';
case _UniversalType.enumerated: return this._getEnumerated().toString();
case _UniversalType.embeddedDataValue: return 'EMBEDDED PDV';
case _UniversalType.utf8String: return "\"" + this._getUtf8String() + "\"";
case _UniversalType.relativeObjectIdentifier: return "{ " + this._getRelativeObjectIdentifier()
.map(function (arc) { return arc.toString(); }).join('.') + " }";
case _UniversalType.time: return "\"" + this._getTime() + "\"";
case _UniversalType.sequence: return "{ " + this._getSequenceOf()
.map(function (el) { return (el.name.length ? el.name + " " + el.toString() : el.toString()); }) // eslint-disable-line
.join(' , ') + " }";
case _UniversalType.abstractSyntaxSet: return "{ " + this._getAbstractSetOf()
.map(function (el) { return (el.name.length ? el.name + " " + el.toString() : el.toString()); }) // eslint-disable-line
.join(' , ') + " }";
case _UniversalType.numericString: return "\"" + this._getNumericString() + "\"";
case _UniversalType.printableString: return "\"" + this._getPrintableString() + "\"";
case _UniversalType.teleprinterTextExchange: return 'TeletexString';
case _UniversalType.videoTextInformationSystem: return 'VideotexString';
case _UniversalType.internationalAlphabetString: return "\"" + this._getInternationalAlphabetString() + "\"";
case _UniversalType.characterString: return 'CHARACTER STRING';
case _UniversalType.date: return "\"" + this._getDate().toISOString() + "\"";
case _UniversalType.timeOfDay: {
var tod = this._getTimeOfDay();
return "\"" + tod.getUTCHours() + ":" + tod.getUTCMinutes() + ":" + tod.getUTCSeconds() + "\"";
}
case _UniversalType.dateTime: return "\"" + this._getDateTime().toISOString() + "\"";
case _UniversalType.objectIdResourceIdentifier: return this._getObjectIdResourceIdentifier();
case _UniversalType.relativeResourceIdentifier: return this._getRelativeResourceIdentifier();
default: return "[UNIV " + this._getTagNumber() + "]: " + this._getValue().toString();
}
}
else if (this._tagClass === _TagClassType.context) {
return "[CTXT " + this._getTagNumber() + "]: " + this._getValue().toString();
}
else if (this._tagClass === _TagClassType.abstractSyntaxPrivate) {
return "[PRIV " + this._getTagNumber() + "]: " + this._getValue().toString();
}
else {
return "[APPL " + this._getTagNumber() + "]: " + this._getValue().toString();
}
};
/* eslint-disable */
/**
* Converts this element to a JSON-serializable representation when possible.
*
* @returns {unknown} A JSON-friendly value or `undefined` if not representable.
* @private
*/
_PdfAbstractSyntaxElement.prototype._toJson = function () {
if (this._tagClass === _TagClassType.universal) {
switch (this._getTagNumber()) {
case _UniversalType.endOfContent:
return undefined;
case _UniversalType.abstractSyntaxBoolean:
return this._getBooleanValue();
case _UniversalType.integer: {
var ret = this._getInteger();
return ret;
}
case _UniversalType.bitString: {
var bits = this._getBitString();
return {
length: bits.length,
value: Array.from(_packBits(bits)).map(function (byte) { return byte.toString(16); }).join('')
};
}
case _UniversalType.octetString:
return Array.from(this._getOctetString())
.map(function (byte) { return byte.toString(16); }).join('');
case _UniversalType.nullValue:
return null;
case _UniversalType.objectIdentifier:
return this._getObjectIdentifier()._toJson();
case _UniversalType.objectDescriptor:
return this._getObjectDescriptor();
case _UniversalType.enumerated:
return this._getEnumerated().toString();
case _UniversalType.utf8String:
return this._getUtf8String();
case _UniversalType.relativeObjectIdentifier:
return this._getRelativeObjectIdentifier()
.map(function (arc) { return arc.toString(); }).join('.');
case _UniversalType.teleprinterTextExchange:
return String.fromCodePoint.apply(String, Array.from(this._getTeleprinterText()));
case _UniversalType.videoTextInformationSystem:
return String.fromCodePoint.apply(String, Array.from(this._getVideoTextInformation()));
case _UniversalType.graphicString:
return this._getGraphicString();
case _UniversalType.visibleString:
return this._getVisibleString();
case _UniversalType.universalString:
return this._getUniversalString();
case _UniversalType.bmpString:
return this._getBmpString();
case _UniversalType.date:
return this._getDate().toISOString();
case _UniversalType.timeOfDay: {
var tod = this._getTimeOfDay();
return tod.getUTCHours() + ":" + tod.getUTCMinutes() + ":" + tod.getUTCSeconds();
}
case _UniversalType.dateTime:
return this._getDateTime().toISOString();
case _UniversalType.objectIdResourceIdentifier:
return this._getObjectIdResourceIdentifier();
case _UniversalType.relativeResourceIdentifier:
return this._getRelativeResourceIdentifier();
default:
return undefined;
}
}
return undefined;
};
/* eslint-ensable */
/**
* Sorts elements into canonical order by their encoded bytes.
*
* @param {_PdfAbstractSyntaxElement[]} elements array of elements to sort.
* @returns {_PdfAbstractSyntaxElement[]} The sorted elements.
* @private
*/
_PdfAbstractSyntaxElement.prototype._sortCanonically = function (elements) {
return elements.sort(function (value1, value2) {
var element1 = value1._toBytes();
var element2 = value2._toBytes();
var n = Math.min(element1.length, element2.length);
for (var i = 0; i < n; i++) {
if (element1[i] !== element2[i]) {
return element1[i] - element2[i];
}
}
return element1.length - element2.length;
});
};
/**
* Determines whether the provided elements have unique (class, tag) pairs.
*
* @param {_PdfAbstractSyntaxElement} elements to examine.
* @returns {boolean} if all elements are uniquely tagged.
* @private
*/
_PdfAbstractSyntaxElement.prototype._isUniquelyTagged = function (elements) {
var finds = new Set([]);
for (var i = 0; i < elements.length; i++) {
var key = ((elements[i]._tagClass << 30)
+ elements[i]._getTagNumber());
if (finds.has(key)) {
return false;
}
finds.add(key);
}
return true;
};
/**
* Decodes and returns this element's integer value.
*
* @returns {number} The decoded integer.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getInteger = function () {
if (this._construction !== _ConstructionType.primitive) {
throw new Error('Number cannot be constructed.');
}
var value = this._getValue();
return this._decodeInteger(value);
};
/**
* Encodes and sets this element's integer value.
*
* @param {number} value integer to encode and assign.
* @returns {void} Nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setInteger = function (value) {
this._setValue(this._encodeInteger(value));
};
/**
* Decodes and returns this element's object identifier.
*
* @returns {_PdfObjectIdentifier} The decoded `_PdfObjectIdentifier`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getObjectIdentifier = function () {
if (this._construction !== _ConstructionType.primitive) {
throw new Error('Object identifier cannot be constructed.');
}
return this._decodeObjectIdentifier(this._getValue());
};
/**
* Encodes and sets this element's object identifier.
*
* @param {_PdfObjectIdentifier} value The object identifier to assign.
* @returns {void} Nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setObjectIdentifier = function (value) {
this._setValue(this._encodeObjectIdentifier(value));
};
/**
* Returns this element's enumerated value as a number.
*
* @returns {number} The enumerated value.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getEnumerated = function () {
return Number(this._getInteger());
};
/**
* Sets this element's enumerated value.
*
* @param {number} value enumerated value to assign.
* @returns {void} Nothing.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setEnumerated = function (value) {
this._setInteger(value);
};
/**
* Decodes and returns this element's relative object identifier as an array of arcs.
*
* @returns {number[]} The relative OID arcs.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getRelativeObjectIdentifier = function () {
if (this._construction !== _ConstructionType.primitive) {
throw new Error('Relative oid cannot be constructed.');
}
return this._decodeRelativeObjectIdentifier(this._getValue());
};
/**
* Encodes and sets this element's relative object identifier.
*
* @param {number[]} value array of arcs to assign.
* @returns {void} This returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setRelativeObjectIdentifier = function (value) {
this._setValue(this._encodeRelativeObjectIdentifier(value));
};
/**
* Decodes and returns this element's time string.
*
* @returns {string} The decoded time string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getTime = function () {
return this._decodeTime(this._getValue());
};
/**
* Encodes and sets this element's time string.
*
* @param {string} value time string to assign.
* @returns {void} This returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setTime = function (value) {
this._setValue(this._encodeTime(value));
};
/**
* Decodes and returns this element's date.
*
* @returns {Date} The decoded `Date`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getDate = function () {
return this._decodeDate(this._getValue());
};
/**
* Encodes and sets this element's date.
*
* @param {Date} value `Date` to assign.
* @returns {void} This returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setDate = function (value) {
this._setValue(this._encodeDate(value));
};
/**
* Decodes and returns this element's time-of-day as a `Date`.
*
* @returns {Date} The decoded time-of-day.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getTimeOfDay = function () {
return this._decodeTimeOfDay(this._getValue());
};
/**
* Encodes and sets this element's time-of-day.
*
* @param {Date} value `Date` representing the time-of-day.
* @returns {void}
* @private
*/
_PdfAbstractSyntaxElement.prototype._setTimeOfDay = function (value) {
this._setValue(this._encodeTimeOfDay(value));
};
/**
* Decodes and returns this element's date-time as a `Date`.
*
* @returns {Date} The decoded date-time.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getDateTime = function () {
return this._decodeDateTime(this._getValue());
};
/**
* Encodes and sets this element's date-time.
*
* @param {Date} value `Date` to assign.
* @returns {void} This returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setDateTime = function (value) {
this._setValue(this._encodeDateTime(value));
};
/**
* Decodes and returns this element's object ID resource identifier.
*
* @returns {string} The decoded resource identifier string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getObjectIdResourceIdentifier = function () {
return this._decodeObjectIdResourceIdentifier(this._getValue());
};
/**
* Encodes and sets this element's object ID resource identifier.
*
* @param {string} value resource identifier string to assign.
* @returns {void} This returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setObjectIdResourceIdentifier = function (value) {
this._setValue(this._encodeObjectIdResourceIdentifier(value));
};
/**
* Decodes and returns this element's relative resource identifier.
*
* @returns {string} The decoded relative resource identifier.
* @private
*/
_PdfAbstractSyntaxElement.prototype._getRelativeResourceIdentifier = function () {
return this._decodeRelativeResourceIdentifier(this._getValue());
};
/**
* Encodes and sets this element's relative resource identifier.
*
* @param {string} value relative resource identifier string to assign.
* @returns {void} this returns void.
* @private
*/
_PdfAbstractSyntaxElement.prototype._setRelativeResourceIdentifier = function (value) {
this._setValue(this._encodeRelativeResourceIdentifier(value));
};
/**
* Encodes a JavaScript number into ASN.1 integer bytes.
*
* @param {number} value number to encode.
* @returns {Uint8Array} The encoded integer bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeInteger = function (value) {
return _integerToBuffer(value);
};
/**
* Decodes ASN.1 integer bytes into a JavaScript number.
*
* @param {Uint8Array} value integer bytes to decode.
* @returns {number} The decoded number.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeInteger = function (value) {
if (value.length === 0) {
throw new Error('Integer or enumeration encoded on zero bytes');
}
if (value.length > 2 && ((value[0] === 0xFF && value[1] >= 128) ||
(value[0] === 0x00 && value[1] < 128))) {
var slice = value.slice(0, 16);
var hexString = Array.from(slice)
.map(function (byte) { return _padStart(byte.toString(16), 2, '0'); })
.join('');
throw new Error('Unnecessary padding bytes on . ' +
("First 16 bytes of the offending value were: 0x" + hexString));
}
return _bufferToInteger(value);
};
/**
* Encodes an object identifier into bytes.
*
* @param {_PdfObjectIdentifier} value `_PdfObjectIdentifier` to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeObjectIdentifier = function (value) {
return value._toBytes();
};
/**
* Decodes bytes into an `_PdfObjectIdentifier` instance.
*
* @param {Uint8Array} value bytes to decode.
* @returns {_PdfObjectIdentifier} The decoded `_PdfObjectIdentifier`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeObjectIdentifier = function (value) {
var oid = new _PdfObjectIdentifier();
return oid._fromBytes(value);
};
/**
* Encodes a relative object identifier into bytes.
*
* @param {number[]} value array of relative OID arcs.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeRelativeObjectIdentifier = function (value) {
var result = [];
for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
var arc = value_1[_i];
if (arc < 128) {
result.push(arc);
continue;
}
var length_1 = 0;
var tempArc = arc;
while (tempArc > 0) {
length_1++;
tempArc >>>= 7;
}
for (var j = length_1 - 1; j >= 0; j--) {
var byte = (arc >>> (j * 7)) & 0x7f;
if (j !== 0) {
byte |= 0x80;
}
result.push(byte);
}
}
return new Uint8Array(result);
};
/**
* Decodes bytes into a relative object identifier (array of arcs).
*
* @param {Uint8Array} value bytes to decode.
* @returns {number[]} The decoded arcs.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeRelativeObjectIdentifier = function (value) {
if (value.length === 0) {
return [];
}
else if (value.length > 1 && (value[value.length - 1] & 128) !== 0) {
throw new Error('The relative object identifier is too long and was shortened.');
}
var nodes = [];
var currentNode = 0;
for (var i = 0; i < value.length; i++) {
var byte = value[i];
if (byte === 0x80 && currentNode === 0) {
throw new Error('The relative object identifier node has unsupported padding.');
}
currentNode <<= 7;
currentNode += (byte & 0x7f);
if ((byte & 0x80) === 0) {
nodes.push(currentNode);
currentNode = 0;
}
}
return nodes;
};
/**
* Encodes a time string into bytes.
*
* @param {string} value time string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeTime = function (value) {
return _stringToBytes(value.replace(/,/g, '.'));
};
/**
* Decodes time bytes into a string.
*
* @param {Uint8Array} bytes to decode.
* @returns {string} The decoded time string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeTime = function (bytes) {
return _convertBytesToText(bytes);
};
/**
* Encodes a `Date` into ASN.1 date bytes (YYYYMMDD).
*
* @param {Date} date to encode.
* @returns {Uint8Array} The encoded date bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeDate = function (date) {
if (date.getFullYear() < 1582 || date.getFullYear() > 9999) {
throw new Error("The Date " + date.toISOString() + " may not be encoded, because the "
+ 'year must be greater than 1581 and less than 10000.');
}
return _stringToBytes(_padStart(date.getFullYear().toString(), 4, '0') +
_padStart((date.getMonth() + 1).toString(), 2, '0') +
_padStart(date.getDate().toString(), 2, '0'));
};
/**
* Decodes ASN.1 date bytes (YYYYMMDD) into a `Date`.
*
* @param {Uint8Array} bytes to decode.
* @returns {Date} The decoded `Date`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeDate = function (bytes) {
var str = _convertBytesToText(bytes);
var year = parseInt(str.slice(0, 4), 10);
var month = parseInt(str.slice(4, 6), 10) - 1;
var day = parseInt(str.slice(6, 8), 10);
_validateDate('DATE', year, month, day);
return new Date(year, month, day);
};
/**
* Encodes a time-of-day `Date` into bytes (HHMMSS).
*
* @param {Date} time to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeTimeOfDay = function (time) {
return _stringToBytes(_padStart(time.getHours().toString(), 2, '0')
+ _padStart(time.getMinutes().toString(), 2, '0')
+ _padStart(time.getSeconds().toString(), 2, '0'));
};
/**
* Decodes time-of-day bytes (HHMMSS) into a `Date`.
*
* @param {Uint8Array} bytes to decode.
* @returns {Date} The decoded `Date`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeTimeOfDay = function (bytes) {
var str = _convertBytesToText(bytes);
var hours = parseInt(str.slice(0, 2), 10);
var minutes = parseInt(str.slice(2, 4), 10);
var seconds = parseInt(str.slice(4, 6), 10);
_validateTime('TIME-OF-DAY', hours, minutes, seconds);
var ret = new Date();
ret.setHours(hours);
ret.setMinutes(minutes);
ret.setSeconds(seconds);
return ret;
};
/**
* Decodes ASN.1 date-time bytes into a `Date`.
*
* @param {Uint8Array} bytes to decode.
* @returns {Date} The decoded `Date`.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeDateTime = function (bytes) {
var str = _convertBytesToText(bytes);
var year = parseInt(str.slice(0, 4), 10);
var month = parseInt(str.slice(4, 6), 10) - 1;
var day = parseInt(str.slice(6, 8), 10);
var hours = parseInt(str.slice(8, 10), 10);
var minutes = parseInt(str.slice(10, 12), 10);
var seconds = parseInt(str.slice(12, 14), 10);
_validateDateTime('DATE-TIME', year, month, day, hours, minutes, seconds);
return new Date(year, month, day, hours, minutes, seconds);
};
/**
* Decodes a GENERAL STRING ensuring only general characters are present.
*
* @param {Uint8Array} value to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeGeneralString = function (value) {
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!_isGeneralCharacter(char)) {
throw new Error('The input must contain only standard ASCII characters.');
}
}
return _convertBytesToText(value);
};
/**
* Decodes a GRAPHIC STRING ensuring allowed graphic characters.
*
* @param {Uint8Array} value bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeGraphicString = function (value) {
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!_isGraphicCharacter(char)) {
throw new Error('Only standard printable ASCII characters are allowed.');
}
}
return _convertBytesToText(value);
};
/**
* Decodes a NUMERIC STRING ensuring only numeric characters and spaces.
*
* @param {Uint8Array} value bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeNumericString = function (value) {
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!isNumericString(char)) {
throw new Error('The input must contain only numeric characters and spaces.');
}
}
return _convertBytesToText(value);
};
/**
* Decodes an OBJECT DESCRIPTOR ensuring only allowed characters.
*
* @param {Uint8Array} value bytes to decode.
* @returns {string} The decoded descriptor string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeObjectDescriptor = function (value) {
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!_isGraphicCharacter(char)) {
throw new Error('Only standard printable ASCII characters are allowed in the object descriptor.');
}
}
return _convertBytesToText(value);
};
/**
* Decodes an object-id resource identifier into a string.
*
* @param {Uint8Array} bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeObjectIdResourceIdentifier = function (bytes) {
return _convertBytesToText(bytes);
};
/**
* Decodes a relative resource identifier into a string.
*
* @param {Uint8Array} bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeRelativeResourceIdentifier = function (bytes) {
return _convertBytesToText(bytes);
};
/**
* Decodes a PRINTABLE STRING, validating allowed characters.
*
* @param {Uint8Array} value bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodePrintableString = function (value) {
var printableStringCharacters = 'etaoinsrhdlucmfywgpbvkxqjzETAOINSRHDLUCMFYWGPBVKXQJZ' +
'0123456789 \'()+,-./:=?';
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!_isPrintableCharacter(char)) {
throw new Error('Printable ASCII string can only contain these characters: ' +
printableStringCharacters + '. ' +
("Encountered character code " + char + "."));
}
}
return _convertBytesToText(value);
};
/**
* Decodes a VISIBLE STRING, validating allowed graphic characters.
*
* @param {Uint8Array} value bytes to decode.
* @returns {string} The decoded string.
* @private
*/
_PdfAbstractSyntaxElement.prototype._decodeVisibleString = function (value) {
for (var i = 0; i < value.length; i++) {
var char = value[i];
if (!_isGraphicCharacter(char)) {
throw new Error('Visible string can only contain characters between 0x20 and 0x7E. ' +
("Encountered character code " + char + "."));
}
}
return _convertBytesToText(value);
};
/**
* Encodes a bit string into ASN.1 BIT STRING bytes.
*
* @param {Uint8ClampedArray} value bit string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeBitString = function (value) {
if (value.length === 0) {
return new Uint8Array([0]);
}
var byteLength = (value.length >>> 3) + (value.length % 8 !== 0 ? 1 : 0);
var result = new Uint8Array(byteLength + 1);
result[0] = 8 - (value.length % 8);
if (result[0] === 8) {
result[0] = 0;
}
result.set(_packBits(value), 1);
return result;
};
/**
* Encodes a boolean into ASN.1 boolean bytes.
*
* @param {boolean} value boolean to encode.
* @returns {Uint8Array} The encoded byte array.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeBoolean = function (value) {
return new Uint8Array([(value ? 0xFF : 0x00)]);
};
/**
* Encodes a `Date` into ASN.1 date-time bytes (YYYYMMDDHHMMSS).
*
* @param {Date} value The `Date` to encode.
* @returns {Uint8Array}The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeDateTime = function (value) {
var year = value.getFullYear();
if (year < 1582 || year > 9999) {
throw new Error('The date cannot be encoded');
}
var dateTimeString = _padStart(year.toString(), 4, '0') +
_padStart((value.getMonth() + 1).toString(), 2, '0') +
_padStart(value.getDate().toString(), 2, '0') +
_padStart(value.getHours().toString(), 2, '0') +
_padStart(value.getMinutes().toString(), 2, '0') +
_padStart(value.getSeconds().toString(), 2, '0');
return _stringToBytes(dateTimeString);
};
/**
* Encodes an object-id resource identifier string into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeObjectIdResourceIdentifier = function (value) {
return _stringToBytes(value);
};
/**
* Encodes a relative resource identifier string into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeRelativeResourceIdentifier = function (value) {
return _stringToBytes(value);
};
/**
* Encodes a sequence of elements into a contiguous byte array.
*
* @param {_PdfAbstractSyntaxElement} value elements to encode.
* @returns {Uint8Array} The concatenated bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeSequence = function (value) {
var byteArrays = value.map(function (element) { return element._toBytes(); });
var totalLength = byteArrays.reduce(function (sum, arr) { return sum + arr.length; }, 0);
var result = new Uint8Array(totalLength);
var offset = 0;
for (var _i = 0, byteArrays_1 = byteArrays; _i < byteArrays_1.length; _i++) {
var arr = byteArrays_1[_i];
result.set(arr, offset);
offset += arr.length;
}
return result;
};
/**
* Encodes a numeric string into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array}The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeNumericString = function (value) {
return _stringToBytes(value);
};
/**
* Encodes a printable string into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodePrintableString = function (value) {
return _stringToBytes(value);
};
/**
* Encodes a graphic string into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeGraphicString = function (value) {
return _stringToBytes(value);
};
/**
* Encodes a visible string into bytes.
*
* @param {string} value to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeVisibleString = function (value) {
return _stringToBytes(value);
};
/**
* Encodes an object descriptor into bytes.
*
* @param {string} value string to encode.
* @returns {Uint8Array} The encoded bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._encodeObjectDescriptor = function (value) {
return _stringToBytes(value);
};
/**
* Returns the serialized bytes for this element (alias for `_toBytes`).
*
* @returns {Uint8Array} The serialized bytes.
* @private
*/
_PdfAbstractSyntaxElement.prototype._toEncodedBytes = function () {
return this._toBytes();
};
/**
* Indicates whether this element is context-tagged.
*
* @returns {boolean} if context tagged.
* @private
*/
_PdfAbstractSyntaxElement.prototype._isTagged = function () {
return this._tagClass === _TagClassType.context;
};
/**
* Indicates whether this element is constructed.
*
* @returns {boolean} if constructed.
* @private
*/
_PdfAbstractSyntaxElement.prototype._isConstructed = function () {
return this._construction === _ConstructionType.constructed;
};
return _PdfAbstractSyntaxElement;
}());
export { _PdfAbstractSyntaxElement };