

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Bson;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq.JsonPath;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AllowPartiallyTrustedCallers]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Newtonsoft")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © James Newton-King 2008")]
[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
[assembly: AssemblyFileVersion("13.0.3.27908")]
[assembly: AssemblyInformationalVersion("13.0.3+0a2e291c0d9c0c7675d445703e51750363a549ef")]
[assembly: AssemblyProduct("Json.NET")]
[assembly: AssemblyTitle("Json.NET .NET 4.5")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: AssemblyVersion("13.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class IsReadOnlyAttribute : Attribute
{
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
internal sealed class NotNullAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
public bool ReturnValue { get; }
public NotNullWhenAttribute(bool returnValue)
{
ReturnValue = returnValue;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)]
internal sealed class MaybeNullAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
internal sealed class AllowNullAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal class DoesNotReturnIfAttribute : Attribute
{
public bool ParameterValue { get; }
public DoesNotReturnIfAttribute(bool parameterValue)
{
ParameterValue = parameterValue;
}
}
}
namespace Newtonsoft.Json
{
public enum ConstructorHandling
{
Default,
AllowNonPublicDefaultConstructor
}
public enum DateFormatHandling
{
IsoDateFormat,
MicrosoftDateFormat
}
public enum DateParseHandling
{
None,
DateTime,
DateTimeOffset
}
public enum DateTimeZoneHandling
{
Local,
Utc,
Unspecified,
RoundtripKind
}
public class DefaultJsonNameTable : JsonNameTable
{
private class Entry
{
internal readonly string Value;
internal readonly int HashCode;
internal Entry Next;
internal Entry(string value, int hashCode, Entry next)
{
Value = value;
HashCode = hashCode;
Next = next;
}
}
private static readonly int HashCodeRandomizer;
private int _count;
private Entry[] _entries;
private int _mask = 31;
static DefaultJsonNameTable()
{
HashCodeRandomizer = Environment.TickCount;
}
public DefaultJsonNameTable()
{
_entries = new Entry[_mask + 1];
}
public override string? Get(char[] key, int start, int length)
{
if (length == 0)
{
return string.Empty;
}
int num = length + HashCodeRandomizer;
num += (num << 7) ^ key[start];
int num2 = start + length;
for (int i = start + 1; i < num2; i++)
{
num += (num << 7) ^ key[i];
}
num -= num >> 17;
num -= num >> 11;
num -= num >> 5;
int num3 = Volatile.Read(ref _mask);
int num4 = num & num3;
for (Entry entry = _entries[num4]; entry != null; entry = entry.Next)
{
if (entry.HashCode == num && TextEquals(entry.Value, key, start, length))
{
return entry.Value;
}
}
return null;
}
public string Add(string key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
int length = key.Length;
if (length == 0)
{
return string.Empty;
}
int num = length + HashCodeRandomizer;
for (int i = 0; i < key.Length; i++)
{
num += (num << 7) ^ key[i];
}
num -= num >> 17;
num -= num >> 11;
num -= num >> 5;
for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next)
{
if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal))
{
return entry.Value;
}
}
return AddEntry(key, num);
}
private string AddEntry(string str, int hashCode)
{
int num = hashCode & _mask;
Entry entry = new Entry(str, hashCode, _entries[num]);
_entries[num] = entry;
if (_count++ == _mask)
{
Grow();
}
return entry.Value;
}
private void Grow()
{
Entry[] entries = _entries;
int num = _mask * 2 + 1;
Entry[] array = new Entry[num + 1];
for (int i = 0; i < entries.Length; i++)
{
Entry entry = entries[i];
while (entry != null)
{
int num2 = entry.HashCode & num;
Entry next = entry.Next;
entry.Next = array[num2];
array[num2] = entry;
entry = next;
}
}
_entries = array;
Volatile.Write(ref _mask, num);
}
private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length)
{
if (str1.Length != str2Length)
{
return false;
}
for (int i = 0; i < str1.Length; i++)
{
if (str1[i] != str2[str2Start + i])
{
return false;
}
}
return true;
}
}
[Flags]
public enum DefaultValueHandling
{
Include = 0,
Ignore = 1,
Populate = 2,
IgnoreAndPopulate = 3
}
public enum FloatFormatHandling
{
String,
Symbol,
DefaultValue
}
public enum FloatParseHandling
{
Double,
Decimal
}
public enum Formatting
{
None,
Indented
}
public interface IArrayPool<T>
{
T[] Rent(int minimumLength);
void Return(T[]? array);
}
public interface IJsonLineInfo
{
int LineNumber { get; }
int LinePosition { get; }
bool HasLineInfo();
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
public sealed class JsonArrayAttribute : JsonContainerAttribute
{
private bool _allowNullItems;
public bool AllowNullItems
{
get
{
return _allowNullItems;
}
set
{
_allowNullItems = value;
}
}
public JsonArrayAttribute()
{
}
public JsonArrayAttribute(bool allowNullItems)
{
_allowNullItems = allowNullItems;
}
public JsonArrayAttribute(string id)
: base(id)
{
}
}
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
public sealed class JsonConstructorAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
public abstract class JsonContainerAttribute : Attribute
{
internal bool? _isReference;
internal bool? _itemIsReference;
internal ReferenceLoopHandling? _itemReferenceLoopHandling;
internal TypeNameHandling? _itemTypeNameHandling;
private Type? _namingStrategyType;
private object[]? _namingStrategyParameters;
public string? Id { get; set; }
public string? Title { get; set; }
public string? Description { get; set; }
public Type? ItemConverterType { get; set; }
public object[]? ItemConverterParameters { get; set; }
public Type? NamingStrategyType
{
get
{
return _namingStrategyType;
}
set
{
_namingStrategyType = value;
NamingStrategyInstance = null;
}
}
public object[]? NamingStrategyParameters
{
get
{
return _namingStrategyParameters;
}
set
{
_namingStrategyParameters = value;
NamingStrategyInstance = null;
}
}
internal NamingStrategy? NamingStrategyInstance { get; set; }
public bool IsReference
{
get
{
return _isReference.GetValueOrDefault();
}
set
{
_isReference = value;
}
}
public bool ItemIsReference
{
get
{
return _itemIsReference.GetValueOrDefault();
}
set
{
_itemIsReference = value;
}
}
public ReferenceLoopHandling ItemReferenceLoopHandling
{
get
{
return _itemReferenceLoopHandling.GetValueOrDefault();
}
set
{
_itemReferenceLoopHandling = value;
}
}
public TypeNameHandling ItemTypeNameHandling
{
get
{
return _itemTypeNameHandling.GetValueOrDefault();
}
set
{
_itemTypeNameHandling = value;
}
}
protected JsonContainerAttribute()
{
}
protected JsonContainerAttribute(string id)
{
Id = id;
}
}
public static class JsonConvert
{
public static readonly string True = "true";
public static readonly string False = "false";
public static readonly string Null = "null";
public static readonly string Undefined = "undefined";
public static readonly string PositiveInfinity = "Infinity";
public static readonly string NegativeInfinity = "-Infinity";
public static readonly string NaN = "NaN";
public static Func<JsonSerializerSettings>? DefaultSettings { get; set; }
public static string ToString(DateTime value)
{
return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
}
public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
{
DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
stringWriter.Write('"');
DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture);
stringWriter.Write('"');
return stringWriter.ToString();
}
public static string ToString(DateTimeOffset value)
{
return ToString(value, DateFormatHandling.IsoDateFormat);
}
public static string ToString(DateTimeOffset value, DateFormatHandling format)
{
using StringWriter stringWriter = StringUtils.CreateStringWriter(64);
stringWriter.Write('"');
DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture);
stringWriter.Write('"');
return stringWriter.ToString();
}
public static string ToString(bool value)
{
if (!value)
{
return False;
}
return True;
}
public static string ToString(char value)
{
return ToString(char.ToString(value));
}
public static string ToString(Enum value)
{
return value.ToString("D");
}
public static string ToString(int value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
public static string ToString(short value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
[CLSCompliant(false)]
public static string ToString(ushort value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
[CLSCompliant(false)]
public static string ToString(uint value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
public static string ToString(long value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
private static string ToStringInternal(BigInteger value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
[CLSCompliant(false)]
public static string ToString(ulong value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
public static string ToString(float value)
{
return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
}
internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
{
return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
}
private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
{
if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value)))
{
return text;
}
if (floatFormatHandling == FloatFormatHandling.DefaultValue)
{
if (nullable)
{
return Null;
}
return "0.0";
}
return quoteChar + text + quoteChar;
}
public static string ToString(double value)
{
return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
}
internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
{
return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
}
private static string EnsureDecimalPlace(double value, string text)
{
if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1)
{
return text;
}
return text + ".0";
}
private static string EnsureDecimalPlace(string text)
{
if (StringUtils.IndexOf(text, '.') != -1)
{
return text;
}
return text + ".0";
}
public static string ToString(byte value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
[CLSCompliant(false)]
public static string ToString(sbyte value)
{
return value.ToString(null, CultureInfo.InvariantCulture);
}
public static string ToString(decimal value)
{
return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
}
public static string ToString(Guid value)
{
return ToString(value, '"');
}
internal static string ToString(Guid value, char quoteChar)
{
string text = value.ToString("D", CultureInfo.InvariantCulture);
string text2 = quoteChar.ToString(CultureInfo.InvariantCulture);
return text2 + text + text2;
}
public static string ToString(TimeSpan value)
{
return ToString(value, '"');
}
internal static string ToString(TimeSpan value, char quoteChar)
{
return ToString(value.ToString(), quoteChar);
}
public static string ToString(Uri? value)
{
if (value == null)
{
return Null;
}
return ToString(value, '"');
}
internal static string ToString(Uri value, char quoteChar)
{
return ToString(value.OriginalString, quoteChar);
}
public static string ToString(string? value)
{
return ToString(value, '"');
}
public static string ToString(string? value, char delimiter)
{
return ToString(value, delimiter, StringEscapeHandling.Default);
}
public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling)
{
if (delimiter != '"' && delimiter != '\'')
{
throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
}
return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling);
}
public static string ToString(object? value)
{
if (value == null)
{
return Null;
}
return ConvertUtils.GetTypeCode(value.GetType()) switch
{
PrimitiveTypeCode.String => ToString((string)value),
PrimitiveTypeCode.Char => ToString((char)value),
PrimitiveTypeCode.Boolean => ToString((bool)value),
PrimitiveTypeCode.SByte => ToString((sbyte)value),
PrimitiveTypeCode.Int16 => ToString((short)value),
PrimitiveTypeCode.UInt16 => ToString((ushort)value),
PrimitiveTypeCode.Int32 => ToString((int)value),
PrimitiveTypeCode.Byte => ToString((byte)value),
PrimitiveTypeCode.UInt32 => ToString((uint)value),
PrimitiveTypeCode.Int64 => ToString((long)value),
PrimitiveTypeCode.UInt64 => ToString((ulong)value),
PrimitiveTypeCode.Single => ToString((float)value),
PrimitiveTypeCode.Double => ToString((double)value),
PrimitiveTypeCode.DateTime => ToString((DateTime)value),
PrimitiveTypeCode.Decimal => ToString((decimal)value),
PrimitiveTypeCode.DBNull => Null,
PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value),
PrimitiveTypeCode.Guid => ToString((Guid)value),
PrimitiveTypeCode.Uri => ToString((Uri)value),
PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value),
PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value),
_ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())),
};
}
[DebuggerStepThrough]
public static string SerializeObject(object? value)
{
return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting)
{
return SerializeObject(value, formatting, (JsonSerializerSettings?)null);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, params JsonConverter[] converters)
{
JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
{
Converters = converters
} : null);
return SerializeObject(value, null, settings);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters)
{
JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
{
Converters = converters
} : null);
return SerializeObject(value, null, formatting, settings);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, JsonSerializerSettings? settings)
{
return SerializeObject(value, null, settings);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings)
{
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
return SerializeObjectInternal(value, type, jsonSerializer);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings)
{
return SerializeObject(value, null, formatting, settings);
}
[DebuggerStepThrough]
public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings)
{
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
jsonSerializer.Formatting = formatting;
return SerializeObjectInternal(value, type, jsonSerializer);
}
private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer)
{
StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture);
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter))
{
jsonTextWriter.Formatting = jsonSerializer.Formatting;
jsonSerializer.Serialize(jsonTextWriter, value, type);
}
return stringWriter.ToString();
}
[DebuggerStepThrough]
public static object? DeserializeObject(string value)
{
return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null);
}
[DebuggerStepThrough]
public static object? DeserializeObject(string value, JsonSerializerSettings settings)
{
return DeserializeObject(value, null, settings);
}
[DebuggerStepThrough]
public static object? DeserializeObject(string value, Type type)
{
return DeserializeObject(value, type, (JsonSerializerSettings?)null);
}
[DebuggerStepThrough]
public static T? DeserializeObject<T>(string value)
{
return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null);
}
[DebuggerStepThrough]
public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{
return DeserializeObject<T>(value);
}
[DebuggerStepThrough]
public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
{
return DeserializeObject<T>(value, settings);
}
[DebuggerStepThrough]
public static T? DeserializeObject<T>(string value, params JsonConverter[] converters)
{
return (T)DeserializeObject(value, typeof(T), converters);
}
[DebuggerStepThrough]
public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings)
{
return (T)DeserializeObject(value, typeof(T), settings);
}
[DebuggerStepThrough]
public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters)
{
JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings
{
Converters = converters
} : null);
return DeserializeObject(value, type, settings);
}
public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings)
{
ValidationUtils.ArgumentNotNull(value, "value");
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
if (!jsonSerializer.IsCheckAdditionalContentSet())
{
jsonSerializer.CheckAdditionalContent = true;
}
using JsonTextReader reader = new JsonTextReader(new StringReader(value));
return jsonSerializer.Deserialize(reader, type);
}
[DebuggerStepThrough]
public static void PopulateObject(string value, object target)
{
PopulateObject(value, target, null);
}
public static void PopulateObject(string value, object target, JsonSerializerSettings? settings)
{
JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
using JsonReader jsonReader = new JsonTextReader(new StringReader(value));
jsonSerializer.Populate(jsonReader, target);
if (settings == null || !settings.CheckAdditionalContent)
{
return;
}
while (jsonReader.Read())
{
if (jsonReader.TokenType != JsonToken.Comment)
{
throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object.");
}
}
}
public static string SerializeXmlNode(XmlNode? node)
{
return SerializeXmlNode(node, Formatting.None);
}
public static string SerializeXmlNode(XmlNode? node, Formatting formatting)
{
XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
return SerializeObject(node, formatting, xmlNodeConverter);
}
public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject)
{
XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
{
OmitRootObject = omitRootObject
};
return SerializeObject(node, formatting, xmlNodeConverter);
}
public static XmlDocument? DeserializeXmlNode(string value)
{
return DeserializeXmlNode(value, null);
}
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName)
{
return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false);
}
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
{
return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
}
public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
{
XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter);
}
public static string SerializeXNode(XObject? node)
{
return SerializeXNode(node, Formatting.None);
}
public static string SerializeXNode(XObject? node, Formatting formatting)
{
return SerializeXNode(node, formatting, omitRootObject: false);
}
public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject)
{
XmlNodeConverter xmlNodeConverter = new XmlNodeConverter
{
OmitRootObject = omitRootObject
};
return SerializeObject(node, formatting, xmlNodeConverter);
}
public static XDocument? DeserializeXNode(string value)
{
return DeserializeXNode(value, null);
}
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName)
{
return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false);
}
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute)
{
return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false);
}
public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters)
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
XmlNodeConverter xmlNodeConverter = new XmlNodeConverter();
xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName;
xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute;
xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters;
return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter);
}
}
public abstract class JsonConverter
{
public virtual bool CanRead => true;
public virtual bool CanWrite => true;
public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer);
public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer);
public abstract bool CanConvert(Type objectType);
}
public abstract class JsonConverter<T> : JsonConverter
{
public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T))))
{
throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
}
WriteJson(writer, (T)value, serializer);
}
public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer);
public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
bool flag = existingValue == null;
if (!flag && !(existingValue is T))
{
throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T)));
}
return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer);
}
public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer);
public sealed override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class JsonConverterAttribute : Attribute
{
private readonly Type _converterType;
public Type ConverterType => _converterType;
public object[]? ConverterParameters { get; }
public JsonConverterAttribute(Type converterType)
{
if (converterType == null)
{
throw new ArgumentNullException("converterType");
}
_converterType = converterType;
}
public JsonConverterAttribute(Type converterType, params object[] converterParameters)
: this(converterType)
{
ConverterParameters = converterParameters;
}
}
public class JsonConverterCollection : Collection<JsonConverter>
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
public sealed class JsonDictionaryAttribute : JsonContainerAttribute
{
public JsonDictionaryAttribute()
{
}
public JsonDictionaryAttribute(string id)
: base(id)
{
}
}
[Serializable]
public class JsonException : Exception
{
public JsonException()
{
}
public JsonException(string message)
: base(message)
{
}
public JsonException(string message, Exception? innerException)
: base(message, innerException)
{
}
public JsonException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
{
message = JsonPosition.FormatMessage(lineInfo, path, message);
return new JsonException(message);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class JsonExtensionDataAttribute : Attribute
{
public bool WriteData { get; set; }
public bool ReadData { get; set; }
public JsonExtensionDataAttribute()
{
WriteData = true;
ReadData = true;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonIgnoreAttribute : Attribute
{
}
public abstract class JsonNameTable
{
public abstract string? Get(char[] key, int start, int length);
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
public sealed class JsonObjectAttribute : JsonContainerAttribute
{
private MemberSerialization _memberSerialization;
internal MissingMemberHandling? _missingMemberHandling;
internal Required? _itemRequired;
internal NullValueHandling? _itemNullValueHandling;
public MemberSerialization MemberSerialization
{
get
{
return _memberSerialization;
}
set
{
_memberSerialization = value;
}
}
public MissingMemberHandling MissingMemberHandling
{
get
{
return _missingMemberHandling.GetValueOrDefault();
}
set
{
_missingMemberHandling = value;
}
}
public NullValueHandling ItemNullValueHandling
{
get
{
return _itemNullValueHandling.GetValueOrDefault();
}
set
{
_itemNullValueHandling = value;
}
}
public Required ItemRequired
{
get
{
return _itemRequired.GetValueOrDefault();
}
set
{
_itemRequired = value;
}
}
public JsonObjectAttribute()
{
}
public JsonObjectAttribute(MemberSerialization memberSerialization)
{
MemberSerialization = memberSerialization;
}
public JsonObjectAttribute(string id)
: base(id)
{
}
}
internal enum JsonContainerType
{
None,
Object,
Array,
Constructor
}
internal struct JsonPosition
{
private static readonly char[] SpecialCharacters = new char[18]
{
'.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t',
'\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029'
};
internal JsonContainerType Type;
internal int Position;
internal string? PropertyName;
internal bool HasIndex;
public JsonPosition(JsonContainerType type)
{
Type = type;
HasIndex = TypeHasIndex(type);
Position = -1;
PropertyName = null;
}
internal int CalculateLength()
{
switch (Type)
{
case JsonContainerType.Object:
return PropertyName.Length + 5;
case JsonContainerType.Array:
case JsonContainerType.Constructor:
return MathUtils.IntLength((ulong)Position) + 2;
default:
throw new ArgumentOutOfRangeException("Type");
}
}
internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer)
{
switch (Type)
{
case JsonContainerType.Object:
{
string propertyName = PropertyName;
if (propertyName.IndexOfAny(SpecialCharacters) != -1)
{
sb.Append("['");
if (writer == null)
{
writer = new StringWriter(sb);
}
JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer);
sb.Append("']");
}
else
{
if (sb.Length > 0)
{
sb.Append('.');
}
sb.Append(propertyName);
}
break;
}
case JsonContainerType.Array:
case JsonContainerType.Constructor:
sb.Append('[');
sb.Append(Position);
sb.Append(']');
break;
}
}
internal static bool TypeHasIndex(JsonContainerType type)
{
if (type != JsonContainerType.Array)
{
return type == JsonContainerType.Constructor;
}
return true;
}
internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition)
{
int num = 0;
if (positions != null)
{
for (int i = 0; i < positions.Count; i++)
{
num += positions[i].CalculateLength();
}
}
if (currentPosition.HasValue)
{
num += currentPosition.GetValueOrDefault().CalculateLength();
}
StringBuilder stringBuilder = new StringBuilder(num);
StringWriter writer = null;
char[] buffer = null;
if (positions != null)
{
foreach (JsonPosition position in positions)
{
position.WriteTo(stringBuilder, ref writer, ref buffer);
}
}
currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer);
return stringBuilder.ToString();
}
internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message)
{
if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal))
{
message = message.Trim();
if (!StringUtils.EndsWith(message, '.'))
{
message += ".";
}
message += " ";
}
message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
if (lineInfo != null && lineInfo.HasLineInfo())
{
message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
}
message += ".";
return message;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class JsonPropertyAttribute : Attribute
{
internal NullValueHandling? _nullValueHandling;
internal DefaultValueHandling? _defaultValueHandling;
internal ReferenceLoopHandling? _referenceLoopHandling;
internal ObjectCreationHandling? _objectCreationHandling;
internal TypeNameHandling? _typeNameHandling;
internal bool? _isReference;
internal int? _order;
internal Required? _required;
internal bool? _itemIsReference;
internal ReferenceLoopHandling? _itemReferenceLoopHandling;
internal TypeNameHandling? _itemTypeNameHandling;
public Type? ItemConverterType { get; set; }
public object[]? ItemConverterParameters { get; set; }
public Type? NamingStrategyType { get; set; }
public object[]? NamingStrategyParameters { get; set; }
public NullValueHandling NullValueHandling
{
get
{
return _nullValueHandling.GetValueOrDefault();
}
set
{
_nullValueHandling = value;
}
}
public DefaultValueHandling DefaultValueHandling
{
get
{
return _defaultValueHandling.GetValueOrDefault();
}
set
{
_defaultValueHandling = value;
}
}
public ReferenceLoopHandling ReferenceLoopHandling
{
get
{
return _referenceLoopHandling.GetValueOrDefault();
}
set
{
_referenceLoopHandling = value;
}
}
public ObjectCreationHandling ObjectCreationHandling
{
get
{
return _objectCreationHandling.GetValueOrDefault();
}
set
{
_objectCreationHandling = value;
}
}
public TypeNameHandling TypeNameHandling
{
get
{
return _typeNameHandling.GetValueOrDefault();
}
set
{
_typeNameHandling = value;
}
}
public bool IsReference
{
get
{
return _isReference.GetValueOrDefault();
}
set
{
_isReference = value;
}
}
public int Order
{
get
{
return _order.GetValueOrDefault();
}
set
{
_order = value;
}
}
public Required Required
{
get
{
return _required.GetValueOrDefault();
}
set
{
_required = value;
}
}
public string? PropertyName { get; set; }
public ReferenceLoopHandling ItemReferenceLoopHandling
{
get
{
return _itemReferenceLoopHandling.GetValueOrDefault();
}
set
{
_itemReferenceLoopHandling = value;
}
}
public TypeNameHandling ItemTypeNameHandling
{
get
{
return _itemTypeNameHandling.GetValueOrDefault();
}
set
{
_itemTypeNameHandling = value;
}
}
public bool ItemIsReference
{
get
{
return _itemIsReference.GetValueOrDefault();
}
set
{
_itemIsReference = value;
}
}
public JsonPropertyAttribute()
{
}
public JsonPropertyAttribute(string propertyName)
{
PropertyName = propertyName;
}
}
public abstract class JsonReader : IDisposable
{
protected internal enum State
{
Start,
Complete,
Property,
ObjectStart,
Object,
ArrayStart,
Array,
Closed,
PostValue,
ConstructorStart,
Constructor,
Error,
Finished
}
private JsonToken _tokenType;
private object? _value;
internal char _quoteChar;
internal State _currentState;
private JsonPosition _currentPosition;
private CultureInfo? _culture;
private DateTimeZoneHandling _dateTimeZoneHandling;
private int? _maxDepth;
private bool _hasExceededMaxDepth;
internal DateParseHandling _dateParseHandling;
internal FloatParseHandling _floatParseHandling;
private string? _dateFormatString;
private List<JsonPosition>? _stack;
protected State CurrentState => _currentState;
public bool CloseInput { get; set; }
public bool SupportMultipleContent { get; set; }
public virtual char QuoteChar
{
get
{
return _quoteChar;
}
protected internal set
{
_quoteChar = value;
}
}
public DateTimeZoneHandling DateTimeZoneHandling
{
get
{
return _dateTimeZoneHandling;
}
set
{
if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind)
{
throw new ArgumentOutOfRangeException("value");
}
_dateTimeZoneHandling = value;
}
}
public DateParseHandling DateParseHandling
{
get
{
return _dateParseHandling;
}
set
{
if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset)
{
throw new ArgumentOutOfRangeException("value");
}
_dateParseHandling = value;
}
}
public FloatParseHandling FloatParseHandling
{
get
{
return _floatParseHandling;
}
set
{
if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal)
{
throw new ArgumentOutOfRangeException("value");
}
_floatParseHandling = value;
}
}
public string? DateFormatString
{
get
{
return _dateFormatString;
}
set
{
_dateFormatString = value;
}
}
public int? MaxDepth
{
get
{
return _maxDepth;
}
set
{
if (value <= 0)
{
throw new ArgumentException("Value must be positive.", "value");
}
_maxDepth = value;
}
}
public virtual JsonToken TokenType => _tokenType;
public virtual object? Value => _value;
public virtual Type? ValueType => _value?.GetType();
public virtual int Depth
{
get
{
int num = _stack?.Count ?? 0;
if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
{
return num;
}
return num + 1;
}
}
public virtual string Path
{
get
{
if (_currentPosition.Type == JsonContainerType.None)
{
return string.Empty;
}
JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null);
return JsonPosition.BuildPath(_stack, currentPosition);
}
}
public CultureInfo Culture
{
get
{
return _culture ?? CultureInfo.InvariantCulture;
}
set
{
_culture = value;
}
}
public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync();
}
public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken))
{
if (TokenType == JsonToken.PropertyName)
{
await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
}
if (JsonTokenUtils.IsStartToken(TokenType))
{
int depth = Depth;
while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth)
{
}
}
}
internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken)
{
if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
{
throw CreateUnexpectedEndException();
}
}
public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean());
}
public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes());
}
internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken)
{
List<byte> buffer = new List<byte>();
do
{
if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
{
SetToken(JsonToken.None);
}
}
while (!ReadArrayElementIntoByteArrayReportDone(buffer));
byte[] array = buffer.ToArray();
SetToken(JsonToken.Bytes, array, updateIndex: false);
return array;
}
public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime());
}
public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset());
}
public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal());
}
public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(ReadAsDouble());
}
public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32());
}
public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString());
}
internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken)
{
bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
if (flag)
{
flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
}
return flag;
}
internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken)
{
JsonToken tokenType = TokenType;
if (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
{
return MoveToContentFromNonContentAsync(cancellationToken);
}
return AsyncUtils.True;
}
private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken)
{
JsonToken tokenType;
do
{
if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)))
{
return false;
}
tokenType = TokenType;
}
while (tokenType == JsonToken.None || tokenType == JsonToken.Comment);
return true;
}
internal JsonPosition GetPosition(int depth)
{
if (_stack != null && depth < _stack.Count)
{
return _stack[depth];
}
return _currentPosition;
}
protected JsonReader()
{
_currentState = State.Start;
_dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
_dateParseHandling = DateParseHandling.DateTime;
_floatParseHandling = FloatParseHandling.Double;
_maxDepth = 64;
CloseInput = true;
}
private void Push(JsonContainerType value)
{
UpdateScopeWithFinishedValue();
if (_currentPosition.Type == JsonContainerType.None)
{
_currentPosition = new JsonPosition(value);
return;
}
if (_stack == null)
{
_stack = new List<JsonPosition>();
}
_stack.Add(_currentPosition);
_currentPosition = new JsonPosition(value);
if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth)
{
return;
}
_hasExceededMaxDepth = true;
throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
}
private JsonContainerType Pop()
{
JsonPosition currentPosition;
if (_stack != null && _stack.Count > 0)
{
currentPosition = _currentPosition;
_currentPosition = _stack[_stack.Count - 1];
_stack.RemoveAt(_stack.Count - 1);
}
else
{
currentPosition = _currentPosition;
_currentPosition = default(JsonPosition);
}
if (_maxDepth.HasValue && Depth <= _maxDepth)
{
_hasExceededMaxDepth = false;
}
return currentPosition.Type;
}
private JsonContainerType Peek()
{
return _currentPosition.Type;
}
public abstract bool Read();
public virtual int? ReadAsInt32()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
{
object value = Value;
if (value is int)
{
return (int)value;
}
int num;
if (value is BigInteger bigInteger)
{
num = (int)bigInteger;
}
else
{
try
{
num = Convert.ToInt32(value, CultureInfo.InvariantCulture);
}
catch (Exception ex)
{
throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
}
}
SetToken(JsonToken.Integer, num, updateIndex: false);
return num;
}
case JsonToken.String:
{
string s = (string)Value;
return ReadInt32String(s);
}
default:
throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal int? ReadInt32String(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (int.TryParse(s, NumberStyles.Integer, Culture, out var result))
{
SetToken(JsonToken.Integer, result, updateIndex: false);
return result;
}
SetToken(JsonToken.String, s, updateIndex: false);
throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
public virtual string? ReadAsString()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.String:
return (string)Value;
default:
if (JsonTokenUtils.IsPrimitiveToken(contentToken))
{
object value = Value;
if (value != null)
{
string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture));
SetToken(JsonToken.String, text, updateIndex: false);
return text;
}
}
throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
public virtual byte[]? ReadAsBytes()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.StartObject:
{
ReadIntoWrappedTypeObject();
byte[] array2 = ReadAsBytes();
ReaderReadAndAssert();
if (TokenType != JsonToken.EndObject)
{
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
SetToken(JsonToken.Bytes, array2, updateIndex: false);
return array2;
}
case JsonToken.String:
{
string text = (string)Value;
Guid g;
byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray()));
SetToken(JsonToken.Bytes, array3, updateIndex: false);
return array3;
}
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Bytes:
if (Value is Guid guid)
{
byte[] array = guid.ToByteArray();
SetToken(JsonToken.Bytes, array, updateIndex: false);
return array;
}
return (byte[])Value;
case JsonToken.StartArray:
return ReadArrayIntoByteArray();
default:
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal byte[] ReadArrayIntoByteArray()
{
List<byte> list = new List<byte>();
do
{
if (!Read())
{
SetToken(JsonToken.None);
}
}
while (!ReadArrayElementIntoByteArrayReportDone(list));
byte[] array = list.ToArray();
SetToken(JsonToken.Bytes, array, updateIndex: false);
return array;
}
private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer)
{
switch (TokenType)
{
case JsonToken.None:
throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
case JsonToken.Integer:
buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
return false;
case JsonToken.EndArray:
return true;
case JsonToken.Comment:
return false;
default:
throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
}
public virtual double? ReadAsDouble()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
{
object value = Value;
if (value is double)
{
return (double)value;
}
double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger));
SetToken(JsonToken.Float, num, updateIndex: false);
return num;
}
case JsonToken.String:
return ReadDoubleString((string)Value);
default:
throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal double? ReadDoubleString(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result))
{
SetToken(JsonToken.Float, result, updateIndex: false);
return result;
}
SetToken(JsonToken.String, s, updateIndex: false);
throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
public virtual bool? ReadAsBoolean()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
{
bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L));
SetToken(JsonToken.Boolean, flag, updateIndex: false);
return flag;
}
case JsonToken.String:
return ReadBooleanString((string)Value);
case JsonToken.Boolean:
return (bool)Value;
default:
throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal bool? ReadBooleanString(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (bool.TryParse(s, out var result))
{
SetToken(JsonToken.Boolean, result, updateIndex: false);
return result;
}
SetToken(JsonToken.String, s, updateIndex: false);
throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
public virtual decimal? ReadAsDecimal()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Integer:
case JsonToken.Float:
{
object value = Value;
if (value is decimal)
{
return (decimal)value;
}
decimal num;
if (value is BigInteger bigInteger)
{
num = (decimal)bigInteger;
}
else
{
try
{
num = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
}
catch (Exception ex)
{
throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex);
}
}
SetToken(JsonToken.Float, num, updateIndex: false);
return num;
}
case JsonToken.String:
return ReadDecimalString((string)Value);
default:
throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal decimal? ReadDecimalString(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result))
{
SetToken(JsonToken.Float, result, updateIndex: false);
return result;
}
if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success)
{
SetToken(JsonToken.Float, result, updateIndex: false);
return result;
}
SetToken(JsonToken.String, s, updateIndex: false);
throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
public virtual DateTime? ReadAsDateTime()
{
switch (GetContentToken())
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Date:
if (Value is DateTimeOffset dateTimeOffset)
{
SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false);
}
return (DateTime)Value;
case JsonToken.String:
return ReadDateTimeString((string)Value);
default:
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
}
}
internal DateTime? ReadDateTimeString(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, updateIndex: false);
return dt;
}
if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
SetToken(JsonToken.Date, dt, updateIndex: false);
return dt;
}
throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
public virtual DateTimeOffset? ReadAsDateTimeOffset()
{
JsonToken contentToken = GetContentToken();
switch (contentToken)
{
case JsonToken.None:
case JsonToken.Null:
case JsonToken.EndArray:
return null;
case JsonToken.Date:
if (Value is DateTime dateTime)
{
SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false);
}
return (DateTimeOffset)Value;
case JsonToken.String:
{
string s = (string)Value;
return ReadDateTimeOffsetString(s);
}
default:
throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken));
}
}
internal DateTimeOffset? ReadDateTimeOffsetString(string? s)
{
if (StringUtils.IsNullOrEmpty(s))
{
SetToken(JsonToken.Null, null, updateIndex: false);
return null;
}
if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt))
{
SetToken(JsonToken.Date, dt, updateIndex: false);
return dt;
}
if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, updateIndex: false);
return dt;
}
SetToken(JsonToken.String, s, updateIndex: false);
throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s));
}
internal void ReaderReadAndAssert()
{
if (!Read())
{
throw CreateUnexpectedEndException();
}
}
internal JsonReaderException CreateUnexpectedEndException()
{
return JsonReaderException.Create(this, "Unexpected end when reading JSON.");
}
internal void ReadIntoWrappedTypeObject()
{
ReaderReadAndAssert();
if (Value != null && Value.ToString() == "$type")
{
ReaderReadAndAssert();
if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal))
{
ReaderReadAndAssert();
if (Value.ToString() == "$value")
{
return;
}
}
}
throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
}
public void Skip()
{
if (TokenType == JsonToken.PropertyName)
{
Read();
}
if (JsonTokenUtils.IsStartToken(TokenType))
{
int depth = Depth;
while (Read() && depth < Depth)
{
}
}
}
protected void SetToken(JsonToken newToken)
{
SetToken(newToken, null, updateIndex: true);
}
protected void SetToken(JsonToken newToken, object? value)
{
SetToken(newToken, value, updateIndex: true);
}
protected void SetToken(JsonToken newToken, object? value, bool updateIndex)
{
_tokenType = newToken;
_value = value;
switch (newToken)
{
case JsonToken.StartObject:
_currentState = State.ObjectStart;
Push(JsonContainerType.Object);
break;
case JsonToken.StartArray:
_currentState = State.ArrayStart;
Push(JsonContainerType.Array);
break;
case JsonToken.StartConstructor:
_currentState = State.ConstructorStart;
Push(JsonContainerType.Constructor);
break;
case JsonToken.EndObject:
ValidateEnd(JsonToken.EndObject);
break;
case JsonToken.EndArray:
ValidateEnd(JsonToken.EndArray);
break;
case JsonToken.EndConstructor:
ValidateEnd(JsonToken.EndConstructor);
break;
case JsonToken.PropertyName:
_currentState = State.Property;
_currentPosition.PropertyName = (string)value;
break;
case JsonToken.Raw:
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Undefined:
case JsonToken.Date:
case JsonToken.Bytes:
SetPostValueState(updateIndex);
break;
case JsonToken.Comment:
break;
}
}
internal void SetPostValueState(bool updateIndex)
{
if (Peek() != 0 || SupportMultipleContent)
{
_currentState = State.PostValue;
}
else
{
SetFinished();
}
if (updateIndex)
{
UpdateScopeWithFinishedValue();
}
}
private void UpdateScopeWithFinishedValue()
{
if (_currentPosition.HasIndex)
{
_currentPosition.Position++;
}
}
private void ValidateEnd(JsonToken endToken)
{
JsonContainerType jsonContainerType = Pop();
if (GetTypeForCloseToken(endToken) != jsonContainerType)
{
throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType));
}
if (Peek() != 0 || SupportMultipleContent)
{
_currentState = State.PostValue;
}
else
{
SetFinished();
}
}
protected void SetStateBasedOnCurrent()
{
JsonContainerType jsonContainerType = Peek();
switch (jsonContainerType)
{
case JsonContainerType.Object:
_currentState = State.Object;
break;
case JsonContainerType.Array:
_currentState = State.Array;
break;
case JsonContainerType.Constructor:
_currentState = State.Constructor;
break;
case JsonContainerType.None:
SetFinished();
break;
default:
throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType));
}
}
private void SetFinished()
{
_currentState = ((!SupportMultipleContent) ? State.Finished : State.Start);
}
private JsonContainerType GetTypeForCloseToken(JsonToken token)
{
return token switch
{
JsonToken.EndObject => JsonContainerType.Object,
JsonToken.EndArray => JsonContainerType.Array,
JsonToken.EndConstructor => JsonContainerType.Constructor,
_ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)),
};
}
void IDisposable.Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_currentState != State.Closed && disposing)
{
Close();
}
}
public virtual void Close()
{
_currentState = State.Closed;
_tokenType = JsonToken.None;
_value = null;
}
internal void ReadAndAssert()
{
if (!Read())
{
throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
}
}
internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter)
{
if (!ReadForType(contract, hasConverter))
{
throw JsonSerializationException.Create(this, "Unexpected end when reading JSON.");
}
}
internal bool ReadForType(JsonContract? contract, bool hasConverter)
{
if (hasConverter)
{
return Read();
}
switch (contract?.InternalReadType ?? ReadType.Read)
{
case ReadType.Read:
return ReadAndMoveToContent();
case ReadType.ReadAsInt32:
ReadAsInt32();
break;
case ReadType.ReadAsInt64:
{
bool result = ReadAndMoveToContent();
if (TokenType == JsonToken.Undefined)
{
throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long)));
}
return result;
}
case ReadType.ReadAsDecimal:
ReadAsDecimal();
break;
case ReadType.ReadAsDouble:
ReadAsDouble();
break;
case ReadType.ReadAsBytes:
ReadAsBytes();
break;
case ReadType.ReadAsBoolean:
ReadAsBoolean();
break;
case ReadType.ReadAsString:
ReadAsString();
break;
case ReadType.ReadAsDateTime:
ReadAsDateTime();
break;
case ReadType.ReadAsDateTimeOffset:
ReadAsDateTimeOffset();
break;
default:
throw new ArgumentOutOfRangeException();
}
return TokenType != JsonToken.None;
}
internal bool ReadAndMoveToContent()
{
if (Read())
{
return MoveToContent();
}
return false;
}
internal bool MoveToContent()
{
JsonToken tokenType = TokenType;
while (tokenType == JsonToken.None || tokenType == JsonToken.Comment)
{
if (!Read())
{
return false;
}
tokenType = TokenType;
}
return true;
}
private JsonToken GetContentToken()
{
JsonToken tokenType;
do
{
if (!Read())
{
SetToken(JsonToken.None);
return JsonToken.None;
}
tokenType = TokenType;
}
while (tokenType == JsonToken.Comment);
return tokenType;
}
}
[Serializable]
public class JsonReaderException : JsonException
{
public int LineNumber { get; }
public int LinePosition { get; }
public string? Path { get; }
public JsonReaderException()
{
}
public JsonReaderException(string message)
: base(message)
{
}
public JsonReaderException(string message, Exception innerException)
: base(message, innerException)
{
}
public JsonReaderException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
: base(message, innerException)
{
Path = path;
LineNumber = lineNumber;
LinePosition = linePosition;
}
internal static JsonReaderException Create(JsonReader reader, string message)
{
return Create(reader, message, null);
}
internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex)
{
return Create(reader as IJsonLineInfo, reader.Path, message, ex);
}
internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
{
message = JsonPosition.FormatMessage(lineInfo, path, message);
int lineNumber;
int linePosition;
if (lineInfo != null && lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
linePosition = lineInfo.LinePosition;
}
else
{
lineNumber = 0;
linePosition = 0;
}
return new JsonReaderException(message, path, lineNumber, linePosition, ex);
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public sealed class JsonRequiredAttribute : Attribute
{
}
[Serializable]
public class JsonSerializationException : JsonException
{
public int LineNumber { get; }
public int LinePosition { get; }
public string? Path { get; }
public JsonSerializationException()
{
}
public JsonSerializationException(string message)
: base(message)
{
}
public JsonSerializationException(string message, Exception innerException)
: base(message, innerException)
{
}
public JsonSerializationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException)
: base(message, innerException)
{
Path = path;
LineNumber = lineNumber;
LinePosition = linePosition;
}
internal static JsonSerializationException Create(JsonReader reader, string message)
{
return Create(reader, message, null);
}
internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex)
{
return Create(reader as IJsonLineInfo, reader.Path, message, ex);
}
internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex)
{
message = JsonPosition.FormatMessage(lineInfo, path, message);
int lineNumber;
int linePosition;
if (lineInfo != null && lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
linePosition = lineInfo.LinePosition;
}
else
{
lineNumber = 0;
linePosition = 0;
}
return new JsonSerializationException(message, path, lineNumber, linePosition, ex);
}
}
public class JsonSerializer
{
internal TypeNameHandling _typeNameHandling;
internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling;
internal PreserveReferencesHandling _preserveReferencesHandling;
internal ReferenceLoopHandling _referenceLoopHandling;
internal MissingMemberHandling _missingMemberHandling;
internal ObjectCreationHandling _objectCreationHandling;
internal NullValueHandling _nullValueHandling;
internal DefaultValueHandling _defaultValueHandling;
internal ConstructorHandling _constructorHandling;
internal MetadataPropertyHandling _metadataPropertyHandling;
internal JsonConverterCollection? _converters;
internal IContractResolver _contractResolver;
internal ITraceWriter? _traceWriter;
internal IEqualityComparer? _equalityComparer;
internal ISerializationBinder _serializationBinder;
internal StreamingContext _context;
private IReferenceResolver? _referenceResolver;
private Formatting? _formatting;
private DateFormatHandling? _dateFormatHandling;
private DateTimeZoneHandling? _dateTimeZoneHandling;
private DateParseHandling? _dateParseHandling;
private FloatFormatHandling? _floatFormatHandling;
private FloatParseHandling? _floatParseHandling;
private StringEscapeHandling? _stringEscapeHandling;
private CultureInfo _culture;
private int? _maxDepth;
private bool _maxDepthSet;
private bool? _checkAdditionalContent;
private string? _dateFormatString;
private bool _dateFormatStringSet;
public virtual IReferenceResolver? ReferenceResolver
{
get
{
return GetReferenceResolver();
}
set
{
if (value == null)
{
throw new ArgumentNullException("value", "Reference resolver cannot be null.");
}
_referenceResolver = value;
}
}
[Obsolete("Binder is obsolete. Use SerializationBinder instead.")]
public virtual SerializationBinder Binder
{
get
{
if (_serializationBinder is SerializationBinder result)
{
return result;
}
if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter)
{
return serializationBinderAdapter.SerializationBinder;
}
throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set.");
}
set
{
if (value == null)
{
throw new ArgumentNullException("value", "Serialization binder cannot be null.");
}
_serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value);
}
}
public virtual ISerializationBinder SerializationBinder
{
get
{
return _serializationBinder;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value", "Serialization binder cannot be null.");
}
_serializationBinder = value;
}
}
public virtual ITraceWriter? TraceWriter
{
get
{
return _traceWriter;
}
set
{
_traceWriter = value;
}
}
public virtual IEqualityComparer? EqualityComparer
{
get
{
return _equalityComparer;
}
set
{
_equalityComparer = value;
}
}
public virtual TypeNameHandling TypeNameHandling
{
get
{
return _typeNameHandling;
}
set
{
if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
{
throw new ArgumentOutOfRangeException("value");
}
_typeNameHandling = value;
}
}
[Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")]
public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
{
get
{
return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling;
}
set
{
if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
{
throw new ArgumentOutOfRangeException("value");
}
_typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value;
}
}
public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling
{
get
{
return _typeNameAssemblyFormatHandling;
}
set
{
if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full)
{
throw new ArgumentOutOfRangeException("value");
}
_typeNameAssemblyFormatHandling = value;
}
}
public virtual PreserveReferencesHandling PreserveReferencesHandling
{
get
{
return _preserveReferencesHandling;
}
set
{
if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
{
throw new ArgumentOutOfRangeException("value");
}
_preserveReferencesHandling = value;
}
}
public virtual ReferenceLoopHandling ReferenceLoopHandling
{
get
{
return _referenceLoopHandling;
}
set
{
if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
{
throw new ArgumentOutOfRangeException("value");
}
_referenceLoopHandling = value;
}
}
public virtual MissingMemberHandling MissingMemberHandling
{
get
{
return _missingMemberHandling;
}
set
{
if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
{
throw new ArgumentOutOfRangeException("value");
}
_missingMemberHandling = value;
}
}
public virtual NullValueHandling NullValueHandling
{
get
{
return _nullValueHandling;
}
set
{
if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
{
throw new ArgumentOutOfRangeException("value");
}
_nullValueHandling = value;
}
}
public virtual DefaultValueHandling DefaultValueHandling
{
get
{
return _defaultValueHandling;
}
set
{
if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
{
throw new ArgumentOutOfRangeException("value");
}
_defaultValueHandling = value;
}
}
public virtual ObjectCreationHandling ObjectCreationHandling
{
get
{
return _objectCreationHandling;
}
set
{
if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
{
throw new ArgumentOutOfRangeException("value");
}
_objectCreationHandling = value;
}
}
public virtual ConstructorHandling ConstructorHandling
{
get
{
return _constructorHandling;
}
set
{
if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
{
throw new ArgumentOutOfRangeException("value");
}
_constructorHandling = value;
}
}
public virtual MetadataPropertyHandling MetadataPropertyHandling
{
get
{
return _metadataPropertyHandling;
}
set
{
if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore)
{
throw new ArgumentOutOfRangeException("value");
}
_metadataPropertyHandling = value;
}
}
public virtual JsonConverterCollection Converters
{
get
{
if (_converters == null)
{
_converters = new JsonConverterCollection();
}
return _converters;
}
}
public virtual IContractResolver ContractResolver
{
get
{
return _contractResolver;
}
set
{
_contractResolver = value ?? DefaultContractResolver.Instance;
}
}
public virtual StreamingContext Context
{
get
{
return _context;
}
set
{
_context = value;
}
}
public virtual Formatting Formatting
{
get
{
return _formatting.GetValueOrDefault();
}
set
{
_formatting = value;
}
}
public virtual DateFormatHandling DateFormatHandling
{
get
{
return _dateFormatHandling.GetValueOrDefault();
}
set
{
_dateFormatHandling = value;
}
}
public virtual DateTimeZoneHandling DateTimeZoneHandling
{
get
{
return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind;
}
set
{
_dateTimeZoneHandling = value;
}
}
public virtual DateParseHandling DateParseHandling
{
get
{
return _dateParseHandling ?? DateParseHandling.DateTime;
}
set
{
_dateParseHandling = value;
}
}
public virtual FloatParseHandling FloatParseHandling
{
get
{
return _floatParseHandling.GetValueOrDefault();
}
set
{
_floatParseHandling = value;
}
}
public virtual FloatFormatHandling FloatFormatHandling
{
get
{
return _floatFormatHandling.GetValueOrDefault();
}
set
{
_floatFormatHandling = value;
}
}
public virtual StringEscapeHandling StringEscapeHandling
{
get
{
return _stringEscapeHandling.GetValueOrDefault();
}
set
{
_stringEscapeHandling = value;
}
}
public virtual string DateFormatString
{
get
{
return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
}
set
{
_dateFormatString = value;
_dateFormatStringSet = true;
}
}
public virtual CultureInfo Culture
{
get
{
return _culture ?? JsonSerializerSettings.DefaultCulture;
}
set
{
_culture = value;
}
}
public virtual int? MaxDepth
{
get
{
return _maxDepth;
}
set
{
if (value <= 0)
{
throw new ArgumentException("Value must be positive.", "value");
}
_maxDepth = value;
_maxDepthSet = true;
}
}
public virtual bool CheckAdditionalContent
{
get
{
return _checkAdditionalContent.GetValueOrDefault();
}
set
{
_checkAdditionalContent = value;
}
}
public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error;
internal bool IsCheckAdditionalContentSet()
{
return _checkAdditionalContent.HasValue;
}
public JsonSerializer()
{
_referenceLoopHandling = ReferenceLoopHandling.Error;
_missingMemberHandling = MissingMemberHandling.Ignore;
_nullValueHandling = NullValueHandling.Include;
_defaultValueHandling = DefaultValueHandling.Include;
_objectCreationHandling = ObjectCreationHandling.Auto;
_preserveReferencesHandling = PreserveReferencesHandling.None;
_constructorHandling = ConstructorHandling.Default;
_typeNameHandling = TypeNameHandling.None;
_metadataPropertyHandling = MetadataPropertyHandling.Default;
_context = JsonSerializerSettings.DefaultContext;
_serializationBinder = DefaultSerializationBinder.Instance;
_culture = JsonSerializerSettings.DefaultCulture;
_contractResolver = DefaultContractResolver.Instance;
}
public static JsonSerializer Create()
{
return new JsonSerializer();
}
public static JsonSerializer Create(JsonSerializerSettings? settings)
{
JsonSerializer jsonSerializer = Create();
if (settings != null)
{
ApplySerializerSettings(jsonSerializer, settings);
}
return jsonSerializer;
}
public static JsonSerializer CreateDefault()
{
return Create(JsonConvert.DefaultSettings?.Invoke());
}
public static JsonSerializer CreateDefault(JsonSerializerSettings? settings)
{
JsonSerializer jsonSerializer = CreateDefault();
if (settings != null)
{
ApplySerializerSettings(jsonSerializer, settings);
}
return jsonSerializer;
}
private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
{
if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
{
for (int i = 0; i < settings.Converters.Count; i++)
{
serializer.Converters.Insert(i, settings.Converters[i]);
}
}
if (settings._typeNameHandling.HasValue)
{
serializer.TypeNameHandling = settings.TypeNameHandling;
}
if (settings._metadataPropertyHandling.HasValue)
{
serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
}
if (settings._typeNameAssemblyFormatHandling.HasValue)
{
serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling;
}
if (settings._preserveReferencesHandling.HasValue)
{
serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
}
if (settings._referenceLoopHandling.HasValue)
{
serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
}
if (settings._missingMemberHandling.HasValue)
{
serializer.MissingMemberHandling = settings.MissingMemberHandling;
}
if (settings._objectCreationHandling.HasValue)
{
serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
}
if (settings._nullValueHandling.HasValue)
{
serializer.NullValueHandling = settings.NullValueHandling;
}
if (settings._defaultValueHandling.HasValue)
{
serializer.DefaultValueHandling = settings.DefaultValueHandling;
}
if (settings._constructorHandling.HasValue)
{
serializer.ConstructorHandling = settings.ConstructorHandling;
}
if (settings._context.HasValue)
{
serializer.Context = settings.Context;
}
if (settings._checkAdditionalContent.HasValue)
{
serializer._checkAdditionalContent = settings._checkAdditionalContent;
}
if (settings.Error != null)
{
serializer.Error += settings.Error;
}
if (settings.ContractResolver != null)
{
serializer.ContractResolver = settings.ContractResolver;
}
if (settings.ReferenceResolverProvider != null)
{
serializer.ReferenceResolver = settings.ReferenceResolverProvider();
}
if (settings.TraceWriter != null)
{
serializer.TraceWriter = settings.TraceWriter;
}
if (settings.EqualityComparer != null)
{
serializer.EqualityComparer = settings.EqualityComparer;
}
if (settings.SerializationBinder != null)
{
serializer.SerializationBinder = settings.SerializationBinder;
}
if (settings._formatting.HasValue)
{
serializer._formatting = settings._formatting;
}
if (settings._dateFormatHandling.HasValue)
{
serializer._dateFormatHandling = settings._dateFormatHandling;
}
if (settings._dateTimeZoneHandling.HasValue)
{
serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
}
if (settings._dateParseHandling.HasValue)
{
serializer._dateParseHandling = settings._dateParseHandling;
}
if (settings._dateFormatStringSet)
{
serializer._dateFormatString = settings._dateFormatString;
serializer._dateFormatStringSet = settings._dateFormatStringSet;
}
if (settings._floatFormatHandling.HasValue)
{
serializer._floatFormatHandling = settings._floatFormatHandling;
}
if (settings._floatParseHandling.HasValue)
{
serializer._floatParseHandling = settings._floatParseHandling;
}
if (settings._stringEscapeHandling.HasValue)
{
serializer._stringEscapeHandling = settings._stringEscapeHandling;
}
if (settings._culture != null)
{
serializer._culture = settings._culture;
}
if (settings._maxDepthSet)
{
serializer._maxDepth = settings._maxDepth;
serializer._maxDepthSet = settings._maxDepthSet;
}
}
[DebuggerStepThrough]
public void Populate(TextReader reader, object target)
{
Populate(new JsonTextReader(reader), target);
}
[DebuggerStepThrough]
public void Populate(JsonReader reader, object target)
{
PopulateInternal(reader, target);
}
internal virtual void PopulateInternal(JsonReader reader, object target)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
ValidationUtils.ArgumentNotNull(target, "target");
SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target);
if (traceJsonReader != null)
{
TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
}
ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
}
[DebuggerStepThrough]
public object? Deserialize(JsonReader reader)
{
return Deserialize(reader, null);
}
[DebuggerStepThrough]
public object? Deserialize(TextReader reader, Type objectType)
{
return Deserialize(new JsonTextReader(reader), objectType);
}
[DebuggerStepThrough]
public T? Deserialize<T>(JsonReader reader)
{
return (T)Deserialize(reader, typeof(T));
}
[DebuggerStepThrough]
public object? Deserialize(JsonReader reader, Type? objectType)
{
return DeserializeInternal(reader, objectType);
}
internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType)
{
ValidationUtils.ArgumentNotNull(reader, "reader");
SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString);
TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null);
object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
if (traceJsonReader != null)
{
TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null);
}
ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString);
return result;
}
internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString)
{
if (_culture != null && !_culture.Equals(reader.Culture))
{
previousCulture = reader.Culture;
reader.Culture = _culture;
}
else
{
previousCulture = null;
}
if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
{
previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
}
else
{
previousDateTimeZoneHandling = null;
}
if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling)
{
previousDateParseHandling = reader.DateParseHandling;
reader.DateParseHandling = _dateParseHandling.GetValueOrDefault();
}
else
{
previousDateParseHandling = null;
}
if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling)
{
previousFloatParseHandling = reader.FloatParseHandling;
reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault();
}
else
{
previousFloatParseHandling = null;
}
if (_maxDepthSet && reader.MaxDepth != _maxDepth)
{
previousMaxDepth = reader.MaxDepth;
reader.MaxDepth = _maxDepth;
}
else
{
previousMaxDepth = null;
}
if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
{
previousDateFormatString = reader.DateFormatString;
reader.DateFormatString = _dateFormatString;
}
else
{
previousDateFormatString = null;
}
if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver)
{
jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable();
}
}
private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString)
{
if (previousCulture != null)
{
reader.Culture = previousCulture;
}
if (previousDateTimeZoneHandling.HasValue)
{
reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault();
}
if (previousDateParseHandling.HasValue)
{
reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault();
}
if (previousFloatParseHandling.HasValue)
{
reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault();
}
if (_maxDepthSet)
{
reader.MaxDepth = previousMaxDepth;
}
if (_dateFormatStringSet)
{
reader.DateFormatString = previousDateFormatString;
}
if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable())
{
jsonTextReader.PropertyNameTable = null;
}
}
public void Serialize(TextWriter textWriter, object? value)
{
Serialize(new JsonTextWriter(textWriter), value);
}
public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType)
{
SerializeInternal(jsonWriter, value, objectType);
}
public void Serialize(TextWriter textWriter, object? value, Type objectType)
{
Serialize(new JsonTextWriter(textWriter), value, objectType);
}
public void Serialize(JsonWriter jsonWriter, object? value)
{
SerializeInternal(jsonWriter, value, null);
}
private TraceJsonReader CreateTraceJsonReader(JsonReader reader)
{
TraceJsonReader traceJsonReader = new TraceJsonReader(reader);
if (reader.TokenType != 0)
{
traceJsonReader.WriteCurrentToken();
}
return traceJsonReader;
}
internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType)
{
ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
Formatting? formatting = null;
if (_formatting.HasValue && jsonWriter.Formatting != _formatting)
{
formatting = jsonWriter.Formatting;
jsonWriter.Formatting = _formatting.GetValueOrDefault();
}
DateFormatHandling? dateFormatHandling = null;
if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling)
{
dateFormatHandling = jsonWriter.DateFormatHandling;
jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault();
}
DateTimeZoneHandling? dateTimeZoneHandling = null;
if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling)
{
dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling;
jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault();
}
FloatFormatHandling? floatFormatHandling = null;
if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling)
{
floatFormatHandling = jsonWriter.FloatFormatHandling;
jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault();
}
StringEscapeHandling? stringEscapeHandling = null;
if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling)
{
stringEscapeHandling = jsonWriter.StringEscapeHandling;
jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault();
}
CultureInfo cultureInfo = null;
if (_culture != null && !_culture.Equals(jsonWriter.Culture))
{
cultureInfo = jsonWriter.Culture;
jsonWriter.Culture = _culture;
}
string dateFormatString = null;
if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
{
dateFormatString = jsonWriter.DateFormatString;
jsonWriter.DateFormatString = _dateFormatString;
}
TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null);
new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType);
if (traceJsonWriter != null)
{
TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null);
}
if (formatting.HasValue)
{
jsonWriter.Formatting = formatting.GetValueOrDefault();
}
if (dateFormatHandling.HasValue)
{
jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault();
}
if (dateTimeZoneHandling.HasValue)
{
jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault();
}
if (floatFormatHandling.HasValue)
{
jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault();
}
if (stringEscapeHandling.HasValue)
{
jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault();
}
if (_dateFormatStringSet)
{
jsonWriter.DateFormatString = dateFormatString;
}
if (cultureInfo != null)
{
jsonWriter.Culture = cultureInfo;
}
}
internal IReferenceResolver GetReferenceResolver()
{
if (_referenceResolver == null)
{
_referenceResolver = new DefaultReferenceResolver();
}
return _referenceResolver;
}
internal JsonConverter? GetMatchingConverter(Type type)
{
return GetMatchingConverter(_converters, type);
}
internal static JsonConverter? GetMatchingConverter(IList<JsonConverter>? converters, Type objectType)
{
if (converters != null)
{
for (int i = 0; i < converters.Count; i++)
{
JsonConverter jsonConverter = converters[i];
if (jsonConverter.CanConvert(objectType))
{
return jsonConverter;
}
}
}
return null;
}
internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e)
{
this.Error?.Invoke(this, e);
}
}
public class JsonSerializerSettings
{
internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error;
internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore;
internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include;
internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include;
internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto;
internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None;
internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default;
internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;
internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default;
internal static readonly StreamingContext DefaultContext;
internal const Formatting DefaultFormatting = Formatting.None;
internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;
internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;
internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double;
internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String;
internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default;
internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple;
internal static readonly CultureInfo DefaultCulture;
internal const bool DefaultCheckAdditionalContent = false;
internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
internal const int DefaultMaxDepth = 64;
internal Formatting? _formatting;
internal DateFormatHandling? _dateFormatHandling;
internal DateTimeZoneHandling? _dateTimeZoneHandling;
internal DateParseHandling? _dateParseHandling;
internal FloatFormatHandling? _floatFormatHandling;
internal FloatParseHandling? _floatParseHandling;
internal StringEscapeHandling? _stringEscapeHandling;
internal CultureInfo? _culture;
internal bool? _checkAdditionalContent;
internal int? _maxDepth;
internal bool _maxDepthSet;
internal string? _dateFormatString;
internal bool _dateFormatStringSet;
internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling;
internal DefaultValueHandling? _defaultValueHandling;
internal PreserveReferencesHandling? _preserveReferencesHandling;
internal NullValueHandling? _nullValueHandling;
internal ObjectCreationHandling? _objectCreationHandling;
internal MissingMemberHandling? _missingMemberHandling;
internal ReferenceLoopHandling? _referenceLoopHandling;
internal StreamingContext? _context;
internal ConstructorHandling? _constructorHandling;
internal TypeNameHandling? _typeNameHandling;
internal MetadataPropertyHandling? _metadataPropertyHandling;
public ReferenceLoopHandling ReferenceLoopHandling
{
get
{
return _referenceLoopHandling.GetValueOrDefault();
}
set
{
_referenceLoopHandling = value;
}
}
public MissingMemberHandling MissingMemberHandling
{
get
{
return _missingMemberHandling.GetValueOrDefault();
}
set
{
_missingMemberHandling = value;
}
}
public ObjectCreationHandling ObjectCreationHandling
{
get
{
return _objectCreationHandling.GetValueOrDefault();
}
set
{
_objectCreationHandling = value;
}
}
public NullValueHandling NullValueHandling
{
get
{
return _nullValueHandling.GetValueOrDefault();
}
set
{
_nullValueHandling = value;
}
}
public DefaultValueHandling DefaultValueHandling
{
get
{
return _defaultValueHandling.GetValueOrDefault();
}
set
{
_defaultValueHandling = value;
}
}
public IList<JsonConverter> Converters { get; set; }
public PreserveReferencesHandling PreserveReferencesHandling
{
get
{
return _preserveReferencesHandling.GetValueOrDef
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Tommy.Extensions")]
[assembly: InternalsVisibleTo("Tommy.Tests")]
[assembly: AssemblyCompany("Denis Zhidkikh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2021 Denis Zhidkikh")]
[assembly: AssemblyDescription("\r\n A simple TOML parser and writer inspired by SimpleJSON.\r\n Provides minimal and simple API for parsing and writing TOML files.\r\n Compliant with TOML 1.0.0 format spec.\r\n ")]
[assembly: AssemblyFileVersion("3.1.2.0")]
[assembly: AssemblyInformationalVersion("3.1.2")]
[assembly: AssemblyProduct("Tommy")]
[assembly: AssemblyTitle("Tommy")]
[assembly: AssemblyVersion("3.1.2.0")]
namespace Tommy;
public abstract class TomlNode : IEnumerable
{
public virtual bool HasValue { get; }
public virtual bool IsArray { get; }
public virtual bool IsTable { get; }
public virtual bool IsString { get; }
public virtual bool IsInteger { get; }
public virtual bool IsFloat { get; }
public bool IsDateTime
{
get
{
if (!IsDateTimeLocal)
{
return IsDateTimeOffset;
}
return true;
}
}
public virtual bool IsDateTimeLocal { get; }
public virtual bool IsDateTimeOffset { get; }
public virtual bool IsBoolean { get; }
public virtual string Comment { get; set; }
public virtual int CollapseLevel { get; set; }
public virtual TomlTable AsTable => this as TomlTable;
public virtual TomlString AsString => this as TomlString;
public virtual TomlInteger AsInteger => this as TomlInteger;
public virtual TomlFloat AsFloat => this as TomlFloat;
public virtual TomlBoolean AsBoolean => this as TomlBoolean;
public virtual TomlDateTimeLocal AsDateTimeLocal => this as TomlDateTimeLocal;
public virtual TomlDateTimeOffset AsDateTimeOffset => this as TomlDateTimeOffset;
public virtual TomlDateTime AsDateTime => this as TomlDateTime;
public virtual TomlArray AsArray => this as TomlArray;
public virtual int ChildrenCount => 0;
public virtual TomlNode this[string key]
{
get
{
return null;
}
set
{
}
}
public virtual TomlNode this[int index]
{
get
{
return null;
}
set
{
}
}
public virtual IEnumerable<TomlNode> Children
{
get
{
yield break;
}
}
public virtual IEnumerable<string> Keys
{
get
{
yield break;
}
}
public IEnumerator GetEnumerator()
{
return Children.GetEnumerator();
}
public virtual bool TryGetNode(string key, out TomlNode node)
{
node = null;
return false;
}
public virtual bool HasKey(string key)
{
return false;
}
public virtual bool HasItemAt(int index)
{
return false;
}
public virtual void Add(string key, TomlNode node)
{
}
public virtual void Add(TomlNode node)
{
}
public virtual void Delete(TomlNode node)
{
}
public virtual void Delete(string key)
{
}
public virtual void Delete(int index)
{
}
public virtual void AddRange(IEnumerable<TomlNode> nodes)
{
foreach (TomlNode node in nodes)
{
Add(node);
}
}
public virtual void WriteTo(TextWriter tw, string name = null)
{
tw.WriteLine(ToInlineToml());
}
public virtual string ToInlineToml()
{
return ToString();
}
public static implicit operator TomlNode(string value)
{
return new TomlString
{
Value = value
};
}
public static implicit operator TomlNode(bool value)
{
return new TomlBoolean
{
Value = value
};
}
public static implicit operator TomlNode(long value)
{
return new TomlInteger
{
Value = value
};
}
public static implicit operator TomlNode(float value)
{
return new TomlFloat
{
Value = value
};
}
public static implicit operator TomlNode(double value)
{
return new TomlFloat
{
Value = value
};
}
public static implicit operator TomlNode(DateTime value)
{
return new TomlDateTimeLocal
{
Value = value
};
}
public static implicit operator TomlNode(DateTimeOffset value)
{
return new TomlDateTimeOffset
{
Value = value
};
}
public static implicit operator TomlNode(TomlNode[] nodes)
{
TomlArray tomlArray = new TomlArray();
tomlArray.AddRange(nodes);
return tomlArray;
}
public static implicit operator string(TomlNode value)
{
return value.ToString();
}
public static implicit operator int(TomlNode value)
{
return (int)value.AsInteger.Value;
}
public static implicit operator long(TomlNode value)
{
return value.AsInteger.Value;
}
public static implicit operator float(TomlNode value)
{
return (float)value.AsFloat.Value;
}
public static implicit operator double(TomlNode value)
{
return value.AsFloat.Value;
}
public static implicit operator bool(TomlNode value)
{
return value.AsBoolean.Value;
}
public static implicit operator DateTime(TomlNode value)
{
return value.AsDateTimeLocal.Value;
}
public static implicit operator DateTimeOffset(TomlNode value)
{
return value.AsDateTimeOffset.Value;
}
}
public class TomlString : TomlNode
{
public override bool HasValue { get; } = true;
public override bool IsString { get; } = true;
public bool IsMultiline { get; set; }
public bool MultilineTrimFirstLine { get; set; }
public bool PreferLiteral { get; set; }
public string Value { get; set; }
public override string ToString()
{
return Value;
}
public override string ToInlineToml()
{
if (Value.IndexOf(new string('\'', (!IsMultiline) ? 1 : 3), StringComparison.Ordinal) != -1 && PreferLiteral)
{
PreferLiteral = false;
}
string text = new string(PreferLiteral ? '\'' : '"', (!IsMultiline) ? 1 : 3);
string text2 = (PreferLiteral ? Value : Value.Escape(!IsMultiline));
if (IsMultiline)
{
text2 = text2.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
}
if (IsMultiline && (MultilineTrimFirstLine || (!MultilineTrimFirstLine && text2.StartsWith(Environment.NewLine))))
{
text2 = Environment.NewLine + text2;
}
return text + text2 + text;
}
}
public class TomlInteger : TomlNode
{
public enum Base
{
Binary = 2,
Octal = 8,
Decimal = 10,
Hexadecimal = 16
}
public override bool IsInteger { get; } = true;
public override bool HasValue { get; } = true;
public Base IntegerBase { get; set; } = Base.Decimal;
public long Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
public override string ToInlineToml()
{
if (IntegerBase == Base.Decimal)
{
return Value.ToString(CultureInfo.InvariantCulture);
}
return "0" + TomlSyntax.BaseIdentifiers[(int)IntegerBase] + Convert.ToString(Value, (int)IntegerBase);
}
}
public class TomlFloat : TomlNode, IFormattable
{
public override bool IsFloat { get; } = true;
public override bool HasValue { get; } = true;
public double Value { get; set; }
public override string ToString()
{
return Value.ToString(CultureInfo.InvariantCulture);
}
public string ToString(string format, IFormatProvider formatProvider)
{
return Value.ToString(format, formatProvider);
}
public string ToString(IFormatProvider formatProvider)
{
return Value.ToString(formatProvider);
}
public override string ToInlineToml()
{
double value = Value;
if (double.IsNaN(value))
{
return "nan";
}
if (double.IsPositiveInfinity(value))
{
return "inf";
}
if (double.IsNegativeInfinity(value))
{
return "-inf";
}
double num = value;
return num.ToString("G", CultureInfo.InvariantCulture).ToLowerInvariant();
}
}
public class TomlBoolean : TomlNode
{
public override bool IsBoolean { get; } = true;
public override bool HasValue { get; } = true;
public bool Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
public override string ToInlineToml()
{
if (!Value)
{
return "false";
}
return "true";
}
}
public class TomlDateTime : TomlNode, IFormattable
{
public int SecondsPrecision { get; set; }
public override bool HasValue { get; } = true;
public virtual string ToString(string format, IFormatProvider formatProvider)
{
return string.Empty;
}
public virtual string ToString(IFormatProvider formatProvider)
{
return string.Empty;
}
protected virtual string ToInlineTomlInternal()
{
return string.Empty;
}
public override string ToInlineToml()
{
return ToInlineTomlInternal().Replace(" ", "T").Replace("+00:00", "Z");
}
}
public class TomlDateTimeOffset : TomlDateTime
{
public override bool IsDateTimeOffset { get; } = true;
public DateTimeOffset Value { get; set; }
public override string ToString()
{
return Value.ToString(CultureInfo.CurrentCulture);
}
public override string ToString(IFormatProvider formatProvider)
{
return Value.ToString(formatProvider);
}
public override string ToString(string format, IFormatProvider formatProvider)
{
return Value.ToString(format, formatProvider);
}
protected override string ToInlineTomlInternal()
{
return Value.ToString(TomlSyntax.RFC3339Formats[base.SecondsPrecision]);
}
}
public class TomlDateTimeLocal : TomlDateTime
{
public enum DateTimeStyle
{
Date,
Time,
DateTime
}
public override bool IsDateTimeLocal { get; } = true;
public DateTimeStyle Style { get; set; } = DateTimeStyle.DateTime;
public DateTime Value { get; set; }
public override string ToString()
{
return Value.ToString(CultureInfo.CurrentCulture);
}
public override string ToString(IFormatProvider formatProvider)
{
return Value.ToString(formatProvider);
}
public override string ToString(string format, IFormatProvider formatProvider)
{
return Value.ToString(format, formatProvider);
}
public override string ToInlineToml()
{
return Style switch
{
DateTimeStyle.Date => Value.ToString(TomlSyntax.LocalDateFormat),
DateTimeStyle.Time => Value.ToString(TomlSyntax.RFC3339LocalTimeFormats[base.SecondsPrecision]),
_ => Value.ToString(TomlSyntax.RFC3339LocalDateTimeFormats[base.SecondsPrecision]),
};
}
}
public class TomlArray : TomlNode
{
private List<TomlNode> values;
public override bool HasValue { get; } = true;
public override bool IsArray { get; } = true;
public bool IsMultiline { get; set; }
public bool IsTableArray { get; set; }
public List<TomlNode> RawArray => values ?? (values = new List<TomlNode>());
public override TomlNode this[int index]
{
get
{
if (index < RawArray.Count)
{
return RawArray[index];
}
return this[index] = new TomlLazy(this);
}
set
{
if (index == RawArray.Count)
{
RawArray.Add(value);
}
else
{
RawArray[index] = value;
}
}
}
public override int ChildrenCount => RawArray.Count;
public override IEnumerable<TomlNode> Children => RawArray.AsEnumerable();
public override void Add(TomlNode node)
{
RawArray.Add(node);
}
public override void AddRange(IEnumerable<TomlNode> nodes)
{
RawArray.AddRange(nodes);
}
public override void Delete(TomlNode node)
{
RawArray.Remove(node);
}
public override void Delete(int index)
{
RawArray.RemoveAt(index);
}
public override string ToString()
{
return ToString(multiline: false);
}
public string ToString(bool multiline)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append('[');
if (ChildrenCount != 0)
{
string value = (multiline ? (Environment.NewLine + " ") : " ");
string self = (multiline ? $"{','}{Environment.NewLine} " : $"{','} ");
string value2 = (multiline ? Environment.NewLine : " ");
stringBuilder.Append(value).Append(self.Join(RawArray.Select((TomlNode n) => n.ToInlineToml()))).Append(value2);
}
stringBuilder.Append(']');
return stringBuilder.ToString();
}
public override void WriteTo(TextWriter tw, string name = null)
{
if (!IsTableArray)
{
tw.WriteLine(ToString(IsMultiline));
return;
}
if (Comment != null)
{
tw.WriteLine();
Comment.AsComment(tw);
}
tw.Write('[');
tw.Write('[');
tw.Write(name);
tw.Write(']');
tw.Write(']');
tw.WriteLine();
bool flag = true;
foreach (TomlNode item in RawArray)
{
TomlTable obj = (item as TomlTable) ?? throw new TomlFormatException("The array is marked as array table but contains non-table nodes!");
obj.IsInline = false;
if (!flag)
{
tw.WriteLine();
Comment?.AsComment(tw);
tw.Write('[');
tw.Write('[');
tw.Write(name);
tw.Write(']');
tw.Write(']');
tw.WriteLine();
}
flag = false;
obj.WriteTo(tw, name, writeSectionName: false);
}
}
}
public class TomlTable : TomlNode
{
private Dictionary<string, TomlNode> children;
public override bool HasValue { get; }
public override bool IsTable { get; } = true;
public bool IsInline { get; set; }
public Dictionary<string, TomlNode> RawTable => children ?? (children = new Dictionary<string, TomlNode>());
public override TomlNode this[string key]
{
get
{
if (RawTable.TryGetValue(key, out var value))
{
return value;
}
TomlLazy tomlLazy = new TomlLazy(this);
RawTable[key] = tomlLazy;
return tomlLazy;
}
set
{
RawTable[key] = value;
}
}
public override int ChildrenCount => RawTable.Count;
public override IEnumerable<TomlNode> Children => RawTable.Select((KeyValuePair<string, TomlNode> kv) => kv.Value);
public override IEnumerable<string> Keys => RawTable.Select((KeyValuePair<string, TomlNode> kv) => kv.Key);
public override bool HasKey(string key)
{
return RawTable.ContainsKey(key);
}
public override void Add(string key, TomlNode node)
{
RawTable.Add(key, node);
}
public override bool TryGetNode(string key, out TomlNode node)
{
return RawTable.TryGetValue(key, out node);
}
public override void Delete(TomlNode node)
{
RawTable.Remove(RawTable.First((KeyValuePair<string, TomlNode> kv) => kv.Value == node).Key);
}
public override void Delete(string key)
{
RawTable.Remove(key);
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append('{');
if (ChildrenCount != 0)
{
LinkedList<KeyValuePair<string, TomlNode>> linkedList = CollectCollapsedItems("", 0, normalizeOrder: false);
if (linkedList.Count != 0)
{
stringBuilder.Append(' ').Append($"{','} ".Join(linkedList.Select((KeyValuePair<string, TomlNode> n) => $"{n.Key} {'='} {n.Value.ToInlineToml()}")));
}
stringBuilder.Append(' ');
}
stringBuilder.Append('}');
return stringBuilder.ToString();
}
private LinkedList<KeyValuePair<string, TomlNode>> CollectCollapsedItems(string prefix = "", int level = 0, bool normalizeOrder = true)
{
LinkedList<KeyValuePair<string, TomlNode>> linkedList = new LinkedList<KeyValuePair<string, TomlNode>>();
LinkedList<KeyValuePair<string, TomlNode>> linkedList2 = (normalizeOrder ? new LinkedList<KeyValuePair<string, TomlNode>>() : linkedList);
foreach (KeyValuePair<string, TomlNode> item in RawTable)
{
TomlNode value = item.Value;
string text = item.Key.AsKey();
if (value is TomlTable tomlTable)
{
LinkedList<KeyValuePair<string, TomlNode>> linkedList3 = tomlTable.CollectCollapsedItems(prefix + text + ".", level + 1, normalizeOrder);
if (linkedList3.Count == 0 && value.CollapseLevel == level)
{
linkedList2.AddLast(new KeyValuePair<string, TomlNode>(prefix + text, value));
}
foreach (KeyValuePair<string, TomlNode> item2 in linkedList3)
{
linkedList2.AddLast(item2);
}
}
else if (value.CollapseLevel == level)
{
linkedList.AddLast(new KeyValuePair<string, TomlNode>(prefix + text, value));
}
}
if (normalizeOrder)
{
foreach (KeyValuePair<string, TomlNode> item3 in linkedList2)
{
linkedList.AddLast(item3);
}
}
return linkedList;
}
public override void WriteTo(TextWriter tw, string name = null)
{
WriteTo(tw, name, writeSectionName: true);
}
internal void WriteTo(TextWriter tw, string name, bool writeSectionName)
{
if (IsInline && name != null)
{
tw.WriteLine(ToInlineToml());
return;
}
LinkedList<KeyValuePair<string, TomlNode>> linkedList = CollectCollapsedItems();
if (linkedList.Count == 0)
{
return;
}
bool flag = !linkedList.All(delegate(KeyValuePair<string, TomlNode> n)
{
TomlNode value2 = n.Value;
if (value2 is TomlTable tomlTable2)
{
if (!tomlTable2.IsInline)
{
goto IL_002e;
}
}
else if (value2 is TomlArray tomlArray2 && tomlArray2.IsTableArray)
{
goto IL_002e;
}
return false;
IL_002e:
return true;
});
Comment?.AsComment(tw);
if (name != null && (flag || Comment != null) && writeSectionName)
{
tw.Write('[');
tw.Write(name);
tw.Write(']');
tw.WriteLine();
}
else if (Comment != null)
{
tw.WriteLine();
}
string text = ((name == null) ? "" : (name + "."));
bool flag2 = true;
foreach (KeyValuePair<string, TomlNode> item in linkedList)
{
string key = item.Key;
TomlNode value = item.Value;
if (value is TomlArray tomlArray)
{
if (tomlArray.IsTableArray)
{
goto IL_011e;
}
}
else if (value is TomlTable tomlTable && !tomlTable.IsInline)
{
goto IL_011e;
}
bool flag3 = false;
goto IL_0126;
IL_011e:
flag3 = true;
goto IL_0126;
IL_0126:
if (flag3)
{
if (!flag2)
{
tw.WriteLine();
}
flag2 = false;
item.Value.WriteTo(tw, text + key);
}
else
{
flag2 = false;
item.Value.Comment?.AsComment(tw);
tw.Write(key);
tw.Write(' ');
tw.Write('=');
tw.Write(' ');
item.Value.WriteTo(tw, text + key);
}
}
}
}
internal class TomlLazy : TomlNode
{
private readonly TomlNode parent;
private TomlNode replacement;
public override TomlNode this[int index]
{
get
{
return Set<TomlArray>()[index];
}
set
{
Set<TomlArray>()[index] = value;
}
}
public override TomlNode this[string key]
{
get
{
return Set<TomlTable>()[key];
}
set
{
Set<TomlTable>()[key] = value;
}
}
public TomlLazy(TomlNode parent)
{
this.parent = parent;
}
public override void Add(TomlNode node)
{
Set<TomlArray>().Add(node);
}
public override void Add(string key, TomlNode node)
{
Set<TomlTable>().Add(key, node);
}
public override void AddRange(IEnumerable<TomlNode> nodes)
{
Set<TomlArray>().AddRange(nodes);
}
private TomlNode Set<T>() where T : TomlNode, new()
{
if (replacement != null)
{
return replacement;
}
T val = new T
{
Comment = Comment
};
if (parent.IsTable)
{
TomlNode node;
string text = parent.Keys.FirstOrDefault((string s) => parent.TryGetNode(s, out node) && node.Equals(this));
if (text == null)
{
return null;
}
parent[text] = val;
}
else
{
if (!parent.IsArray)
{
return null;
}
int num = parent.Children.TakeWhile((TomlNode child) => child != this).Count();
if (num == parent.ChildrenCount)
{
return null;
}
parent[num] = val;
}
replacement = val;
return val;
}
}
public class TOMLParser : IDisposable
{
public enum ParseState
{
None,
KeyValuePair,
SkipToNextLine,
Table
}
private readonly TextReader reader;
private ParseState currentState;
private int line;
private int col;
private List<TomlSyntaxException> syntaxErrors;
public bool ForceASCII { get; set; }
public TOMLParser(TextReader reader)
{
this.reader = reader;
line = (col = 0);
}
public void Dispose()
{
reader?.Dispose();
}
public TomlTable Parse()
{
syntaxErrors = new List<TomlSyntaxException>();
line = (col = 1);
TomlTable tomlTable = new TomlTable();
TomlTable tomlTable2 = tomlTable;
currentState = ParseState.None;
List<string> parts = new List<string>();
bool flag = false;
StringBuilder stringBuilder = null;
bool flag2 = true;
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
if (currentState != 0)
{
goto IL_011d;
}
if (!TomlSyntax.IsWhiteSpace(c))
{
if (TomlSyntax.IsNewLine(c))
{
if (stringBuilder != null && flag2)
{
tomlTable.Comment = stringBuilder.ToString().TrimEnd(new char[0]);
stringBuilder = null;
flag2 = false;
}
if (TomlSyntax.IsLineBreak(c))
{
AdvanceLine();
}
}
else
{
if (c == '#')
{
if (stringBuilder == null)
{
stringBuilder = new StringBuilder();
}
stringBuilder.AppendLine(ParseComment());
AdvanceLine(1);
continue;
}
flag2 = false;
if (c != '[')
{
if (TomlSyntax.IsBareKey(c) || TomlSyntax.IsQuoted(c))
{
currentState = ParseState.KeyValuePair;
goto IL_011d;
}
AddError($"Unexpected character \"{c}\"");
continue;
}
currentState = ParseState.Table;
}
}
goto IL_0368;
IL_011d:
if (currentState == ParseState.KeyValuePair)
{
TomlNode tomlNode = ReadKeyValuePair(parts);
if (tomlNode == null)
{
stringBuilder = null;
parts.Clear();
if (currentState != 0)
{
AddError("Failed to parse key-value pair!");
}
continue;
}
tomlNode.Comment = stringBuilder?.ToString()?.TrimEnd(new char[0]);
bool num2 = InsertNode(tomlNode, tomlTable2, parts);
stringBuilder = null;
parts.Clear();
if (num2)
{
currentState = ParseState.SkipToNextLine;
}
continue;
}
if (currentState == ParseState.Table)
{
if (parts.Count == 0)
{
if (c == '[')
{
ConsumeChar();
flag = true;
}
if (!ReadKeyName(ref parts, ']'))
{
parts.Clear();
}
else if (parts.Count == 0)
{
AddError("Table name is emtpy.");
flag = false;
stringBuilder = null;
parts.Clear();
}
continue;
}
if (c == ']')
{
if (flag)
{
ConsumeChar();
int num3 = reader.Peek();
if (num3 < 0 || (ushort)num3 != 93)
{
AddError("Array table " + ".".Join(parts) + " has only one closing bracket.");
parts.Clear();
flag = false;
stringBuilder = null;
continue;
}
}
tomlTable2 = CreateTable(tomlTable, parts, flag);
if (tomlTable2 != null)
{
tomlTable2.IsInline = false;
tomlTable2.Comment = stringBuilder?.ToString()?.TrimEnd(new char[0]);
}
parts.Clear();
flag = false;
stringBuilder = null;
if (tomlTable2 == null)
{
if (currentState != 0)
{
AddError("Error creating table array!");
}
tomlTable2 = tomlTable;
continue;
}
currentState = ParseState.SkipToNextLine;
goto IL_0368;
}
if (parts.Count != 0)
{
AddError($"Unexpected character \"{c}\"");
parts.Clear();
flag = false;
stringBuilder = null;
}
}
if (currentState == ParseState.SkipToNextLine && !TomlSyntax.IsWhiteSpace(c))
{
switch (c)
{
case '\n':
case '#':
currentState = ParseState.None;
AdvanceLine();
if (c == '#')
{
col++;
ParseComment();
continue;
}
break;
default:
AddError($"Unexpected character \"{c}\" at the end of the line.");
break;
case '\r':
break;
}
}
goto IL_0368;
IL_0368:
reader.Read();
col++;
}
if (currentState != 0 && currentState != ParseState.SkipToNextLine)
{
AddError("Unexpected end of file!");
}
if (syntaxErrors.Count > 0)
{
throw new TomlParseException(tomlTable, syntaxErrors);
}
return tomlTable;
}
private bool AddError(string message, bool skipLine = true)
{
syntaxErrors.Add(new TomlSyntaxException(message, currentState, line, col));
if (skipLine)
{
reader.ReadLine();
AdvanceLine(1);
}
currentState = ParseState.None;
return false;
}
private void AdvanceLine(int startCol = 0)
{
line++;
col = startCol;
}
private int ConsumeChar()
{
col++;
return reader.Read();
}
private TomlNode ReadKeyValuePair(List<string> keyParts)
{
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
if (TomlSyntax.IsQuoted(c) || TomlSyntax.IsBareKey(c))
{
if (keyParts.Count != 0)
{
AddError("Encountered extra characters in key definition!");
return null;
}
if (!ReadKeyName(ref keyParts, '='))
{
return null;
}
continue;
}
if (TomlSyntax.IsWhiteSpace(c))
{
ConsumeChar();
continue;
}
if (c == '=')
{
ConsumeChar();
return ReadValue();
}
AddError($"Unexpected character \"{c}\" in key name.");
return null;
}
return null;
}
private TomlNode ReadValue(bool skipNewlines = false)
{
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
if (TomlSyntax.IsWhiteSpace(c))
{
ConsumeChar();
continue;
}
if (c == '#')
{
AddError("No value found!");
return null;
}
if (TomlSyntax.IsNewLine(c))
{
if (skipNewlines)
{
reader.Read();
AdvanceLine(1);
continue;
}
AddError("Encountered a newline when expecting a value!");
return null;
}
if (TomlSyntax.IsQuoted(c))
{
char excess;
bool flag = IsTripleQuote(c, out excess);
if (currentState == ParseState.None)
{
return null;
}
string text = (flag ? ReadQuotedValueMultiLine(c) : ReadQuotedValueSingleLine(c, excess));
if (text == null)
{
return null;
}
return new TomlString
{
Value = text,
IsMultiline = flag,
PreferLiteral = (c == '\'')
};
}
return c switch
{
'{' => ReadInlineTable(),
'[' => ReadArray(),
_ => ReadTomlValue(),
};
}
return null;
}
private bool ReadKeyName(ref List<string> parts, char until)
{
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
bool flag2 = false;
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
if (c == until)
{
break;
}
if (TomlSyntax.IsWhiteSpace(c))
{
flag2 = true;
}
else
{
if (stringBuilder.Length == 0)
{
flag2 = false;
}
if (c == '.')
{
if (stringBuilder.Length == 0 && !flag)
{
return AddError("Found an extra subkey separator in " + ".".Join(parts) + "...");
}
parts.Add(stringBuilder.ToString());
stringBuilder.Length = 0;
flag = false;
flag2 = false;
}
else
{
if (flag2)
{
return AddError("Invalid spacing in key name");
}
if (TomlSyntax.IsQuoted(c))
{
if (flag)
{
return AddError("Expected a subkey separator but got extra data instead!");
}
if (stringBuilder.Length != 0)
{
return AddError("Encountered a quote in the middle of subkey name!");
}
col++;
stringBuilder.Append(ReadQuotedValueSingleLine((char)reader.Read()));
flag = true;
continue;
}
if (!TomlSyntax.IsBareKey(c))
{
break;
}
stringBuilder.Append(c);
}
}
reader.Read();
col++;
}
if (stringBuilder.Length == 0 && !flag)
{
return AddError("Found an extra subkey separator in " + ".".Join(parts) + "...");
}
parts.Add(stringBuilder.ToString());
return true;
}
private string ReadRawValue()
{
StringBuilder stringBuilder = new StringBuilder();
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
if (c == '#' || TomlSyntax.IsNewLine(c) || TomlSyntax.IsValueSeparator(c))
{
break;
}
stringBuilder.Append(c);
ConsumeChar();
}
return stringBuilder.ToString().Trim();
}
private TomlNode ReadTomlValue()
{
string text = ReadRawValue();
string text2 = text;
string text3 = text2;
int numberBase;
TomlNode tomlNode = (TomlSyntax.IsBoolean(text3) ? ((TomlNode)bool.Parse(text3)) : (TomlSyntax.IsNaN(text2) ? ((TomlNode)double.NaN) : (TomlSyntax.IsPosInf(text2) ? ((TomlNode)double.PositiveInfinity) : (TomlSyntax.IsNegInf(text2) ? ((TomlNode)double.NegativeInfinity) : (TomlSyntax.IsInteger(text2) ? ((TomlNode)long.Parse(text.RemoveAll('_'), CultureInfo.InvariantCulture)) : (TomlSyntax.IsFloat(text2) ? ((TomlNode)double.Parse(text.RemoveAll('_'), CultureInfo.InvariantCulture)) : ((!TomlSyntax.IsIntegerWithBase(text2, out numberBase)) ? null : new TomlInteger
{
Value = Convert.ToInt64(text.Substring(2).RemoveAll('_'), numberBase),
IntegerBase = (TomlInteger.Base)numberBase
})))))));
TomlNode tomlNode2 = tomlNode;
if (tomlNode2 != null)
{
return tomlNode2;
}
text = text.Replace(" ", "T");
if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339LocalDateTimeFormats, DateTimeStyles.AssumeLocal, (StringUtils.TryDateParseDelegate<DateTime>)DateTime.TryParseExact, out DateTime dateTime, out int parsedFormat))
{
return new TomlDateTimeLocal
{
Value = dateTime,
SecondsPrecision = parsedFormat
};
}
if (DateTime.TryParseExact(text, TomlSyntax.LocalDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out dateTime))
{
return new TomlDateTimeLocal
{
Value = dateTime,
Style = TomlDateTimeLocal.DateTimeStyle.Date
};
}
if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339LocalTimeFormats, DateTimeStyles.AssumeLocal, (StringUtils.TryDateParseDelegate<DateTime>)DateTime.TryParseExact, out dateTime, out parsedFormat))
{
return new TomlDateTimeLocal
{
Value = dateTime,
Style = TomlDateTimeLocal.DateTimeStyle.Time,
SecondsPrecision = parsedFormat
};
}
if (StringUtils.TryParseDateTime(text, TomlSyntax.RFC3339Formats, DateTimeStyles.None, (StringUtils.TryDateParseDelegate<DateTimeOffset>)DateTimeOffset.TryParseExact, out DateTimeOffset dateTime2, out parsedFormat))
{
return new TomlDateTimeOffset
{
Value = dateTime2,
SecondsPrecision = parsedFormat
};
}
AddError("Value \"" + text + "\" is not a valid TOML value!");
return null;
}
private TomlArray ReadArray()
{
ConsumeChar();
TomlArray tomlArray = new TomlArray();
TomlNode tomlNode = null;
bool flag = true;
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
switch (c)
{
case ']':
break;
case '#':
reader.ReadLine();
AdvanceLine(1);
continue;
default:
if (TomlSyntax.IsWhiteSpace(c) || TomlSyntax.IsNewLine(c))
{
if (TomlSyntax.IsLineBreak(c))
{
AdvanceLine();
}
}
else
{
if (c != ',')
{
if (!flag)
{
AddError("Missing separator between values");
return null;
}
tomlNode = ReadValue(skipNewlines: true);
if (tomlNode == null)
{
if (currentState != 0)
{
AddError("Failed to determine and parse a value!");
}
return null;
}
flag = false;
continue;
}
if (tomlNode == null)
{
AddError("Encountered multiple value separators");
return null;
}
tomlArray.Add(tomlNode);
tomlNode = null;
flag = true;
}
ConsumeChar();
continue;
}
ConsumeChar();
break;
}
if (tomlNode != null)
{
tomlArray.Add(tomlNode);
}
return tomlArray;
}
private TomlNode ReadInlineTable()
{
ConsumeChar();
TomlTable tomlTable = new TomlTable
{
IsInline = true
};
TomlNode tomlNode = null;
bool flag = false;
List<string> list = new List<string>();
int num;
while ((num = reader.Peek()) >= 0)
{
char c = (char)num;
switch (c)
{
case '}':
break;
case '#':
AddError("Incomplete inline table definition!");
return null;
default:
if (TomlSyntax.IsNewLine(c))
{
AddError("Inline tables are only allowed to be on single line");
return null;
}
if (!TomlSyntax.IsWhiteSpace(c))
{
if (c != ',')
{
flag = false;
tomlNode = ReadKeyValuePair(list);
continue;
}
if (tomlNode == null)
{
AddError("Encountered multiple value separators in inline table!");
return null;
}
if (!InsertNode(tomlNode, tomlTable, list))
{
return null;
}
list.Clear();
tomlNode = null;
flag = true;
}
ConsumeChar();
continue;
}
ConsumeChar();
break;
}
if (flag)
{
AddError("Trailing commas are not allowed in inline tables.");
return null;
}
if (tomlNode != null && !InsertNode(tomlNode, tomlTable, list))
{
return null;
}
return tomlTable;
}
private bool IsTripleQuote(char quote, out char excess)
{
ConsumeChar();
int num;
if ((num = reader.Peek()) < 0)
{
excess = '\0';
return AddError("Unexpected end of file!");
}
if ((ushort)num != quote)
{
excess = '\0';
return false;
}
excess = (char)ConsumeChar();
if ((num = reader.Peek()) < 0 || (ushort)num != quote)
{
return false;
}
ConsumeChar();
excess = '\0';
return true;
}
private bool ProcessQuotedValueCharacter(char quote, bool isNonLiteral, char c, StringBuilder sb, ref bool escaped)
{
if (TomlSyntax.MustBeEscaped(c))
{
return AddError($"The character U+{(int)c:X8} must be escaped in a string!");
}
if (escaped)
{
sb.Append(c);
escaped = false;
return false;
}
if (c == quote)
{
return true;
}
if (isNonLiteral && c == '\\')
{
escaped = true;
}
if (c == '\n')
{
return AddError("Encountered newline in single line string!");
}
sb.Append(c);
return false;
}
private string ReadQuotedValueSingleLine(char quote, char initialData = '\0')
{
bool flag = quote == '"';
StringBuilder stringBuilder = new StringBuilder();
bool escaped = false;
if (initialData != 0)
{
bool flag2 = ProcessQuotedValueCharacter(quote, flag, initialData, stringBuilder, ref escaped);
if (currentState == ParseState.None)
{
return null;
}
if (flag2)
{
if (flag)
{
if (stringBuilder.ToString().TryUnescape(out var unescaped, out var exception))
{
return unescaped;
}
AddError(exception.Message);
return null;
}
return stringBuilder.ToString();
}
}
bool flag3 = false;
int num;
while ((num = reader.Read()) >= 0)
{
col++;
char c = (char)num;
flag3 = ProcessQuotedValueCharacter(quote, flag, c, stringBuilder, ref escaped);
if (flag3)
{
if (currentState != 0)
{
break;
}
return null;
}
}
if (!flag3)
{
AddError("Unclosed string.");
return null;
}
if (!flag)
{
return stringBuilder.ToString();
}
if (stringBuilder.ToString().TryUnescape(out var unescaped2, out var exception2))
{
return unescaped2;
}
AddError(exception2.Message);
return null;
}
private string ReadQuotedValueMultiLine(char quote)
{
bool flag = quote == '"';
StringBuilder stringBuilder = new StringBuilder();
bool flag2 = false;
bool flag3 = false;
bool flag4 = false;
int num = 0;
bool flag5 = true;
int num2;
while ((num2 = ConsumeChar()) >= 0)
{
char c = (char)num2;
if (TomlSyntax.MustBeEscaped(c, allowNewLines: true))
{
AddError($"The character U+{(int)c:X8} must be escaped!");
return null;
}
if (flag5 && TomlSyntax.IsNewLine(c))
{
if (TomlSyntax.IsLineBreak(c))
{
flag5 = false;
}
else
{
AdvanceLine();
}
continue;
}
flag5 = false;
if (flag2)
{
stringBuilder.Append(c);
flag2 = false;
continue;
}
if (flag3)
{
if (TomlSyntax.IsEmptySpace(c))
{
if (TomlSyntax.IsLineBreak(c))
{
flag4 = true;
AdvanceLine();
}
continue;
}
if (!flag4)
{
AddError("Non-whitespace character after trim marker.");
return null;
}
flag4 = false;
flag3 = false;
}
if (flag && c == '\\')
{
int num3 = reader.Peek();
char c2 = (char)num3;
if (num3 >= 0)
{
if (TomlSyntax.IsEmptySpace(c2))
{
flag3 = true;
continue;
}
if (c2 == quote || c2 == '\\')
{
flag2 = true;
}
}
}
num = ((c == quote) ? (num + 1) : 0);
if (num == 3)
{
break;
}
stringBuilder.Append(c);
}
num = 0;
while ((num2 = reader.Peek()) >= 0)
{
char c3 = (char)num2;
if (c3 != quote || ++num >= 3)
{
break;
}
stringBuilder.Append(c3);
ConsumeChar();
}
stringBuilder.Length -= 2;
if (!flag)
{
return stringBuilder.ToString();
}
if (stringBuilder.ToString().TryUnescape(out var unescaped, out var exception))
{
return unescaped;
}
AddError(exception.Message);
return null;
}
private bool InsertNode(TomlNode node, TomlNode root, IList<string> path)
{
TomlNode tomlNode = root;
if (path.Count > 1)
{
for (int i = 0; i < path.Count - 1; i++)
{
string key = path[i];
if (!tomlNode.TryGetNode(key, out var node2))
{
node2 = (tomlNode[key] = new TomlTable());
}
else if (node2.HasValue)
{
return AddError("The key " + ".".Join(path) + " already has a value assigned to it!");
}
tomlNode = node2;
if (tomlNode is TomlTable tomlTable && tomlTable.IsInline)
{
return AddError("Cannot assign " + ".".Join(path) + " because it will edit an immutable table.");
}
}
}
if (tomlNode.HasKey(path[path.Count - 1]))
{
return AddError("The key " + ".".Join(path) + " is already defined!");
}
tomlNode[path[path.Count - 1]] = node;
node.CollapseLevel = path.Count - 1;
return true;
}
private TomlTable CreateTable(TomlNode root, IList<string> path, bool arrayTable)
{
if (path.Count == 0)
{
return null;
}
TomlNode tomlNode = root;
for (int i = 0; i < path.Count; i++)
{
string key = path[i];
if (tomlNode.TryGetNode(key, out var node))
{
if (node.IsArray && arrayTable)
{
TomlArray tomlArray = (TomlArray)node;
if (!tomlArray.IsTableArray)
{
AddError("The array " + ".".Join(path) + " cannot be redefined as an array table!");
return null;
}
if (i == path.Count - 1)
{
tomlNode = new TomlTable();
tomlArray.Add(tomlNode);
break;
}
tomlNode = tomlArray[tomlArray.ChildrenCount - 1];
continue;
}
if (node.HasValue)
{
if (!(node is TomlArray tomlArray2) || !tomlArray2.IsTableArray)
{
AddError("The key " + ".".Join(path) + " has a value assigned to it!");
return null;
}
tomlNode = tomlArray2[tomlArray2.ChildrenCount - 1];
continue;
}
if (i == path.Count - 1)
{
if (arrayTable && !node.IsArray)
{
AddError("The table " + ".".Join(path) + " cannot be redefined as an array table!");
return null;
}
if (node is TomlTable tomlTable && !tomlTable.IsInline)
{
AddError("The table " + ".".Join(path) + " is defined multiple times!");
return null;
}
}
}
else
{
if (i == path.Count - 1 && arrayTable)
{
TomlTable tomlTable2 = new TomlTable();
TomlArray tomlArray3 = new TomlArray
{
IsTableArray = true
};
tomlArray3.Add(tomlTable2);
tomlNode[key] = tomlArray3;
tomlNode = tomlTable2;
break;
}
node = (tomlNode[key] = new TomlTable
{
IsInline = true
});
}
tomlNode = node;
}
return (TomlTable)tomlNode;
}
private string ParseComment()
{
ConsumeChar();
string obj = reader.ReadLine()?.Trim() ?? "";
if (obj.Any((char ch) => TomlSyntax.MustBeEscaped(ch)))
{
AddError("Comment must not contain control characters other than tab.", skipLine: false);
}
return obj;
}
}
public static class TOML
{
public static bool ForceASCII { get; set; }
public static TomlTable Parse(TextReader reader)
{
using TOMLParser tOMLParser = new TOMLParser(reader)
{
ForceASCII = ForceASCII
};
return tOMLParser.Parse();
}
}
public class TomlFormatException : Exception
{
public TomlFormatException(string message)
: base(message)
{
}
}
public class TomlParseException : Exception
{
public TomlTable ParsedTable { get; }
public IEnumerable<TomlSyntaxException> SyntaxErrors { get; }
public TomlParseException(TomlTable parsed, IEnumerable<TomlSyntaxException> exceptions)
: base("TOML file contains format errors")
{
ParsedTable = parsed;
SyntaxErrors = exceptions;
}
}
public class TomlSyntaxException : Exception
{
public TOMLParser.ParseState ParseState { get; }
public int Line { get; }
public int Column { get; }
public TomlSyntaxException(string message, TOMLParser.ParseState state, int line, int col)
: base(message)
{
ParseState = state;
Line = line;
Column = col;
}
}
internal static class TomlSyntax
{
public const string TRUE_VALUE = "true";
public const string FALSE_VALUE = "false";
public const string NAN_VALUE = "nan";
public const string POS_NAN_VALUE = "+nan";
public const string NEG_NAN_VALUE = "-nan";
public const string INF_VALUE = "inf";
public const string POS_INF_VALUE = "+inf";
public const string NEG_INF_VALUE = "-inf";
public static readonly Regex IntegerPattern = new Regex("^(\\+|-)?(?!_)(0|(?!0)(_?\\d)*)$", RegexOptions.Compiled);
public static readonly Regex BasedIntegerPattern = new Regex("^0(?<base>x|b|o)(?!_)(_?[0-9A-F])*$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static readonly Regex FloatPattern = new Regex("^(\\+|-)?(?!_)(0|(?!0)(_?\\d)+)(((e(\\+|-)?(?!_)(_?\\d)+)?)|(\\.(?!_)(_?\\d)+(e(\\+|-)?(?!_)(_?\\d)+)?))$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public static readonly Dictionary<string, int> IntegerBases = new Dictionary<string, int>
{
["x"] = 16,
["o"] = 8,
["b"] = 2
};
public static readonly Dictionary<int, string> BaseIdentifiers = new Dictionary<int, string>
{
[2] = "b",
[8] = "o",
[16] = "x"
};
public const string RFC3339EmptySeparator = " ";
public const string ISO861Separator = "T";
public const string ISO861ZeroZone = "+00:00";
public const string RFC3339ZeroZone = "Z";
public static readonly string[] RFC3339Formats = new string[8] { "yyyy'-'MM-ddTHH':'mm':'ssK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffffK", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffffK" };
public static readonly string[] RFC3339LocalDateTimeFormats = new string[8] { "yyyy'-'MM-ddTHH':'mm':'ss", "yyyy'-'MM-ddTHH':'mm':'ss'.'f", "yyyy'-'MM-ddTHH':'mm':'ss'.'ff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fff", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'ffffff", "yyyy'-'MM-ddTHH':'mm':'ss'.'fffffff" };
public static readonly string LocalDateFormat = "yyyy'-'MM'-'dd";
public static readonly string[] RFC3339LocalTimeFormats = new string[8] { "HH':'mm':'ss", "HH':'mm':'ss'.'f", "HH':'mm':'ss'.'ff", "HH':'mm':'ss'.'fff", "HH':'mm':'ss'.'ffff", "HH':'mm':'ss'.'fffff", "HH':'mm':'ss'.'ffffff", "HH':'mm':'ss'.'fffffff" };
public const char ARRAY_END_SYMBOL = ']';
public const char ITEM_SEPARATOR = ',';
public const char ARRAY_START_SYMBOL = '[';
public const char BASIC_STRING_SYMBOL = '"';
public const char COMMENT_SYMBOL = '#';
public const char ESCAPE_SYMBOL = '\\';
public const char KEY_VALUE_SEPARATOR = '=';
public const char NEWLINE_CARRIAGE_RETURN_CHARACTER = '\r';
public const char NEWLINE_CHARACTER = '\n';
public const char SUBKEY_SEPARATOR = '.';
public const char TABLE_END_SYMBOL = ']';
public const char TABLE_START_SYMBOL = '[';
public const char INLINE_TABLE_START_SYMBOL = '{';
public const char INLINE_TABLE_END_SYMBOL = '}';
public const char LITERAL_STRING_SYMBOL = '\'';
public const char INT_NUMBER_SEPARATOR = '_';
public static readonly char[] NewLineCharacters = new char[2] { '\n', '\r' };
public static bool IsBoolean(string s)
{
if (!(s == "true"))
{
return s == "false";
}
return true;
}
public static bool IsPosInf(string s)
{
if (!(s == "inf"))
{
return s == "+inf";
}
return true;
}
public static bool IsNegInf(string s)
{
return s == "-inf";
}
public static bool IsNaN(string s)
{
if (!(s == "nan") && !(s == "+nan"))
{
return s == "-nan";
}
return true;
}
public static bool IsInteger(string s)
{
return IntegerPattern.IsMatch(s);
}
public static bool IsFloat(string s)
{
return FloatPattern.IsMatch(s);
}
public static bool IsIntegerWithBase(string s, out int numberBase)
{
numberBase = 10;
Match match = BasedIntegerPattern.Match(s);
if (!match.Success)
{
return false;
}
IntegerBases.TryGetValue(match.Groups["base"].Value, out numberBase);
return true;
}
public static bool IsQuoted(char c)
{
if (c != '"')
{
return c == '\'';
}
return true;
}
public static bool IsWhiteSpace(char c)
{
if (c != ' ')
{
return c == '\t';
}
return true;
}
public static bool IsNewLine(char c)
{
if (c != '\n')
{
return c == '\r';
}
return true;
}
public static bool IsLineBreak(char c)
{
return c == '\n';
}
public static bool IsEmptySpace(char c)
{
if (!IsWhiteSpace(c))
{
return IsNewLine(c);
}
return true;
}
public static bool IsBareKey(char c)
{
switch (c)
{
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
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 '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':
return true;
default:
return false;
}
}
public static bool MustBeEscaped(char c, bool allowNewLines = false)
{
if (c >= '\u000e')
{
if (c <= '\u001f' || c == '\u007f')
{
goto IL_001f;
}
}
else if (c <= '\b' || c == '\v' || c == '\f')
{
goto IL_001f;
}
bool flag = false;
goto IL_0025;
IL_001f:
flag = true;
goto IL_0025;
IL_0025:
bool flag2 = flag;
if (!allowNewLines)
{
flag2 = flag2 || (c >= '\n' && c <= '\u000e');
}
return flag2;
}
public static bool IsValueSeparator(char c)
{
if (c != ',' && c != ']')
{
return c == '}';
}
return true;
}
}
internal static class StringUtils
{
public delegate bool TryDateParseDelegate<T>(string s, string format, IFormatProvider ci, DateTimeStyles dts, out T dt);
public static string AsKey(this string key)
{
if (key == string.Empty || key.Any((char c) => !TomlSyntax.IsBareKey(c)))
{
return $"{'"'}{key.Escape()}{'"'}";
}
return key;
}
public static string Join(this string self, IEnumerable<string> subItems)
{
StringBuilder stringBuilder = new StringBuilder();
bool flag = true;
foreach (string subItem in subItems)
{
if (!flag)
{
stringBuilder.Append(self);
}
flag = false;
stringBuilder.Append(subItem);
}
return stringBuilder.ToString();
}
public static bool TryParseDateTime<T>(string s, string[] formats, DateTimeStyles styles, TryDateParseDelegate<T> parser, out T dateTime, out int parsedFormat)
{
parsedFormat = 0;
dateTime = default(T);
for (int i = 0; i < formats.Length; i++)
{
string format = formats[i];
if (parser(s, format, CultureInfo.InvariantCulture, styles, out dateTime))
{
parsedFormat = i;
return true;
}
}
return false;
}
public static void AsComment(this string self, TextWriter tw)
{
string[] array = self.Split(new char[1] { '\n' });
foreach (string text in array)
{
tw.WriteLine($"{'#'} {text.Trim()}");
}
}
public static string RemoveAll(this string txt, char toRemove)
{
StringBuilder stringBuilder = new StringBuilder(txt.Length);
foreach (char item in txt.Where((char c) => c != toRemove))
{
stringBuilder.Append(item);
}
return stringBuilder.ToString();
}
public static string Escape(this string txt, bool escapeNewlines = true)
{
StringBuilder stringBuilder = new StringBuilder(txt.Length + 2);
StringBuilder stringBuilder2;
object value;
for (int j = 0; j < txt.Length; stringBuilder2.Append(value), j++)
{
char c2 = txt[j];
stringBuilder2 = stringBuilder;
switch (c2)
{
case '\b':
value = "\\b";
continue;
case '\t':
value = "\\t";
continue;
case '\n':
if (escapeNewlines)
{
value = "\\n";
continue;
}
break;
case '\f':
value = "\\f";
continue;
case '\r':
if (escapeNewlines)
{
value = "\\r";
continue;
}
break;
case '\\':
value = "\\\\";
continue;
case '"':
value = "\\\"";
continue;
}
value = ((!TomlSyntax.MustBeEscaped(c2, !escapeNewlines) && (!TOML.ForceASCII || c2 <= '\u007f')) ? ((object)c2) : CodePoint(txt, ref j, c2));
}
return stringBuilder.ToString();
static string CodePoint(string txt, ref int i, char c)
{
if (!char.IsSurrogatePair(txt, i))
{
return $"\\u{(ushort)c:X4}";
}
return $"\\U{char.ConvertToUtf32(txt, i++):X8}";
}
}
public static bool TryUnescape(this string txt, out string unescaped, out Exception exception)
{
try
{
exception = null;
unescaped = txt.Unescape();
return true;
}
catch (Exception ex)
{
exception = ex;
unescaped = null;
return false;
}
}
public static string Unescape(this string txt)
{
if (string.IsNullOrEmpty(txt))
{
return txt;
}
StringBuilder stringBuilder = new StringBuilder(txt.Length);
int num2 = 0;
while (num2 < txt.Length)
{
int num3 = txt.IndexOf('\\', num2);
int num4 = num3 + 1;
if (num3 < 0 || num3 == txt.Length - 1)
{
num3 = txt.Length;
}
stringBuilder.Append(txt, num2, num3 - num2);
if (num3 >= txt.Length)
{
break;
}
char c = txt[num4];
StringBuilder stringBuilder2 = stringBuilder;
stringBuilder2.Append(c switch
{
'b' => "\b",
't' => "\t",
'n' => "\n",
'f' => "\f",
'r' => "\r",
'\'' => "'",
'"' => "\"",
'\\' => "\\",
'u' => CodePoint(num4, txt, ref num3, 4),
'U' => CodePoint(num4, txt, ref num3, 8),
_ => throw new Exception("Undefined escape sequence!"),
});
num2 = num3 + 2;
}
return stringBuilder.ToString();
static string CodePoint(int next, string txt, ref int num, int size)
{
if (next + size >= txt.Length)
{
throw new Exception("Undefined escape sequence!");
}
num += size;
return char.ConvertFromUtf32(Convert.ToInt32(txt.Substring(next + 1, size), 16));
}
}
}
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Timers;
using AngryLevelLoader;
using AngryLevelLoader.Containers;
using AngryLevelLoader.Managers;
using AngryLevelLoader.Notifications;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using RudeLevelScript;
using SettingsMenu.Components;
using SettingsMenu.Models;
using Steamworks;
using Steamworks.Data;
using TMPro;
using UltraBINGO;
using UltraBINGO.Components;
using UltraBINGO.NetworkMessages;
using UltraBINGO.UI_Elements;
using UltrakillBingoClient;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using WebSocketSharp;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
public class BingoMapBrowser
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction<BaseEventData> <>9__25_0;
public static UnityAction<BaseEventData> <>9__25_1;
public static UnityAction<BaseEventData> <>9__25_4;
public static UnityAction <>9__26_0;
public static UnityAction <>9__26_1;
internal void <Setup>b__25_0(BaseEventData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
ShowMapData((PointerEventData)data);
}
internal void <Setup>b__25_1(BaseEventData data)
{
HideMapData();
}
internal void <Setup>b__25_4(BaseEventData data)
{
HideMapData();
}
internal void <Init>b__26_0()
{
ReturnToLobby();
}
internal void <Init>b__26_1()
{
GameManager.isUsingCustomMappool = true;
GameManager.customMappool = selectedLevels;
ReturnToLobby();
}
}
public static GameObject LoadingText;
public static GameObject MapBrowserWindow;
public static GameObject SelectedMapsList;
public static GameObject selectedMapsCount;
public static GameObject BackButton;
public static GameObject FinishButton;
public static string catalogURL = "https://raw.githubusercontent.com/eternalUnion/AngryLevels/release/V2/LevelCatalog.json";
public static string thumbnailURL = "https://raw.githubusercontent.com/eternalUnion/AngryLevels/release/Levels/";
public static GameObject MapTemplate;
public static bool hasFetched = false;
public static AngryMapCatalog catalog = null;
public static List<string> selectedLevels = new List<string>();
public static List<string> selectedLevelNames = new List<string>();
public static List<GameObject> levelCatalog = new List<GameObject>();
public static List<int> campaignLevelIds;
public static void ReturnToLobby()
{
BingoEncapsulator.BingoMapSelection.SetActive(false);
BingoEncapsulator.BingoLobbyScreen.SetActive(true);
}
public static void ShowMapData(PointerEventData pointerEventData, AngryBundle parentBundle = null, AngryLevel level = null)
{
}
public static void HideMapData()
{
}
public static async Task<Texture2D> FetchThumbnail(string thumbnailGuid)
{
if (File.Exists(Path.Combine(Main.ModFolder, "ThumbnailCache", thumbnailGuid + ".png")))
{
Logging.Message("Loading " + thumbnailGuid + ".png from thumbnail cache");
byte[] array = File.ReadAllBytes(Path.Combine(Main.ModFolder, "ThumbnailCache", thumbnailGuid + ".png"));
Texture2D val = new Texture2D(2, 2);
ImageConversion.LoadImage(val, array);
return val;
}
string text = thumbnailURL + "/" + thumbnailGuid + "/thumbnail.png";
UnityWebRequest texture = UnityWebRequestTexture.GetTexture(text);
try
{
texture.SendWebRequest();
while (!texture.isDone)
{
await Task.Yield();
}
if ((int)texture.result == 1)
{
Logging.Message("Saving " + thumbnailGuid + ".png to thumbnail cache");
byte[] bytes = ImageConversion.EncodeToPNG(DownloadHandlerTexture.GetContent(texture));
File.WriteAllBytes(Path.Combine(Main.ModFolder, "ThumbnailCache", thumbnailGuid + ".png"), bytes);
return DownloadHandlerTexture.GetContent(texture);
}
Logging.Error("Error while trying to download image from thumbnail catalog!");
Logging.Error(texture.responseCode.ToString());
return null;
}
finally
{
((IDisposable)texture)?.Dispose();
}
}
public static void UpdateSelectedMaps()
{
int num = GameManager.CurrentGame.gameSettingsArray["gridSize"];
int num2 = (3 + num) * (3 + num);
((TMP_Text)SelectedMapsList.GetComponent<TextMeshProUGUI>()).text = string.Join("\n", selectedLevelNames);
((TMP_Text)selectedMapsCount.GetComponent<TextMeshProUGUI>()).text = ((selectedLevels.Count >= num2) ? "<color=green>" : "<color=orange>") + selectedLevels.Count + "</color>/<color=orange>" + num2 + "</color>";
}
public static void ToggleMapSelection(ref GameObject levelPanel, string levelId, string levelName)
{
if (!selectedLevels.Contains(levelId))
{
selectedLevels.Add(levelId);
CommonFunctions.GetGameObjectChild(levelPanel, "SelectionIndicator").SetActive(true);
selectedLevelNames.Add(levelName);
}
else
{
selectedLevels.Remove(levelId);
CommonFunctions.GetGameObjectChild(levelPanel, "SelectionIndicator").SetActive(false);
selectedLevelNames.Remove(levelName);
}
UpdateSelectedMaps();
}
public static async Task<int> fetchCatalog()
{
try
{
catalog = JsonConvert.DeserializeObject<AngryMapCatalog>(await NetworkManager.FetchCatalog(catalogURL));
return 0;
}
catch (Exception ex)
{
Logging.Error(ex.ToString());
return -1;
}
}
public static void setupCampaignLevelIds()
{
campaignLevelIds = new List<int>();
for (int i = 1; i < 34; i++)
{
campaignLevelIds.Add(i);
}
List<int> second = new List<int> { 100, 101 };
List<int> second2 = new List<int> { 666, 667 };
campaignLevelIds = campaignLevelIds.Concat(second).Concat(second2).ToList();
}
public static async Task asyncFetchCustomThumbnails()
{
foreach (GameObject angryLevel in levelCatalog)
{
if (!((Object)angryLevel).name.Contains("Level "))
{
Texture2D val = await FetchThumbnail(angryLevel.GetComponent<BingoMapSelectionID>().bundleId);
if ((Object)(object)val != (Object)null)
{
CommonFunctions.GetGameObjectChild(angryLevel, "BundleImage").GetComponent<Image>().sprite = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
}
}
}
}
public static void ResetListPosition()
{
foreach (GameObject item in levelCatalog)
{
if ((Object)(object)item != (Object)null)
{
Object.Destroy((Object)(object)item);
}
}
levelCatalog = new List<GameObject>();
((TMP_Text)SelectedMapsList.GetComponent<TextMeshProUGUI>()).text = "";
((TMP_Text)selectedMapsCount.GetComponent<TextMeshProUGUI>()).text = "";
}
public static async void Setup()
{
if (hasFetched)
{
return;
}
Logging.Message("Fetching Angry map catalog...");
if (await fetchCatalog() != 0 || hasFetched)
{
return;
}
MapBrowserWindow.SetActive(true);
setupCampaignLevelIds();
foreach (int campaignLevel in campaignLevelIds)
{
GameObject levelPanel2 = Object.Instantiate<GameObject>(MapTemplate, MapTemplate.transform.parent);
CommonFunctions.GetGameObjectChild(levelPanel2, "BundleName").GetComponent<Text>().text = "CAMPAIGN";
CommonFunctions.GetGameObjectChild(levelPanel2, "MapName").GetComponent<Text>().text = GetMissionName.GetMissionNameOnly(campaignLevel);
CommonFunctions.GetGameObjectChild(levelPanel2, "SelectionIndicator").SetActive(false);
Entry val = new Entry();
val.eventID = (EventTriggerType)0;
((UnityEvent<BaseEventData>)(object)val.callback).AddListener((UnityAction<BaseEventData>)delegate(BaseEventData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Expected O, but got Unknown
ShowMapData((PointerEventData)data);
});
levelPanel2.AddComponent<EventTrigger>();
levelPanel2.GetComponent<EventTrigger>().triggers.Add(val);
((UnityEvent<BaseEventData>)(object)new Entry
{
eventID = (EventTriggerType)1
}.callback).AddListener((UnityAction<BaseEventData>)delegate
{
HideMapData();
});
levelPanel2.AddComponent<Button>();
((UnityEvent)levelPanel2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
ToggleMapSelection(ref levelPanel2, GetMissionName.GetSceneName(campaignLevel), GetMissionName.GetMissionNameOnly(campaignLevel));
});
string text = "assets/bingo/lvlimg/campaign/" + GetMissionName.GetSceneName(campaignLevel) + ".png";
Texture2D val2 = AssetLoader.Assets.LoadAsset<Texture2D>(text);
Sprite sprite = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f);
CommonFunctions.GetGameObjectChild(levelPanel2, "BundleImage").GetComponent<Image>().sprite = sprite;
((Object)levelPanel2).name = GetMissionName.GetSceneName(campaignLevel);
levelPanel2.SetActive(true);
levelCatalog.Add(levelPanel2);
}
foreach (AngryBundle bundle in catalog.Levels)
{
foreach (AngryLevel level in bundle.Levels)
{
GameObject levelPanel = Object.Instantiate<GameObject>(MapTemplate, MapTemplate.transform.parent);
CommonFunctions.GetGameObjectChild(levelPanel, "BundleName").GetComponent<Text>().text = bundle.Name;
CommonFunctions.GetGameObjectChild(levelPanel, "MapName").GetComponent<Text>().text = level.LevelName;
CommonFunctions.GetGameObjectChild(levelPanel, "SelectionIndicator").SetActive(false);
Entry val3 = new Entry();
val3.eventID = (EventTriggerType)0;
((UnityEvent<BaseEventData>)(object)val3.callback).AddListener((UnityAction<BaseEventData>)delegate(BaseEventData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
ShowMapData((PointerEventData)data, bundle, level);
});
levelPanel.AddComponent<EventTrigger>();
levelPanel.GetComponent<EventTrigger>().triggers.Add(val3);
((UnityEvent<BaseEventData>)(object)new Entry
{
eventID = (EventTriggerType)1
}.callback).AddListener((UnityAction<BaseEventData>)delegate
{
HideMapData();
});
levelPanel.AddComponent<Button>();
((UnityEvent)levelPanel.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
ToggleMapSelection(ref levelPanel, level.LevelId, level.LevelName);
});
levelPanel.AddComponent<BingoMapSelectionID>();
levelPanel.GetComponent<BingoMapSelectionID>().bundleId = bundle.Guid;
((Object)levelPanel).name = level.LevelId;
levelPanel.SetActive(true);
levelCatalog.Add(levelPanel);
}
}
LoadingText.SetActive(false);
hasFetched = true;
await asyncFetchCustomThumbnails();
}
public static void Init(ref GameObject MapBrowser)
{
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Expected O, but got Unknown
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Expected O, but got Unknown
LoadingText = CommonFunctions.GetGameObjectChild(MapBrowser, "DownloadingText");
MapBrowserWindow = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(MapBrowser, "Maps"), "Grid"), "Scroll View"), "Viewport"), "Content");
MapTemplate = CommonFunctions.GetGameObjectChild(MapBrowserWindow, "MapTemplate");
BackButton = CommonFunctions.GetGameObjectChild(MapBrowser, "Back");
ButtonClickedEvent onClick = BackButton.GetComponent<Button>().onClick;
object obj = <>c.<>9__26_0;
if (obj == null)
{
UnityAction val = delegate
{
ReturnToLobby();
};
<>c.<>9__26_0 = val;
obj = (object)val;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
FinishButton = CommonFunctions.GetGameObjectChild(MapBrowser, "Finish");
ButtonClickedEvent onClick2 = FinishButton.GetComponent<Button>().onClick;
object obj2 = <>c.<>9__26_1;
if (obj2 == null)
{
UnityAction val2 = delegate
{
GameManager.isUsingCustomMappool = true;
GameManager.customMappool = selectedLevels;
ReturnToLobby();
};
<>c.<>9__26_1 = val2;
obj2 = (object)val2;
}
((UnityEvent)onClick2).AddListener((UnityAction)obj2);
SelectedMapsList = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(MapBrowser, "Summary"), "SelectedMaps"), "List");
selectedMapsCount = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(MapBrowser, "Summary"), "TotalMapsNumber");
((TMP_Text)selectedMapsCount.GetComponent<TextMeshProUGUI>()).text = "<color=orange>0</color>/<color=orange>0</color>";
}
}
namespace UltrakillBingoClient
{
public static class Logging
{
public static ManualLogSource BingoLogger = Logger.CreateLogSource("Baphomet's BINGO");
public static void Debug(string text)
{
BingoLogger.LogDebug((object)text);
}
public static void Message(string text)
{
BingoLogger.LogMessage((object)text);
}
public static void Warn(string text)
{
BingoLogger.LogWarning((object)text);
}
public static void Error(string text)
{
BingoLogger.LogError((object)text);
}
public static void Fatal(string text)
{
BingoLogger.LogFatal((object)text);
}
public static void Info(string text)
{
BingoLogger.LogInfo((object)text);
}
}
public enum State
{
NORMAL,
INMENU,
INLOBBY,
INBROWSER,
INGAME
}
public enum AsyncAction
{
None,
Host,
Join,
ModCheck,
RetrySend,
ReconnectGame,
FetchGames
}
public class SendMessage
{
public string messageType;
}
public class MessageResponse
{
public string messageType;
}
public class PlayerNotification
{
public string messageType;
}
public static class NetworkManager
{
public static AsyncAction pendingAction = AsyncAction.None;
public static string pendingPassword = "";
public static VerifyModRequest pendingVmr = null;
public static string QueuedMessage = "";
public static State currentState = State.NORMAL;
public static ConfigEntry<string> serverURLConfig;
public static ConfigEntry<string> serverPortConfig;
public static ConfigEntry<string> lastRankUsedConfig;
public static string serverURL;
private static readonly HttpClient Client = new HttpClient();
public static bool startupDone = false;
public static bool modlistCheckPassed = false;
private static string steamTicket;
public static string requestedRank = "";
private static WebSocket ws;
private static Timer heartbeatTimer;
public static int maxReconnectionAttempts = 3;
public static int currentReconnection = 0;
public static string lastErrorString = "";
public static Dictionary<string, (Type messageType, Action<object> messageHandler)> messages = new Dictionary<string, (Type, Action<object>)>
{
{
"ChatMessage",
(typeof(ChatMessageReceive), delegate(object msg)
{
ChatMessageReceiveHandler.handle((ChatMessageReceive)msg);
})
},
{
"ChatWarn",
(typeof(ChatWarn), delegate(object msg)
{
ChatWarnHandler.handle((ChatWarn)msg);
})
},
{
"CheatNotification",
(typeof(CheatNotification), delegate(object msg)
{
CheatNotificationHandler.handle((CheatNotification)msg);
})
},
{
"CreateRoomResponse",
(typeof(CreateRoomResponse), delegate(object msg)
{
CreateRoomResponseHandler.handle((CreateRoomResponse)msg);
})
},
{
"DisconnectNotification",
(typeof(DisconnectNotification), delegate(object msg)
{
DisconnectNotificationHandler.handle((DisconnectNotification)msg);
})
},
{
"FetchGamesResponse",
(typeof(FetchGamesResponse), delegate(object msg)
{
FetchGamesReponseHandler.handle((FetchGamesResponse)msg);
})
},
{
"GameEnd",
(typeof(EndGameSignal), delegate(object msg)
{
EndGameSignalHandler.handle((EndGameSignal)msg);
})
},
{
"JoinRoomResponse",
(typeof(JoinRoomResponse), delegate(object msg)
{
JoinRoomResponseHandler.handle((JoinRoomResponse)msg);
})
},
{
"JoinRoomNotification",
(typeof(PlayerJoiningMessage), delegate(object msg)
{
PlayerJoiningResponseHandler.handle((PlayerJoiningMessage)msg);
})
},
{
"Kicked",
(typeof(KickHandler), delegate
{
KickHandler.handle();
})
},
{
"KickNotification",
(typeof(KickNotification), delegate(object msg)
{
KickNotificationHandler.handle((KickNotification)msg);
})
},
{
"LevelClaimed",
(typeof(LevelClaimNotification), delegate(object msg)
{
LevelClaimHandler.handle((LevelClaimNotification)msg);
})
},
{
"MapPing",
(typeof(MapPingNotification), delegate(object msg)
{
MapPingNotificationHandler.handle((MapPingNotification)msg);
})
},
{
"MapPools",
(typeof(MapPoolResponse), delegate(object msg)
{
MapPoolResponseHandler.handle((MapPoolResponse)msg);
})
},
{
"ModVerificationResponse",
(typeof(ModVerificationResponse), delegate(object msg)
{
ModVerificationHandler.handle((ModVerificationResponse)msg);
})
},
{
"NewHostNotification",
(typeof(HostMigration), delegate(object msg)
{
HostMigrationHandler.handle((HostMigration)msg);
})
},
{
"RerollVote",
(typeof(RerollVoteNotification), delegate(object msg)
{
RerollVoteNotificationHandler.handle((RerollVoteNotification)msg);
})
},
{
"RerollSuccess",
(typeof(RerollSuccessNotification), delegate(object msg)
{
RerollSuccessNotificationHandler.handle((RerollSuccessNotification)msg);
})
},
{
"RerollExpire",
(typeof(RerollExpireNotification), delegate(object msg)
{
RerollExpireNotificationHandler.handle((RerollExpireNotification)msg);
})
},
{
"ReconnectResponse",
(typeof(ReconnectResponse), delegate(object msg)
{
ReconnectResponseHandler.handle((ReconnectResponse)msg);
})
},
{
"RoomUpdate",
(typeof(UpdateRoomSettingsNotification), delegate(object msg)
{
UpdateRoomSettingsHandler.handle((UpdateRoomSettingsNotification)msg);
})
},
{
"StartGame",
(typeof(StartGameResponse), delegate(object msg)
{
StartGameResponseHandler.handle((StartGameResponse)msg);
})
},
{
"ServerDisconnection",
(typeof(DisconnectSignal), delegate(object msg)
{
DisconnectSignalHandler.handle((DisconnectSignal)msg);
})
},
{
"TimeoutNotification",
(typeof(TimeoutSignal), delegate(object msg)
{
TimeoutSignalHandler.handle((TimeoutSignal)msg);
})
},
{
"UpdateTeamsNotif",
(typeof(UpdateTeamsNotification), delegate(object msg)
{
UpdateTeamsNotificationHandler.handle((UpdateTeamsNotification)msg);
})
}
};
public static void setState(State newState)
{
currentState = newState;
}
public static void HandleAsyncConnect()
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
SetupHeartbeat();
switch (pendingAction)
{
case AsyncAction.Host:
CreateRoom();
break;
case AsyncAction.Join:
JoinGame(pendingPassword);
break;
case AsyncAction.ModCheck:
SendEncodedMessage(JsonConvert.SerializeObject((object)pendingVmr));
break;
case AsyncAction.RetrySend:
SendEncodedMessage(JsonConvert.SerializeObject((object)QueuedMessage));
QueuedMessage = "";
break;
case AsyncAction.ReconnectGame:
{
Logging.Warn("Requesting to reconnect");
ReconnectRequest reconnectRequest = new ReconnectRequest();
SteamId steamId = SteamClient.SteamId;
reconnectRequest.steamId = ((object)(SteamId)(ref steamId)).ToString();
reconnectRequest.roomId = GameManager.CurrentGame.gameId;
reconnectRequest.ticket = CreateRegisterTicket();
SendEncodedMessage(JsonConvert.SerializeObject((object)reconnectRequest));
break;
}
case AsyncAction.FetchGames:
SendEncodedMessage(JsonConvert.SerializeObject((object)new FetchGamesRequest()));
break;
}
}
public static void SendModCheck(VerifyModRequest vmr)
{
pendingAction = AsyncAction.ModCheck;
pendingVmr = vmr;
ConnectWebSocket();
}
public static string GetSteamTicket()
{
return steamTicket;
}
public static void SetSteamTicket(string ticket)
{
steamTicket = ticket;
}
public static async Task<string> FetchCatalog(string urlToRequest)
{
try
{
return await Client.GetStringAsync(urlToRequest);
}
catch (Exception ex)
{
Logging.Error("Something went wrong while fetching from the URL");
Logging.Error(ex.Message);
return null;
}
}
public static bool IsConnectionUp()
{
return ws.IsAlive;
}
public static void Initialise(string url, string port, bool isDev = false)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
serverURL = (isDev ? "ws://127.0.0.1:2052" : ("ws://" + url + ":" + port));
ws = new WebSocket(serverURL, Array.Empty<string>());
ws.EnableRedirection = true;
ws.WaitTime = TimeSpan.FromSeconds(15.0);
ws.OnOpen += delegate
{
HandleAsyncConnect();
};
ws.OnMessage += delegate(object sender, MessageEventArgs e)
{
onMessageRecieved(e);
};
ws.OnError += delegate(object sender, ErrorEventArgs e)
{
HandleError(e);
};
ws.OnClose += delegate(object sender, CloseEventArgs e)
{
if (e.WasClean)
{
Logging.Message("Disconnected cleanly from server");
}
else
{
Logging.Error("Network connection error.");
Logging.Error(e.Reason);
Logging.Error(e.Code.ToString());
lastErrorString = e.Reason + "(" + e.Code + ")";
}
};
}
public static void TryReconnect()
{
pendingAction = AsyncAction.ReconnectGame;
ConnectWebSocket();
}
public static async void HandleError(ErrorEventArgs e)
{
Logging.Error("Network error happened");
if (ws.IsAlive)
{
ws.CloseAsync();
return;
}
switch (currentState)
{
case State.NORMAL:
Logging.Error("Unable to perform startup connection to server");
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Failed to connect to Baphomet's Bingo server.", "", "", 0, false, false, true);
break;
case State.INMENU:
Logging.Error("Unable to connect to server to join/host game");
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Failed to contact server.", "", "", 0, false, false, true);
BingoMainMenu.UnlockUI();
break;
case State.INLOBBY:
Logging.Error("Network error happened in lobby");
Logging.Error(e.Message);
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Connection to the lobby was lost. Returning to menu.", "", "", 0, false, false, true);
GameManager.ClearGameVariables();
setState(State.INMENU);
BingoEncapsulator.BingoCardScreen.SetActive(false);
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoEndScreen.SetActive(false);
BingoEncapsulator.BingoMenu.SetActive(true);
BingoLobby.UnlockUI();
break;
case State.INGAME:
Logging.Error("Network error happened in-game");
if (GameManager.IsInBingoLevel)
{
currentReconnection++;
if (currentReconnection > maxReconnectionAttempts)
{
currentReconnection = 0;
GameManager.ClearGameVariables();
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Failed to reconnect. Exitting game in 5 seconds.", "", "", 0, false, false, true);
setState(State.NORMAL);
await Task.Delay(5000);
SceneHelper.LoadScene("Main Menu", false);
}
else
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Connection to the game was lost.\nAttempting reconnection... <color=orange>(" + currentReconnection + "/" + maxReconnectionAttempts + ")</color>", "", "", 0, false, false, true);
await Task.Delay(2000);
TryReconnect();
}
}
break;
case State.INBROWSER:
Logging.Error("Network error happened in-browser");
if (!BingoBrowser.fetchDone)
{
BingoBrowser.DisplayError();
}
else
{
BingoBrowser.UnlockUI();
}
break;
}
}
public static string DecodeMessage(string encodedMessage)
{
byte[] bytes = Convert.FromBase64String(encodedMessage);
return Encoding.UTF8.GetString(bytes);
}
public static void SendEncodedMessage(string jsonToEncode)
{
if (!ws.IsAlive)
{
Logging.Warn("Queuing message & retrying connection");
QueuedMessage = jsonToEncode;
pendingAction = AsyncAction.RetrySend;
ws.ConnectAsync();
return;
}
string text = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonToEncode));
ws.SendAsync(text, (Action<bool>)delegate(bool completed)
{
if (!completed)
{
Logging.Warn("Async not sent");
}
});
}
public static RegisterTicket CreateRegisterTicket()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
RegisterTicket registerTicket = new RegisterTicket();
SteamId steamId = SteamClient.SteamId;
registerTicket.steamId = ((object)(SteamId)(ref steamId)).ToString();
registerTicket.steamTicket = GetSteamTicket();
registerTicket.steamUsername = SteamClient.Name;
registerTicket.gameId = GameManager.CurrentGame.gameId;
return registerTicket;
}
public static void RegisterConnection()
{
Logging.Message("Registering connection with server");
SendEncodedMessage(JsonConvert.SerializeObject((object)CreateRegisterTicket()));
}
public static void ConnectWebSocket()
{
if (!ws.IsAlive)
{
ws.ConnectAsync();
}
}
public static void DisconnectWebSocket(ushort code = 1000, string reason = "Disconnect reason not specified")
{
ws.Close(code, reason);
}
public static void SetupHeartbeat()
{
heartbeatTimer = new Timer(10000.0);
heartbeatTimer.Elapsed += SendPing;
heartbeatTimer.AutoReset = true;
heartbeatTimer.Enabled = true;
}
public static void SendPing(object source, ElapsedEventArgs e)
{
ws.Ping();
}
public static void CreateRoom()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
CreateRoomRequest obj = new CreateRoomRequest
{
roomName = "TestRoom",
roomPassword = "password",
maxPlayers = 8,
pRankRequired = false,
hostSteamName = CommonFunctions.sanitiseUsername(SteamClient.Name)
};
SteamId steamId = SteamClient.SteamId;
obj.hostSteamId = ((object)(SteamId)(ref steamId)).ToString();
obj.rank = (GameManager.hasRankAccess ? requestedRank : "");
SendEncodedMessage(JsonConvert.SerializeObject((object)obj));
}
public static void JoinGame(string password)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
JoinRoomRequest obj = new JoinRoomRequest
{
password = password,
username = CommonFunctions.sanitiseUsername(SteamClient.Name)
};
SteamId steamId = SteamClient.SteamId;
obj.steamId = ((object)(SteamId)(ref steamId)).ToString();
obj.rank = (GameManager.hasRankAccess ? requestedRank : "");
SendEncodedMessage(JsonConvert.SerializeObject((object)obj));
}
public static void SendStartGameSignal(int roomId)
{
SendEncodedMessage(JsonConvert.SerializeObject((object)new StartGameRequest
{
roomId = roomId,
ticket = CreateRegisterTicket(),
selectedMapIds = BingoMapBrowser.selectedLevels
}));
}
public static void SubmitRun(SubmitRunRequest srr)
{
SendEncodedMessage(JsonConvert.SerializeObject((object)srr));
}
public static void SendLeaveGameRequest(int roomId)
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
LeaveGameRequest obj = new LeaveGameRequest
{
username = CommonFunctions.sanitiseUsername(SteamClient.Name)
};
SteamId steamId = SteamClient.SteamId;
obj.steamId = ((object)(SteamId)(ref steamId)).ToString();
obj.roomId = roomId;
SendEncodedMessage(JsonConvert.SerializeObject((object)obj));
}
public static void KickPlayer(string steamId)
{
SendEncodedMessage(JsonConvert.SerializeObject((object)new KickPlayer
{
gameId = GameManager.CurrentGame.gameId,
playerToKick = steamId,
ticket = CreateRegisterTicket()
}));
}
public static void RequestGames()
{
pendingAction = AsyncAction.FetchGames;
ws.ConnectAsync();
}
public static void onMessageRecieved(MessageEventArgs e)
{
Main.Queue(delegate
{
EncapsulatedMessage encapsulatedMessage = JsonConvert.DeserializeObject<EncapsulatedMessage>(DecodeMessage(e.Data));
if (encapsulatedMessage.header != "Pong")
{
if (messages.TryGetValue(encapsulatedMessage.header, out (Type, Action<object>) value))
{
object obj = JsonConvert.DeserializeObject(encapsulatedMessage.contents, value.Item1);
value.Item2(obj);
}
else
{
Logging.Warn("Unknown or unimplemented packet received from server (" + encapsulatedMessage.header + "), discarding");
}
}
});
}
}
[BepInPlugin("clearwater.ultrakillbingo.ultrakillbingo", "Baphomet's BINGO", "1.2.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Main : BaseUnityPlugin
{
public const string pluginId = "clearwater.ultrakillbingo.ultrakillbingo";
public const string pluginName = "Baphomet's BINGO";
public const string pluginVersion = "1.2.1";
public static bool IsDevelopmentBuild = false;
public static bool IsSteamAuthenticated = false;
public static bool HasUnlocked = true;
public static bool UpdateAvailable = false;
public static List<string> LoadedMods = new List<string>();
private static readonly ConcurrentQueue<Action> actions = new ConcurrentQueue<Action>();
public static string ModFolder => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
public static void Queue(Action action)
{
actions.Enqueue(action);
}
private void Awake()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
Logging.Message("--Now loading Baphomet's Bingo...--");
Debug.unityLogger.filterLogType = (LogType)2;
Logging.Message("--Loading asset bundle...--");
AssetLoader.LoadAssets();
Logging.Message("--Applying patches...--");
new Harmony("clearwater.ultrakillbingo.ultrakillbingo").PatchAll();
Logging.Message("--Network manager init...--");
NetworkManager.serverURLConfig = ((BaseUnityPlugin)this).Config.Bind<string>("ServerConfig", "serverUrl", "clearwaterbirb.uk", "Server URL");
NetworkManager.serverPortConfig = ((BaseUnityPlugin)this).Config.Bind<string>("ServerConfig", "serverPort", "2052", "Server Port");
NetworkManager.lastRankUsedConfig = ((BaseUnityPlugin)this).Config.Bind<string>("ServerConfig", "lastRankUsed", "None", "Last Rank Used (Only works if your SteamID has access to this rank)");
if (!Directory.Exists(Path.Combine(ModFolder, "ThumbnailCache")))
{
Logging.Message("--Thumbnail cache folder doesn't exist, creating now---");
Directory.CreateDirectory(Path.Combine(ModFolder, "ThumbnailCache"));
}
string value = NetworkManager.serverURLConfig.Value;
string value2 = NetworkManager.serverPortConfig.Value;
NetworkManager.Initialise(value, value2, IsDevelopmentBuild);
Logging.Message("--Done!--");
SceneManager.sceneLoaded += onSceneLoaded;
}
private void Update()
{
Action result;
while (actions.TryDequeue(out result))
{
result();
}
}
public bool Authenticate()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
Logging.Message("Authenticating game ownership with Steam...");
try
{
AuthTicket authSessionTicket = SteamUser.GetAuthSessionTicket(default(NetIdentity));
string text = BitConverter.ToString(authSessionTicket.Data, 0, authSessionTicket.Data.Length).Replace("-", string.Empty);
if (text.Length > 0)
{
IsSteamAuthenticated = true;
NetworkManager.SetSteamTicket(text);
return true;
}
}
catch (Exception ex)
{
Logging.Error("Unable to authenticate with Steam!");
Logging.Error(ex.ToString());
return false;
}
return false;
}
public void VerifyModWhitelist()
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
if (!IsSteamAuthenticated)
{
Logging.Error("Failed to authenticate with Steam! Not running whitelist check");
return;
}
Logging.Message("Validating current modlist...");
foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
{
List<string> list = ((object)pluginInfo.Value).ToString().Split(new char[1] { ' ' }).ToList();
list.RemoveAt(list.Count - 1);
string item = string.Join(" ", list);
LoadedMods.Add(item);
}
List<string> loadedMods = LoadedMods;
SteamId steamId = SteamClient.SteamId;
NetworkManager.SendModCheck(new VerifyModRequest(loadedMods, ((object)(SteamId)(ref steamId)).ToString()));
}
public void onSceneLoaded(Scene scene, LoadSceneMode mode)
{
GameManager.ResetVars();
if (CommonFunctions.getSceneName() == "Main Menu")
{
HasUnlocked = CommonFunctions.hasUnlockedMod();
if (!IsSteamAuthenticated)
{
Authenticate();
VerifyModWhitelist();
}
if (GameManager.CurrentGame != null && GameManager.CurrentGame.isGameFinished())
{
BingoEnd.ShowEndScreen();
MonoSingleton<AssistController>.Instance.majorEnabled = false;
MonoSingleton<AssistController>.Instance.gameSpeed = 1f;
}
UIManager.ultrabingoLockedPanel = Object.Instantiate<GameObject>(AssetLoader.BingoLockedPanel, CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("Canvas"), "Difficulty Select (1)").transform);
UIManager.ultrabingoErrorMessagePanel = Object.Instantiate<GameObject>(AssetLoader.BingoUnallowedModsPanel, CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("Canvas"), "Difficulty Select (1)").transform);
((TMP_Text)CommonFunctions.GetGameObjectChild(BingoMainMenu.VersionInfo, "VersionNum").GetComponent<TextMeshProUGUI>()).text = "1.2.1";
UIManager.ultrabingoLockedPanel.SetActive(false);
UIManager.ultrabingoErrorMessagePanel.SetActive(false);
}
else
{
UIManager.RemoveLimit();
if (GameManager.IsInBingoLevel && GameManager.CurrentGame.gameSettingsArray["disableCampaignAltExits"] == 1)
{
CampaignPatches.Apply(CommonFunctions.getSceneName());
}
}
}
}
}
namespace UltraBINGO
{
public static class AssetLoader
{
public static AssetBundle Assets;
public static TMP_FontAsset GameFont;
public static Font GameFontLegacy;
public static Sprite UISprite;
public static GameObject BingoEntryButton;
public static GameObject BingoPauseCard;
public static GameObject BingoMainMenu;
public static GameObject BingoLobbyMenu;
public static GameObject BingoCardElements;
public static GameObject BingoEndScreen;
public static GameObject BingoSetTeams;
public static GameObject BingoCardButtonTemplate;
public static GameObject BingoGameBrowser;
public static GameObject BingoVotePanel;
public static GameObject BingoDominationTimer;
public static GameObject BingoChat;
public static GameObject BingoMapSelection;
public static GameObject BingoInGameGridPanel;
public static GameObject BingoLockedPanel;
public static GameObject BingoUnallowedModsPanel;
public static AudioClip GameOverSound;
public static void LoadAssets()
{
Assets = AssetBundle.LoadFromFile(Path.Combine(Main.ModFolder, "bingo.resource"));
GameFont = Assets.LoadAsset<TMP_FontAsset>("VCR_OSD_MONO_EXTENDED_TMP");
GameFontLegacy = Assets.LoadAsset<Font>("VCR_OSD_MONO_LEGACY");
BingoEntryButton = Assets.LoadAsset<GameObject>("BingoEntryButton");
BingoPauseCard = Assets.LoadAsset<GameObject>("BingoPauseCard");
BingoMainMenu = Assets.LoadAsset<GameObject>("BingoMainMenu");
BingoLobbyMenu = Assets.LoadAsset<GameObject>("BingoLobbyMenu");
BingoCardElements = Assets.LoadAsset<GameObject>("BingoCard");
BingoEndScreen = Assets.LoadAsset<GameObject>("BingoEndScreen");
BingoSetTeams = Assets.LoadAsset<GameObject>("BingoSetTeams");
BingoCardButtonTemplate = Assets.LoadAsset<GameObject>("BingoGridButtonTemplate");
BingoGameBrowser = Assets.LoadAsset<GameObject>("BingoMatchBrowser");
BingoLockedPanel = Assets.LoadAsset<GameObject>("BingoLocked");
BingoUnallowedModsPanel = Assets.LoadAsset<GameObject>("BingoUnallowedMods");
BingoInGameGridPanel = Assets.LoadAsset<GameObject>("BingoInGameGrid");
BingoDominationTimer = Assets.LoadAsset<GameObject>("BingoDominationTimer");
BingoChat = Assets.LoadAsset<GameObject>("BingoChat");
BingoMapSelection = Assets.LoadAsset<GameObject>("BingoMapSelection");
UISprite = Assets.LoadAsset<Sprite>("UISprite");
GameOverSound = Assets.LoadAsset<AudioClip>("gameEnd");
BingoVotePanel = Assets.LoadAsset<GameObject>("BingoVotePanel");
}
}
public class AngryMapCatalog
{
public List<AngryBundle> Levels;
}
public class AngryBundle
{
public List<AngryLevel> Levels;
public string Name;
public string Author;
public int size;
public string Guid;
public string Hash;
public string ThumbnailHash;
public bool locked;
}
public class AngryLevel
{
public string LevelName;
public string LevelId;
}
public class MapPoolContainer
{
public string mapPoolId;
public string mapPoolName;
public string description;
public int numOfMaps;
public List<string> mapList;
public MapPoolContainer(string mapPoolId, string mapPoolName, string description, int numOfMaps, List<string> mapList)
{
this.mapPoolId = mapPoolId;
this.mapPoolName = mapPoolName;
this.description = description;
this.numOfMaps = numOfMaps;
this.mapList = mapList;
}
}
public class Player
{
public string username;
public string steamId;
public string rank;
}
public class GameLevel
{
public string levelName;
public string levelId;
public string claimedBy;
public string personToBeat;
public float timeToBeat;
public int row;
public int column;
public bool isAngryLevel;
public string angryParentBundle;
public string angryLevelId;
}
public class GameGrid
{
public int size;
public Dictionary<string, GameLevel> levelTable;
}
public class Game
{
public int gameId;
public Dictionary<string, Player> currentPlayers;
public GameGrid grid;
public string gameHost;
public int gameState;
public Dictionary<string, int> gameSettingsArray;
public string winningTeam;
public List<Player> getPlayers()
{
return currentPlayers.Values.ToList();
}
public bool isGameFinished()
{
return gameState == 2;
}
}
public static class CampaignPatches
{
public static void Apply(string levelName)
{
if (levelName == null)
{
return;
}
int length = levelName.Length;
if (length != 9)
{
return;
}
switch (levelName[6])
{
case '0':
if (levelName == "Level 0-2")
{
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("5B - Secret Arena"), "5B Nonstuff"), "Altar (Blue Skull) Variant").SetActive(false);
}
break;
case '1':
if (levelName == "Level 1-1")
{
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("1 - First Field"), "1 Stuff"), "Fountain");
((Behaviour)gameObjectChild.GetComponent<Door>()).enabled = false;
GameObject gameObject = ((Component)gameObjectChild.transform.GetChild(0)).gameObject;
GameObject gameObject2 = ((Component)gameObjectChild.transform.GetChild(1)).gameObject;
gameObject.SetActive(false);
gameObject2.SetActive(false);
GameObject gameObjectChild2 = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("1 - First Field"), "1 Nonstuff"), "FinalRoom 1");
gameObjectChild2.SetActive(false);
((Behaviour)gameObjectChild2.GetComponent<FinalRoom>()).enabled = false;
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("1 - First Field"), "1 Nonstuff"), "FinalRoom SecretEntrance").SetActive(false);
}
break;
case '2':
if (levelName == "Level 2-3")
{
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("4 - End Hallway"), "4 Nonstuff"), "ElectricityBox").SetActive(false);
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Sewer Arena"), "2 Nonstuff"), "Secret Level Entrance").SetActive(false);
}
break;
case '3':
if (levelName == "Level 3-1")
{
((Behaviour)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("6S - P Door"), "6S Nonstuff"), "HellgateLimboSwitch Variant").GetComponent<LimboSwitchLock>()).enabled = false;
}
break;
case '4':
if (levelName == "Level 4-2")
{
CommonFunctions.GetInactiveRootObject("GreedSwitch Variant").SetActive(false);
}
break;
case '5':
if (levelName == "Level 5-1")
{
((Behaviour)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Elevator"), "2B Secret"), "FinalRoom 1"), "FinalDoor").GetComponent<FinalDoor>()).enabled = false;
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Elevator"), "2B Secret"), "FinalRoom 1").SetActive(false);
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Elevator"), "2B Secret"), "FinalRoom SecretEntrance").SetActive(false);
}
break;
case '6':
if (levelName == "Level 6-2")
{
((Behaviour)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("1S - P Door"), "6S Nonstuff"), "ToActivate"), "HellgateLimboSwitch Variant").GetComponent<LimboSwitchLock>()).enabled = false;
}
break;
case '7':
if (levelName == "Level 7-3")
{
((Behaviour)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("Doors"), "1 -> S"), "Plane (1)").GetComponent<Flammable>()).enabled = false;
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Garden Maze"), "Secret"), "FinalRoom 1"), "Pit").SetActive(false);
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("2 - Garden Maze"), "Secret"), "FinalRoom SecretEntrance").SetActive(false);
}
break;
}
}
}
public static class CommonFunctions
{
public static string sanitiseUsername(string rawUsername)
{
return Regex.Replace(rawUsername, "\\p{Cs}", "");
}
public static bool checkIfLevelSaveExists(string savePath, string fileName)
{
return File.Exists(Path.Combine(savePath, string.Format("Slot{0}/" + fileName, GameProgressSaver.currentSlot + 1)));
}
public static bool hasUnlockedMod()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Invalid comparison between Unknown and I4
return checkIfLevelSaveExists(Path.Combine(((int)SystemInfo.deviceType == 3) ? Directory.GetParent(Application.dataPath).FullName : Application.persistentDataPath, "Saves"), "lvl29progress.bepis");
}
public static string getSceneName()
{
return SceneHelper.CurrentScene;
}
public static GameObject GetInactiveRootObject(string objectName)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
List<GameObject> list = new List<GameObject>();
Scene activeScene = SceneManager.GetActiveScene();
((Scene)(ref activeScene)).GetRootGameObjects(list);
foreach (GameObject item in list)
{
if (((Object)item).name == objectName)
{
return item;
}
}
return null;
}
public static IEnumerator WaitforSeconds(float seconds)
{
yield return (object)new WaitForSeconds(seconds);
}
public static GameObject GetGameObjectChild(GameObject parentObject, string childToFind)
{
try
{
return ((Component)parentObject.transform.Find(childToFind)).gameObject;
}
catch (Exception)
{
Logging.Warn("Couldn't find requested child gameObject " + childToFind + " in parent gameObject '" + ((Object)parentObject).name + "'");
return null;
}
}
public static TextMeshProUGUI GetTextMeshProGUI(GameObject objectToUse)
{
return objectToUse.GetComponent<TextMeshProUGUI>();
}
public static Text GetTextfromGameObject(GameObject objectToUse)
{
return objectToUse.GetComponent<Text>();
}
public static string getFormattedTime(float time)
{
float num = time;
float num2 = 0f;
while (num >= 60f)
{
num -= 60f;
num2 += 1f;
}
return num2 + ":" + num.ToString("00.000");
}
}
public static class GameManager
{
public static Game CurrentGame;
public static bool IsInBingoLevel = false;
public static bool ReturningFromBingoLevel = false;
public static int CurrentRow = 0;
public static int CurrentColumn = 0;
public static string CurrentTeam = "";
public static List<string> Teammates;
public static bool HasSent = false;
public static bool EnteringAngryLevel = false;
public static bool TriedToActivateCheats = false;
public static bool IsDownloadingLevel = false;
public static bool IsSwitchingLevels = false;
public static bool alreadyStartedVote = false;
public static bool isUsingCustomMappool = false;
public static List<string> customMappool = new List<string>();
public static GameObject LevelBeingDownloaded = null;
public static float dominationTimer = 0f;
public static bool hasRankAccess = false;
public static bool canUseChat = true;
public static VoteData voteData = new VoteData(ongoing: false);
public static Dictionary<string, ICheat> cheatList;
public static async void SwapRerolledMap(string oldMapId, GameLevel level, int column, int row)
{
if (IsInBingoLevel && CurrentGame != null)
{
CurrentGame.grid.levelTable[column + "-" + row] = level;
BingoLevelData component = CommonFunctions.GetGameObjectChild(BingoCardPauseMenu.Grid, column + "-" + row).GetComponent<BingoLevelData>();
component.isAngryLevel = level.isAngryLevel;
component.angryParentBundle = level.angryParentBundle;
component.angryLevelId = level.angryLevelId;
component.levelName = level.levelName;
}
if (oldMapId == CommonFunctions.getSceneName())
{
Logging.Message("Currently on old map - switching in 5 seconds");
await Task.Delay(5000);
((UnityEvent)CommonFunctions.GetGameObjectChild(BingoCardPauseMenu.Grid, column + "-" + row).GetComponent<Button>().onClick).Invoke();
}
}
public static void UpdateGridPosition(int row, int column)
{
CurrentRow = row;
CurrentColumn = column;
}
public static void ClearGameVariables()
{
if (CurrentGame.gameSettingsArray["gameModifier"] > 0)
{
MonoSingleton<AssistController>.Instance.cheatsEnabled = true;
MonoSingleton<CheatsManager>.Instance.SetCheatActive(cheatList["ultrakill.disable-enemy-spawns"], false, true);
MonoSingleton<CheatsManager>.Instance.SetCheatActive(cheatList["ultrakill.hide-weapons"], false, true);
MonoSingleton<AssistController>.Instance.cheatsEnabled = false;
}
CurrentGame = null;
CurrentTeam = null;
CurrentRow = 0;
CurrentColumn = 0;
IsInBingoLevel = false;
ReturningFromBingoLevel = false;
Teammates = null;
voteData = null;
if (CommonFunctions.getSceneName() == "Main Menu")
{
BingoCard.Cleanup();
BingoChatManager.clearChatHistory();
}
}
public static void HumiliateSelf()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
CheatActivation obj = new CheatActivation
{
username = CommonFunctions.sanitiseUsername(SteamClient.Name),
gameId = CurrentGame.gameId
};
SteamId steamId = SteamClient.SteamId;
obj.steamId = ((object)(SteamId)(ref steamId)).ToString();
NetworkManager.SendEncodedMessage(JsonConvert.SerializeObject((object)obj));
}
public static void LeaveGame(bool isInLevel = false)
{
NetworkManager.SendLeaveGameRequest(CurrentGame.gameId);
Logging.Message("Closing connection");
NetworkManager.DisconnectWebSocket(1000, "Normal close");
ClearGameVariables();
BingoMapBrowser.selectedLevels.Clear();
BingoMapBrowser.selectedLevelNames.Clear();
if (!isInLevel)
{
BingoEncapsulator.BingoCardScreen.SetActive(false);
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoEndScreen.SetActive(false);
BingoEncapsulator.BingoMenu.SetActive(true);
NetworkManager.setState(State.INMENU);
BingoMapBrowser.ResetListPosition();
}
else
{
NetworkManager.setState(State.NORMAL);
}
BingoMapBrowser.hasFetched = false;
BingoMapBrowser.levelCatalog = new List<GameObject>();
}
public static void MoveToCard(int gameType)
{
BingoCard.UpdateTitles(gameType);
BingoLobby.UnlockUI();
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoCardScreen.SetActive(true);
}
public static bool PlayerIsHost()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
SteamId steamId = SteamClient.SteamId;
return ((object)(SteamId)(ref steamId)).ToString() == CurrentGame.gameHost;
}
public static bool PreStartChecks()
{
int num = CurrentGame.gameSettingsArray["gridSize"] + 3;
int num2 = num * num;
if (BingoMapBrowser.selectedLevels.Count < num2)
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Not enough maps selected. Add more map pools, or reduce the grid size.\n(<color=orange>" + num2 + " </color>required, <color=orange>" + BingoMapBrowser.selectedLevels.Count + "</color> selected)", "", "", 0, false, false, true);
return false;
}
if (CurrentGame.gameSettingsArray["teamComposition"] == 1 && CurrentGame.gameSettingsArray["hasManuallySetTeams"] == 0)
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("Teams must be set before starting the game.", "", "", 0, false, false, true);
return false;
}
return true;
}
public static void ResetVars()
{
HasSent = false;
EnteringAngryLevel = false;
TriedToActivateCheats = false;
IsSwitchingLevels = false;
}
public static void RefreshPlayerList()
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_0217: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Expected O, but got Unknown
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
//IL_0246: Unknown result type (might be due to invalid IL or missing references)
//IL_024b: Unknown result type (might be due to invalid IL or missing references)
//IL_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!(CommonFunctions.getSceneName() == "Main Menu"))
{
return;
}
BingoLobby.PlayerList.SetActive(false);
string gameHost = CurrentGame.gameHost;
SteamId steamId2 = SteamClient.SteamId;
_ = gameHost == ((object)(SteamId)(ref steamId2)).ToString();
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(BingoLobby.PlayerList, "PlayerList");
GameObject gameObjectChild2 = CommonFunctions.GetGameObjectChild(gameObjectChild, "PlayerTemplate");
foreach (Transform item in gameObjectChild.transform)
{
Transform val = item;
if (((Object)((Component)val).gameObject).name != "PlayerTemplate")
{
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
foreach (string steamId in CurrentGame.currentPlayers.Keys.ToList())
{
GameObject obj = Object.Instantiate<GameObject>(gameObjectChild2, gameObjectChild.transform);
string text = "";
if (steamId == CurrentGame.gameHost)
{
text = "<color=orange>" + Regex.Replace(CurrentGame.currentPlayers[steamId].username, "^<[^>]*>", "") + "</color>";
}
CommonFunctions.GetGameObjectChild(obj, "PlayerName").GetComponent<Text>().text = ((steamId == CurrentGame.gameHost) ? text : CurrentGame.currentPlayers[steamId].username) + ((CurrentGame.currentPlayers[steamId].rank != "") ? (" | " + CurrentGame.currentPlayers[steamId].rank) : "");
((UnityEvent)CommonFunctions.GetGameObjectChild(obj, "Kick").GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
NetworkManager.KickPlayer(steamId);
});
CommonFunctions.GetGameObjectChild(obj, "Kick").transform.localScale = Vector3.one;
GameObject gameObjectChild3 = CommonFunctions.GetGameObjectChild(obj, "Kick");
steamId2 = SteamClient.SteamId;
int active;
if (((object)(SteamId)(ref steamId2)).ToString() == CurrentGame.gameHost)
{
string text2 = steamId;
steamId2 = SteamClient.SteamId;
active = ((text2 != ((object)(SteamId)(ref steamId2)).ToString()) ? 1 : 0);
}
else
{
active = 0;
}
gameObjectChild3.SetActive((byte)active != 0);
obj.SetActive(true);
}
BingoLobby.PlayerList.SetActive(true);
}
catch (Exception ex)
{
Logging.Error("Something went wrong when trying to update player list");
Logging.Error(ex.ToString());
}
}
public static void SetupBingoCardDynamic()
{
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_027a: Unknown result type (might be due to invalid IL or missing references)
//IL_029b: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: Expected O, but got Unknown
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(BingoCard.Root, "BingoGrid");
gameObjectChild.GetComponent<GridLayoutGroup>().constraintCount = CurrentGame.grid.size;
gameObjectChild.GetComponent<GridLayoutGroup>().spacing = new Vector2(30f, 30f);
gameObjectChild.GetComponent<GridLayoutGroup>().cellSize = new Vector2(150f, 50f);
for (int i = 0; i < CurrentGame.grid.size; i++)
{
for (int j = 0; j < CurrentGame.grid.size; j++)
{
GameObject level = Object.Instantiate<GameObject>(AssetLoader.BingoCardButtonTemplate, gameObjectChild.transform);
string lvlCoords = i + "-" + j;
((Object)level).name = lvlCoords;
GameLevel levelObject = CurrentGame.grid.levelTable[lvlCoords];
CommonFunctions.GetGameObjectChild(level, "Text").GetComponent<Text>().text = levelObject.levelName;
level.AddComponent<BingoLevelData>();
level.GetComponent<BingoLevelData>().column = i;
level.GetComponent<BingoLevelData>().row = j;
level.GetComponent<BingoLevelData>().isAngryLevel = levelObject.isAngryLevel;
level.GetComponent<BingoLevelData>().angryParentBundle = levelObject.angryParentBundle;
level.GetComponent<BingoLevelData>().angryLevelId = levelObject.angryLevelId;
level.GetComponent<BingoLevelData>().levelName = levelObject.levelName;
((UnityEventBase)level.GetComponent<Button>().onClick).RemoveAllListeners();
((UnityEvent)level.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
BingoMenuController.LoadBingoLevel(levelObject.levelId, lvlCoords, level.GetComponent<BingoLevelData>());
});
level.transform.SetParent(BingoCard.Grid.transform);
level.SetActive(true);
}
}
switch (CurrentGame.grid.size)
{
case 3:
gameObjectChild.transform.localPosition = new Vector3(-200f, 100f, 0f);
break;
case 4:
gameObjectChild.transform.localPosition = new Vector3(-275f, 122f, 0f);
break;
case 5:
gameObjectChild.transform.localPosition = new Vector3(-350f, 145f, 0f);
break;
}
TextMeshProUGUI component = CommonFunctions.GetGameObjectChild(BingoCard.Teammates, "Players").GetComponent<TextMeshProUGUI>();
((TMP_Text)component).text = "";
foreach (string teammate in Teammates)
{
((TMP_Text)component).text = ((TMP_Text)component).text + teammate + "\n";
}
alreadyStartedVote = false;
}
public static void SetupJoinMidgameDetails(Game game, string team, List<string> teammates, int remainingDominationTime, bool needsTeam)
{
CurrentGame = game;
BingoEncapsulator.BingoMenu.SetActive(false);
BingoEncapsulator.BingoGameBrowser.SetActive(false);
CurrentTeam = team;
Teammates = teammates;
if (game.gameSettingsArray["gamemode"] == 1)
{
dominationTimer = remainingDominationTime;
}
NetworkManager.setState(State.INLOBBY);
NetworkManager.RegisterConnection();
BingoMenuController.StartGame(game.gameSettingsArray["gamemode"], isJoiningMidGame: true);
}
public static async void SetupGameDetails(Game game, string password, bool isHost = true)
{
CurrentGame = game;
BingoEncapsulator.BingoMenu.SetActive(false);
BingoEncapsulator.BingoGameBrowser.SetActive(false);
TextMeshProUGUI[] componentsInChildren = BingoEncapsulator.BingoLobbyScreen.GetComponentsInChildren<TextMeshProUGUI>(true);
foreach (TextMeshProUGUI text in componentsInChildren)
{
await Task.Delay(1);
((TMP_Text)text).ForceMeshUpdate(false, false);
}
BingoEncapsulator.BingoLobbyScreen.SetActive(true);
ShowGameId(password);
RefreshPlayerList();
((Selectable)BingoLobby.MaxPlayers).interactable = isHost;
((Selectable)BingoLobby.MaxTeams).interactable = isHost;
((Selectable)BingoLobby.TimeLimit).interactable = isHost;
((Selectable)BingoLobby.TeamComposition).interactable = isHost;
((Selectable)BingoLobby.GridSize).interactable = isHost;
((Selectable)BingoLobby.Gamemode).interactable = isHost;
((Selectable)BingoLobby.Difficulty).interactable = isHost;
((Selectable)BingoLobby.RequirePRank).interactable = isHost;
((Selectable)BingoLobby.DisableCampaignAltExits).interactable = isHost;
((Selectable)BingoLobby.GameVisibility).interactable = isHost;
((Selectable)BingoLobby.AllowRejoin).interactable = isHost;
((Selectable)BingoLobby.GameModifiers).interactable = isHost;
BingoLobby.StartGame.SetActive(isHost);
BingoLobby.SelectMaps.SetActive(isHost);
BingoLobby.RoomIdDisplay.SetActive(isHost);
BingoLobby.CopyId.SetActive(isHost);
((Selectable)BingoLobby.SetTeams.GetComponent<Button>()).interactable = isHost;
if (isHost)
{
BingoLobby.MaxPlayers.text = 8.ToString();
BingoLobby.MaxTeams.text = 4.ToString();
BingoLobby.TeamComposition.value = 0;
BingoLobby.GridSize.value = 0;
BingoLobby.Gamemode.value = 0;
BingoLobby.TimeLimit.text = 5.ToString();
BingoLobby.Difficulty.value = 2;
BingoLobby.RequirePRank.isOn = false;
BingoLobby.DisableCampaignAltExits.isOn = false;
BingoLobby.GameVisibility.value = 0;
BingoLobby.AllowRejoin.isOn = false;
BingoLobby.GameModifiers.value = 0;
}
else
{
BingoLobby.MaxPlayers.text = CurrentGame.gameSettingsArray["maxPlayers"].ToString();
BingoLobby.MaxTeams.text = CurrentGame.gameSettingsArray["maxTeams"].ToString();
BingoLobby.TimeLimit.text = CurrentGame.gameSettingsArray["timeLimit"].ToString();
BingoLobby.TeamComposition.value = CurrentGame.gameSettingsArray["teamComposition"];
BingoLobby.GridSize.value = CurrentGame.gameSettingsArray["gridSize"];
BingoLobby.Gamemode.value = CurrentGame.gameSettingsArray["gamemode"];
BingoLobby.Difficulty.value = CurrentGame.gameSettingsArray["difficulty"];
BingoLobby.RequirePRank.isOn = CurrentGame.gameSettingsArray["requiresPRank"] == 1;
BingoLobby.DisableCampaignAltExits.isOn = CurrentGame.gameSettingsArray["disableCampaignAltExits"] == 1;
BingoLobby.GameVisibility.value = CurrentGame.gameSettingsArray["gameVisibility"];
BingoLobby.AllowRejoin.isOn = CurrentGame.gameSettingsArray["allowRejoin"] == 1;
BingoLobby.GameModifiers.value = CurrentGame.gameSettingsArray["gameModifier"];
}
MonoSingleton<BingoChatManager>.Instance.updateChatPanel();
NetworkManager.setState(State.INLOBBY);
NetworkManager.RegisterConnection();
}
public static void ShowGameId(string password)
{
CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(BingoLobby.RoomIdDisplay, "Title"), "Text").GetComponent<Text>().text = "Game ID: " + password;
}
public static void StartGame()
{
NetworkManager.SendStartGameSignal(CurrentGame.gameId);
}
public static void UpdateCards(int row, int column, string team, string playername, float newTime)
{
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
string text = row + "-" + column;
CurrentGame.grid.levelTable.Keys.ToList();
if (!CurrentGame.grid.levelTable.ContainsKey(text))
{
Logging.Error("RECEIVED AN INVALID GRID POSITION TO UPDATE!");
Logging.Error(text);
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("A level was claimed by someone but an <color=orange>invalid grid position</color> was given.\nCheck BepInEx console and report it to Clearwater!", "", "", 0, false, false, true);
return;
}
try
{
CurrentGame.grid.levelTable[text].claimedBy = team;
CurrentGame.grid.levelTable[text].timeToBeat = newTime;
Color value;
if (CommonFunctions.getSceneName() == "Main Menu")
{
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(BingoEncapsulator.BingoCardScreen, "BingoGrid");
((Graphic)CommonFunctions.GetGameObjectChild(gameObjectChild, text).GetComponent<Image>()).color = BingoCardPauseMenu.teamColors[team];
CommonFunctions.GetGameObjectChild(gameObjectChild, text).GetComponent<BingoLevelData>().isClaimed = true;
CommonFunctions.GetGameObjectChild(gameObjectChild, text).GetComponent<BingoLevelData>().claimedTeam = team;
CommonFunctions.GetGameObjectChild(gameObjectChild, text).GetComponent<BingoLevelData>().claimedPlayer = playername;
CommonFunctions.GetGameObjectChild(gameObjectChild, text).GetComponent<BingoLevelData>().timeRequirement = newTime;
}
else if (!BingoCardPauseMenu.teamColors.TryGetValue(team, out value))
{
Logging.Error("Unable to get color, throwing exception");
}
else
{
((Graphic)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(BingoCardPauseMenu.Root, "Card"), text).GetComponent<Image>()).color = BingoCardPauseMenu.teamColors[team];
((Graphic)CommonFunctions.GetGameObjectChild(BingoCardPauseMenu.inGamePanel, text).GetComponent<Image>()).color = BingoCardPauseMenu.teamColors[team];
BingoLevelData component = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(BingoCardPauseMenu.Root, "Card"), text).GetComponent<BingoLevelData>();
component.isClaimed = true;
component.claimedTeam = team;
component.claimedPlayer = playername;
component.timeRequirement = newTime;
}
}
catch (Exception ex)
{
Logging.Error("THREW AN INVALID GRID POSITION TO UPDATE!");
Logging.Error(ex.ToString());
Logging.Error(text);
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("A level was claimed by someone but the grid could not be updated.\nCheck BepInEx console and report it to Clearwater!", "", "", 0, false, false, true);
}
}
public static void RequestReroll(int row, int column)
{
//IL_003c: 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)
if (alreadyStartedVote)
{
MonoSingleton<HudMessageReceiver>.Instance.SendHudMessage("You have already used your reroll vote for this game.", "", "", 0, false, false, true);
}
else
{
RerollRequest obj = new RerollRequest
{
gameId = CurrentGame.gameId
};
SteamId steamId = SteamClient.SteamId;
obj.steamId = ((object)(SteamId)(ref steamId)).ToString();
obj.row = row;
obj.column = column;
obj.steamTicket = NetworkManager.CreateRegisterTicket();
NetworkManager.SendEncodedMessage(JsonConvert.SerializeObject((object)obj));
}
MonoSingleton<OptionsManager>.Instance.UnPause();
}
public static void PingMapForTeam(string team, int row, int column)
{
NetworkManager.SendEncodedMessage(JsonConvert.SerializeObject((object)new MapPing
{
gameId = CurrentGame.gameId,
team = team,
row = row,
column = column,
ticket = NetworkManager.CreateRegisterTicket()
}));
}
}
public static class UIManager
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__8_0;
internal void <SetupElements>b__8_0()
{
Open();
}
}
public static GameObject ultrabingoButtonObject = null;
public static GameObject ultrabingoEncapsulator = null;
public static GameObject ultrabingoLockedPanel = null;
public static GameObject ultrabingoErrorMessagePanel = null;
public static bool wasVsyncActive = false;
public static int fpsLimit = -1;
public static List<string> nonWhitelistedMods = new List<string>();
public static void HandleGameSettingsUpdate()
{
if (GameManager.PlayerIsHost())
{
NetworkManager.SendEncodedMessage(JsonConvert.SerializeObject((object)new UpdateRoomSettingsRequest
{
roomId = GameManager.CurrentGame.gameId,
updatedSettings = GameManager.CurrentGame.gameSettingsArray,
ticket = NetworkManager.CreateRegisterTicket()
}));
}
}
public static void SetupElements(CanvasController __instance)
{
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
GameObject gameObject = ((Component)((Transform)((Component)__instance).GetComponent<RectTransform>()).Find("Difficulty Select (1)")).gameObject;
if ((Object)(object)ultrabingoButtonObject == (Object)null)
{
ultrabingoButtonObject = Object.Instantiate<GameObject>(AssetLoader.BingoEntryButton, gameObject.transform);
((Object)ultrabingoButtonObject).name = "UltraBingoButton";
}
ButtonClickedEvent onClick = ultrabingoButtonObject.GetComponent<Button>().onClick;
object obj = <>c.<>9__8_0;
if (obj == null)
{
UnityAction val = delegate
{
Open();
};
<>c.<>9__8_0 = val;
obj = (object)val;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
if ((Object)(object)ultrabingoEncapsulator == (Object)null)
{
ultrabingoEncapsulator = BingoEncapsulator.Init();
((Object)ultrabingoEncapsulator).name = "UltraBingo";
ultrabingoEncapsulator.transform.parent = ((Component)__instance).transform;
ultrabingoEncapsulator.transform.localPosition = Vector3.zero;
ultrabingoEncapsulator.AddComponent<BingoMenuManager>();
}
ultrabingoEncapsulator.SetActive(false);
}
public static string PopulateUnallowedMods()
{
string text = "<color=orange>";
foreach (string nonWhitelistedMod in nonWhitelistedMods)
{
text = text + nonWhitelistedMod + "\n";
}
return text + "</color>";
}
public static void EnforceLimit()
{
wasVsyncActive = QualitySettings.vSyncCount == 1;
fpsLimit = Application.targetFrameRate;
Application.targetFrameRate = 60;
QualitySettings.vSyncCount = 1;
}
public static void RemoveLimit()
{
Application.targetFrameRate = fpsLimit;
QualitySettings.vSyncCount = (wasVsyncActive ? 1 : 0);
}
public static void showErrorMessage(string headerText, string paragraphText = "", string rowText = "")
{
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(ultrabingoErrorMessagePanel, "BingoLockedPanel"), "Panel");
TextMeshProUGUI component = CommonFunctions.GetGameObjectChild(gameObjectChild, "Text").GetComponent<TextMeshProUGUI>();
TextMeshProUGUI component2 = CommonFunctions.GetGameObjectChild(gameObjectChild, "Text (1)").GetComponent<TextMeshProUGUI>();
TextMeshProUGUI component3 = CommonFunctions.GetGameObjectChild(gameObjectChild, "ModList").GetComponent<TextMeshProUGUI>();
((TMP_Text)component).text = "<color=orange>" + headerText + "</color>";
((TMP_Text)component2).text = paragraphText;
((TMP_Text)component3).text = rowText;
ultrabingoErrorMessagePanel.SetActive(true);
}
public static void Open()
{
if (!Main.IsSteamAuthenticated)
{
showErrorMessage("Avast matey", "Unable to authenticate with Steam.\n\nYou must be connected to the Steam servers (not running in offline mode), and own a legal copy of ULTRAKILL to play Baphomet's Bingo.");
}
else if (!NetworkManager.startupDone)
{
showErrorMessage("Unable to contact server", "ULTRAKILL failed to establish a connection to the Baphomet's Bingo server. Please restart your game to try again.\nIf this keeps happening, please check your internet connection & console for any errors.\n(<color=red>" + NetworkManager.lastErrorString + "</color>)");
}
else if (!NetworkManager.modlistCheckPassed)
{
string rowText = PopulateUnallowedMods();
showErrorMessage("Non-whitelisted mods detected", "To ensure fair gameplay between players, please <color=orange>disable the following mods</color> and <color=orange>restart</color> to play Baphomet's Bingo:", rowText);
}
else if (Main.UpdateAvailable)
{
showErrorMessage("UPDATE AVAILABLE", "<color=orange>An update is available! Please update your mod to play Baphomet's Bingo.</color>");
}
else if (Main.HasUnlocked)
{
if (NetworkManager.IsConnectionUp())
{
NetworkManager.DisconnectWebSocket(1000);
GameManager.ClearGameVariables();
}
EnforceLimit();
((Component)ultrabingoButtonObject.transform.parent).gameObject.SetActive(false);
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.Root.SetActive(true);
BingoEncapsulator.BingoMenu.SetActive(true);
NetworkManager.setState(State.INMENU);
}
else
{
ultrabingoLockedPanel.SetActive(true);
}
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "UltraBINGO";
public const string PLUGIN_NAME = "UltraBINGO";
public const string PLUGIN_VERSION = "1.0.0";
}
}
namespace UltraBINGO.UI_Elements
{
public static class BingoBrowser
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__10_0;
internal void <Init>b__10_0()
{
BingoEncapsulator.BingoGameBrowser.SetActive(false);
BingoEncapsulator.BingoMenu.SetActive(true);
NetworkManager.setState(State.INMENU);
}
}
public static GameObject Root;
public static GameObject FetchText;
public static GameObject GameTemplate;
public static GameObject GameListWrapper;
public static GameObject GameList;
public static GameObject Back;
public static bool fetchDone = false;
public static List<GameObject> gameArray = new List<GameObject>();
public static void LockUI()
{
_ = ((Component)GameTemplate.transform.parent).gameObject;
foreach (GameObject item in gameArray)
{
((Selectable)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(item, "JoinWrapper"), "JoinButton").GetComponent<Button>()).interactable = false;
}
}
public static void UnlockUI()
{
foreach (GameObject item in gameArray)
{
((Selectable)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(item, "JoinWrapper"), "JoinButton").GetComponent<Button>()).interactable = true;
}
}
public static void Init(ref GameObject BingoGameBrowser)
{
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
FetchText = CommonFunctions.GetGameObjectChild(BingoGameBrowser, "FetchText");
Back = CommonFunctions.GetGameObjectChild(BingoGameBrowser, "Back");
ButtonClickedEvent onClick = Back.GetComponent<Button>().onClick;
object obj = <>c.<>9__10_0;
if (obj == null)
{
UnityAction val = delegate
{
BingoEncapsulator.BingoGameBrowser.SetActive(false);
BingoEncapsulator.BingoMenu.SetActive(true);
NetworkManager.setState(State.INMENU);
};
<>c.<>9__10_0 = val;
obj = (object)val;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
GameListWrapper = CommonFunctions.GetGameObjectChild(BingoGameBrowser, "GameList");
GameList = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(GameListWrapper, "Viewport"), "Content");
GameTemplate = CommonFunctions.GetGameObjectChild(GameList, "GameTemplate");
}
public static void clearOldGames()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
foreach (Transform item in GameList.transform)
{
Transform val = item;
if (((Object)((Component)val).gameObject).name != "GameTemplate")
{
Object.Destroy((Object)(object)((Component)val).gameObject);
}
}
gameArray.Clear();
}
public static void PopulateGames(List<PublicGameData> games)
{
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Expected O, but got Unknown
Dictionary<int, string> dictionary = new Dictionary<int, string>
{
{ 0, "HARMLESS" },
{ 1, "LENIENT" },
{ 2, "STANDARD" },
{ 3, "VIOLENT" },
{ 4, "BRUTAL" }
};
if (games.Count == 0)
{
((TMP_Text)FetchText.GetComponent<TextMeshProUGUI>()).text = "No public games currently available.";
return;
}
clearOldGames();
foreach (PublicGameData game in games)
{
GameObject val = Object.Instantiate<GameObject>(GameTemplate, GameTemplate.transform.parent);
CommonFunctions.GetGameObjectChild(val, "HostName").GetComponent<Text>().text = game.C_USERNAME;
CommonFunctions.GetGameObjectChild(val, "Difficulty").GetComponent<Text>().text = dictionary[game.R_DIFFICULTY];
CommonFunctions.GetGameObjectChild(val, "Players").GetComponent<Text>().text = game.R_CURRENTPLAYERS + "/" + game.R_MAXPLAYERS;
((UnityEvent)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(val, "JoinWrapper"), "JoinButton").GetComponent<Button>().onClick).AddListener((UnityAction)delegate
{
LockUI();
BingoMenuController.JoinRoom(game.R_PASSWORD);
});
val.SetActive(true);
gameArray.Add(val);
}
FetchText.SetActive(false);
GameListWrapper.SetActive(true);
GameList.SetActive(true);
fetchDone = true;
}
public static void DisplayError()
{
((TMP_Text)FetchText.GetComponent<TextMeshProUGUI>()).text = "Unable to connect to server.";
}
public static void FetchGames()
{
FetchText.SetActive(true);
GameListWrapper.SetActive(false);
GameList.SetActive(false);
((TMP_Text)FetchText.GetComponent<TextMeshProUGUI>()).text = "Fetching games, please wait...";
fetchDone = false;
NetworkManager.RequestGames();
}
}
public class BingoCard
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__11_0;
internal void <Init>b__11_0()
{
GameManager.LeaveGame();
}
}
public static GameObject Root;
public static GameObject Grid;
public static GameObject ButtonTemplate;
public static GameObject LeaveGame;
public static GameObject TeamIndicator;
public static GameObject ObjectiveIndicator;
public static GameObject Teammates;
public static GameObject CardElements;
public static string team = "PLACEHOLDER";
public static void Cleanup()
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
foreach (Transform item in Grid.transform)
{
Object.Destroy((Object)(object)((Component)item).gameObject);
}
}
public static void UpdateTitles(int gameType)
{
string text = "Race to <color=orange>obtain the fastest time</color> for your team on each level.\nClaim " + GameManager.CurrentGame.grid.size + " levels horizontally, vertically or diagonally for your team to win!";
string text2 = "Race to <color=orange>claim as many levels</color> for your team as possible.\nThe team with the most claims when time is up is the winner!";
TeamIndicator.GetComponent<TMP_Text>().text = "-- You are on the <color=" + GameManager.CurrentTeam.ToLower() + ">" + GameManager.CurrentTeam + " team</color> --";
ObjectiveIndicator.GetComponent<TMP_Text>().text = ((gameType == 0) ? text : text2);
if (GameManager.CurrentGame.gameSettingsArray["requiresPRank"] == 1)
{
TMP_Text component = ObjectiveIndicator.GetComponent<TMP_Text>();
component.text += "\n<color=#ffa200d9>P</color>-Ranks are <color=orange>required</color> to claim a level.";
}
}
public static GameObject Init()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Expected O, but got Unknown
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Expected O, but got Unknown
if ((Object)(object)Root == (Object)null)
{
Root = new GameObject();
}
((Object)Root).name = "UltraBingoCard";
CardElements = Object.Instantiate<GameObject>(AssetLoader.BingoCardElements, Root.transform);
Grid = CommonFunctions.GetGameObjectChild(CardElements, "BingoGrid");
((Object)Grid).name = "BingoGrid";
Grid.transform.SetParent(Root.transform);
if ((Object)(object)ButtonTemplate == (Object)null)
{
ButtonTemplate = new GameObject();
}
ButtonTemplate = Object.Instantiate<GameObject>(AssetLoader.BingoCardButtonTemplate, Root.transform);
ButtonTemplate.transform.SetParent(Root.transform);
ButtonTemplate.SetActive(false);
LeaveGame = CommonFunctions.GetGameObjectChild(CardElements, "LeaveGame");
ButtonClickedEvent onClick = LeaveGame.GetComponent<Button>().onClick;
object obj = <>c.<>9__11_0;
if (obj == null)
{
UnityAction val = delegate
{
GameManager.LeaveGame();
};
<>c.<>9__11_0 = val;
obj = (object)val;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
TeamIndicator = CommonFunctions.GetGameObjectChild(CardElements, "TeamIndicator");
((TMP_Text)TeamIndicator.GetComponent<TextMeshProUGUI>()).text = "-- You are on the " + team + " team -- ";
ObjectiveIndicator = CommonFunctions.GetGameObjectChild(CardElements, "ObjectiveIndicator");
Teammates = CommonFunctions.GetGameObjectChild(CardElements, "Teammates");
Root.SetActive(false);
return Root;
}
}
public static class BingoCardPauseMenu
{
public static Dictionary<string, Color> teamColors = new Dictionary<string, Color>
{
{
"NONE",
new Color(1f, 1f, 1f, 1f)
},
{
"Red",
new Color(1f, 0f, 0f, 1f)
},
{
"Green",
new Color(0f, 1f, 0f, 1f)
},
{
"Blue",
new Color(0f, 0f, 1f, 1f)
},
{
"Yellow",
new Color(1f, 1f, 0f, 1f)
}
};
public static GameObject Root;
public static GameObject Grid;
public static GameObject inGamePanel;
public static GameObject DescriptorText;
public static Outline pingedMap = null;
public static void onMouseEnterLevelSquare(PointerEventData data)
{
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Expected O, but got Unknown
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0211: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Unknown result type (might be due to invalid IL or missing references)
string text = data.pointerEnter.gameObject.GetComponent<BingoLevelData>().levelName.ToLower();
string text2 = GameManager.CurrentGame.grid.levelTable[((Object)data.pointerEnter.gameObject).name].levelId.ToLower();
bool isAngryLevel = data.pointerEnter.gameObject.GetComponent<BingoLevelData>().isAngryLevel;
Sprite val = null;
if (isAngryLevel)
{
string angryParentBundle = data.pointerEnter.gameObject.GetComponent<BingoLevelData>().angryParentBundle;
if (File.Exists(Path.Combine(Main.ModFolder, "ThumbnailCache", angryParentBundle + ".png")))
{
byte[] array = File.ReadAllBytes(Path.Combine(Main.ModFolder, "ThumbnailCache", angryParentBundle + ".png"));
Texture2D val2 = new Texture2D(2, 2);
ImageConversion.LoadImage(val2, array);
val = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f);
}
else
{
string text3 = "assets/bingo/lvlimg/unknown.png";
Texture2D val3 = AssetLoader.Assets.LoadAsset<Texture2D>(text3);
val = Sprite.Create(val3, new Rect(0f, 0f, (float)((Texture)val3).width, (float)((Texture)val3).height), new Vector2(0.5f, 0.5f), 100f);
}
}
else
{
string text4 = "assets/bingo/lvlimg/" + (data.pointerEnter.gameObject.GetComponent<BingoLevelData>().isAngryLevel ? "angry" : "campaign") + "/" + (data.pointerEnter.gameObject.GetComponent<BingoLevelData>().isAngryLevel ? text : text2) + ".png";
if (!AssetLoader.Assets.Contains(text4))
{
text4 = "assets/bingo/lvlimg/unknown.png";
}
Texture2D val4 = AssetLoader.Assets.LoadAsset<Texture2D>(text4);
val = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 100f);
}
CommonFunctions.GetGameObjectChild(Root, "SelectedLevelImage").GetComponent<Image>().overrideSprite = val;
bool flag = !data.pointerEnter.gameObject.GetComponent<BingoLevelData>().isClaimed && !MonoSingleton<BingoVoteManager>.Instance.voteOngoing;
GameLevel gameLevel = GameManager.CurrentGame.grid.levelTable[((Object)data.pointerEnter.gameObject).name];
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Root, "SelectedLevel"), "Text (TMP)").GetComponent<TextMeshProUGUI>()).text = gameLevel.levelName + ((gameLevel.claimedBy != "NONE") ? ("\n<color=orange>" + CommonFunctions.getFormattedTime(gameLevel.timeToBeat) + "</color>") : "") + (flag ? "\n<color=orange>R: Start a reroll vote</color>" : "");
CommonFunctions.GetGameObjectChild(Root, "SelectedLevel").SetActive(true);
CommonFunctions.GetGameObjectChild(Root, "SelectedLevelImage").SetActive(true);
}
public static void ShowBingoCardInPauseMenu(ref OptionsManager __instance)
{
//IL_0252: Unknown result type (might be due to invalid IL or missing references)
//IL_0271: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Expected O, but got Unknown
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
Game currentGame = GameManager.CurrentGame;
GameObject gameObjectChild = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Root, "Card"), "Image");
gameObjectChild.SetActive(false);
for (int i = 0; i < currentGame.grid.size; i++)
{
for (int j = 0; j < currentGame.grid.size; j++)
{
GameObject val = Object.Instantiate<GameObject>(gameObjectChild, ((Component)gameObjectChild.transform.parent).transform);
((Object)val).name = i + "-" + j;
GameLevel gameLevel = GameManager.CurrentGame.grid.levelTable[((Object)val).name];
BingoLevelData bingoLevelData = val.AddComponent<BingoLevelData>();
bingoLevelData.levelName = gameLevel.levelName;
bingoLevelData.isAngryLevel = gameLevel.isAngryLevel;
bingoLevelData.angryParentBundle = gameLevel.angryParentBundle;
bingoLevelData.angryLevelId = gameLevel.angryLevelId;
bingoLevelData.column = i;
bingoLevelData.row = j;
bingoLevelData.isClaimed = gameLevel.claimedBy != "NONE";
bingoLevelData.claimedTeam = gameLevel.claimedBy;
val.AddComponent<BingoLevelSquare>();
((Graphic)val.GetComponent<Image>()).color = teamColors[currentGame.grid.levelTable[i + "-" + j].claimedBy];
if (GameManager.CurrentRow == i && GameManager.CurrentColumn == j)
{
val.AddComponent<Outline>();
((Shadow)val.GetComponent<Outline>()).effectColor = Color.magenta;
((Shadow)val.GetComponent<Outline>()).effectDistance = new Vector2(2f, -2f);
}
val.AddComponent<EventTrigger>();
Entry val2 = new Entry();
val2.eventID = (EventTriggerType)0;
((UnityEvent<BaseEventData>)(object)val2.callback).AddListener((UnityAction<BaseEventData>)delegate(BaseEventData data)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
onMouseEnterLevelSquare((PointerEventData)data);
});
val.GetComponent<EventTrigger>().triggers.Add(val2);
val.SetActive(true);
}
}
GameObject gameObjectChild2 = CommonFunctions.GetGameObjectChild(Root, "Card");
switch (GameManager.CurrentGame.grid.size)
{
case 3:
gameObjectChild2.transform.localPosition = new Vector3(-65f, 170f, 0f);
gameObjectChild2.transform.localScale = new Vector3(1.25f, 1.25f, 1.25f);
break;
case 4:
gameObjectChild2.transform.localPosition = new Vector3(-82.5f, 185f, 0f);
gameObjectChild2.transform.localScale = new Vector3(1.1f, 1.1f, 1.1f);
break;
}
}
public static GameObject Init(ref OptionsManager __instance)
{
if ((Object)(object)Root == (Object)null)
{
Root = Object.Instantiate<GameObject>(AssetLoader.BingoPauseCard, __instance.pauseMenu.gameObject.transform);
}
((Object)Root).name = "BingoPauseCard";
Grid = CommonFunctions.GetGameObjectChild(Root, "Card");
Grid.GetComponent<GridLayoutGroup>().constraintCount = GameManager.CurrentGame.grid.size;
DescriptorText = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Root, "Descriptor"), "Text (TMP)");
Root.SetActive(true);
return Root;
}
}
public static class BingoDominationTimer
{
public static GameObject Root;
public static GameObject Timer;
public static void Init(ref GameObject DominationTimer)
{
Timer = CommonFunctions.GetGameObjectChild(DominationTimer, "Timer");
}
}
public static class BingoEncapsulator
{
public static GameObject Root;
public static GameObject BingoMenu;
public static GameObject BingoLobbyScreen;
public static GameObject BingoCardScreen;
public static GameObject BingoEndScreen;
public static GameObject BingoSetTeams;
public static GameObject BingoGameBrowser;
public static GameObject BingoMapSelection;
public static GameObject Init()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
if ((Object)(object)Root == (Object)null)
{
Root = new GameObject();
}
((Object)Root).name = "UltraBingo";
BingoMenu = Object.Instantiate<GameObject>(AssetLoader.BingoMainMenu, Root.transform);
BingoMainMenu.Init(ref BingoMenu);
((Object)BingoMenu).name = "BingoMainMenu";
BingoMenu.AddComponent<MenuEsc>();
BingoMenu.GetComponent<MenuEsc>().previousPage = CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("Canvas"), "Difficulty Select (1)");
BingoMenu.transform.SetParent(Root.transform);
BingoLobbyScreen = Object.Instantiate<GameObject>(AssetLoader.BingoLobbyMenu, Root.transform);
BingoLobby.Init(ref BingoLobbyScreen);
BingoLobbyScreen.transform.SetParent(Root.transform);
BingoCardScreen = BingoCard.Init();
BingoCardScreen.transform.SetParent(Root.transform);
BingoSetTeams = Object.Instantiate<GameObject>(AssetLoader.BingoSetTeams, Root.transform);
BingoSetTeamsMenu.Init(ref BingoSetTeams);
BingoSetTeams.transform.SetParent(Root.transform);
BingoEndScreen = Object.Instantiate<GameObject>(AssetLoader.BingoEndScreen, Root.transform);
BingoEnd.Init(ref BingoEndScreen);
BingoGameBrowser = Object.Instantiate<GameObject>(AssetLoader.BingoGameBrowser, Root.transform);
BingoBrowser.Init(ref BingoGameBrowser);
BingoMapSelection = Object.Instantiate<GameObject>(AssetLoader.BingoMapSelection, Root.transform);
BingoMapBrowser.Init(ref BingoMapSelection);
return Root;
}
}
public static class BingoEnd
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__16_0;
internal void <Init>b__16_0()
{
GameManager.LeaveGame();
}
}
public static GameObject Root;
public static GameObject WinnerIndicator;
public static GameObject WinningPlayers;
public static GameObject Stats;
public static GameObject LeaveGame;
public static string winningTeam;
public static string winningPlayers;
public static string timeElapsed;
public static int numOfClaims;
public static string firstMap;
public static string lastMap;
public static float bestStatValue;
public static string bestStatName;
public static int endCode;
public static string tiedTeams;
public static async void ShowEndScreen()
{
await Task.Delay(50);
CommonFunctions.GetGameObjectChild(CommonFunctions.GetInactiveRootObject("Canvas"), "Main Menu (1)").SetActive(false);
BingoEncapsulator.Root.SetActive(true);
BingoEncapsulator.BingoMenu.SetActive(false);
BingoEncapsulator.BingoCardScreen.SetActive(false);
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoEndScreen.SetActive(true);
string text = "";
switch (endCode)
{
case 0:
text = "The <color=" + winningTeam.ToLower() + ">" + winningTeam + " </color>team has won the game!";
break;
case 1:
text = "No team won the game.";
break;
case 2:
text = "The " + tiedTeams + " teams have tied!";
break;
}
((TMP_Text)WinnerIndicator.GetComponent<TextMeshProUGUI>()).text = text;
((TMP_Text)CommonFunctions.GetGameObjectChild(WinningPlayers, "Text (TMP) (1)").GetComponent<TextMeshProUGUI>()).text = winningPlayers;
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Stats, "TimeElapsed"), "Value").GetComponent<TextMeshProUGUI>()).text = "<color=orange>" + timeElapsed + "</color>";
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Stats, "TotalClaims"), "Value").GetComponent<TextMeshProUGUI>()).text = "<color=orange>" + numOfClaims + "</color>";
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Stats, "FirstMap"), "Value").GetComponent<TextMeshProUGUI>()).text = "<color=orange>" + firstMap + "</color>";
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Stats, "LastMap"), "Value").GetComponent<TextMeshProUGUI>()).text = "<color=orange>" + lastMap + "</color>";
((TMP_Text)CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(Stats, "HighestStat"), "Value").GetComponent<TextMeshProUGUI>()).text = "<color=orange>" + bestStatValue + " </color>(<color=orange>" + bestStatName + "</color>)";
Root.SetActive(true);
}
public static void Init(ref GameObject BingoEndScreen)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Expected O, but got Unknown
if ((Object)(object)Root == (Object)null)
{
Root = new GameObject();
}
((Object)Root).name = "BingoEndScreen";
WinnerIndicator = CommonFunctions.GetGameObjectChild(BingoEndScreen, "WinningTeam");
WinningPlayers = CommonFunctions.GetGameObjectChild(BingoEndScreen, "WinningPlayers");
Stats = CommonFunctions.GetGameObjectChild(BingoEndScreen, "Stats");
LeaveGame = CommonFunctions.GetGameObjectChild(BingoEndScreen, "LeaveGame");
ButtonClickedEvent onClick = LeaveGame.GetComponent<Button>().onClick;
object obj = <>c.<>9__16_0;
if (obj == null)
{
UnityAction val = delegate
{
GameManager.LeaveGame();
};
<>c.<>9__16_0 = val;
obj = (object)val;
}
((UnityEvent)onClick).AddListener((UnityAction)obj);
LeaveGame.transform.SetParent(BingoEndScreen.transform);
BingoEndScreen.SetActive(false);
}
}
public static class BingoLobby
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__32_0;
public static UnityAction <>9__32_1;
public static UnityAction <>9__32_2;
public static UnityAction <>9__32_3;
public static UnityAction <>9__32_4;
public static UnityAction<string> <>9__32_5;
public static UnityAction<string> <>9__32_6;
public static UnityAction<string> <>9__32_7;
public static UnityAction<int> <>9__32_8;
public static UnityAction<int> <>9__32_9;
public static UnityAction<int> <>9__32_10;
public static UnityAction<int> <>9__32_11;
public static UnityAction<bool> <>9__32_12;
public static UnityAction<bool> <>9__32_13;
public static UnityAction<int> <>9__32_14;
public static UnityAction<bool> <>9__32_15;
public static UnityAction<int> <>9__32_16;
public static UnityAction <>9__32_17;
public static UnityAction <>9__32_18;
internal void <Init>b__32_0()
{
GameManager.LeaveGame();
}
internal void <Init>b__32_1()
{
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoMapSelection.SetActive(true);
BingoMapBrowser.Setup();
}
internal void <Init>b__32_2()
{
BingoSetTeamsMenu.Setup();
BingoEncapsulator.BingoLobbyScreen.SetActive(false);
BingoEncapsulator.BingoSetTeams.SetActive(true);
}
internal void <Init>b__32_3()
{
if (GameManager.PreStartChecks())
{
LockUI();
GameManager.StartGame();
}
}
internal void <Init>b__32_4()
{
GUIUtility.systemCopyBuffer = CommonFunctions.GetGameObjectChild(CommonFunctions.GetGameObjectChild(RoomIdDisplay, "Title"), "Text").GetComponent<Text>().text.Split(new char[1] { ':' })[1];
}
internal void <Init>b__32_5(string <p0>)
{
onSettingUpdate("maxPlayers", int.Parse(MaxPlayers.text));
}
internal void <Init>b__32_6(string <p0>)
{
onSettingUpdate("maxTeams", int.Parse(MaxTeams.text));
}
internal void <Init>b__32_7(string <p0>)
{
onSettingUpdate("timeLimit", int.Parse(TimeLimit.text));
}
internal void <Init>b__32_8(int <p0>)
{
onSettingUpdate("teamComposition", TeamComposition.value);
}
internal void <Init>b__32_9(int <p0>)
{
onSettingUpdate("gamemode", Gamemode.value);
}
internal void <Init>b__32_10(int <p0>)
{
onSettingUpdate("gridSize", GridSize.value);
}
internal void <Init>b__32_11(int <p0>)
{
onSettingUpdate("difficulty", Difficulty.value);
}
internal void <Init>b__32_12(bool <p0>)
{
onSettingUpdate("requiresPRank", RequirePRank.isOn ? 1 : 0);
}
internal void <Init>b__32_13(bool <p0>)
{
onSettingUpdate("disableCampaignAltExits", DisableCampaignAltExits.isOn ? 1 : 0);
}
internal void <Init>b__32_14(int <p0>)
{
onSettingUpdate("gameVisibility", GameVisibility.value);
}
internal void <Init>b__32_15(bool <p0>)
{
onSettingUpdate("allowRejoin", AllowRejoin.isOn ? 1 : 0);
}
internal void <Init>b__32_16(int <p0>)
{
onSettingUpdate("gameModifier", GameModifiers.value);
}
internal void <Init>b__32_17()
{
SwitchPage(-1);
}
internal void <Init>b__32_18()
{
SwitchPage(1);
}
}
public static GameObject PlayerList;
public static GameObject ReturnToBingoMenu;
public static GameObject SelectMaps;
public static GameObject SetTeams;
public static GameObject StartGame;
public static GameObject RoomIdDisplay;
public static GameObject CopyId;
public static GameObject GameOptions;
public static TMP_InputField MaxPlayers;
public static TMP_InputField MaxTeams;
public static TMP_InputField TimeLimit;
public static TMP_Dropdown Gamemode;
public static TMP_Dropdown TeamComposition;
public static TMP_Dropdown GridSize;
public static TMP_Dropdown Difficulty;
public static Toggle RequirePRank;
public static Toggle DisableCampaignAltExits;
public static TMP_Dropdown GameVisibility;
public static Toggle AllowRejoin;
public static TMP_Dropdown GameModifiers;
public static List<GameObject> settingPages;
public static GameObject Controls;
public static Button Back;
public static TextMeshProUGUI PageCount;
public static Button Forward;
public static GameObject chatWindow;
public static int pagePointer;
public static void SwitchPage(int direction)
{
pagePointer = Mathf.Clamp(pagePointer + direction, 0, 1);
((TMP_Text)PageCount).text = pagePointer + 1 + "/2";
foreach (GameObject settingPage in settingPages)
{
settingPage.SetActive(((Object)settingPage
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Timers;
using WebSocketSharp.Net;
using WebSocketSharp.Net.WebSockets;
using WebSocketSharp.Server;
[assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyTitle("websocket-sharp")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("sta.blockhead")]
[assembly: AssemblyProduct("websocket-sharp.dll")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.2.36589")]
namespace WebSocketSharp
{
public static class Ext
{
private const string _tspecials = "()<>@,;:\\\"/[]?={} \t";
private static readonly byte[] _last;
internal static readonly byte[] EmptyByteArray;
private static byte[] compress(this byte[] data)
{
if (data.LongLength == 0)
{
return data;
}
using MemoryStream stream = new MemoryStream(data);
return stream.compressToArray();
}
private static MemoryStream compress(this Stream stream)
{
MemoryStream memoryStream = new MemoryStream();
if (stream.Length == 0)
{
return memoryStream;
}
stream.Position = 0L;
using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, leaveOpen: true);
CopyTo(stream, deflateStream);
deflateStream.Close();
memoryStream.Write(_last, 0, 1);
memoryStream.Position = 0L;
return memoryStream;
}
private static byte[] compressToArray(this Stream stream)
{
using MemoryStream memoryStream = stream.compress();
memoryStream.Close();
return memoryStream.ToArray();
}
private static byte[] decompress(this byte[] data)
{
if (data.LongLength == 0)
{
return data;
}
using MemoryStream stream = new MemoryStream(data);
return stream.decompressToArray();
}
private static MemoryStream decompress(this Stream stream)
{
MemoryStream memoryStream = new MemoryStream();
if (stream.Length == 0)
{
return memoryStream;
}
stream.Position = 0L;
using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true);
CopyTo(source, memoryStream);
memoryStream.Position = 0L;
return memoryStream;
}
private static byte[] decompressToArray(this Stream stream)
{
using MemoryStream memoryStream = stream.decompress();
memoryStream.Close();
return memoryStream.ToArray();
}
private static byte[] readBytes(this Stream stream, byte[] buffer, int offset, int count)
{
int i = 0;
try
{
i = stream.Read(buffer, offset, count);
if (i < 1)
{
return buffer.SubArray(0, offset);
}
int num;
for (; i < count; i += num)
{
num = stream.Read(buffer, offset + i, count - i);
if (num < 1)
{
break;
}
}
}
catch
{
}
return (i < count) ? buffer.SubArray(0, offset + i) : buffer;
}
private static void times(this ulong n, Action action)
{
for (ulong num = 0uL; num < n; num++)
{
action();
}
}
private static bool writeTo(this Stream stream, Stream destination, int length, byte[] buffer)
{
byte[] array = stream.readBytes(buffer, 0, length);
int num = array.Length;
destination.Write(array, 0, num);
return num == length;
}
internal static byte[] Append(this ushort code, string reason)
{
using MemoryStream memoryStream = new MemoryStream();
byte[] buffer = code.InternalToByteArray(ByteOrder.Big);
memoryStream.Write(buffer, 0, 2);
if (reason != null && reason.Length > 0)
{
buffer = Encoding.UTF8.GetBytes(reason);
memoryStream.Write(buffer, 0, buffer.Length);
}
memoryStream.Close();
return memoryStream.ToArray();
}
internal static string CheckIfCanRead(this Stream stream)
{
return (stream == null) ? "'stream' is null." : ((!stream.CanRead) ? "'stream' cannot be read." : null);
}
internal static string CheckIfClosable(this WebSocketState state)
{
return state switch
{
WebSocketState.Closed => "The WebSocket connection has already been closed.",
WebSocketState.Closing => "While closing the WebSocket connection.",
_ => null,
};
}
internal static string CheckIfConnectable(this WebSocketState state)
{
return (state == WebSocketState.Open || state == WebSocketState.Closing) ? "A WebSocket connection has already been established." : null;
}
internal static string CheckIfOpen(this WebSocketState state)
{
return state switch
{
WebSocketState.Closed => "The WebSocket connection has already been closed.",
WebSocketState.Closing => "While closing the WebSocket connection.",
WebSocketState.Connecting => "A WebSocket connection isn't established.",
_ => null,
};
}
internal static string CheckIfStart(this ServerState state)
{
return state switch
{
ServerState.Stop => "The server has already stopped.",
ServerState.ShuttingDown => "The server is shutting down.",
ServerState.Ready => "The server hasn't yet started.",
_ => null,
};
}
internal static string CheckIfStartable(this ServerState state)
{
return state switch
{
ServerState.ShuttingDown => "The server is shutting down.",
ServerState.Start => "The server has already started.",
_ => null,
};
}
internal static string CheckIfValidProtocols(this string[] protocols)
{
return protocols.Contains((string protocol) => protocol == null || protocol.Length == 0 || !protocol.IsToken()) ? "Contains an invalid value." : (protocols.ContainsTwice() ? "Contains a value twice." : null);
}
internal static string CheckIfValidSendData(this byte[] data)
{
return (data == null) ? "'data' is null." : null;
}
internal static string CheckIfValidSendData(this FileInfo file)
{
return (file == null) ? "'file' is null." : null;
}
internal static string CheckIfValidSendData(this string data)
{
return (data == null) ? "'data' is null." : null;
}
internal static string CheckIfValidServicePath(this string path)
{
return (path == null || path.Length == 0) ? "'path' is null or empty." : ((path[0] != '/') ? "'path' isn't an absolute path." : ((path.IndexOfAny(new char[2] { '?', '#' }) > -1) ? "'path' includes either or both query and fragment components." : null));
}
internal static string CheckIfValidSessionID(this string id)
{
return (id == null || id.Length == 0) ? "'id' is null or empty." : null;
}
internal static string CheckIfValidWaitTime(this TimeSpan time)
{
return (time <= TimeSpan.Zero) ? "A wait time is zero or less." : null;
}
internal static void Close(this WebSocketSharp.Net.HttpListenerResponse response, WebSocketSharp.Net.HttpStatusCode code)
{
response.StatusCode = (int)code;
response.OutputStream.Close();
}
internal static void CloseWithAuthChallenge(this WebSocketSharp.Net.HttpListenerResponse response, string challenge)
{
response.Headers.InternalSet("WWW-Authenticate", challenge, response: true);
response.Close(WebSocketSharp.Net.HttpStatusCode.Unauthorized);
}
internal static byte[] Compress(this byte[] data, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? data.compress() : data;
}
internal static Stream Compress(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.compress() : stream;
}
internal static byte[] CompressToArray(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.compressToArray() : stream.ToByteArray();
}
internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition)
{
foreach (T item in source)
{
if (condition(item))
{
return true;
}
}
return false;
}
internal static bool ContainsTwice(this string[] values)
{
int len = values.Length;
Func<int, bool> contains = null;
contains = delegate(int idx)
{
if (idx < len - 1)
{
for (int i = idx + 1; i < len; i++)
{
if (values[i] == values[idx])
{
return true;
}
}
return contains(++idx);
}
return false;
};
return contains(0);
}
internal static T[] Copy<T>(this T[] source, long length)
{
T[] array = new T[length];
Array.Copy(source, 0L, array, 0L, length);
return array;
}
internal static void CopyTo(this Stream source, Stream destination)
{
int num = 1024;
byte[] buffer = new byte[num];
int num2 = 0;
while ((num2 = source.Read(buffer, 0, num)) > 0)
{
destination.Write(buffer, 0, num2);
}
}
internal static byte[] Decompress(this byte[] data, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? data.decompress() : data;
}
internal static Stream Decompress(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.decompress() : stream;
}
internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method)
{
return (method == CompressionMethod.Deflate) ? stream.decompressToArray() : stream.ToByteArray();
}
internal static bool EqualsWith(this int value, char c, Action<int> action)
{
action(value);
return value == c;
}
internal static string GetAbsolutePath(this Uri uri)
{
if (uri.IsAbsoluteUri)
{
return uri.AbsolutePath;
}
string originalString = uri.OriginalString;
if (originalString[0] != '/')
{
return null;
}
int num = originalString.IndexOfAny(new char[2] { '?', '#' });
return (num > 0) ? originalString.Substring(0, num) : originalString;
}
internal static string GetMessage(this CloseStatusCode code)
{
return code switch
{
CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.",
CloseStatusCode.ServerError => "WebSocket server got an internal error.",
CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).",
CloseStatusCode.TooBig => "A too big message has been received.",
CloseStatusCode.PolicyViolation => "A policy violation has occurred.",
CloseStatusCode.InvalidData => "Invalid data has been received.",
CloseStatusCode.Abnormal => "An exception has occurred.",
CloseStatusCode.UnsupportedData => "Unsupported data has been received.",
CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.",
_ => string.Empty,
};
}
internal static string GetName(this string nameAndValue, char separator)
{
int num = nameAndValue.IndexOf(separator);
return (num > 0) ? nameAndValue.Substring(0, num).Trim() : null;
}
internal static string GetValue(this string nameAndValue, char separator)
{
int num = nameAndValue.IndexOf(separator);
return (num > -1 && num < nameAndValue.Length - 1) ? nameAndValue.Substring(num + 1).Trim() : null;
}
internal static string GetValue(this string nameAndValue, char separator, bool unquote)
{
int num = nameAndValue.IndexOf(separator);
if (num < 0 || num == nameAndValue.Length - 1)
{
return null;
}
string text = nameAndValue.Substring(num + 1).Trim();
return unquote ? text.Unquote() : text;
}
internal static TcpListenerWebSocketContext GetWebSocketContext(this TcpClient tcpClient, string protocol, bool secure, ServerSslConfiguration sslConfig, Logger logger)
{
return new TcpListenerWebSocketContext(tcpClient, protocol, secure, sslConfig, logger);
}
internal static byte[] InternalToByteArray(this ushort value, ByteOrder order)
{
byte[] bytes = BitConverter.GetBytes(value);
if (!order.IsHostOrder())
{
Array.Reverse((Array)bytes);
}
return bytes;
}
internal static byte[] InternalToByteArray(this ulong value, ByteOrder order)
{
byte[] bytes = BitConverter.GetBytes(value);
if (!order.IsHostOrder())
{
Array.Reverse((Array)bytes);
}
return bytes;
}
internal static bool IsCompressionExtension(this string value, CompressionMethod method)
{
return value.StartsWith(method.ToExtensionString());
}
internal static bool IsPortNumber(this int value)
{
return value > 0 && value < 65536;
}
internal static bool IsReserved(this ushort code)
{
return code == 1004 || code == 1005 || code == 1006 || code == 1015;
}
internal static bool IsReserved(this CloseStatusCode code)
{
return code == CloseStatusCode.Undefined || code == CloseStatusCode.NoStatus || code == CloseStatusCode.Abnormal || code == CloseStatusCode.TlsHandshakeFailure;
}
internal static bool IsText(this string value)
{
int length = value.Length;
for (int i = 0; i < length; i++)
{
char c = value[i];
if (c < ' ' && !Contains("\r\n\t", c))
{
return false;
}
switch (c)
{
case '\u007f':
return false;
case '\n':
if (++i < length)
{
c = value[i];
if (!Contains(" \t", c))
{
return false;
}
}
break;
}
}
return true;
}
internal static bool IsToken(this string value)
{
foreach (char c in value)
{
if (c < ' ' || c >= '\u007f' || Contains("()<>@,;:\\\"/[]?={} \t", c))
{
return false;
}
}
return true;
}
internal static string Quote(this string value)
{
return string.Format("\"{0}\"", value.Replace("\"", "\\\""));
}
internal static byte[] ReadBytes(this Stream stream, int length)
{
return stream.readBytes(new byte[length], 0, length);
}
internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength)
{
using MemoryStream memoryStream = new MemoryStream();
long num = length / bufferLength;
int num2 = (int)(length % bufferLength);
byte[] buffer = new byte[bufferLength];
bool flag = false;
for (long num3 = 0L; num3 < num; num3++)
{
if (!stream.writeTo(memoryStream, bufferLength, buffer))
{
flag = true;
break;
}
}
if (!flag && num2 > 0)
{
stream.writeTo(memoryStream, num2, new byte[num2]);
}
memoryStream.Close();
return memoryStream.ToArray();
}
internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error)
{
byte[] buff = new byte[length];
stream.BeginRead(buff, 0, length, delegate(IAsyncResult ar)
{
try
{
byte[] array = null;
try
{
int num = stream.EndRead(ar);
array = ((num < 1) ? EmptyByteArray : ((num < length) ? stream.readBytes(buff, num, length - num) : buff));
}
catch
{
array = EmptyByteArray;
}
if (completed != null)
{
completed(array);
}
}
catch (Exception obj2)
{
if (error != null)
{
error(obj2);
}
}
}, null);
}
internal static string RemovePrefix(this string value, params string[] prefixes)
{
int num = 0;
foreach (string text in prefixes)
{
if (value.StartsWith(text))
{
num = text.Length;
break;
}
}
return (num > 0) ? value.Substring(num) : value;
}
internal static T[] Reverse<T>(this T[] array)
{
int num = array.Length;
T[] array2 = new T[num];
int num2 = num - 1;
for (int i = 0; i <= num2; i++)
{
array2[i] = array[num2 - i];
}
return array2;
}
internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators)
{
int len = value.Length;
string seps = new string(separators);
StringBuilder buff = new StringBuilder(32);
bool escaped = false;
bool quoted = false;
for (int i = 0; i < len; i++)
{
char c = value[i];
switch (c)
{
case '"':
if (escaped)
{
escaped = !escaped;
}
else
{
quoted = !quoted;
}
break;
case '\\':
if (i < len - 1 && value[i + 1] == '"')
{
escaped = true;
}
break;
default:
if (Contains(seps, c) && !quoted)
{
yield return buff.ToString();
buff.Length = 0;
continue;
}
break;
}
buff.Append(c);
}
if (buff.Length > 0)
{
yield return buff.ToString();
}
}
internal static byte[] ToByteArray(this Stream stream)
{
using MemoryStream memoryStream = new MemoryStream();
stream.Position = 0L;
CopyTo(stream, memoryStream);
memoryStream.Close();
return memoryStream.ToArray();
}
internal static CompressionMethod ToCompressionMethod(this string value)
{
foreach (CompressionMethod value2 in Enum.GetValues(typeof(CompressionMethod)))
{
if (value2.ToExtensionString() == value)
{
return value2;
}
}
return CompressionMethod.None;
}
internal static string ToExtensionString(this CompressionMethod method, params string[] parameters)
{
if (method == CompressionMethod.None)
{
return string.Empty;
}
string text = $"permessage-{method.ToString().ToLower()}";
if (parameters == null || parameters.Length == 0)
{
return text;
}
return string.Format("{0}; {1}", text, parameters.ToString("; "));
}
internal static IPAddress ToIPAddress(this string hostnameOrAddress)
{
try
{
return Dns.GetHostAddresses(hostnameOrAddress)[0];
}
catch
{
return null;
}
}
internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
return new List<TSource>(source);
}
internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder)
{
return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0);
}
internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder)
{
return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0);
}
internal static string TrimEndSlash(this string value)
{
value = value.TrimEnd(new char[1] { '/' });
return (value.Length > 0) ? value : "/";
}
internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message)
{
result = null;
Uri uri = uriString.ToUri();
if (uri == null)
{
message = "An invalid URI string: " + uriString;
return false;
}
if (!uri.IsAbsoluteUri)
{
message = "Not an absolute URI: " + uriString;
return false;
}
string scheme = uri.Scheme;
if (!(scheme == "ws") && !(scheme == "wss"))
{
message = "The scheme part isn't 'ws' or 'wss': " + uriString;
return false;
}
if (uri.Fragment.Length > 0)
{
message = "Includes the fragment component: " + uriString;
return false;
}
int port = uri.Port;
if (port == 0)
{
message = "The port part is zero: " + uriString;
return false;
}
result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery)));
message = string.Empty;
return true;
}
internal static string Unquote(this string value)
{
int num = value.IndexOf('"');
if (num < 0)
{
return value;
}
int num2 = value.LastIndexOf('"');
int num3 = num2 - num - 1;
return (num3 < 0) ? value : ((num3 == 0) ? string.Empty : value.Substring(num + 1, num3).Replace("\\\"", "\""));
}
internal static void WriteBytes(this Stream stream, byte[] bytes)
{
using MemoryStream source = new MemoryStream(bytes);
CopyTo(source, stream);
}
public static bool Contains(this string value, params char[] chars)
{
return chars == null || chars.Length == 0 || (value != null && value.Length != 0 && value.IndexOfAny(chars) > -1);
}
public static bool Contains(this NameValueCollection collection, string name)
{
return collection != null && collection.Count > 0 && collection[name] != null;
}
public static bool Contains(this NameValueCollection collection, string name, string value)
{
if (collection == null || collection.Count == 0)
{
return false;
}
string text = collection[name];
if (text == null)
{
return false;
}
string[] array = text.Split(new char[1] { ',' });
foreach (string text2 in array)
{
if (text2.Trim().Equals(value, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
public static void Emit(this EventHandler eventHandler, object sender, EventArgs e)
{
eventHandler?.Invoke(sender, e);
}
public static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs
{
eventHandler?.Invoke(sender, e);
}
public static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response)
{
string name = (response ? "Set-Cookie" : "Cookie");
return (headers != null && headers.Contains(name)) ? WebSocketSharp.Net.CookieCollection.Parse(headers[name], response) : new WebSocketSharp.Net.CookieCollection();
}
public static string GetDescription(this WebSocketSharp.Net.HttpStatusCode code)
{
return ((int)code).GetStatusDescription();
}
public static string GetStatusDescription(this int code)
{
return code switch
{
100 => "Continue",
101 => "Switching Protocols",
102 => "Processing",
200 => "OK",
201 => "Created",
202 => "Accepted",
203 => "Non-Authoritative Information",
204 => "No Content",
205 => "Reset Content",
206 => "Partial Content",
207 => "Multi-Status",
300 => "Multiple Choices",
301 => "Moved Permanently",
302 => "Found",
303 => "See Other",
304 => "Not Modified",
305 => "Use Proxy",
307 => "Temporary Redirect",
400 => "Bad Request",
401 => "Unauthorized",
402 => "Payment Required",
403 => "Forbidden",
404 => "Not Found",
405 => "Method Not Allowed",
406 => "Not Acceptable",
407 => "Proxy Authentication Required",
408 => "Request Timeout",
409 => "Conflict",
410 => "Gone",
411 => "Length Required",
412 => "Precondition Failed",
413 => "Request Entity Too Large",
414 => "Request-Uri Too Long",
415 => "Unsupported Media Type",
416 => "Requested Range Not Satisfiable",
417 => "Expectation Failed",
422 => "Unprocessable Entity",
423 => "Locked",
424 => "Failed Dependency",
500 => "Internal Server Error",
501 => "Not Implemented",
502 => "Bad Gateway",
503 => "Service Unavailable",
504 => "Gateway Timeout",
505 => "Http Version Not Supported",
507 => "Insufficient Storage",
_ => string.Empty,
};
}
public static bool IsCloseStatusCode(this ushort value)
{
return value > 999 && value < 5000;
}
public static bool IsEnclosedIn(this string value, char c)
{
return value != null && value.Length > 1 && value[0] == c && value[value.Length - 1] == c;
}
public static bool IsHostOrder(this ByteOrder order)
{
return !(BitConverter.IsLittleEndian ^ (order == ByteOrder.Little));
}
public static bool IsLocal(this IPAddress address)
{
if (address == null)
{
return false;
}
if (address.Equals(IPAddress.Any) || IPAddress.IsLoopback(address))
{
return true;
}
string hostName = Dns.GetHostName();
IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName);
IPAddress[] array = hostAddresses;
foreach (IPAddress obj in array)
{
if (address.Equals(obj))
{
return true;
}
}
return false;
}
public static bool IsNullOrEmpty(this string value)
{
return value == null || value.Length == 0;
}
public static bool IsPredefinedScheme(this string value)
{
if (value == null || value.Length < 2)
{
return false;
}
char c = value[0];
if (c == 'h')
{
return value == "http" || value == "https";
}
if (c == 'w')
{
return value == "ws" || value == "wss";
}
if (c == 'f')
{
return value == "file" || value == "ftp";
}
if (c == 'n')
{
c = value[1];
return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp");
}
return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto");
}
public static bool IsUpgradeTo(this WebSocketSharp.Net.HttpListenerRequest request, string protocol)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (protocol == null)
{
throw new ArgumentNullException("protocol");
}
if (protocol.Length == 0)
{
throw new ArgumentException("An empty string.", "protocol");
}
return request.Headers.Contains("Upgrade", protocol) && request.Headers.Contains("Connection", "Upgrade");
}
public static bool MaybeUri(this string value)
{
if (value == null || value.Length == 0)
{
return false;
}
int num = value.IndexOf(':');
if (num == -1)
{
return false;
}
if (num >= 10)
{
return false;
}
return value.Substring(0, num).IsPredefinedScheme();
}
public static T[] SubArray<T>(this T[] array, int startIndex, int length)
{
int num;
if (array == null || (num = array.Length) == 0)
{
return new T[0];
}
if (startIndex < 0 || length <= 0 || startIndex + length > num)
{
return new T[0];
}
if (startIndex == 0 && length == num)
{
return array;
}
T[] array2 = new T[length];
Array.Copy(array, startIndex, array2, 0, length);
return array2;
}
public static T[] SubArray<T>(this T[] array, long startIndex, long length)
{
long longLength;
if (array == null || (longLength = array.LongLength) == 0)
{
return new T[0];
}
if (startIndex < 0 || length <= 0 || startIndex + length > longLength)
{
return new T[0];
}
if (startIndex == 0 && length == longLength)
{
return array;
}
T[] array2 = new T[length];
Array.Copy(array, startIndex, array2, 0L, length);
return array2;
}
public static void Times(this int n, Action action)
{
if (n > 0 && action != null)
{
((ulong)n).times(action);
}
}
public static void Times(this long n, Action action)
{
if (n > 0 && action != null)
{
((ulong)n).times(action);
}
}
public static void Times(this uint n, Action action)
{
if (n != 0 && action != null)
{
times(n, action);
}
}
public static void Times(this ulong n, Action action)
{
if (n != 0 && action != null)
{
n.times(action);
}
}
public static void Times(this int n, Action<int> action)
{
if (n > 0 && action != null)
{
for (int i = 0; i < n; i++)
{
action(i);
}
}
}
public static void Times(this long n, Action<long> action)
{
if (n > 0 && action != null)
{
for (long num = 0L; num < n; num++)
{
action(num);
}
}
}
public static void Times(this uint n, Action<uint> action)
{
if (n != 0 && action != null)
{
for (uint num = 0u; num < n; num++)
{
action(num);
}
}
}
public static void Times(this ulong n, Action<ulong> action)
{
if (n != 0 && action != null)
{
for (ulong num = 0uL; num < n; num++)
{
action(num);
}
}
}
public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if (source.Length == 0)
{
return default(T);
}
Type typeFromHandle = typeof(T);
byte[] value = source.ToHostOrder(sourceOrder);
return ((object)typeFromHandle == typeof(bool)) ? ((T)(object)BitConverter.ToBoolean(value, 0)) : (((object)typeFromHandle == typeof(char)) ? ((T)(object)BitConverter.ToChar(value, 0)) : (((object)typeFromHandle == typeof(double)) ? ((T)(object)BitConverter.ToDouble(value, 0)) : (((object)typeFromHandle == typeof(short)) ? ((T)(object)BitConverter.ToInt16(value, 0)) : (((object)typeFromHandle == typeof(int)) ? ((T)(object)BitConverter.ToInt32(value, 0)) : (((object)typeFromHandle == typeof(long)) ? ((T)(object)BitConverter.ToInt64(value, 0)) : (((object)typeFromHandle == typeof(float)) ? ((T)(object)BitConverter.ToSingle(value, 0)) : (((object)typeFromHandle == typeof(ushort)) ? ((T)(object)BitConverter.ToUInt16(value, 0)) : (((object)typeFromHandle == typeof(uint)) ? ((T)(object)BitConverter.ToUInt32(value, 0)) : (((object)typeFromHandle == typeof(ulong)) ? ((T)(object)BitConverter.ToUInt64(value, 0)) : default(T))))))))));
}
public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct
{
Type typeFromHandle = typeof(T);
byte[] array = (((object)typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : (((object)typeFromHandle == typeof(byte)) ? new byte[1] { (byte)(object)value } : (((object)typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : (((object)typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : (((object)typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : (((object)typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : (((object)typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : (((object)typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : (((object)typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : (((object)typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : (((object)typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : EmptyByteArray)))))))))));
if (array.Length > 1 && !order.IsHostOrder())
{
Array.Reverse((Array)array);
}
return array;
}
public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
return (source.Length > 1 && !sourceOrder.IsHostOrder()) ? source.Reverse() : source;
}
public static string ToString<T>(this T[] array, string separator)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
int num = array.Length;
if (num == 0)
{
return string.Empty;
}
if (separator == null)
{
separator = string.Empty;
}
StringBuilder buff = new StringBuilder(64);
(num - 1).Times(delegate(int i)
{
buff.AppendFormat("{0}{1}", array[i].ToString(), separator);
});
buff.Append(array[num - 1].ToString());
return buff.ToString();
}
public static Uri ToUri(this string uriString)
{
Uri.TryCreate(uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result);
return result;
}
public static string UrlDecode(this string value)
{
return (value != null && value.Length > 0) ? HttpUtility.UrlDecode(value) : value;
}
public static string UrlEncode(this string value)
{
return (value != null && value.Length > 0) ? HttpUtility.UrlEncode(value) : value;
}
public static void WriteContent(this WebSocketSharp.Net.HttpListenerResponse response, byte[] content)
{
if (response == null)
{
throw new ArgumentNullException("response");
}
if (content == null)
{
throw new ArgumentNullException("content");
}
long longLength = content.LongLength;
if (longLength == 0)
{
response.Close();
return;
}
response.ContentLength64 = longLength;
Stream outputStream = response.OutputStream;
if (longLength <= int.MaxValue)
{
outputStream.Write(content, 0, (int)longLength);
}
else
{
outputStream.WriteBytes(content);
}
outputStream.Close();
}
static Ext()
{
byte[] last = new byte[1];
_last = last;
EmptyByteArray = new byte[0];
}
}
public class MessageEventArgs : EventArgs
{
private string _data;
private bool _dataSet;
private Opcode _opcode;
private byte[] _rawData;
public string Data
{
get
{
if (!_dataSet)
{
_data = ((_opcode != Opcode.Binary) ? convertToString(_rawData) : BitConverter.ToString(_rawData));
_dataSet = true;
}
return _data;
}
}
public byte[] RawData => _rawData;
public Opcode Type => _opcode;
internal MessageEventArgs(WebSocketFrame frame)
{
_opcode = frame.Opcode;
_rawData = frame.PayloadData.ApplicationData;
}
internal MessageEventArgs(Opcode opcode, byte[] rawData)
{
if ((ulong)rawData.LongLength > 9223372036854775807uL)
{
throw new WebSocketException(CloseStatusCode.TooBig);
}
_opcode = opcode;
_rawData = rawData;
}
private static string convertToString(byte[] rawData)
{
try
{
return Encoding.UTF8.GetString(rawData);
}
catch
{
return null;
}
}
}
public class CloseEventArgs : EventArgs
{
private bool _clean;
private ushort _code;
private PayloadData _payloadData;
private byte[] _rawData;
private string _reason;
internal PayloadData PayloadData => _payloadData ?? (_payloadData = new PayloadData(_rawData));
internal byte[] RawData => _rawData;
public ushort Code => _code;
public string Reason => _reason ?? string.Empty;
public bool WasClean
{
get
{
return _clean;
}
internal set
{
_clean = value;
}
}
internal CloseEventArgs()
{
_code = 1005;
_payloadData = new PayloadData();
_rawData = _payloadData.ApplicationData;
}
internal CloseEventArgs(ushort code)
{
_code = code;
_rawData = code.InternalToByteArray(ByteOrder.Big);
}
internal CloseEventArgs(CloseStatusCode code)
: this((ushort)code)
{
}
internal CloseEventArgs(PayloadData payloadData)
{
_payloadData = payloadData;
_rawData = payloadData.ApplicationData;
int num = _rawData.Length;
_code = (ushort)((num > 1) ? _rawData.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005);
_reason = ((num > 2) ? Encoding.UTF8.GetString(_rawData.SubArray(2, num - 2)) : string.Empty);
}
internal CloseEventArgs(ushort code, string reason)
{
_code = code;
_reason = reason;
_rawData = code.Append(reason);
}
internal CloseEventArgs(CloseStatusCode code, string reason)
: this((ushort)code, reason)
{
}
}
public enum ByteOrder : byte
{
Little,
Big
}
public class ErrorEventArgs : EventArgs
{
private Exception _exception;
private string _message;
public Exception Exception => _exception;
public string Message => _message;
internal ErrorEventArgs(string message)
: this(message, null)
{
}
internal ErrorEventArgs(string message, Exception exception)
{
_message = message;
_exception = exception;
}
}
public class WebSocket : IDisposable
{
private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private const string _version = "13";
internal const int FragmentLength = 1016;
private AuthenticationChallenge _authChallenge;
private string _base64Key;
private bool _client;
private Action _closeContext;
private CompressionMethod _compression;
private WebSocketContext _context;
private WebSocketSharp.Net.CookieCollection _cookies;
private WebSocketSharp.Net.NetworkCredential _credentials;
private bool _emitOnPing;
private bool _enableRedirection;
private string _extensions;
private AutoResetEvent _exitReceiving;
private Opcode _fopcode;
private object _forConn;
private object _forEvent;
private object _forMessageEventQueue;
private object _forSend;
private MemoryStream _fragmentsBuffer;
private Func<WebSocketContext, string> _handshakeRequestChecker;
private bool _ignoreExtensions;
private bool _inContinuation;
private volatile Logger _logger;
private Queue<MessageEventArgs> _messageEventQueue;
private uint _nonceCount;
private string _origin;
private bool _preAuth;
private string _protocol;
private string[] _protocols;
private WebSocketSharp.Net.NetworkCredential _proxyCredentials;
private Uri _proxyUri;
private volatile WebSocketState _readyState;
private AutoResetEvent _receivePong;
private bool _secure;
private ClientSslConfiguration _sslConfig;
private Stream _stream;
private TcpClient _tcpClient;
private Uri _uri;
private TimeSpan _waitTime;
internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies;
internal Func<WebSocketContext, string> CustomHandshakeRequestChecker
{
get
{
return _handshakeRequestChecker ?? ((Func<WebSocketContext, string>)((WebSocketContext context) => null));
}
set
{
_handshakeRequestChecker = value;
}
}
internal bool IgnoreExtensions
{
get
{
return _ignoreExtensions;
}
set
{
_ignoreExtensions = value;
}
}
internal bool IsConnected => _readyState == WebSocketState.Open || _readyState == WebSocketState.Closing;
public CompressionMethod Compression
{
get
{
return _compression;
}
set
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the compression.", null);
}
else
{
_compression = value;
}
}
}
}
public IEnumerable<WebSocketSharp.Net.Cookie> Cookies
{
get
{
object syncRoot;
object obj = (syncRoot = _cookies.SyncRoot);
Monitor.Enter(syncRoot);
try
{
foreach (WebSocketSharp.Net.Cookie cookie in _cookies)
{
yield return cookie;
}
}
finally
{
Monitor.Exit(obj);
}
}
}
public WebSocketSharp.Net.NetworkCredential Credentials => _credentials;
public bool EmitOnPing
{
get
{
return _emitOnPing;
}
set
{
_emitOnPing = value;
}
}
public bool EnableRedirection
{
get
{
return _enableRedirection;
}
set
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the enable redirection.", null);
}
else
{
_enableRedirection = value;
}
}
}
}
public string Extensions => _extensions ?? string.Empty;
public bool IsAlive => Ping();
public bool IsSecure => _secure;
public Logger Log
{
get
{
return _logger;
}
internal set
{
_logger = value;
}
}
public string Origin
{
get
{
return _origin;
}
set
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text == null)
{
if (value.IsNullOrEmpty())
{
_origin = value;
return;
}
if (!Uri.TryCreate(value, UriKind.Absolute, out Uri result) || result.Segments.Length > 1)
{
text = "The syntax of the origin must be '<scheme>://<host>[:<port>]'.";
}
}
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the origin.", null);
}
else
{
_origin = value.TrimEnd(new char[1] { '/' });
}
}
}
}
public string Protocol
{
get
{
return _protocol ?? string.Empty;
}
internal set
{
_protocol = value;
}
}
public WebSocketState ReadyState => _readyState;
public ClientSslConfiguration SslConfiguration
{
get
{
return _client ? (_sslConfig ?? (_sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost))) : null;
}
set
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the ssl configuration.", null);
}
else
{
_sslConfig = value;
}
}
}
}
public Uri Url => _client ? _uri : _context.RequestUri;
public TimeSpan WaitTime
{
get
{
return _waitTime;
}
set
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: true, asConnected: false) ?? value.CheckIfValidWaitTime();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the wait time.", null);
}
else
{
_waitTime = value;
}
}
}
}
public event EventHandler<CloseEventArgs> OnClose;
public event EventHandler<ErrorEventArgs> OnError;
public event EventHandler<MessageEventArgs> OnMessage;
public event EventHandler OnOpen;
internal WebSocket(HttpListenerWebSocketContext context, string protocol)
{
_context = context;
_protocol = protocol;
_closeContext = context.Close;
_logger = context.Log;
_secure = context.IsSecureConnection;
_stream = context.Stream;
_waitTime = TimeSpan.FromSeconds(1.0);
init();
}
internal WebSocket(TcpListenerWebSocketContext context, string protocol)
{
_context = context;
_protocol = protocol;
_closeContext = context.Close;
_logger = context.Log;
_secure = context.IsSecureConnection;
_stream = context.Stream;
_waitTime = TimeSpan.FromSeconds(1.0);
init();
}
public WebSocket(string url, params string[] protocols)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
if (url.Length == 0)
{
throw new ArgumentException("An empty string.", "url");
}
if (!url.TryCreateWebSocketUri(out _uri, out var message))
{
throw new ArgumentException(message, "url");
}
if (protocols != null && protocols.Length > 0)
{
message = protocols.CheckIfValidProtocols();
if (message != null)
{
throw new ArgumentException(message, "protocols");
}
_protocols = protocols;
}
_base64Key = CreateBase64Key();
_client = true;
_logger = new Logger();
_secure = _uri.Scheme == "wss";
_waitTime = TimeSpan.FromSeconds(5.0);
init();
}
private bool acceptHandshake()
{
_logger.Debug($"A connection request from {_context.UserEndPoint}:\n{_context}");
string text = checkIfValidHandshakeRequest(_context);
if (text != null)
{
_logger.Error(text);
error("An error has occurred while connecting.", null);
Close(WebSocketSharp.Net.HttpStatusCode.BadRequest);
return false;
}
if (_protocol != null && !_context.SecWebSocketProtocols.Contains((string protocol) => protocol == _protocol))
{
_protocol = null;
}
if (!_ignoreExtensions)
{
string text2 = _context.Headers["Sec-WebSocket-Extensions"];
if (text2 != null && text2.Length > 0)
{
processSecWebSocketExtensionsHeader(text2);
}
}
return sendHttpResponse(createHandshakeResponse());
}
private string checkIfAvailable(bool asServer, bool asConnected)
{
return (!_client && !asServer) ? "This operation isn't available as a server." : ((!asConnected) ? _readyState.CheckIfConnectable() : null);
}
private string checkIfCanConnect()
{
return (!_client && _readyState == WebSocketState.Closed) ? "Connect isn't available to reconnect as a server." : _readyState.CheckIfConnectable();
}
private string checkIfValidHandshakeRequest(WebSocketContext context)
{
NameValueCollection headers = context.Headers;
return (context.RequestUri == null) ? "Specifies an invalid Request-URI." : ((!context.IsWebSocketRequest) ? "Not a WebSocket connection request." : ((!validateSecWebSocketKeyHeader(headers["Sec-WebSocket-Key"])) ? "Includes an invalid Sec-WebSocket-Key header." : ((!validateSecWebSocketVersionClientHeader(headers["Sec-WebSocket-Version"])) ? "Includes an invalid Sec-WebSocket-Version header." : CustomHandshakeRequestChecker(context))));
}
private string checkIfValidHandshakeResponse(HttpResponse response)
{
NameValueCollection headers = response.Headers;
return response.IsRedirect ? "Indicates the redirection." : (response.IsUnauthorized ? "Requires the authentication." : ((!response.IsWebSocketResponse) ? "Not a WebSocket connection response." : ((!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"])) ? "Includes an invalid Sec-WebSocket-Accept header." : ((!validateSecWebSocketProtocolHeader(headers["Sec-WebSocket-Protocol"])) ? "Includes an invalid Sec-WebSocket-Protocol header." : ((!validateSecWebSocketExtensionsHeader(headers["Sec-WebSocket-Extensions"])) ? "Includes an invalid Sec-WebSocket-Extensions header." : ((!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"])) ? "Includes an invalid Sec-WebSocket-Version header." : null))))));
}
private string checkIfValidReceivedFrame(WebSocketFrame frame)
{
bool isMasked = frame.IsMasked;
return (_client && isMasked) ? "A frame from the server is masked." : ((!_client && !isMasked) ? "A frame from a client isn't masked." : ((_inContinuation && frame.IsData) ? "A data frame has been received while receiving the fragmented data." : ((frame.IsCompressed && _compression == CompressionMethod.None) ? "A compressed frame is without the available decompression method." : null)));
}
private void close(CloseEventArgs e, bool send, bool wait)
{
lock (_forConn)
{
if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed)
{
_logger.Info("Closing the connection has already been done.");
return;
}
send = send && _readyState == WebSocketState.Open;
wait = wait && send;
_readyState = WebSocketState.Closing;
}
_logger.Trace("Begin closing the connection.");
e.WasClean = closeHandshake(send ? WebSocketFrame.CreateCloseFrame(e.PayloadData, _client).ToByteArray() : null, wait ? _waitTime : TimeSpan.Zero, _client ? new Action(releaseClientResources) : new Action(releaseServerResources));
_logger.Trace("End closing the connection.");
_readyState = WebSocketState.Closed;
try
{
this.OnClose.Emit(this, e);
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
error("An exception has occurred during an OnClose event.", ex);
}
}
private void closeAsync(CloseEventArgs e, bool send, bool wait)
{
Action<CloseEventArgs, bool, bool> closer = close;
closer.BeginInvoke(e, send, wait, delegate(IAsyncResult ar)
{
closer.EndInvoke(ar);
}, null);
}
private bool closeHandshake(byte[] frameAsBytes, TimeSpan timeout, Action release)
{
bool flag = frameAsBytes != null && sendBytes(frameAsBytes);
bool flag2 = timeout == TimeSpan.Zero || (flag && _exitReceiving != null && _exitReceiving.WaitOne(timeout));
release();
if (_fragmentsBuffer != null)
{
_fragmentsBuffer.Dispose();
_fragmentsBuffer = null;
}
if (_receivePong != null)
{
_receivePong.Close();
_receivePong = null;
}
if (_exitReceiving != null)
{
_exitReceiving.Close();
_exitReceiving = null;
}
bool flag3 = flag && flag2;
_logger.Debug($"Was clean?: {flag3}\n sent: {flag}\n received: {flag2}");
return flag3;
}
private bool connect()
{
lock (_forConn)
{
string text = _readyState.CheckIfConnectable();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
return false;
}
try
{
_readyState = WebSocketState.Connecting;
if (_client ? doHandshake() : acceptHandshake())
{
_readyState = WebSocketState.Open;
return true;
}
}
catch (Exception exception)
{
processException(exception, "An exception has occurred while connecting.");
}
return false;
}
}
private string createExtensions()
{
StringBuilder stringBuilder = new StringBuilder(80);
if (_compression != 0)
{
string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover");
stringBuilder.AppendFormat("{0}, ", arg);
}
int length = stringBuilder.Length;
if (length > 2)
{
stringBuilder.Length = length - 2;
return stringBuilder.ToString();
}
return null;
}
private HttpResponse createHandshakeCloseResponse(WebSocketSharp.Net.HttpStatusCode code)
{
HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code);
httpResponse.Headers["Sec-WebSocket-Version"] = "13";
return httpResponse;
}
private HttpRequest createHandshakeRequest()
{
HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri);
NameValueCollection headers = httpRequest.Headers;
if (!_origin.IsNullOrEmpty())
{
headers["Origin"] = _origin;
}
headers["Sec-WebSocket-Key"] = _base64Key;
if (_protocols != null)
{
headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", ");
}
string text = createExtensions();
if (text != null)
{
headers["Sec-WebSocket-Extensions"] = text;
}
headers["Sec-WebSocket-Version"] = "13";
AuthenticationResponse authenticationResponse = null;
if (_authChallenge != null && _credentials != null)
{
authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
_nonceCount = authenticationResponse.NonceCount;
}
else if (_preAuth)
{
authenticationResponse = new AuthenticationResponse(_credentials);
}
if (authenticationResponse != null)
{
headers["Authorization"] = authenticationResponse.ToString();
}
if (_cookies.Count > 0)
{
httpRequest.SetCookies(_cookies);
}
return httpRequest;
}
private HttpResponse createHandshakeResponse()
{
HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse();
NameValueCollection headers = httpResponse.Headers;
headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key);
if (_protocol != null)
{
headers["Sec-WebSocket-Protocol"] = _protocol;
}
if (_extensions != null)
{
headers["Sec-WebSocket-Extensions"] = _extensions;
}
if (_cookies.Count > 0)
{
httpResponse.SetCookies(_cookies);
}
return httpResponse;
}
private MessageEventArgs dequeueFromMessageEventQueue()
{
lock (_forMessageEventQueue)
{
return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null;
}
}
private bool doHandshake()
{
setClientStream();
HttpResponse httpResponse = sendHandshakeRequest();
string text = checkIfValidHandshakeResponse(httpResponse);
if (text != null)
{
_logger.Error(text);
text = "An error has occurred while connecting.";
error(text, null);
close(new CloseEventArgs(CloseStatusCode.Abnormal, text), send: false, wait: false);
return false;
}
WebSocketSharp.Net.CookieCollection cookies = httpResponse.Cookies;
if (cookies.Count > 0)
{
_cookies.SetOrRemove(cookies);
}
return true;
}
private void enqueueToMessageEventQueue(MessageEventArgs e)
{
lock (_forMessageEventQueue)
{
_messageEventQueue.Enqueue(e);
}
}
private void error(string message, Exception exception)
{
try
{
this.OnError.Emit(this, new ErrorEventArgs(message, exception));
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
}
}
private void init()
{
_compression = CompressionMethod.None;
_cookies = new WebSocketSharp.Net.CookieCollection();
_forConn = new object();
_forEvent = new object();
_forSend = new object();
_messageEventQueue = new Queue<MessageEventArgs>();
_forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot;
_readyState = WebSocketState.Connecting;
}
private void open()
{
try
{
startReceiving();
lock (_forEvent)
{
try
{
this.OnOpen.Emit(this, EventArgs.Empty);
}
catch (Exception exception)
{
processException(exception, "An exception has occurred during an OnOpen event.");
}
}
}
catch (Exception exception)
{
processException(exception, "An exception has occurred while opening.");
}
}
private bool processCloseFrame(WebSocketFrame frame)
{
PayloadData payloadData = frame.PayloadData;
close(new CloseEventArgs(payloadData), !payloadData.IncludesReservedCloseStatusCode, wait: false);
return false;
}
private bool processDataFrame(WebSocketFrame frame)
{
enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame));
return true;
}
private void processException(Exception exception, string message)
{
CloseStatusCode closeStatusCode = CloseStatusCode.Abnormal;
string text = message;
if (exception is WebSocketException)
{
WebSocketException ex = (WebSocketException)exception;
closeStatusCode = ex.Code;
text = ex.Message;
}
if (closeStatusCode == CloseStatusCode.Abnormal || closeStatusCode == CloseStatusCode.TlsHandshakeFailure)
{
_logger.Fatal(exception.ToString());
}
else
{
_logger.Error(text);
}
error(message ?? closeStatusCode.GetMessage(), exception);
if (!_client && _readyState == WebSocketState.Connecting)
{
Close(WebSocketSharp.Net.HttpStatusCode.BadRequest);
}
else
{
close(new CloseEventArgs(closeStatusCode, text ?? closeStatusCode.GetMessage()), !closeStatusCode.IsReserved(), wait: false);
}
}
private bool processFragmentedFrame(WebSocketFrame frame)
{
if (!_inContinuation)
{
if (frame.IsContinuation)
{
return true;
}
_fopcode = frame.Opcode;
_fragmentsBuffer = new MemoryStream();
_inContinuation = true;
}
_fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData);
if (frame.IsFinal)
{
using (_fragmentsBuffer)
{
byte[] rawData = ((_compression != 0) ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray());
enqueueToMessageEventQueue(new MessageEventArgs(_fopcode, rawData));
}
_fragmentsBuffer = null;
_inContinuation = false;
}
return true;
}
private bool processPingFrame(WebSocketFrame frame)
{
if (send(new WebSocketFrame(Opcode.Pong, frame.PayloadData, _client).ToByteArray()))
{
_logger.Trace("Returned a Pong.");
}
if (_emitOnPing)
{
enqueueToMessageEventQueue(new MessageEventArgs(frame));
}
return true;
}
private bool processPongFrame(WebSocketFrame frame)
{
_receivePong.Set();
_logger.Trace("Received a Pong.");
return true;
}
private bool processReceivedFrame(WebSocketFrame frame)
{
string text = checkIfValidReceivedFrame(frame);
if (text != null)
{
return processUnsupportedFrame(frame, CloseStatusCode.ProtocolError, text);
}
frame.Unmask();
return frame.IsFragmented ? processFragmentedFrame(frame) : (frame.IsData ? processDataFrame(frame) : (frame.IsPing ? processPingFrame(frame) : (frame.IsPong ? processPongFrame(frame) : (frame.IsClose ? processCloseFrame(frame) : processUnsupportedFrame(frame, CloseStatusCode.UnsupportedData, null)))));
}
private void processSecWebSocketExtensionsHeader(string value)
{
StringBuilder stringBuilder = new StringBuilder(80);
bool flag = false;
foreach (string item in value.SplitHeaderValue(','))
{
string value2 = item.Trim();
if (!flag && value2.IsCompressionExtension(CompressionMethod.Deflate))
{
_compression = CompressionMethod.Deflate;
string arg = _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover");
stringBuilder.AppendFormat("{0}, ", arg);
flag = true;
}
}
int length = stringBuilder.Length;
if (length > 2)
{
stringBuilder.Length = length - 2;
_extensions = stringBuilder.ToString();
}
}
private bool processUnsupportedFrame(WebSocketFrame frame, CloseStatusCode code, string reason)
{
_logger.Debug("An unsupported frame:" + frame.PrintToString(dumped: false));
processException(new WebSocketException(code, reason), null);
return false;
}
private void releaseClientResources()
{
if (_stream != null)
{
_stream.Dispose();
_stream = null;
}
if (_tcpClient != null)
{
_tcpClient.Close();
_tcpClient = null;
}
}
private void releaseServerResources()
{
if (_closeContext != null)
{
_closeContext();
_closeContext = null;
_stream = null;
_context = null;
}
}
private bool send(byte[] frameAsBytes)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("Closing the connection has been done.");
return false;
}
return sendBytes(frameAsBytes);
}
}
private bool send(Opcode opcode, Stream stream)
{
lock (_forSend)
{
Stream stream2 = stream;
bool flag = false;
bool flag2 = false;
try
{
if (_compression != 0)
{
stream = stream.Compress(_compression);
flag = true;
}
flag2 = send(opcode, stream, flag);
if (!flag2)
{
error("Sending the data has been interrupted.", null);
}
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
error("An exception has occurred while sending the data.", ex);
}
finally
{
if (flag)
{
stream.Dispose();
}
stream2.Dispose();
}
return flag2;
}
}
private bool send(Opcode opcode, Stream stream, bool compressed)
{
long length = stream.Length;
if (length == 0)
{
return send(Fin.Final, opcode, new byte[0], compressed);
}
long num = length / 1016;
int num2 = (int)(length % 1016);
byte[] array = null;
if (num == 0)
{
array = new byte[num2];
return stream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed);
}
array = new byte[1016];
if (num == 1 && num2 == 0)
{
return stream.Read(array, 0, 1016) == 1016 && send(Fin.Final, opcode, array, compressed);
}
if (stream.Read(array, 0, 1016) != 1016 || !send(Fin.More, opcode, array, compressed))
{
return false;
}
long num3 = ((num2 == 0) ? (num - 2) : (num - 1));
for (long num4 = 0L; num4 < num3; num4++)
{
if (stream.Read(array, 0, 1016) != 1016 || !send(Fin.More, Opcode.Cont, array, compressed))
{
return false;
}
}
if (num2 == 0)
{
num2 = 1016;
}
else
{
array = new byte[num2];
}
return stream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed);
}
private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("Closing the connection has been done.");
return false;
}
return sendBytes(new WebSocketFrame(fin, opcode, data, compressed, _client).ToByteArray());
}
}
private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed)
{
Func<Opcode, Stream, bool> sender = send;
sender.BeginInvoke(opcode, stream, delegate(IAsyncResult ar)
{
try
{
bool obj = sender.EndInvoke(ar);
if (completed != null)
{
completed(obj);
}
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
error("An exception has occurred during a send callback.", ex);
}
}, null);
}
private bool sendBytes(byte[] bytes)
{
try
{
_stream.Write(bytes, 0, bytes.Length);
return true;
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
return false;
}
}
private HttpResponse sendHandshakeRequest()
{
HttpRequest httpRequest = createHandshakeRequest();
HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000);
if (httpResponse.IsUnauthorized)
{
string text = httpResponse.Headers["WWW-Authenticate"];
_logger.Warn($"Received an authentication requirement for '{text}'.");
if (text.IsNullOrEmpty())
{
_logger.Error("No authentication challenge is specified.");
return httpResponse;
}
_authChallenge = AuthenticationChallenge.Parse(text);
if (_authChallenge == null)
{
_logger.Error("An invalid authentication challenge is specified.");
return httpResponse;
}
if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest))
{
if (httpResponse.HasConnectionClose)
{
releaseClientResources();
setClientStream();
}
AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
_nonceCount = authenticationResponse.NonceCount;
httpRequest.Headers["Authorization"] = authenticationResponse.ToString();
httpResponse = sendHttpRequest(httpRequest, 15000);
}
}
if (httpResponse.IsRedirect)
{
string text2 = httpResponse.Headers["Location"];
_logger.Warn($"Received a redirection to '{text2}'.");
if (_enableRedirection)
{
if (text2.IsNullOrEmpty())
{
_logger.Error("No url to redirect is located.");
return httpResponse;
}
if (!text2.TryCreateWebSocketUri(out var result, out var message))
{
_logger.Error("An invalid url to redirect is located: " + message);
return httpResponse;
}
releaseClientResources();
_uri = result;
_secure = result.Scheme == "wss";
setClientStream();
return sendHandshakeRequest();
}
}
return httpResponse;
}
private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout)
{
_logger.Debug("A request to the server:\n" + request.ToString());
HttpResponse response = request.GetResponse(_stream, millisecondsTimeout);
_logger.Debug("A response to this request:\n" + response.ToString());
return response;
}
private bool sendHttpResponse(HttpResponse response)
{
_logger.Debug("A response to this request:\n" + response.ToString());
return sendBytes(response.ToByteArray());
}
private void sendProxyConnectRequest()
{
HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri);
HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000);
if (httpResponse.IsProxyAuthenticationRequired)
{
string text = httpResponse.Headers["Proxy-Authenticate"];
_logger.Warn($"Received a proxy authentication requirement for '{text}'.");
if (text.IsNullOrEmpty())
{
throw new WebSocketException("No proxy authentication challenge is specified.");
}
AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text);
if (authenticationChallenge == null)
{
throw new WebSocketException("An invalid proxy authentication challenge is specified.");
}
if (_proxyCredentials != null)
{
if (httpResponse.HasConnectionClose)
{
releaseClientResources();
_tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
_stream = _tcpClient.GetStream();
}
AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u);
httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString();
httpResponse = sendHttpRequest(httpRequest, 15000);
}
if (httpResponse.IsProxyAuthenticationRequired)
{
throw new WebSocketException("A proxy authentication is required.");
}
}
if (httpResponse.StatusCode[0] != '2')
{
throw new WebSocketException("The proxy has failed a connection to the requested host and port.");
}
}
private void setClientStream()
{
if (_proxyUri != null)
{
_tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
_stream = _tcpClient.GetStream();
sendProxyConnectRequest();
}
else
{
_tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port);
_stream = _tcpClient.GetStream();
}
if (_secure)
{
ClientSslConfiguration sslConfiguration = SslConfiguration;
string targetHost = sslConfiguration.TargetHost;
if (targetHost != _uri.DnsSafeHost)
{
throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified.");
}
try
{
SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback);
sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation);
_stream = sslStream;
}
catch (Exception innerException)
{
throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException);
}
}
}
private void startReceiving()
{
if (_messageEventQueue.Count > 0)
{
_messageEventQueue.Clear();
}
_exitReceiving = new AutoResetEvent(initialState: false);
_receivePong = new AutoResetEvent(initialState: false);
Action receive = null;
receive = delegate
{
WebSocketFrame.ReadAsync(_stream, unmask: false, delegate(WebSocketFrame frame)
{
if (processReceivedFrame(frame) && _readyState != WebSocketState.Closed)
{
receive();
if ((!frame.IsControl || (frame.IsPing && _emitOnPing)) && frame.IsFinal)
{
lock (_forEvent)
{
try
{
MessageEventArgs messageEventArgs = dequeueFromMessageEventQueue();
if (messageEventArgs != null && _readyState == WebSocketState.Open)
{
this.OnMessage.Emit(this, messageEventArgs);
}
}
catch (Exception exception)
{
processException(exception, "An exception has occurred during an OnMessage event.");
}
}
}
}
else if (_exitReceiving != null)
{
_exitReceiving.Set();
}
}, delegate(Exception ex)
{
processException(ex, "An exception has occurred while receiving a message.");
});
};
receive();
}
private bool validateSecWebSocketAcceptHeader(string value)
{
return value != null && value == CreateResponseKey(_base64Key);
}
private bool validateSecWebSocketExtensionsHeader(string value)
{
bool flag = _compression != CompressionMethod.None;
if (value == null || value.Length == 0)
{
if (flag)
{
_compression = CompressionMethod.None;
}
return true;
}
if (!flag)
{
return false;
}
foreach (string item in value.SplitHeaderValue(','))
{
string text = item.Trim();
if (text.IsCompressionExtension(_compression))
{
if (!text.Contains("server_no_context_takeover"))
{
_logger.Error("The server hasn't sent back 'server_no_context_takeover'.");
return false;
}
if (!text.Contains("client_no_context_takeover"))
{
_logger.Warn("The server hasn't sent back 'client_no_context_takeover'.");
}
string method = _compression.ToExtensionString();
if (text.SplitHeaderValue(';').Contains(delegate(string t)
{
t = t.Trim();
return t != method && t != "server_no_context_takeover" && t != "client_no_context_takeover";
}))
{
return false;
}
continue;
}
return false;
}
_extensions = value;
return true;
}
private bool validateSecWebSocketKeyHeader(string value)
{
if (value == null || value.Length == 0)
{
return false;
}
_base64Key = value;
return true;
}
private bool validateSecWebSocketProtocolHeader(string value)
{
if (value == null)
{
return _protocols == null;
}
if (_protocols == null || !_protocols.Contains((string protocol) => protocol == value))
{
return false;
}
_protocol = value;
return true;
}
private bool validateSecWebSocketVersionClientHeader(string value)
{
return value != null && value == "13";
}
private bool validateSecWebSocketVersionServerHeader(string value)
{
return value == null || value == "13";
}
internal static string CheckCloseParameters(ushort code, string reason, bool client)
{
return (!code.IsCloseStatusCode()) ? "An invalid close status code." : ((code != 1005) ? ((code == 1010 && !client) ? "MandatoryExtension cannot be used by the server." : ((code == 1011 && client) ? "ServerError cannot be used by the client." : ((!reason.IsNullOrEmpty() && Encoding.UTF8.GetBytes(reason).Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null));
}
internal static string CheckCloseParameters(CloseStatusCode code, string reason, bool client)
{
return (code != CloseStatusCode.NoStatus) ? ((code == CloseStatusCode.MandatoryExtension && !client) ? "MandatoryExtension cannot be used by the server." : ((code == CloseStatusCode.ServerError && client) ? "ServerError cannot be used by the client." : ((!reason.IsNullOrEmpty() && Encoding.UTF8.GetBytes(reason).Length > 123) ? "A reason has greater than the allowable max size." : null))) : ((!reason.IsNullOrEmpty()) ? "NoStatus cannot have a reason." : null);
}
internal static string CheckPingParameter(string message, out byte[] bytes)
{
bytes = Encoding.UTF8.GetBytes(message);
return (bytes.Length > 125) ? "A message has greater than the allowable max size." : null;
}
internal void Close(HttpResponse response)
{
_readyState = WebSocketState.Closing;
sendHttpResponse(response);
releaseServerResources();
_readyState = WebSocketState.Closed;
}
internal void Close(WebSocketSharp.Net.HttpStatusCode code)
{
Close(createHandshakeCloseResponse(code));
}
internal void Close(CloseEventArgs e, byte[] frameAsBytes, TimeSpan timeout)
{
lock (_forConn)
{
if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed)
{
_logger.Info("Closing the connection has already been done.");
return;
}
_readyState = WebSocketState.Closing;
}
e.WasClean = closeHandshake(frameAsBytes, timeout, releaseServerResources);
_readyState = WebSocketState.Closed;
try
{
this.OnClose.Emit(this, e);
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
}
}
internal void ConnectAsServer()
{
try
{
if (acceptHandshake())
{
_readyState = WebSocketState.Open;
open();
}
}
catch (Exception exception)
{
processException(exception, "An exception has occurred while connecting.");
}
}
internal static string CreateBase64Key()
{
byte[] array = new byte[16];
Random random = new Random();
random.NextBytes(array);
return Convert.ToBase64String(array);
}
internal static string CreateResponseKey(string base64Key)
{
StringBuilder stringBuilder = new StringBuilder(base64Key, 64);
stringBuilder.Append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
SHA1 sHA = new SHA1CryptoServiceProvider();
byte[] inArray = sHA.ComputeHash(Encoding.UTF8.GetBytes(stringBuilder.ToString()));
return Convert.ToBase64String(inArray);
}
internal bool Ping(byte[] frameAsBytes, TimeSpan timeout)
{
try
{
AutoResetEvent receivePong;
return _readyState == WebSocketState.Open && send(frameAsBytes) && (receivePong = _receivePong) != null && receivePong.WaitOne(timeout);
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
return false;
}
}
internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache)
{
lock (_forSend)
{
lock (_forConn)
{
if (_readyState != WebSocketState.Open)
{
_logger.Error("Closing the connection has been done.");
return;
}
try
{
if (!cache.TryGetValue(_compression, out var value))
{
value = new WebSocketFrame(Fin.Final, opcode, data.Compress(_compression), _compression != CompressionMethod.None, mask: false).ToByteArray();
cache.Add(_compression, value);
}
sendBytes(value);
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
}
}
}
}
internal void Send(Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache)
{
lock (_forSend)
{
try
{
if (!cache.TryGetValue(_compression, out var value))
{
value = stream.Compress(_compression);
cache.Add(_compression, value);
}
else
{
value.Position = 0L;
}
send(opcode, value, _compression != CompressionMethod.None);
}
catch (Exception ex)
{
_logger.Fatal(ex.ToString());
}
}
}
public void Close()
{
string text = _readyState.CheckIfClosable();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else
{
close(new CloseEventArgs(), send: true, wait: true);
}
}
public void Close(ushort code)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
close(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
close(new CloseEventArgs(code), wait, wait);
}
}
public void Close(CloseStatusCode code)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
close(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
close(new CloseEventArgs(code), wait, wait);
}
}
public void Close(ushort code, string reason)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
close(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
close(new CloseEventArgs(code, reason), wait, wait);
}
}
public void Close(CloseStatusCode code, string reason)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
close(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
close(new CloseEventArgs(code, reason), wait, wait);
}
}
public void CloseAsync()
{
string text = _readyState.CheckIfClosable();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else
{
closeAsync(new CloseEventArgs(), send: true, wait: true);
}
}
public void CloseAsync(ushort code)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
closeAsync(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
closeAsync(new CloseEventArgs(code), wait, wait);
}
}
public void CloseAsync(CloseStatusCode code)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, null, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
closeAsync(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
closeAsync(new CloseEventArgs(code), wait, wait);
}
}
public void CloseAsync(ushort code, string reason)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == 1005)
{
closeAsync(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
closeAsync(new CloseEventArgs(code, reason), wait, wait);
}
}
public void CloseAsync(CloseStatusCode code, string reason)
{
string text = _readyState.CheckIfClosable() ?? CheckCloseParameters(code, reason, _client);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in closing the connection.", null);
}
else if (code == CloseStatusCode.NoStatus)
{
closeAsync(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool wait = !code.IsReserved();
closeAsync(new CloseEventArgs(code, reason), wait, wait);
}
}
public void Connect()
{
string text = checkIfCanConnect();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
}
else if (connect())
{
open();
}
}
public void ConnectAsync()
{
string text = checkIfCanConnect();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in connecting.", null);
return;
}
Func<bool> connector = connect;
connector.BeginInvoke(delegate(IAsyncResult ar)
{
if (connector.EndInvoke(ar))
{
open();
}
}, null);
}
public bool Ping()
{
byte[] frameAsBytes = (_client ? WebSocketFrame.CreatePingFrame(mask: true).ToByteArray() : WebSocketFrame.EmptyUnmaskPingBytes);
return Ping(frameAsBytes, _waitTime);
}
public bool Ping(string message)
{
if (message == null || message.Length == 0)
{
return Ping();
}
byte[] bytes;
string text = CheckPingParameter(message, out bytes);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the ping.", null);
return false;
}
return Ping(WebSocketFrame.CreatePingFrame(bytes, _client).ToByteArray(), _waitTime);
}
public void Send(byte[] data)
{
string text = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
send(Opcode.Binary, new MemoryStream(data));
}
}
public void Send(FileInfo file)
{
string text = _readyState.CheckIfOpen() ?? file.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
send(Opcode.Binary, file.OpenRead());
}
}
public void Send(string data)
{
string text = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
send(Opcode.Text, new MemoryStream(Encoding.UTF8.GetBytes(data)));
}
}
public void SendAsync(byte[] data, Action<bool> completed)
{
string text = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
sendAsync(Opcode.Binary, new MemoryStream(data), completed);
}
}
public void SendAsync(FileInfo file, Action<bool> completed)
{
string text = _readyState.CheckIfOpen() ?? file.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
sendAsync(Opcode.Binary, file.OpenRead(), completed);
}
}
public void SendAsync(string data, Action<bool> completed)
{
string text = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData();
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
}
else
{
sendAsync(Opcode.Text, new MemoryStream(Encoding.UTF8.GetBytes(data)), completed);
}
}
public void SendAsync(Stream stream, int length, Action<bool> completed)
{
string text = _readyState.CheckIfOpen() ?? stream.CheckIfCanRead() ?? ((length < 1) ? "'length' is less than 1." : null);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in sending the data.", null);
return;
}
stream.ReadBytesAsync(length, delegate(byte[] data)
{
int num = data.Length;
if (num == 0)
{
_logger.Error("The data cannot be read from 'stream'.");
error("An error has occurred in sending the data.", null);
}
else
{
if (num < length)
{
_logger.Warn($"The data with 'length' cannot be read from 'stream':\n expected: {length}\n actual: {num}");
}
bool obj = send(Opcode.Binary, new MemoryStream(data));
if (completed != null)
{
completed(obj);
}
}
}, delegate(Exception ex)
{
_logger.Fatal(ex.ToString());
error("An exception has occurred while sending the data.", ex);
});
}
public void SetCookie(WebSocketSharp.Net.Cookie cookie)
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false) ?? ((cookie == null) ? "'cookie' is null." : null);
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the cookie.", null);
return;
}
lock (_cookies.SyncRoot)
{
_cookies.SetOrRemove(cookie);
}
}
}
public void SetCredentials(string username, string password, bool preAuth)
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text == null)
{
if (username.IsNullOrEmpty())
{
_credentials = null;
_preAuth = false;
_logger.Warn("The credentials were set back to the default.");
return;
}
text = ((Ext.Contains(username, ':') || !username.IsText()) ? "'username' contains an invalid character." : ((!password.IsNullOrEmpty() && !password.IsText()) ? "'password' contains an invalid character." : null));
}
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the credentials.", null);
}
else
{
_credentials = new WebSocketSharp.Net.NetworkCredential(username, password, _uri.PathAndQuery);
_preAuth = preAuth;
}
}
}
public void SetProxy(string url, string username, string password)
{
lock (_forConn)
{
string text = checkIfAvailable(asServer: false, asConnected: false);
if (text == null)
{
if (url.IsNullOrEmpty())
{
_proxyUri = null;
_proxyCredentials = null;
_logger.Warn("The proxy url and credentials were set back to the default.");
return;
}
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result) || result.Scheme != "http" || result.Segments.Length > 1)
{
text = "The syntax of the proxy url must be 'http://<host>[:<port>]'.";
}
else
{
_proxyUri = result;
if (username.IsNullOrEmpty())
{
_proxyCredentials = null;
_logger.Warn("The proxy credentials were set back to the default.");
return;
}
text = ((Ext.Contains(username, ':') || !username.IsText()) ? "'username' contains an invalid character." : ((!password.IsNullOrEmpty() && !password.IsText()) ? "'password' contains an invalid character." : null));
}
}
if (text != null)
{
_logger.Error(text);
error("An error has occurred in setting the proxy.", null);
}
else
{
_proxyCredentials = new WebSocketSharp.Net.NetworkCredential(username, password, $"{_uri.DnsSafeHost}:{_uri.Port}");
}
}
}
void IDisposable.Dispose()
{
close(new CloseEventArgs(CloseStatusCode.Away), send: true, wait: true);
}
}
}
namespace WebSocketSharp.Server
{
public class WebSocketServer
{
private IPAddress _address;
private WebSocketSharp.Net.AuthenticationSchemes _authSchemes;
private Func<IIdentity, WebSocketSharp.Net.NetworkCredential> _credFinder;
private bool _dnsStyle;
private string _hostname;
private TcpListener _listener;
private Logger _logger;
private int _port;
private string _realm;
private Thread _receiveThread;
private bool _reuseAddress;
private bool _secure;
private WebSocketServiceManager _services;
private ServerSslConfiguration _sslConfig;
private volatile ServerState _state;
private object _sync;
public IPAddress Address => _address;
public WebSocketSharp.Net.AuthenticationSchemes AuthenticationSchemes
{
get
{
return _authSchemes;
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_authSchemes = value;
}
}
}
public bool IsListening => _state == ServerState.Start;
public bool IsSecure => _secure;
public bool KeepClean
{
get
{
return _services.KeepClean;
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_services.KeepClean = value;
}
}
}
public Logger Log => _logger;
public int Port => _port;
public string Realm
{
get
{
return _realm ?? (_realm = "SECRET AREA");
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_realm = value;
}
}
}
public bool ReuseAddress
{
get
{
return _reuseAddress;
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_reuseAddress = value;
}
}
}
public ServerSslConfiguration SslConfiguration
{
get
{
return _sslConfig ?? (_sslConfig = new ServerSslConfiguration(null));
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_sslConfig = value;
}
}
}
public Func<IIdentity, WebSocketSharp.Net.NetworkCredential> UserCredentialsFinder
{
get
{
return (IIdentity identity) => null;
}
set
{
string text = _state.CheckIfStartable();
if (text != null)
{
_logger.Error(text);
}
else
{
_credFinder = value;
}
}
}
public TimeSpan WaitTime
{
get
{
return _services.WaitTime;
}
set
{
string text = _state.CheckIfStartable() ?? value.CheckIfValidWaitTime();
if (text != null)
{
_logger.Error(text);
}
else
{
_services.WaitTime = value;
}
}
}
public WebSocketServiceManager WebSocketServices => _services;
public WebSocketServer()
{
init(null, IPAddress.Any, 80, secure: false);
}
public WebSocketServer(int port)
: this(port, port == 443)
{
}
public WebSocketServer(string url)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
if (url.Length == 0)
{
throw new ArgumentException("An empty string.", "url");
}
if (!tryCreateUri(url, out var result, out var message))
{
throw new ArgumentException(message, "url");
}
string dnsSafeHost = result.DnsSafeHost;
IPAddress address = dnsSafeHost.ToIPAddress();
if (!address.IsLocal())
{
throw new ArgumentException("The host part isn't a local host name: " + url, "url");
}
init(dnsSafeHost, address, result.Port, result.Scheme == "wss");
}
public WebSocketServer(int port, bool secure)
{
if (!port.IsPortNumber())
{
throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port);
}
init(null, IPAddress.Any, port, secure);
}
public WebSocketServer(IPAddress address, int port)
: this(address, port, port == 443)
{
}
public WebSocketServer(IPAddress address, int port, bool secure)
{
if (address == null)
{
throw new ArgumentNullException("address");
}
if (!address.IsLocal())
{
throw new ArgumentException("Not a local IP address: " + address, "address");
}
if (!port.IsPortNumber())
{
throw new ArgumentOutOfRangeException("port", "Not between 1 and 65535 inclusive: " + port);
}
init(null, address, port, secure);
}
private void abort()
{
lock (_sync)
{
if (!IsListening)
{
return;
}
_state = ServerState.ShuttingDown;
}
_listener.Stop();
_services.Stop(new CloseEventArgs(CloseStatusCode.ServerError), send: true, wait: false);
_state = ServerState.Stop;
}
private static bool authenticate(TcpListenerWebSocketContext context, WebSocketSharp.Net.AuthenticationSchemes scheme, string realm, Func<IIdentity, WebSocketSharp.Net.NetworkCredential> credentialsFinder)
{
string chal = ((scheme == WebSocketSharp.Net.AuthenticationSchemes.Basic) ? AuthenticationChallenge.CreateBasicChallenge(realm).ToBasicString() : ((scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest) ? AuthenticationChallenge.CreateDigestChallenge(realm).ToDigestString() : null));
if (chal == null)
{
context.Close(WebSocketSharp.Net.HttpStatusCode.Forbidden);
return false;
}
int retry = -1;
Func<bool> auth = null;
auth = delegate
{
retry++;
if (retry > 99)
{
context.Close(WebSocketSharp.Net.HttpStatusCode.Forbidden);
return false;
}
IPrincipal principal = HttpUtility.CreateUser(context.Headers["Authorization"], scheme, realm, context.HttpMethod, credentialsFinder);
if (principal != null && principal.Identity.IsAuthenticated)
{
context.SetUser(principal);
return true;
}
context.SendAuthenticationChallenge(chal);
return auth();
};
return auth();
}
private string checkIfCertificateExists()
{
return (_secure && (_sslConfig == null || _sslConfig.ServerCertificate == null)) ? "The secure connection requires a server certificate." : null;
}
private void init(string hostname, IPAddress address, int port, bool secure)
{
_hostname = hostname ?? address.ToString();
_address = address;
_port = port;
_secure = secure;
_authSchemes = WebSocketSharp.Net.AuthenticationSchemes.Anonymous;
_dnsStyle = Uri.CheckHostName(hostname) == UriHostNameType.Dns;
_listener = new TcpListener(address, port);
_logger = new Logger();
_services = new WebSocketServiceManager(_logger);
_sync = new object();
}
private void processRequest(TcpListenerWebSocketContext context)
{
Uri requestUri = context.RequestUri;
if (requestUri == null || requestUri.Port != _port)
{
context.Close(WebSocketSharp.Net.HttpStatusCode.BadRequest);
return;
}
if (_dnsStyle)
{
string dnsSafeHost = requestUri.DnsSafeHost;
if (Uri.CheckHostName(dnsSafeHost) == UriHostNameType.Dns && dnsSafeHost != _hostname)
{
context.Close(WebSocketSharp.Net.HttpStatusCode.NotFound);
return;
}
}
if (!_services.InternalTryGetServiceHost(requestUri.AbsolutePath, out var host))
{
context.Close(WebSocketSharp.Net.HttpStatusCode.NotImplemented);
}
else
{
host.StartSession(context);
}
}
private void receiveRequest()
{
while (true)
{
bool flag = true;
try
{
TcpClient cl = _listener.AcceptTcpClient();
ThreadPool.QueueUserWorkItem(delegate
{
try
{
TcpListenerWebSocketContext webSocketContext = cl.GetWebSocketContext(null, _secure, _sslConfig, _logger);
if (_authSchemes == WebSocketSharp.Net.AuthenticationSchemes.Anonymous || authenticate(webSocketContext, _authSchemes, Realm, UserCredentialsFinder))
{
processRequest(webSocketContext);
}
}
catch (Exception ex3)
{
_logger.Fatal(ex3.ToString());
cl.Close();
}
});
}
catch (SocketException ex)
{
_logger.Warn("Receiving has been stopped.\n reason: " + ex.Message);
break;
}
catch (Exception ex2)
{
_logger.Fatal(ex2.ToString());
break;
}
}
if (IsListening)
{
abort();
}
}
private void startReceiving()
{
if (_reuseAddress)
{
_listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true);
}
_listener.Start();
_receiveThread = new Thread(receiveRequest);
_receiveThread.IsBackground = true;
_receiveThread.Start();
}
private void stopReceiving(int millisecondsTimeout)
{
_listener.Stop();
_receiveThread.Join(millisecondsTimeout);
}
private static bool tryCreateUri(string uriString, out Uri result, out string message)
{
if (!uriString.TryCreateWebSocketUri(out result, out message))
{
return false;
}
if (result.PathAndQuery != "/")
{
result = null;
message = "Includes the path or query component: " + uriString;
return false;
}
return true;
}
public void AddWebSocketService<TBehavior>(string path, Func<TBehavior> initializer) where TBehavior : WebSocketBehavior
{
string text = path.CheckIfValidServicePath() ?? ((initializer == null) ? "'initializer' is null." : null);
if (text != null)
{
_logger.Error(text);
}
else
{
_services.Add(path, initializer);
}
}
public void AddWebSocketService<TBehaviorWithNew>(string path) where TBehaviorWithNew : WebSocketBehavior, new()
{
AddWebSocketService(path, () => new TBehaviorWithNew());
}
public bool RemoveWebSocketService(string path)
{
string text = path.CheckIfValidServicePath();
if (text != null)
{
_logger.Error(text);
return false;
}
return _services.Remove(path);
}
public void Start()
{
lock (_sync)
{
string text = _state.CheckIfStartable() ?? checkIfCertificateExists();
if (text != null)
{
_logger.Error(text);
return;
}
_services.Start();
startReceiving();
_state = ServerState.Start;
}
}
public void Stop()
{
lock (_sync)
{
string text = _state.CheckIfStart();
if (text != null)
{
_logger.Error(text);
return;
}
_state = ServerState.ShuttingDown;
}
stopReceiving(5000);
_services.Stop(new CloseEventArgs(), send: true, wait: true);
_state = ServerState.Stop;
}
public void Stop(ushort code, string reason)
{
lock (_sync)
{
string text = _state.CheckIfStart() ?? WebSocket.CheckCloseParameters(code, reason, client: false);
if (text != null)
{
_logger.Error(text);
return;
}
_state = ServerState.ShuttingDown;
}
stopReceiving(5000);
if (code == 1005)
{
_services.Stop(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool flag = !code.IsReserved();
_services.Stop(new CloseEventArgs(code, reason), flag, flag);
}
_state = ServerState.Stop;
}
public void Stop(CloseStatusCode code, string reason)
{
lock (_sync)
{
string text = _state.CheckIfStart() ?? WebSocket.CheckCloseParameters(code, reason, client: false);
if (text != null)
{
_logger.Error(text);
return;
}
_state = ServerState.ShuttingDown;
}
stopReceiving(5000);
if (code == CloseStatusCode.NoStatus)
{
_services.Stop(new CloseEventArgs(), send: true, wait: true);
}
else
{
bool flag = !code.IsReserved();
_services.Stop(new CloseEventArgs(code, reason), flag, flag);
}
_state = ServerState.Stop;
}
}
}
namespace WebSocketSharp.Net
{
[Flags]
public enum AuthenticationSchemes
{
None = 0,
Digest = 1,
Basic = 8,
Anonymous = 0x8000
}
internal class ChunkStream
{
private int _chunkRead;
private int _chunkSize;
private List<Chunk> _chunks;
private bool _gotIt;
private WebHeaderCollection _headers;
private StringBuilder _saved;
private bool _sawCr;
private InputChunkState _state;
private int _trailerState;
internal WebHeaderCollection Headers => _headers;
public int ChunkLeft => _chunkSize - _chunkRead;
public bool WantMore => _state != InputChunkState.End;
public ChunkStream(WebHeaderCollection headers)
{
_headers = headers;
_chunkSize = -1;
_chunks = new List<Chunk>();
_saved = new StringBuilder();
}
public ChunkStream(byte[] buffer, int offset, int count, WebHeaderCollection headers)
: this(headers)
{
Write(buffer, offset, count);
}
private int read(byte[] buffer, int offset, int count)
{
int num = 0;
int count2 = _chunks.Count;
for (int i = 0; i < count2; i++)
{
Chunk chunk = _chunks[i];
if (chunk == null)
{
continue;
}
if (chunk.ReadLeft == 0)
{
_chunks[i] = null;
continue;
}
num += chunk.Read(buffer, offset + num, count - num);
if (num == count)
{
break;
}
}
return num;
}
private static string removeChunkExtension(string value)
{
int num = value.IndexOf(';');
return (num > -1) ? value.Substring(0, num) : value;
}
private InputChunkState seekCrLf(byte[] buffer, ref int offset, int length)
{
if (!_sawCr)
{
if (buffer[offset++] != 13)
{
throwProtocolViolation("CR is expected.");
}
_sawCr = true;
if (offset == length)
{
return InputChunkState.DataEnded;
}
}
if (buffer[offset++] != 10)
{
throwProtocolViolation("LF is expected.");
}
return InputChunkState.None;
}
private InputChunkState setChunkSize(byte[] buffer, ref int offset, int length)
{
byte b = 0;
while (offset < length)
{
b = buffer[offset++];
if (_sawCr)
{
if (b != 10)
{
throwProtocolViolation("LF is expected.");
}
break;
}
switch (b)
{
case 13:
_sawCr = true;
continue;
case 10:
throwProtocolViolation("LF is unexpected.");
break;
}
if (b == 32)
{
_gotIt = true;
}
if (!_gotIt)
{
_saved.Append((char)b);
}
if (_saved.Length > 20)
{
throwProtocolViolation("The chunk size is too long.");
}
}
if (!_sawCr || b != 10)
{
return InputChunkState.None;
}
_chunkRead = 0;
try
{
_chunkSize = int.Parse(removeChunkExtension(_saved.ToString()), NumberStyles.HexNumber);
}
catch
{
throwProtocolViolation("The chunk size cannot be parsed.");
}
if (_chunkSize == 0)
{
_trailerState = 2;
return InputChunkState.Trailer;
}
return InputChunkState.Data;
}
private InputChunkState setTrailer(byte[] buffer, ref int offset, int length)
{
if (_trailerState == 2 && buffer[offset] == 13 && _saved.Length == 0)
{
offset++;
if (offset < length && buffer[offset] == 10)
{
offset++;
return InputChunkState.End;
}
offset--;
}
while (offset < length && _trailerState < 4)
{
byte b = buffer[offset++];
_saved.Append((char)b);
if (_saved.Length > 4196)
{
throwProtocolViolation("The trailer is too long.");
}
if (_trailerState == 1 || _trailerState == 3)
{
if (b != 10)
{
throwProtocolViolation("LF is expected.");
}
_trailerState++;
continue;
}
switch (b)
{
case 13:
_trailerState++;
continue;
case 10:
throwProtocolViolation("LF is unexpected.");
break;
}
_trailerState = 0;
}
if (_trailerState < 4)
{
return InputChunkState.Trailer;
}
_saved.Length -= 2;
StringReader stringReader = new StringReader(_saved.ToString());
string text;
while ((text = stringReader.ReadLine()) != null && text.Length > 0)
{
_headers.Add(text);
}
return InputChunkState.End;
}
private static void throwProtocolViolation(string message)
{
throw new WebException(message, null, WebExceptionStatus.ServerProtocolViolation, null);
}
private void write(byte[] buffer, ref int offset, int length)
{
if (_state == InputChunkState.End)
{
throwProtocolViolation("The chunks were ended.");
}
if (_state == InputChunkState.None)
{
_state = setChunkSize(buffer, ref offset, length);
if (_state == InputChunkState.None)
{
return;
}
_saved.Length = 0;
_sawCr = false;
_gotIt = false;
}
if (_state == InputChunkState.Data && offset < length)
{
_state = writeData(buffer, ref offset, length);
if (_state == InputChunkState.Data)
{
return;
}
}
if (_state == InputChunkState.DataEnded && offset < length)
{
_state = seekCrLf(buffer, ref offset, length);
if (_state == InputChunkState.DataEnded)
{
return;
}
_sawCr = false;
}
if (_state == InputChunkState.Trailer && offset < length)
{
_state = setTrailer(buffer, ref offset, length);
if (_state == InputChunkState.Trailer)
{
return;
}
_saved.Length = 0;
}
if (offset < length)
{
write(buffer, ref offset, length);
}
}
private InputChunkState writeData(byte[] buffer, ref int offset, int length)
{
int num = length - offset;
int num2 = _chunkSize - _chunkRead;
if (num > num2)
{
num = num2;
}
byte[] array = new byte[num];
Buffer.BlockCopy(buffer, offset, array, 0, num);
_chunks.Add(new Chunk(array));
offset += num;
_chunkRead += num;
return (_chunkRead != _chunkSize) ? InputChunkState.Data : InputChunkState.DataEnded;
}
internal void ResetBuffer()
{
_chunkRead = 0;
_chunkSize = -1;
_chunks.Clear();
}
internal int WriteAndReadBack(byte[] buffer, int offset, int writeCount, int readC