| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.Xml
- {
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.IO;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.Text;
- using System.Security;
- using System.Security.Permissions;
- public interface IXmlMtomReaderInitializer
- {
- void SetInput(byte[] buffer, int offset, int count, Encoding[] encodings, string contentType, XmlDictionaryReaderQuotas quotas, int maxBufferSize, OnXmlDictionaryReaderClose onClose);
- void SetInput(Stream stream, Encoding[] encodings, string contentType, XmlDictionaryReaderQuotas quotas, int maxBufferSize, OnXmlDictionaryReaderClose onClose);
- }
- class XmlMtomReader : XmlDictionaryReader, IXmlLineInfo, IXmlMtomReaderInitializer
- {
- Encoding[] encodings;
- XmlDictionaryReader xmlReader;
- XmlDictionaryReader infosetReader;
- MimeReader mimeReader;
- Dictionary<string, MimePart> mimeParts;
- OnXmlDictionaryReaderClose onClose;
- bool readingBinaryElement;
- int maxBufferSize;
- int bufferRemaining;
- MimePart part;
- public XmlMtomReader()
- {
- }
- internal static void DecrementBufferQuota(int maxBuffer, ref int remaining, int size)
- {
- if (remaining - size <= 0)
- {
- remaining = 0;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomBufferQuotaExceeded, maxBuffer)));
- }
- else
- {
- remaining -= size;
- }
- }
- void SetReadEncodings(Encoding[] encodings)
- {
- if (encodings == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encodings");
- for (int i = 0; i < encodings.Length; i++)
- {
- if (encodings[i] == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(String.Format(CultureInfo.InvariantCulture, "encodings[{0}]", i));
- }
- this.encodings = new Encoding[encodings.Length];
- encodings.CopyTo(this.encodings, 0);
- }
- void CheckContentType(string contentType)
- {
- if (contentType != null && contentType.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MtomContentTypeInvalid), "contentType"));
- }
- public void SetInput(byte[] buffer, int offset, int count, Encoding[] encodings, string contentType, XmlDictionaryReaderQuotas quotas, int maxBufferSize, OnXmlDictionaryReaderClose onClose)
- {
- SetInput(new MemoryStream(buffer, offset, count), encodings, contentType, quotas, maxBufferSize, onClose);
- }
- public void SetInput(Stream stream, Encoding[] encodings, string contentType, XmlDictionaryReaderQuotas quotas, int maxBufferSize, OnXmlDictionaryReaderClose onClose)
- {
- SetReadEncodings(encodings);
- CheckContentType(contentType);
- Initialize(stream, contentType, quotas, maxBufferSize);
- this.onClose = onClose;
- }
- void Initialize(Stream stream, string contentType, XmlDictionaryReaderQuotas quotas, int maxBufferSize)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- this.maxBufferSize = maxBufferSize;
- this.bufferRemaining = maxBufferSize;
- string boundary, start, startInfo;
- if (contentType == null)
- {
- MimeMessageReader messageReader = new MimeMessageReader(stream);
- MimeHeaders messageHeaders = messageReader.ReadHeaders(this.maxBufferSize, ref this.bufferRemaining);
- ReadMessageMimeVersionHeader(messageHeaders.MimeVersion);
- ReadMessageContentTypeHeader(messageHeaders.ContentType, out boundary, out start, out startInfo);
- stream = messageReader.GetContentStream();
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageInvalidContent)));
- }
- else
- {
- ReadMessageContentTypeHeader(new ContentTypeHeader(contentType), out boundary, out start, out startInfo);
- }
- this.mimeReader = new MimeReader(stream, boundary);
- this.mimeParts = null;
- this.readingBinaryElement = false;
- MimePart infosetPart = (start == null) ? ReadRootMimePart() : ReadMimePart(GetStartUri(start));
- byte[] infosetBytes = infosetPart.GetBuffer(this.maxBufferSize, ref this.bufferRemaining);
- int infosetByteCount = (int)infosetPart.Length;
- Encoding encoding = ReadRootContentTypeHeader(infosetPart.Headers.ContentType, this.encodings, startInfo);
- CheckContentTransferEncodingOnRoot(infosetPart.Headers.ContentTransferEncoding);
- IXmlTextReaderInitializer initializer = xmlReader as IXmlTextReaderInitializer;
- if (initializer != null)
- initializer.SetInput(infosetBytes, 0, infosetByteCount, encoding, quotas, null);
- else
- xmlReader = XmlDictionaryReader.CreateTextReader(infosetBytes, 0, infosetByteCount, encoding, quotas, null);
- }
- public override XmlDictionaryReaderQuotas Quotas
- {
- get
- {
- return this.xmlReader.Quotas;
- }
- }
- void ReadMessageMimeVersionHeader(MimeVersionHeader header)
- {
- if (header != null && header.Version != MimeVersionHeader.Default.Version)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageInvalidMimeVersion, header.Version, MimeVersionHeader.Default.Version)));
- }
- void ReadMessageContentTypeHeader(ContentTypeHeader header, out string boundary, out string start, out string startInfo)
- {
- if (header == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageContentTypeNotFound)));
- if (String.Compare(MtomGlobals.MediaType, header.MediaType, StringComparison.OrdinalIgnoreCase) != 0
- || String.Compare(MtomGlobals.MediaSubtype, header.MediaSubtype, StringComparison.OrdinalIgnoreCase) != 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageNotMultipart, MtomGlobals.MediaType, MtomGlobals.MediaSubtype)));
- string type;
- if (!header.Parameters.TryGetValue(MtomGlobals.TypeParam, out type) || MtomGlobals.XopType != type)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageNotApplicationXopXml, MtomGlobals.XopType)));
- if (!header.Parameters.TryGetValue(MtomGlobals.BoundaryParam, out boundary))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageRequiredParamNotSpecified, MtomGlobals.BoundaryParam)));
- if (!MailBnfHelper.IsValidMimeBoundary(boundary))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomBoundaryInvalid, boundary)));
- if (!header.Parameters.TryGetValue(MtomGlobals.StartParam, out start))
- start = null;
- if (!header.Parameters.TryGetValue(MtomGlobals.StartInfoParam, out startInfo))
- startInfo = null;
- }
- Encoding ReadRootContentTypeHeader(ContentTypeHeader header, Encoding[] expectedEncodings, string expectedType)
- {
- if (header == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootContentTypeNotFound)));
- if (String.Compare(MtomGlobals.XopMediaType, header.MediaType, StringComparison.OrdinalIgnoreCase) != 0
- || String.Compare(MtomGlobals.XopMediaSubtype, header.MediaSubtype, StringComparison.OrdinalIgnoreCase) != 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootNotApplicationXopXml, MtomGlobals.XopMediaType, MtomGlobals.XopMediaSubtype)));
- string charset;
- if (!header.Parameters.TryGetValue(MtomGlobals.CharsetParam, out charset)
- || charset == null || charset.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootRequiredParamNotSpecified, MtomGlobals.CharsetParam)));
- Encoding encoding = null;
- for (int i = 0; i < encodings.Length; i++)
- {
- if (String.Compare(charset, expectedEncodings[i].WebName, StringComparison.OrdinalIgnoreCase) == 0)
- {
- encoding = expectedEncodings[i];
- break;
- }
- }
- if (encoding == null)
- {
- // Check for alternate names
- if (String.Compare(charset, "utf-16LE", StringComparison.OrdinalIgnoreCase) == 0)
- {
- for (int i = 0; i < encodings.Length; i++)
- {
- if (String.Compare(expectedEncodings[i].WebName, Encoding.Unicode.WebName, StringComparison.OrdinalIgnoreCase) == 0)
- {
- encoding = expectedEncodings[i];
- break;
- }
- }
- }
- else if (String.Compare(charset, "utf-16BE", StringComparison.OrdinalIgnoreCase) == 0)
- {
- for (int i = 0; i < encodings.Length; i++)
- {
- if (String.Compare(expectedEncodings[i].WebName, Encoding.BigEndianUnicode.WebName, StringComparison.OrdinalIgnoreCase) == 0)
- {
- encoding = expectedEncodings[i];
- break;
- }
- }
- }
- if (encoding == null)
- {
- StringBuilder expectedCharSetStr = new StringBuilder();
- for (int i = 0; i < encodings.Length; i++)
- {
- if (expectedCharSetStr.Length != 0)
- expectedCharSetStr.Append(" | ");
- expectedCharSetStr.Append(encodings[i].WebName);
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootUnexpectedCharset, charset, expectedCharSetStr.ToString())));
- }
- }
- if (expectedType != null)
- {
- string rootType;
- if (!header.Parameters.TryGetValue(MtomGlobals.TypeParam, out rootType)
- || rootType == null || rootType.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootRequiredParamNotSpecified, MtomGlobals.TypeParam)));
- if (rootType != expectedType)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootUnexpectedType, rootType, expectedType)));
- }
- return encoding;
- }
- // 7bit is default encoding in the absence of content-transfer-encoding header
- void CheckContentTransferEncodingOnRoot(ContentTransferEncodingHeader header)
- {
- if (header != null && header.ContentTransferEncoding == ContentTransferEncoding.Other)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomContentTransferEncodingNotSupported,
- header.Value,
- ContentTransferEncodingHeader.SevenBit.ContentTransferEncodingValue,
- ContentTransferEncodingHeader.EightBit.ContentTransferEncodingValue,
- ContentTransferEncodingHeader.Binary.ContentTransferEncodingValue)));
- }
- void CheckContentTransferEncodingOnBinaryPart(ContentTransferEncodingHeader header)
- {
- if (header == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomContentTransferEncodingNotPresent,
- ContentTransferEncodingHeader.Binary.ContentTransferEncodingValue)));
- else if (header.ContentTransferEncoding != ContentTransferEncoding.Binary)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomInvalidTransferEncodingForMimePart,
- header.Value, ContentTransferEncodingHeader.Binary.ContentTransferEncodingValue)));
- }
- string GetStartUri(string startUri)
- {
- if (startUri.StartsWith("<", StringComparison.Ordinal))
- {
- if (startUri.EndsWith(">", StringComparison.Ordinal))
- return startUri;
- else
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomInvalidStartUri, startUri)));
- }
- else
- return String.Format(CultureInfo.InvariantCulture, "<{0}>", startUri);
- }
- public override bool Read()
- {
- bool retVal = xmlReader.Read();
- if (xmlReader.NodeType == XmlNodeType.Element)
- {
- XopIncludeReader binaryDataReader = null;
- if (xmlReader.IsStartElement(MtomGlobals.XopIncludeLocalName, MtomGlobals.XopIncludeNamespace))
- {
- string uri = null;
- while (xmlReader.MoveToNextAttribute())
- {
- if (xmlReader.LocalName == MtomGlobals.XopIncludeHrefLocalName && xmlReader.NamespaceURI == MtomGlobals.XopIncludeHrefNamespace)
- uri = xmlReader.Value;
- else if (xmlReader.NamespaceURI == MtomGlobals.XopIncludeNamespace)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomXopIncludeInvalidXopAttributes, xmlReader.LocalName, MtomGlobals.XopIncludeNamespace)));
- }
- if (uri == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomXopIncludeHrefNotSpecified, MtomGlobals.XopIncludeHrefLocalName)));
- MimePart mimePart = ReadMimePart(uri);
- CheckContentTransferEncodingOnBinaryPart(mimePart.Headers.ContentTransferEncoding);
- this.part = mimePart;
- binaryDataReader = new XopIncludeReader(mimePart, xmlReader);
- binaryDataReader.Read();
- xmlReader.MoveToElement();
- if (xmlReader.IsEmptyElement)
- {
- xmlReader.Read();
- }
- else
- {
- int xopDepth = xmlReader.Depth;
- xmlReader.ReadStartElement();
- while (xmlReader.Depth > xopDepth)
- {
- if (xmlReader.IsStartElement() && xmlReader.NamespaceURI == MtomGlobals.XopIncludeNamespace)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomXopIncludeInvalidXopElement, xmlReader.LocalName, MtomGlobals.XopIncludeNamespace)));
- xmlReader.Skip();
- }
- xmlReader.ReadEndElement();
- }
- }
- if (binaryDataReader != null)
- {
- this.xmlReader.MoveToContent();
- this.infosetReader = this.xmlReader;
- this.xmlReader = binaryDataReader;
- binaryDataReader = null;
- }
- }
- if (xmlReader.ReadState == ReadState.EndOfFile && infosetReader != null)
- {
- // Read past the containing EndElement if necessary
- if (!retVal)
- retVal = infosetReader.Read();
- this.part.Release(this.maxBufferSize, ref this.bufferRemaining);
- xmlReader = infosetReader;
- infosetReader = null;
- }
- return retVal;
- }
- MimePart ReadMimePart(string uri)
- {
- MimePart part = null;
- if (uri == null || uri.Length == 0)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomInvalidEmptyURI)));
- string contentID = null;
- if (uri.StartsWith(MimeGlobals.ContentIDScheme, StringComparison.Ordinal))
- contentID = String.Format(CultureInfo.InvariantCulture, "<{0}>", Uri.UnescapeDataString(uri.Substring(MimeGlobals.ContentIDScheme.Length)));
- else if (uri.StartsWith("<", StringComparison.Ordinal))
- contentID = uri;
- if (contentID == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomInvalidCIDUri, uri)));
- if (mimeParts != null && mimeParts.TryGetValue(contentID, out part))
- {
- if (part.ReferencedFromInfoset)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMimePartReferencedMoreThanOnce, contentID)));
- }
- else
- {
- int maxMimeParts = AppSettings.MaxMimeParts;
- while (part == null && mimeReader.ReadNextPart())
- {
- MimeHeaders headers = mimeReader.ReadHeaders(this.maxBufferSize, ref this.bufferRemaining);
- Stream contentStream = mimeReader.GetContentStream();
- if (contentStream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageInvalidContentInMimePart)));
- ContentIDHeader contentIDHeader = (headers == null) ? null : headers.ContentID;
- if (contentIDHeader == null || contentIDHeader.Value == null)
- {
- // Skip content if Content-ID header is not present
- int size = 256;
- byte[] bytes = new byte[size];
- int read = 0;
- do
- {
- read = contentStream.Read(bytes, 0, size);
- }
- while (read > 0);
- continue;
- }
- string currentContentID = headers.ContentID.Value;
- MimePart currentPart = new MimePart(contentStream, headers);
- if (mimeParts == null)
- mimeParts = new Dictionary<string, MimePart>();
- mimeParts.Add(currentContentID, currentPart);
- if (mimeParts.Count > maxMimeParts)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MaxMimePartsExceeded, maxMimeParts, AppSettings.MaxMimePartsAppSettingsString)));
- if (currentContentID.Equals(contentID))
- part = currentPart;
- else
- currentPart.GetBuffer(this.maxBufferSize, ref this.bufferRemaining);
- }
- if (part == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomPartNotFound, uri)));
- }
- part.ReferencedFromInfoset = true;
- return part;
- }
- MimePart ReadRootMimePart()
- {
- MimePart part = null;
- if (!mimeReader.ReadNextPart())
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomRootPartNotFound)));
- MimeHeaders headers = mimeReader.ReadHeaders(this.maxBufferSize, ref this.bufferRemaining);
- Stream contentStream = mimeReader.GetContentStream();
- if (contentStream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.MtomMessageInvalidContentInMimePart)));
- part = new MimePart(contentStream, headers);
- return part;
- }
- void AdvanceToContentOnElement()
- {
- if (NodeType != XmlNodeType.Attribute)
- {
- MoveToContent();
- }
- }
- public override int AttributeCount
- {
- get
- {
- return xmlReader.AttributeCount;
- }
- }
- public override string BaseURI
- {
- get
- {
- return xmlReader.BaseURI;
- }
- }
- public override bool CanReadBinaryContent
- {
- get
- {
- return xmlReader.CanReadBinaryContent;
- }
- }
- public override bool CanReadValueChunk
- {
- get
- {
- return xmlReader.CanReadValueChunk;
- }
- }
- public override bool CanResolveEntity
- {
- get
- {
- return xmlReader.CanResolveEntity;
- }
- }
- public override void Close()
- {
- xmlReader.Close();
- mimeReader.Close();
- OnXmlDictionaryReaderClose onClose = this.onClose;
- this.onClose = null;
- if (onClose != null)
- {
- try
- {
- onClose(this);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e)) throw;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
- }
- }
- }
- public override int Depth
- {
- get
- {
- return xmlReader.Depth;
- }
- }
- public override bool EOF
- {
- get
- {
- return xmlReader.EOF;
- }
- }
- public override string GetAttribute(int index)
- {
- return xmlReader.GetAttribute(index);
- }
- public override string GetAttribute(string name)
- {
- return xmlReader.GetAttribute(name);
- }
- public override string GetAttribute(string name, string ns)
- {
- return xmlReader.GetAttribute(name, ns);
- }
- public override string GetAttribute(XmlDictionaryString localName, XmlDictionaryString ns)
- {
- return xmlReader.GetAttribute(localName, ns);
- }
- #if NO
- public override ArraySegment<byte> GetSubset(bool advance)
- {
- return xmlReader.GetSubset(advance);
- }
- #endif
- public override bool HasAttributes
- {
- get
- {
- return xmlReader.HasAttributes;
- }
- }
- public override bool HasValue
- {
- get
- {
- return xmlReader.HasValue;
- }
- }
- public override bool IsDefault
- {
- get
- {
- return xmlReader.IsDefault;
- }
- }
- public override bool IsEmptyElement
- {
- get
- {
- return xmlReader.IsEmptyElement;
- }
- }
- public override bool IsLocalName(string localName)
- {
- return xmlReader.IsLocalName(localName);
- }
- public override bool IsLocalName(XmlDictionaryString localName)
- {
- return xmlReader.IsLocalName(localName);
- }
- public override bool IsNamespaceUri(string ns)
- {
- return xmlReader.IsNamespaceUri(ns);
- }
- public override bool IsNamespaceUri(XmlDictionaryString ns)
- {
- return xmlReader.IsNamespaceUri(ns);
- }
- public override bool IsStartElement()
- {
- return xmlReader.IsStartElement();
- }
- public override bool IsStartElement(string localName)
- {
- return xmlReader.IsStartElement(localName);
- }
- public override bool IsStartElement(string localName, string ns)
- {
- return xmlReader.IsStartElement(localName, ns);
- }
- public override bool IsStartElement(XmlDictionaryString localName, XmlDictionaryString ns)
- {
- return xmlReader.IsStartElement(localName, ns);
- }
- #if NO
- public override bool IsStartSubsetElement()
- {
- return xmlReader.IsStartSubsetElement();
- }
- #endif
- public override string LocalName
- {
- get
- {
- return xmlReader.LocalName;
- }
- }
- public override string LookupNamespace(string ns)
- {
- return xmlReader.LookupNamespace(ns);
- }
- public override void MoveToAttribute(int index)
- {
- xmlReader.MoveToAttribute(index);
- }
- public override bool MoveToAttribute(string name)
- {
- return xmlReader.MoveToAttribute(name);
- }
- public override bool MoveToAttribute(string name, string ns)
- {
- return xmlReader.MoveToAttribute(name, ns);
- }
- public override bool MoveToElement()
- {
- return xmlReader.MoveToElement();
- }
- public override bool MoveToFirstAttribute()
- {
- return xmlReader.MoveToFirstAttribute();
- }
- public override bool MoveToNextAttribute()
- {
- return xmlReader.MoveToNextAttribute();
- }
- public override string Name
- {
- get
- {
- return xmlReader.Name;
- }
- }
- public override string NamespaceURI
- {
- get
- {
- return xmlReader.NamespaceURI;
- }
- }
- public override XmlNameTable NameTable
- {
- get
- {
- return xmlReader.NameTable;
- }
- }
- public override XmlNodeType NodeType
- {
- get
- {
- return xmlReader.NodeType;
- }
- }
- public override string Prefix
- {
- get
- {
- return xmlReader.Prefix;
- }
- }
- public override char QuoteChar
- {
- get
- {
- return xmlReader.QuoteChar;
- }
- }
- public override bool ReadAttributeValue()
- {
- return xmlReader.ReadAttributeValue();
- }
- public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver)
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAs(returnType, namespaceResolver);
- }
- public override byte[] ReadContentAsBase64()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsBase64();
- }
- public override int ReadValueAsBase64(byte[] buffer, int offset, int count)
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadValueAsBase64(buffer, offset, count);
- }
- public override int ReadContentAsBase64(byte[] buffer, int offset, int count)
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsBase64(buffer, offset, count);
- }
- public override int ReadElementContentAsBase64(byte[] buffer, int offset, int count)
- {
- if (!readingBinaryElement)
- {
- if (IsEmptyElement)
- {
- Read();
- return 0;
- }
- ReadStartElement();
- readingBinaryElement = true;
- }
- int i = ReadContentAsBase64(buffer, offset, count);
- if (i == 0)
- {
- ReadEndElement();
- readingBinaryElement = false;
- }
- return i;
- }
- public override int ReadElementContentAsBinHex(byte[] buffer, int offset, int count)
- {
- if (!readingBinaryElement)
- {
- if (IsEmptyElement)
- {
- Read();
- return 0;
- }
- ReadStartElement();
- readingBinaryElement = true;
- }
- int i = ReadContentAsBinHex(buffer, offset, count);
- if (i == 0)
- {
- ReadEndElement();
- readingBinaryElement = false;
- }
- return i;
- }
- public override int ReadContentAsBinHex(byte[] buffer, int offset, int count)
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsBinHex(buffer, offset, count);
- }
- public override bool ReadContentAsBoolean()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsBoolean();
- }
- public override int ReadContentAsChars(char[] chars, int index, int count)
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsChars(chars, index, count);
- }
- public override DateTime ReadContentAsDateTime()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsDateTime();
- }
- public override decimal ReadContentAsDecimal()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsDecimal();
- }
- public override double ReadContentAsDouble()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsDouble();
- }
- public override int ReadContentAsInt()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsInt();
- }
- public override long ReadContentAsLong()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsLong();
- }
- #if NO
- public override ICollection ReadContentAsList()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsList();
- }
- #endif
- public override object ReadContentAsObject()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsObject();
- }
- public override float ReadContentAsFloat()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsFloat();
- }
- public override string ReadContentAsString()
- {
- AdvanceToContentOnElement();
- return xmlReader.ReadContentAsString();
- }
- public override string ReadInnerXml()
- {
- return xmlReader.ReadInnerXml();
- }
- public override string ReadOuterXml()
- {
- return xmlReader.ReadOuterXml();
- }
- public override ReadState ReadState
- {
- get
- {
- if (xmlReader.ReadState != ReadState.Interactive && infosetReader != null)
- return infosetReader.ReadState;
- return xmlReader.ReadState;
- }
- }
- public override int ReadValueChunk(char[] buffer, int index, int count)
- {
- return xmlReader.ReadValueChunk(buffer, index, count);
- }
- public override void ResolveEntity()
- {
- xmlReader.ResolveEntity();
- }
- public override XmlReaderSettings Settings
- {
- get
- {
- return xmlReader.Settings;
- }
- }
- public override void Skip()
- {
- xmlReader.Skip();
- }
- public override string this[int index]
- {
- get
- {
- return xmlReader[index];
- }
- }
- public override string this[string name]
- {
- get
- {
- return xmlReader[name];
- }
- }
- public override string this[string name, string ns]
- {
- get
- {
- return xmlReader[name, ns];
- }
- }
- public override string Value
- {
- get
- {
- return xmlReader.Value;
- }
- }
- public override Type ValueType
- {
- get
- {
- return xmlReader.ValueType;
- }
- }
- public override string XmlLang
- {
- get
- {
- return xmlReader.XmlLang;
- }
- }
- public override XmlSpace XmlSpace
- {
- get
- {
- return xmlReader.XmlSpace;
- }
- }
- public bool HasLineInfo()
- {
- if (xmlReader.ReadState == ReadState.Closed)
- return false;
- IXmlLineInfo lineInfo = xmlReader as IXmlLineInfo;
- if (lineInfo == null)
- return false;
- return lineInfo.HasLineInfo();
- }
- public int LineNumber
- {
- get
- {
- if (xmlReader.ReadState == ReadState.Closed)
- return 0;
- IXmlLineInfo lineInfo = xmlReader as IXmlLineInfo;
- if (lineInfo == null)
- return 0;
- return lineInfo.LineNumber;
- }
- }
- public int LinePosition
- {
- get
- {
- if (xmlReader.ReadState == ReadState.Closed)
- return 0;
- IXmlLineInfo lineInfo = xmlReader as IXmlLineInfo;
- if (lineInfo == null)
- return 0;
- return lineInfo.LinePosition;
- }
- }
- internal class MimePart
- {
- Stream stream;
- MimeHeaders headers;
- byte[] buffer;
- bool isReferencedFromInfoset;
- internal MimePart(Stream stream, MimeHeaders headers)
- {
- this.stream = stream;
- this.headers = headers;
- }
- internal Stream Stream
- {
- get { return stream; }
- }
- internal MimeHeaders Headers
- {
- get { return headers; }
- }
- internal bool ReferencedFromInfoset
- {
- get { return isReferencedFromInfoset; }
- set { isReferencedFromInfoset = value; }
- }
- internal long Length
- {
- get { return stream.CanSeek ? stream.Length : 0; }
- }
- internal byte[] GetBuffer(int maxBuffer, ref int remaining)
- {
- if (buffer == null)
- {
- MemoryStream bufferedStream = stream.CanSeek ? new MemoryStream((int)stream.Length) : new MemoryStream();
- int size = 256;
- byte[] bytes = new byte[size];
- int read = 0;
- do
- {
- read = stream.Read(bytes, 0, size);
- XmlMtomReader.DecrementBufferQuota(maxBuffer, ref remaining, read);
- if (read > 0)
- bufferedStream.Write(bytes, 0, read);
- }
- while (read > 0);
- bufferedStream.Seek(0, SeekOrigin.Begin);
- buffer = bufferedStream.GetBuffer();
- stream = bufferedStream;
- }
- return buffer;
- }
- internal void Release(int maxBuffer, ref int remaining)
- {
- remaining += (int)this.Length;
- this.headers.Release(ref remaining);
- }
- }
- internal class XopIncludeReader : XmlDictionaryReader, IXmlLineInfo
- {
- int chunkSize = 4096; // Just a default. Serves as a max chunk size.
- int bytesRemaining;
- MimePart part;
- ReadState readState;
- XmlDictionaryReader parentReader;
- string stringValue;
- int stringOffset;
- XmlNodeType nodeType;
- MemoryStream binHexStream;
- byte[] valueBuffer;
- int valueOffset;
- int valueCount;
- bool finishedStream;
- public XopIncludeReader(MimePart part, XmlDictionaryReader reader)
- {
- if (part == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("part");
- if (reader == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
- this.part = part;
- this.parentReader = reader;
- this.readState = ReadState.Initial;
- this.nodeType = XmlNodeType.None;
- this.chunkSize = Math.Min(reader.Quotas.MaxBytesPerRead, chunkSize);
- this.bytesRemaining = this.chunkSize;
- this.finishedStream = false;
- }
- public override XmlDictionaryReaderQuotas Quotas
- {
- get
- {
- return this.parentReader.Quotas;
- }
- }
- public override XmlNodeType NodeType
- {
- get
- {
- return (readState == ReadState.Interactive) ? nodeType : parentReader.NodeType;
- }
- }
- public override bool Read()
- {
- bool retVal = true;
- switch (readState)
- {
- case ReadState.Initial:
- readState = ReadState.Interactive;
- nodeType = XmlNodeType.Text;
- break;
- case ReadState.Interactive:
- if (this.finishedStream || (this.bytesRemaining == this.chunkSize && this.stringValue == null))
- {
- readState = ReadState.EndOfFile;
- nodeType = XmlNodeType.EndElement;
- }
- else
- {
- this.bytesRemaining = this.chunkSize;
- }
- break;
- case ReadState.EndOfFile:
- nodeType = XmlNodeType.None;
- retVal = false;
- break;
- }
- this.stringValue = null;
- this.binHexStream = null;
- this.valueOffset = 0;
- this.valueCount = 0;
- this.stringOffset = 0;
- CloseStreams();
- return retVal;
- }
- public override int ReadValueAsBase64(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > buffer.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > buffer.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
- if (this.stringValue != null)
- {
- count = Math.Min(count, this.valueCount);
- if (count > 0)
- {
- Buffer.BlockCopy(this.valueBuffer, this.valueOffset, buffer, offset, count);
- this.valueOffset += count;
- this.valueCount -= count;
- }
- return count;
- }
- if (this.bytesRemaining < count)
- count = this.bytesRemaining;
- int read = 0;
- if (readState == ReadState.Interactive)
- {
- while (read < count)
- {
- int actual = part.Stream.Read(buffer, offset + read, count - read);
- if (actual == 0)
- {
- this.finishedStream = true;
- break;
- }
- read += actual;
- }
- }
- this.bytesRemaining -= read;
- return read;
- }
- public override int ReadContentAsBase64(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > buffer.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > buffer.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
- if (this.valueCount > 0)
- {
- count = Math.Min(count, this.valueCount);
- Buffer.BlockCopy(this.valueBuffer, this.valueOffset, buffer, offset, count);
- this.valueOffset += count;
- this.valueCount -= count;
- return count;
- }
- if (this.chunkSize < count)
- count = this.chunkSize;
- int read = 0;
- if (readState == ReadState.Interactive)
- {
- while (read < count)
- {
- int actual = part.Stream.Read(buffer, offset + read, count - read);
- if (actual == 0)
- {
- this.finishedStream = true;
- if (!Read())
- break;
- }
- read += actual;
- }
- }
- this.bytesRemaining = this.chunkSize;
- return read;
- }
- public override int ReadContentAsBinHex(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > buffer.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > buffer.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
- if (this.chunkSize < count)
- count = this.chunkSize;
- int read = 0;
- int consumed = 0;
- while (read < count)
- {
- if (binHexStream == null)
- {
- try
- {
- binHexStream = new MemoryStream(new BinHexEncoding().GetBytes(this.Value));
- }
- catch (FormatException e) // Wrap format exceptions from decoding document contents
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(e.Message, e));
- }
- }
- int actual = binHexStream.Read(buffer, offset + read, count - read);
- if (actual == 0)
- {
- this.finishedStream = true;
- if (!Read())
- break;
- consumed = 0;
- }
- read += actual;
- consumed += actual;
- }
- // Trim off the consumed chars
- if (this.stringValue != null && consumed > 0)
- {
- this.stringValue = this.stringValue.Substring(consumed * 2);
- this.stringOffset = Math.Max(0, this.stringOffset - consumed * 2);
- this.bytesRemaining = this.chunkSize;
- }
- return read;
- }
- public override int ReadValueChunk(char[] chars, int offset, int count)
- {
- if (chars == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("chars");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > chars.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, chars.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > chars.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, chars.Length - offset)));
- if (readState != ReadState.Interactive)
- return 0;
- // Copy characters from the Value property
- string str = this.Value;
- count = Math.Min(stringValue.Length - stringOffset, count);
- if (count > 0)
- {
- stringValue.CopyTo(stringOffset, chars, offset, count);
- stringOffset += count;
- }
- return count;
- }
- public override string Value
- {
- get
- {
- if (readState != ReadState.Interactive)
- return String.Empty;
- if (stringValue == null)
- {
- // Compute the bytes to read
- int byteCount = this.bytesRemaining;
- byteCount -= byteCount % 3;
- // Handle trailing bytes
- if (this.valueCount > 0 && this.valueOffset > 0)
- {
- Buffer.BlockCopy(this.valueBuffer, this.valueOffset, this.valueBuffer, 0, this.valueCount);
- this.valueOffset = 0;
- }
- byteCount -= this.valueCount;
- // Resize buffer if needed
- if (this.valueBuffer == null)
- {
- this.valueBuffer = new byte[byteCount];
- }
- else if (this.valueBuffer.Length < byteCount)
- {
- Array.Resize(ref this.valueBuffer, byteCount);
- }
- byte[] buffer = this.valueBuffer;
- // Fill up the buffer
- int offset = 0;
- int read = 0;
- while (byteCount > 0)
- {
- read = part.Stream.Read(buffer, offset, byteCount);
- if (read == 0)
- {
- this.finishedStream = true;
- break;
- }
- this.bytesRemaining -= read;
- this.valueCount += read;
- byteCount -= read;
- offset += read;
- }
- // Convert the bytes
- this.stringValue = Convert.ToBase64String(buffer, 0, this.valueCount);
- }
- return this.stringValue;
- }
- }
- public override string ReadContentAsString()
- {
- int stringContentQuota = this.Quotas.MaxStringContentLength;
- StringBuilder sb = new StringBuilder();
- do
- {
- string val = this.Value;
- if (val.Length > stringContentQuota)
- XmlExceptionHelper.ThrowMaxStringContentLengthExceeded(this, this.Quotas.MaxStringContentLength);
- stringContentQuota -= val.Length;
- sb.Append(val);
- } while (Read());
- return sb.ToString();
- }
- public override int AttributeCount
- {
- get { return 0; }
- }
- public override string BaseURI
- {
- get { return parentReader.BaseURI; }
- }
- public override bool CanReadBinaryContent
- {
- get { return true; }
- }
- public override bool CanReadValueChunk
- {
- get { return true; }
- }
- public override bool CanResolveEntity
- {
- get { return parentReader.CanResolveEntity; }
- }
- public override void Close()
- {
- CloseStreams();
- readState = ReadState.Closed;
- }
- void CloseStreams()
- {
- if (binHexStream != null)
- {
- binHexStream.Close();
- binHexStream = null;
- }
- }
- public override int Depth
- {
- get
- {
- return (readState == ReadState.Interactive) ? parentReader.Depth + 1 : parentReader.Depth;
- }
- }
- public override bool EOF
- {
- get { return readState == ReadState.EndOfFile; }
- }
- public override string GetAttribute(int index)
- {
- return null;
- }
- public override string GetAttribute(string name)
- {
- return null;
- }
- public override string GetAttribute(string name, string ns)
- {
- return null;
- }
- public override string GetAttribute(XmlDictionaryString localName, XmlDictionaryString ns)
- {
- return null;
- }
- public override bool HasAttributes
- {
- get { return false; }
- }
- public override bool HasValue
- {
- get { return readState == ReadState.Interactive; }
- }
- public override bool IsDefault
- {
- get { return false; }
- }
- public override bool IsEmptyElement
- {
- get { return false; }
- }
- public override bool IsLocalName(string localName)
- {
- return false;
- }
- public override bool IsLocalName(XmlDictionaryString localName)
- {
- return false;
- }
- public override bool IsNamespaceUri(string ns)
- {
- return false;
- }
- public override bool IsNamespaceUri(XmlDictionaryString ns)
- {
- return false;
- }
- public override bool IsStartElement()
- {
- return false;
- }
- public override bool IsStartElement(string localName)
- {
- return false;
- }
- public override bool IsStartElement(string localName, string ns)
- {
- return false;
- }
- public override bool IsStartElement(XmlDictionaryString localName, XmlDictionaryString ns)
- {
- return false;
- }
- #if NO
- public override bool IsStartSubsetElement()
- {
- return false;
- }
- #endif
- public override string LocalName
- {
- get
- {
- return (readState == ReadState.Interactive) ? String.Empty : parentReader.LocalName;
- }
- }
- public override string LookupNamespace(string ns)
- {
- return parentReader.LookupNamespace(ns);
- }
- public override void MoveToAttribute(int index)
- {
- }
- public override bool MoveToAttribute(string name)
- {
- return false;
- }
- public override bool MoveToAttribute(string name, string ns)
- {
- return false;
- }
- public override bool MoveToElement()
- {
- return false;
- }
- public override bool MoveToFirstAttribute()
- {
- return false;
- }
- public override bool MoveToNextAttribute()
- {
- return false;
- }
- public override string Name
- {
- get
- {
- return (readState == ReadState.Interactive) ? String.Empty : parentReader.Name;
- }
- }
- public override string NamespaceURI
- {
- get
- {
- return (readState == ReadState.Interactive) ? String.Empty : parentReader.NamespaceURI;
- }
- }
- public override XmlNameTable NameTable
- {
- get { return parentReader.NameTable; }
- }
- public override string Prefix
- {
- get
- {
- return (readState == ReadState.Interactive) ? String.Empty : parentReader.Prefix;
- }
- }
- public override char QuoteChar
- {
- get { return parentReader.QuoteChar; }
- }
- public override bool ReadAttributeValue()
- {
- return false;
- }
- public override string ReadInnerXml()
- {
- return ReadContentAsString();
- }
- public override string ReadOuterXml()
- {
- return ReadContentAsString();
- }
- public override ReadState ReadState
- {
- get { return readState; }
- }
- public override void ResolveEntity()
- {
- }
- public override XmlReaderSettings Settings
- {
- get { return parentReader.Settings; }
- }
- public override void Skip()
- {
- Read();
- }
- public override string this[int index]
- {
- get { return null; }
- }
- public override string this[string name]
- {
- get { return null; }
- }
- public override string this[string name, string ns]
- {
- get { return null; }
- }
- public override string XmlLang
- {
- get { return parentReader.XmlLang; }
- }
- public override XmlSpace XmlSpace
- {
- get { return parentReader.XmlSpace; }
- }
- public override Type ValueType
- {
- get
- {
- return (readState == ReadState.Interactive) ? typeof(byte[]) : parentReader.ValueType;
- }
- }
- bool IXmlLineInfo.HasLineInfo()
- {
- return ((IXmlLineInfo)parentReader).HasLineInfo();
- }
- int IXmlLineInfo.LineNumber
- {
- get
- {
- return ((IXmlLineInfo)parentReader).LineNumber;
- }
- }
- int IXmlLineInfo.LinePosition
- {
- get
- {
- return ((IXmlLineInfo)parentReader).LinePosition;
- }
- }
- }
- }
- internal class MimeMessageReader
- {
- static byte[] CRLFCRLF = new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' };
- bool getContentStreamCalled;
- MimeHeaderReader mimeHeaderReader;
- DelimittedStreamReader reader;
- public MimeMessageReader(Stream stream)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- this.reader = new DelimittedStreamReader(stream);
- this.mimeHeaderReader = new MimeHeaderReader(this.reader.GetNextStream(CRLFCRLF));
- }
- public Stream GetContentStream()
- {
- if (getContentStreamCalled)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MimeMessageGetContentStreamCalledAlready)));
- mimeHeaderReader.Close();
- Stream s = reader.GetNextStream(null);
- getContentStreamCalled = true;
- return s;
- }
- public MimeHeaders ReadHeaders(int maxBuffer, ref int remaining)
- {
- MimeHeaders headers = new MimeHeaders();
- while (mimeHeaderReader.Read(maxBuffer, ref remaining))
- {
- headers.Add(mimeHeaderReader.Name, mimeHeaderReader.Value, ref remaining);
- }
- return headers;
- }
- }
- internal class MimeReader
- {
- static byte[] CRLFCRLF = new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' };
- byte[] boundaryBytes;
- string content;
- Stream currentStream;
- MimeHeaderReader mimeHeaderReader;
- DelimittedStreamReader reader;
- byte[] scratch = new byte[2];
- public MimeReader(Stream stream, string boundary)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- if (boundary == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("boundary");
- this.reader = new DelimittedStreamReader(stream);
- this.boundaryBytes = MimeWriter.GetBoundaryBytes(boundary);
- // Need to ensure that the content begins with a CRLF, in case the
- // outer construct has consumed the trailing CRLF
- this.reader.Push(this.boundaryBytes, 0, 2);
- }
- public void Close()
- {
- this.reader.Close();
- }
- /// Gets the content preceding the first part of the MIME multi-part message
- public string Preface
- {
- get
- {
- if (content == null)
- {
- Stream s = this.reader.GetNextStream(this.boundaryBytes);
- content = new StreamReader(s, System.Text.Encoding.ASCII, false, 256).ReadToEnd();
- s.Close();
- if (content == null)
- content = string.Empty;
- }
- return content;
- }
- }
- public Stream GetContentStream()
- {
- Fx.Assert(content != null, "");
- mimeHeaderReader.Close();
- return reader.GetNextStream(this.boundaryBytes);
- }
- public bool ReadNextPart()
- {
- string content = Preface;
- if (currentStream != null)
- {
- currentStream.Close();
- currentStream = null;
- }
- Stream stream = reader.GetNextStream(CRLFCRLF);
- if (stream == null)
- return false;
- if (BlockRead(stream, scratch, 0, 2) == 2)
- {
- if (scratch[0] == '\r' && scratch[1] == '\n')
- {
- if (mimeHeaderReader == null)
- mimeHeaderReader = new MimeHeaderReader(stream);
- else
- mimeHeaderReader.Reset(stream);
- return true;
- }
- else if (scratch[0] == '-' && scratch[1] == '-')
- {
- int read = BlockRead(stream, scratch, 0, 2);
- if (read < 2 || (scratch[0] == '\r' && scratch[1] == '\n'))
- return false;
- }
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderTruncated)));
- }
- public MimeHeaders ReadHeaders(int maxBuffer, ref int remaining)
- {
- MimeHeaders headers = new MimeHeaders();
- while (mimeHeaderReader.Read(maxBuffer, ref remaining))
- {
- headers.Add(mimeHeaderReader.Name, mimeHeaderReader.Value, ref remaining);
- }
- return headers;
- }
- int BlockRead(Stream stream, byte[] buffer, int offset, int count)
- {
- int read = 0;
- do
- {
- int r = stream.Read(buffer, offset + read, count - read);
- if (r == 0)
- break;
- read += r;
- } while (read < count);
- return read;
- }
- }
- internal class DelimittedStreamReader
- {
- bool canGetNextStream = true;
- // used for closing the reader, and validating that only one stream can be reading at a time.
- DelimittedReadStream currentStream;
- byte[] delimitter;
- byte[] matchBuffer;
- byte[] scratch;
- BufferedReadStream stream;
- public DelimittedStreamReader(Stream stream)
- {
- this.stream = new BufferedReadStream(stream);
- }
- public void Close()
- {
- this.stream.Close();
- }
- // Closes the current stream. If the current stream is not the same as the caller, nothing is done.
- void Close(DelimittedReadStream caller)
- {
- if (currentStream == caller)
- {
- if (delimitter == null)
- {
- stream.Close();
- }
- else
- {
- if (scratch == null)
- {
- scratch = new byte[1024];
- }
- while (0 != Read(caller, this.scratch, 0, this.scratch.Length));
- }
- currentStream = null;
- }
- }
- // Gets the next logical stream delimitted by the given sequence.
- public Stream GetNextStream(byte[] delimitter)
- {
- if (currentStream != null)
- {
- currentStream.Close();
- currentStream = null;
- }
- if (!canGetNextStream)
- return null;
- this.delimitter = delimitter;
- canGetNextStream = delimitter != null;
- currentStream = new DelimittedReadStream(this);
- return currentStream;
- }
- enum MatchState
- {
- True,
- False,
- InsufficientData
- }
- MatchState MatchDelimitter(byte[] buffer, int start, int end)
- {
- if (this.delimitter.Length > end - start)
- {
- for (int i = end - start - 1; i >= 1; i--)
- {
- if (buffer[start + i] != delimitter[i])
- return MatchState.False;
- }
- return MatchState.InsufficientData;
- }
- for (int i = delimitter.Length - 1; i >= 1; i--)
- {
- if (buffer[start + i] != delimitter[i])
- return MatchState.False;
- }
- return MatchState.True;
- }
- int ProcessRead(byte[] buffer, int offset, int read)
- {
- // nothing to process if 0 bytes were read
- if (read == 0)
- return read;
- for (int ptr = offset, end = offset + read; ptr < end; ptr++)
- {
- if (buffer[ptr] == delimitter[0])
- {
- switch (MatchDelimitter(buffer, ptr, end))
- {
- case MatchState.True:
- {
- int actual = ptr - offset;
- ptr += this.delimitter.Length;
- this.stream.Push(buffer, ptr, end - ptr);
- this.currentStream = null;
- return actual;
- }
- case MatchState.False:
- break;
- case MatchState.InsufficientData:
- {
- int actual = ptr - offset;
- if (actual > 0)
- {
- this.stream.Push(buffer, ptr, end - ptr);
- return actual;
- }
- else
- {
- return -1;
- }
- }
- }
- }
- }
- return read;
- }
- int Read(DelimittedReadStream caller, byte[] buffer, int offset, int count)
- {
- if (this.currentStream != caller)
- return 0;
- int read = this.stream.Read(buffer, offset, count);
- if (read == 0)
- {
- this.canGetNextStream = false;
- this.currentStream = null;
- return read;
- }
- // If delimitter is null, read until the underlying stream returns 0 bytes
- if (this.delimitter == null)
- return read;
- // Scans the read data for the delimitter. If found, the number of bytes read are adjusted
- // to account for the number of bytes up to but not including the delimitter.
- int actual = ProcessRead(buffer, offset, read);
- if (actual < 0)
- {
- if (this.matchBuffer == null || this.matchBuffer.Length < this.delimitter.Length - read)
- this.matchBuffer = new byte[this.delimitter.Length - read];
- int matched = this.stream.ReadBlock(this.matchBuffer, 0, this.delimitter.Length - read);
- if (MatchRemainder(read, matched))
- {
- this.currentStream = null;
- actual = 0;
- }
- else
- {
- this.stream.Push(this.matchBuffer, 0, matched);
- int i = 1;
- for (; i < read; i++)
- {
- if (buffer[i] == this.delimitter[0])
- break;
- }
- if (i < read)
- this.stream.Push(buffer, offset + i, read - i);
- actual = i;
- }
- }
- return actual;
- }
- bool MatchRemainder(int start, int count)
- {
- if (start + count != this.delimitter.Length)
- return false;
- for (count--; count >= 0; count--)
- {
- if (this.delimitter[start + count] != this.matchBuffer[count])
- return false;
- }
- return true;
- }
- internal void Push(byte[] buffer, int offset, int count)
- {
- this.stream.Push(buffer, offset, count);
- }
- class DelimittedReadStream : Stream
- {
- DelimittedStreamReader reader;
- public DelimittedReadStream(DelimittedStreamReader reader)
- {
- if (reader == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
- this.reader = reader;
- }
- public override bool CanRead
- {
- get { return true; }
- }
- public override bool CanSeek
- {
- get { return false; }
- }
- public override bool CanWrite
- {
- get { return false; }
- }
- public override long Length
- {
- #pragma warning suppress 56503 // [....], required by the XmlReader
- get { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, this.GetType().FullName))); }
- }
- public override long Position
- {
- get
- {
- #pragma warning suppress 56503 // [....], required by the XmlReader
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, this.GetType().FullName)));
- }
- set { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, this.GetType().FullName))); }
- }
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, this.GetType().FullName)));
- }
- public override void Close()
- {
- reader.Close(this);
- }
- public override void EndWrite(IAsyncResult asyncResult)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, this.GetType().FullName)));
- }
- public override void Flush()
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, this.GetType().FullName)));
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (buffer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > buffer.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > buffer.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
- return reader.Read(this, buffer, offset, count);
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, this.GetType().FullName)));
- }
- public override void SetLength(long value)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, this.GetType().FullName)));
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, this.GetType().FullName)));
- }
- }
- }
- internal class MimeHeaders
- {
- static class Constants
- {
- public const string ContentTransferEncoding = "content-transfer-encoding";
- public const string ContentID = "content-id";
- public const string ContentType = "content-type";
- public const string MimeVersion = "mime-version";
- }
- Dictionary<string, MimeHeader> headers = new Dictionary<string, MimeHeader>();
- public MimeHeaders()
- {
- }
- public ContentTypeHeader ContentType
- {
- get
- {
- MimeHeader header;
- if (headers.TryGetValue(Constants.ContentType, out header))
- return header as ContentTypeHeader;
- return null;
- }
- }
- public ContentIDHeader ContentID
- {
- get
- {
- MimeHeader header;
- if (headers.TryGetValue(Constants.ContentID, out header))
- return header as ContentIDHeader;
- return null;
- }
- }
- public ContentTransferEncodingHeader ContentTransferEncoding
- {
- get
- {
- MimeHeader header;
- if (headers.TryGetValue(Constants.ContentTransferEncoding, out header))
- return header as ContentTransferEncodingHeader;
- return null;
- }
- }
- public MimeVersionHeader MimeVersion
- {
- get
- {
- MimeHeader header;
- if (headers.TryGetValue(Constants.MimeVersion, out header))
- return header as MimeVersionHeader;
- return null;
- }
- }
- public void Add(string name, string value, ref int remaining)
- {
- if (name == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
- if (value == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
- switch (name)
- {
- case Constants.ContentType:
- Add(new ContentTypeHeader(value));
- break;
- case Constants.ContentID:
- Add(new ContentIDHeader(name, value));
- break;
- case Constants.ContentTransferEncoding:
- Add(new ContentTransferEncodingHeader(value));
- break;
- case Constants.MimeVersion:
- Add(new MimeVersionHeader(value));
- break;
- // Skip any fields that are not recognized
- // Content-description is currently not stored since it is not used
- default:
- remaining += value.Length * sizeof(char);
- break;
- }
- remaining += name.Length * sizeof(char);
- }
- public void Add(MimeHeader header)
- {
- if (header == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("header");
- MimeHeader existingHeader;
- if (headers.TryGetValue(header.Name, out existingHeader))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderHeaderAlreadyExists, header.Name)));
- else
- headers.Add(header.Name, header);
- }
- public void Release(ref int remaining)
- {
- foreach (MimeHeader header in this.headers.Values)
- {
- remaining += header.Value.Length * sizeof(char);
- }
- }
- }
- internal class MimeHeader
- {
- string name;
- string value;
- public MimeHeader(string name, string value)
- {
- if (name == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
- this.name = name;
- this.value = value;
- }
- public string Name
- {
- get
- {
- return this.name;
- }
- }
- public string Value
- {
- get
- {
- return this.value;
- }
- }
- }
- internal class ContentTypeHeader : MimeHeader
- {
- public readonly static ContentTypeHeader Default = new ContentTypeHeader("application/octet-stream");
- public ContentTypeHeader(string value)
- : base("content-type", value)
- {
- }
- string mediaType;
- string subType;
- Dictionary<string, string> parameters;
- public string MediaType
- {
- get
- {
- if (this.mediaType == null && Value != null)
- ParseValue();
- return this.mediaType;
- }
- }
- public string MediaSubtype
- {
- get
- {
- if (this.subType == null && Value != null)
- ParseValue();
- return this.subType;
- }
- }
- public Dictionary<string, string> Parameters
- {
- get
- {
- if (this.parameters == null)
- {
- if (Value != null)
- ParseValue();
- else
- this.parameters = new Dictionary<string, string>();
- }
- return this.parameters;
- }
- }
- void ParseValue()
- {
- if (this.parameters == null)
- {
- int offset = 0;
- this.parameters = new Dictionary<string, string>();
- this.mediaType = MailBnfHelper.ReadToken(Value, ref offset, null);
- if (offset >= Value.Length || Value[offset++] != '/')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeContentTypeHeaderInvalid)));
- this.subType = MailBnfHelper.ReadToken(Value, ref offset, null);
- while (MailBnfHelper.SkipCFWS(Value, ref offset))
- {
- if (offset >= Value.Length || Value[offset++] != ';')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeContentTypeHeaderInvalid)));
- if (!MailBnfHelper.SkipCFWS(Value, ref offset))
- break;
- string paramAttribute = MailBnfHelper.ReadParameterAttribute(Value, ref offset, null);
- if (paramAttribute == null || offset >= Value.Length || Value[offset++] != '=')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeContentTypeHeaderInvalid)));
- string paramValue = MailBnfHelper.ReadParameterValue(Value, ref offset, null);
- this.parameters.Add(paramAttribute.ToLowerInvariant(), paramValue);
- }
- if (this.parameters.ContainsKey(MtomGlobals.StartInfoParam))
- {
- // This allows us to maintain back compat with Orcas clients while allowing clients
- // following the spec (with action inside start-info) to interop with RFC 2387
- string startInfo = this.parameters[MtomGlobals.StartInfoParam];
- // we're only interested in finding the action here - skipping past the content type to the first ;
- int startInfoOffset = startInfo.IndexOf(';');
- if (startInfoOffset > -1)
- {
- // keep going through the start-info string until we've reached the end of the stream
- while (MailBnfHelper.SkipCFWS(startInfo, ref startInfoOffset))
- {
- // after having read through an attribute=value pair, we always expect to be at a ;
- if (startInfo[startInfoOffset] == ';')
- {
- startInfoOffset++;
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeContentTypeHeaderInvalid)));
- }
- string paramAttribute = MailBnfHelper.ReadParameterAttribute(startInfo, ref startInfoOffset, null);
- if (paramAttribute == null || startInfoOffset >= startInfo.Length || startInfo[startInfoOffset++] != '=')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeContentTypeHeaderInvalid)));
- string paramValue = MailBnfHelper.ReadParameterValue(startInfo, ref startInfoOffset, null);
- if (paramAttribute == MtomGlobals.ActionParam)
- {
- this.parameters[MtomGlobals.ActionParam] = paramValue;
- }
- }
- }
- }
- }
- }
- }
- enum ContentTransferEncoding
- {
- SevenBit,
- EightBit,
- Binary,
- Other,
- Unspecified
- }
- internal class ContentTransferEncodingHeader : MimeHeader
- {
- ContentTransferEncoding contentTransferEncoding;
- string contentTransferEncodingValue;
- public readonly static ContentTransferEncodingHeader Binary = new ContentTransferEncodingHeader(ContentTransferEncoding.Binary, "binary");
- public readonly static ContentTransferEncodingHeader EightBit = new ContentTransferEncodingHeader(ContentTransferEncoding.EightBit, "8bit");
- public readonly static ContentTransferEncodingHeader SevenBit = new ContentTransferEncodingHeader(ContentTransferEncoding.SevenBit, "7bit");
- public ContentTransferEncodingHeader(string value)
- : base("content-transfer-encoding", value.ToLowerInvariant())
- {
- }
- public ContentTransferEncodingHeader(ContentTransferEncoding contentTransferEncoding, string value)
- : base("content-transfer-encoding", null)
- {
- this.contentTransferEncoding = contentTransferEncoding;
- this.contentTransferEncodingValue = value;
- }
- public ContentTransferEncoding ContentTransferEncoding
- {
- get
- {
- ParseValue();
- return this.contentTransferEncoding;
- }
- }
- public string ContentTransferEncodingValue
- {
- get
- {
- ParseValue();
- return this.contentTransferEncodingValue;
- }
- }
- void ParseValue()
- {
- if (this.contentTransferEncodingValue == null)
- {
- int offset = 0;
- this.contentTransferEncodingValue = (Value.Length == 0) ? Value : ((Value[0] == '"') ? MailBnfHelper.ReadQuotedString(Value, ref offset, null) : MailBnfHelper.ReadToken(Value, ref offset, null));
- switch (this.contentTransferEncodingValue)
- {
- case "7bit":
- this.contentTransferEncoding = ContentTransferEncoding.SevenBit;
- break;
- case "8bit":
- this.contentTransferEncoding = ContentTransferEncoding.EightBit;
- break;
- case "binary":
- this.contentTransferEncoding = ContentTransferEncoding.Binary;
- break;
- default:
- this.contentTransferEncoding = ContentTransferEncoding.Other;
- break;
- }
- }
- }
- }
- internal class ContentIDHeader : MimeHeader
- {
- public ContentIDHeader(string name, string value)
- : base(name, value)
- {
- }
- }
- internal class MimeVersionHeader : MimeHeader
- {
- public static readonly MimeVersionHeader Default = new MimeVersionHeader("1.0");
- public MimeVersionHeader(string value)
- : base("mime-version", value)
- {
- }
- string version;
- public string Version
- {
- get
- {
- if (this.version == null && Value != null)
- ParseValue();
- return this.version;
- }
- }
- void ParseValue()
- {
- // shortcut for the most common case.
- if (Value == "1.0")
- {
- this.version = "1.0";
- }
- else
- {
- int offset = 0;
- if (!MailBnfHelper.SkipCFWS(Value, ref offset))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeVersionHeaderInvalid)));
- StringBuilder builder = new StringBuilder();
- MailBnfHelper.ReadDigits(Value, ref offset, builder);
- if ((!MailBnfHelper.SkipCFWS(Value, ref offset) || offset >= Value.Length || Value[offset++] != '.') || !MailBnfHelper.SkipCFWS(Value, ref offset))
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeVersionHeaderInvalid)));
- builder.Append('.');
- MailBnfHelper.ReadDigits(Value, ref offset, builder);
- this.version = builder.ToString();
- }
- }
- }
- internal class MimeHeaderReader
- {
- enum ReadState
- {
- ReadName,
- SkipWS,
- ReadValue,
- ReadLF,
- ReadWS,
- EOF
- }
- string value;
- byte[] buffer = new byte[1024];
- int maxOffset;
- string name;
- int offset;
- ReadState readState = ReadState.ReadName;
- Stream stream;
- public MimeHeaderReader(Stream stream)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- this.stream = stream;
- }
- public string Value
- {
- get
- {
- return value;
- }
- }
- public string Name
- {
- get
- {
- return name;
- }
- }
- public void Close()
- {
- stream.Close();
- readState = ReadState.EOF;
- }
- public bool Read(int maxBuffer, ref int remaining)
- {
- name = null;
- value = null;
- while (readState != ReadState.EOF)
- {
- if (offset == maxOffset)
- {
- maxOffset = stream.Read(this.buffer, 0, this.buffer.Length);
- offset = 0;
- if (BufferEnd())
- break;
- }
- if (ProcessBuffer(maxBuffer, ref remaining))
- break;
- }
- return value != null;
- }
- [Fx.Tag.SecurityNote(Critical = "Calls unsafe code", Safe = "Demands for FullTrust")]
- [SecuritySafeCritical]
- [PermissionSet(SecurityAction.Demand, Unrestricted = true)]
- bool ProcessBuffer(int maxBuffer, ref int remaining)
- {
- unsafe
- {
- fixed (byte* pBuffer = this.buffer)
- {
- byte* start = pBuffer + this.offset;
- byte* end = pBuffer + this.maxOffset;
- byte* ptr = start;
- switch (readState)
- {
- case ReadState.ReadName:
- for (; ptr < end; ptr++)
- {
- if (*ptr == ':')
- {
- AppendName(new string((sbyte*)start, 0, (int)(ptr - start)), maxBuffer, ref remaining);
- ptr++;
- goto case ReadState.SkipWS;
- }
- else
- {
- // convert to lower case up front.
- if (*ptr >= 'A' && *ptr <= 'Z')
- {
- *ptr += 'a' - 'A';
- }
- else if (*ptr < 33 || *ptr > 126)
- {
- if (name == null && *ptr == (byte)'\r')
- {
- ptr++;
- if (ptr >= end || *ptr != '\n')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderMalformedHeader)));
- goto case ReadState.EOF;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeHeaderInvalidCharacter, (char)(*ptr), ((int)(*ptr)).ToString("X", CultureInfo.InvariantCulture))));
- }
- }
- }
- AppendName(new string((sbyte*)start, 0, (int)(ptr - start)), maxBuffer, ref remaining);
- readState = ReadState.ReadName;
- break;
- case ReadState.SkipWS:
- for (; ptr < end; ptr++)
- if (*ptr != (byte)'\t' && *ptr != ' ')
- goto case ReadState.ReadValue;
- readState = ReadState.SkipWS;
- break;
- case ReadState.ReadValue:
- start = ptr;
- for (; ptr < end; ptr++)
- {
- if (*ptr == (byte)'\r')
- {
- AppendValue(new string((sbyte*)start, 0, (int)(ptr - start)), maxBuffer, ref remaining);
- ptr++;
- goto case ReadState.ReadLF;
- }
- else if (*ptr == (byte)'\n')
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderMalformedHeader)));
- }
- }
- AppendValue(new string((sbyte*)start, 0, (int)(ptr - start)), maxBuffer, ref remaining);
- readState = ReadState.ReadValue;
- break;
- case ReadState.ReadLF:
- if (ptr < end)
- {
- if (*ptr != (byte)'\n')
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderMalformedHeader)));
- ptr++;
- goto case ReadState.ReadWS;
- }
- readState = ReadState.ReadLF;
- break;
- case ReadState.ReadWS:
- if (ptr < end)
- {
- if (*ptr != (byte)' ' && *ptr != (byte)'\t')
- {
- readState = ReadState.ReadName;
- offset = (int)(ptr - pBuffer);
- return true;
- }
- goto case ReadState.ReadValue;
- }
- readState = ReadState.ReadWS;
- break;
- case ReadState.EOF:
- readState = ReadState.EOF;
- offset = (int)(ptr - pBuffer);
- return true;
- }
- offset = (int)(ptr - pBuffer);
- }
- }
- return false;
- }
- bool BufferEnd()
- {
- if (maxOffset == 0)
- {
- if (readState != ReadState.ReadWS && readState != ReadState.ReadValue)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderMalformedHeader)));
- readState = ReadState.EOF;
- return true;
- }
- return false;
- }
- // Resets the mail field reader to the new stream to reuse buffers
- public void Reset(Stream stream)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- if (readState != ReadState.EOF)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MimeReaderResetCalledBeforeEOF)));
- this.stream = stream;
- readState = ReadState.ReadName;
- maxOffset = 0;
- offset = 0;
- }
- // helper methods
- void AppendValue(string value, int maxBuffer, ref int remaining)
- {
- XmlMtomReader.DecrementBufferQuota(maxBuffer, ref remaining, value.Length * sizeof(char));
- if (this.value == null)
- this.value = value;
- else
- this.value += value;
- }
- void AppendName(string value, int maxBuffer, ref int remaining)
- {
- XmlMtomReader.DecrementBufferQuota(maxBuffer, ref remaining, value.Length * sizeof(char));
- if (this.name == null)
- this.name = value;
- else
- this.name += value;
- }
- }
- internal class BufferedReadStream : Stream
- {
- Stream stream;
- byte[] storedBuffer;
- int storedLength;
- int storedOffset;
- bool readMore;
- public BufferedReadStream(Stream stream)
- : this(stream, false)
- {
- }
- public BufferedReadStream(Stream stream, bool readMore)
- {
- if (stream == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
- this.stream = stream;
- this.readMore = readMore;
- }
- public override bool CanWrite
- {
- get { return false; }
- }
- public override bool CanSeek
- {
- get { return false; }
- }
- public override bool CanRead
- {
- get { return stream.CanRead; }
- }
- public override long Length
- {
- get
- {
- #pragma warning suppress 56503 // [....], required by the Stream contract
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, stream.GetType().FullName)));
- }
- }
- public override long Position
- {
- get
- {
- #pragma warning suppress 56503 // [....], required by the Stream contract
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, stream.GetType().FullName)));
- }
- set
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, stream.GetType().FullName)));
- }
- }
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (!CanRead)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.ReadNotSupportedOnStream, stream.GetType().FullName)));
- return stream.BeginRead(buffer, offset, count, callback, state);
- }
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, stream.GetType().FullName)));
- }
- public override void Close()
- {
- stream.Close();
- }
- public override int EndRead(IAsyncResult asyncResult)
- {
- if (!CanRead)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.ReadNotSupportedOnStream, stream.GetType().FullName)));
- return stream.EndRead(asyncResult);
- }
- public override void EndWrite(IAsyncResult asyncResult)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, stream.GetType().FullName)));
- }
- public override void Flush()
- {
- stream.Flush();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (!CanRead)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.ReadNotSupportedOnStream, stream.GetType().FullName)));
- if (buffer == null)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
- if (offset < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
- if (offset > buffer.Length)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, buffer.Length)));
- if (count < 0)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
- if (count > buffer.Length - offset)
- throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset)));
- int read = 0;
- if (this.storedOffset < this.storedLength)
- {
- read = Math.Min(count, this.storedLength - this.storedOffset);
- Buffer.BlockCopy(this.storedBuffer, this.storedOffset, buffer, offset, read);
- this.storedOffset += read;
- if (read == count || !this.readMore)
- return read;
- offset += read;
- count -= read;
- }
- return read + stream.Read(buffer, offset, count);
- }
- public override int ReadByte()
- {
- if (this.storedOffset < this.storedLength)
- return (int)this.storedBuffer[this.storedOffset++];
- else
- return base.ReadByte();
- }
- public int ReadBlock(byte[] buffer, int offset, int count)
- {
- int read;
- int total = 0;
- while (total < count && (read = Read(buffer, offset + total, count - total)) != 0)
- {
- total += read;
- }
- return total;
- }
- public void Push(byte[] buffer, int offset, int count)
- {
- if (count == 0)
- return;
- if (this.storedOffset == this.storedLength)
- {
- if (this.storedBuffer == null || this.storedBuffer.Length < count)
- this.storedBuffer = new byte[count];
- this.storedOffset = 0;
- this.storedLength = count;
- }
- else
- {
- // if there's room to just insert before existing data
- if (count <= this.storedOffset)
- this.storedOffset -= count;
- // if there's room in the buffer but need to shift things over
- else if (count <= this.storedBuffer.Length - this.storedLength + this.storedOffset)
- {
- Buffer.BlockCopy(this.storedBuffer, this.storedOffset, this.storedBuffer, count, this.storedLength - this.storedOffset);
- this.storedLength += count - this.storedOffset;
- this.storedOffset = 0;
- }
- else
- {
- byte[] newBuffer = new byte[count + this.storedLength - this.storedOffset];
- Buffer.BlockCopy(this.storedBuffer, this.storedOffset, newBuffer, count, this.storedLength - this.storedOffset);
- this.storedLength += count - this.storedOffset;
- this.storedOffset = 0;
- this.storedBuffer = newBuffer;
- }
- }
- Buffer.BlockCopy(buffer, offset, this.storedBuffer, this.storedOffset, count);
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, stream.GetType().FullName)));
- }
- public override void SetLength(long value)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SeekNotSupportedOnStream, stream.GetType().FullName)));
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.WriteNotSupportedOnStream, stream.GetType().FullName)));
- }
- }
- internal static class MailBnfHelper
- {
- static bool[] s_fqtext = new bool[128];
- static bool[] s_ttext = new bool[128];
- static bool[] s_digits = new bool[128];
- static bool[] s_boundary = new bool[128];
- static MailBnfHelper()
- {
- // fqtext = %d1-9 / %d11 / %d12 / %d14-33 / %d35-91 / %d93-127
- for (int i = 1; i <= 9; i++) { s_fqtext[i] = true; }
- s_fqtext[11] = true;
- s_fqtext[12] = true;
- for (int i = 14; i <= 33; i++) { s_fqtext[i] = true; }
- for (int i = 35; i <= 91; i++) { s_fqtext[i] = true; }
- for (int i = 93; i <= 127; i++) { s_fqtext[i] = true; }
- // ttext = %d33-126 except '()<>@,;:\"/[]?='
- for (int i = 33; i <= 126; i++) { s_ttext[i] = true; }
- s_ttext['('] = false;
- s_ttext[')'] = false;
- s_ttext['<'] = false;
- s_ttext['>'] = false;
- s_ttext['@'] = false;
- s_ttext[','] = false;
- s_ttext[';'] = false;
- s_ttext[':'] = false;
- s_ttext['\\'] = false;
- s_ttext['"'] = false;
- s_ttext['/'] = false;
- s_ttext['['] = false;
- s_ttext[']'] = false;
- s_ttext['?'] = false;
- s_ttext['='] = false;
- // digits = %d48-57
- for (int i = 48; i <= 57; i++)
- s_digits[i] = true;
- // boundary = DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?" / " "
- // cannot end with " "
- for (int i = '0'; i <= '9'; i++) { s_boundary[i] = true; }
- for (int i = 'A'; i <= 'Z'; i++) { s_boundary[i] = true; }
- for (int i = 'a'; i <= 'z'; i++) { s_boundary[i] = true; }
- s_boundary['\''] = true;
- s_boundary['('] = true;
- s_boundary[')'] = true;
- s_boundary['+'] = true;
- s_boundary['_'] = true;
- s_boundary[','] = true;
- s_boundary['-'] = true;
- s_boundary['.'] = true;
- s_boundary['/'] = true;
- s_boundary[':'] = true;
- s_boundary['='] = true;
- s_boundary['?'] = true;
- s_boundary[' '] = true;
- }
- public static bool SkipCFWS(string data, ref int offset)
- {
- int comments = 0;
- for (; offset < data.Length; offset++)
- {
- if (data[offset] > 127)
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeHeaderInvalidCharacter, data[offset], ((int)data[offset]).ToString("X", CultureInfo.InvariantCulture))));
- else if (data[offset] == '\\' && comments > 0)
- offset += 2;
- else if (data[offset] == '(')
- comments++;
- else if (data[offset] == ')')
- comments--;
- else if (data[offset] != ' ' && data[offset] != '\t' && comments == 0)
- return true;
- }
- return false;
- }
- public static string ReadQuotedString(string data, ref int offset, StringBuilder builder)
- {
- // assume first char is the opening quote
- int start = ++offset;
- StringBuilder localBuilder = (builder != null ? builder : new StringBuilder());
- for (; offset < data.Length; offset++)
- {
- if (data[offset] == '\\')
- {
- localBuilder.Append(data, start, offset - start);
- start = ++offset;
- continue;
- }
- else if (data[offset] == '"')
- {
- localBuilder.Append(data, start, offset - start);
- offset++;
- return (builder != null ? null : localBuilder.ToString());
- }
- else if (!(data[offset] < s_fqtext.Length && s_fqtext[data[offset]]))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeHeaderInvalidCharacter, data[offset], ((int)data[offset]).ToString("X", CultureInfo.InvariantCulture))));
- }
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeReaderMalformedHeader)));
- }
- public static string ReadParameterAttribute(string data, ref int offset, StringBuilder builder)
- {
- if (!SkipCFWS(data, ref offset))
- return null;
- return ReadToken(data, ref offset, null);
- }
- public static string ReadParameterValue(string data, ref int offset, StringBuilder builder)
- {
- if (!SkipCFWS(data, ref offset))
- return string.Empty;
- if (offset < data.Length && data[offset] == '"')
- return ReadQuotedString(data, ref offset, builder);
- else
- return ReadToken(data, ref offset, builder);
- }
- public static string ReadToken(string data, ref int offset, StringBuilder builder)
- {
- int start = offset;
- for (; offset < data.Length; offset++)
- {
- if (data[offset] > s_ttext.Length)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.MimeHeaderInvalidCharacter, data[offset], ((int)data[offset]).ToString("X", CultureInfo.InvariantCulture))));
- }
- else if (!s_ttext[data[offset]])
- {
- break;
- }
- }
- return data.Substring(start, offset - start);
- }
- public static string ReadDigits(string data, ref int offset, StringBuilder builder)
- {
- int start = offset;
- StringBuilder localBuilder = (builder != null ? builder : new StringBuilder());
- for (; offset < data.Length && data[offset] < s_digits.Length && s_digits[data[offset]]; offset++);
- localBuilder.Append(data, start, offset - start);
- return (builder != null ? null : localBuilder.ToString());
- }
- public static bool IsValidMimeBoundary(string data)
- {
- int length = (data == null) ? 0 : data.Length;
- if (length == 0 || length > 70 || data[length - 1] == ' ')
- return false;
- for (int i = 0; i < length; i++)
- {
- if (!(data[i] < s_boundary.Length && s_boundary[data[i]]))
- return false;
- }
- return true;
- }
- }
- }
|