UNPKG

@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
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 };