node_modules: update (#344)

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Dawid Dziurlaanddawidd6 authored and GitHub committed 2026-10-10 17:27:57 +02:00
1 parent b099186883
commit 6e88c72525
63 files changed
+2863 -1227

No files matched your search

+2
View File
@@ -14,6 +14,8 @@ export declare function wrap(str: string, lineLength?: number): string;
export interface QPEncoderOptions {
/** Maximum length for lines, set to false to disable wrapping */
lineLength?: number | false | undefined;
/** The input is binary data: a CR or LF that is not part of a CRLF pair is encoded */
binary?: boolean | undefined;
}
/** The name @types/nodemailer used for QPEncoderOptions */
export type EncoderOptions = QPEncoderOptions;
+103 -33
View File
@@ -21,23 +21,52 @@ const QP_RANGES = [
[0x20, 0x3c], // <SP>!"#$%&'()*+,-./0123456789:;
[0x3e, 0x7e] // >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
];
// 1 for every byte value that is written as is, see QP_RANGES
const QP_LITERAL = new Uint8Array(256);
for (let i = 0; i < 256; i++) {
QP_LITERAL[i] = checkRanges(i, QP_RANGES) ? 1 : 0;
}
const HEX_DIGITS = Buffer.from('0123456789ABCDEF', 'latin1');
const isWhitespace = (c) => c === 0x20 || c === 0x09;
function encode(buffer) {
if (typeof buffer === 'string') {
buffer = Buffer.from(buffer, 'utf-8');
}
let result = '';
let ord;
for (let i = 0, len = buffer.length; i < len; i++) {
ord = buffer[i];
return encodeBytes(typeof buffer === 'string' ? Buffer.from(buffer, 'utf-8') : buffer);
}
/**
* Encodes bytes that may be followed by more input
*
* @param buffer Bytes to encode
* @param [next] The byte that follows the buffer, whitespace before it is kept literal unless it
* is a line break. Without it the buffer ends the input and its trailing whitespace is encoded
* @param [binary] Keep only CRLF pairs literal. A lone CR or LF is data, not a line break, and
* anything that rewrites line endings on the way would change it
* @param [previous] The byte before the buffer, for a buffer that starts with LF
* @returns Quoted-Printable encoded string
*/
function encodeBytes(buffer, next, binary, previous) {
const len = buffer.length;
// every byte takes three characters at most
const output = Buffer.allocUnsafe(len * 3);
let pos = 0;
for (let i = 0; i < len; i++) {
const ord = buffer[i];
const following = i + 1 < len ? buffer[i + 1] : next;
const lineBreakByte = binary && (ord === 0x0d || ord === 0x0a)
? ord === 0x0d
? following === 0x0a
: (i > 0 ? buffer[i - 1] : previous) === 0x0d
: true;
// if the char is in allowed range, then keep as is, unless it is a WS in the end of a line
if (checkRanges(ord, QP_RANGES) &&
!((ord === 0x20 || ord === 0x09) && (i === len - 1 || buffer[i + 1] === 0x0a || buffer[i + 1] === 0x0d))) {
result += String.fromCharCode(ord);
if (QP_LITERAL[ord] &&
lineBreakByte &&
!(isWhitespace(ord) && (following === undefined || following === 0x0a || following === 0x0d))) {
output[pos++] = ord;
continue;
}
result += '=' + (ord < 0x10 ? '0' : '') + ord.toString(16).toUpperCase();
output[pos++] = 0x3d; // =
output[pos++] = HEX_DIGITS[Math.floor(ord / 16)];
output[pos++] = HEX_DIGITS[ord % 16];
}
return result;
return output.toString('latin1', 0, pos);
}
/**
* Adds soft line breaks to a Quoted-Printable string
@@ -148,6 +177,10 @@ function checkRanges(nr, ranges) {
}
return false;
}
// Input is encoded and wrapped this many bytes at a time. wrap() works on strings, and a large
// chunk handed over at once, such as a whole Buffer attachment, would be held several times over
// as intermediate strings
const ENCODE_SLICE_SIZE = 64 * 1024;
/**
* Creates a transform stream for encoding data to Quoted-Printable encoding
*
@@ -163,45 +196,82 @@ class Encoder extends node_stream_1.Transform {
this.options.lineLength = this.options.lineLength || 76;
}
this._curLine = '';
this._remainingBytes = false;
this._lastByte = undefined;
this.inputBytes = 0;
this.outputBytes = 0;
}
/** @internal */
_transform(chunk, encoding, done) {
let qp;
if (encoding !== 'buffer') {
chunk = Buffer.from(chunk, encoding);
}
if (!chunk || !chunk.length) {
let buf = encoding !== 'buffer' ? Buffer.from(chunk, encoding) : chunk;
if (!buf || !buf.length) {
return done();
}
this.inputBytes += chunk.length;
if (this.options.lineLength) {
qp = this._curLine + encode(chunk);
qp = wrap(qp, this.options.lineLength);
qp = qp.replace(/(^|\n)([^\n]*)$/, (match, lineBreak, lastLine) => {
this._curLine = lastLine;
return lineBreak;
});
if (qp) {
this.outputBytes += qp.length;
this.push(qp);
}
this.inputBytes += buf.length;
if (this._remainingBytes) {
buf = Buffer.concat([this._remainingBytes, buf], this._remainingBytes.length + buf.length);
this._remainingBytes = false;
}
else {
qp = encode(chunk);
this.outputBytes += qp.length;
this.push(qp, 'ascii');
// Whitespace is encoded when it ends a line, and the end of the input counts as one. Hold
// back the whitespace a chunk ends with until it is known what follows it, so the output
// does not depend on where the input was split
let end = buf.length;
// a binary CR can only be written once it is known whether LF follows
while (end > 0 && (isWhitespace(buf[end - 1]) || (this.options.binary && buf[end - 1] === 0x0d))) {
end--;
}
if (buf.length - end <= ENCODE_SLICE_SIZE) {
this._remainingBytes = end < buf.length ? Buffer.from(buf.subarray(end)) : false;
buf = buf.subarray(0, end);
}
this._encodeSlices(buf);
done();
}
/** @internal */
_flush(done) {
if (this._remainingBytes) {
this._encodeSlices(this._remainingBytes);
this._remainingBytes = false;
}
if (this._curLine) {
this.outputBytes += this._curLine.length;
this.push(this._curLine, 'ascii');
this._curLine = '';
}
done();
}
/**
* Encodes the input in slices of ENCODE_SLICE_SIZE bytes. Each slice is told the byte that
* follows it, so a slice that ends in whitespace is encoded as if it was not split
*
* @internal
*/
_encodeSlices(buf) {
for (let start = 0; start < buf.length; start += ENCODE_SLICE_SIZE) {
const end = Math.min(start + ENCODE_SLICE_SIZE, buf.length);
this._encodeSlice(buf.subarray(start, end), end < buf.length ? buf[end] : undefined);
this._lastByte = buf[end - 1];
}
}
/** @internal */
_encodeSlice(buf, next) {
let qp;
if (this.options.lineLength) {
qp = wrap(this._curLine + encodeBytes(buf, next, this.options.binary, this._lastByte), this.options.lineLength);
// the last line is kept until it is known whether it needs a soft break
const lastLF = qp.lastIndexOf('\n');
this._curLine = qp.substring(lastLF + 1);
qp = qp.substring(0, lastLF + 1);
if (qp) {
this.outputBytes += qp.length;
this.push(qp, 'ascii');
}
}
else {
qp = encodeBytes(buf, next, this.options.binary, this._lastByte);
this.outputBytes += qp.length;
this.push(qp, 'ascii');
}
}
}
exports.Encoder = Encoder;