@@ -70,10 +70,7 @@ class Indexer {
7070
7171 let finalize = ( ) => {
7272 if ( node . boundary ) {
73- append ( `--${ node . boundary } --` ) ;
74- if ( node . epilogue && node . epilogue . length ) {
75- size += node . epilogue . length ;
76- }
73+ append ( `--${ node . boundary } --\r\n` ) ;
7774 }
7875
7976 append ( ) ;
@@ -85,21 +82,7 @@ class Indexer {
8582 if ( ! node . boundary ) {
8683 append ( false , true ) ; // force newline
8784 }
88- let nodeSize = Number ( node . size ) ;
89- if ( ! Number . isFinite ( nodeSize ) ) {
90- if ( Buffer . isBuffer ( node . body ) ) {
91- nodeSize = node . body . length ;
92- } else if ( node . body && node . body . buffer && Buffer . isBuffer ( node . body . buffer ) ) {
93- nodeSize = node . body . buffer . length ;
94- } else if ( typeof node . body === 'string' ) {
95- nodeSize = Buffer . byteLength ( node . body , 'binary' ) ;
96- } else if ( Array . isArray ( node . body ) ) {
97- nodeSize = Buffer . byteLength ( node . body . join ( '' ) , 'binary' ) ;
98- } else {
99- nodeSize = 0 ;
100- }
101- }
102- size += nodeSize ;
85+ size += node . size ;
10386 }
10487
10588 if ( node . boundary ) {
@@ -153,8 +136,6 @@ class Indexer {
153136
154137 let curWritePos = 0 ;
155138 let writeLength = 0 ;
156- let lastByte = null ;
157- let forceSeparator = false ;
158139
159140 let getCurrentBounds = size => {
160141 if ( curWritePos + size < startFrom ) {
@@ -185,10 +166,6 @@ class Indexer {
185166 if ( ! chunk || ! chunk . length ) {
186167 return ;
187168 }
188- chunk = normalizeChunk ( chunk ) ;
189- if ( ! chunk || ! chunk . length ) {
190- return ;
191- }
192169
193170 if ( curWritePos >= startFrom ) {
194171 // already allowed to write
@@ -219,7 +196,6 @@ class Indexer {
219196 }
220197 }
221198
222- lastByte = chunk [ chunk . length - 1 ] ;
223199 if ( output . write ( chunk ) === false ) {
224200 await new Promise ( resolve => {
225201 output . once ( 'drain' , resolve ( ) ) ;
@@ -236,10 +212,7 @@ class Indexer {
236212 let emit = async ( data , force ) => {
237213 if ( remainder || data || force ) {
238214 if ( ! firstLine ) {
239- if ( forceSeparator || lastByte !== 0x0a ) {
240- await write ( NEWLINE ) ;
241- }
242- forceSeparator = false ;
215+ await write ( NEWLINE ) ;
243216 } else {
244217 firstLine = false ;
245218 }
@@ -262,11 +235,9 @@ class Indexer {
262235
263236 if ( ! textOnly || ! isRootNode ) {
264237 await emit ( formatHeaders ( node . header ) . join ( '\r\n' ) + '\r\n' ) ;
265- forceSeparator = true ;
266238 }
267239
268240 isRootNode = false ;
269- let epilogue = null ;
270241 if ( Buffer . isBuffer ( node . body ) ) {
271242 // node Buffer
272243 remainder = node . body ;
@@ -281,16 +252,6 @@ class Indexer {
281252 remainder = node . body ;
282253 }
283254
284- if ( node . boundary ) {
285- if ( node . epilogue && node . epilogue . length ) {
286- epilogue = normalizeChunk ( node . epilogue ) ;
287- } else if ( remainder && remainder . length ) {
288- let splitBody = splitMultipartBody ( remainder ) ;
289- remainder = splitBody . preamble ;
290- epilogue = splitBody . epilogue ;
291- }
292- }
293-
294255 if ( node . boundary ) {
295256 // this is a multipart node, so start with initial boundary before continuing
296257 await emit ( `--${ node . boundary } ` ) ;
@@ -328,62 +289,33 @@ class Indexer {
328289 }
329290 }
330291
331- let attachmentSize = Number ( node . size ) ;
332- if ( ! Number . isFinite ( attachmentSize ) ) {
333- attachmentSize = Number ( attachmentData && attachmentData . metadata && attachmentData . metadata . esize ) ;
334- }
335- if ( ! Number . isFinite ( attachmentSize ) ) {
336- attachmentSize = Number ( attachmentData && attachmentData . length ) ;
337- }
338- if ( ! Number . isFinite ( attachmentSize ) ) {
339- attachmentSize = 0 ;
340- }
341- let nodeTransferEncoding = ( ( node . parsedHeader && node . parsedHeader [ 'content-transfer-encoding' ] ) || '7bit' )
342- . toString ( )
343- . toLowerCase ( )
344- . trim ( ) ;
292+ let attachmentSize = node . size ;
345293 // we need to calculate expected length as the original does not apply anymore
346294 // original size matches input data but decoding/encoding is not 100% lossless so we need to
347295 // calculate the actual possible output size
348296 if ( attachmentData . metadata && attachmentData . metadata . decoded && attachmentData . metadata . lineLen ) {
349297 let b64Size = Math . ceil ( attachmentData . length / 3 ) * 4 ;
350- let lineBreaks = Math . floor ( ( b64Size - 1 ) / attachmentData . metadata . lineLen ) ;
351- let storedLineCount = normalizeLineCount ( attachmentData . metadata . lineCount ) ;
352-
353- if ( storedLineCount !== null ) {
354- lineBreaks = storedLineCount ;
355- } else if ( attachmentData . metadata . esize ) {
356- let recovered = Math . floor ( ( attachmentData . metadata . esize - b64Size ) / 2 ) ;
357- if ( recovered >= 0 ) {
358- lineBreaks = Math . max ( lineBreaks , recovered ) ;
359- }
360- }
298+ let lineBreaks = Math . floor ( b64Size / attachmentData . metadata . lineLen ) ;
361299
362- let computedSize = b64Size + lineBreaks * 2 ;
363- if ( Number . isFinite ( attachmentSize ) ) {
364- attachmentSize = Math . max ( attachmentSize , computedSize ) ;
365- } else {
366- attachmentSize = computedSize ;
300+ // extra case where base64 string ends at line end
301+ // in this case we do not need the ending line break
302+ if ( lineBreaks && b64Size % attachmentData . metadata . lineLen === 0 ) {
303+ lineBreaks -- ;
367304 }
305+
306+ attachmentSize = b64Size + lineBreaks * 2 ;
368307 }
369308
370309 let readBounds = getCurrentBounds ( attachmentSize ) ;
371310 if ( readBounds ) {
372311 // move write pointer ahead by skipped base64 bytes
373- let bytes = Math . min ( readBounds . startFrom , attachmentSize ) ;
312+ let bytes = Math . min ( readBounds . startFrom , node . size ) ;
374313 curWritePos += bytes ;
375314
376315 // only process attachment if we are reading inside existing bounds
377- if ( attachmentSize > readBounds . startFrom ) {
316+ if ( node . size > readBounds . startFrom ) {
378317 let attachmentStream = this . attachmentStorage . createReadStream ( attachmentId , attachmentData , readBounds ) ;
379318 await new Promise ( ( resolve , reject ) => {
380- let attachmentOutputBytes = 0 ;
381- attachmentStream . on ( 'data' , chunk => {
382- if ( chunk && chunk . length ) {
383- lastByte = chunk [ chunk . length - 1 ] ;
384- attachmentOutputBytes += chunk . length ;
385- }
386- } ) ;
387319 attachmentStream . once ( 'error' , err => {
388320 if ( err . code === 'ENOENT' ) {
389321 this . loggelf ( {
@@ -398,36 +330,16 @@ class Indexer {
398330
399331 attachmentStream . once ( 'end' , ( ) => {
400332 // update read offset counters
401- let bytes = attachmentOutputBytes ;
402-
403- if ( ! bytes && 'outputBytes' in attachmentStream ) {
404- bytes = attachmentStream . outputBytes ;
405- }
406333
407- if ( ! bytes ) {
408- bytes = readBounds . maxLength ;
409- }
334+ let bytes = 'outputBytes' in attachmentStream ? attachmentStream . outputBytes : readBounds . maxLength ;
410335
411336 if ( bytes ) {
412337 curWritePos += bytes ;
413338 if ( maxLength ) {
414339 writeLength += bytes ;
415340 }
416341 }
417-
418- if ( ! output . isLimited && attachmentSize && bytes && bytes < attachmentSize ) {
419- let missing = attachmentSize - bytes ;
420- if ( missing > 0 && missing % 2 === 0 ) {
421- let transferEncoding = ( attachmentData && attachmentData . transferEncoding ) || nodeTransferEncoding ;
422- if ( transferEncoding === 'base64' ) {
423- return write ( Buffer . alloc ( missing , '\r\n' ) )
424- . then ( resolve )
425- . catch ( reject ) ;
426- }
427- }
428- }
429-
430- return resolve ( ) ;
342+ resolve ( ) ;
431343 } ) ;
432344
433345 attachmentStream . pipe ( output , {
@@ -455,17 +367,18 @@ class Indexer {
455367 }
456368
457369 if ( node . boundary ) {
458- await emit ( `--${ node . boundary } --` ) ;
459- if ( epilogue && epilogue . length ) {
460- await write ( epilogue ) ;
461- }
370+ await emit ( `--${ node . boundary } --\r\n` ) ;
462371 }
463372
464373 await emit ( ) ;
465374 } ;
466375
467376 await walk ( mimeTree ) ;
468377
378+ if ( mimeTree . lineCount > 1 ) {
379+ await write ( NEWLINE ) ;
380+ }
381+
469382 output . end ( ) ;
470383 } ;
471384
@@ -966,81 +879,6 @@ function formatHeaders(headers) {
966879 return headers ;
967880}
968881
969- function normalizeChunk ( chunk ) {
970- if ( ! chunk ) {
971- return chunk ;
972- }
973- if ( Buffer . isBuffer ( chunk ) ) {
974- return chunk ;
975- }
976- if ( chunk . buffer && Buffer . isBuffer ( chunk . buffer ) ) {
977- return chunk . buffer ;
978- }
979- if ( typeof chunk === 'string' ) {
980- return Buffer . from ( chunk , 'binary' ) ;
981- }
982- try {
983- return Buffer . from ( chunk ) ;
984- } catch {
985- return null ;
986- }
987- }
988-
989- function normalizeLineCount ( value ) {
990- if ( typeof value === 'number' && Number . isFinite ( value ) && value >= 0 ) {
991- return value ;
992- }
993- if ( ! value ) {
994- return null ;
995- }
996- if ( typeof value . toNumber === 'function' ) {
997- const num = value . toNumber ( ) ;
998- if ( Number . isFinite ( num ) && num >= 0 ) {
999- return num ;
1000- }
1001- }
1002- const coerced = Number ( value ) ;
1003- if ( Number . isFinite ( coerced ) && coerced >= 0 ) {
1004- return coerced ;
1005- }
1006- return null ;
1007- }
1008-
1009- function splitMultipartBody ( body ) {
1010- if ( ! body || ! body . length ) {
1011- return { preamble : body , epilogue : null } ;
1012- }
1013-
1014- let buffer = Buffer . isBuffer ( body ) ? body : Buffer . from ( body , 'binary' ) ;
1015-
1016- // Find last non-linebreak byte to ensure there is actual content.
1017- let lastContent = buffer . length - 1 ;
1018- while ( lastContent >= 0 && ( buffer [ lastContent ] === 0x0d || buffer [ lastContent ] === 0x0a ) ) {
1019- lastContent -- ;
1020- }
1021-
1022- if ( lastContent < 0 ) {
1023- return { preamble : buffer , epilogue : null } ;
1024- }
1025-
1026- let pos = buffer . length ;
1027- let crlfCount = 0 ;
1028- while ( pos >= 2 && buffer [ pos - 2 ] === 0x0d && buffer [ pos - 1 ] === 0x0a ) {
1029- crlfCount ++ ;
1030- pos -= 2 ;
1031- }
1032-
1033- if ( crlfCount <= 1 ) {
1034- return { preamble : buffer , epilogue : null } ;
1035- }
1036-
1037- let splitIndex = buffer . length - ( crlfCount - 1 ) * 2 ;
1038- return {
1039- preamble : buffer . slice ( 0 , splitIndex ) ,
1040- epilogue : buffer . slice ( splitIndex )
1041- } ;
1042- }
1043-
1044882function textToHtml ( str ) {
1045883 let encoded = he
1046884 // encode special chars
0 commit comments