Comparing version 1.1.0 to 2.0.0
260
lib/libqp.js
@@ -0,16 +1,8 @@ | ||
/* eslint no-useless-escape: 0 */ | ||
'use strict'; | ||
var stream = require('stream'); | ||
var util = require('util'); | ||
var Transform = stream.Transform; | ||
const stream = require('stream'); | ||
const Transform = stream.Transform; | ||
// expose to the world | ||
module.exports = { | ||
encode: encode, | ||
decode: decode, | ||
wrap: wrap, | ||
Encoder: Encoder, | ||
Decoder: Decoder | ||
}; | ||
/** | ||
@@ -24,18 +16,18 @@ * Encodes a Buffer into a Quoted-Printable encoded string | ||
if (typeof buffer === 'string') { | ||
buffer = new Buffer(buffer, 'utf-8'); | ||
buffer = Buffer.from(buffer, 'utf-8'); | ||
} | ||
// usable characters that do not need encoding | ||
var ranges = [ | ||
let ranges = [ | ||
// https://tools.ietf.org/html/rfc2045#section-6.7 | ||
[0x09], // <TAB> | ||
[0x0A], // <LF> | ||
[0x0D], // <CR> | ||
[0x20, 0x3C], // <SP>!"#$%&'()*+,-./0123456789:; | ||
[0x3E, 0x7E] // >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} | ||
[0x0a], // <LF> | ||
[0x0d], // <CR> | ||
[0x20, 0x3c], // <SP>!"#$%&'()*+,-./0123456789:; | ||
[0x3e, 0x7e] // >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} | ||
]; | ||
var result = ''; | ||
var ord; | ||
let result = ''; | ||
let ord; | ||
for (var i = 0, len = buffer.length; i < len; i++) { | ||
for (let i = 0, len = buffer.length; i < len; i++) { | ||
ord = buffer[i]; | ||
@@ -60,15 +52,17 @@ // if the char is in allowed range, then keep as is, unless it is a ws in the end of a line | ||
function decode(str) { | ||
str = (str || '').toString(). | ||
str = (str || '') | ||
.toString() | ||
// remove invalid whitespace from the end of lines | ||
replace(/[\t ]+$/gm, ''). | ||
.replace(/[\t ]+$/gm, '') | ||
// remove soft line breaks | ||
replace(/\=(?:\r?\n|$)/g, ''); | ||
.replace(/\=(?:\r?\n|$)/g, ''); | ||
var encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length, | ||
let encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length, | ||
bufferLength = str.length - encodedBytesCount * 2, | ||
chr, hex, | ||
buffer = new Buffer(bufferLength), | ||
chr, | ||
hex, | ||
buffer = Buffer.from(bufferLength), | ||
bufferPos = 0; | ||
for (var i = 0, len = str.length; i < len; i++) { | ||
for (let i = 0, len = str.length; i < len; i++) { | ||
chr = str.charAt(i); | ||
@@ -101,5 +95,7 @@ if (chr === '=' && (hex = str.substr(i + 1, 2)) && /[\da-fA-F]{2}/.test(hex)) { | ||
var pos = 0, | ||
let pos = 0, | ||
len = str.length, | ||
match, code, line, | ||
match, | ||
code, | ||
line, | ||
lineMargin = Math.floor(lineLength / 3), | ||
@@ -132,22 +128,19 @@ result = ''; | ||
line = line.substr(0, line.length - (match[0].length - 1)); | ||
} else { | ||
if (line.match(/\=[\da-f]{0,2}$/i)) { | ||
} else if (line.match(/\=[\da-f]{0,2}$/i)) { | ||
// push incomplete encoding sequences to the next line | ||
if ((match = line.match(/\=[\da-f]{0,1}$/i))) { | ||
line = line.substr(0, line.length - match[0].length); | ||
} | ||
// push incomplete encoding sequences to the next line | ||
if ((match = line.match(/\=[\da-f]{0,1}$/i))) { | ||
line = line.substr(0, line.length - match[0].length); | ||
// ensure that utf-8 sequences are not split | ||
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/gi))) { | ||
code = parseInt(match[0].substr(1, 2), 16); | ||
if (code < 128) { | ||
break; | ||
} | ||
// ensure that utf-8 sequences are not split | ||
while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))) { | ||
code = parseInt(match[0].substr(1, 2), 16); | ||
if (code < 128) { | ||
break; | ||
} | ||
line = line.substr(0, line.length - 3); | ||
line = line.substr(0, line.length - 3); | ||
if (code >= 0xC0) { | ||
break; | ||
} | ||
if (code >= 0xc0) { | ||
break; | ||
} | ||
@@ -183,3 +176,3 @@ } | ||
function checkRanges(nr, ranges) { | ||
for (var i = ranges.length - 1; i >= 0; i--) { | ||
for (let i = ranges.length - 1; i >= 0; i--) { | ||
if (!ranges[i].length) { | ||
@@ -205,61 +198,63 @@ continue; | ||
*/ | ||
function Encoder(options) { | ||
// init Transform | ||
this.options = options || {}; | ||
class Encoder extends Transform { | ||
constructor(options) { | ||
super(); | ||
if (this.options.lineLength !== false) { | ||
this.options.lineLength = this.options.lineLength || 76; | ||
} | ||
// init Transform | ||
this.options = options || {}; | ||
this._curLine = ''; | ||
if (this.options.lineLength !== false) { | ||
this.options.lineLength = this.options.lineLength || 76; | ||
} | ||
this.inputBytes = 0; | ||
this.outputBytes = 0; | ||
this._curLine = ''; | ||
Transform.call(this, this.options); | ||
} | ||
util.inherits(Encoder, Transform); | ||
this.inputBytes = 0; | ||
this.outputBytes = 0; | ||
Encoder.prototype._transform = function(chunk, encoding, done) { | ||
var qp, _self = this; | ||
if (encoding !== 'buffer') { | ||
chunk = new Buffer(chunk, encoding); | ||
Transform.call(this, this.options); | ||
} | ||
if (!chunk || !chunk.length) { | ||
return done(); | ||
} | ||
_transform(chunk, encoding, done) { | ||
let qp; | ||
this.inputBytes += chunk.length; | ||
if (encoding !== 'buffer') { | ||
chunk = Buffer.from(chunk, encoding); | ||
} | ||
if (this.options.lineLength) { | ||
qp = this._curLine + encode(chunk); | ||
qp = wrap(qp, this.options.lineLength); | ||
qp = qp.replace(/(^|\n)([^\n]*)$/, function(match, lineBreak, lastLine) { | ||
_self._curLine = lastLine; | ||
return lineBreak; | ||
}); | ||
if (!chunk || !chunk.length) { | ||
return done(); | ||
} | ||
if (qp) { | ||
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); | ||
} | ||
} else { | ||
qp = encode(chunk); | ||
this.outputBytes += qp.length; | ||
this.push(qp); | ||
this.push(qp, 'ascii'); | ||
} | ||
} else { | ||
qp = encode(chunk); | ||
this.outputBytes += qp.length; | ||
this.push(qp, 'ascii'); | ||
done(); | ||
} | ||
done(); | ||
}; | ||
Encoder.prototype._flush = function(done) { | ||
if (this._curLine) { | ||
this.outputBytes += this._curLine.length; | ||
this.push(this._curLine, 'ascii'); | ||
_flush(done) { | ||
if (this._curLine) { | ||
this.outputBytes += this._curLine.length; | ||
this.push(this._curLine, 'ascii'); | ||
} | ||
done(); | ||
} | ||
done(); | ||
}; | ||
} | ||
@@ -272,49 +267,60 @@ /** | ||
*/ | ||
function Decoder(options) { | ||
// init Transform | ||
this.options = options || {}; | ||
this._curLine = ''; | ||
class Decoder extends Transform { | ||
constructor(options) { | ||
options = options || {}; | ||
super(options); | ||
this.inputBytes = 0; | ||
this.outputBytes = 0; | ||
// init Transform | ||
this.options = options; | ||
this._curLine = ''; | ||
Transform.call(this, this.options); | ||
} | ||
util.inherits(Decoder, Transform); | ||
this.inputBytes = 0; | ||
this.outputBytes = 0; | ||
} | ||
Decoder.prototype._transform = function(chunk, encoding, done) { | ||
var qp, buf, _self = this; | ||
_transform(chunk, encoding, done) { | ||
let qp, buf; | ||
chunk = chunk.toString('ascii'); | ||
chunk = chunk.toString('ascii'); | ||
if (!chunk || !chunk.length) { | ||
return done(); | ||
} | ||
if (!chunk || !chunk.length) { | ||
return done(); | ||
} | ||
this.inputBytes += chunk.length; | ||
this.inputBytes += chunk.length; | ||
qp = (this._curLine + chunk); | ||
this._curLine = ''; | ||
qp = qp.replace(/=[^\n]?$/, function(lastLine) { | ||
_self._curLine = lastLine; | ||
return ''; | ||
}); | ||
qp = this._curLine + chunk; | ||
this._curLine = ''; | ||
qp = qp.replace(/\=[^\n]?$/, lastLine => { | ||
this._curLine = lastLine; | ||
return ''; | ||
}); | ||
if (qp) { | ||
buf = decode(qp); | ||
this.outputBytes += buf.length; | ||
this.push(buf); | ||
if (qp) { | ||
buf = decode(qp); | ||
this.outputBytes += buf.length; | ||
this.push(buf); | ||
} | ||
done(); | ||
} | ||
done(); | ||
_flush(done) { | ||
let buf; | ||
if (this._curLine) { | ||
buf = decode(this._curLine); | ||
this.outputBytes += buf.length; | ||
this.push(buf); | ||
} | ||
done(); | ||
} | ||
} | ||
// expose to the world | ||
module.exports = { | ||
encode, | ||
decode, | ||
wrap, | ||
Encoder, | ||
Decoder | ||
}; | ||
Decoder.prototype._flush = function(done) { | ||
var qp, buf; | ||
if (this._curLine) { | ||
buf = decode(this._curLine); | ||
this.outputBytes += buf.length; | ||
this.push(buf); | ||
} | ||
done(); | ||
}; |
{ | ||
"name": "libqp", | ||
"version": "1.1.0", | ||
"description": "Encode and decode quoted-printable strings according to rfc2045", | ||
"main": "lib/libqp.js", | ||
"scripts": { | ||
"test": "grunt" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/andris9/libqp.git" | ||
}, | ||
"keywords": [ | ||
"quoted-printable", | ||
"mime" | ||
], | ||
"author": "Andris Reinman", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/andris9/libqp/issues" | ||
}, | ||
"homepage": "https://github.com/andris9/libqp", | ||
"devDependencies": { | ||
"chai": "~3.3.0", | ||
"grunt": "~0.4.5", | ||
"grunt-contrib-jshint": "~0.11.3", | ||
"grunt-mocha-test": "~0.12.7", | ||
"mocha": "^2.3.3" | ||
} | ||
"name": "libqp", | ||
"version": "2.0.0", | ||
"description": "Encode and decode quoted-printable strings according to rfc2045", | ||
"main": "lib/libqp.js", | ||
"scripts": { | ||
"test": "node --test test/" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/andris9/libqp.git" | ||
}, | ||
"keywords": [ | ||
"quoted-printable", | ||
"mime" | ||
], | ||
"author": "Andris Reinman", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/andris9/libqp/issues" | ||
}, | ||
"homepage": "https://github.com/andris9/libqp", | ||
"devDependencies": { | ||
"eslint-config-nodemailer": "1.2.0", | ||
"eslint-config-prettier": "8.5.0" | ||
} | ||
} |
@@ -9,3 +9,5 @@ # libqp | ||
npm install libqp | ||
``` | ||
npm install libqp | ||
``` | ||
@@ -15,3 +17,3 @@ Require in your script | ||
```javascript | ||
var libqp = require('libqp'); | ||
const libqp = require('libqp'); | ||
``` | ||
@@ -23,7 +25,9 @@ | ||
libqp.encode(val) → String | ||
``` | ||
libqp.encode(val) → String | ||
``` | ||
Where | ||
* **val** is a Buffer or an unicode string | ||
- **val** is a Buffer or an unicode string | ||
@@ -43,8 +47,10 @@ **Example** | ||
libqp.wrap(str[, lineLength]) → String | ||
``` | ||
libqp.wrap(str[, lineLength]) → String | ||
``` | ||
Where | ||
* **str** is a Quoted-Printable encoded string | ||
* **lineLength** (defaults to 76) is the maximum allowed line length. Any longer line will be soft wrapped | ||
- **str** is a Quoted-Printable encoded string | ||
- **lineLength** (defaults to 76) is the maximum allowed line length. Any longer line will be soft wrapped | ||
@@ -54,3 +60,3 @@ **Example** | ||
```javascript | ||
libqp.wrap('abc j=C3=B5geva', 10) | ||
libqp.wrap('abc j=C3=B5geva', 10); | ||
// abc j=\r\n | ||
@@ -68,7 +74,9 @@ // =C3=B5geva | ||
var encoder = new libqp.Encoder([options]) | ||
``` | ||
const encoder = new libqp.Encoder([options]) | ||
``` | ||
Where | ||
* **options** is the optional stream options object with an additional option `lineLength` if you want to use any other line length than the default 76 characters (or set to `false` to turn the soft wrapping off completely) | ||
- **options** is the optional stream options object with an additional option `lineLength` if you want to use any other line length than the default 76 characters (or set to `false` to turn the soft wrapping off completely) | ||
@@ -93,7 +101,9 @@ **Example** | ||
var decoder = new libqp.Decoder([options]) | ||
``` | ||
const decoder = new libqp.Decoder([options]) | ||
``` | ||
Where | ||
* **options** is the optional stream options object | ||
- **options** is the optional stream options object | ||
@@ -105,7 +115,7 @@ **Example** | ||
```javascript | ||
var libqp = require('libqp'); | ||
var fs = require('fs'); | ||
var encoded = fs.createReadStream('encoded.txt'); | ||
var dest = fs.createReadStream('dest.txt'); | ||
var decoder = new libqp.Decoder(); | ||
const libqp = require('libqp'); | ||
const fs = require('fs'); | ||
let encoded = fs.createReadStream('encoded.txt'); | ||
let dest = fs.createReadStream('dest.txt'); | ||
let decoder = new libqp.Decoder(); | ||
@@ -117,2 +127,2 @@ encoded.pipe(decoder).pipe(dest); | ||
**MIT** | ||
**MIT** |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14566
2
7
310
120