diff --git a/src/cleartext.js b/src/cleartext.js index c716fc6b..8d8b57a6 100644 --- a/src/cleartext.js +++ b/src/cleartext.js @@ -43,7 +43,7 @@ export function CleartextMessage(text, signature) { return new CleartextMessage(text, signature); } // normalize EOL to canonical form - this.text = util.removeTrailingSpaces(text).replace(/\r\n/g, '\n').replace(/[\r\n]/g, '\r\n'); + this.text = util.removeTrailingSpaces(text).replace(/\r?\n/g, '\r\n'); if (signature && !(signature instanceof Signature)) { throw new Error('Invalid signature input'); } diff --git a/src/util.js b/src/util.js index 3c6cf767..11ab51e7 100644 --- a/src/util.js +++ b/src/util.js @@ -695,19 +695,29 @@ export default { canonicalizeEOL: function(data) { const CR = 13; const LF = 10; + let carryOverCR = false; + + return stream.transform(data, bytes => { + bytes = carryOverCR ? [CR].concat(Array.from(bytes)) : Array.from(bytes); + + if (bytes[bytes.length - 1] === CR) { + carryOverCR = true; + bytes.pop(); + } else { + carryOverCR = false; + } - return stream.transform(util.nativeEOL(data, true), bytes => { const normalized = []; for (let i = 0; i < bytes.length; i++){ const x = bytes[i]; - if (x === LF || x === CR) { + if (x === LF && i > 0 && bytes[i - 1] !== CR) { normalized.push(CR, LF); } else { normalized.push(x); } } return new Uint8Array(normalized); - }); + }, () => new Uint8Array(carryOverCR ? [CR] : [])); }, /**