GQ_Communicate/GQ_VR/Assets/Best HTTP/Source/SecureProtocol/asn1/Asn1GeneralizedTime.cs

267 lines
9.9 KiB
C#

#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using System.Globalization;
using System.IO;
using System.Text;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1
{
/// <summary>GeneralizedTime ASN.1 type</summary>
public class Asn1GeneralizedTime
: Asn1Object
{
internal class Meta : Asn1UniversalType
{
internal static readonly Asn1UniversalType Instance = new Meta();
private Meta() : base(typeof(Asn1GeneralizedTime), Asn1Tags.GeneralizedTime) { }
internal override Asn1Object FromImplicitPrimitive(DerOctetString octetString)
{
return CreatePrimitive(octetString.GetOctets());
}
}
public static Asn1GeneralizedTime GetInstance(object obj)
{
if (obj == null)
return null;
if (obj is Asn1GeneralizedTime asn1GeneralizedTime)
return asn1GeneralizedTime;
if (obj is IAsn1Convertible asn1Convertible)
{
Asn1Object asn1Object = asn1Convertible.ToAsn1Object();
if (asn1Object is Asn1GeneralizedTime converted)
return converted;
}
else if (obj is byte[] bytes)
{
try
{
return (Asn1GeneralizedTime)Meta.Instance.FromByteArray(bytes);
}
catch (IOException e)
{
throw new ArgumentException("failed to construct generalized time from byte[]: " + e.Message);
}
}
throw new ArgumentException("illegal object in GetInstance: " + Org.BouncyCastle.Utilities.Platform.GetTypeName(obj), nameof(obj));
}
public static Asn1GeneralizedTime GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
{
return (Asn1GeneralizedTime)Meta.Instance.GetContextInstance(taggedObject, declaredExplicit);
}
private readonly string m_timeString;
private readonly bool m_timeStringCanonical;
private readonly DateTime m_dateTime;
public Asn1GeneralizedTime(string timeString)
{
m_timeString = timeString ?? throw new ArgumentNullException(nameof(timeString));
m_timeStringCanonical = false; // TODO Dynamic check?
try
{
m_dateTime = FromString(timeString);
}
catch (FormatException e)
{
throw new ArgumentException("invalid date string: " + e.Message);
}
}
public Asn1GeneralizedTime(DateTime dateTime)
{
dateTime = dateTime.ToUniversalTime();
m_dateTime = dateTime;
m_timeString = ToStringCanonical(dateTime);
m_timeStringCanonical = true;
}
// TODO TimeZoneInfo or other locale-specific constructors?
internal Asn1GeneralizedTime(byte[] contents)
: this(Encoding.ASCII.GetString(contents))
{
}
public string TimeString => m_timeString;
public DateTime ToDateTime()
{
return m_dateTime;
}
internal byte[] GetContents(int encoding)
{
if (encoding == Asn1OutputStream.EncodingDer && !m_timeStringCanonical)
return Encoding.ASCII.GetBytes(ToStringCanonical(m_dateTime));
return Encoding.ASCII.GetBytes(m_timeString);
}
internal override IAsn1Encoding GetEncoding(int encoding)
{
return new PrimitiveEncoding(Asn1Tags.Universal, Asn1Tags.GeneralizedTime, GetContents(encoding));
}
internal override IAsn1Encoding GetEncodingImplicit(int encoding, int tagClass, int tagNo)
{
return new PrimitiveEncoding(tagClass, tagNo, GetContents(encoding));
}
protected override bool Asn1Equals(Asn1Object asn1Object)
{
if (!(asn1Object is Asn1GeneralizedTime that))
return false;
// TODO Performance
return Arrays.AreEqual(
this.GetContents(Asn1OutputStream.EncodingDer),
that.GetContents(Asn1OutputStream.EncodingDer));
}
protected override int Asn1GetHashCode()
{
// TODO Performance
return Arrays.GetHashCode(
this.GetContents(Asn1OutputStream.EncodingDer));
}
internal static Asn1GeneralizedTime CreatePrimitive(byte[] contents)
{
return new Asn1GeneralizedTime(contents);
}
private static DateTime FromString(string s)
{
if (s.Length < 10)
throw new FormatException();
s = s.Replace(',', '.');
if (Org.BouncyCastle.Utilities.Platform.EndsWith(s, "Z"))
{
switch (s.Length)
{
case 11: return ParseUtc(s, @"yyyyMMddHH\Z");
case 13: return ParseUtc(s, @"yyyyMMddHHmm\Z");
case 15: return ParseUtc(s, @"yyyyMMddHHmmss\Z");
case 17: return ParseUtc(s, @"yyyyMMddHHmmss.f\Z");
case 18: return ParseUtc(s, @"yyyyMMddHHmmss.ff\Z");
case 19: return ParseUtc(s, @"yyyyMMddHHmmss.fff\Z");
case 20: return ParseUtc(s, @"yyyyMMddHHmmss.ffff\Z");
case 21: return ParseUtc(s, @"yyyyMMddHHmmss.fffff\Z");
case 22: return ParseUtc(s, @"yyyyMMddHHmmss.ffffff\Z");
case 23: return ParseUtc(s, @"yyyyMMddHHmmss.fffffff\Z");
default:
throw new FormatException();
}
}
int signIndex = IndexOfSign(s, System.Math.Max(10, s.Length - 5));
if (signIndex < 0)
{
switch (s.Length)
{
case 10: return ParseLocal(s, @"yyyyMMddHH");
case 12: return ParseLocal(s, @"yyyyMMddHHmm");
case 14: return ParseLocal(s, @"yyyyMMddHHmmss");
case 16: return ParseLocal(s, @"yyyyMMddHHmmss.f");
case 17: return ParseLocal(s, @"yyyyMMddHHmmss.ff");
case 18: return ParseLocal(s, @"yyyyMMddHHmmss.fff");
case 19: return ParseLocal(s, @"yyyyMMddHHmmss.ffff");
case 20: return ParseLocal(s, @"yyyyMMddHHmmss.fffff");
case 21: return ParseLocal(s, @"yyyyMMddHHmmss.ffffff");
case 22: return ParseLocal(s, @"yyyyMMddHHmmss.fffffff");
default:
throw new FormatException();
}
}
if (signIndex == s.Length - 5)
{
switch (s.Length)
{
case 15: return ParseTimeZone(s, @"yyyyMMddHHzzz");
case 17: return ParseTimeZone(s, @"yyyyMMddHHmmzzz");
case 19: return ParseTimeZone(s, @"yyyyMMddHHmmsszzz");
case 21: return ParseTimeZone(s, @"yyyyMMddHHmmss.fzzz");
case 22: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffzzz");
case 23: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffzzz");
case 24: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffzzz");
case 25: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffzzz");
case 26: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffffzzz");
case 27: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffffzzz");
default:
throw new FormatException();
}
}
if (signIndex == s.Length - 3)
{
switch (s.Length)
{
case 13: return ParseTimeZone(s, @"yyyyMMddHHzz");
case 15: return ParseTimeZone(s, @"yyyyMMddHHmmzz");
case 17: return ParseTimeZone(s, @"yyyyMMddHHmmsszz");
case 19: return ParseTimeZone(s, @"yyyyMMddHHmmss.fzz");
case 20: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffzz");
case 21: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffzz");
case 22: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffzz");
case 23: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffzz");
case 24: return ParseTimeZone(s, @"yyyyMMddHHmmss.ffffffzz");
case 25: return ParseTimeZone(s, @"yyyyMMddHHmmss.fffffffzz");
default:
throw new FormatException();
}
}
throw new FormatException();
}
private static int IndexOfSign(string s, int startIndex)
{
int index = Org.BouncyCastle.Utilities.Platform.IndexOf(s, '+', startIndex);
if (index < 0)
{
index = Org.BouncyCastle.Utilities.Platform.IndexOf(s, '-', startIndex);
}
return index;
}
private static DateTime ParseLocal(string s, string format)
{
return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AssumeLocal);
}
private static DateTime ParseTimeZone(string s, string format)
{
return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal);
}
private static DateTime ParseUtc(string s, string format)
{
return DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo,
DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal);
}
private static string ToStringCanonical(DateTime dateTime)
{
return dateTime.ToUniversalTime().ToString(@"yyyyMMddHHmmss.FFFFFFFK", DateTimeFormatInfo.InvariantInfo);
}
}
}
#pragma warning restore
#endif