Skip to content

Commit da1c0e0

Browse files
committed
Modified ExperimentalMimeParser to also properly handle "double boundaries"
1 parent 4099004 commit da1c0e0

File tree

3 files changed

+109
-6
lines changed

3 files changed

+109
-6
lines changed

MimeKit/ExperimentalMimeParser.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,20 @@ protected override void OnMultipartPreambleEnd (long beginOffset, int beginLineN
673673
/// <param name="cancellationToken">The cancellation token.</param>
674674
protected override void OnMultipartBoundaryRead (byte[] buffer, int startIndex, int count, long beginOffset, int lineNumber, CancellationToken cancellationToken)
675675
{
676-
rawBoundary = new byte[count];
676+
// Note: Each call to OnMultipartBoundaryRead will contain a full boundary marker. If rawBoundary is *not* null,
677+
// then it means that we've encountered a "double boundary". In order to support this scenario, we append the
678+
// second (or third, etc) boundary to the existing rawBoundary buffer.
679+
int rawIndex;
680+
681+
if (rawBoundary != null) {
682+
rawIndex = rawBoundary.Length;
683+
Array.Resize (ref rawBoundary, rawIndex + count);
684+
} else {
685+
rawBoundary = new byte[count];
686+
rawIndex = 0;
687+
}
677688

678-
Buffer.BlockCopy (buffer, startIndex, rawBoundary, 0, count);
689+
Buffer.BlockCopy (buffer, startIndex, rawBoundary, rawIndex, count);
679690
}
680691

681692
/// <summary>

UnitTests/ExperimentalMimeParserTests.cs

+44-2
Original file line numberDiff line numberDiff line change
@@ -2131,9 +2131,20 @@ This is technically the third part.
21312131
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
21322132
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
21332133
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2134+
2135+
using (var memory = new MemoryStream ()) {
2136+
var options = FormatOptions.Default.Clone ();
2137+
options.NewLineFormat = NewLineFormat.Unix;
2138+
2139+
message.WriteTo (options, memory);
2140+
2141+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2142+
Assert.That (output, Is.EqualTo (text));
2143+
}
21342144
}
21352145

2136-
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) {
2146+
text = text.Replace ("\n", "\r\n");
2147+
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) {
21372148
var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity);
21382149
var message = parser.ParseMessage ();
21392150

@@ -2153,6 +2164,16 @@ This is technically the third part.
21532164
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
21542165
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
21552166
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2167+
2168+
using (var memory = new MemoryStream ()) {
2169+
var options = FormatOptions.Default.Clone ();
2170+
options.NewLineFormat = NewLineFormat.Dos;
2171+
2172+
message.WriteTo (options, memory);
2173+
2174+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2175+
Assert.That (output, Is.EqualTo (text));
2176+
}
21562177
}
21572178
}
21582179

@@ -2204,9 +2225,20 @@ This is technically the third part.
22042225
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
22052226
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
22062227
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2228+
2229+
using (var memory = new MemoryStream ()) {
2230+
var options = FormatOptions.Default.Clone ();
2231+
options.NewLineFormat = NewLineFormat.Unix;
2232+
2233+
await message.WriteToAsync (options, memory);
2234+
2235+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2236+
Assert.That (output, Is.EqualTo (text));
2237+
}
22072238
}
22082239

2209-
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) {
2240+
text = text.Replace ("\n", "\r\n");
2241+
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) {
22102242
var parser = new ExperimentalMimeParser (stream, MimeFormat.Entity);
22112243
var message = await parser.ParseMessageAsync ();
22122244

@@ -2226,6 +2258,16 @@ This is technically the third part.
22262258
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
22272259
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
22282260
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2261+
2262+
using (var memory = new MemoryStream ()) {
2263+
var options = FormatOptions.Default.Clone ();
2264+
options.NewLineFormat = NewLineFormat.Dos;
2265+
2266+
await message.WriteToAsync (options, memory);
2267+
2268+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2269+
Assert.That (output, Is.EqualTo (text));
2270+
}
22292271
}
22302272
}
22312273

UnitTests/MimeParserTests.cs

+52-2
Original file line numberDiff line numberDiff line change
@@ -2147,9 +2147,22 @@ This is technically the third part.
21472147
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
21482148
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
21492149
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2150+
2151+
#if false // TODO: Bring MimeParser up to par with ExperimentalMimeParser
2152+
using (var memory = new MemoryStream ()) {
2153+
var options = FormatOptions.Default.Clone ();
2154+
options.NewLineFormat = NewLineFormat.Unix;
2155+
2156+
message.WriteTo (options, memory);
2157+
2158+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2159+
Assert.That (output, Is.EqualTo (text));
2160+
}
2161+
#endif
21502162
}
21512163

2152-
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) {
2164+
text = text.Replace ("\n", "\r\n");
2165+
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) {
21532166
var parser = new MimeParser (stream, MimeFormat.Entity);
21542167
var message = parser.ParseMessage ();
21552168

@@ -2169,6 +2182,18 @@ This is technically the third part.
21692182
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
21702183
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
21712184
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2185+
2186+
#if false // TODO: Bring MimeParser up to par with ExperimentalMimeParser
2187+
using (var memory = new MemoryStream ()) {
2188+
var options = FormatOptions.Default.Clone ();
2189+
options.NewLineFormat = NewLineFormat.Dos;
2190+
2191+
message.WriteTo (options, memory);
2192+
2193+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2194+
Assert.That (output, Is.EqualTo (text));
2195+
}
2196+
#endif
21722197
}
21732198
}
21742199

@@ -2220,9 +2245,22 @@ This is technically the third part.
22202245
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
22212246
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
22222247
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2248+
2249+
#if false // TODO: Bring MimeParser up to par with ExperimentalMimeParser
2250+
using (var memory = new MemoryStream ()) {
2251+
var options = FormatOptions.Default.Clone ();
2252+
options.NewLineFormat = NewLineFormat.Unix;
2253+
2254+
await message.WriteToAsync (options, memory);
2255+
2256+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2257+
Assert.That (output, Is.EqualTo (text));
2258+
}
2259+
#endif
22232260
}
22242261

2225-
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text.Replace ("\n", "\r\n")), false)) {
2262+
text.Replace ("\n", "\r\n");
2263+
using (var stream = new MemoryStream (Encoding.ASCII.GetBytes (text), false)) {
22262264
var parser = new MimeParser (stream, MimeFormat.Entity);
22272265
var message = await parser.ParseMessageAsync ();
22282266

@@ -2242,6 +2280,18 @@ This is technically the third part.
22422280
Assert.That (body.Headers[HeaderId.ContentType], Is.EqualTo ("text/plain; charset=utf-8"));
22432281
Assert.That (body.ContentType.Charset, Is.EqualTo ("utf-8"));
22442282
Assert.That (body.Text, Is.EqualTo ("This is technically the third part." + Environment.NewLine));
2283+
2284+
#if false // TODO: Bring MimeParser up to par with ExperimentalMimeParser
2285+
using (var memory = new MemoryStream ()) {
2286+
var options = FormatOptions.Default.Clone ();
2287+
options.NewLineFormat = NewLineFormat.Dos;
2288+
2289+
await message.WriteToAsync (options, memory);
2290+
2291+
var output = Encoding.ASCII.GetString (memory.GetBuffer (), 0, (int) memory.Length);
2292+
Assert.That (output, Is.EqualTo (text));
2293+
}
2294+
#endif
22452295
}
22462296
}
22472297

0 commit comments

Comments
 (0)