VimUnDo{\}_{ԅ2^z;xB؈ƌOGlQ_OG5_OG5_OG+$var assert = common.assert;5_OG+9var MultipartParser = common.require('multipart_parser');5_0OG+1var MultipartParser = require(common.dir.lib + ''5_1OG+5var MultipartParser = require(common.dir.lib + 'part'5_0OG+5var MultipartParser = require(common.dir.lib + 'part'5_ 0OG+6var MultipartParser = require(common.dir.lib + '/part'5_ 5OG+5var MultipartParser = require(common.dir.lib + 'part'5_ 0OG+7var MultipartParser = require(common.dir.lib + 'part');5_ OG-var Part = common.require('part');5_ OGAvar boundary = '------WebKitFormBoundarytyE4wkKlZ5CQJVTG';5_  OG)test('MultipartParser', {5_ OG before: function() {5_OG. parser = MultipartParser.create(boundary);5_OG },5_OG5_OG var parser;5_OG5 '#write: error: invalid parser state': function() { parser._state = 'SOMETHING';N assertEmitsError(new Buffer('123'), 'MultipartParser.InvalidParserState'); },7 '#write: error: write without boundary': function() {! var buffer = new Buffer('a');' parser = new MultipartParser(); assert.throws(function() { parser.write(buffer);! }, /Bad state: NO_BOUNDARY/); },A '#write: tolerate missing CRLF on first boundary': function() {6 var buffer = new Buffer('--' + boundary + '\r\n'); parser.write(buffer);0 assert.equal(parser._state, 'HEADER_FIELD'); },* '#write: leading preamble': function() {= parser.write(new Buffer(boundary.substr(0, 4) + 'HAHA'));, assert.equal(parser._state, 'PREAMBLE');7 parser.write(new Buffer('--' + boundary + '\r\n'));0 assert.equal(parser._state, 'HEADER_FIELD'); },5 '#write: error: Invalid header token': function() {P // ',' is an example for an invalid token for header fields (see RFC 2616)0 var buffer = new Buffer('Invalid,Header: ');# parser._state = 'HEADER_FIELD';H assertEmitsError(buffer, 'MultipartParser.InvalidHeaderFieldToken'); },B '#write: Emit part object with lowercased headers': function() {L var buffer = new Buffer('Header-1:value-1\r\nHeader-2:value-2\r\n\r\n');# parser._state = 'HEADER_FIELD'; parser._part = new Part(); parser.write(buffer);, assert.deepEqual(parser._part.headers, { 'header-1': 'value-1', 'header-2': 'value-2', }); },K '#write: Trim leading and trailing header value whitespace': function() {6 var buffer = new Buffer('header: value \r\n\r\n');# parser._state = 'HEADER_FIELD'; parser._part = new Part(); parser.write(buffer);@ assert.deepEqual(parser._part.headers, {'header': 'value'}); },9 // See: http://tools.ietf.org/html/rfc822#section-3.1.3F '#write: Handle multi-line header field value (email)': function() { var buffer = new Buffer(& 'Content-Type: text/html;\r\n' +$ '\tcharset="ISO-8859-4"\r\n' +; 'Content-Transfer-Encoding: quoted-printable\r\n\r\n' );# parser._state = 'HEADER_FIELD'; parser._part = new Part(); parser.write(buffer);, assert.deepEqual(parser._part.headers, {9 'content-type': 'text/html;\tcharset="ISO-8859-4"',6 'content-transfer-encoding': 'quoted-printable', }); },= '#write: error: CR on non-empty _headerField': function() {& var buffer = new Buffer('head\r');# parser._state = 'HEADER_FIELD';H assertEmitsError(buffer, 'MultipartParser.InvalidHeaderFieldToken'); },) '#write: no part headers': function() {$ var buffer = new Buffer('\r\n');# parser._state = 'HEADER_FIELD'; parser._part = new Part(); parser.write(buffer);/ assert.deepEqual(parser._part.headers, {}); },9 '#write: header buffer overflow in field': function() {" parser._headerBufferLimit = 2;" var buffer = new Buffer('ab');# parser._state = 'HEADER_FIELD'; parser.write(buffer);N assertEmitsError(new Buffer('c'), 'MultipartParser.HeaderBufferOverflow'); },( '#write: emit part data': function() { parser._part = new Part(); parser._state = 'PART_BODY'; var expected = [ new Buffer('abc'), new Buffer('def'), ];. parser._part.on('data', function(buffer) {3 assert.equal(''+buffer, ''+expected.shift()); }); parser.write(expected[0]); parser.write(expected[0]);+ assert.strictEqual(expected.length, 0);$ assert.equal(parser._offset, 6); },; '#write: hit partial boundary in part data': function() { parser.boundary('end'); parser._preamble = false;" parser._part = new Part();# parser._state = 'PART_BODY'; var buffers =[];. parser._part.on('data', function(buffer) { buffers.push(''+buffer); });, parser.write(new Buffer('ab\r\n--enc'));7 assert.deepEqual(buffers, ['ab', '\r\n--en', 'c']); },Q '#write: hit partial boundary in part data spread over 2 buffers': function() { parser.boundary('end'); parser._preamble = false;" parser._part = new Part();# parser._state = 'PART_BODY'; var buffers =[];. parser._part.on('data', function(buffer) { buffers.push(''+buffer); });( var first = new Buffer('ab\r\n--e');$ var second = new Buffer('haha'); parser.write(first);$ assert.equal(buffers.length, 1); parser.write(second);9 assert.deepEqual(buffers, ['ab', '\r\n--e', 'haha']); },Q '#write: hit partial boundary in part data spread over 3 buffers': function() { parser.boundary('end'); parser._preamble = false;" parser._part = new Part();# parser._state = 'PART_BODY'; var buffers =[];. parser._part.on('data', function(buffer) { buffers.push(''+buffer); });( var first = new Buffer('ab\r\n--e');! var second = new Buffer('n');# var third = new Buffer('haha'); parser.write(first);$ assert.equal(buffers.length, 1); parser.write(second);$ assert.equal(buffers.length, 1); parser.write(third);: assert.deepEqual(buffers, ['ab', '\r\n--en', 'haha']); },- '#write: full rfc1341 entity': function() { testRfc1341Entity(); },B '#write: full rfc1341 entity with chunk size 1-10': function() {S // What can I say, my ability to visualize this state machine has its limits :)# for (var i = 1; i <= 10; i++) { try { testRfc1341Entity(i); } catch (err) {6 err.message = 'Chunk size: ' + i + ': ' + err; throw err; } } }5_OGV2function assertEmitsError(buffer, expectedError) { var hadError = false;$ parser.on('error', function(err) { hadError = true;M assert.equal(err.message.substr(0, expectedError.length), expectedError); }); parser.write(buffer);. assert.ok(hadError, 'no error was emitted');}'function testRfc1341Entity(chunkSize) {% parser.boundary('simple boundary'); var part1 =6 'This is implicitly typed plain ASCII text.\r\n' +( 'It does NOT end with a linebreak.'; var part2 =6 'This is explicitly typed plain ASCII text.\r\n' +( 'It DOES end with a linebreak.\r\n'; var rfc1341Entity =A 'This is the preamble. It is to be ignored, though it\r\n' += 'is a handy place for mail composers to include an\r\n' +; 'explanatory note to non-MIME compliant readers.\r\n' + '--simple boundary\r\n' + '\r\n' + part1 + '\r\n' + '--simple boundary\r\n' +6 'Content-type: text/plain; charset=us-ascii\r\n' + '\r\n' + part2 + '\r\n' + '--simple boundary--\r\n' +; 'This is the epilogue. It is also to be ignored.\r\n'; var parts = []; var ended = false; parser" .on('error', function(error) { throw error; }) .on('part', function(part) { parts.push(part); part.data = ''; part% .on('data', function(chunk) { part.data += chunk; }) .on('end', function() { part.ended = true; }); }) .on('end', function() { ended = true; });) var buffer = new Buffer(rfc1341Entity); if (!chunkSize) { parser.write(buffer); } else {8 for (var i = 0; i < buffer.length; i += chunkSize) {/ var end = (i + chunkSize < buffer.length) ? i + chunkSize : buffer.length;3 var chunk = new Buffer(buffer.slice(i, end)); parser.write(chunk); } } assert.equal(parts.length, 2);% assert.equal(parts[0].data, part1);% assert.equal(parts[1].data, part2);# parts.forEach(function(part, i) {? assert.ok(part.ended, 'Part ' + (i + 1) + ' did not end.'); }); assert.ok(ended);* // Reset the parser so it can be re-used parser.reset(); parser.removeAllListeners();}5_OG5_OG5_OG ''5_ OG  'test single header parameter'5_ OG  }5_ OG  }<5_OG 5_OG 5_ OG5_! OG   5_ "!OG 5_!#"OG  var part = new Part(0;5_"$# OG 5_#%$OG  5_$&% OG  5_%'&OG% 8var MultipartParser = require(common.dir.lib + '/part');5_&('VOG'-var Part = require(common.dir.lib + '/part');(var assert = require('assert');'var test = require('utest');+var common = require('../common');5_')(VOG*   5_(*) VOG  part.setHeader();5_)+* VOG 5 part.setHeader('boundary=Apple-Mail-3-1061547936;5_*,+ VOG 7 part.setHeader('''boundary=Apple-Mail-3-1061547936;5_+-, !VOG C part.setHeader('Content-Type''boundary=Apple-Mail-3-1061547936;5_,.- VOG  type="text/html");5_-/. EVOG E part.setHeader('Content-Type', 'boundary=Apple-Mail-3-1061547936;5_.0/ $VOG  G part.setHeader('Content-Type', 'boundary=Apple-Mail-3-1061547936');5_/10 $VOG H part.setHeader('Content-Type', ';boundary=Apple-Mail-3-1061547936');5_021 #VOG Y part.setHeader('Content-Type', multipart/related;;boundary=Apple-Mail-3-1061547936');5_132 6VOG Z part.setHeader('Content-Type', 'multipart/related;;boundary=Apple-Mail-3-1061547936');5_253 6VOG  Y part.setHeader('Content-Type', 'multipart/related;boundary=Apple-Mail-3-1061547936');5_3645VOG0 . 'test single header parameter': function() {5_576VOG3   'test getHeade': function() {5_687 VOGB   5_798 VOGD 5_8:9 VOGD  5_9;: VOGi   5_:<; +VOGo 5_;=< *VOGq , var params = part.getHeaderParameters();5_<>= +VOGq . var params = part.getHeaderParameters('');5_=?> VOGs 5_>@? VOGu 5_?A@ VOGx 5_@BA VOG Z part.setHeader('Content-Type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_AEB VOG Z part.setHeader('content-Type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_BFCE +VOG    5_EGF   vOG  assert.equal(val, expected);5_FHG " " )v)OG , assert.equal(params.boundary, expected);5_GIH # @ VvVOG & assert.equal(params.boundary, '');5_HJI  @ VvVOG 5_IKJ @ VvVOG 5_JLK VOG] = assert.equal(params.boundary, 'Apple-Mail-3-1061547936'); : var params = part.getHeaderParameters('Content-Type');  Z part.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');  var part = new Part();5_KML VOG ? //assert.equal(params.boundary, 'Apple-Mail-3-1061547936'); < //var params = part.getHeaderParameters('Content-Type');  \ //part.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');  //var part = new Part();5_LNM VOG= '#getHeaderParameters: Test single parameter': function() {5_MPN' VOG6 '#getHeaderParameters: Test getHeader': function() {5_NQOP . VOG : var params = part.getHeaderParameters('Content-Type');5_PRQ . VOG = assert.equal(params.boundary, 'Apple-Mail-3-1061547936');5_QSR  VOG   5_RTS % VOG    5_SUT   vOG  assert.equal(val, expected);5_TVU   vOG " assert.equal(value, expected);5_UWV   vOG  assert.equal(value, '');5_VXW   vOG  < //var params = part.getHeaderParameters('Content-Type');5_WZX   vOG   ? //assert.equal(params.boundary, 'Apple-Mail-3-1061547936');5_X[YZ   vOGZ    5_Z\[   vOG[!  console.log(var);5_[]\   vOG]"  console.log(value);5_\^]   vOGn    5_]_^   vOGn#  console.log(var);5_^`_   vOGs$  console.log(part);5__a` $  vOGt & var value = part.getHeaderValue();5_`da %  vOGu' ( var value = part.getHeaderValue('');5_aecd,  vOG(; '#getHeaderParameters: Test getHeaderValue': function() {5_dfe,+ +V+OG; '#getHeaderParameters: Test getHeaderValue': function() {5_egf? V?OG5_fhg ?V?OG 5_gih;?V?OGO '#getHeaderParameters: Test getHeaderValue for parameter value': function() {5_hji;?V?OGO '#getHeaderParameters: Test getHeaderValue for parameter value': function() {5_ilj1?V?OGO '#getHeaderParameters: Test getHeaderValue for parameter field': function() {5_jnkl $?V?OG Z part.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_lomn ?V?OG. - assert.equal(value, 'multipart/related');5_npoVOGB5_oqpVOGB5_prqVOGDO '#getHeaderParameters: Test getHeaderValue for parameter field': function() {5_qsrVOGLO '#getHeaderParameters: Test getHeaderValue for parameter field': function() {5_rtsVOGLJ '#getHeaderParameters: getHeaderValue for parameter field': function() {5_sutVOGL; '#getHeaderParameters: for parameter field': function() {5_tvuVOGOL '#getHeaderParameters: Test getHeaderValue for normal field': function() {5_uxvVOGO= '#getHeaderParameters: Test for normal field': function() {5_vywxVOGQ2 '#getHeaderParameters: Test getHe': function() {5_xzyVOGS7 '#getHeaderParameters: parameter field': function() {5_y{zvOGX9 '#getHeaderParameters: Test normal field': function() {5_z|{vOG]/2 '#getHeaderValue: parameter field': function() {5_{}|vOG` '#h: Test getHe': function() {5_|~}vOGf2 '#getHeaderParameters: Test getHe': function() {5_}~vOGi06 '#getHeaderParameters: Simple, single': function() {5_~5vOGo1Z part.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_vOGr4 var value = part.getHeaderValue('content-type');5_vOGv9 var value = part.getHeaderParameters('content-type');5_vOGy- assert.equal(value, 'multipart/related');5_vOG} 5_vOG assert.equal(val, expected);5_ vOG4 assert.equal(value, {});5_vOG9 assert.deepEqual(value, {});5_ VOG%5_ VOG%5_ VOG &1 '#getHeaderParameters: No params': function() {5_!5 VOG "&8 part.setHeader('content-type', 'multipart/related');5_$ VOG#%&! assert.deepEqual(params, {});5_$ VOG#'&! assert.deepEqual(params, {});5_% VOG >$&( 5_  VOG) (5_ VOG) part.headers = {8 part.setHeader('content-type', 'multipart/related');5_ VOG(I part.headers = { part.setHeader('content-type', 'multipart/related');5_ VOG(H part.headers = {part.setHeader('content-type', 'multipart/related');5_ VOG(D part.headers = {.setHeader('content-type', 'multipart/related');5_ VOG(C part.headers = {setHeader('content-type', 'multipart/related');5_ VOG(: part.headers = {('content-type', 'multipart/related');5_ VOG(8 part.headers = {content-type', 'multipart/related');5_" VOG(9 part.headers = {'content-type', 'multipart/related');5_8 VOG(9 part.headers = {'content-type': 'multipart/related');5_ VOG "(5_ VOG )5_ $VOG *1 part.setHeader('content-type', 'text/plain');5_ % % 5v5OG *9 part.headers = {'content-type': 'multipart/related'};5_  % .v5OG ' part.setHeader('content-type', '');5_ % .v5OG)5_$ % .v5OG*Z part.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_%%5v5OG*9 part.headers = {'content-type': 'multipart/related'};5_%Wv5OG' part.setHeader('content-type', '');5_"$"$"$v$OG!#)A part.setHeader('content-type', 'multipart/related; foo=bar');5_!%!%!5v5OGA ")9 part.headers = {'content-type': 'multipart/related'};5_"!%!>v5OGB!"' part.setHeader('content-type', '');5_!%!>v5OG(5_VOG)5_ VOG"04 '#getHeaderValue: Test normal field': function() {5_VOG#0/ '#getHeader: Test normal field': function() {5_ VOG0C 04 var value = part.getHeaderValue('content-type');5_ VOGH 0/ var value = part.getHeader('content-type');5_ (VOGI 0/ var value = part.getHeader('Content-type');5_VOGKD09 '#getHeader: Lowercases given field name': function() {5_VOGNP0: '!#getHeader: Lowercases given field name': function() {5_/V OGkQ1 '#getHeaderParameters: No params': function() { var part = new Part();9 part.headers = {'content-type': 'multipart/related'};: var params = part.getHeaderParameters('content-type');! assert.deepEqual(params, {}); },4 '#getHeaderParameters: Single param': function() { var part = new Part();B part.headers = {'content-type': 'multipart/related; foo=bar'};: var params = part.getHeaderParameters('content-type'); assert.deepEqual(params, { 'foo': 'bar', }); },5_VOGz 0$ var part = new Part({headers: );5_ VOG 0 part.headers = ;5_"VOG 0C var part = new Part({headers: {'content-type': 'text/plain'}});5_ VOG 5_  VOG 5_VOG .5_  VOG 5_ VOGI .5_VOG/ part.headers = ;5_VOG/A var part = new Part(headers: {'content-type': 'text/plain'});5_VOGJ5_?VOG.B var part = new Part(headers: {'content-type': 'text/plain'}});5_VOGK.C var part = new Part({headers: {'content-type': 'text/plain'}});5_VOGN5_VOG- part.headers = 5_VOG-l var part = new Part({headers: {'content-type': 'multipart/related; boundary=Apple-Mail-3-1061547936'};);5_VOG- part.headers = 5_VOG-8 part.headers = ; boundary=Apple-Mail-3-1061547936'};5_VOG5_VOG5_ VOG 0 '#getHeader': function() {5_"$%Wv5OG!#)' part.setHeader('content-type', '');5_!5!%!NvNOG ")S part.headers = {'content-type': 'multipart/relatemultipart/related; foo=bard'};5_%Wv5OG)9 part.headers = {'content-type': 'multipart/related'};5_ VOG 5_vxwVOGO2 '#getHeaderParameters: Test field': function() {5_lnm %?V?OG 2 assert.equal(value, 'multipart/retext/plain');5_jlk 5?V?OG 6 part.setHeader('content-type', 'multipart/related;5_abdc %  vOG| 4 var value = part.getHeaderValue('Content-type');5_acb %  vOG{ 4 var value = part.getHeaderValue('Content-type');5_XZY   vOGH Vpart.setHeader('content-type', 'multipart/related; boundary=Apple-Mail-3-1061547936');5_NPO . VOG 9 var params = part.getHeaderParameters('Conent-Type');5_BDEC +VOG : var params = part.getHeaderParameters('content-Type');5_CD 3VOG : var params = part.getHeaderParameters('content-type');5_354VOG   & 'get header parameter': function() {5_OGV2function assertEmitsError(buffer, expectedError) { var hadError = false;$ parser.on('error', function(err) { hadError = true;M assert.equal(err.message.substr(0, expectedError.length), expectedError); }); parser.write(buffer);. assert.ok(hadError, 'no error was emitted');}'function testRfc1341Entity(chunkSize) {% parser.boundary('simple boundary'); var part1 =6 'This is implicitly typed plain ASCII text.\r\n' +( 'It does NOT end with a linebreak.'; var part2 =6 'This is explicitly typed plain ASCII text.\r\n' +( 'It DOES end with a linebreak.\r\n'; var rfc1341Entity =A 'This is the preamble. It is to be ignored, though it\r\n' += 'is a handy place for mail composers to include an\r\n' +; 'explanatory note to non-MIME compliant readers.\r\n' + '--simple boundary\r\n' + '\r\n' + part1 + '\r\n' + '--simple boundary\r\n' +6 'Content-type: text/plain; charset=us-ascii\r\n' + '\r\n' + part2 + '\r\n' + '--simple boundary--\r\n' +; 'This is the epilogue. It is also to be ignored.\r\n'; var parts = []; var ended = false; parser" .on('error', function(error) { throw error; }) .on('part', function(part) { parts.push(part); part.data = ''; part% .on('data', function(chunk) { part.data += chunk; }) .on('end', function() { part.ended = true; }); }) .on('end', function() { ended = true; });) var buffer = new Buffer(rfc1341Entity); if (!chunkSize) { parser.write(buffer); } else {8 for (var i = 0; i < buffer.length; i += chunkSize) {/ var end = (i + chunkSize < buffer.length) ? i + chunkSize : buffer.length;3 var chunk = new Buffer(buffer.slice(i, end)); parser.write(chunk); } } assert.equal(parts.length, 2);% assert.equal(parts[0].data, part1);% assert.equal(parts[1].data, part2);# parts.forEach(function(part, i) {? assert.ok(part.ended, 'Part ' + (i + 1) + ' did not end.'); }); assert.ok(ended);* // Reset the parser so it can be re-used parser.reset(); parser.removeAllListeners();}5_OGV2function assertEmitsError(buffer, expectedError) { var hadError = false;$ parser.on('error', function(err) { hadError = true;M assert.equal(err.message.substr(0, expectedError.length), expectedError); }); parser.write(buffer);. assert.ok(hadError, 'no error was emitted');}'function testRfc1341Entity(chunkSize) {% parser.boundary('simple boundary'); var part1 =6 'This is implicitly typed plain ASCII text.\r\n' +( 'It does NOT end with a linebreak.'; var part2 =6 'This is explicitly typed plain ASCII text.\r\n' +( 'It DOES end with a linebreak.\r\n'; var rfc1341Entity =A 'This is the preamble. It is to be ignored, though it\r\n' += 'is a handy place for mail composers to include an\r\n' +; 'explanatory note to non-MIME compliant readers.\r\n' + '--simple boundary\r\n' + '\r\n' + part1 + '\r\n' + '--simple boundary\r\n' +6 'Content-type: text/plain; charset=us-ascii\r\n' + '\r\n' + part2 + '\r\n' + '--simple boundary--\r\n' +; 'This is the epilogue. It is also to be ignored.\r\n'; var parts = []; var ended = false; parser" .on('error', function(error) { throw error; }) .on('part', function(part) { parts.push(part); part.data = ''; part% .on('data', function(chunk) { part.data += chunk; }) .on('end', function() { part.ended = true; }); }) .on('end', function() { ended = true; });) var buffer = new Buffer(rfc1341Entity); if (!chunkSize) { parser.write(buffer); } else {8 for (var i = 0; i < buffer.length; i += chunkSize) {/ var end = (i + chunkSize < buffer.length) ? i + chunkSize : buffer.length;3 var chunk = new Buffer(buffer.slice(i, end)); parser.write(chunk); } } assert.equal(parts.length, 2);% assert.equal(parts[0].data, part1);% assert.equal(parts[1].data, part2);# parts.forEach(function(part, i) {? assert.ok(part.ended, 'Part ' + (i + 1) + ' did not end.'); }); assert.ok(ended);* // Reset the parser so it can be re-used parser.reset(); parser.removeAllListeners();}5