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; } }
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; }
internal void AppendLine(MimeString line) { this.AppendLine(line, true); }
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); }
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; }
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]; }
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; }
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); }
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); }
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; }
internal MimeString(MimeString original, int offset, int count) { this.Data = original.Data; this.Offset = offset; this.LengthAndMask = (uint) (count | -268435456); }
public MimeString(byte[] data) { this = new MimeString(data, 0, data.Length); }
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; }
internal bool CompareEqI(MimeString str2) { return Internal.ByteString.EqualsI(this.Data, this.Offset, this.Length, str2.Data, str2.Offset, str2.Length, true); }
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; } }
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; }
public MimeStringList(byte[] data) { first = new MimeString(data, 0, data.Length); overflow = null; }
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; }
public void Reset() { first = new MimeString(); if (overflow == null) return; overflow[0].Reset(); }
public void SetContentType(MajorContentType contentType, MimeString boundaryValue) { currentLevel.SetContentType(contentType, boundaryValue); if (contentType == MajorContentType.Multipart) return; nextBoundaryLevel = -1; }
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); } }
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); }
public MimeStringList(byte[] data, int offset, int count) { first = new MimeString(data, offset, count); overflow = null; }
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; }
public MimeStringList(MimeString str) { first = str; overflow = null; }
internal override void AppendLine(MimeString line, bool markDirty) { if (parsed) this.Reset(); base.AppendLine(line, markDirty); }
public bool StrMergeIfAdjacent(MimeString refLine) { var str = this.Str; if (!str.MergeIfAdjacent(refLine)) return false; this.Str = str; return true; }
internal virtual void AppendLine(MimeString line, bool markDirty) { this.RawValueAboutToChange(); lines.Append(line); if (!markDirty) return; this.SetDirty(); }
internal MimeString(MimeString original, int offset, int count, uint mask) { this.Data = original.Data; this.Offset = offset; this.LengthAndMask = (uint) count | mask; }