@@ -55,6 +55,7 @@ class Boundary
55
55
public int FinalLength { get { return Marker . Length ; } }
56
56
public int Length { get ; private set ; }
57
57
public int MaxLength { get ; private set ; }
58
+ public bool IsMboxMarker { get { return Marker == MboxFrom ; } }
58
59
59
60
public Boundary ( string boundary , int currentMaxLength )
60
61
{
@@ -1222,24 +1223,33 @@ unsafe bool IsPossibleBoundary (byte* text, int length)
1222
1223
return false;
1223
1224
}
1224
1225
1225
- static unsafe bool IsBoundary ( byte * text , int length , byte [ ] boundary , int boundaryLength )
1226
+ static unsafe bool IsBoundary ( byte * text , int length , Boundary boundary , out bool final )
1226
1227
{
1227
- if ( boundaryLength > length )
1228
+ final = false ;
1229
+
1230
+ if ( boundary . Length > length )
1228
1231
return false;
1229
1232
1230
- fixed ( byte * boundaryptr = boundary) {
1233
+ fixed ( byte * boundaryptr = boundary. Marker ) {
1231
1234
// make sure that the text matches the boundary
1232
- if ( ! CStringsEqual ( text , boundaryptr , boundaryLength ) )
1235
+ if ( ! CStringsEqual ( text , boundaryptr , boundary . Length ) )
1233
1236
return false;
1234
1237
1235
1238
// if this is an mbox marker, we're done
1236
- if ( IsMboxMarker ( text ) )
1239
+ if ( boundary . IsMboxMarker ) {
1240
+ final = true;
1237
1241
return true;
1242
+ }
1238
1243
1239
- // the boundary may optionally be followed by lwsp
1240
- byte * inptr = text + boundaryLength ;
1244
+ byte* inptr = text + boundary . Length ;
1241
1245
byte * inend = text + length ;
1242
1246
1247
+ if ( length >= boundary . FinalLength && inptr [ 0 ] == ( byte ) '-' && inptr [ 1 ] == ( byte ) '-' ) {
1248
+ final = true ;
1249
+ inptr += 2 ;
1250
+ }
1251
+
1252
+ // the boundary may optionally be followed by lwsp
1243
1253
while ( inptr < inend ) {
1244
1254
if ( ! ( * inptr ) . IsWhitespace ( ) )
1245
1255
return false;
@@ -1266,28 +1276,30 @@ unsafe BoundaryType CheckBoundary (int startIndex, byte* start, int length)
1266
1276
for ( int i = 0 ; i < count ; i++ ) {
1267
1277
var boundary = bounds[ i] ;
1268
1278
1269
- if ( IsBoundary ( start , length , boundary . Marker , boundary . FinalLength ) )
1270
- return i == 0 ? BoundaryType . ImmediateEndBoundary : BoundaryType . ParentEndBoundary ;
1279
+ if ( IsBoundary ( start , length , boundary , out var final ) ) {
1280
+ if ( final )
1281
+ return i == 0 ? BoundaryType . ImmediateEndBoundary : BoundaryType . ParentEndBoundary ;
1271
1282
1272
- if ( IsBoundary ( start , length , boundary . Marker , boundary . Length ) )
1273
1283
return i == 0 ? BoundaryType . ImmediateBoundary : BoundaryType . ParentBoundary ;
1284
+ }
1274
1285
}
1275
1286
1276
1287
if ( contentEnd > 0 ) {
1277
1288
// now it is time to check the mbox From-marker for the Content-Length case
1278
1289
long curOffset = GetOffset ( startIndex ) ;
1279
1290
var boundary = bounds[ count ] ;
1280
1291
1281
- if ( curOffset >= contentEnd && IsBoundary ( start , length , boundary . Marker , boundary . Length ) )
1292
+ if ( curOffset >= contentEnd && IsBoundary ( start , length , boundary , out _ ) )
1282
1293
return BoundaryType . ImmediateEndBoundary ;
1283
1294
}
1284
1295
1285
1296
return BoundaryType. None ;
1286
1297
}
1287
1298
1288
- unsafe bool FoundImmediateBoundary ( byte * inbuf , bool final )
1299
+ unsafe bool FoundImmediateBoundary ( byte * inbuf , out bool final )
1289
1300
{
1290
- int boundaryLength = final ? bounds [ 0 ] . FinalLength : bounds [ 0 ] . Length ;
1301
+ // TODO: If the MimeReader recorded which boundary marker it found, we wouldn't need to re-scan the input buffer for eoln,
1302
+ // we could just check if boundary[0] == MimeReader.lastFoundBoundary (or whatever we call it).
1291
1303
byte * start = inbuf + inputIndex;
1292
1304
byte * inend = inbuf + inputEnd ;
1293
1305
byte * inptr = start;
@@ -1297,9 +1309,10 @@ unsafe bool FoundImmediateBoundary (byte* inbuf, bool final)
1297
1309
while ( * inptr != ( byte ) '\n ' )
1298
1310
inptr++ ;
1299
1311
1300
- return IsBoundary ( start , ( int ) ( inptr - start ) , bounds [ 0 ] . Marker , boundaryLength ) ;
1312
+ return IsBoundary ( start , ( int ) ( inptr - start ) , bounds [ 0 ] , out final ) ;
1301
1313
}
1302
1314
1315
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
1303
1316
int GetMaxBoundaryLength ( )
1304
1317
{
1305
1318
return bounds. Count > 0 ? bounds [ 0 ] . MaxLength + 2 : 0 ;
@@ -1716,10 +1729,12 @@ unsafe void ConstructMultipart (Multipart multipart, MimeEntityEndEventArgs args
1716
1729
// We either found the end of the stream or we found a parent's boundary
1717
1730
PopBoundary ( ) ;
1718
1731
1719
- if ( boundary == BoundaryType. ParentEndBoundary && FoundImmediateBoundary ( inbuf, true) )
1720
- boundary = BoundaryType. ImmediateEndBoundary;
1721
- else if ( boundary == BoundaryType. ParentBoundary && FoundImmediateBoundary ( inbuf, false) )
1722
- boundary = BoundaryType. ImmediateBoundary;
1732
+ // If the last boundary we found (before popping one off the stack) was a parent's boundary, we need to check
1733
+ // to see if that boundary is now an immediate boundary and update our state.
1734
+ if ( boundary == BoundaryType. ParentEndBoundary || boundary == BoundaryType. ParentBoundary) {
1735
+ if ( FoundImmediateBoundary ( inbuf, out var final) )
1736
+ boundary = final ? BoundaryType. ImmediateEndBoundary : BoundaryType. ImmediateBoundary;
1737
+ }
1723
1738
}
1724
1739
1725
1740
/// <summary>
0 commit comments