using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net.Cache; using System.Net.Http.Headers; using System.Net.Mail; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using Mono.Net.Security; using Mono.Security.Interface; using Unity; [assembly: NeutralResourcesLanguage("en-US")] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("System.Net.Http.WebRequest, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: AssemblyDelaySign(true)] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CLSCompliant(true)] [assembly: AssemblyTitle("System.Net.Http.dll")] [assembly: AssemblyDescription("System.Net.Http.dll")] [assembly: AssemblyDefaultAlias("System.Net.Http.dll")] [assembly: AssemblyCompany("Mono development team")] [assembly: AssemblyProduct("Mono Common Language Infrastructure")] [assembly: AssemblyCopyright("(c) Various Mono authors")] [assembly: SatelliteContractVersion("4.0.0.0")] [assembly: AssemblyInformationalVersion("4.6.57.0")] [assembly: AssemblyFileVersion("4.6.57.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.0.0.0")] [module: UnverifiableCode] namespace System.Net.Http { internal static class ConnectHelper { internal sealed class CertificateCallbackMapper { public readonly Func FromHttpClientHandler; public readonly RemoteCertificateValidationCallback ForSocketsHttpHandler; public CertificateCallbackMapper(Func fromHttpClientHandler) { FromHttpClientHandler = fromHttpClientHandler; ForSocketsHttpHandler = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => FromHttpClientHandler(new HttpRequestMessage(HttpMethod.Get, (string)sender), certificate as X509Certificate2, chain, sslPolicyErrors); } } private sealed class ConnectEventArgs : SocketAsyncEventArgs { public AsyncTaskMethodBuilder Builder { get; private set; } public CancellationToken CancellationToken { get; private set; } public void Initialize(CancellationToken cancellationToken) { CancellationToken = cancellationToken; AsyncTaskMethodBuilder builder = default(AsyncTaskMethodBuilder); _ = builder.Task; Builder = builder; } public void Clear() { CancellationToken = default(CancellationToken); } protected override void OnCompleted(SocketAsyncEventArgs _) { switch (base.SocketError) { case SocketError.Success: Builder.SetResult(); return; case SocketError.OperationAborted: case SocketError.ConnectionAborted: if (CancellationToken.IsCancellationRequested) { Builder.SetException(CancellationHelper.CreateOperationCanceledException(null, CancellationToken)); return; } break; } Builder.SetException(new SocketException((int)base.SocketError)); } } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct d__2 : IAsyncStateMachine { public int <>1__state; public AsyncValueTaskMethodBuilder<(Socket, Stream)> <>t__builder; public CancellationToken cancellationToken; public string host; public int port; private ConnectEventArgs 5__2; private CancellationTokenRegistration <>7__wrap2; private ConfiguredTaskAwaitable.ConfiguredTaskAwaiter <>u__1; private void MoveNext() { int num = <>1__state; (Socket, Stream) result; try { if (num != 0 && !s_connectEventArgs.TryDequeue(ref 5__2)) { 5__2 = new ConnectEventArgs(); } try { if (num != 0) { 5__2.Initialize(cancellationToken); 5__2.RemoteEndPoint = new DnsEndPoint(host, port); if (!Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, 5__2)) { if (5__2.SocketError != 0) { throw new SocketException((int)5__2.SocketError); } goto IL_015b; } <>7__wrap2 = cancellationToken.Register(delegate(object s) { Socket.CancelConnectAsync((SocketAsyncEventArgs)s); }, 5__2); } try { ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter; if (num != 0) { awaiter = 5__2.Builder.Task.ConfigureAwait(continueOnCapturedContext: false).GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter; <>t__builder.AwaitUnsafeOnCompletedd__2>(ref awaiter, ref this); return; } } else { awaiter = <>u__1; <>u__1 = default(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter); num = (<>1__state = -1); } awaiter.GetResult(); } finally { if (num < 0) { ((IDisposable)<>7__wrap2).Dispose(); } } <>7__wrap2 = default(CancellationTokenRegistration); goto IL_015b; IL_015b: Socket connectSocket = 5__2.ConnectSocket; connectSocket.NoDelay = true; result = (connectSocket, new NetworkStream(connectSocket, ownsSocket: true)); } catch (Exception ex) { throw CancellationHelper.ShouldWrapInOperationCanceledException(ex, cancellationToken) ? CancellationHelper.CreateOperationCanceledException(ex, cancellationToken) : new HttpRequestException(ex.Message, ex); } finally { if (num < 0) { 5__2.Clear(); if (!s_connectEventArgs.TryEnqueue(5__2)) { 5__2.Dispose(); } } } } catch (Exception exception) { <>1__state = -2; 5__2 = null; <>t__builder.SetException(exception); return; } <>1__state = -2; 5__2 = null; <>t__builder.SetResult(result); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { <>t__builder.SetStateMachine(stateMachine); } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } } [StructLayout(LayoutKind.Auto)] [CompilerGenerated] private struct d__5 : IAsyncStateMachine { public int <>1__state; public AsyncValueTaskMethodBuilder <>t__builder; public Stream stream; public CancellationToken cancellationToken; public SslClientAuthenticationOptions sslOptions; private SslStream 5__2; private CancellationTokenRegistration 5__3; private ConfiguredTaskAwaitable.ConfiguredTaskAwaiter <>u__1; private void MoveNext() { int num = <>1__state; SslStream result; try { if (num != 0) { 5__2 = new SslStream(stream); 5__3 = cancellationToken.Register(delegate(object s) { ((Stream)s).Dispose(); }, stream); } try { ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter; if (num != 0) { awaiter = 5__2.AuthenticateAsClientAsync(sslOptions, cancellationToken).ConfigureAwait(continueOnCapturedContext: false).GetAwaiter(); if (!awaiter.IsCompleted) { num = (<>1__state = 0); <>u__1 = awaiter; <>t__builder.AwaitUnsafeOnCompletedd__5>(ref awaiter, ref this); return; } } else { awaiter = <>u__1; <>u__1 = default(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter); num = (<>1__state = -1); } awaiter.GetResult(); } catch (Exception ex) { 5__2.Dispose(); if (CancellationHelper.ShouldWrapInOperationCanceledException(ex, cancellationToken)) { throw CancellationHelper.CreateOperationCanceledException(ex, cancellationToken); } throw new HttpRequestException("The SSL connection could not be established, see inner exception.", ex); } finally { if (num < 0) { 5__3.Dispose(); } } if (cancellationToken.IsCancellationRequested) { 5__2.Dispose(); throw CancellationHelper.CreateOperationCanceledException(null, cancellationToken); } result = 5__2; } catch (Exception exception) { <>1__state = -2; 5__2 = null; 5__3 = default(CancellationTokenRegistration); <>t__builder.SetException(exception); return; } <>1__state = -2; 5__2 = null; 5__3 = default(CancellationTokenRegistration); <>t__builder.SetResult(result); } void IAsyncStateMachine.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext this.MoveNext(); } [DebuggerHidden] private void SetStateMachine(IAsyncStateMachine stateMachine) { <>t__builder.SetStateMachine(stateMachine); } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine this.SetStateMachine(stateMachine); } } private static readonly Segment s_connectEventArgs = new Segment(Segment.RoundUpToPowerOf2(Math.Max(2, Environment.ProcessorCount))); [AsyncStateMachine(typeof(d__2))] public static ValueTask<(Socket, Stream)> ConnectAsync(string host, int port, CancellationToken cancellationToken) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) d__2 d__ = default(d__2); d__.host = host; d__.port = port; d__.cancellationToken = cancellationToken; d__.<>t__builder = AsyncValueTaskMethodBuilder<(Socket, Stream)>.Create(); d__.<>1__state = -1; d__.<>t__builder.Start<d__2>(ref d__); return d__.<>t__builder.Task; } public static ValueTask EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Stream stream, CancellationToken cancellationToken) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) RemoteCertificateValidationCallback remoteCertificateValidationCallback = sslOptions.RemoteCertificateValidationCallback; if (remoteCertificateValidationCallback != null && remoteCertificateValidationCallback.Target is CertificateCallbackMapper certificateCallbackMapper) { sslOptions = SslClientAuthenticationOptionsExtensions.ShallowClone(sslOptions); Func localFromHttpClientHandler = certificateCallbackMapper.FromHttpClientHandler; HttpRequestMessage localRequest = request; sslOptions.RemoteCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => localFromHttpClientHandler(localRequest, certificate as X509Certificate2, chain, sslPolicyErrors); } return EstablishSslConnectionAsyncCore(stream, sslOptions, cancellationToken); } [AsyncStateMachine(typeof(d__5))] private static ValueTask EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) d__5 d__ = default(d__5); d__.stream = stream; d__.sslOptions = sslOptions; d__.cancellationToken = cancellationToken; d__.<>t__builder = AsyncValueTaskMethodBuilder.Create(); d__.<>1__state = -1; d__.<>t__builder.Start<d__5>(ref d__); return d__.<>t__builder.Task; } } internal static class HttpUtilities { internal static Version DefaultRequestVersion => HttpVersion.Version20; internal static Version DefaultResponseVersion => HttpVersion.Version11; internal static bool IsHttpUri(Uri uri) { return IsSupportedScheme(uri.Scheme); } internal static bool IsSupportedScheme(string scheme) { if (!IsSupportedNonSecureScheme(scheme)) { return IsSupportedSecureScheme(scheme); } return true; } internal static bool IsSupportedNonSecureScheme(string scheme) { if (!string.Equals(scheme, "http", StringComparison.OrdinalIgnoreCase)) { return IsNonSecureWebSocketScheme(scheme); } return true; } internal static bool IsSupportedSecureScheme(string scheme) { if (!string.Equals(scheme, "https", StringComparison.OrdinalIgnoreCase)) { return IsSecureWebSocketScheme(scheme); } return true; } internal static bool IsNonSecureWebSocketScheme(string scheme) { return string.Equals(scheme, "ws", StringComparison.OrdinalIgnoreCase); } internal static bool IsSecureWebSocketScheme(string scheme) { return string.Equals(scheme, "wss", StringComparison.OrdinalIgnoreCase); } internal static Task ContinueWithStandard(this Task task, object state, Action, object> continuation) { return task.ContinueWith(continuation, state, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } } internal static class CancellationHelper { private static readonly string s_cancellationMessage = new OperationCanceledException().Message; internal static bool ShouldWrapInOperationCanceledException(Exception exception, CancellationToken cancellationToken) { if (!(exception is OperationCanceledException)) { return cancellationToken.IsCancellationRequested; } return false; } internal static Exception CreateOperationCanceledException(Exception innerException, CancellationToken cancellationToken) { return new TaskCanceledException(s_cancellationMessage, innerException, cancellationToken); } private static void ThrowOperationCanceledException(Exception innerException, CancellationToken cancellationToken) { throw CreateOperationCanceledException(innerException, cancellationToken); } internal static void ThrowIfCancellationRequested(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { ThrowOperationCanceledException(null, cancellationToken); } } } public class HttpClientHandler : HttpMessageHandler { private readonly IMonoHttpClientHandler _delegatingHandler; private ClientCertificateOption _clientCertificateOptions; public static Func DangerousAcceptAnyServerCertificateValidator { get { throw new PlatformNotSupportedException(); } } public virtual bool SupportsAutomaticDecompression => _delegatingHandler.SupportsAutomaticDecompression; public virtual bool SupportsProxy => true; public virtual bool SupportsRedirectConfiguration => true; public bool UseCookies { get { return _delegatingHandler.UseCookies; } set { _delegatingHandler.UseCookies = value; } } public CookieContainer CookieContainer { get { return _delegatingHandler.CookieContainer; } set { _delegatingHandler.CookieContainer = value; } } public ClientCertificateOption ClientCertificateOptions { get { return _clientCertificateOptions; } set { switch (value) { case ClientCertificateOption.Manual: ThrowForModifiedManagedSslOptionsIfStarted(); _clientCertificateOptions = value; _delegatingHandler.SslOptions.LocalCertificateSelectionCallback = (object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) => CertificateHelper.GetEligibleClientCertificate(ClientCertificates); break; case ClientCertificateOption.Automatic: ThrowForModifiedManagedSslOptionsIfStarted(); _clientCertificateOptions = value; _delegatingHandler.SslOptions.LocalCertificateSelectionCallback = (object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) => CertificateHelper.GetEligibleClientCertificate(); break; default: throw new ArgumentOutOfRangeException("value"); } } } public X509CertificateCollection ClientCertificates { get { if (ClientCertificateOptions != 0) { throw new InvalidOperationException(SR.Format("The {0} property must be set to '{1}' to use this property.", (object)"ClientCertificateOptions", (object)"Manual")); } return _delegatingHandler.SslOptions.ClientCertificates ?? (_delegatingHandler.SslOptions.ClientCertificates = new X509CertificateCollection()); } } public Func ServerCertificateCustomValidationCallback { get { return (_delegatingHandler.SslOptions.RemoteCertificateValidationCallback?.Target as ConnectHelper.CertificateCallbackMapper)?.FromHttpClientHandler; } set { ThrowForModifiedManagedSslOptionsIfStarted(); _delegatingHandler.SslOptions.RemoteCertificateValidationCallback = ((value != null) ? new ConnectHelper.CertificateCallbackMapper(value).ForSocketsHttpHandler : null); } } public bool CheckCertificateRevocationList { get { return _delegatingHandler.SslOptions.CertificateRevocationCheckMode == X509RevocationMode.Online; } set { ThrowForModifiedManagedSslOptionsIfStarted(); _delegatingHandler.SslOptions.CertificateRevocationCheckMode = (value ? X509RevocationMode.Online : X509RevocationMode.NoCheck); } } public SslProtocols SslProtocols { get { return _delegatingHandler.SslOptions.EnabledSslProtocols; } set { ThrowForModifiedManagedSslOptionsIfStarted(); _delegatingHandler.SslOptions.EnabledSslProtocols = value; } } public DecompressionMethods AutomaticDecompression { get { return _delegatingHandler.AutomaticDecompression; } set { _delegatingHandler.AutomaticDecompression = value; } } public bool UseProxy { get { return _delegatingHandler.UseProxy; } set { _delegatingHandler.UseProxy = value; } } public IWebProxy Proxy { get { return _delegatingHandler.Proxy; } set { _delegatingHandler.Proxy = value; } } public ICredentials DefaultProxyCredentials { get { return _delegatingHandler.DefaultProxyCredentials; } set { _delegatingHandler.DefaultProxyCredentials = value; } } public bool PreAuthenticate { get { return _delegatingHandler.PreAuthenticate; } set { _delegatingHandler.PreAuthenticate = value; } } public bool UseDefaultCredentials { get { return _delegatingHandler.Credentials == CredentialCache.DefaultCredentials; } set { if (value) { _delegatingHandler.Credentials = CredentialCache.DefaultCredentials; } else if (_delegatingHandler.Credentials == CredentialCache.DefaultCredentials) { _delegatingHandler.Credentials = null; } } } public ICredentials Credentials { get { return _delegatingHandler.Credentials; } set { _delegatingHandler.Credentials = value; } } public bool AllowAutoRedirect { get { return _delegatingHandler.AllowAutoRedirect; } set { _delegatingHandler.AllowAutoRedirect = value; } } public int MaxAutomaticRedirections { get { return _delegatingHandler.MaxAutomaticRedirections; } set { _delegatingHandler.MaxAutomaticRedirections = value; } } public int MaxConnectionsPerServer { get { return _delegatingHandler.MaxConnectionsPerServer; } set { _delegatingHandler.MaxConnectionsPerServer = value; } } public int MaxResponseHeadersLength { get { return _delegatingHandler.MaxResponseHeadersLength; } set { _delegatingHandler.MaxResponseHeadersLength = value; } } public long MaxRequestContentBufferSize { get { return _delegatingHandler.MaxRequestContentBufferSize; } set { _delegatingHandler.MaxRequestContentBufferSize = value; } } public IDictionary Properties => _delegatingHandler.Properties; private static IMonoHttpClientHandler CreateDefaultHandler() { return new MonoWebRequestHandler(); } public HttpClientHandler() : this(CreateDefaultHandler()) { } internal HttpClientHandler(IMonoHttpClientHandler handler) { _delegatingHandler = handler; ClientCertificateOptions = ClientCertificateOption.Manual; } protected override void Dispose(bool disposing) { if (disposing) { _delegatingHandler.Dispose(); } base.Dispose(disposing); } private void ThrowForModifiedManagedSslOptionsIfStarted() { _delegatingHandler.SslOptions = _delegatingHandler.SslOptions; } internal void SetWebRequestTimeout(TimeSpan timeout) { _delegatingHandler.SetWebRequestTimeout(timeout); } protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return _delegatingHandler.SendAsync(request, cancellationToken); } } internal interface IMonoHttpClientHandler : IDisposable { bool SupportsAutomaticDecompression { get; } bool UseCookies { get; set; } CookieContainer CookieContainer { get; set; } SslClientAuthenticationOptions SslOptions { get; set; } DecompressionMethods AutomaticDecompression { get; set; } bool UseProxy { get; set; } IWebProxy Proxy { get; set; } ICredentials DefaultProxyCredentials { get; set; } bool PreAuthenticate { get; set; } ICredentials Credentials { get; set; } bool AllowAutoRedirect { get; set; } int MaxAutomaticRedirections { get; set; } int MaxConnectionsPerServer { get; set; } int MaxResponseHeadersLength { get; set; } long MaxRequestContentBufferSize { get; set; } IDictionary Properties { get; } Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); void SetWebRequestTimeout(TimeSpan timeout); } internal class MonoWebRequestHandler : IMonoHttpClientHandler, IDisposable { private static long groupCounter; private bool allowAutoRedirect; private DecompressionMethods automaticDecompression; private CookieContainer cookieContainer; private ICredentials credentials; private int maxAutomaticRedirections; private long maxRequestContentBufferSize; private bool preAuthenticate; private IWebProxy proxy; private bool useCookies; private bool useProxy; private SslClientAuthenticationOptions sslOptions; private bool allowPipelining; private RequestCachePolicy cachePolicy; private AuthenticationLevel authenticationLevel; private TimeSpan continueTimeout; private TokenImpersonationLevel impersonationLevel; private int maxResponseHeadersLength; private int readWriteTimeout; private RemoteCertificateValidationCallback serverCertificateValidationCallback; private bool unsafeAuthenticatedConnectionSharing; private bool sentRequest; private string connectionGroupName; private TimeSpan? timeout; private bool disposed; public bool AllowAutoRedirect { get { return allowAutoRedirect; } set { EnsureModifiability(); allowAutoRedirect = value; } } public DecompressionMethods AutomaticDecompression { get { return automaticDecompression; } set { EnsureModifiability(); automaticDecompression = value; } } public CookieContainer CookieContainer { get { return cookieContainer ?? (cookieContainer = new CookieContainer()); } set { EnsureModifiability(); cookieContainer = value; } } public ICredentials Credentials { get { return credentials; } set { EnsureModifiability(); credentials = value; } } public int MaxAutomaticRedirections { get { return maxAutomaticRedirections; } set { EnsureModifiability(); if (value <= 0) { throw new ArgumentOutOfRangeException(); } maxAutomaticRedirections = value; } } public long MaxRequestContentBufferSize { get { return maxRequestContentBufferSize; } set { EnsureModifiability(); if (value < 0) { throw new ArgumentOutOfRangeException(); } maxRequestContentBufferSize = value; } } public bool PreAuthenticate { get { return preAuthenticate; } set { EnsureModifiability(); preAuthenticate = value; } } public IWebProxy Proxy { get { return proxy; } set { EnsureModifiability(); if (!UseProxy) { throw new InvalidOperationException(); } proxy = value; } } public virtual bool SupportsAutomaticDecompression => true; public virtual bool SupportsProxy => true; public virtual bool SupportsRedirectConfiguration => true; public bool UseCookies { get { return useCookies; } set { EnsureModifiability(); useCookies = value; } } public bool UseProxy { get { return useProxy; } set { EnsureModifiability(); useProxy = value; } } public bool AllowPipelining { get { return allowPipelining; } set { EnsureModifiability(); allowPipelining = value; } } public RequestCachePolicy CachePolicy { get { return cachePolicy; } set { EnsureModifiability(); cachePolicy = value; } } public AuthenticationLevel AuthenticationLevel { get { return authenticationLevel; } set { EnsureModifiability(); authenticationLevel = value; } } [MonoTODO] public TimeSpan ContinueTimeout { get { return continueTimeout; } set { EnsureModifiability(); continueTimeout = value; } } public TokenImpersonationLevel ImpersonationLevel { get { return impersonationLevel; } set { EnsureModifiability(); impersonationLevel = value; } } public int MaxResponseHeadersLength { get { return maxResponseHeadersLength; } set { EnsureModifiability(); maxResponseHeadersLength = value; } } public int ReadWriteTimeout { get { return readWriteTimeout; } set { EnsureModifiability(); readWriteTimeout = value; } } public RemoteCertificateValidationCallback ServerCertificateValidationCallback { get { return serverCertificateValidationCallback; } set { EnsureModifiability(); serverCertificateValidationCallback = value; } } public bool UnsafeAuthenticatedConnectionSharing { get { return unsafeAuthenticatedConnectionSharing; } set { EnsureModifiability(); unsafeAuthenticatedConnectionSharing = value; } } public SslClientAuthenticationOptions SslOptions { get { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0017: Expected O, but got Unknown SslClientAuthenticationOptions obj = sslOptions; if (obj == null) { SslClientAuthenticationOptions val = new SslClientAuthenticationOptions(); SslClientAuthenticationOptions val2 = val; sslOptions = val; obj = val2; } return obj; } set { EnsureModifiability(); sslOptions = value; } } public ICredentials DefaultProxyCredentials { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public int MaxConnectionsPerServer { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public IDictionary Properties { get { throw new NotImplementedException(); } } public MonoWebRequestHandler() { allowAutoRedirect = true; maxAutomaticRedirections = 50; maxRequestContentBufferSize = 2147483647L; useCookies = true; useProxy = true; allowPipelining = true; authenticationLevel = AuthenticationLevel.MutualAuthRequested; cachePolicy = WebRequest.DefaultCachePolicy; continueTimeout = TimeSpan.FromMilliseconds(350.0); impersonationLevel = TokenImpersonationLevel.Delegation; maxResponseHeadersLength = HttpWebRequest.DefaultMaximumResponseHeadersLength; readWriteTimeout = 300000; serverCertificateValidationCallback = null; unsafeAuthenticatedConnectionSharing = false; connectionGroupName = "HttpClientHandler" + Interlocked.Increment(ref groupCounter); } internal void EnsureModifiability() { if (sentRequest) { throw new InvalidOperationException("This instance has already started one or more requests. Properties can only be modified before sending the first request."); } } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && !disposed) { Volatile.Write(ref disposed, value: true); ServicePointManager.CloseConnectionGroup(connectionGroupName); } } private bool GetConnectionKeepAlive(HttpRequestHeaders headers) { return headers.Connection.Any((string l) => string.Equals(l, "Keep-Alive", StringComparison.OrdinalIgnoreCase)); } internal virtual HttpWebRequest CreateWebRequest(HttpRequestMessage request) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown HttpWebRequest httpWebRequest; if (HttpUtilities.IsSupportedSecureScheme(request.RequestUri.Scheme)) { httpWebRequest = new HttpWebRequest(request.RequestUri, MonoTlsProviderFactory.GetProviderInternal(), MonoTlsSettings.CopyDefaultSettings()); httpWebRequest.TlsSettings.ClientCertificateSelectionCallback = (MonoLocalCertificateSelectionCallback)((string t, X509CertificateCollection lc, X509Certificate rc, string[] ai) => SslOptions.LocalCertificateSelectionCallback(this, t, lc, rc, ai)); } else { httpWebRequest = new HttpWebRequest(request.RequestUri); } httpWebRequest.ThrowOnError = false; httpWebRequest.AllowWriteStreamBuffering = false; if (request.Version == HttpVersion.Version20) { httpWebRequest.ProtocolVersion = HttpVersion.Version11; } else { httpWebRequest.ProtocolVersion = request.Version; } httpWebRequest.ConnectionGroupName = connectionGroupName; httpWebRequest.Method = request.Method.Method; if (httpWebRequest.ProtocolVersion == HttpVersion.Version10) { httpWebRequest.KeepAlive = GetConnectionKeepAlive(request.Headers); } else { httpWebRequest.KeepAlive = request.Headers.ConnectionClose != true; } if (allowAutoRedirect) { httpWebRequest.AllowAutoRedirect = true; httpWebRequest.MaximumAutomaticRedirections = maxAutomaticRedirections; } else { httpWebRequest.AllowAutoRedirect = false; } httpWebRequest.AutomaticDecompression = automaticDecompression; httpWebRequest.PreAuthenticate = preAuthenticate; if (useCookies) { httpWebRequest.CookieContainer = CookieContainer; } httpWebRequest.Credentials = credentials; if (useProxy) { httpWebRequest.Proxy = proxy; } else { httpWebRequest.Proxy = null; } httpWebRequest.ServicePoint.Expect100Continue = request.Headers.ExpectContinue == true; if (timeout.HasValue) { httpWebRequest.Timeout = (int)timeout.Value.TotalMilliseconds; } httpWebRequest.ServerCertificateValidationCallback = SslOptions.RemoteCertificateValidationCallback; WebHeaderCollection headers = httpWebRequest.Headers; foreach (KeyValuePair> header in request.Headers) { IEnumerable enumerable = header.Value; if (header.Key == "Host") { httpWebRequest.Host = request.Headers.Host; continue; } if (header.Key == "Transfer-Encoding") { enumerable = enumerable.Where((string l) => l != "chunked"); } string singleHeaderString = PlatformHelper.GetSingleHeaderString(header.Key, enumerable); if (singleHeaderString != null) { headers.AddInternal(header.Key, singleHeaderString); } } return httpWebRequest; } private HttpResponseMessage CreateResponseMessage(HttpWebResponse wr, HttpRequestMessage requestMessage, CancellationToken cancellationToken) { HttpResponseMessage httpResponseMessage = new HttpResponseMessage(wr.StatusCode); httpResponseMessage.RequestMessage = requestMessage; httpResponseMessage.ReasonPhrase = wr.StatusDescription; httpResponseMessage.Content = PlatformHelper.CreateStreamContent(wr.GetResponseStream(), cancellationToken); WebHeaderCollection headers = wr.Headers; for (int i = 0; i < headers.Count; i++) { string key = headers.GetKey(i); string[] values = headers.GetValues(i); HttpHeaders httpHeaders = ((!PlatformHelper.IsContentHeader(key)) ? ((HttpHeaders)httpResponseMessage.Headers) : ((HttpHeaders)httpResponseMessage.Content.Headers)); httpHeaders.TryAddWithoutValidation(key, values); } requestMessage.RequestUri = wr.ResponseUri; return httpResponseMessage; } private static bool MethodHasBody(HttpMethod method) { switch (method.Method) { case "HEAD": case "GET": case "MKCOL": case "CONNECT": case "TRACE": return false; default: return true; } } public async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (disposed) { throw new ObjectDisposedException(GetType().ToString()); } FieldInfo field = typeof(CancellationToken).GetField("_source", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); CancellationTokenSource obj = (CancellationTokenSource)field.GetValue(cancellationToken); field = typeof(CancellationTokenSource).GetField("_timer", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); Timer timer = (Timer)field.GetValue(obj); if (timer != null) { field = typeof(Timer).GetField("due_time_ms", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); timeout = TimeSpan.FromMilliseconds((long)field.GetValue(timer)); } Volatile.Write(ref sentRequest, value: true); HttpWebRequest wrequest = CreateWebRequest(request); HttpWebResponse wresponse = null; try { using (cancellationToken.Register(delegate(object l) { ((HttpWebRequest)l).Abort(); }, wrequest)) { HttpContent content = request.Content; if (content != null) { WebHeaderCollection headers = wrequest.Headers; foreach (KeyValuePair> header in content.Headers) { foreach (string item in header.Value) { headers.AddInternal(header.Key, item); } } if (request.Headers.TransferEncodingChunked == true) { wrequest.SendChunked = true; } else { long? contentLength = content.Headers.ContentLength; if (contentLength.HasValue) { wrequest.ContentLength = contentLength.Value; } else { if (MaxRequestContentBufferSize == 0L) { throw new InvalidOperationException("The content length of the request content can't be determined. Either set TransferEncodingChunked to true, load content into buffer, or set MaxRequestContentBufferSize."); } await content.LoadIntoBufferAsync(MaxRequestContentBufferSize).ConfigureAwait(continueOnCapturedContext: false); wrequest.ContentLength = content.Headers.ContentLength.Value; } } wrequest.ResendContentFactory = content.CopyToAsync; using Stream stream = await wrequest.GetRequestStreamAsync().ConfigureAwait(continueOnCapturedContext: false); await request.Content.CopyToAsync(stream).ConfigureAwait(continueOnCapturedContext: false); } else if (MethodHasBody(request.Method)) { wrequest.ContentLength = 0L; } wresponse = (HttpWebResponse)(await wrequest.GetResponseAsync().ConfigureAwait(continueOnCapturedContext: false)); } } catch (WebException ex) { if (ex.Status != WebExceptionStatus.RequestCanceled) { throw new HttpRequestException("An error occurred while sending the request", ex); } } catch (IOException inner) { throw new HttpRequestException("An error occurred while sending the request", inner); } if (cancellationToken.IsCancellationRequested) { TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); taskCompletionSource.SetCanceled(); return await taskCompletionSource.Task; } return CreateResponseMessage(wresponse, request, cancellationToken); } void IMonoHttpClientHandler.SetWebRequestTimeout(TimeSpan timeout) { this.timeout = timeout; } } internal static class PlatformHelper { internal static bool IsContentHeader(string name) { return HttpHeaders.GetKnownHeaderKind(name) == HttpHeaderKind.Content; } internal static string GetSingleHeaderString(string name, IEnumerable values) { return HttpHeaders.GetSingleHeaderString(name, values); } internal static StreamContent CreateStreamContent(Stream stream, CancellationToken cancellationToken) { return new StreamContent(stream, cancellationToken); } } public class ByteArrayContent : HttpContent { private readonly byte[] content; private readonly int offset; private readonly int count; public ByteArrayContent(byte[] content) { if (content == null) { throw new ArgumentNullException("content"); } this.content = content; count = content.Length; } public ByteArrayContent(byte[] content, int offset, int count) : this(content) { if (offset < 0 || offset > this.count) { throw new ArgumentOutOfRangeException("offset"); } if (count < 0 || count > this.count - offset) { throw new ArgumentOutOfRangeException("count"); } this.offset = offset; this.count = count; } protected override Task CreateContentReadStreamAsync() { return Task.FromResult((Stream)new MemoryStream(content, offset, count)); } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { return stream.WriteAsync(content, offset, count); } protected internal override bool TryComputeLength(out long length) { length = count; return true; } } public enum ClientCertificateOption { Manual, Automatic } public abstract class DelegatingHandler : HttpMessageHandler { private bool disposed; private HttpMessageHandler handler; public HttpMessageHandler InnerHandler { get { return handler; } set { if (value == null) { throw new ArgumentNullException("InnerHandler"); } handler = value; } } protected DelegatingHandler() { } protected DelegatingHandler(HttpMessageHandler innerHandler) { if (innerHandler == null) { throw new ArgumentNullException("innerHandler"); } InnerHandler = innerHandler; } protected override void Dispose(bool disposing) { if (disposing && !disposed) { disposed = true; if (InnerHandler != null) { InnerHandler.Dispose(); } } base.Dispose(disposing); } protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (InnerHandler == null) { throw new InvalidOperationException("The inner handler has not been assigned."); } return InnerHandler.SendAsync(request, cancellationToken); } } public class FormUrlEncodedContent : ByteArrayContent { public FormUrlEncodedContent(IEnumerable> nameValueCollection) : base(EncodeContent(nameValueCollection)) { base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); } private static byte[] EncodeContent(IEnumerable> nameValueCollection) { if (nameValueCollection == null) { throw new ArgumentNullException("nameValueCollection"); } List list = new List(); foreach (KeyValuePair item in nameValueCollection) { if (list.Count != 0) { list.Add(38); } byte[] array = SerializeValue(item.Key); if (array != null) { list.AddRange(array); } list.Add(61); array = SerializeValue(item.Value); if (array != null) { list.AddRange(array); } } return list.ToArray(); } private static byte[] SerializeValue(string value) { if (value == null) { return null; } value = Uri.EscapeDataString(value).Replace("%20", "+"); return Encoding.ASCII.GetBytes(value); } } public class HttpClient : HttpMessageInvoker { private static readonly TimeSpan TimeoutDefault = TimeSpan.FromSeconds(100.0); private Uri base_address; private CancellationTokenSource cts; private bool disposed; private HttpRequestHeaders headers; private long buffer_size; private TimeSpan timeout; public Uri BaseAddress { get { return base_address; } set { base_address = value; } } public HttpRequestHeaders DefaultRequestHeaders => headers ?? (headers = new HttpRequestHeaders()); public long MaxResponseContentBufferSize { get { return buffer_size; } set { if (value <= 0) { throw new ArgumentOutOfRangeException(); } buffer_size = value; } } public TimeSpan Timeout { get { return timeout; } set { if (value != System.Threading.Timeout.InfiniteTimeSpan && (value <= TimeSpan.Zero || value.TotalMilliseconds > 2147483647.0)) { throw new ArgumentOutOfRangeException(); } timeout = value; } } public HttpClient() : this(new HttpClientHandler(), disposeHandler: true) { } public HttpClient(HttpMessageHandler handler) : this(handler, disposeHandler: true) { } public HttpClient(HttpMessageHandler handler, bool disposeHandler) : base(handler, disposeHandler) { buffer_size = 2147483647L; timeout = TimeoutDefault; cts = new CancellationTokenSource(); } public void CancelPendingRequests() { using CancellationTokenSource cancellationTokenSource = Interlocked.Exchange(ref cts, new CancellationTokenSource()); cancellationTokenSource.Cancel(); } protected override void Dispose(bool disposing) { if (disposing && !disposed) { disposed = true; cts.Cancel(); cts.Dispose(); } base.Dispose(disposing); } public Task DeleteAsync(string requestUri) { return SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri)); } public Task DeleteAsync(string requestUri, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri), cancellationToken); } public Task DeleteAsync(Uri requestUri) { return SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri)); } public Task DeleteAsync(Uri requestUri, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Delete, requestUri), cancellationToken); } public Task GetAsync(string requestUri) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri)); } public Task GetAsync(string requestUri, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), cancellationToken); } public Task GetAsync(string requestUri, HttpCompletionOption completionOption) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption); } public Task GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken); } public Task GetAsync(Uri requestUri) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri)); } public Task GetAsync(Uri requestUri, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), cancellationToken); } public Task GetAsync(Uri requestUri, HttpCompletionOption completionOption) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption); } public Task GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken); } public Task PostAsync(string requestUri, HttpContent content) { return SendAsync(new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = content }); } public Task PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = content }, cancellationToken); } public Task PostAsync(Uri requestUri, HttpContent content) { return SendAsync(new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = content }); } public Task PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = content }, cancellationToken); } public Task PutAsync(Uri requestUri, HttpContent content) { return SendAsync(new HttpRequestMessage(HttpMethod.Put, requestUri) { Content = content }); } public Task PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Put, requestUri) { Content = content }, cancellationToken); } public Task PutAsync(string requestUri, HttpContent content) { return SendAsync(new HttpRequestMessage(HttpMethod.Put, requestUri) { Content = content }); } public Task PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Put, requestUri) { Content = content }, cancellationToken); } public Task SendAsync(HttpRequestMessage request) { return SendAsync(request, HttpCompletionOption.ResponseContentRead, CancellationToken.None); } public Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption) { return SendAsync(request, completionOption, CancellationToken.None); } public override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken); } public Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException("request"); } if (request.SetIsUsed()) { throw new InvalidOperationException("Cannot send the same request message multiple times"); } Uri requestUri = request.RequestUri; if (requestUri == null) { if (base_address == null) { throw new InvalidOperationException("The request URI must either be an absolute URI or BaseAddress must be set"); } request.RequestUri = base_address; } else if (!requestUri.IsAbsoluteUri || (requestUri.Scheme == Uri.UriSchemeFile && requestUri.OriginalString.StartsWith("/", StringComparison.Ordinal))) { if (base_address == null) { throw new InvalidOperationException("The request URI must either be an absolute URI or BaseAddress must be set"); } request.RequestUri = new Uri(base_address, requestUri); } if (headers != null) { request.Headers.AddHeaders(headers); } return SendAsyncWorker(request, completionOption, cancellationToken); } private async Task SendAsyncWorker(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { using CancellationTokenSource lcts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, cancellationToken); if (handler is HttpClientHandler httpClientHandler) { httpClientHandler.SetWebRequestTimeout(timeout); } lcts.CancelAfter(timeout); HttpResponseMessage response = await (base.SendAsync(request, lcts.Token) ?? throw new InvalidOperationException("Handler failed to return a value")).ConfigureAwait(continueOnCapturedContext: false); if (response == null) { throw new InvalidOperationException("Handler failed to return a response"); } if (response.Content != null && (completionOption & HttpCompletionOption.ResponseHeadersRead) == 0) { await response.Content.LoadIntoBufferAsync(MaxResponseContentBufferSize).ConfigureAwait(continueOnCapturedContext: false); } return response; } public async Task GetByteArrayAsync(string requestUri) { using HttpResponseMessage resp = await GetAsync(requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait(continueOnCapturedContext: false); resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsByteArrayAsync().ConfigureAwait(continueOnCapturedContext: false); } public async Task GetByteArrayAsync(Uri requestUri) { using HttpResponseMessage resp = await GetAsync(requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait(continueOnCapturedContext: false); resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsByteArrayAsync().ConfigureAwait(continueOnCapturedContext: false); } public async Task GetStreamAsync(string requestUri) { HttpResponseMessage obj = await GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(continueOnCapturedContext: false); obj.EnsureSuccessStatusCode(); return await obj.Content.ReadAsStreamAsync().ConfigureAwait(continueOnCapturedContext: false); } public async Task GetStreamAsync(Uri requestUri) { HttpResponseMessage obj = await GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(continueOnCapturedContext: false); obj.EnsureSuccessStatusCode(); return await obj.Content.ReadAsStreamAsync().ConfigureAwait(continueOnCapturedContext: false); } public async Task GetStringAsync(string requestUri) { using HttpResponseMessage resp = await GetAsync(requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait(continueOnCapturedContext: false); resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false); } public async Task GetStringAsync(Uri requestUri) { using HttpResponseMessage resp = await GetAsync(requestUri, HttpCompletionOption.ResponseContentRead).ConfigureAwait(continueOnCapturedContext: false); resp.EnsureSuccessStatusCode(); return await resp.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false); } public Task PatchAsync(string requestUri, HttpContent content) { throw new PlatformNotSupportedException(); } public Task PatchAsync(string requestUri, HttpContent content, CancellationToken cancellationToken) { throw new PlatformNotSupportedException(); } public Task PatchAsync(Uri requestUri, HttpContent content) { throw new PlatformNotSupportedException(); } public Task PatchAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken) { throw new PlatformNotSupportedException(); } } public enum HttpCompletionOption { ResponseContentRead, ResponseHeadersRead } public abstract class HttpContent : IDisposable { private sealed class FixedMemoryStream : MemoryStream { private readonly long maxSize; public FixedMemoryStream(long maxSize) { this.maxSize = maxSize; } private void CheckOverflow(int count) { if (Length + count > maxSize) { throw new HttpRequestException($"Cannot write more bytes to the buffer than the configured maximum buffer size: {maxSize}"); } } public override void WriteByte(byte value) { CheckOverflow(1); base.WriteByte(value); } public override void Write(byte[] buffer, int offset, int count) { CheckOverflow(count); base.Write(buffer, offset, count); } } private FixedMemoryStream buffer; private Stream stream; private bool disposed; private HttpContentHeaders headers; public HttpContentHeaders Headers => headers ?? (headers = new HttpContentHeaders(this)); internal long? LoadedBufferLength { get { if (buffer != null) { return buffer.Length; } return null; } } internal void CopyTo(Stream stream) { CopyToAsync(stream).Wait(); } public Task CopyToAsync(Stream stream) { return CopyToAsync(stream, null); } public Task CopyToAsync(Stream stream, TransportContext context) { if (stream == null) { throw new ArgumentNullException("stream"); } if (buffer != null) { return buffer.CopyToAsync(stream); } return SerializeToStreamAsync(stream, context); } protected virtual async Task CreateContentReadStreamAsync() { await LoadIntoBufferAsync().ConfigureAwait(continueOnCapturedContext: false); return buffer; } private static FixedMemoryStream CreateFixedMemoryStream(long maxBufferSize) { return new FixedMemoryStream(maxBufferSize); } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && !disposed) { disposed = true; if (buffer != null) { buffer.Dispose(); } } } public Task LoadIntoBufferAsync() { return LoadIntoBufferAsync(2147483647L); } public async Task LoadIntoBufferAsync(long maxBufferSize) { if (disposed) { throw new ObjectDisposedException(GetType().ToString()); } if (buffer == null) { buffer = CreateFixedMemoryStream(maxBufferSize); await SerializeToStreamAsync(buffer, null).ConfigureAwait(continueOnCapturedContext: false); buffer.Seek(0L, SeekOrigin.Begin); } } public async Task ReadAsStreamAsync() { if (disposed) { throw new ObjectDisposedException(GetType().ToString()); } if (buffer != null) { return new MemoryStream(buffer.GetBuffer(), 0, (int)buffer.Length, writable: false); } if (stream == null) { stream = await CreateContentReadStreamAsync().ConfigureAwait(continueOnCapturedContext: false); } return stream; } public async Task ReadAsByteArrayAsync() { await LoadIntoBufferAsync().ConfigureAwait(continueOnCapturedContext: false); return buffer.ToArray(); } public async Task ReadAsStringAsync() { await LoadIntoBufferAsync().ConfigureAwait(continueOnCapturedContext: false); if (buffer.Length == 0L) { return string.Empty; } byte[] array = buffer.GetBuffer(); int num = (int)buffer.Length; int preambleLength = 0; Encoding encoding; if (headers != null && headers.ContentType != null && headers.ContentType.CharSet != null) { encoding = Encoding.GetEncoding(headers.ContentType.CharSet); preambleLength = StartsWith(array, num, encoding.GetPreamble()); } else { encoding = GetEncodingFromBuffer(array, num, ref preambleLength) ?? Encoding.UTF8; } return encoding.GetString(array, preambleLength, num - preambleLength); } private static Encoding GetEncodingFromBuffer(byte[] buffer, int length, ref int preambleLength) { Encoding[] array = new Encoding[3] { Encoding.UTF8, Encoding.UTF32, Encoding.Unicode }; foreach (Encoding encoding in array) { if ((preambleLength = StartsWith(buffer, length, encoding.GetPreamble())) != 0) { return encoding; } } return null; } private static int StartsWith(byte[] array, int length, byte[] value) { if (length < value.Length) { return 0; } for (int i = 0; i < value.Length; i++) { if (array[i] != value[i]) { return 0; } } return value.Length; } internal Task SerializeToStreamAsync_internal(Stream stream, TransportContext context) { return SerializeToStreamAsync(stream, context); } protected abstract Task SerializeToStreamAsync(Stream stream, TransportContext context); protected internal abstract bool TryComputeLength(out long length); } public abstract class HttpMessageHandler : IDisposable { public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { } protected internal abstract Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); } public class HttpMessageInvoker : IDisposable { private protected HttpMessageHandler handler; private readonly bool disposeHandler; public HttpMessageInvoker(HttpMessageHandler handler) : this(handler, disposeHandler: true) { } public HttpMessageInvoker(HttpMessageHandler handler, bool disposeHandler) { if (handler == null) { throw new ArgumentNullException("handler"); } this.handler = handler; this.disposeHandler = disposeHandler; } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && disposeHandler && handler != null) { handler.Dispose(); handler = null; } } public virtual Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return handler.SendAsync(request, cancellationToken); } } public class HttpMethod : IEquatable { private static readonly HttpMethod delete_method = new HttpMethod("DELETE"); private static readonly HttpMethod get_method = new HttpMethod("GET"); private static readonly HttpMethod head_method = new HttpMethod("HEAD"); private static readonly HttpMethod options_method = new HttpMethod("OPTIONS"); private static readonly HttpMethod post_method = new HttpMethod("POST"); private static readonly HttpMethod put_method = new HttpMethod("PUT"); private static readonly HttpMethod trace_method = new HttpMethod("TRACE"); private readonly string method; public static HttpMethod Delete => delete_method; public static HttpMethod Get => get_method; public static HttpMethod Head => head_method; public string Method => method; public static HttpMethod Options => options_method; public static HttpMethod Post => post_method; public static HttpMethod Put => put_method; public static HttpMethod Trace => trace_method; public static HttpMethod Patch { get { throw new PlatformNotSupportedException(); } } public HttpMethod(string method) { if (string.IsNullOrEmpty(method)) { throw new ArgumentException("method"); } Parser.Token.Check(method); this.method = method; } public static bool operator ==(HttpMethod left, HttpMethod right) { if ((object)left == null || (object)right == null) { return (object)left == right; } return left.Equals(right); } public static bool operator !=(HttpMethod left, HttpMethod right) { return !(left == right); } public bool Equals(HttpMethod other) { return string.Equals(method, other.method, StringComparison.OrdinalIgnoreCase); } public override bool Equals(object obj) { if (obj is HttpMethod other) { return Equals(other); } return false; } public override int GetHashCode() { return method.GetHashCode(); } public override string ToString() { return method; } } [Serializable] public class HttpRequestException : Exception { public HttpRequestException() { } public HttpRequestException(string message) : base(message) { } public HttpRequestException(string message, Exception inner) : base(message, inner) { } } public class HttpRequestMessage : IDisposable { private HttpRequestHeaders headers; private HttpMethod method; private Version version; private Dictionary properties; private Uri uri; private bool is_used; private bool disposed; public HttpContent Content { get; set; } public HttpRequestHeaders Headers => headers ?? (headers = new HttpRequestHeaders()); public HttpMethod Method { get { return method; } set { if (value == null) { throw new ArgumentNullException("method"); } method = value; } } public IDictionary Properties => properties ?? (properties = new Dictionary()); public Uri RequestUri { get { return uri; } set { if (value != null && value.IsAbsoluteUri && !IsAllowedAbsoluteUri(value)) { throw new ArgumentException("Only http or https scheme is allowed"); } uri = value; } } public Version Version { get { return version ?? HttpVersion.Version11; } set { if (value == null) { throw new ArgumentNullException("Version"); } version = value; } } public HttpRequestMessage() { method = HttpMethod.Get; } public HttpRequestMessage(HttpMethod method, string requestUri) : this(method, string.IsNullOrEmpty(requestUri) ? null : new Uri(requestUri, UriKind.RelativeOrAbsolute)) { } public HttpRequestMessage(HttpMethod method, Uri requestUri) { Method = method; RequestUri = requestUri; } private static bool IsAllowedAbsoluteUri(Uri uri) { if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) { return true; } if (uri.Scheme == Uri.UriSchemeFile && uri.OriginalString.StartsWith("/", StringComparison.Ordinal)) { return true; } return false; } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && !disposed) { disposed = true; if (Content != null) { Content.Dispose(); } } } internal bool SetIsUsed() { if (is_used) { return true; } is_used = true; return false; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("Method: ").Append(method); stringBuilder.Append(", RequestUri: '").Append((RequestUri != null) ? RequestUri.ToString() : ""); stringBuilder.Append("', Version: ").Append(Version); stringBuilder.Append(", Content: ").Append((Content != null) ? Content.ToString() : ""); stringBuilder.Append(", Headers:\r\n{\r\n").Append(Headers); if (Content != null) { stringBuilder.Append(Content.Headers); } stringBuilder.Append("}"); return stringBuilder.ToString(); } } public class HttpResponseMessage : IDisposable { private HttpResponseHeaders headers; private HttpResponseHeaders trailingHeaders; private string reasonPhrase; private HttpStatusCode statusCode; private Version version; private bool disposed; public HttpContent Content { get; set; } public HttpResponseHeaders Headers => headers ?? (headers = new HttpResponseHeaders()); public bool IsSuccessStatusCode { get { if (statusCode >= HttpStatusCode.OK) { return statusCode < HttpStatusCode.MultipleChoices; } return false; } } public string ReasonPhrase { get { return reasonPhrase ?? HttpStatusDescription.Get(statusCode); } set { reasonPhrase = value; } } public HttpRequestMessage RequestMessage { get; set; } public HttpStatusCode StatusCode { get { return statusCode; } set { if (value < (HttpStatusCode)0) { throw new ArgumentOutOfRangeException(); } statusCode = value; } } public Version Version { get { return version ?? HttpVersion.Version11; } set { if (value == null) { throw new ArgumentNullException("Version"); } version = value; } } public HttpResponseHeaders TrailingHeaders { get { if (trailingHeaders == null) { trailingHeaders = new HttpResponseHeaders(); } return trailingHeaders; } } public HttpResponseMessage() : this(HttpStatusCode.OK) { } public HttpResponseMessage(HttpStatusCode statusCode) { StatusCode = statusCode; } public void Dispose() { Dispose(disposing: true); } protected virtual void Dispose(bool disposing) { if (disposing && !disposed) { disposed = true; if (Content != null) { Content.Dispose(); } } } public HttpResponseMessage EnsureSuccessStatusCode() { if (IsSuccessStatusCode) { return this; } throw new HttpRequestException($"{(int)statusCode} ({ReasonPhrase})"); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("StatusCode: ").Append((int)StatusCode); stringBuilder.Append(", ReasonPhrase: '").Append(ReasonPhrase ?? ""); stringBuilder.Append("', Version: ").Append(Version); stringBuilder.Append(", Content: ").Append((Content != null) ? Content.ToString() : ""); stringBuilder.Append(", Headers:\r\n{\r\n").Append(Headers); if (Content != null) { stringBuilder.Append(Content.Headers); } stringBuilder.Append("}"); return stringBuilder.ToString(); } } public abstract class MessageProcessingHandler : DelegatingHandler { protected MessageProcessingHandler() { } protected MessageProcessingHandler(HttpMessageHandler innerHandler) : base(innerHandler) { } protected abstract HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken); protected abstract HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken); protected internal sealed override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request = ProcessRequest(request, cancellationToken); return ProcessResponse(await base.SendAsync(request, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), cancellationToken); } } public class MultipartContent : HttpContent, IEnumerable, IEnumerable { private List nested_content; private readonly string boundary; public MultipartContent() : this("mixed") { } public MultipartContent(string subtype) : this(subtype, Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture)) { } public MultipartContent(string subtype, string boundary) { if (string.IsNullOrWhiteSpace(subtype)) { throw new ArgumentException("boundary"); } if (string.IsNullOrWhiteSpace(boundary)) { throw new ArgumentException("boundary"); } if (boundary.Length > 70) { throw new ArgumentOutOfRangeException("boundary"); } if (boundary.Last() == ' ' || !IsValidRFC2049(boundary)) { throw new ArgumentException("boundary"); } this.boundary = boundary; nested_content = new List(2); base.Headers.ContentType = new MediaTypeHeaderValue("multipart/" + subtype) { Parameters = { new NameValueHeaderValue("boundary", "\"" + boundary + "\"") } }; } private static bool IsValidRFC2049(string s) { foreach (char c in s) { if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9')) { switch (c) { case '\'': case '(': case ')': case '+': case ',': case '-': case '.': case '/': case ':': case '=': case '?': continue; } return false; } } return true; } public virtual void Add(HttpContent content) { if (content == null) { throw new ArgumentNullException("content"); } if (nested_content == null) { nested_content = new List(); } nested_content.Add(content); } protected override void Dispose(bool disposing) { if (disposing) { foreach (HttpContent item in nested_content) { item.Dispose(); } nested_content = null; } base.Dispose(disposing); } protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) { StringBuilder sb = new StringBuilder(); sb.Append('-').Append('-'); sb.Append(boundary); sb.Append('\r').Append('\n'); byte[] bytes; for (int i = 0; i < nested_content.Count; i++) { HttpContent c = nested_content[i]; foreach (KeyValuePair> header in c.Headers) { sb.Append(header.Key); sb.Append(':').Append(' '); foreach (string item in header.Value) { sb.Append(item); } sb.Append('\r').Append('\n'); } sb.Append('\r').Append('\n'); bytes = Encoding.ASCII.GetBytes(sb.ToString()); sb.Clear(); await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(continueOnCapturedContext: false); await c.SerializeToStreamAsync_internal(stream, context).ConfigureAwait(continueOnCapturedContext: false); if (i != nested_content.Count - 1) { sb.Append('\r').Append('\n'); sb.Append('-').Append('-'); sb.Append(boundary); sb.Append('\r').Append('\n'); } } sb.Append('\r').Append('\n'); sb.Append('-').Append('-'); sb.Append(boundary); sb.Append('-').Append('-'); sb.Append('\r').Append('\n'); bytes = Encoding.ASCII.GetBytes(sb.ToString()); await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(continueOnCapturedContext: false); } protected internal override bool TryComputeLength(out long length) { length = 12 + 2 * boundary.Length; for (int i = 0; i < nested_content.Count; i++) { HttpContent httpContent = nested_content[i]; foreach (KeyValuePair> header in httpContent.Headers) { length += header.Key.Length; length += 4L; foreach (string item in header.Value) { length += item.Length; } } if (!httpContent.TryComputeLength(out var length2)) { return false; } length += 2L; length += length2; if (i != nested_content.Count - 1) { length += 6L; length += boundary.Length; } } return true; } public IEnumerator GetEnumerator() { return nested_content.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return nested_content.GetEnumerator(); } } public class MultipartFormDataContent : MultipartContent { public MultipartFormDataContent() : base("form-data") { } public MultipartFormDataContent(string boundary) : base("form-data", boundary) { } public override void Add(HttpContent content) { base.Add(content); AddContentDisposition(content, null, null); } public void Add(HttpContent content, string name) { base.Add(content); if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("name"); } AddContentDisposition(content, name, null); } public void Add(HttpContent content, string name, string fileName) { base.Add(content); if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("name"); } if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentException("fileName"); } AddContentDisposition(content, name, fileName); } private void AddContentDisposition(HttpContent content, string name, string fileName) { HttpContentHeaders httpContentHeaders = content.Headers; if (httpContentHeaders.ContentDisposition == null) { httpContentHeaders.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = name, FileName = fileName, FileNameStar = fileName }; } } } public class StreamContent : HttpContent { private readonly Stream content; private readonly int bufferSize; private readonly CancellationToken cancellationToken; private readonly long startPosition; private bool contentCopied; public StreamContent(Stream content) : this(content, 16384) { } public StreamContent(Stream content, int bufferSize) { if (content == null) { throw new ArgumentNullException("content"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } this.content = content; this.bufferSize = bufferSize; if (content.CanSeek) { startPosition = content.Position; } } internal StreamContent(Stream content, CancellationToken cancellationToken) : this(content) { this.cancellationToken = cancellationToken; } protected override Task CreateContentReadStreamAsync() { return Task.FromResult(content); } protected override void Dispose(bool disposing) { if (disposing) { content.Dispose(); } base.Dispose(disposing); } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { if (contentCopied) { if (!content.CanSeek) { throw new InvalidOperationException("The stream was already consumed. It cannot be read again."); } content.Seek(startPosition, SeekOrigin.Begin); } else { contentCopied = true; } return content.CopyToAsync(stream, bufferSize, cancellationToken); } protected internal override bool TryComputeLength(out long length) { if (!content.CanSeek) { length = 0L; return false; } length = content.Length - startPosition; return true; } } public class StringContent : ByteArrayContent { public StringContent(string content) : this(content, null, null) { } public StringContent(string content, Encoding encoding) : this(content, encoding, null) { } public StringContent(string content, Encoding encoding, string mediaType) : base(GetByteArray(content, encoding)) { base.Headers.ContentType = new MediaTypeHeaderValue(mediaType ?? "text/plain") { CharSet = (encoding ?? Encoding.UTF8).WebName }; } private static byte[] GetByteArray(string content, Encoding encoding) { return (encoding ?? Encoding.UTF8).GetBytes(content); } } public sealed class ReadOnlyMemoryContent : HttpContent { public ReadOnlyMemoryContent(ReadOnlyMemory content) { throw new PlatformNotSupportedException(); } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { throw new PlatformNotSupportedException(); } protected internal override bool TryComputeLength(out long length) { throw new PlatformNotSupportedException(); } } } namespace System.Net.Http.Headers { public class AuthenticationHeaderValue : ICloneable { public string Parameter { get; private set; } public string Scheme { get; private set; } public AuthenticationHeaderValue(string scheme) : this(scheme, null) { } public AuthenticationHeaderValue(string scheme, string parameter) { Parser.Token.Check(scheme); Scheme = scheme; Parameter = parameter; } private AuthenticationHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (obj is AuthenticationHeaderValue authenticationHeaderValue && string.Equals(authenticationHeaderValue.Scheme, Scheme, StringComparison.OrdinalIgnoreCase)) { return authenticationHeaderValue.Parameter == Parameter; } return false; } public override int GetHashCode() { int num = Scheme.ToLowerInvariant().GetHashCode(); if (!string.IsNullOrEmpty(Parameter)) { num ^= Parameter.ToLowerInvariant().GetHashCode(); } return num; } public static AuthenticationHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out AuthenticationHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out AuthenticationHeaderValue parsedValue, out Token t) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { parsedValue = null; return false; } parsedValue = new AuthenticationHeaderValue(); parsedValue.Scheme = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.Token) { parsedValue.Parameter = lexer.GetRemainingStringValue(t.StartPosition); t = new Token(Token.Type.End, 0, 0); } return true; } public override string ToString() { if (Parameter == null) { return Scheme; } return Scheme + " " + Parameter; } } public class CacheControlHeaderValue : ICloneable { private List extensions; private List no_cache_headers; private List private_headers; public ICollection Extensions => extensions ?? (extensions = new List()); public TimeSpan? MaxAge { get; set; } public bool MaxStale { get; set; } public TimeSpan? MaxStaleLimit { get; set; } public TimeSpan? MinFresh { get; set; } public bool MustRevalidate { get; set; } public bool NoCache { get; set; } public ICollection NoCacheHeaders => no_cache_headers ?? (no_cache_headers = new List()); public bool NoStore { get; set; } public bool NoTransform { get; set; } public bool OnlyIfCached { get; set; } public bool Private { get; set; } public ICollection PrivateHeaders => private_headers ?? (private_headers = new List()); public bool ProxyRevalidate { get; set; } public bool Public { get; set; } public TimeSpan? SharedMaxAge { get; set; } object ICloneable.Clone() { CacheControlHeaderValue cacheControlHeaderValue = (CacheControlHeaderValue)MemberwiseClone(); if (extensions != null) { cacheControlHeaderValue.extensions = new List(); foreach (NameValueHeaderValue extension in extensions) { cacheControlHeaderValue.extensions.Add(extension); } } if (no_cache_headers != null) { cacheControlHeaderValue.no_cache_headers = new List(); foreach (string no_cache_header in no_cache_headers) { cacheControlHeaderValue.no_cache_headers.Add(no_cache_header); } } if (private_headers != null) { cacheControlHeaderValue.private_headers = new List(); foreach (string private_header in private_headers) { cacheControlHeaderValue.private_headers.Add(private_header); } } return cacheControlHeaderValue; } public override bool Equals(object obj) { if (!(obj is CacheControlHeaderValue cacheControlHeaderValue)) { return false; } TimeSpan? maxAge = MaxAge; TimeSpan? maxAge2 = cacheControlHeaderValue.MaxAge; if (maxAge.HasValue == maxAge2.HasValue && (!maxAge.HasValue || !(maxAge.GetValueOrDefault() != maxAge2.GetValueOrDefault())) && MaxStale == cacheControlHeaderValue.MaxStale && !(MaxStaleLimit != cacheControlHeaderValue.MaxStaleLimit)) { maxAge = MinFresh; maxAge2 = cacheControlHeaderValue.MinFresh; if (maxAge.HasValue == maxAge2.HasValue && (!maxAge.HasValue || !(maxAge.GetValueOrDefault() != maxAge2.GetValueOrDefault())) && MustRevalidate == cacheControlHeaderValue.MustRevalidate && NoCache == cacheControlHeaderValue.NoCache && NoStore == cacheControlHeaderValue.NoStore && NoTransform == cacheControlHeaderValue.NoTransform && OnlyIfCached == cacheControlHeaderValue.OnlyIfCached && Private == cacheControlHeaderValue.Private && ProxyRevalidate == cacheControlHeaderValue.ProxyRevalidate && Public == cacheControlHeaderValue.Public && !(SharedMaxAge != cacheControlHeaderValue.SharedMaxAge)) { if (extensions.SequenceEqual(cacheControlHeaderValue.extensions) && no_cache_headers.SequenceEqual(cacheControlHeaderValue.no_cache_headers)) { return private_headers.SequenceEqual(cacheControlHeaderValue.private_headers); } return false; } } return false; } public override int GetHashCode() { return (((((((((((((((29 * 29 + HashCodeCalculator.Calculate(extensions)) * 29 + MaxAge.GetHashCode()) * 29 + MaxStale.GetHashCode()) * 29 + MaxStaleLimit.GetHashCode()) * 29 + MinFresh.GetHashCode()) * 29 + MustRevalidate.GetHashCode()) * 29 + HashCodeCalculator.Calculate(no_cache_headers)) * 29 + NoCache.GetHashCode()) * 29 + NoStore.GetHashCode()) * 29 + NoTransform.GetHashCode()) * 29 + OnlyIfCached.GetHashCode()) * 29 + Private.GetHashCode()) * 29 + HashCodeCalculator.Calculate(private_headers)) * 29 + ProxyRevalidate.GetHashCode()) * 29 + Public.GetHashCode()) * 29 + SharedMaxAge.GetHashCode(); } public static CacheControlHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out CacheControlHeaderValue parsedValue) { parsedValue = null; if (input == null) { return true; } CacheControlHeaderValue cacheControlHeaderValue = new CacheControlHeaderValue(); Lexer lexer = new Lexer(input); Token token; do { token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } string stringValue = lexer.GetStringValue(token); bool flag = false; switch (stringValue) { case "no-store": cacheControlHeaderValue.NoStore = true; break; case "no-transform": cacheControlHeaderValue.NoTransform = true; break; case "only-if-cached": cacheControlHeaderValue.OnlyIfCached = true; break; case "public": cacheControlHeaderValue.Public = true; break; case "must-revalidate": cacheControlHeaderValue.MustRevalidate = true; break; case "proxy-revalidate": cacheControlHeaderValue.ProxyRevalidate = true; break; case "max-stale": { cacheControlHeaderValue.MaxStale = true; token = lexer.Scan(); if ((Token.Type)token != Token.Type.SeparatorEqual) { flag = true; break; } token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } TimeSpan? maxStaleLimit = lexer.TryGetTimeSpanValue(token); if (!maxStaleLimit.HasValue) { return false; } cacheControlHeaderValue.MaxStaleLimit = maxStaleLimit; break; } case "max-age": case "s-maxage": case "min-fresh": { token = lexer.Scan(); if ((Token.Type)token != Token.Type.SeparatorEqual) { return false; } token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } TimeSpan? maxStaleLimit = lexer.TryGetTimeSpanValue(token); if (!maxStaleLimit.HasValue) { return false; } switch (stringValue.Length) { case 7: cacheControlHeaderValue.MaxAge = maxStaleLimit; break; case 8: cacheControlHeaderValue.SharedMaxAge = maxStaleLimit; break; default: cacheControlHeaderValue.MinFresh = maxStaleLimit; break; } break; } case "private": case "no-cache": { if (stringValue.Length == 7) { cacheControlHeaderValue.Private = true; } else { cacheControlHeaderValue.NoCache = true; } token = lexer.Scan(); if ((Token.Type)token != Token.Type.SeparatorEqual) { flag = true; break; } token = lexer.Scan(); if ((Token.Type)token != Token.Type.QuotedString) { return false; } string[] array = lexer.GetQuotedStringValue(token).Split(','); for (int i = 0; i < array.Length; i++) { string item = array[i].Trim('\t', ' '); if (stringValue.Length == 7) { cacheControlHeaderValue.PrivateHeaders.Add(item); continue; } cacheControlHeaderValue.NoCache = true; cacheControlHeaderValue.NoCacheHeaders.Add(item); } break; } default: { string stringValue2 = lexer.GetStringValue(token); string value = null; token = lexer.Scan(); if ((Token.Type)token == Token.Type.SeparatorEqual) { token = lexer.Scan(); Token.Type kind = token.Kind; if ((uint)(kind - 2) > 1u) { return false; } value = lexer.GetStringValue(token); } else { flag = true; } cacheControlHeaderValue.Extensions.Add(NameValueHeaderValue.Create(stringValue2, value)); break; } } if (!flag) { token = lexer.Scan(); } } while ((Token.Type)token == Token.Type.SeparatorComma); if ((Token.Type)token != Token.Type.End) { return false; } parsedValue = cacheControlHeaderValue; return true; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); if (NoStore) { stringBuilder.Append("no-store"); stringBuilder.Append(", "); } if (NoTransform) { stringBuilder.Append("no-transform"); stringBuilder.Append(", "); } if (OnlyIfCached) { stringBuilder.Append("only-if-cached"); stringBuilder.Append(", "); } if (Public) { stringBuilder.Append("public"); stringBuilder.Append(", "); } if (MustRevalidate) { stringBuilder.Append("must-revalidate"); stringBuilder.Append(", "); } if (ProxyRevalidate) { stringBuilder.Append("proxy-revalidate"); stringBuilder.Append(", "); } if (NoCache) { stringBuilder.Append("no-cache"); if (no_cache_headers != null) { stringBuilder.Append("=\""); no_cache_headers.ToStringBuilder(stringBuilder); stringBuilder.Append("\""); } stringBuilder.Append(", "); } if (MaxAge.HasValue) { stringBuilder.Append("max-age="); stringBuilder.Append(MaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append(", "); } if (SharedMaxAge.HasValue) { stringBuilder.Append("s-maxage="); stringBuilder.Append(SharedMaxAge.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append(", "); } if (MaxStale) { stringBuilder.Append("max-stale"); if (MaxStaleLimit.HasValue) { stringBuilder.Append("="); stringBuilder.Append(MaxStaleLimit.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture)); } stringBuilder.Append(", "); } if (MinFresh.HasValue) { stringBuilder.Append("min-fresh="); stringBuilder.Append(MinFresh.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append(", "); } if (Private) { stringBuilder.Append("private"); if (private_headers != null) { stringBuilder.Append("=\""); private_headers.ToStringBuilder(stringBuilder); stringBuilder.Append("\""); } stringBuilder.Append(", "); } extensions.ToStringBuilder(stringBuilder); if (stringBuilder.Length > 2 && stringBuilder[stringBuilder.Length - 2] == ',' && stringBuilder[stringBuilder.Length - 1] == ' ') { stringBuilder.Remove(stringBuilder.Length - 2, 2); } return stringBuilder.ToString(); } } internal static class CollectionExtensions { public static bool SequenceEqual(this List first, List second) { if (first == null) { if (second != null) { return second.Count == 0; } return true; } if (second == null) { if (first != null) { return first.Count == 0; } return true; } return Enumerable.SequenceEqual(first, second); } public static void SetValue(this List parameters, string key, string value) { for (int i = 0; i < parameters.Count; i++) { if (string.Equals(parameters[i].Name, key, StringComparison.OrdinalIgnoreCase)) { if (value == null) { parameters.RemoveAt(i); } else { parameters[i].Value = value; } return; } } if (!string.IsNullOrEmpty(value)) { parameters.Add(new NameValueHeaderValue(key, value)); } } public static string ToString(this List list) { if (list == null || list.Count == 0) { return null; } StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < list.Count; i++) { stringBuilder.Append("; "); stringBuilder.Append(list[i]); } return stringBuilder.ToString(); } public static void ToStringBuilder(this List list, StringBuilder sb) { if (list == null || list.Count == 0) { return; } for (int i = 0; i < list.Count; i++) { if (i > 0) { sb.Append(", "); } sb.Append(list[i]); } } } internal delegate bool ElementTryParser(Lexer lexer, out T parsedValue, out Token token); internal static class CollectionParser { public static bool TryParse(string input, int minimalCount, ElementTryParser parser, out List result) where T : class { Lexer lexer = new Lexer(input); result = new List(); Token token; do { if (!parser(lexer, out var parsedValue, out token)) { return false; } if (parsedValue != null) { result.Add(parsedValue); } } while ((Token.Type)token == Token.Type.SeparatorComma); if ((Token.Type)token == Token.Type.End) { if (minimalCount > result.Count) { result = null; return false; } return true; } result = null; return false; } public static bool TryParse(string input, int minimalCount, out List result) { return TryParse(input, minimalCount, (ElementTryParser)TryParseStringElement, out result); } public static bool TryParseRepetition(string input, int minimalCount, out List result) { return TryParseRepetition(input, minimalCount, (ElementTryParser)TryParseStringElement, out result); } private static bool TryParseStringElement(Lexer lexer, out string parsedValue, out Token t) { t = lexer.Scan(); if ((Token.Type)t == Token.Type.Token) { parsedValue = lexer.GetStringValue(t); if (parsedValue.Length == 0) { parsedValue = null; } t = lexer.Scan(); } else { parsedValue = null; } return true; } public static bool TryParseRepetition(string input, int minimalCount, ElementTryParser parser, out List result) where T : class { Lexer lexer = new Lexer(input); result = new List(); Token token; do { if (!parser(lexer, out var parsedValue, out token)) { return false; } if (parsedValue != null) { result.Add(parsedValue); } } while ((Token.Type)token != Token.Type.End); if (minimalCount > result.Count) { return false; } return true; } } public class ContentDispositionHeaderValue : ICloneable { private string dispositionType; private List parameters; public DateTimeOffset? CreationDate { get { return GetDateValue("creation-date"); } set { SetDateValue("creation-date", value); } } public string DispositionType { get { return dispositionType; } set { Parser.Token.Check(value); dispositionType = value; } } public string FileName { get { string text = FindParameter("filename"); if (text == null) { return null; } return DecodeValue(text, extendedNotation: false); } set { if (value != null) { value = EncodeBase64Value(value); } SetValue("filename", value); } } public string FileNameStar { get { string text = FindParameter("filename*"); if (text == null) { return null; } return DecodeValue(text, extendedNotation: true); } set { if (value != null) { value = EncodeRFC5987(value); } SetValue("filename*", value); } } public DateTimeOffset? ModificationDate { get { return GetDateValue("modification-date"); } set { SetDateValue("modification-date", value); } } public string Name { get { string text = FindParameter("name"); if (text == null) { return null; } return DecodeValue(text, extendedNotation: false); } set { if (value != null) { value = EncodeBase64Value(value); } SetValue("name", value); } } public ICollection Parameters => parameters ?? (parameters = new List()); public DateTimeOffset? ReadDate { get { return GetDateValue("read-date"); } set { SetDateValue("read-date", value); } } public long? Size { get { if (Parser.Long.TryParse(FindParameter("size"), out var result)) { return result; } return null; } set { if (!value.HasValue) { SetValue("size", null); return; } if (value < 0) { throw new ArgumentOutOfRangeException("value"); } SetValue("size", value.Value.ToString(CultureInfo.InvariantCulture)); } } private ContentDispositionHeaderValue() { } public ContentDispositionHeaderValue(string dispositionType) { DispositionType = dispositionType; } protected ContentDispositionHeaderValue(ContentDispositionHeaderValue source) { if (source == null) { throw new ArgumentNullException("source"); } dispositionType = source.dispositionType; if (source.parameters == null) { return; } foreach (NameValueHeaderValue parameter in source.parameters) { Parameters.Add(new NameValueHeaderValue(parameter)); } } object ICloneable.Clone() { return new ContentDispositionHeaderValue(this); } public override bool Equals(object obj) { if (obj is ContentDispositionHeaderValue contentDispositionHeaderValue && string.Equals(contentDispositionHeaderValue.dispositionType, dispositionType, StringComparison.OrdinalIgnoreCase)) { return contentDispositionHeaderValue.parameters.SequenceEqual(parameters); } return false; } private string FindParameter(string name) { if (parameters == null) { return null; } foreach (NameValueHeaderValue parameter in parameters) { if (string.Equals(parameter.Name, name, StringComparison.OrdinalIgnoreCase)) { return parameter.Value; } } return null; } private DateTimeOffset? GetDateValue(string name) { string text = FindParameter(name); if (text == null || text == null) { return null; } if (text.Length < 3) { return null; } if (text[0] == '"') { text = text.Substring(1, text.Length - 2); } if (Lexer.TryGetDateValue(text, out var value)) { return value; } return null; } private static string EncodeBase64Value(string value) { bool flag = value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"'; if (flag) { value = value.Substring(1, value.Length - 2); } for (int i = 0; i < value.Length; i++) { if (value[i] > '\u007f') { Encoding uTF = Encoding.UTF8; return $"\"=?{uTF.WebName}?B?{Convert.ToBase64String(uTF.GetBytes(value))}?=\""; } } if (flag || !Lexer.IsValidToken(value)) { return "\"" + value + "\""; } return value; } private static string EncodeRFC5987(string value) { Encoding uTF = Encoding.UTF8; StringBuilder stringBuilder = new StringBuilder(value.Length + 11); stringBuilder.Append(uTF.WebName); stringBuilder.Append('\''); stringBuilder.Append('\''); foreach (char c in value) { if (c > '\u007f') { byte[] bytes = uTF.GetBytes(new char[1] { c }); foreach (byte b in bytes) { stringBuilder.Append('%'); stringBuilder.Append(b.ToString("X2")); } } else if (!Lexer.IsValidCharacter(c) || c == '*' || c == '?' || c == '%') { stringBuilder.Append(Uri.HexEscape(c)); } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } private static string DecodeValue(string value, bool extendedNotation) { if (value.Length < 2) { return value; } string[] array; Encoding encoding; if (value[0] == '"') { array = value.Split('?'); if (array.Length != 5 || array[0] != "\"=" || array[4] != "=\"" || (array[2] != "B" && array[2] != "b")) { return value; } try { encoding = Encoding.GetEncoding(array[1]); return encoding.GetString(Convert.FromBase64String(array[3])); } catch { return value; } } if (!extendedNotation) { return value; } array = value.Split('\''); if (array.Length != 3) { return null; } try { encoding = Encoding.GetEncoding(array[0]); } catch { return null; } value = array[2]; if (value.IndexOf('%') < 0) { return value; } StringBuilder stringBuilder = new StringBuilder(); byte[] array2 = null; int num = 0; int index = 0; while (index < value.Length) { char c = value[index]; if (c == '%') { char c2 = c; c = Uri.HexUnescape(value, ref index); if (c != c2) { if (array2 == null) { array2 = new byte[value.Length - index + 1]; } array2[num++] = (byte)c; continue; } } else { index++; } if (num != 0) { stringBuilder.Append(encoding.GetChars(array2, 0, num)); num = 0; } stringBuilder.Append(c); } if (num != 0) { stringBuilder.Append(encoding.GetChars(array2, 0, num)); } return stringBuilder.ToString(); } public override int GetHashCode() { return dispositionType.ToLowerInvariant().GetHashCode() ^ HashCodeCalculator.Calculate(parameters); } public static ContentDispositionHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } private void SetDateValue(string key, DateTimeOffset? value) { SetValue(key, (!value.HasValue) ? null : ("\"" + value.Value.ToString("r", CultureInfo.InvariantCulture) + "\"")); } private void SetValue(string key, string value) { if (parameters == null) { parameters = new List(); } parameters.SetValue(key, value); } public override string ToString() { return dispositionType + CollectionExtensions.ToString(parameters); } public static bool TryParse(string input, out ContentDispositionHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); Token token = lexer.Scan(); if (token.Kind != Token.Type.Token) { return false; } List result = null; string stringValue = lexer.GetStringValue(token); token = lexer.Scan(); switch (token.Kind) { case Token.Type.SeparatorSemicolon: if (!NameValueHeaderValue.TryParseParameters(lexer, out result, out token) || (Token.Type)token != Token.Type.End) { return false; } break; default: return false; case Token.Type.End: break; } parsedValue = new ContentDispositionHeaderValue { dispositionType = stringValue, parameters = result }; return true; } } public class ContentRangeHeaderValue : ICloneable { private string unit = "bytes"; public long? From { get; private set; } public bool HasLength => Length.HasValue; public bool HasRange => From.HasValue; public long? Length { get; private set; } public long? To { get; private set; } public string Unit { get { return unit; } set { if (value == null) { throw new ArgumentNullException("Unit"); } Parser.Token.Check(value); unit = value; } } private ContentRangeHeaderValue() { } public ContentRangeHeaderValue(long length) { if (length < 0) { throw new ArgumentOutOfRangeException("length"); } Length = length; } public ContentRangeHeaderValue(long from, long to) { if (from < 0 || from > to) { throw new ArgumentOutOfRangeException("from"); } From = from; To = to; } public ContentRangeHeaderValue(long from, long to, long length) : this(from, to) { if (length < 0) { throw new ArgumentOutOfRangeException("length"); } if (to > length) { throw new ArgumentOutOfRangeException("to"); } Length = length; } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is ContentRangeHeaderValue contentRangeHeaderValue)) { return false; } if (contentRangeHeaderValue.Length == Length && contentRangeHeaderValue.From == From && contentRangeHeaderValue.To == To) { return string.Equals(contentRangeHeaderValue.unit, unit, StringComparison.OrdinalIgnoreCase); } return false; } public override int GetHashCode() { return Unit.GetHashCode() ^ Length.GetHashCode() ^ From.GetHashCode() ^ To.GetHashCode() ^ unit.ToLowerInvariant().GetHashCode(); } public static ContentRangeHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out ContentRangeHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); Token token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } ContentRangeHeaderValue contentRangeHeaderValue = new ContentRangeHeaderValue(); contentRangeHeaderValue.unit = lexer.GetStringValue(token); token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } if (!lexer.IsStarStringValue(token)) { if (!lexer.TryGetNumericValue(token, out long value)) { string stringValue = lexer.GetStringValue(token); if (stringValue.Length < 3) { return false; } string[] array = stringValue.Split('-'); if (array.Length != 2) { return false; } if (!long.TryParse(array[0], NumberStyles.None, CultureInfo.InvariantCulture, out value)) { return false; } contentRangeHeaderValue.From = value; if (!long.TryParse(array[1], NumberStyles.None, CultureInfo.InvariantCulture, out value)) { return false; } contentRangeHeaderValue.To = value; } else { contentRangeHeaderValue.From = value; token = lexer.Scan(recognizeDash: true); if ((Token.Type)token != Token.Type.SeparatorDash) { return false; } token = lexer.Scan(); if (!lexer.TryGetNumericValue(token, out value)) { return false; } contentRangeHeaderValue.To = value; } } token = lexer.Scan(); if ((Token.Type)token != Token.Type.SeparatorSlash) { return false; } token = lexer.Scan(); if (!lexer.IsStarStringValue(token)) { if (!lexer.TryGetNumericValue(token, out long value2)) { return false; } contentRangeHeaderValue.Length = value2; } token = lexer.Scan(); if ((Token.Type)token != Token.Type.End) { return false; } parsedValue = contentRangeHeaderValue; return true; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(unit); stringBuilder.Append(" "); if (!From.HasValue) { stringBuilder.Append("*"); } else { stringBuilder.Append(From.Value.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append("-"); stringBuilder.Append(To.Value.ToString(CultureInfo.InvariantCulture)); } stringBuilder.Append("/"); stringBuilder.Append((!Length.HasValue) ? "*" : Length.Value.ToString(CultureInfo.InvariantCulture)); return stringBuilder.ToString(); } } public class EntityTagHeaderValue : ICloneable { private static readonly EntityTagHeaderValue any = new EntityTagHeaderValue { Tag = "*" }; public static EntityTagHeaderValue Any => any; public bool IsWeak { get; internal set; } public string Tag { get; internal set; } public EntityTagHeaderValue(string tag) { Parser.Token.CheckQuotedString(tag); Tag = tag; } public EntityTagHeaderValue(string tag, bool isWeak) : this(tag) { IsWeak = isWeak; } internal EntityTagHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (obj is EntityTagHeaderValue entityTagHeaderValue && entityTagHeaderValue.Tag == Tag) { return string.Equals(entityTagHeaderValue.Tag, Tag, StringComparison.Ordinal); } return false; } public override int GetHashCode() { return IsWeak.GetHashCode() ^ Tag.GetHashCode(); } public static EntityTagHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out EntityTagHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } private static bool TryParseElement(Lexer lexer, out EntityTagHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); bool isWeak = false; if ((Token.Type)t == Token.Type.Token) { string stringValue = lexer.GetStringValue(t); if (stringValue == "*") { parsedValue = any; t = lexer.Scan(); return true; } if (stringValue != "W" || lexer.PeekChar() != 47) { return false; } isWeak = true; lexer.EatChar(); t = lexer.Scan(); } if ((Token.Type)t != Token.Type.QuotedString) { return false; } parsedValue = new EntityTagHeaderValue(); parsedValue.Tag = lexer.GetStringValue(t); parsedValue.IsWeak = isWeak; t = lexer.Scan(); return true; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } public override string ToString() { if (!IsWeak) { return Tag; } return "W/" + Tag; } } internal static class HashCodeCalculator { public static int Calculate(ICollection list) { if (list == null) { return 0; } int num = 17; foreach (T item in list) { num = num * 29 + item.GetHashCode(); } return num; } } internal delegate bool TryParseDelegate(string value, out T result); internal delegate bool TryParseListDelegate(string value, int minimalCount, out List result); internal abstract class HeaderInfo { private class HeaderTypeInfo : HeaderInfo where U : class { private readonly TryParseDelegate parser; public HeaderTypeInfo(string name, TryParseDelegate parser, HttpHeaderKind headerKind) : base(name, headerKind) { this.parser = parser; } public override void AddToCollection(object collection, object value) { HttpHeaderValueCollection httpHeaderValueCollection = (HttpHeaderValueCollection)collection; if (value is List values) { httpHeaderValueCollection.AddRange(values); } else { httpHeaderValueCollection.Add((U)value); } } protected override object CreateCollection(HttpHeaders headers, HeaderInfo headerInfo) { return new HttpHeaderValueCollection(headers, headerInfo); } public override List ToStringCollection(object collection) { if (collection == null) { return null; } HttpHeaderValueCollection httpHeaderValueCollection = (HttpHeaderValueCollection)collection; if (httpHeaderValueCollection.Count == 0) { if (httpHeaderValueCollection.InvalidValues == null) { return null; } return new List(httpHeaderValueCollection.InvalidValues); } List list = new List(); foreach (U item in httpHeaderValueCollection) { list.Add(item.ToString()); } if (httpHeaderValueCollection.InvalidValues != null) { list.AddRange(httpHeaderValueCollection.InvalidValues); } return list; } public override bool TryParse(string value, out object result) { T result2; bool result3 = parser(value, out result2); result = result2; return result3; } } private class CollectionHeaderTypeInfo : HeaderTypeInfo where U : class { private readonly int minimalCount; private readonly string separator; private readonly TryParseListDelegate parser; public override string Separator => separator; public CollectionHeaderTypeInfo(string name, TryParseListDelegate parser, HttpHeaderKind headerKind, int minimalCount, string separator) : base(name, (TryParseDelegate)null, headerKind) { this.parser = parser; this.minimalCount = minimalCount; AllowsMany = true; this.separator = separator; } public override bool TryParse(string value, out object result) { if (!parser(value, minimalCount, out var result2)) { result = null; return false; } result = result2; return true; } } public bool AllowsMany; public readonly HttpHeaderKind HeaderKind; public readonly string Name; public Func CustomToString { get; private set; } public virtual string Separator { get { throw new NotSupportedException(); } } protected HeaderInfo(string name, HttpHeaderKind headerKind) { Name = name; HeaderKind = headerKind; } public static HeaderInfo CreateSingle(string name, TryParseDelegate parser, HttpHeaderKind headerKind, Func toString = null) { return new HeaderTypeInfo(name, parser, headerKind) { CustomToString = toString }; } public static HeaderInfo CreateMulti(string name, TryParseListDelegate elementParser, HttpHeaderKind headerKind, int minimalCount = 1, string separator = ", ") where T : class { return new CollectionHeaderTypeInfo(name, elementParser, headerKind, minimalCount, separator); } public object CreateCollection(HttpHeaders headers) { return CreateCollection(headers, this); } public abstract void AddToCollection(object collection, object value); protected abstract object CreateCollection(HttpHeaders headers, HeaderInfo headerInfo); public abstract List ToStringCollection(object collection); public abstract bool TryParse(string value, out object result); } public sealed class HttpContentHeaders : HttpHeaders { private readonly HttpContent content; public ICollection Allow => GetValues("Allow"); public ICollection ContentEncoding => GetValues("Content-Encoding"); public ContentDispositionHeaderValue ContentDisposition { get { return GetValue("Content-Disposition"); } set { AddOrRemove("Content-Disposition", value); } } public ICollection ContentLanguage => GetValues("Content-Language"); public long? ContentLength { get { long? value = GetValue("Content-Length"); if (value.HasValue) { return value; } value = content.LoadedBufferLength; if (value.HasValue) { return value; } if (content.TryComputeLength(out var length)) { SetValue("Content-Length", length); return length; } return null; } set { AddOrRemove("Content-Length", value); } } public Uri ContentLocation { get { return GetValue("Content-Location"); } set { AddOrRemove("Content-Location", value); } } public byte[] ContentMD5 { get { return GetValue("Content-MD5"); } set { AddOrRemove("Content-MD5", value, Parser.MD5.ToString); } } public ContentRangeHeaderValue ContentRange { get { return GetValue("Content-Range"); } set { AddOrRemove("Content-Range", value); } } public MediaTypeHeaderValue ContentType { get { return GetValue("Content-Type"); } set { AddOrRemove("Content-Type", value); } } public DateTimeOffset? Expires { get { return GetValue("Expires"); } set { AddOrRemove("Expires", value, Parser.DateTime.ToString); } } public DateTimeOffset? LastModified { get { return GetValue("Last-Modified"); } set { AddOrRemove("Last-Modified", value, Parser.DateTime.ToString); } } internal HttpContentHeaders(HttpContent content) : base(HttpHeaderKind.Content) { this.content = content; } internal HttpContentHeaders() { ThrowStub.ThrowNotSupportedException(); } } [Flags] internal enum HttpHeaderKind { None = 0, Request = 1, Response = 2, Content = 4 } public sealed class HttpHeaderValueCollection : ICollection, IEnumerable, IEnumerable where T : class { private readonly List list; private readonly HttpHeaders headers; private readonly HeaderInfo headerInfo; private List invalidValues; public int Count => list.Count; internal List InvalidValues => invalidValues; public bool IsReadOnly => false; internal HttpHeaderValueCollection(HttpHeaders headers, HeaderInfo headerInfo) { list = new List(); this.headers = headers; this.headerInfo = headerInfo; } public void Add(T item) { list.Add(item); } internal void AddRange(List values) { list.AddRange(values); } internal void AddInvalidValue(string invalidValue) { if (invalidValues == null) { invalidValues = new List(); } invalidValues.Add(invalidValue); } public void Clear() { list.Clear(); invalidValues = null; } public bool Contains(T item) { return list.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); } public void ParseAdd(string input) { headers.AddValue(input, headerInfo, ignoreInvalid: false); } public bool Remove(T item) { return list.Remove(item); } public override string ToString() { string text = string.Join(headerInfo.Separator, list); if (invalidValues != null) { text += string.Join(headerInfo.Separator, invalidValues); } return text; } public bool TryParseAdd(string input) { return headers.AddValue(input, headerInfo, ignoreInvalid: true); } public IEnumerator GetEnumerator() { return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } internal T Find(Predicate predicate) { return list.Find(predicate); } internal void Remove(Predicate predicate) { T val = Find(predicate); if (val != null) { Remove(val); } } internal HttpHeaderValueCollection() { ThrowStub.ThrowNotSupportedException(); } } public abstract class HttpHeaders : IEnumerable>>, IEnumerable { private class HeaderBucket { public object Parsed; private List values; public readonly Func CustomToString; public bool HasStringValues { get { if (values != null) { return values.Count > 0; } return false; } } public List Values { get { return values ?? (values = new List()); } set { values = value; } } public HeaderBucket(object parsed, Func converter) { Parsed = parsed; CustomToString = converter; } public string ParsedToString() { if (Parsed == null) { return null; } if (CustomToString != null) { return CustomToString(Parsed); } return Parsed.ToString(); } } private static readonly Dictionary known_headers; private readonly Dictionary headers; private readonly HttpHeaderKind HeaderKind; internal bool? connectionclose; internal bool? transferEncodingChunked; static HttpHeaders() { HeaderInfo[] obj = new HeaderInfo[48] { HeaderInfo.CreateMulti("Accept", MediaTypeWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("Accept-Charset", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("Accept-Encoding", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("Accept-Language", StringWithQualityHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("Accept-Ranges", CollectionParser.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle("Age", Parser.TimeSpanSeconds.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateMulti("Allow", CollectionParser.TryParse, HttpHeaderKind.Content, 0), HeaderInfo.CreateSingle("Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Cache-Control", CacheControlHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("Connection", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateSingle("Content-Disposition", ContentDispositionHeaderValue.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateMulti("Content-Encoding", CollectionParser.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateMulti("Content-Language", CollectionParser.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Content-Length", Parser.Long.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Content-Location", Parser.Uri.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Content-MD5", Parser.MD5.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Content-Range", ContentRangeHeaderValue.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Content-Type", MediaTypeHeaderValue.TryParse, HttpHeaderKind.Content), HeaderInfo.CreateSingle("Date", Parser.DateTime.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response, Parser.DateTime.ToString), HeaderInfo.CreateSingle("ETag", EntityTagHeaderValue.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateMulti("Expect", NameValueWithParametersHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Expires", Parser.DateTime.TryParse, HttpHeaderKind.Content, Parser.DateTime.ToString), HeaderInfo.CreateSingle("From", Parser.EmailAddress.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Host", Parser.Host.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("If-Match", EntityTagHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("If-Modified-Since", Parser.DateTime.TryParse, HttpHeaderKind.Request, Parser.DateTime.ToString), HeaderInfo.CreateMulti("If-None-Match", EntityTagHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("If-Range", RangeConditionHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("If-Unmodified-Since", Parser.DateTime.TryParse, HttpHeaderKind.Request, Parser.DateTime.ToString), HeaderInfo.CreateSingle("Last-Modified", Parser.DateTime.TryParse, HttpHeaderKind.Content, Parser.DateTime.ToString), HeaderInfo.CreateSingle("Location", Parser.Uri.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle("Max-Forwards", Parser.Int.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateMulti("Pragma", NameValueHeaderValue.TryParsePragma, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("Proxy-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateSingle("Proxy-Authorization", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Range", RangeHeaderValue.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Referer", Parser.Uri.TryParse, HttpHeaderKind.Request), HeaderInfo.CreateSingle("Retry-After", RetryConditionHeaderValue.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateMulti("Server", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Response, 1, " "), HeaderInfo.CreateMulti("TE", TransferCodingWithQualityHeaderValue.TryParse, HttpHeaderKind.Request, 0), HeaderInfo.CreateMulti("Trailer", CollectionParser.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("Transfer-Encoding", TransferCodingHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("Upgrade", ProductHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("User-Agent", ProductInfoHeaderValue.TryParse, HttpHeaderKind.Request, 1, " "), HeaderInfo.CreateMulti("Vary", CollectionParser.TryParse, HttpHeaderKind.Response), HeaderInfo.CreateMulti("Via", ViaHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("Warning", WarningHeaderValue.TryParse, HttpHeaderKind.Request | HttpHeaderKind.Response), HeaderInfo.CreateMulti("WWW-Authenticate", AuthenticationHeaderValue.TryParse, HttpHeaderKind.Response) }; known_headers = new Dictionary(StringComparer.OrdinalIgnoreCase); HeaderInfo[] array = obj; foreach (HeaderInfo headerInfo in array) { known_headers.Add(headerInfo.Name, headerInfo); } } protected HttpHeaders() { headers = new Dictionary(StringComparer.OrdinalIgnoreCase); } internal HttpHeaders(HttpHeaderKind headerKind) : this() { HeaderKind = headerKind; } public void Add(string name, string value) { Add(name, new string[1] { value }); } public void Add(string name, IEnumerable values) { if (values == null) { throw new ArgumentNullException("values"); } AddInternal(name, values, CheckName(name), ignoreInvalid: false); } internal bool AddValue(string value, HeaderInfo headerInfo, bool ignoreInvalid) { return AddInternal(headerInfo.Name, new string[1] { value }, headerInfo, ignoreInvalid); } private bool AddInternal(string name, IEnumerable values, HeaderInfo headerInfo, bool ignoreInvalid) { headers.TryGetValue(name, out var value); bool result = true; foreach (string value2 in values) { bool flag = value == null; if (headerInfo != null) { if (!headerInfo.TryParse(value2, out var result2)) { if (ignoreInvalid) { result = false; continue; } throw new FormatException("Could not parse value for header '" + name + "'"); } if (headerInfo.AllowsMany) { if (value == null) { value = new HeaderBucket(headerInfo.CreateCollection(this), headerInfo.CustomToString); } headerInfo.AddToCollection(value.Parsed, result2); } else { if (value != null) { throw new FormatException(); } value = new HeaderBucket(result2, headerInfo.CustomToString); } } else { if (value == null) { value = new HeaderBucket(null, null); } value.Values.Add(value2 ?? string.Empty); } if (flag) { headers.Add(name, value); } } return result; } public bool TryAddWithoutValidation(string name, string value) { return TryAddWithoutValidation(name, new string[1] { value }); } public bool TryAddWithoutValidation(string name, IEnumerable values) { if (values == null) { throw new ArgumentNullException("values"); } if (!TryCheckName(name, out var _)) { return false; } AddInternal(name, values, null, ignoreInvalid: true); return true; } private HeaderInfo CheckName(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentException("name"); } Parser.Token.Check(name); if (known_headers.TryGetValue(name, out var value) && (value.HeaderKind & HeaderKind) == 0) { if (HeaderKind != 0 && ((HeaderKind | value.HeaderKind) & HttpHeaderKind.Content) != 0) { throw new InvalidOperationException(name); } return null; } return value; } private bool TryCheckName(string name, out HeaderInfo headerInfo) { if (!Parser.Token.TryCheck(name)) { headerInfo = null; return false; } if (known_headers.TryGetValue(name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0 && HeaderKind != 0 && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0) { return false; } return true; } public void Clear() { connectionclose = null; transferEncodingChunked = null; headers.Clear(); } public bool Contains(string name) { CheckName(name); return headers.ContainsKey(name); } public IEnumerator>> GetEnumerator() { foreach (KeyValuePair header in headers) { HeaderBucket bucket = headers[header.Key]; known_headers.TryGetValue(header.Key, out var value); List allHeaderValues = GetAllHeaderValues(bucket, value); if (allHeaderValues != null) { yield return new KeyValuePair>(header.Key, allHeaderValues); } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerable GetValues(string name) { CheckName(name); if (!TryGetValues(name, out var values)) { throw new InvalidOperationException(); } return values; } public bool Remove(string name) { CheckName(name); return headers.Remove(name); } public bool TryGetValues(string name, out IEnumerable values) { if (!TryCheckName(name, out var headerInfo)) { values = null; return false; } if (!headers.TryGetValue(name, out var value)) { values = null; return false; } values = GetAllHeaderValues(value, headerInfo); return true; } internal static string GetSingleHeaderString(string key, IEnumerable values) { string text = ","; if (known_headers.TryGetValue(key, out var value) && value.AllowsMany) { text = value.Separator; } StringBuilder stringBuilder = new StringBuilder(); bool flag = true; foreach (string value2 in values) { if (!flag) { stringBuilder.Append(text); if (text != " ") { stringBuilder.Append(" "); } } stringBuilder.Append(value2); flag = false; } if (flag) { return null; } return stringBuilder.ToString(); } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); using (IEnumerator>> enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { KeyValuePair> current = enumerator.Current; stringBuilder.Append(current.Key); stringBuilder.Append(": "); stringBuilder.Append(GetSingleHeaderString(current.Key, current.Value)); stringBuilder.Append("\r\n"); } } return stringBuilder.ToString(); } internal void AddOrRemove(string name, string value) { if (string.IsNullOrEmpty(value)) { Remove(name); } else { SetValue(name, value); } } internal void AddOrRemove(string name, T value, Func converter = null) where T : class { if (value == null) { Remove(name); } else { SetValue(name, value, converter); } } internal void AddOrRemove(string name, T? value) where T : struct { AddOrRemove(name, value, null); } internal void AddOrRemove(string name, T? value, Func converter) where T : struct { if (!value.HasValue) { Remove(name); } else { SetValue(name, value, converter); } } private List GetAllHeaderValues(HeaderBucket bucket, HeaderInfo headerInfo) { List list = null; if (headerInfo != null && headerInfo.AllowsMany) { list = headerInfo.ToStringCollection(bucket.Parsed); } else if (bucket.Parsed != null) { string text = bucket.ParsedToString(); if (!string.IsNullOrEmpty(text)) { list = new List(); list.Add(text); } } if (bucket.HasStringValues) { if (list == null) { list = new List(); } list.AddRange(bucket.Values); } return list; } internal static HttpHeaderKind GetKnownHeaderKind(string name) { if (string.IsNullOrEmpty(name)) { throw new ArgumentException("name"); } if (known_headers.TryGetValue(name, out var value)) { return value.HeaderKind; } return HttpHeaderKind.None; } internal T GetValue(string name) { if (!headers.TryGetValue(name, out var value)) { return default(T); } if (value.HasStringValues) { if (!known_headers[name].TryParse(value.Values[0], out var result)) { if (!(typeof(T) == typeof(string))) { return default(T); } return (T)(object)value.Values[0]; } value.Parsed = result; value.Values = null; } return (T)value.Parsed; } internal HttpHeaderValueCollection GetValues(string name) where T : class { if (!headers.TryGetValue(name, out var value)) { HeaderInfo headerInfo = known_headers[name]; value = new HeaderBucket(new HttpHeaderValueCollection(this, headerInfo), headerInfo.CustomToString); headers.Add(name, value); } HttpHeaderValueCollection httpHeaderValueCollection = (HttpHeaderValueCollection)value.Parsed; if (value.HasStringValues) { HeaderInfo headerInfo2 = known_headers[name]; if (httpHeaderValueCollection == null) { httpHeaderValueCollection = (HttpHeaderValueCollection)(value.Parsed = new HttpHeaderValueCollection(this, headerInfo2)); } for (int i = 0; i < value.Values.Count; i++) { string text = value.Values[i]; if (!headerInfo2.TryParse(text, out var result)) { httpHeaderValueCollection.AddInvalidValue(text); } else { headerInfo2.AddToCollection(httpHeaderValueCollection, result); } } value.Values.Clear(); } return httpHeaderValueCollection; } internal void SetValue(string name, T value, Func toStringConverter = null) { headers[name] = new HeaderBucket(value, toStringConverter); } } public sealed class HttpRequestHeaders : HttpHeaders { private bool? expectContinue; public HttpHeaderValueCollection Accept => GetValues("Accept"); public HttpHeaderValueCollection AcceptCharset => GetValues("Accept-Charset"); public HttpHeaderValueCollection AcceptEncoding => GetValues("Accept-Encoding"); public HttpHeaderValueCollection AcceptLanguage => GetValues("Accept-Language"); public AuthenticationHeaderValue Authorization { get { return GetValue("Authorization"); } set { AddOrRemove("Authorization", value); } } public CacheControlHeaderValue CacheControl { get { return GetValue("Cache-Control"); } set { AddOrRemove("Cache-Control", value); } } public HttpHeaderValueCollection Connection => GetValues("Connection"); public bool? ConnectionClose { get { if (connectionclose == true || Connection.Find((string l) => string.Equals(l, "close", StringComparison.OrdinalIgnoreCase)) != null) { return true; } return connectionclose; } set { if (connectionclose != value) { Connection.Remove("close"); if (value == true) { Connection.Add("close"); } connectionclose = value; } } } internal bool ConnectionKeepAlive => Connection.Find((string l) => string.Equals(l, "Keep-Alive", StringComparison.OrdinalIgnoreCase)) != null; public DateTimeOffset? Date { get { return GetValue("Date"); } set { AddOrRemove("Date", value, Parser.DateTime.ToString); } } public HttpHeaderValueCollection Expect => GetValues("Expect"); public bool? ExpectContinue { get { if (expectContinue.HasValue) { return expectContinue; } if (TransferEncoding.Find((TransferCodingHeaderValue l) => string.Equals(l.Value, "100-continue", StringComparison.OrdinalIgnoreCase)) == null) { return null; } return true; } set { if (expectContinue != value) { Expect.Remove((NameValueWithParametersHeaderValue l) => l.Name == "100-continue"); if (value == true) { Expect.Add(new NameValueWithParametersHeaderValue("100-continue")); } expectContinue = value; } } } public string From { get { return GetValue("From"); } set { if (!string.IsNullOrEmpty(value) && !Parser.EmailAddress.TryParse(value, out value)) { throw new FormatException(); } AddOrRemove("From", value); } } public string Host { get { return GetValue("Host"); } set { AddOrRemove("Host", value); } } public HttpHeaderValueCollection IfMatch => GetValues("If-Match"); public DateTimeOffset? IfModifiedSince { get { return GetValue("If-Modified-Since"); } set { AddOrRemove("If-Modified-Since", value, Parser.DateTime.ToString); } } public HttpHeaderValueCollection IfNoneMatch => GetValues("If-None-Match"); public RangeConditionHeaderValue IfRange { get { return GetValue("If-Range"); } set { AddOrRemove("If-Range", value); } } public DateTimeOffset? IfUnmodifiedSince { get { return GetValue("If-Unmodified-Since"); } set { AddOrRemove("If-Unmodified-Since", value, Parser.DateTime.ToString); } } public int? MaxForwards { get { return GetValue("Max-Forwards"); } set { AddOrRemove("Max-Forwards", value); } } public HttpHeaderValueCollection Pragma => GetValues("Pragma"); public AuthenticationHeaderValue ProxyAuthorization { get { return GetValue("Proxy-Authorization"); } set { AddOrRemove("Proxy-Authorization", value); } } public RangeHeaderValue Range { get { return GetValue("Range"); } set { AddOrRemove("Range", value); } } public Uri Referrer { get { return GetValue("Referer"); } set { AddOrRemove("Referer", value); } } public HttpHeaderValueCollection TE => GetValues("TE"); public HttpHeaderValueCollection Trailer => GetValues("Trailer"); public HttpHeaderValueCollection TransferEncoding => GetValues("Transfer-Encoding"); public bool? TransferEncodingChunked { get { if (transferEncodingChunked.HasValue) { return transferEncodingChunked; } if (TransferEncoding.Find((TransferCodingHeaderValue l) => string.Equals(l.Value, "chunked", StringComparison.OrdinalIgnoreCase)) == null) { return null; } return true; } set { if (value != transferEncodingChunked) { TransferEncoding.Remove((TransferCodingHeaderValue l) => l.Value == "chunked"); if (value == true) { TransferEncoding.Add(new TransferCodingHeaderValue("chunked")); } transferEncodingChunked = value; } } } public HttpHeaderValueCollection Upgrade => GetValues("Upgrade"); public HttpHeaderValueCollection UserAgent => GetValues("User-Agent"); public HttpHeaderValueCollection Via => GetValues("Via"); public HttpHeaderValueCollection Warning => GetValues("Warning"); internal HttpRequestHeaders() : base(HttpHeaderKind.Request) { } internal void AddHeaders(HttpRequestHeaders headers) { foreach (KeyValuePair> header in headers) { TryAddWithoutValidation(header.Key, header.Value); } } } public sealed class HttpResponseHeaders : HttpHeaders { public HttpHeaderValueCollection AcceptRanges => GetValues("Accept-Ranges"); public TimeSpan? Age { get { return GetValue("Age"); } set { AddOrRemove("Age", value, (object l) => ((long)((TimeSpan)l).TotalSeconds).ToString()); } } public CacheControlHeaderValue CacheControl { get { return GetValue("Cache-Control"); } set { AddOrRemove("Cache-Control", value); } } public HttpHeaderValueCollection Connection => GetValues("Connection"); public bool? ConnectionClose { get { if (connectionclose == true || Connection.Find((string l) => string.Equals(l, "close", StringComparison.OrdinalIgnoreCase)) != null) { return true; } return connectionclose; } set { if (connectionclose != value) { Connection.Remove("close"); if (value == true) { Connection.Add("close"); } connectionclose = value; } } } public DateTimeOffset? Date { get { return GetValue("Date"); } set { AddOrRemove("Date", value, Parser.DateTime.ToString); } } public EntityTagHeaderValue ETag { get { return GetValue("ETag"); } set { AddOrRemove("ETag", value); } } public Uri Location { get { return GetValue("Location"); } set { AddOrRemove("Location", value); } } public HttpHeaderValueCollection Pragma => GetValues("Pragma"); public HttpHeaderValueCollection ProxyAuthenticate => GetValues("Proxy-Authenticate"); public RetryConditionHeaderValue RetryAfter { get { return GetValue("Retry-After"); } set { AddOrRemove("Retry-After", value); } } public HttpHeaderValueCollection Server => GetValues("Server"); public HttpHeaderValueCollection Trailer => GetValues("Trailer"); public HttpHeaderValueCollection TransferEncoding => GetValues("Transfer-Encoding"); public bool? TransferEncodingChunked { get { if (transferEncodingChunked.HasValue) { return transferEncodingChunked; } if (TransferEncoding.Find((TransferCodingHeaderValue l) => StringComparer.OrdinalIgnoreCase.Equals(l.Value, "chunked")) == null) { return null; } return true; } set { if (value != transferEncodingChunked) { TransferEncoding.Remove((TransferCodingHeaderValue l) => l.Value == "chunked"); if (value == true) { TransferEncoding.Add(new TransferCodingHeaderValue("chunked")); } transferEncodingChunked = value; } } } public HttpHeaderValueCollection Upgrade => GetValues("Upgrade"); public HttpHeaderValueCollection Vary => GetValues("Vary"); public HttpHeaderValueCollection Via => GetValues("Via"); public HttpHeaderValueCollection Warning => GetValues("Warning"); public HttpHeaderValueCollection WwwAuthenticate => GetValues("WWW-Authenticate"); internal HttpResponseHeaders() : base(HttpHeaderKind.Response) { } } internal struct Token { public enum Type { Error, End, Token, QuotedString, SeparatorEqual, SeparatorSemicolon, SeparatorSlash, SeparatorDash, SeparatorComma, OpenParens } public static readonly Token Empty = new Token(Type.Token, 0, 0); private readonly Type type; public int StartPosition { get; private set; } public int EndPosition { get; private set; } public Type Kind => type; public Token(Type type, int startPosition, int endPosition) { this = default(Token); this.type = type; StartPosition = startPosition; EndPosition = endPosition; } public static implicit operator Type(Token token) { return token.type; } public override string ToString() { return type.ToString(); } } internal class Lexer { private static readonly bool[] token_chars = new bool[127] { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, true, true, true, true, false, false, true, true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, true }; private static readonly int last_token_char = token_chars.Length; private static readonly string[] dt_formats = new string[5] { "r", "dddd, dd'-'MMM'-'yy HH:mm:ss 'GMT'", "ddd MMM d HH:mm:ss yyyy", "d MMM yy H:m:s", "ddd, d MMM yyyy H:m:s zzz" }; private readonly string s; private int pos; public int Position { get { return pos; } set { pos = value; } } public Lexer(string stream) { s = stream; } public string GetStringValue(Token token) { return s.Substring(token.StartPosition, token.EndPosition - token.StartPosition); } public string GetStringValue(Token start, Token end) { return s.Substring(start.StartPosition, end.EndPosition - start.StartPosition); } public string GetQuotedStringValue(Token start) { return s.Substring(start.StartPosition + 1, start.EndPosition - start.StartPosition - 2); } public string GetRemainingStringValue(int position) { if (position <= s.Length) { return s.Substring(position); } return null; } public bool IsStarStringValue(Token token) { if (token.EndPosition - token.StartPosition == 1) { return s[token.StartPosition] == '*'; } return false; } public bool TryGetNumericValue(Token token, out int value) { return int.TryParse(GetStringValue(token), NumberStyles.None, CultureInfo.InvariantCulture, out value); } public bool TryGetNumericValue(Token token, out long value) { return long.TryParse(GetStringValue(token), NumberStyles.None, CultureInfo.InvariantCulture, out value); } public TimeSpan? TryGetTimeSpanValue(Token token) { if (TryGetNumericValue(token, out int value)) { return TimeSpan.FromSeconds(value); } return null; } public bool TryGetDateValue(Token token, out DateTimeOffset value) { return TryGetDateValue(((Token.Type)token == Token.Type.QuotedString) ? s.Substring(token.StartPosition + 1, token.EndPosition - token.StartPosition - 2) : GetStringValue(token), out value); } public static bool TryGetDateValue(string text, out DateTimeOffset value) { return DateTimeOffset.TryParseExact(text, dt_formats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeUniversal, out value); } public bool TryGetDoubleValue(Token token, out double value) { return double.TryParse(GetStringValue(token), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out value); } public static bool IsValidToken(string input) { int i; for (i = 0; i < input.Length; i++) { if (!IsValidCharacter(input[i])) { return false; } } return i > 0; } public static bool IsValidCharacter(char input) { if (input < last_token_char) { return token_chars[(uint)input]; } return false; } public void EatChar() { pos++; } public int PeekChar() { if (pos >= s.Length) { return -1; } return s[pos]; } public bool ScanCommentOptional(out string value) { if (ScanCommentOptional(out value, out var readToken)) { return true; } return (Token.Type)readToken == Token.Type.End; } public bool ScanCommentOptional(out string value, out Token readToken) { readToken = Scan(); if ((Token.Type)readToken != Token.Type.OpenParens) { value = null; return false; } int num = 1; while (pos < s.Length) { switch (s[pos]) { case '(': num++; pos++; continue; case ')': { pos++; if (--num > 0) { continue; } int startPosition = readToken.StartPosition; value = s.Substring(startPosition, pos - startPosition); return true; } case ' ': case '!': case '"': case '#': case '$': case '%': case '&': case '\'': case '*': case '+': case ',': case '-': case '.': case '/': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ':': case ';': case '<': case '=': case '>': case '?': case '@': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '[': case '\\': case ']': case '^': case '_': case '`': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}': case '~': pos++; continue; } break; } value = null; return false; } public Token Scan(bool recognizeDash = false) { int startPosition = pos; if (s == null) { return new Token(Token.Type.Error, 0, 0); } Token.Type type; if (pos >= s.Length) { type = Token.Type.End; } else { type = Token.Type.Error; while (true) { char c = s[pos++]; switch (c) { case '\t': case ' ': goto IL_00a7; case '=': type = Token.Type.SeparatorEqual; break; case ';': type = Token.Type.SeparatorSemicolon; break; case '/': type = Token.Type.SeparatorSlash; break; case '-': if (recognizeDash) { type = Token.Type.SeparatorDash; break; } goto default; case ',': type = Token.Type.SeparatorComma; break; case '"': startPosition = pos - 1; while (pos < s.Length) { switch (s[pos++]) { case '\\': if (pos + 1 < s.Length) { pos++; continue; } break; case '"': type = Token.Type.QuotedString; break; default: continue; } break; } break; case '(': startPosition = pos - 1; type = Token.Type.OpenParens; break; default: if (c >= last_token_char || !token_chars[(uint)c]) { break; } startPosition = pos - 1; type = Token.Type.Token; while (pos < s.Length) { c = s[pos]; if (c >= last_token_char || !token_chars[(uint)c]) { break; } pos++; } break; } break; IL_00a7: if (pos == s.Length) { type = Token.Type.End; break; } } } return new Token(type, startPosition, pos); } } public class MediaTypeHeaderValue : ICloneable { internal List parameters; internal string media_type; public string CharSet { get { if (parameters == null) { return null; } return parameters.Find((NameValueHeaderValue l) => string.Equals(l.Name, "charset", StringComparison.OrdinalIgnoreCase))?.Value; } set { if (parameters == null) { parameters = new List(); } parameters.SetValue("charset", value); } } public string MediaType { get { return media_type; } set { if (value == null) { throw new ArgumentNullException("MediaType"); } string media; Token? token = TryParseMediaType(new Lexer(value), out media); if (!token.HasValue || token.Value.Kind != Token.Type.End) { throw new FormatException(); } media_type = media; } } public ICollection Parameters => parameters ?? (parameters = new List()); public MediaTypeHeaderValue(string mediaType) { MediaType = mediaType; } protected MediaTypeHeaderValue(MediaTypeHeaderValue source) { if (source == null) { throw new ArgumentNullException("source"); } media_type = source.media_type; if (source.parameters == null) { return; } foreach (NameValueHeaderValue parameter in source.parameters) { Parameters.Add(new NameValueHeaderValue(parameter)); } } internal MediaTypeHeaderValue() { } object ICloneable.Clone() { return new MediaTypeHeaderValue(this); } public override bool Equals(object obj) { if (!(obj is MediaTypeHeaderValue mediaTypeHeaderValue)) { return false; } if (string.Equals(mediaTypeHeaderValue.media_type, media_type, StringComparison.OrdinalIgnoreCase)) { return mediaTypeHeaderValue.parameters.SequenceEqual(parameters); } return false; } public override int GetHashCode() { return media_type.ToLowerInvariant().GetHashCode() ^ HashCodeCalculator.Calculate(parameters); } public static MediaTypeHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public override string ToString() { if (parameters == null) { return media_type; } return media_type + CollectionExtensions.ToString(parameters); } public static bool TryParse(string input, out MediaTypeHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); List result = null; string media; Token? token = TryParseMediaType(lexer, out media); if (!token.HasValue) { return false; } switch (token.Value.Kind) { case Token.Type.SeparatorSemicolon: { if (!NameValueHeaderValue.TryParseParameters(lexer, out result, out var t) || (Token.Type)t != Token.Type.End) { return false; } break; } default: return false; case Token.Type.End: break; } parsedValue = new MediaTypeHeaderValue { media_type = media, parameters = result }; return true; } internal static Token? TryParseMediaType(Lexer lexer, out string media) { media = null; Token token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return null; } if ((Token.Type)lexer.Scan() != Token.Type.SeparatorSlash) { return null; } Token token2 = lexer.Scan(); if ((Token.Type)token2 != Token.Type.Token) { return null; } media = lexer.GetStringValue(token) + "/" + lexer.GetStringValue(token2); return lexer.Scan(); } } public sealed class MediaTypeWithQualityHeaderValue : MediaTypeHeaderValue { public double? Quality { get { return QualityValue.GetValue(parameters); } set { QualityValue.SetValue(ref parameters, value); } } public MediaTypeWithQualityHeaderValue(string mediaType) : base(mediaType) { } public MediaTypeWithQualityHeaderValue(string mediaType, double quality) : this(mediaType) { Quality = quality; } private MediaTypeWithQualityHeaderValue() { } public new static MediaTypeWithQualityHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(); } public static bool TryParse(string input, out MediaTypeWithQualityHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } private static bool TryParseElement(Lexer lexer, out MediaTypeWithQualityHeaderValue parsedValue, out Token t) { parsedValue = null; List result = null; string media; Token? token = MediaTypeHeaderValue.TryParseMediaType(lexer, out media); if (!token.HasValue) { t = Token.Empty; return false; } t = token.Value; if ((Token.Type)t == Token.Type.SeparatorSemicolon && !NameValueHeaderValue.TryParseParameters(lexer, out result, out t)) { return false; } parsedValue = new MediaTypeWithQualityHeaderValue(); parsedValue.media_type = media; parsedValue.parameters = result; return true; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } } public class NameValueHeaderValue : ICloneable { internal string value; public string Name { get; internal set; } public string Value { get { return value; } set { if (!string.IsNullOrEmpty(value)) { Lexer lexer = new Lexer(value); Token token = lexer.Scan(); if ((Token.Type)lexer.Scan() != Token.Type.End || ((Token.Type)token != Token.Type.Token && (Token.Type)token != Token.Type.QuotedString)) { throw new FormatException(); } value = lexer.GetStringValue(token); } this.value = value; } } public NameValueHeaderValue(string name) : this(name, null) { } public NameValueHeaderValue(string name, string value) { Parser.Token.Check(name); Name = name; Value = value; } protected internal NameValueHeaderValue(NameValueHeaderValue source) { Name = source.Name; value = source.value; } internal NameValueHeaderValue() { } internal static NameValueHeaderValue Create(string name, string value) { return new NameValueHeaderValue { Name = name, value = value }; } object ICloneable.Clone() { return new NameValueHeaderValue(this); } public override int GetHashCode() { int num = Name.ToLowerInvariant().GetHashCode(); if (!string.IsNullOrEmpty(value)) { num ^= value.ToLowerInvariant().GetHashCode(); } return num; } public override bool Equals(object obj) { if (!(obj is NameValueHeaderValue nameValueHeaderValue) || !string.Equals(nameValueHeaderValue.Name, Name, StringComparison.OrdinalIgnoreCase)) { return false; } if (string.IsNullOrEmpty(value)) { return string.IsNullOrEmpty(nameValueHeaderValue.value); } return string.Equals(nameValueHeaderValue.value, value, StringComparison.OrdinalIgnoreCase); } public static NameValueHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } internal static bool TryParsePragma(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } internal static bool TryParseParameters(Lexer lexer, out List result, out Token t) { List list = new List(); result = null; do { Token token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { t = Token.Empty; return false; } string text = null; t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorEqual) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token && (Token.Type)t != Token.Type.QuotedString) { return false; } text = lexer.GetStringValue(t); t = lexer.Scan(); } list.Add(new NameValueHeaderValue { Name = lexer.GetStringValue(token), value = text }); } while ((Token.Type)t == Token.Type.SeparatorSemicolon); result = list; return true; } public override string ToString() { if (string.IsNullOrEmpty(value)) { return Name; } return Name + "=" + value; } public static bool TryParse(string input, out NameValueHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } private static bool TryParseElement(Lexer lexer, out NameValueHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } parsedValue = new NameValueHeaderValue { Name = lexer.GetStringValue(t) }; t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorEqual) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token && (Token.Type)t != Token.Type.QuotedString) { return false; } parsedValue.value = lexer.GetStringValue(t); t = lexer.Scan(); } return true; } } public class NameValueWithParametersHeaderValue : NameValueHeaderValue, ICloneable { private List parameters; public ICollection Parameters => parameters ?? (parameters = new List()); public NameValueWithParametersHeaderValue(string name) : base(name) { } public NameValueWithParametersHeaderValue(string name, string value) : base(name, value) { } protected NameValueWithParametersHeaderValue(NameValueWithParametersHeaderValue source) : base(source) { if (source.parameters == null) { return; } foreach (NameValueHeaderValue parameter in source.parameters) { Parameters.Add(parameter); } } private NameValueWithParametersHeaderValue() { } object ICloneable.Clone() { return new NameValueWithParametersHeaderValue(this); } public override bool Equals(object obj) { if (!(obj is NameValueWithParametersHeaderValue nameValueWithParametersHeaderValue)) { return false; } if (base.Equals(obj)) { return nameValueWithParametersHeaderValue.parameters.SequenceEqual(parameters); } return false; } public override int GetHashCode() { return base.GetHashCode() ^ HashCodeCalculator.Calculate(parameters); } public new static NameValueWithParametersHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public override string ToString() { if (parameters == null || parameters.Count == 0) { return base.ToString(); } return base.ToString() + CollectionExtensions.ToString(parameters); } public static bool TryParse(string input, out NameValueWithParametersHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out NameValueWithParametersHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } parsedValue = new NameValueWithParametersHeaderValue { Name = lexer.GetStringValue(t) }; t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorEqual) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token && (Token.Type)t != Token.Type.QuotedString) { return false; } parsedValue.value = lexer.GetStringValue(t); t = lexer.Scan(); } if ((Token.Type)t == Token.Type.SeparatorSemicolon) { if (!NameValueHeaderValue.TryParseParameters(lexer, out var result, out t)) { return false; } parsedValue.parameters = result; } return true; } } internal static class Parser { public static class Token { public static bool TryParse(string input, out string result) { if (input != null && Lexer.IsValidToken(input)) { result = input; return true; } result = null; return false; } public static void Check(string s) { if (s == null) { throw new ArgumentNullException(); } if (!Lexer.IsValidToken(s)) { if (s.Length == 0) { throw new ArgumentException(); } throw new FormatException(s); } } public static bool TryCheck(string s) { if (s == null) { return false; } return Lexer.IsValidToken(s); } public static void CheckQuotedString(string s) { if (s == null) { throw new ArgumentNullException(); } Lexer lexer = new Lexer(s); if ((System.Net.Http.Headers.Token.Type)lexer.Scan() == System.Net.Http.Headers.Token.Type.QuotedString && (System.Net.Http.Headers.Token.Type)lexer.Scan() == System.Net.Http.Headers.Token.Type.End) { return; } if (s.Length == 0) { throw new ArgumentException(); } throw new FormatException(s); } public static void CheckComment(string s) { if (s == null) { throw new ArgumentNullException(); } if (!new Lexer(s).ScanCommentOptional(out var _)) { if (s.Length == 0) { throw new ArgumentException(); } throw new FormatException(s); } } } public static class DateTime { public new static readonly Func ToString = (object l) => ((DateTimeOffset)l).ToString("r", CultureInfo.InvariantCulture); public static bool TryParse(string input, out DateTimeOffset result) { return Lexer.TryGetDateValue(input, out result); } } public static class EmailAddress { public static bool TryParse(string input, out string result) { try { new MailAddress(input); result = input; return true; } catch { result = null; return false; } } } public static class Host { public static bool TryParse(string input, out string result) { result = input; System.Uri result2; return System.Uri.TryCreate("http://u@" + input + "/", UriKind.Absolute, out result2); } } public static class Int { public static bool TryParse(string input, out int result) { return int.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out result); } } public static class Long { public static bool TryParse(string input, out long result) { return long.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out result); } } public static class MD5 { public new static readonly Func ToString = (object l) => Convert.ToBase64String((byte[])l); public static bool TryParse(string input, out byte[] result) { try { result = Convert.FromBase64String(input); return true; } catch { result = null; return false; } } } public static class TimeSpanSeconds { public static bool TryParse(string input, out TimeSpan result) { if (Int.TryParse(input, out var result2)) { result = TimeSpan.FromSeconds(result2); return true; } result = TimeSpan.Zero; return false; } } public static class Uri { public static bool TryParse(string input, out System.Uri result) { return System.Uri.TryCreate(input, UriKind.RelativeOrAbsolute, out result); } public static void Check(string s) { if (s == null) { throw new ArgumentNullException(); } if (!TryParse(s, out var _)) { if (s.Length == 0) { throw new ArgumentException(); } throw new FormatException(s); } } } } public class ProductHeaderValue : ICloneable { public string Name { get; internal set; } public string Version { get; internal set; } public ProductHeaderValue(string name) { Parser.Token.Check(name); Name = name; } public ProductHeaderValue(string name, string version) : this(name) { if (!string.IsNullOrEmpty(version)) { Parser.Token.Check(version); } Version = version; } internal ProductHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is ProductHeaderValue productHeaderValue)) { return false; } if (string.Equals(productHeaderValue.Name, Name, StringComparison.OrdinalIgnoreCase)) { return string.Equals(productHeaderValue.Version, Version, StringComparison.OrdinalIgnoreCase); } return false; } public override int GetHashCode() { int num = Name.ToLowerInvariant().GetHashCode(); if (Version != null) { num ^= Version.ToLowerInvariant().GetHashCode(); } return num; } public static ProductHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out ProductHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out ProductHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } parsedValue = new ProductHeaderValue(); parsedValue.Name = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorSlash) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } parsedValue.Version = lexer.GetStringValue(t); t = lexer.Scan(); } return true; } public override string ToString() { if (Version != null) { return Name + "/" + Version; } return Name; } } public class ProductInfoHeaderValue : ICloneable { public string Comment { get; private set; } public ProductHeaderValue Product { get; private set; } public ProductInfoHeaderValue(ProductHeaderValue product) { if (product == null) { throw new ArgumentNullException(); } Product = product; } public ProductInfoHeaderValue(string comment) { Parser.Token.CheckComment(comment); Comment = comment; } public ProductInfoHeaderValue(string productName, string productVersion) { Product = new ProductHeaderValue(productName, productVersion); } private ProductInfoHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is ProductInfoHeaderValue productInfoHeaderValue)) { return false; } if (Product == null) { return productInfoHeaderValue.Comment == Comment; } return Product.Equals(productInfoHeaderValue.Product); } public override int GetHashCode() { if (Product == null) { return Comment.GetHashCode(); } return Product.GetHashCode(); } public static ProductInfoHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out ProductInfoHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); if (!TryParseElement(lexer, out parsedValue) || parsedValue == null) { return false; } if ((Token.Type)lexer.Scan() != Token.Type.End) { parsedValue = null; return false; } return true; } internal static bool TryParse(string input, int minimalCount, out List result) { List list = new List(); Lexer lexer = new Lexer(input); result = null; while (true) { if (!TryParseElement(lexer, out var parsedValue)) { return false; } if (parsedValue == null) { if (list != null && minimalCount <= list.Count) { result = list; return true; } return false; } list.Add(parsedValue); switch (lexer.PeekChar()) { case 9: case 32: goto IL_004e; case -1: if (minimalCount <= list.Count) { result = list; return true; } break; } break; IL_004e: lexer.EatChar(); } return false; } private static bool TryParseElement(Lexer lexer, out ProductInfoHeaderValue parsedValue) { parsedValue = null; if (lexer.ScanCommentOptional(out var value, out var readToken)) { if (value == null) { return false; } parsedValue = new ProductInfoHeaderValue(); parsedValue.Comment = value; return true; } if ((Token.Type)readToken == Token.Type.End) { return true; } if ((Token.Type)readToken != Token.Type.Token) { return false; } ProductHeaderValue productHeaderValue = new ProductHeaderValue(); productHeaderValue.Name = lexer.GetStringValue(readToken); int position = lexer.Position; readToken = lexer.Scan(); if ((Token.Type)readToken == Token.Type.SeparatorSlash) { readToken = lexer.Scan(); if ((Token.Type)readToken != Token.Type.Token) { return false; } productHeaderValue.Version = lexer.GetStringValue(readToken); } else { lexer.Position = position; } parsedValue = new ProductInfoHeaderValue(productHeaderValue); return true; } public override string ToString() { if (Product == null) { return Comment; } return Product.ToString(); } } internal static class QualityValue { public static double? GetValue(List parameters) { if (parameters == null) { return null; } NameValueHeaderValue nameValueHeaderValue = parameters.Find((NameValueHeaderValue l) => string.Equals(l.Name, "q", StringComparison.OrdinalIgnoreCase)); if (nameValueHeaderValue == null) { return null; } if (!double.TryParse(nameValueHeaderValue.Value, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out var result)) { return null; } return result; } public static void SetValue(ref List parameters, double? value) { if (value < 0.0 || value > 1.0) { throw new ArgumentOutOfRangeException("Quality"); } if (parameters == null) { parameters = new List(); } parameters.SetValue("q", (!value.HasValue) ? null : value.Value.ToString(NumberFormatInfo.InvariantInfo)); } } public class RangeConditionHeaderValue : ICloneable { public DateTimeOffset? Date { get; private set; } public EntityTagHeaderValue EntityTag { get; private set; } public RangeConditionHeaderValue(DateTimeOffset date) { Date = date; } public RangeConditionHeaderValue(EntityTagHeaderValue entityTag) { if (entityTag == null) { throw new ArgumentNullException("entityTag"); } EntityTag = entityTag; } public RangeConditionHeaderValue(string entityTag) : this(new EntityTagHeaderValue(entityTag)) { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is RangeConditionHeaderValue rangeConditionHeaderValue)) { return false; } if (EntityTag == null) { DateTimeOffset? date = Date; DateTimeOffset? date2 = rangeConditionHeaderValue.Date; if (date.HasValue != date2.HasValue) { return false; } if (!date.HasValue) { return true; } return date.GetValueOrDefault() == date2.GetValueOrDefault(); } return EntityTag.Equals(rangeConditionHeaderValue.EntityTag); } public override int GetHashCode() { if (EntityTag == null) { return Date.GetHashCode(); } return EntityTag.GetHashCode(); } public static RangeConditionHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out RangeConditionHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); Token token = lexer.Scan(); bool isWeak; if ((Token.Type)token == Token.Type.Token) { if (lexer.GetStringValue(token) != "W") { if (!Lexer.TryGetDateValue(input, out var value)) { return false; } parsedValue = new RangeConditionHeaderValue(value); return true; } if (lexer.PeekChar() != 47) { return false; } isWeak = true; lexer.EatChar(); token = lexer.Scan(); } else { isWeak = false; } if ((Token.Type)token != Token.Type.QuotedString) { return false; } if ((Token.Type)lexer.Scan() != Token.Type.End) { return false; } parsedValue = new RangeConditionHeaderValue(new EntityTagHeaderValue { Tag = lexer.GetStringValue(token), IsWeak = isWeak }); return true; } public override string ToString() { if (EntityTag != null) { return EntityTag.ToString(); } return Date.Value.ToString("r", CultureInfo.InvariantCulture); } } public class RangeHeaderValue : ICloneable { private List ranges; private string unit; public ICollection Ranges => ranges ?? (ranges = new List()); public string Unit { get { return unit; } set { if (value == null) { throw new ArgumentNullException("Unit"); } Parser.Token.Check(value); unit = value; } } public RangeHeaderValue() { unit = "bytes"; } public RangeHeaderValue(long? from, long? to) : this() { Ranges.Add(new RangeItemHeaderValue(from, to)); } private RangeHeaderValue(RangeHeaderValue source) : this() { if (source.ranges == null) { return; } foreach (RangeItemHeaderValue range in source.ranges) { Ranges.Add(range); } } object ICloneable.Clone() { return new RangeHeaderValue(this); } public override bool Equals(object obj) { if (!(obj is RangeHeaderValue rangeHeaderValue)) { return false; } if (string.Equals(rangeHeaderValue.Unit, Unit, StringComparison.OrdinalIgnoreCase)) { return rangeHeaderValue.ranges.SequenceEqual(ranges); } return false; } public override int GetHashCode() { return Unit.ToLowerInvariant().GetHashCode() ^ HashCodeCalculator.Calculate(ranges); } public static RangeHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out RangeHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); Token token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } RangeHeaderValue rangeHeaderValue = new RangeHeaderValue(); rangeHeaderValue.unit = lexer.GetStringValue(token); token = lexer.Scan(); if ((Token.Type)token != Token.Type.SeparatorEqual) { return false; } do { long? num = null; long? num2 = null; bool flag = false; token = lexer.Scan(recognizeDash: true); long result; switch (token.Kind) { case Token.Type.SeparatorDash: token = lexer.Scan(); if (!lexer.TryGetNumericValue(token, out result)) { return false; } num2 = result; break; case Token.Type.Token: { string stringValue = lexer.GetStringValue(token); string[] array = stringValue.Split(new char[1] { '-' }, StringSplitOptions.RemoveEmptyEntries); if (!Parser.Long.TryParse(array[0], out result)) { return false; } switch (array.Length) { case 1: token = lexer.Scan(recognizeDash: true); num = result; switch (token.Kind) { case Token.Type.SeparatorDash: token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { flag = true; break; } if (!lexer.TryGetNumericValue(token, out result)) { return false; } num2 = result; if (!(num2 < num)) { break; } return false; case Token.Type.End: if (stringValue.Length > 0 && stringValue[stringValue.Length - 1] != '-') { return false; } flag = true; break; case Token.Type.SeparatorComma: flag = true; break; default: return false; } break; case 2: num = result; if (!Parser.Long.TryParse(array[1], out result)) { return false; } num2 = result; if (num2 < num) { return false; } break; default: return false; } break; } default: return false; } rangeHeaderValue.Ranges.Add(new RangeItemHeaderValue(num, num2)); if (!flag) { token = lexer.Scan(); } } while ((Token.Type)token == Token.Type.SeparatorComma); if ((Token.Type)token != Token.Type.End) { return false; } parsedValue = rangeHeaderValue; return true; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(unit); stringBuilder.Append("="); for (int i = 0; i < Ranges.Count; i++) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(ranges[i]); } return stringBuilder.ToString(); } } public class RangeItemHeaderValue : ICloneable { public long? From { get; private set; } public long? To { get; private set; } public RangeItemHeaderValue(long? from, long? to) { if (!from.HasValue && !to.HasValue) { throw new ArgumentException(); } if (from.HasValue && to.HasValue && from > to) { throw new ArgumentOutOfRangeException("from"); } if (from < 0) { throw new ArgumentOutOfRangeException("from"); } if (to < 0) { throw new ArgumentOutOfRangeException("to"); } From = from; To = to; } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (obj is RangeItemHeaderValue rangeItemHeaderValue && rangeItemHeaderValue.From == From) { return rangeItemHeaderValue.To == To; } return false; } public override int GetHashCode() { return From.GetHashCode() ^ To.GetHashCode(); } public override string ToString() { if (!From.HasValue) { return "-" + To.Value; } if (!To.HasValue) { return From.Value + "-"; } return From.Value + "-" + To.Value; } } public class RetryConditionHeaderValue : ICloneable { public DateTimeOffset? Date { get; private set; } public TimeSpan? Delta { get; private set; } public RetryConditionHeaderValue(DateTimeOffset date) { Date = date; } public RetryConditionHeaderValue(TimeSpan delta) { if (delta.TotalSeconds > 4294967295.0) { throw new ArgumentOutOfRangeException("delta"); } Delta = delta; } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (obj is RetryConditionHeaderValue retryConditionHeaderValue && retryConditionHeaderValue.Date == Date) { TimeSpan? delta = retryConditionHeaderValue.Delta; TimeSpan? delta2 = Delta; if (delta.HasValue != delta2.HasValue) { return false; } if (!delta.HasValue) { return true; } return delta.GetValueOrDefault() == delta2.GetValueOrDefault(); } return false; } public override int GetHashCode() { return Date.GetHashCode() ^ Delta.GetHashCode(); } public static RetryConditionHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out RetryConditionHeaderValue parsedValue) { parsedValue = null; Lexer lexer = new Lexer(input); Token token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } TimeSpan? timeSpan = lexer.TryGetTimeSpanValue(token); if (timeSpan.HasValue) { if ((Token.Type)lexer.Scan() != Token.Type.End) { return false; } parsedValue = new RetryConditionHeaderValue(timeSpan.Value); } else { if (!Lexer.TryGetDateValue(input, out var value)) { return false; } parsedValue = new RetryConditionHeaderValue(value); } return true; } public override string ToString() { if (!Delta.HasValue) { return Date.Value.ToString("r", CultureInfo.InvariantCulture); } return Delta.Value.TotalSeconds.ToString(CultureInfo.InvariantCulture); } } public class StringWithQualityHeaderValue : ICloneable { public double? Quality { get; private set; } public string Value { get; private set; } public StringWithQualityHeaderValue(string value) { Parser.Token.Check(value); Value = value; } public StringWithQualityHeaderValue(string value, double quality) : this(value) { if (quality < 0.0 || quality > 1.0) { throw new ArgumentOutOfRangeException("quality"); } Quality = quality; } private StringWithQualityHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (obj is StringWithQualityHeaderValue stringWithQualityHeaderValue && string.Equals(stringWithQualityHeaderValue.Value, Value, StringComparison.OrdinalIgnoreCase)) { return stringWithQualityHeaderValue.Quality == Quality; } return false; } public override int GetHashCode() { return Value.ToLowerInvariant().GetHashCode() ^ Quality.GetHashCode(); } public static StringWithQualityHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out StringWithQualityHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out StringWithQualityHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } StringWithQualityHeaderValue stringWithQualityHeaderValue = new StringWithQualityHeaderValue(); stringWithQualityHeaderValue.Value = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorSemicolon) { t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } string stringValue = lexer.GetStringValue(t); if (stringValue != "q" && stringValue != "Q") { return false; } t = lexer.Scan(); if ((Token.Type)t != Token.Type.SeparatorEqual) { return false; } t = lexer.Scan(); if (!lexer.TryGetDoubleValue(t, out var value)) { return false; } if (value > 1.0) { return false; } stringWithQualityHeaderValue.Quality = value; t = lexer.Scan(); } parsedValue = stringWithQualityHeaderValue; return true; } public override string ToString() { if (Quality.HasValue) { return Value + "; q=" + Quality.Value.ToString("0.0##", CultureInfo.InvariantCulture); } return Value; } } public class TransferCodingHeaderValue : ICloneable { internal string value; internal List parameters; public ICollection Parameters => parameters ?? (parameters = new List()); public string Value => value; public TransferCodingHeaderValue(string value) { Parser.Token.Check(value); this.value = value; } protected TransferCodingHeaderValue(TransferCodingHeaderValue source) { value = source.value; if (source.parameters == null) { return; } foreach (NameValueHeaderValue parameter in source.parameters) { Parameters.Add(new NameValueHeaderValue(parameter)); } } internal TransferCodingHeaderValue() { } object ICloneable.Clone() { return new TransferCodingHeaderValue(this); } public override bool Equals(object obj) { if (obj is TransferCodingHeaderValue transferCodingHeaderValue && string.Equals(value, transferCodingHeaderValue.value, StringComparison.OrdinalIgnoreCase)) { return parameters.SequenceEqual(transferCodingHeaderValue.parameters); } return false; } public override int GetHashCode() { int num = value.ToLowerInvariant().GetHashCode(); if (parameters != null) { num ^= HashCodeCalculator.Calculate(parameters); } return num; } public static TransferCodingHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public override string ToString() { return value + CollectionExtensions.ToString(parameters); } public static bool TryParse(string input, out TransferCodingHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out TransferCodingHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } TransferCodingHeaderValue transferCodingHeaderValue = new TransferCodingHeaderValue(); transferCodingHeaderValue.value = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters(lexer, out transferCodingHeaderValue.parameters, out t) || (Token.Type)t != Token.Type.End)) { return false; } parsedValue = transferCodingHeaderValue; return true; } } public sealed class TransferCodingWithQualityHeaderValue : TransferCodingHeaderValue { public double? Quality { get { return QualityValue.GetValue(parameters); } set { QualityValue.SetValue(ref parameters, value); } } public TransferCodingWithQualityHeaderValue(string value) : base(value) { } public TransferCodingWithQualityHeaderValue(string value, double quality) : this(value) { Quality = quality; } private TransferCodingWithQualityHeaderValue() { } public new static TransferCodingWithQualityHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(); } public static bool TryParse(string input, out TransferCodingWithQualityHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out TransferCodingWithQualityHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } TransferCodingWithQualityHeaderValue transferCodingWithQualityHeaderValue = new TransferCodingWithQualityHeaderValue(); transferCodingWithQualityHeaderValue.value = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.SeparatorSemicolon && (!NameValueHeaderValue.TryParseParameters(lexer, out transferCodingWithQualityHeaderValue.parameters, out t) || (Token.Type)t != Token.Type.End)) { return false; } parsedValue = transferCodingWithQualityHeaderValue; return true; } } public class ViaHeaderValue : ICloneable { public string Comment { get; private set; } public string ProtocolName { get; private set; } public string ProtocolVersion { get; private set; } public string ReceivedBy { get; private set; } public ViaHeaderValue(string protocolVersion, string receivedBy) { Parser.Token.Check(protocolVersion); Parser.Uri.Check(receivedBy); ProtocolVersion = protocolVersion; ReceivedBy = receivedBy; } public ViaHeaderValue(string protocolVersion, string receivedBy, string protocolName) : this(protocolVersion, receivedBy) { if (!string.IsNullOrEmpty(protocolName)) { Parser.Token.Check(protocolName); ProtocolName = protocolName; } } public ViaHeaderValue(string protocolVersion, string receivedBy, string protocolName, string comment) : this(protocolVersion, receivedBy, protocolName) { if (!string.IsNullOrEmpty(comment)) { Parser.Token.CheckComment(comment); Comment = comment; } } private ViaHeaderValue() { } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is ViaHeaderValue viaHeaderValue)) { return false; } if (string.Equals(viaHeaderValue.Comment, Comment, StringComparison.Ordinal) && string.Equals(viaHeaderValue.ProtocolName, ProtocolName, StringComparison.OrdinalIgnoreCase) && string.Equals(viaHeaderValue.ProtocolVersion, ProtocolVersion, StringComparison.OrdinalIgnoreCase)) { return string.Equals(viaHeaderValue.ReceivedBy, ReceivedBy, StringComparison.OrdinalIgnoreCase); } return false; } public override int GetHashCode() { int hashCode = ProtocolVersion.ToLowerInvariant().GetHashCode(); hashCode ^= ReceivedBy.ToLowerInvariant().GetHashCode(); if (!string.IsNullOrEmpty(ProtocolName)) { hashCode ^= ProtocolName.ToLowerInvariant().GetHashCode(); } if (!string.IsNullOrEmpty(Comment)) { hashCode ^= Comment.GetHashCode(); } return hashCode; } public static ViaHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out ViaHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out ViaHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } Token token = lexer.Scan(); ViaHeaderValue viaHeaderValue = new ViaHeaderValue(); if ((Token.Type)token == Token.Type.SeparatorSlash) { token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } viaHeaderValue.ProtocolName = lexer.GetStringValue(t); viaHeaderValue.ProtocolVersion = lexer.GetStringValue(token); token = lexer.Scan(); } else { viaHeaderValue.ProtocolVersion = lexer.GetStringValue(t); } if ((Token.Type)token != Token.Type.Token) { return false; } if (lexer.PeekChar() == 58) { lexer.EatChar(); t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } } else { t = token; } viaHeaderValue.ReceivedBy = lexer.GetStringValue(token, t); if (lexer.ScanCommentOptional(out var value, out t)) { t = lexer.Scan(); } viaHeaderValue.Comment = value; parsedValue = viaHeaderValue; return true; } public override string ToString() { string text = ((ProtocolName != null) ? (ProtocolName + "/" + ProtocolVersion + " " + ReceivedBy) : (ProtocolVersion + " " + ReceivedBy)); if (Comment == null) { return text; } return text + " " + Comment; } } public class WarningHeaderValue : ICloneable { public string Agent { get; private set; } public int Code { get; private set; } public DateTimeOffset? Date { get; private set; } public string Text { get; private set; } public WarningHeaderValue(int code, string agent, string text) { if (!IsCodeValid(code)) { throw new ArgumentOutOfRangeException("code"); } Parser.Uri.Check(agent); Parser.Token.CheckQuotedString(text); Code = code; Agent = agent; Text = text; } public WarningHeaderValue(int code, string agent, string text, DateTimeOffset date) : this(code, agent, text) { Date = date; } private WarningHeaderValue() { } private static bool IsCodeValid(int code) { if (code >= 0) { return code < 1000; } return false; } object ICloneable.Clone() { return MemberwiseClone(); } public override bool Equals(object obj) { if (!(obj is WarningHeaderValue warningHeaderValue)) { return false; } if (Code == warningHeaderValue.Code && string.Equals(warningHeaderValue.Agent, Agent, StringComparison.OrdinalIgnoreCase) && Text == warningHeaderValue.Text) { DateTimeOffset? date = Date; DateTimeOffset? date2 = warningHeaderValue.Date; if (date.HasValue != date2.HasValue) { return false; } if (!date.HasValue) { return true; } return date.GetValueOrDefault() == date2.GetValueOrDefault(); } return false; } public override int GetHashCode() { return Code.GetHashCode() ^ Agent.ToLowerInvariant().GetHashCode() ^ Text.GetHashCode() ^ Date.GetHashCode(); } public static WarningHeaderValue Parse(string input) { if (TryParse(input, out var parsedValue)) { return parsedValue; } throw new FormatException(input); } public static bool TryParse(string input, out WarningHeaderValue parsedValue) { if (TryParseElement(new Lexer(input), out parsedValue, out var t) && (Token.Type)t == Token.Type.End) { return true; } parsedValue = null; return false; } internal static bool TryParse(string input, int minimalCount, out List result) { return CollectionParser.TryParse(input, minimalCount, (ElementTryParser)TryParseElement, out result); } private static bool TryParseElement(Lexer lexer, out WarningHeaderValue parsedValue, out Token t) { parsedValue = null; t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } if (!lexer.TryGetNumericValue(t, out int value) || !IsCodeValid(value)) { return false; } t = lexer.Scan(); if ((Token.Type)t != Token.Type.Token) { return false; } Token token = t; if (lexer.PeekChar() == 58) { lexer.EatChar(); token = lexer.Scan(); if ((Token.Type)token != Token.Type.Token) { return false; } } WarningHeaderValue warningHeaderValue = new WarningHeaderValue(); warningHeaderValue.Code = value; warningHeaderValue.Agent = lexer.GetStringValue(t, token); t = lexer.Scan(); if ((Token.Type)t != Token.Type.QuotedString) { return false; } warningHeaderValue.Text = lexer.GetStringValue(t); t = lexer.Scan(); if ((Token.Type)t == Token.Type.QuotedString) { if (!lexer.TryGetDateValue(t, out var value2)) { return false; } warningHeaderValue.Date = value2; t = lexer.Scan(); } parsedValue = warningHeaderValue; return true; } public override string ToString() { string text = Code.ToString("000") + " " + Agent + " " + Text; if (Date.HasValue) { text = text + " \"" + Date.Value.ToString("r", CultureInfo.InvariantCulture) + "\""; } return text; } } } namespace Unity { internal sealed class ThrowStub : ObjectDisposedException { public static void ThrowNotSupportedException() { throw new PlatformNotSupportedException(); } } }