﻿// Decompiled with JetBrains decompiler
// Type: System.Net.Cache.Rfc2616
// Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 5ABD58FD-DF31-44FD-A492-63F2B47CC9AF
// Assembly location: C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.dll

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Net;

namespace System.Net.Cache
{
  internal class Rfc2616
  {
    private Rfc2616()
    {
    }

    public static CacheValidationStatus OnValidateRequest(HttpRequestCacheValidator ctx)
    {
      CacheValidationStatus validationStatus = Rfc2616.Common.OnValidateRequest(ctx);
      if (validationStatus == CacheValidationStatus.DoNotUseCache)
        return validationStatus;
      ctx.Request.Headers.RemoveInternal("Pragma");
      ctx.Request.Headers.RemoveInternal("Cache-Control");
      if (ctx.Policy.Level == HttpRequestCacheLevel.NoCacheNoStore)
      {
        ctx.Request.Headers.AddInternal("Cache-Control", "no-store");
        ctx.Request.Headers.AddInternal("Cache-Control", "no-cache");
        ctx.Request.Headers.AddInternal("Pragma", "no-cache");
        validationStatus = CacheValidationStatus.DoNotTakeFromCache;
      }
      else if (validationStatus == CacheValidationStatus.Continue)
      {
        if (ctx.Policy.Level == HttpRequestCacheLevel.Reload || ctx.Policy.Level == HttpRequestCacheLevel.NoCacheNoStore)
        {
          ctx.Request.Headers.AddInternal("Cache-Control", "no-cache");
          ctx.Request.Headers.AddInternal("Pragma", "no-cache");
          validationStatus = CacheValidationStatus.DoNotTakeFromCache;
        }
        else if (ctx.Policy.Level == HttpRequestCacheLevel.Refresh)
        {
          ctx.Request.Headers.AddInternal("Cache-Control", "max-age=0");
          ctx.Request.Headers.AddInternal("Pragma", "no-cache");
          validationStatus = CacheValidationStatus.DoNotTakeFromCache;
        }
        else if (ctx.Policy.Level == HttpRequestCacheLevel.Default)
        {
          if (ctx.Policy.MinFresh > TimeSpan.Zero)
            ctx.Request.Headers.AddInternal("Cache-Control", "min-fresh=" + (object) (int) ctx.Policy.MinFresh.TotalSeconds);
          if (ctx.Policy.MaxAge != TimeSpan.MaxValue)
            ctx.Request.Headers.AddInternal("Cache-Control", "max-age=" + (object) (int) ctx.Policy.MaxAge.TotalSeconds);
          if (ctx.Policy.MaxStale > TimeSpan.Zero)
            ctx.Request.Headers.AddInternal("Cache-Control", "max-stale=" + (object) (int) ctx.Policy.MaxStale.TotalSeconds);
        }
        else if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly || ctx.Policy.Level == HttpRequestCacheLevel.CacheOrNextCacheOnly)
          ctx.Request.Headers.AddInternal("Cache-Control", "only-if-cached");
      }
      return validationStatus;
    }

    public static CacheFreshnessStatus OnValidateFreshness(HttpRequestCacheValidator ctx)
    {
      CacheFreshnessStatus freshness = Rfc2616.Common.ComputeFreshness(ctx);
      if (ctx.Uri.Query.Length != 0)
      {
        if (ctx.CacheHeaders.Expires == null && (ctx.CacheEntry.IsPrivateEntry ? (ctx.CacheCacheControl.MaxAge == -1 ? 1 : 0) : (ctx.CacheCacheControl.SMaxAge == -1 ? 1 : 0)) != 0)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_uri_with_query_has_no_expiration"));
          return CacheFreshnessStatus.Stale;
        }
        if (ctx.CacheHttpVersion.Major <= 1 && ctx.CacheHttpVersion.Minor < 1)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_uri_with_query_and_cached_resp_from_http_10"));
          return CacheFreshnessStatus.Stale;
        }
      }
      return freshness;
    }

    public static CacheValidationStatus OnValidateCache(HttpRequestCacheValidator ctx)
    {
      if (Rfc2616.Common.ValidateCacheByVaryHeader(ctx) == Rfc2616.TriState.Invalid)
        return CacheValidationStatus.DoNotTakeFromCache;
      if (ctx.Policy.Level == HttpRequestCacheLevel.Revalidate)
        return Rfc2616.Common.TryConditionalRequest(ctx);
      if (Rfc2616.Common.ValidateCacheBySpecialCases(ctx) == Rfc2616.TriState.Invalid)
      {
        if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly)
          return CacheValidationStatus.DoNotTakeFromCache;
        return Rfc2616.Common.TryConditionalRequest(ctx);
      }
      if (!Rfc2616.Common.ValidateCacheByClientPolicy(ctx) && ctx.Policy.Level != HttpRequestCacheLevel.CacheOnly && (ctx.Policy.Level != HttpRequestCacheLevel.CacheIfAvailable && ctx.Policy.Level != HttpRequestCacheLevel.CacheOrNextCacheOnly))
        return Rfc2616.Common.TryConditionalRequest(ctx);
      CacheValidationStatus validationStatus = Rfc2616.Common.TryResponseFromCache(ctx);
      if (validationStatus != CacheValidationStatus.ReturnCachedResponse)
      {
        if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly)
          return CacheValidationStatus.DoNotTakeFromCache;
        return validationStatus;
      }
      if (Logging.On)
        Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_valid_as_fresh_or_because_policy", new object[1]
        {
          (object) ctx.Policy.ToString()
        }));
      return CacheValidationStatus.ReturnCachedResponse;
    }

    public static CacheValidationStatus OnValidateResponse(HttpRequestCacheValidator ctx)
    {
      if (ctx.ResponseCount > 1)
      {
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_accept_based_on_retry_count", new object[1]
          {
            (object) ctx.ResponseCount
          }));
        return CacheValidationStatus.Continue;
      }
      if (ctx.RequestRangeUser)
        return CacheValidationStatus.Continue;
      if (ctx.CacheDate != DateTime.MinValue && ctx.ResponseDate != DateTime.MinValue && ctx.CacheDate > ctx.ResponseDate)
      {
        if (Logging.On)
          Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_date_header_older_than_cache_entry"));
        Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
        return CacheValidationStatus.RetryResponseFromServer;
      }
      HttpWebResponse httpWebResponse = ctx.Response as HttpWebResponse;
      if (ctx.RequestRangeCache && httpWebResponse.StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable)
      {
        if (Logging.On)
          Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_server_didnt_satisfy_range", new object[1]
          {
            (object) ctx.Request.Headers["Range"]
          }));
        Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
        return CacheValidationStatus.RetryResponseFromServer;
      }
      if (httpWebResponse.StatusCode == HttpStatusCode.NotModified)
      {
        if (ctx.RequestIfHeader1 == null)
        {
          if (Logging.On)
            Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_304_received_on_unconditional_request"));
          Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
          return CacheValidationStatus.RetryResponseFromServer;
        }
        if (ctx.RequestRangeCache)
        {
          if (Logging.On)
            Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_304_received_on_unconditional_request_expected_200_206"));
          Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
          return CacheValidationStatus.RetryResponseFromServer;
        }
      }
      if (ctx.CacheHttpVersion.Major <= 1 && httpWebResponse.ProtocolVersion.Major <= 1 && (ctx.CacheHttpVersion.Minor < 1 && httpWebResponse.ProtocolVersion.Minor < 1) && ctx.CacheLastModified > ctx.ResponseLastModified)
      {
        if (Logging.On)
          Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_last_modified_header_older_than_cache_entry"));
        Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
        return CacheValidationStatus.RetryResponseFromServer;
      }
      if (ctx.Policy.Level == HttpRequestCacheLevel.Default && ctx.ResponseAge != TimeSpan.MinValue && (ctx.ResponseAge > ctx.Policy.MaxAge || ctx.ResponseExpires != DateTime.MinValue && ctx.Policy.MinFresh > TimeSpan.Zero && ctx.ResponseExpires - DateTime.UtcNow < ctx.Policy.MinFresh || ctx.Policy.MaxStale > TimeSpan.Zero && DateTime.UtcNow - ctx.ResponseExpires > ctx.Policy.MaxStale))
      {
        if (Logging.On)
          Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_freshness_outside_policy_limits"));
        Rfc2616.Common.ConstructUnconditionalRefreshRequest(ctx);
        return CacheValidationStatus.RetryResponseFromServer;
      }
      if (ctx.RequestIfHeader1 != null)
      {
        ctx.Request.Headers.RemoveInternal(ctx.RequestIfHeader1);
        ctx.RequestIfHeader1 = (string) null;
      }
      if (ctx.RequestIfHeader2 != null)
      {
        ctx.Request.Headers.RemoveInternal(ctx.RequestIfHeader2);
        ctx.RequestIfHeader2 = (string) null;
      }
      if (ctx.RequestRangeCache)
      {
        ctx.Request.Headers.RemoveInternal("Range");
        ctx.RequestRangeCache = false;
      }
      return CacheValidationStatus.Continue;
    }

    public static CacheValidationStatus OnUpdateCache(HttpRequestCacheValidator ctx)
    {
      if (ctx.CacheStatusCode == HttpStatusCode.NotModified)
      {
        if (Logging.On)
          Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_need_to_remove_invalid_cache_entry_304"));
        return CacheValidationStatus.RemoveFromCache;
      }
      HttpWebResponse resp = ctx.Response as HttpWebResponse;
      if (Logging.On)
        Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_status", new object[1]
        {
          (object) resp.StatusCode
        }));
      if (ctx.ValidationStatus == CacheValidationStatus.RemoveFromCache)
        return CacheValidationStatus.RemoveFromCache;
      CacheValidationStatus validationStatus1 = ctx.RequestMethod >= HttpMethod.Post && ctx.RequestMethod <= HttpMethod.Delete || ctx.RequestMethod == HttpMethod.Other ? CacheValidationStatus.RemoveFromCache : CacheValidationStatus.DoNotUpdateCache;
      if (Rfc2616.Common.OnUpdateCache(ctx, resp) != Rfc2616.TriState.Valid)
        return validationStatus1;
      CacheValidationStatus validationStatus2 = CacheValidationStatus.CacheResponse;
      ctx.CacheEntry.IsPartialEntry = false;
      if (resp.StatusCode == HttpStatusCode.NotModified || ctx.RequestMethod == HttpMethod.Head)
      {
        validationStatus2 = CacheValidationStatus.UpdateResponseInformation;
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_304_or_request_head"));
        if (ctx.CacheDontUpdateHeaders)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_dont_update_cached_headers"));
          ctx.CacheHeaders = (WebHeaderCollection) null;
          ctx.CacheEntry.ExpiresUtc = ctx.ResponseExpires;
          ctx.CacheEntry.LastModifiedUtc = ctx.ResponseLastModified;
          if (ctx.Policy.Level == HttpRequestCacheLevel.Default)
            ctx.CacheEntry.MaxStale = ctx.Policy.MaxStale;
          else
            ctx.CacheEntry.MaxStale = TimeSpan.MinValue;
          ctx.CacheEntry.LastSynchronizedUtc = DateTime.UtcNow;
        }
        else if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_update_cached_headers"));
      }
      else if (resp.StatusCode == HttpStatusCode.PartialContent)
      {
        if (ctx.CacheEntry.StreamSize != ctx.ResponseRangeStart && ctx.ResponseRangeStart != 0L)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_partial_resp_not_combined_with_existing_entry", (object) ctx.CacheEntry.StreamSize, (object) ctx.ResponseRangeStart));
          return validationStatus1;
        }
        if (!ctx.RequestRangeUser)
          ctx.CacheStreamOffset = 0L;
        Rfc2616.Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
        ctx.CacheHttpVersion = resp.ProtocolVersion;
        ctx.CacheEntityLength = ctx.ResponseEntityLength;
        ctx.CacheStreamLength = ctx.CacheEntry.StreamSize = ctx.ResponseRangeEnd + 1L;
        if (ctx.CacheEntityLength > 0L && ctx.CacheEntityLength == ctx.CacheEntry.StreamSize)
          Rfc2616.Common.Construct200ok(ctx);
        else
          Rfc2616.Common.Construct206PartialContent(ctx, 0);
      }
      else
      {
        Rfc2616.Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
        ctx.CacheHttpVersion = resp.ProtocolVersion;
        ctx.CacheStatusCode = resp.StatusCode;
        ctx.CacheStatusDescription = resp.StatusDescription;
        ctx.CacheEntry.StreamSize = resp.ContentLength;
      }
      return validationStatus2;
    }

    internal enum TriState
    {
      Unknown,
      Valid,
      Invalid,
    }

    internal static class Common
    {
      public const string PartialContentDescription = "Partial Content";
      public const string OkDescription = "OK";

      public static CacheValidationStatus OnValidateRequest(HttpRequestCacheValidator ctx)
      {
        if (ctx.RequestMethod >= HttpMethod.Post && ctx.RequestMethod <= HttpMethod.Delete)
        {
          if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly)
            ctx.FailRequest(WebExceptionStatus.RequestProhibitedByCachePolicy);
          return CacheValidationStatus.DoNotTakeFromCache;
        }
        if (ctx.RequestMethod < HttpMethod.Head || ctx.RequestMethod > HttpMethod.Get)
        {
          if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly)
            ctx.FailRequest(WebExceptionStatus.RequestProhibitedByCachePolicy);
          return CacheValidationStatus.DoNotUseCache;
        }
        if (ctx.Request.Headers["If-Modified-Since"] == null && ctx.Request.Headers["If-None-Match"] == null && (ctx.Request.Headers["If-Range"] == null && ctx.Request.Headers["If-Match"] == null) && ctx.Request.Headers["If-Unmodified-Since"] == null)
          return CacheValidationStatus.Continue;
        if (Logging.On)
          Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_request_contains_conditional_header"));
        if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly)
          ctx.FailRequest(WebExceptionStatus.RequestProhibitedByCachePolicy);
        return CacheValidationStatus.DoNotTakeFromCache;
      }

      public static CacheFreshnessStatus ComputeFreshness(HttpRequestCacheValidator ctx)
      {
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_now_time", new object[1]
          {
            (object) DateTime.UtcNow.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)
          }));
        DateTime utcNow = DateTime.UtcNow;
        TimeSpan timeSpan = TimeSpan.MaxValue;
        DateTime dateTime1 = ctx.CacheDate;
        if (dateTime1 != DateTime.MinValue)
        {
          timeSpan = utcNow - dateTime1;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_age1_date_header", (object) ((int) timeSpan.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo), (object) ctx.CacheDate.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)));
        }
        else if (ctx.CacheEntry.LastSynchronizedUtc != DateTime.MinValue)
        {
          timeSpan = utcNow - ctx.CacheEntry.LastSynchronizedUtc;
          if (ctx.CacheAge != TimeSpan.MinValue)
            timeSpan += ctx.CacheAge;
          if (Logging.On)
          {
            if (ctx.CacheAge != TimeSpan.MinValue)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_age1_last_synchronized_age_header", (object) ((int) timeSpan.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo), (object) ctx.CacheEntry.LastSynchronizedUtc.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture), (object) ((int) ctx.CacheAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)));
            else
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_age1_last_synchronized", (object) ((int) timeSpan.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo), (object) ctx.CacheEntry.LastSynchronizedUtc.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)));
          }
        }
        if (ctx.CacheAge != TimeSpan.MinValue)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_age2", new object[1]
            {
              (object) ((int) ctx.CacheAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
            }));
          if (ctx.CacheAge > timeSpan || timeSpan == TimeSpan.MaxValue)
            timeSpan = ctx.CacheAge;
        }
        ctx.CacheAge = timeSpan < TimeSpan.Zero ? TimeSpan.Zero : timeSpan;
        if (ctx.CacheAge != TimeSpan.MinValue)
        {
          if (!ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.SMaxAge != -1)
          {
            ctx.CacheMaxAge = TimeSpan.FromSeconds((double) ctx.CacheCacheControl.SMaxAge);
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_max_age_cache_s_max_age", new object[1]
              {
                (object) ((int) ctx.CacheMaxAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
              }));
            return ctx.CacheAge < ctx.CacheMaxAge ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
          }
          if (ctx.CacheCacheControl.MaxAge != -1)
          {
            ctx.CacheMaxAge = TimeSpan.FromSeconds((double) ctx.CacheCacheControl.MaxAge);
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_max_age_cache_max_age", new object[1]
              {
                (object) ((int) ctx.CacheMaxAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
              }));
            return ctx.CacheAge < ctx.CacheMaxAge ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
          }
        }
        if (dateTime1 == DateTime.MinValue)
          dateTime1 = ctx.CacheEntry.LastSynchronizedUtc;
        DateTime dateTime2 = ctx.CacheEntry.ExpiresUtc;
        if (ctx.CacheExpires != DateTime.MinValue && ctx.CacheExpires < dateTime2)
          dateTime2 = ctx.CacheExpires;
        if (dateTime2 != DateTime.MinValue && dateTime1 != DateTime.MinValue && ctx.CacheAge != TimeSpan.MinValue)
        {
          ctx.CacheMaxAge = dateTime2 - dateTime1;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_max_age_expires_date", (object) ((int) (dateTime2 - dateTime1).TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo), (object) dateTime2.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)));
          return ctx.CacheAge < ctx.CacheMaxAge ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
        }
        if (dateTime2 != DateTime.MinValue)
        {
          ctx.CacheMaxAge = dateTime2 - DateTime.UtcNow;
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_max_age_absolute", new object[1]
            {
              (object) dateTime2.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)
            }));
          return dateTime2 < DateTime.UtcNow ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
        }
        ctx.HeuristicExpiration = true;
        DateTime dateTime3 = ctx.CacheEntry.LastModifiedUtc;
        if (ctx.CacheLastModified > dateTime3)
          dateTime3 = ctx.CacheLastModified;
        ctx.CacheMaxAge = ctx.UnspecifiedMaxAge;
        if (dateTime3 != DateTime.MinValue)
        {
          int num = (int) ((utcNow - dateTime3).TotalSeconds / 10.0);
          ctx.CacheMaxAge = TimeSpan.FromSeconds((double) num);
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_no_max_age_use_10_percent", (object) num.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo), (object) dateTime3.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture)));
          return ctx.CacheAge.TotalSeconds < (double) num ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
        }
        ctx.CacheMaxAge = ctx.UnspecifiedMaxAge;
        if (Logging.On)
          Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_no_max_age_use_default", new object[1]
          {
            (object) ((int) ctx.UnspecifiedMaxAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
          }));
        return ctx.CacheMaxAge >= ctx.CacheAge ? CacheFreshnessStatus.Fresh : CacheFreshnessStatus.Stale;
      }

      internal static Rfc2616.TriState OnUpdateCache(HttpRequestCacheValidator ctx, HttpWebResponse resp)
      {
        if (ctx.RequestMethod != HttpMethod.Head && ctx.RequestMethod != HttpMethod.Get && ctx.RequestMethod != HttpMethod.Post)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_not_a_get_head_post"));
          return Rfc2616.TriState.Unknown;
        }
        if (ctx.CacheStream == Stream.Null || ctx.CacheStatusCode == (HttpStatusCode) 0)
        {
          if (resp.StatusCode == HttpStatusCode.NotModified)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_cannot_update_cache_if_304"));
            return Rfc2616.TriState.Unknown;
          }
          if (ctx.RequestMethod == HttpMethod.Head)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_cannot_update_cache_with_head_resp"));
            return Rfc2616.TriState.Unknown;
          }
        }
        if (resp == null)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_http_resp_is_null"));
          return Rfc2616.TriState.Unknown;
        }
        if (ctx.ResponseCacheControl.NoStore)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_cache_control_is_no_store"));
          return Rfc2616.TriState.Unknown;
        }
        if (ctx.ResponseDate != DateTime.MinValue && ctx.CacheDate != DateTime.MinValue && ctx.ResponseDate < ctx.CacheDate)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_resp_older_than_cache"));
          return Rfc2616.TriState.Unknown;
        }
        if (ctx.ResponseCacheControl.Public)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_cache_control_is_public"));
          return Rfc2616.TriState.Valid;
        }
        Rfc2616.TriState triState = Rfc2616.TriState.Unknown;
        if (ctx.ResponseCacheControl.Private)
        {
          if (!ctx.CacheEntry.IsPrivateEntry)
          {
            if (ctx.ResponseCacheControl.PrivateHeaders == null)
            {
              if (Logging.On)
                Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_cache_control_is_private"));
              return Rfc2616.TriState.Unknown;
            }
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_cache_control_is_private_plus_headers"));
            for (int index = 0; index < ctx.ResponseCacheControl.PrivateHeaders.Length; ++index)
            {
              ctx.CacheHeaders.Remove(ctx.ResponseCacheControl.PrivateHeaders[index]);
              triState = Rfc2616.TriState.Valid;
            }
          }
          else
            triState = Rfc2616.TriState.Valid;
        }
        if (ctx.ResponseCacheControl.NoCache)
        {
          if (ctx.ResponseLastModified == DateTime.MinValue && ctx.Response.Headers.ETag == null)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_revalidation_required"));
            return Rfc2616.TriState.Unknown;
          }
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_needs_revalidation"));
          return Rfc2616.TriState.Valid;
        }
        if (ctx.ResponseCacheControl.SMaxAge != -1 || ctx.ResponseCacheControl.MaxAge != -1)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_allows_caching", new object[1]
            {
              (object) ctx.ResponseCacheControl.ToString()
            }));
          return Rfc2616.TriState.Valid;
        }
        if (!ctx.CacheEntry.IsPrivateEntry && ctx.Request.Headers["Authorization"] != null)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_auth_header_and_no_s_max_age"));
          return Rfc2616.TriState.Unknown;
        }
        if (ctx.RequestMethod == HttpMethod.Post && resp.Headers.Expires == null)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_post_resp_without_cache_control_or_expires"));
          return Rfc2616.TriState.Unknown;
        }
        if (resp.StatusCode == HttpStatusCode.NotModified || resp.StatusCode == HttpStatusCode.OK || (resp.StatusCode == HttpStatusCode.NonAuthoritativeInformation || resp.StatusCode == HttpStatusCode.PartialContent) || (resp.StatusCode == HttpStatusCode.MultipleChoices || resp.StatusCode == HttpStatusCode.MovedPermanently || resp.StatusCode == HttpStatusCode.Gone))
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_valid_based_on_status_code", new object[1]
            {
              (object) resp.StatusCode
            }));
          return Rfc2616.TriState.Valid;
        }
        if (triState != Rfc2616.TriState.Valid && Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_resp_no_cache_control", new object[1]
          {
            (object) resp.StatusCode
          }));
        return triState;
      }

      public static bool ValidateCacheByClientPolicy(HttpRequestCacheValidator ctx)
      {
        if (ctx.Policy.Level == HttpRequestCacheLevel.Default)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_age", ctx.CacheAge != TimeSpan.MinValue ? (object) ((int) ctx.CacheAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo) : (object) SR.GetString("net_log_unknown"), ctx.CacheMaxAge != TimeSpan.MinValue ? (object) ((int) ctx.CacheMaxAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo) : (object) SR.GetString("net_log_unknown")));
          if (ctx.Policy.MinFresh > TimeSpan.Zero)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_policy_min_fresh", new object[1]
              {
                (object) ((int) ctx.Policy.MinFresh.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
              }));
            if (ctx.CacheAge + ctx.Policy.MinFresh >= ctx.CacheMaxAge)
              return false;
          }
          if (ctx.Policy.MaxAge != TimeSpan.MaxValue)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_policy_max_age", new object[1]
              {
                (object) ((int) ctx.Policy.MaxAge.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
              }));
            if (ctx.CacheAge >= ctx.Policy.MaxAge)
              return false;
          }
          if (ctx.Policy.InternalCacheSyncDateUtc != DateTime.MinValue)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_policy_cache_sync_date", (object) ctx.Policy.InternalCacheSyncDateUtc.ToString("r", (IFormatProvider) CultureInfo.CurrentCulture), (object) ctx.CacheEntry.LastSynchronizedUtc.ToString((IFormatProvider) CultureInfo.CurrentCulture)));
            if (ctx.CacheEntry.LastSynchronizedUtc < ctx.Policy.InternalCacheSyncDateUtc)
              return false;
          }
          TimeSpan cacheMaxAge = ctx.CacheMaxAge;
          if (ctx.Policy.MaxStale > TimeSpan.Zero)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_policy_max_stale", new object[1]
              {
                (object) ((int) ctx.Policy.MaxStale.TotalSeconds).ToString((IFormatProvider) NumberFormatInfo.InvariantInfo)
              }));
            TimeSpan timeSpan = !(cacheMaxAge < TimeSpan.MaxValue - ctx.Policy.MaxStale) ? TimeSpan.MaxValue : cacheMaxAge + ctx.Policy.MaxStale;
            return !(ctx.CacheAge >= timeSpan);
          }
        }
        return ctx.CacheFreshnessStatus == CacheFreshnessStatus.Fresh;
      }

      internal static Rfc2616.TriState ValidateCacheBySpecialCases(HttpRequestCacheValidator ctx)
      {
        if (ctx.CacheCacheControl.NoCache)
        {
          if (ctx.CacheCacheControl.NoCacheHeaders == null)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_control_no_cache"));
            return Rfc2616.TriState.Invalid;
          }
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_control_no_cache_removing_some_headers"));
          for (int index = 0; index < ctx.CacheCacheControl.NoCacheHeaders.Length; ++index)
            ctx.CacheHeaders.Remove(ctx.CacheCacheControl.NoCacheHeaders[index]);
        }
        if ((ctx.CacheCacheControl.MustRevalidate || !ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.ProxyRevalidate) && ctx.CacheFreshnessStatus != CacheFreshnessStatus.Fresh)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_control_must_revalidate"));
          return Rfc2616.TriState.Invalid;
        }
        if (ctx.Request.Headers["Authorization"] != null)
        {
          if (ctx.CacheFreshnessStatus != CacheFreshnessStatus.Fresh)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_cached_auth_header"));
            return Rfc2616.TriState.Invalid;
          }
          if (!ctx.CacheEntry.IsPrivateEntry && ctx.CacheCacheControl.SMaxAge == -1 && (!ctx.CacheCacheControl.MustRevalidate && !ctx.CacheCacheControl.Public))
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_cached_auth_header_no_control_directive"));
            return Rfc2616.TriState.Invalid;
          }
        }
        return Rfc2616.TriState.Valid;
      }

      public static CacheValidationStatus ValidateCacheAfterResponse(HttpRequestCacheValidator ctx, HttpWebResponse resp)
      {
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_after_validation"));
        if ((ctx.CacheStream == Stream.Null || ctx.CacheStatusCode == (HttpStatusCode) 0) && resp.StatusCode == HttpStatusCode.NotModified)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_resp_status_304"));
          return CacheValidationStatus.DoNotTakeFromCache;
        }
        if (ctx.RequestMethod == HttpMethod.Head)
        {
          bool flag = false;
          if (ctx.ResponseEntityLength != -1L && ctx.ResponseEntityLength != ctx.CacheEntityLength)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_head_resp_has_different_content_length"));
            flag = true;
          }
          if (resp.Headers["Content-MD5"] != ctx.CacheHeaders["Content-MD5"])
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_head_resp_has_different_content_md5"));
            flag = true;
          }
          if (resp.Headers.ETag != ctx.CacheHeaders.ETag)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_head_resp_has_different_etag"));
            flag = true;
          }
          if (resp.StatusCode != HttpStatusCode.NotModified && resp.Headers.LastModified != ctx.CacheHeaders.LastModified)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_304_head_resp_has_different_last_modified"));
            flag = true;
          }
          if (flag)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_existing_entry_has_to_be_discarded"));
            return CacheValidationStatus.RemoveFromCache;
          }
        }
        if (resp.StatusCode == HttpStatusCode.PartialContent)
        {
          if (ctx.CacheHeaders.ETag != ctx.Response.Headers.ETag || ctx.CacheHeaders.LastModified != ctx.Response.Headers.LastModified && (ctx.Response.Headers.LastModified != null || ctx.Response.Headers.ETag == null))
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_206_resp_non_matching_entry"));
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_existing_entry_should_be_discarded"));
            return CacheValidationStatus.RemoveFromCache;
          }
          if (ctx.CacheEntry.StreamSize != ctx.ResponseRangeStart)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_206_resp_starting_position_not_adjusted"));
            return CacheValidationStatus.DoNotTakeFromCache;
          }
          Rfc2616.Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
          if (ctx.RequestRangeUser)
          {
            ctx.CacheStreamOffset = ctx.CacheEntry.StreamSize;
            ctx.CacheStreamLength = ctx.ResponseRangeEnd - ctx.ResponseRangeStart + 1L;
            ctx.CacheEntityLength = ctx.ResponseEntityLength;
            ctx.CacheStatusCode = resp.StatusCode;
            ctx.CacheStatusDescription = resp.StatusDescription;
            ctx.CacheHttpVersion = resp.ProtocolVersion;
          }
          else
          {
            ctx.CacheStreamOffset = 0L;
            ctx.CacheStreamLength = ctx.ResponseEntityLength;
            ctx.CacheEntityLength = ctx.ResponseEntityLength;
            ctx.CacheStatusCode = HttpStatusCode.OK;
            ctx.CacheStatusDescription = "OK";
            ctx.CacheHttpVersion = resp.ProtocolVersion;
            ctx.CacheHeaders.Remove("Content-Range");
            if (ctx.CacheStreamLength == -1L)
              ctx.CacheHeaders.Remove("Content-Length");
            else
              ctx.CacheHeaders["Content-Length"] = ctx.CacheStreamLength.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo);
          }
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_combined_resp_requested"));
          return CacheValidationStatus.CombineCachedAndServerResponse;
        }
        if (resp.StatusCode == HttpStatusCode.NotModified)
        {
          WebHeaderCollection headers = resp.Headers;
          string str;
          string etag;
          if (ctx.CacheExpires != ctx.ResponseExpires || ctx.CacheLastModified != ctx.ResponseLastModified || (ctx.CacheDate != ctx.ResponseDate || ctx.ResponseCacheControl.IsNotEmpty) || ((str = headers["Content-Location"]) != null && str != ctx.CacheHeaders["Content-Location"] || (etag = headers.ETag) != null && etag != ctx.CacheHeaders.ETag))
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_updating_headers_on_304"));
            Rfc2616.Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
            return CacheValidationStatus.ReturnCachedResponse;
          }
          int num = 0;
          if (etag != null)
            ++num;
          if (str != null)
            ++num;
          if (ctx.ResponseAge != TimeSpan.MinValue)
            ++num;
          if (ctx.ResponseLastModified != DateTime.MinValue)
            ++num;
          if (ctx.ResponseExpires != DateTime.MinValue)
            ++num;
          if (ctx.ResponseDate != DateTime.MinValue)
            ++num;
          if (headers.Via != null)
            ++num;
          if (headers["Connection"] != null)
            ++num;
          if (headers["Keep-Alive"] != null)
            ++num;
          if (headers.ProxyAuthenticate != null)
            ++num;
          if (headers["Proxy-Authorization"] != null)
            ++num;
          if (headers["TE"] != null)
            ++num;
          if (headers["Transfer-Encoding"] != null)
            ++num;
          if (headers["Trailer"] != null)
            ++num;
          if (headers["Upgrade"] != null)
            ++num;
          if (resp.Headers.Count <= num)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_suppressing_headers_update_on_304"));
            ctx.CacheDontUpdateHeaders = true;
          }
          else
            Rfc2616.Common.ReplaceOrUpdateCacheHeaders(ctx, resp);
          return CacheValidationStatus.ReturnCachedResponse;
        }
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_status_code_not_304_206"));
        return CacheValidationStatus.DoNotTakeFromCache;
      }

      public static CacheValidationStatus ValidateCacheOn5XXResponse(HttpRequestCacheValidator ctx)
      {
        if (ctx.CacheStream == Stream.Null || ctx.CacheStatusCode == (HttpStatusCode) 0 || (ctx.CacheEntityLength != ctx.CacheEntry.StreamSize || ctx.CacheStatusCode == HttpStatusCode.PartialContent) || Rfc2616.Common.ValidateCacheBySpecialCases(ctx) != Rfc2616.TriState.Valid)
          return CacheValidationStatus.DoNotTakeFromCache;
        if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly || ctx.Policy.Level == HttpRequestCacheLevel.CacheIfAvailable || ctx.Policy.Level == HttpRequestCacheLevel.CacheOrNextCacheOnly)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_sxx_resp_cache_only"));
          return CacheValidationStatus.ReturnCachedResponse;
        }
        if (ctx.Policy.Level != HttpRequestCacheLevel.Default && ctx.Policy.Level != HttpRequestCacheLevel.Revalidate || !Rfc2616.Common.ValidateCacheByClientPolicy(ctx))
          return CacheValidationStatus.DoNotTakeFromCache;
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_sxx_resp_can_be_replaced"));
        ctx.CacheHeaders.Add("Warning", "111 Revalidation failed");
        return CacheValidationStatus.ReturnCachedResponse;
      }

      internal static Rfc2616.TriState ValidateCacheByVaryHeader(HttpRequestCacheValidator ctx)
      {
        string[] values1 = ctx.CacheHeaders.GetValues("Vary");
        if (values1 == null)
          return Rfc2616.TriState.Unknown;
        ArrayList arrayList1 = new ArrayList();
        HttpRequestCacheValidator.ParseHeaderValues(values1, HttpRequestCacheValidator.ParseValuesCallback, (IList) arrayList1);
        if (arrayList1.Count == 0)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_vary_header_empty"));
          return Rfc2616.TriState.Invalid;
        }
        if ((int) ((string) arrayList1[0])[0] == 42)
        {
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_vary_header_contains_asterisks"));
          return Rfc2616.TriState.Invalid;
        }
        if (ctx.SystemMeta == null || ctx.SystemMeta.Count == 0)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_no_headers_in_metadata"));
          return Rfc2616.TriState.Invalid;
        }
        for (int index1 = 0; index1 < arrayList1.Count; ++index1)
        {
          string[] values2 = ctx.Request.Headers.GetValues((string) arrayList1[index1]);
          ArrayList arrayList2 = new ArrayList();
          if (values2 != null)
            HttpRequestCacheValidator.ParseHeaderValues(values2, HttpRequestCacheValidator.ParseValuesCallback, (IList) arrayList2);
          string[] values3 = ctx.SystemMeta.GetValues((string) arrayList1[index1]);
          ArrayList arrayList3 = new ArrayList();
          if (values3 != null)
            HttpRequestCacheValidator.ParseHeaderValues(values3, HttpRequestCacheValidator.ParseValuesCallback, (IList) arrayList3);
          if (arrayList2.Count != arrayList3.Count)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_vary_header_mismatched_count", new object[1]
              {
                (object) (string) arrayList1[index1]
              }));
            return Rfc2616.TriState.Invalid;
          }
          for (int index2 = 0; index2 < arrayList3.Count; ++index2)
          {
            if (!Rfc2616.Common.AsciiLettersNoCaseEqual((string) arrayList3[index2], (string) arrayList2[index2]))
            {
              if (Logging.On)
                Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_vary_header_mismatched_field", (object) (string) arrayList1[index1], (object) (string) arrayList3[index2], (object) (string) arrayList2[index2]));
              return Rfc2616.TriState.Invalid;
            }
          }
        }
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_vary_header_match"));
        return Rfc2616.TriState.Valid;
      }

      public static CacheValidationStatus TryConditionalRequest(HttpRequestCacheValidator ctx)
      {
        string ranges;
        switch (Rfc2616.Common.CheckForRangeRequest(ctx, out ranges))
        {
          case Rfc2616.TriState.Invalid:
            return CacheValidationStatus.Continue;
          case Rfc2616.TriState.Valid:
            if (ctx is FtpRequestCacheValidator || !Rfc2616.Common.TryConditionalRangeRequest(ctx))
              return CacheValidationStatus.DoNotTakeFromCache;
            ctx.RequestRangeCache = true;
            ((HttpWebRequest) ctx.Request).AddRange((int) ctx.CacheEntry.StreamSize);
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_range", new object[1]
              {
                (object) ctx.Request.Headers["Range"]
              }));
            return CacheValidationStatus.Continue;
          default:
            return Rfc2616.Common.ConstructConditionalRequest(ctx);
        }
      }

      public static CacheValidationStatus TryResponseFromCache(HttpRequestCacheValidator ctx)
      {
        string ranges;
        switch (Rfc2616.Common.CheckForRangeRequest(ctx, out ranges))
        {
          case Rfc2616.TriState.Unknown:
            return CacheValidationStatus.ReturnCachedResponse;
          case Rfc2616.TriState.Invalid:
            long start = 0L;
            long end = 0L;
            long total = 0L;
            if (!Rfc2616.Common.GetBytesRange(ranges, ref start, ref end, ref total, true))
            {
              if (Logging.On)
                Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_range_invalid_format", new object[1]
                {
                  (object) ranges
                }));
              return CacheValidationStatus.DoNotTakeFromCache;
            }
            if (start >= ctx.CacheEntry.StreamSize || end > ctx.CacheEntry.StreamSize || end == -1L && ctx.CacheEntityLength == -1L || end == -1L && ctx.CacheEntityLength > ctx.CacheEntry.StreamSize || start == -1L && (end == -1L || ctx.CacheEntityLength == -1L || ctx.CacheEntityLength - end >= ctx.CacheEntry.StreamSize))
            {
              if (Logging.On)
                Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_range_not_in_cache", new object[1]
                {
                  (object) ranges
                }));
              return CacheValidationStatus.Continue;
            }
            if (start == -1L)
              start = ctx.CacheEntityLength - end;
            if (end <= 0L)
              end = ctx.CacheEntry.StreamSize - 1L;
            ctx.CacheStreamOffset = start;
            ctx.CacheStreamLength = end - start + 1L;
            Rfc2616.Common.Construct206PartialContent(ctx, (int) start);
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_range_in_cache", new object[1]
              {
                (object) ctx.CacheHeaders["Content-Range"]
              }));
            return CacheValidationStatus.ReturnCachedResponse;
          default:
            if (ctx.Policy.Level == HttpRequestCacheLevel.CacheOnly && (ctx.Uri.Scheme == Uri.UriSchemeHttp || ctx.Uri.Scheme == Uri.UriSchemeHttps))
            {
              ctx.CacheStreamOffset = 0L;
              ctx.CacheStreamLength = ctx.CacheEntry.StreamSize;
              Rfc2616.Common.Construct206PartialContent(ctx, 0);
              if (Logging.On)
                Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_partial_resp", new object[1]
                {
                  (object) ctx.CacheHeaders["Content-Range"]
                }));
              return CacheValidationStatus.ReturnCachedResponse;
            }
            if (ctx.CacheEntry.StreamSize >= (long) int.MaxValue)
            {
              if (Logging.On)
                Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_entry_size_too_big", new object[1]
                {
                  (object) ctx.CacheEntry.StreamSize
                }));
              return CacheValidationStatus.DoNotTakeFromCache;
            }
            if (!Rfc2616.Common.TryConditionalRangeRequest(ctx))
              return CacheValidationStatus.Continue;
            ctx.RequestRangeCache = true;
            ((HttpWebRequest) ctx.Request).AddRange((int) ctx.CacheEntry.StreamSize);
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_range", new object[1]
              {
                (object) ctx.Request.Headers["Range"]
              }));
            return CacheValidationStatus.Continue;
        }
      }

      public static CacheValidationStatus ConstructConditionalRequest(HttpRequestCacheValidator ctx)
      {
        CacheValidationStatus validationStatus = CacheValidationStatus.DoNotTakeFromCache;
        bool flag = false;
        string etag = ctx.CacheHeaders.ETag;
        if (etag != null)
        {
          validationStatus = CacheValidationStatus.Continue;
          ctx.Request.Headers["If-None-Match"] = etag;
          ctx.RequestIfHeader1 = "If-None-Match";
          ctx.RequestValidator1 = etag;
          flag = true;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_condition_if_none_match", new object[1]
            {
              (object) ctx.Request.Headers["If-None-Match"]
            }));
        }
        if (ctx.CacheEntry.LastModifiedUtc != DateTime.MinValue)
        {
          validationStatus = CacheValidationStatus.Continue;
          string str = ctx.CacheEntry.LastModifiedUtc.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture);
          ctx.Request.Headers.ChangeInternal("If-Modified-Since", str);
          if (flag)
          {
            ctx.RequestIfHeader2 = "If-Modified-Since";
            ctx.RequestValidator2 = str;
          }
          else
          {
            ctx.RequestIfHeader1 = "If-Modified-Since";
            ctx.RequestValidator1 = str;
          }
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_condition_if_modified_since", new object[1]
            {
              (object) ctx.Request.Headers["If-Modified-Since"]
            }));
        }
        if (Logging.On && validationStatus == CacheValidationStatus.DoNotTakeFromCache)
          Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_cannot_construct_conditional_request"));
        return validationStatus;
      }

      public static void Construct206PartialContent(HttpRequestCacheValidator ctx, int rangeStart)
      {
        ctx.CacheStatusCode = HttpStatusCode.PartialContent;
        ctx.CacheStatusDescription = "Partial Content";
        if (ctx.CacheHttpVersion == (Version) null)
          ctx.CacheHttpVersion = new Version(1, 1);
        string str = "bytes " + (object) rangeStart + (string) (object) '-' + (string) (object) ((long) rangeStart + ctx.CacheStreamLength - 1L) + (string) (object) '/' + (string) (ctx.CacheEntityLength <= 0L ? (object) "*" : (object) ctx.CacheEntityLength.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
        ctx.CacheHeaders["Content-Range"] = str;
        ctx.CacheHeaders["Content-Length"] = ctx.CacheStreamLength.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo);
        ctx.CacheEntry.IsPartialEntry = true;
      }

      public static void Construct200ok(HttpRequestCacheValidator ctx)
      {
        ctx.CacheStatusCode = HttpStatusCode.OK;
        ctx.CacheStatusDescription = "OK";
        if (ctx.CacheHttpVersion == (Version) null)
          ctx.CacheHttpVersion = new Version(1, 1);
        ctx.CacheHeaders.Remove("Content-Range");
        if (ctx.CacheEntityLength == -1L)
          ctx.CacheHeaders.Remove("Content-Length");
        else
          ctx.CacheHeaders["Content-Length"] = ctx.CacheEntityLength.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo);
        ctx.CacheEntry.IsPartialEntry = false;
      }

      public static void ConstructUnconditionalRefreshRequest(HttpRequestCacheValidator ctx)
      {
        WebHeaderCollection headers = ctx.Request.Headers;
        headers["Cache-Control"] = "max-age=0";
        headers["Pragma"] = "no-cache";
        if (ctx.RequestIfHeader1 != null)
        {
          headers.RemoveInternal(ctx.RequestIfHeader1);
          ctx.RequestIfHeader1 = (string) null;
        }
        if (ctx.RequestIfHeader2 != null)
        {
          headers.RemoveInternal(ctx.RequestIfHeader2);
          ctx.RequestIfHeader2 = (string) null;
        }
        if (!ctx.RequestRangeCache)
          return;
        headers.RemoveInternal("Range");
        ctx.RequestRangeCache = false;
      }

      public static void ReplaceOrUpdateCacheHeaders(HttpRequestCacheValidator ctx, HttpWebResponse resp)
      {
        if (ctx.CacheHeaders == null || resp.StatusCode != HttpStatusCode.NotModified && resp.StatusCode != HttpStatusCode.PartialContent)
          ctx.CacheHeaders = new WebHeaderCollection();
        string[] values = resp.Headers.GetValues("Vary");
        if (values != null)
        {
          ArrayList arrayList = new ArrayList();
          HttpRequestCacheValidator.ParseHeaderValues(values, HttpRequestCacheValidator.ParseValuesCallback, (IList) arrayList);
          if (arrayList.Count != 0 && (int) ((string) arrayList[0])[0] != 42)
          {
            if (Logging.On)
              Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_saving_request_headers", new object[1]
              {
                (object) resp.Headers["Vary"]
              }));
            if (ctx.SystemMeta == null)
              ctx.SystemMeta = new NameValueCollection(arrayList.Count + 1, (IEqualityComparer) CaseInsensitiveAscii.StaticInstance);
            for (int index = 0; index < arrayList.Count; ++index)
            {
              string str = ctx.Request.Headers[(string) arrayList[index]];
              ctx.SystemMeta[(string) arrayList[index]] = str;
            }
          }
        }
        for (int index = 0; index < ctx.Response.Headers.Count; ++index)
        {
          string key = ctx.Response.Headers.GetKey(index);
          if (!Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Connection") && !Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Keep-Alive") && (!Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Proxy-Authenticate") && !Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Proxy-Authorization")) && (!Rfc2616.Common.AsciiLettersNoCaseEqual(key, "TE") && !Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Transfer-Encoding") && (!Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Trailer") && !Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Upgrade"))) && (resp.StatusCode != HttpStatusCode.NotModified || !Rfc2616.Common.AsciiLettersNoCaseEqual(key, "Content-Length")))
            ctx.CacheHeaders.ChangeInternal(key, ctx.Response.Headers[index]);
        }
      }

      internal static unsafe bool UnsafeAsciiLettersNoCaseEqual(char* s1, int start, int length, string s2)
      {
        if (length - start < s2.Length)
          return false;
        for (int index = 0; index < s2.Length; ++index)
        {
          if (((int) s1[start + index] | 32) != ((int) s2[index] | 32))
            return false;
        }
        return true;
      }

      public static bool GetBytesRange(string ranges, ref long start, ref long end, ref long total, bool isRequest)
      {
        ranges = ranges.ToLower(CultureInfo.InvariantCulture);
        int index1 = 0;
        while (index1 < ranges.Length && (int) ranges[index1] == 32)
          ++index1;
        int index2 = index1 + 5;
        if (index2 >= ranges.Length || (int) ranges[index2 - 5] != 98 || ((int) ranges[index2 - 4] != 121 || (int) ranges[index2 - 3] != 116) || ((int) ranges[index2 - 2] != 101 || (int) ranges[index2 - 1] != 115))
        {
          if (Logging.On)
            Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_only_byte_range_implemented"));
          return false;
        }
        if (isRequest)
        {
          while (index2 < ranges.Length && (int) ranges[index2] == 32)
            ++index2;
          if ((int) ranges[index2] != 61)
            return false;
        }
        else if ((int) ranges[index2] != 32)
          return false;
        char ch1 = char.MinValue;
        do
          ;
        while (++index2 < ranges.Length && (int) (ch1 = ranges[index2]) == 32);
        start = -1L;
        if ((int) ch1 != 45)
        {
          if (index2 < ranges.Length && (int) ch1 >= 48 && (int) ch1 <= 57)
          {
            start = (long) ((int) ch1 - 48);
            while (++index2 < ranges.Length && (int) (ch1 = ranges[index2]) >= 48 && (int) ch1 <= 57)
              start = start * 10L + (long) ((int) ch1 - 48);
          }
          while (index2 < ranges.Length && (int) ch1 == 32)
            ch1 = ranges[++index2];
          if ((int) ch1 != 45)
            return false;
        }
        do
          ;
        while (index2 < ranges.Length && (int) (ch1 = ranges[++index2]) == 32);
        end = -1L;
        if (index2 < ranges.Length && (int) ch1 >= 48 && (int) ch1 <= 57)
        {
          end = (long) ((int) ch1 - 48);
          while (++index2 < ranges.Length && (int) (ch1 = ranges[index2]) >= 48 && (int) ch1 <= 57)
            end = end * 10L + (long) ((int) ch1 - 48);
        }
        if (isRequest)
        {
          while (index2 < ranges.Length)
          {
            if ((int) ranges[index2++] != 32)
            {
              if (Logging.On)
                Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_multiple_complex_range_not_implemented"));
              return false;
            }
          }
        }
        else
        {
          while (index2 < ranges.Length && (int) (ch1 = ranges[index2]) == 32)
            ++index2;
          if ((int) ch1 != 47)
            return false;
          do
            ;
          while (++index2 < ranges.Length && (int) (ch1 = ranges[index2]) == 32);
          total = -1L;
          if ((int) ch1 != 42 && index2 < ranges.Length && ((int) ch1 >= 48 && (int) ch1 <= 57))
          {
            total = (long) ((int) ch1 - 48);
            char ch2;
            while (++index2 < ranges.Length && (int) (ch2 = ranges[index2]) >= 48 && (int) ch2 <= 57)
              total = total * 10L + (long) ((int) ch2 - 48);
          }
        }
        return isRequest || start != -1L && end != -1L;
      }

      private static Rfc2616.TriState CheckForRangeRequest(HttpRequestCacheValidator ctx, out string ranges)
      {
        if ((ranges = ctx.Request.Headers["Range"]) != null)
        {
          ctx.RequestRangeUser = true;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_range_request_range", new object[1]
            {
              (object) ctx.Request.Headers["Range"]
            }));
          return Rfc2616.TriState.Invalid;
        }
        if (ctx.CacheStatusCode == HttpStatusCode.PartialContent && ctx.CacheEntityLength == ctx.CacheEntry.StreamSize)
        {
          ctx.CacheStatusCode = HttpStatusCode.OK;
          ctx.CacheStatusDescription = "OK";
          return Rfc2616.TriState.Unknown;
        }
        if (!ctx.CacheEntry.IsPartialEntry && (ctx.CacheEntityLength == -1L || ctx.CacheEntityLength == ctx.CacheEntry.StreamSize) && ctx.CacheStatusCode != HttpStatusCode.PartialContent)
          return Rfc2616.TriState.Unknown;
        if (Logging.On)
          Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_could_be_partial", (object) ctx.CacheEntry.StreamSize, (object) ctx.CacheEntityLength));
        return Rfc2616.TriState.Valid;
      }

      private static bool TryConditionalRangeRequest(HttpRequestCacheValidator ctx)
      {
        if (ctx.CacheEntry.StreamSize >= (long) int.MaxValue)
        {
          if (Logging.On)
            Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_entry_size_too_big", new object[1]
            {
              (object) ctx.CacheEntry.StreamSize
            }));
          return false;
        }
        string etag = ctx.CacheHeaders.ETag;
        if (etag != null)
        {
          ctx.Request.Headers["If-Range"] = etag;
          ctx.RequestIfHeader1 = "If-Range";
          ctx.RequestValidator1 = etag;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_condition_if_range", new object[1]
            {
              (object) ctx.Request.Headers["If-Range"]
            }));
          return true;
        }
        if (ctx.CacheEntry.LastModifiedUtc != DateTime.MinValue)
        {
          string str = ctx.CacheEntry.LastModifiedUtc.ToString("r", (IFormatProvider) CultureInfo.InvariantCulture);
          if (ctx.CacheHttpVersion.Major == 1 && ctx.CacheHttpVersion.Minor == 0)
          {
            if (Logging.On)
              Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_conditional_range_not_implemented_on_http_10"));
            return false;
          }
          ctx.Request.Headers["If-Range"] = str;
          ctx.RequestIfHeader1 = "If-Range";
          ctx.RequestValidator1 = str;
          if (Logging.On)
            Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_condition_if_range", new object[1]
            {
              (object) ctx.Request.Headers["If-Range"]
            }));
          return true;
        }
        if (Logging.On)
          Logging.PrintWarning(Logging.RequestCache, SR.GetString("net_log_cache_cannot_construct_conditional_range_request"));
        return false;
      }

      private static bool AsciiLettersNoCaseEqual(string s1, string s2)
      {
        if (s1.Length != s2.Length)
          return false;
        for (int index = 0; index < s1.Length; ++index)
        {
          if (((int) s1[index] | 32) != ((int) s2[index] | 32))
            return false;
        }
        return true;
      }
    }
  }
}
