@ -2,7 +2,8 @@ var EventEmitter = require('events').EventEmitter,
ReadableStream = require ( 'stream' ) . Readable || require ( 'readable-stream' ) ,
ReadableStream = require ( 'stream' ) . Readable || require ( 'readable-stream' ) ,
inherits = require ( 'util' ) . inherits ,
inherits = require ( 'util' ) . inherits ,
inspect = require ( 'util' ) . inspect ,
inspect = require ( 'util' ) . inspect ,
utf7 = require ( 'utf7' ) . imap ;
utf7 = require ( 'utf7' ) . imap ,
iconv = require ( 'iconv-lite' ) ;
var CH _LF = 10 ,
var CH _LF = 10 ,
LITPLACEHOLDER = String . fromCharCode ( 0 ) ,
LITPLACEHOLDER = String . fromCharCode ( 0 ) ,
@ -17,7 +18,9 @@ var CH_LF = 10,
RE _TAGGED = /^A(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i ,
RE _TAGGED = /^A(\d+) (OK|NO|BAD) (?:\[([^\]]+)\] )?(.+)$/i ,
RE _CONTINUE = /^\+ (?:\[([^\]]+)\] )?(.+)$/i ,
RE _CONTINUE = /^\+ (?:\[([^\]]+)\] )?(.+)$/i ,
RE _CRLF = /\r\n/g ,
RE _CRLF = /\r\n/g ,
RE _HDR = /^([^:]+):[ \t]?(.+)?$/ ;
RE _HDR = /^([^:]+):[ \t]?(.+)?$/ ,
RE _ENCWORD = /=\?([^?]*?)\?([qb])\?(.*?)\?=/gi ,
RE _QENC = /(?:=([a-fA-F0-9]{2}))|_/g ;
function Parser ( stream , debug ) {
function Parser ( stream , debug ) {
if ( ! ( this instanceof Parser ) )
if ( ! ( this instanceof Parser ) )
@ -637,7 +640,28 @@ function convStr(str, literals) {
return str ;
return str ;
}
}
function parseHeader ( str ) {
function decodeWords ( str ) {
return str . replace ( RE _ENCWORD ,
function ( match , charset , encoding , word ) {
encoding = encoding . toLowerCase ( ) ;
if ( encoding === 'q' ) {
// q-encoding, similar to quoted-printable
return iconv . decode ( new Buffer ( word . replace ( RE _QENC ,
function ( match2 , byte ) {
if ( match2 === '_' )
return ' ' ;
else
return String . fromCharCode ( parseInt ( byte , 16 ) ) ;
}
) , 'binary' ) , charset ) ;
} else {
// base64
return iconv . decode ( new Buffer ( word , 'base64' ) , charset ) ;
}
} ) ;
}
function parseHeader ( str , noDecode ) {
var lines = str . split ( RE _CRLF ) ,
var lines = str . split ( RE _CRLF ) ,
len = lines . length ,
len = lines . length ,
header = { } ,
header = { } ,
@ -647,6 +671,8 @@ function parseHeader(str) {
if ( lines [ i ] . length === 0 )
if ( lines [ i ] . length === 0 )
continue ;
continue ;
if ( lines [ i ] [ 0 ] === '\t' || lines [ i ] [ 0 ] === ' ' ) {
if ( lines [ i ] [ 0 ] === '\t' || lines [ i ] [ 0 ] === ' ' ) {
if ( ! noDecode )
lines [ i ] = decodeWords ( lines [ i ] ) ;
// folded header content
// folded header content
// RFC2822 says to just remove the CRLF and not the whitespace following
// RFC2822 says to just remove the CRLF and not the whitespace following
// it, so we follow the RFC and include the leading whitespace ...
// it, so we follow the RFC and include the leading whitespace ...
@ -656,6 +682,9 @@ function parseHeader(str) {
if ( m ) {
if ( m ) {
h = m [ 1 ] . toLowerCase ( ) ;
h = m [ 1 ] . toLowerCase ( ) ;
if ( m [ 2 ] ) {
if ( m [ 2 ] ) {
if ( ! noDecode )
m [ 2 ] = decodeWords ( m [ 2 ] ) ;
if ( header [ h ] === undefined )
if ( header [ h ] === undefined )
header [ h ] = [ m [ 2 ] ] ;
header [ h ] = [ m [ 2 ] ] ;
else
else