Beispiel #1
0
 public MimeString this[int index]
 {
     get {
         if (index == 0)
             return first;
         if (index < 4096)
             return overflow[index].Str;
         return overflow[4096 + index/4096 - 1].Secondary[index%4096];
     }
     set {
         if (overflow != null)
             overflow[0].HeaderTotalLength += value.Length - this[index].Length;
         if (index == 0)
             first = value;
         else if (index < 4096)
             overflow[index].Str = value;
         else
             overflow[4096 + index/4096 - 1].Secondary[index%4096] = value;
     }
 }
Beispiel #2
0
 public static bool IsPureASCII(MimeString str)
 {
     var flag = true;
     for (var index = 0; index < str.Length; ++index) {
         if (str[index] >= 128) {
             flag = false;
             break;
         }
     }
     return flag;
 }
Beispiel #3
0
 internal void AppendLine(MimeString line)
 {
     this.AppendLine(line, true);
 }
Beispiel #4
0
 public static int ParseToken(MimeString str, out int characterCount, bool allowUTF8)
 {
     return MimeScan.FindEndOf(MimeScan.Token.Token, str.Data, str.Offset, str.Length, out characterCount, allowUTF8);
 }
Beispiel #5
0
 public void Reset(bool cleanMimeState)
 {
     this.StreamMode = false;
     this.ContentType = MajorContentType.Other;
     Epilogue = false;
     this.TransferEncoding = ContentTransferEncoding.SevenBit;
     if (cleanMimeState)
         this.IsMime = false;
     boundaryValue = new MimeString();
     boundaryCrc = 0U;
     endBoundaryCrc = 0U;
     this.PartDepth = 0;
 }
Beispiel #6
0
 private static bool IsUUEncodeBegin(byte[] data, int line, int nextNL)
 {
     var mimeString = new MimeString(data, line, nextNL - line);
     if (mimeString.Length < 13 || !mimeString.HasPrefixEq(UUBegin, 0, 6))
         return false;
     var index = 6;
     while (index < 10 && (48 <= mimeString[index] && 55 >= mimeString[index]))
         ++index;
     return index != 6 && 32 == mimeString[index];
 }
Beispiel #7
0
 private bool IsQuotingRequired(MimeString mimeStr, bool allowUTF8)
 {
     var writeState = WriteState.Begin;
     var mimeString = new MimeString(WordBreakBytes, 0, WordBreakBytes.Length);
     int offset;
     int count;
     var data = mimeStr.GetData(out offset, out count);
     while (count != 0) {
         switch (writeState) {
             case WriteState.Begin:
                 var characterCount = 0;
                 var endOf = MimeScan.FindEndOf(MimeScan.Token.Atom, data, offset, count, out characterCount, allowUTF8);
                 if (endOf == 0) {
                     if (count <= 3 || offset != 0 || !mimeString.HasPrefixEq(data, 0, 3))
                         return true;
                     offset += 3;
                     count -= 3;
                     writeState = WriteState.Begin;
                     continue;
                 }
                 offset += endOf;
                 count -= endOf;
                 writeState = WriteState.Atom;
                 continue;
             case WriteState.Atom:
                 if ((count < 2 || data[offset] != 32) && (count < 1 || data[offset] != 46))
                     return true;
                 ++offset;
                 --count;
                 writeState = WriteState.Begin;
                 continue;
             default:
                 continue;
         }
     }
     return false;
 }
Beispiel #8
0
 private void Parse()
 {
     this.Reset();
     parsed = true;
     var headerDecodingOptions = this.GetHeaderDecodingOptions();
     var valueParser = new ValueParser(this.Lines, headerDecodingOptions.AllowUTF8);
     var mimeStringList1 = new MimeStringList();
     var mimeStringList2 = new MimeStringList();
     var mimeString1 = new MimeString();
     var mimeString2 = MimeString.Empty;
     var parseState1 = ParseState.None;
     while (true) {
         valueParser.ParseWhitespace(true, ref mimeStringList1);
         var num1 = valueParser.ParseGet();
         if (num1 != 0) {
             if (59 == num1)
                 parseState1 = ParseState.Date;
             else if (40 == num1 && parseState1 == ParseState.DomainValue)
                 parseState1 = ParseState.DomainAddress;
             else {
                 valueParser.ParseUnget();
                 mimeString1 = valueParser.ParseToken();
                 if (mimeString1.Length == 0) {
                     int num2 = valueParser.ParseGet();
                     mimeStringList2.TakeOverAppend(ref mimeStringList1);
                     valueParser.ParseAppendLastByte(ref mimeStringList2);
                     continue;
                 }
                 var parseState2 = this.StateFromToken(mimeString1);
                 if (ParseState.None != parseState2)
                     parseState1 = parseState2;
             }
             switch (parseState1) {
                 case ParseState.Domain:
                 case ParseState.OptInfo:
                     if (mimeString2.Length != 0)
                         this.FinishClause(ref mimeString2, ref mimeStringList2, headerDecodingOptions.AllowUTF8);
                     else
                         mimeStringList2.Reset();
                     mimeString2 = mimeString1;
                     valueParser.ParseWhitespace(false, ref mimeStringList1);
                     mimeStringList1.Reset();
                     ++parseState1;
                     continue;
                 case ParseState.DomainValue:
                     mimeStringList2.TakeOverAppend(ref mimeStringList1);
                     mimeStringList2.AppendFragment(mimeString1);
                     continue;
                 case ParseState.DomainAddress:
                     var flag = mimeString2.CompareEqI(ParamFrom);
                     this.FinishClause(ref mimeString2, ref mimeStringList2, headerDecodingOptions.AllowUTF8);
                     mimeStringList1.Reset();
                     valueParser.ParseUnget();
                     valueParser.ParseComment(true, false, ref mimeStringList2, true);
                     var sz1 = mimeStringList2.GetSz();
                     var str = sz1 == null ? null : Internal.ByteString.BytesToString(sz1, headerDecodingOptions.AllowUTF8);
                     if (flag)
                         fromTcpInfoValue = str;
                     else
                         byTcpInfoValue = str;
                     mimeStringList2.Reset();
                     parseState1 = ParseState.None;
                     continue;
                 case ParseState.OptInfoValue:
                     mimeStringList2.TakeOverAppend(ref mimeStringList1);
                     mimeStringList2.AppendFragment(mimeString1);
                     continue;
                 case ParseState.Date:
                     this.FinishClause(ref mimeString2, ref mimeStringList2, headerDecodingOptions.AllowUTF8);
                     mimeStringList1.Reset();
                     valueParser.ParseWhitespace(false, ref mimeStringList1);
                     valueParser.ParseToEnd(ref mimeStringList2);
                     var sz2 = mimeStringList2.GetSz();
                     dateValue = sz2 == null ? null : Internal.ByteString.BytesToString(sz2, false);
                     continue;
                 case ParseState.None:
                     mimeStringList2.Reset();
                     continue;
                 default:
                     continue;
             }
         }
         break;
     }
     this.FinishClause(ref mimeString2, ref mimeStringList2, headerDecodingOptions.AllowUTF8);
 }
Beispiel #9
0
 public void AppendFragment(MimeString refLine)
 {
     var count = this.Count;
     if (count != 0) {
         var index = count - 1;
         if (index == 0) {
             if (first.MergeIfAdjacent(refLine)) {
                 if (overflow == null)
                     return;
                 overflow[0].HeaderTotalLength += refLine.Length;
                 return;
             }
         } else if (index < 4096) {
             if (overflow[index].StrMergeIfAdjacent(refLine)) {
                 overflow[0].HeaderTotalLength += refLine.Length;
                 return;
             }
         } else if (overflow[4096 + index/4096 - 1].Secondary[index%4096].MergeIfAdjacent(refLine)) {
             overflow[0].HeaderTotalLength += refLine.Length;
             return;
         }
     }
     this.Append(refLine);
 }
Beispiel #10
0
 internal static MimeStringList EncodeValue(string value, EncodingOptions encodingOptions, ValueEncodingStyle style)
 {
     if (string.IsNullOrEmpty(value))
         return MimeStringList.Empty;
     if (!MimeCommon.IsEncodingRequired(value, encodingOptions.AllowUTF8))
         return new MimeStringList(new MimeString(value));
     var mimeStringList = new MimeStringList();
     Globalization.Charset charset;
     if (encodingOptions.CharsetName != null)
         charset = encodingOptions.GetEncodingCharset();
     else {
         var codePageDetector = new Globalization.OutboundCodePageDetector();
         codePageDetector.AddText(value);
         if (!Globalization.Charset.TryGetCharset(codePageDetector.GetCodePage(), out charset))
             charset = DefaultEncodingOptions.GetEncodingCharset();
     }
     var charClasses = Schema.Mime.Encoders.ByteEncoder.Tables.CharClasses.QEncode;
     if (style == ValueEncodingStyle.Phrase)
         charClasses |= Schema.Mime.Encoders.ByteEncoder.Tables.CharClasses.QPhraseUnsafe;
     else if (style == ValueEncodingStyle.Comment)
         charClasses |= Schema.Mime.Encoders.ByteEncoder.Tables.CharClasses.QCommentUnsafe;
     var allowQEncoding = false;
     CalculateMethodAndChunkSize methodAndChunkSize;
     if (charset.Kind == Globalization.CodePageKind.Sbcs) {
         methodAndChunkSize = calculateMethodAndChunkSizeSbcs;
         if (charset.AsciiSupport >= Globalization.CodePageAsciiSupport.Fine)
             allowQEncoding = true;
     } else if (charset.Kind == Globalization.CodePageKind.Dbcs) {
         methodAndChunkSize = calculateMethodAndChunkSizeDbcs;
         if (charset.AsciiSupport >= Globalization.CodePageAsciiSupport.Fine)
             allowQEncoding = true;
     } else if (charset.CodePage == 65001) {
         methodAndChunkSize = calculateMethodAndChunkSizeUtf8;
         allowQEncoding = true;
     } else {
         methodAndChunkSize = charset.CodePage == 1200 || charset.CodePage == 1201
                                  ? calculateMethodAndChunkSizeUnicode16
                                  : (charset.CodePage == 12000 || charset.CodePage == 12001 ? calculateMethodAndChunkSizeUnicode32 : calculateMethodAndChunkSizeMbcs);
     }
     var num1 = 75;
     var num2 = 7 + charset.Name.Length;
     var num3 = num1 - num2;
     if (num3 < 32) {
         num1 = num2 + 32;
         num3 = 32;
     }
     var byteBuffer = Internal.ScratchPad.GetByteBuffer(num3);
     var encoding = charset.GetEncoding();
     var numArray1 = new byte[5 + charset.Name.Length];
     var num4 = 0;
     var numArray2 = numArray1;
     var index1 = num4;
     var num5 = 1;
     var num6 = index1 + num5;
     var num7 = 61;
     numArray2[index1] = (byte) num7;
     var numArray3 = numArray1;
     var index2 = num6;
     var num8 = 1;
     var bytesOffset = index2 + num8;
     var num9 = 63;
     numArray3[index2] = (byte) num9;
     var num10 = bytesOffset + Internal.ByteString.StringToBytes(charset.Name, numArray1, bytesOffset, false);
     var numArray4 = numArray1;
     var index3 = num10;
     var num11 = 1;
     var num12 = index3 + num11;
     var num13 = 63;
     numArray4[index3] = (byte) num13;
     var numArray5 = numArray1;
     var index4 = num12;
     var num14 = 1;
     var num15 = index4 + num14;
     var num16 = 88;
     numArray5[index4] = (byte) num16;
     var numArray6 = numArray1;
     var index5 = num15;
     var num17 = 1;
     var num18 = index5 + num17;
     var num19 = 63;
     numArray6[index5] = (byte) num19;
     var mimeString = new MimeString(numArray1);
     var num20 = 0;
     byte[] numArray7 = null;
     var count = 0;
     var num21 = num3/4;
     while (num20 != value.Length) {
         byte method;
         int chunkSize;
         methodAndChunkSize(allowQEncoding, charClasses, encoding, value, num20, num3, out method, out chunkSize);
         label_25:
         int bytes;
         int outputOffset;
         while (true) {
             do {
                 do {
                     try {
                         bytes = encoding.GetBytes(value, num20, chunkSize, byteBuffer, 0);
                     } catch (System.ArgumentException ex) {
                         if (chunkSize < 2)
                             throw;
                         chunkSize -= chunkSize > 10 ? 3 : 1;
                         if (MimeCommon.IsLowSurrogate(value[num20 + chunkSize])) {
                             if (MimeCommon.IsHighSurrogate(value[num20 + chunkSize - 1]))
                                 --chunkSize;
                         }
                         goto label_25;
                     }
                     if (bytes != 0) {
                         if (numArray7 == null || numArray7.Length - count < num1 + 1) {
                             if (numArray7 != null) {
                                 mimeStringList.Append(new MimeString(numArray7, 0, count));
                                 count = 0;
                             }
                             numArray7 = new byte[System.Math.Min(((value.Length - num20)/chunkSize + 1)*(num1 + 1), 4096/(num1 + 1)*(num1 + 1))];
                         }
                         var destinationIndex = count;
                         if (mimeStringList.Count > 0 || destinationIndex > 0)
                             numArray7[destinationIndex++] = 32;
                         outputOffset = destinationIndex + mimeString.CopyTo(numArray7, destinationIndex);
                         numArray7[outputOffset - 2] = method;
                         if (method == 81) {
                             var num22 = outputOffset;
                             int index6;
                             for (index6 = 0; index6 < bytes && outputOffset - num22 + 1 <= num3; ++index6) {
                                 var num23 = byteBuffer[index6];
                                 if (MimeCommon.QEncodingRequired((char) num23, charClasses)) {
                                     if (outputOffset - num22 + 3 <= num3) {
                                         var numArray8 = numArray7;
                                         var index7 = outputOffset;
                                         var num24 = 1;
                                         var num25 = index7 + num24;
                                         var num26 = 61;
                                         numArray8[index7] = (byte) num26;
                                         var numArray9 = numArray7;
                                         var index8 = num25;
                                         var num27 = 1;
                                         var num28 = index8 + num27;
                                         int num29 = Schema.Mime.Encoders.ByteEncoder.NibbleToHex[num23 >> 4];
                                         numArray9[index8] = (byte) num29;
                                         var numArray10 = numArray7;
                                         var index9 = num28;
                                         var num30 = 1;
                                         outputOffset = index9 + num30;
                                         int num31 = Schema.Mime.Encoders.ByteEncoder.NibbleToHex[num23 & 15];
                                         numArray10[index9] = (byte) num31;
                                     } else
                                         break;
                                 } else {
                                     if (num23 == 32)
                                         num23 = 95;
                                     numArray7[outputOffset++] = num23;
                                 }
                             }
                             if (index6 != bytes) {
                                 if (chunkSize < 2)
                                     throw new System.InvalidOperationException("unexpected thing just happened");
                                 chunkSize -= chunkSize > 10 ? 3 : 1;
                             } else
                                 goto label_56;
                         } else
                             goto label_55;
                     } else
                         goto label_57;
                 } while (!MimeCommon.IsLowSurrogate(value[num20 + chunkSize]));
             } while (!MimeCommon.IsHighSurrogate(value[num20 + chunkSize - 1]));
             --chunkSize;
         }
         label_55:
         outputOffset += MimeCommon.Base64EncodeChunk(byteBuffer, 0, bytes, numArray7, outputOffset);
         label_56:
         var numArray11 = numArray7;
         var index10 = outputOffset;
         var num32 = 1;
         var num33 = index10 + num32;
         var num34 = 63;
         numArray11[index10] = (byte) num34;
         var numArray12 = numArray7;
         var index11 = num33;
         var num35 = 1;
         var num36 = index11 + num35;
         var num37 = 61;
         numArray12[index11] = (byte) num37;
         count = num36;
         label_57:
         num20 += chunkSize;
     }
     if (numArray7 != null)
         mimeStringList.Append(new MimeString(numArray7, 0, count));
     return mimeStringList;
 }
Beispiel #11
0
 internal MimeString(MimeString original, int offset, int count)
 {
     this.Data = original.Data;
     this.Offset = offset;
     this.LengthAndMask = (uint) (count | -268435456);
 }
Beispiel #12
0
 public MimeString(byte[] data)
 {
     this = new MimeString(data, 0, data.Length);
 }
Beispiel #13
0
 internal bool MergeIfAdjacent(MimeString refString)
 {
     if (this.Data != refString.Data || this.Offset + this.Length != refString.Offset || (int) this.Mask != (int) refString.Mask)
         return false;
     this.LengthAndMask += (uint) refString.Length;
     return true;
 }
Beispiel #14
0
 internal bool CompareEqI(MimeString str2)
 {
     return Internal.ByteString.EqualsI(this.Data, this.Offset, this.Length, str2.Data, str2.Offset, str2.Length, true);
 }
Beispiel #15
0
 public void Append(MimeString value)
 {
     if (value.Length == 0)
         return;
     var count = this.Count;
     if (count == 0) {
         first = value;
         if (overflow == null)
             return;
         ++overflow[0].HeaderCount;
         overflow[0].HeaderTotalLength += value.Length;
     } else if (count < 4096) {
         if (overflow == null) {
             overflow = new ListEntry[8];
             overflow[0].HeaderCount = 1;
             overflow[0].HeaderTotalLength = first.Length;
         } else if (count == overflow.Length) {
             var length = count*2;
             if (length >= 4096)
                 length = 4128;
             var listEntryArray = new ListEntry[length];
             System.Array.Copy(overflow, 0, listEntryArray, 0, overflow.Length);
             overflow = listEntryArray;
         }
         overflow[count].Str = value;
         ++overflow[0].HeaderCount;
         overflow[0].HeaderTotalLength += value.Length;
     } else {
         var index1 = 4096 + count/4096 - 1;
         var index2 = count%4096;
         if (index1 >= overflow.Length)
             throw new MimeException("MIME is too complex (header value is too long)");
         if (overflow[index1].Secondary == null)
             overflow[index1].Secondary = new MimeString[4096];
         overflow[index1].Secondary[index2] = value;
         ++overflow[0].HeaderCount;
         overflow[0].HeaderTotalLength += value.Length;
     }
 }
Beispiel #16
0
 private void FinishClause(ref MimeString param, ref MimeStringList value, bool allowUTF8)
 {
     if (param.Length == 0)
         return;
     var sz = value.GetSz();
     var str = sz == null ? null : Internal.ByteString.BytesToString(sz, allowUTF8);
     var crcI = param.ComputeCrcI();
     if (crcI <= 2556329580U) {
         if ((int) crcI != 271896810) {
             if ((int) crcI != 2115158205) {
                 if ((int) crcI == -1738637716)
                     fromValue = str;
             } else
                 byValue = str;
         } else
             forValue = str;
     } else if ((int) crcI != -1177273070) {
         if ((int) crcI != -554265150) {
             if ((int) crcI == -18844241)
                 idValue = str;
         } else
             viaValue = str;
     } else
         withValue = str;
     value.Reset();
     param = MimeString.Empty;
 }
Beispiel #17
0
 public MimeStringList(byte[] data)
 {
     first = new MimeString(data, 0, data.Length);
     overflow = null;
 }
Beispiel #18
0
 private ParseState StateFromToken(MimeString token)
 {
     var crcI = token.ComputeCrcI();
     if (crcI <= 2556329580U) {
         if ((int) crcI == 271896810)
             return ParseState.OptInfo;
         if ((int) crcI == 2115158205 || (int) crcI == -1738637716)
             return ParseState.Domain;
     } else if ((int) crcI == -1177273070 || (int) crcI == -554265150 || (int) crcI == -18844241)
         return ParseState.OptInfo;
     return ParseState.None;
 }
Beispiel #19
0
 public void Reset()
 {
     first = new MimeString();
     if (overflow == null)
         return;
     overflow[0].Reset();
 }
Beispiel #20
0
 public void SetContentType(MajorContentType contentType, MimeString boundaryValue)
 {
     currentLevel.SetContentType(contentType, boundaryValue);
     if (contentType == MajorContentType.Multipart)
         return;
     nextBoundaryLevel = -1;
 }
Beispiel #21
0
 public void TakeOver(ref MimeStringList list, uint mask)
 {
     if ((int) mask == -268435456) {
         first = list.first;
         overflow = list.overflow;
         list.first = new MimeString();
         list.overflow = null;
     } else {
         this.Reset();
         this.TakeOverAppend(ref list, mask);
     }
 }
Beispiel #22
0
 private static bool IsUUEncodeEnd(byte[] data, int line, int nextNL)
 {
     var mimeString = new MimeString(data, line, nextNL - line);
     return mimeString.Length >= 3 && mimeString.HasPrefixEq(UUEnd, 0, 3);
 }
Beispiel #23
0
 public MimeStringList(byte[] data, int offset, int count)
 {
     first = new MimeString(data, offset, count);
     overflow = null;
 }
Beispiel #24
0
 public void SetContentType(MajorContentType contentType, MimeString boundaryValue)
 {
     if (contentType == MajorContentType.Multipart) {
         int offset;
         int count;
         var data = boundaryValue.GetData(out offset, out count);
         var numArray = new byte[MimeString.TwoDashes.Length + count + MimeString.TwoDashes.Length];
         var length = MimeString.TwoDashes.Length;
         System.Buffer.BlockCopy(MimeString.TwoDashes, 0, numArray, 0, length);
         System.Buffer.BlockCopy(data, offset, numArray, length, count);
         var num1 = length + count;
         boundaryCrc = Internal.ByteString.ComputeCrc(numArray, 0, num1);
         System.Buffer.BlockCopy(MimeString.TwoDashes, 0, numArray, num1, MimeString.TwoDashes.Length);
         var num2 = num1 + MimeString.TwoDashes.Length;
         endBoundaryCrc = Internal.ByteString.ComputeCrc(numArray, 0, num2);
         this.boundaryValue = new MimeString(numArray, 0, num2);
     } else {
         this.boundaryValue = new MimeString();
         boundaryCrc = 0U;
         endBoundaryCrc = 0U;
     }
     this.ContentType = contentType;
 }
Beispiel #25
0
 public MimeStringList(MimeString str)
 {
     first = str;
     overflow = null;
 }
 internal override void AppendLine(MimeString line, bool markDirty)
 {
     if (parsed)
         this.Reset();
     base.AppendLine(line, markDirty);
 }
Beispiel #27
0
 public bool StrMergeIfAdjacent(MimeString refLine)
 {
     var str = this.Str;
     if (!str.MergeIfAdjacent(refLine))
         return false;
     this.Str = str;
     return true;
 }
Beispiel #28
0
 internal virtual void AppendLine(MimeString line, bool markDirty)
 {
     this.RawValueAboutToChange();
     lines.Append(line);
     if (!markDirty)
         return;
     this.SetDirty();
 }
Beispiel #29
0
 internal MimeString(MimeString original, int offset, int count, uint mask)
 {
     this.Data = original.Data;
     this.Offset = offset;
     this.LengthAndMask = (uint) count | mask;
 }