diff --git a/.gitignore b/.gitignore
index 2655c8e..2c2c277 100644
--- a/.gitignore
+++ b/.gitignore
@@ -348,6 +348,11 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+app/XDM/XDM.Win.Installer/ffmpeg-x86.exe
+*.wixobj
+app/XDM/XDM.Win.Installer/net4.7.2.wxs
+app/XDM/XDM.Win.Installer/net4.7.2/
+app/XDM/XDM.Win.Installer/*.msi
+*.wixpdb
+app/XDM/XDM.Win.Installer/*.exe
app/xdm-browser-monitor/extension-code.js
-app/XDM/translation-generator/
-app/XDM/XDM.Win.Installer/
diff --git a/app/XDM/.editorconfig b/app/XDM/.editorconfig
new file mode 100644
index 0000000..a7a6802
--- /dev/null
+++ b/app/XDM/.editorconfig
@@ -0,0 +1,4 @@
+[*.cs]
+
+# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
+dotnet_diagnostic.CS8618.severity = silent
diff --git a/app/XDM/BrowserMonitor/BrowserMonitor.csproj b/app/XDM/BrowserMonitor/BrowserMonitor.csproj
deleted file mode 100644
index 6e7c0ea..0000000
--- a/app/XDM/BrowserMonitor/BrowserMonitor.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2;net5.0
- AnyCPU;x86
- 9.0
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/XDM/BrowserMonitor/NativeMessagingHostHandler.cs b/app/XDM/BrowserMonitor/NativeMessagingHostHandler.cs
deleted file mode 100644
index 3de494e..0000000
--- a/app/XDM/BrowserMonitor/NativeMessagingHostHandler.cs
+++ /dev/null
@@ -1,297 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO.Pipes;
-using System.IO;
-using XDM.Core.Lib.Common;
-using System.Threading;
-#if NET35
-using NetFX.Polyfill;
-#else
-using System.Collections.Concurrent;
-#endif
-using TraceLog;
-
-namespace BrowserMonitoring
-{
- public class NativeMessagingHostHandler : IDisposable
- {
- private int MaxPipeInstance = 254;
- private static readonly string PipeName = "XDM_Ipc_Browser_Monitoring_Pipe";
- private List inPipes = new();
- private Dictionary inOutMap = new();
- private readonly IApp app;
- private static Mutex globalMutex;
- private readonly BlockingCollection Messages = new();
- private Thread WriterThread;
-
- public static void EnsureSingleInstance(IApp app)
- {
- try
- {
- using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
- throw new InstanceAlreadyRunningException(@"XDM instance already running, Mutex exists 'Global\XDM_Active_Instance'");
- }
- catch (Exception ex)
- {
- Log.Debug(ex, "Exception in NativeMessagingHostHandler ctor");
- if (ex is InstanceAlreadyRunningException)
- {
- Log.Debug(ex, "Sending args to running instance");
-
- if (app.Args != null && app.Args.Length > 0)
- {
- SendArgsToRunningInstance(app.Args);
- Environment.Exit(0);
- }
- throw;
- }
- }
- globalMutex = new Mutex(true, @"Global\XDM_Active_Instance");
- }
-
- public NativeMessagingHostHandler(IApp app)
- {
- this.app = app;
- try
- {
- using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
- throw new InstanceAlreadyRunningException(@"XDM instance already running, Mutex exists 'Global\XDM_Active_Instance'");
- }
- catch (Exception ex)
- {
- Log.Debug(ex, "Exception in NativeMessagingHostHandler ctor");
- if (ex is InstanceAlreadyRunningException)
- {
- Log.Debug(ex, "Sending args to running instance");
-
- if (app.Args != null && app.Args.Length > 0)
- {
- SendArgsToRunningInstance(app.Args);
- Environment.Exit(0);
- }
- throw;
- }
- }
- globalMutex = new Mutex(true, @"Global\XDM_Active_Instance");
- }
-
- public void BroadcastConfig()
- {
- var bytes = GetSyncBytes(app);
- Messages.Add(bytes);
- }
-
- public void StartPipedChannel()
- {
- WriterThread = new Thread(() =>
- {
- while (true)
- {
- //Log.Debug("Total messages to be sent to native host: " + Messages.Count);
- var bytes = Messages.Take();
- foreach (var key in inOutMap.Keys)
- {
- //Log.Debug("Sending message to native host");
- try
- {
- var outpipe = inOutMap[key];
- WriteMessage(outpipe, bytes);
- //Log.Debug("Send message to native host successfully");
- }
- catch (Exception ex)
- {
- Log.Debug(ex, "Send message to native host failed");
- }
- }
- }
- });
- WriterThread.Start();
- new Thread(() =>
- {
- try
- {
- if (inPipes.Count == MaxPipeInstance)
- {
- Log.Debug("Max pipe count of " + MaxPipeInstance + " is reached");
- return;
- }
- var inPipe =
- new NamedPipeServerStream(PipeName,
- PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances,
- PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
- inPipes.Add(inPipe);
- var first = true;
- while (true)
- {
- Log.Debug("Waiting for native host pipe...");
- inPipe.WaitForConnection();
- Log.Debug("Pipe request received");
-
- if (first)
- {
- Log.Debug("Creating one more additional pipe");
- StartPipedChannel();
- first = false;
- }
-
- try
- {
- ConsumePipe(inPipe);
- }
- catch (Exception e)
- {
- inPipe.Disconnect();
- Log.Debug(e, "Error in message exchange");
- }
- Log.Debug("Terminated message exchange, will reuse the pipe");
- }
- }
- catch (Exception ex)
- {
- Log.Debug(ex, "Error in message exchange flow");
- }
- }).Start();
- }
-
- private void ConsumePipe(NamedPipeServerStream inPipe)
- {
- try
- {
- Log.Debug("Initiate message handshake");
- var clientPipeName = Encoding.UTF8.GetString(ReadMessageBytes(inPipe));
- Log.Debug("Client pipe: " + clientPipeName);
- if (clientPipeName.StartsWith("XDM-APP-"))
- {
- var command = ReadMessageBytes(inPipe);
- var args = ArgsProcessor.ParseArgs(Encoding.UTF8.GetString(command).Split('\r'));
- ArgsProcessor.Process(app, args);
- return;
- }
- var outPipe = new NamedPipeClientStream(".", clientPipeName, PipeDirection.Out);
- outPipe.Connect();
- SendConfig(outPipe);
- inOutMap[inPipe] = outPipe;
- Log.Debug("Message handshake completed");
- while (true)
- {
- var text = ReadMessageBytes(inPipe);
- using var ms = new MemoryStream(text);
- using var br = new BinaryReader(ms);
- // Log.Debug("{Text}", text);
- var envelop = RawBrowserMessageEnvelop.Deserialize(br);
- BrowserMessageHandler.Handle(app, envelop);
- }
- }
- finally
- {
- try
- {
- NamedPipeClientStream? op = null;
- lock (this)
- {
- if (inOutMap.TryGetValue(inPipe, out op))
- {
- inOutMap.Remove(inPipe);
- }
- }
- op?.Close();
- op?.Dispose();
- }
- catch { }
- }
- }
-
- private void SendConfig(Stream pipe)
- {
- var bytes = GetSyncBytes(app);
- WriteMessage(pipe, bytes);
- }
-
- private static void ReadFully(Stream stream, byte[] buf, int bytesToRead)
- {
- var rem = bytesToRead;
- var index = 0;
- while (rem > 0)
- {
- var c = stream.Read(buf, index, rem);
- if (c == 0) throw new IOException("Unexpected EOF");
- index += c;
- rem -= c;
- }
- }
-
- private static byte[] ReadMessageBytes(Stream pipe)
- {
- var b4 = new byte[4];
- ReadFully(pipe, b4, 4);
- var syncLength = BitConverter.ToInt32(b4, 0);
- var bytes = new byte[syncLength];
- ReadFully(pipe, bytes, syncLength);
- return bytes;
- }
-
- private static void WriteMessage(Stream pipe, string message)
- {
- var msgBytes = Encoding.UTF8.GetBytes(message);
- WriteMessage(pipe, msgBytes);
- }
-
- private static void WriteMessage(Stream pipe, byte[] msgBytes)
- {
- var bytes = BitConverter.GetBytes(msgBytes.Length);
- pipe.Write(bytes, 0, bytes.Length);
- pipe.Write(msgBytes, 0, msgBytes.Length);
- pipe.Flush();
- }
-
- public void Dispose()
- {
- foreach (var pipe in inPipes)
- {
- try { pipe.Disconnect(); } catch { }
- try { pipe.Dispose(); } catch { }
- }
- }
-
- private static byte[] GetSyncBytes(IApp app)
- {
- var msg = new SyncMessage()
- {
- Enabled = Config.Instance.IsBrowserMonitoringEnabled,
- BlockedHosts = Config.Instance.BlockedHosts,
- VideoUrls = new string[0],
- FileExts = Config.Instance.FileExtensions,
- VidExts = Config.Instance.VideoExtensions,
- VidList = app.GetVideoList(false).Select(a => new VideoItem
- {
- Id = a.ID,
- Text = a.File,
- Info = a.DisplayName
- }).ToList(),
- MimeList = new string[] { "video", "audio", "mpegurl", "f4m", "m3u8", "dash" },
- BlockedMimeList = new string[] { "text/javascript", "application/javascript", "text/css", "text/html" },
- VideoUrlsWithPostReq = new string[] { "ubei/v1/player?key=", "ubei/v1/next?key=" }
- };
- return msg.Serialize();
- }
-
- private static void SendArgsToRunningInstance(string[] args)
- {
- using var clientPipe =
- new NamedPipeClientStream(".", PipeName, PipeDirection.Out);
- clientPipe.Connect();
- WriteMessage(clientPipe, $"XDM-APP-${Guid.NewGuid()}");
- WriteMessage(clientPipe, string.Join("\r", args));
- clientPipe.Flush();
- }
- }
-
- public class InstanceAlreadyRunningException : Exception
- {
- public InstanceAlreadyRunningException(string message) : base(message)
- {
- }
- }
-}
diff --git a/app/XDM/BrowserMonitor/RawBrowserMessageEnvelop.cs b/app/XDM/BrowserMonitor/RawBrowserMessageEnvelop.cs
deleted file mode 100644
index 7f1c386..0000000
--- a/app/XDM/BrowserMonitor/RawBrowserMessageEnvelop.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-using XDM.Core.Lib.Util;
-
-
-namespace BrowserMonitoring
-{
- public struct RawBrowserMessageEnvelop
- {
- public string MessageType { get; set; }
-
- public RawBrowserMessage Message { get; set; }
-
- public string[] VideoIds { get; set; }
-
- public void Serialize(BinaryWriter w)
- {
- RawBrowserMessageEnvelopSerializerV1.Serialize(this, w);
- }
-
- public static RawBrowserMessageEnvelop Deserialize(BinaryReader r)
- {
- var version = r.ReadInt32();
- if (version == 1)
- {
- return RawBrowserMessageEnvelopSerializerV1.Deserialize(r);
- }
- throw new InvalidDataException($"Version ${version} not supported.");
- }
- }
-
- internal static class RawBrowserMessageEnvelopSerializerV1
- {
- public static void Serialize(RawBrowserMessageEnvelop e, BinaryWriter w)
- {
- w.Write(1);
- w.Write(e.MessageType);
- w.Write(e.Message != null);
- if (e.Message != null)
- {
- w.Write(e.Message.Url ?? string.Empty);
- w.Write(e.Message.File ?? string.Empty);
- w.Write(e.Message.Method ?? string.Empty);
- w.Write(e.Message.RequestBody ?? string.Empty);
- Helpers.WriteStateHeaders(e.Message.RequestHeaders, w);
- Helpers.WriteStateHeaders(e.Message.ResponseHeaders, w);
- Helpers.WriteStateCookies(e.Message.Cookies, w);
- }
- var count = e.VideoIds?.Length ?? 0;
- w.Write(count);
- if (e.VideoIds != null && e.VideoIds.Length > 0)
- {
- foreach (var item in e.VideoIds)
- {
- w.Write(item);
- }
- }
- }
-
- public static RawBrowserMessageEnvelop Deserialize(BinaryReader r)
- {
- var e = new RawBrowserMessageEnvelop { };
- e.MessageType = Helpers.ReadString(r);
- if (r.ReadBoolean())
- {
- e.Message = new();
- e.Message.Url = Helpers.ReadString(r);
- e.Message.File = Helpers.ReadString(r);
- e.Message.Method = Helpers.ReadString(r);
- e.Message.RequestBody = Helpers.ReadString(r);
- Helpers.ReadStateHeaders(r, out Dictionary> dict1);
- Helpers.ReadStateHeaders(r, out Dictionary> dict2);
- Helpers.ReadStateCookies(r, out Dictionary dict3);
- e.Message.RequestHeaders = dict1;
- e.Message.ResponseHeaders = dict2;
- e.Message.Cookies = dict3;
- }
- var count = r.ReadInt32();
- e.VideoIds = new string[count];
- for (int i = 0; i < count; i++)
- {
- e.VideoIds[i] = r.ReadString();
- }
- return e;
- }
- }
-}
diff --git a/app/XDM/CoreFx.Polyfill/CoreFx.Polyfill.csproj b/app/XDM/CoreFx.Polyfill/CoreFx.Polyfill.csproj
deleted file mode 100644
index b9974ef..0000000
--- a/app/XDM/CoreFx.Polyfill/CoreFx.Polyfill.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net4.5.2
- 9.0
- enable
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/XDM/CoreFx.Polyfill/ExternalInit.cs b/app/XDM/CoreFx.Polyfill/ExternalInit.cs
deleted file mode 100644
index 830871d..0000000
--- a/app/XDM/CoreFx.Polyfill/ExternalInit.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using System.ComponentModel;
-
-namespace System.Runtime.CompilerServices
-{
- [EditorBrowsable(EditorBrowsableState.Never)]
- internal class IsExternalInit { }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/HashHelpers.cs b/app/XDM/CoreFx.Polyfill/HashHelpers.cs
deleted file mode 100644
index f3e5b58..0000000
--- a/app/XDM/CoreFx.Polyfill/HashHelpers.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Numerics.Hashing
-{
- internal static class HashHelpers
- {
- public static int Combine(int h1, int h2)
- {
- // RyuJIT optimizes this to use the ROL instruction
- // Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830
- uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
- return ((int)rol5 + h1) ^ h2;
- }
- }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/Index.cs b/app/XDM/CoreFx.Polyfill/Index.cs
deleted file mode 100644
index d29e272..0000000
--- a/app/XDM/CoreFx.Polyfill/Index.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- /// Represent a type can be used to index a collection either from the start or the end.
- ///
- /// Index is used by the C# compiler to support the new index syntax
- ///
- /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
- /// int lastElement = someArray[^1]; // lastElement = 5
- ///
- ///
- public readonly struct Index : IEquatable
- {
- private readonly int _value;
-
- /// Construct an Index using a value and indicating if the index is from the start or from the end.
- /// The index value. it has to be zero or positive number.
- /// Indicating if the index is from the start or from the end.
- ///
- /// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Index(int value, bool fromEnd = false)
- {
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException("ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException();");
-
- }
-
- if (fromEnd)
- _value = ~value;
- else
- _value = value;
- }
-
- // The following private constructors mainly created for perf reason to avoid the checks
- private Index(int value)
- {
- _value = value;
- }
-
- /// Create an Index pointing at first element.
- public static Index Start => new Index(0);
-
- /// Create an Index pointing at beyond last element.
- public static Index End => new Index(~0);
-
- /// Create an Index from the start at the position indicated by the value.
- /// The index value from the start.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Index FromStart(int value)
- {
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException("ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException");
-
- }
-
- return new Index(value);
- }
-
- /// Create an Index from the end at the position indicated by the value.
- /// The index value from the end.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Index FromEnd(int value)
- {
- if (value < 0)
- {
- throw new ArgumentOutOfRangeException("ThrowHelper.ThrowValueArgumentOutOfRange_NeedNonNegNumException();");
-
- }
-
- return new Index(~value);
- }
-
- /// Returns the index value.
- public int Value
- {
- get
- {
- if (_value < 0)
- return ~_value;
- else
- return _value;
- }
- }
-
- /// Indicates whether the index is from the start or the end.
- public bool IsFromEnd => _value < 0;
-
- /// Calculate the offset from the start using the giving collection length.
- /// The length of the collection that the Index will be used with. length has to be a positive value
- ///
- /// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
- /// we don't validate either the returned offset is greater than the input length.
- /// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
- /// then used to index a collection will get out of range exception which will be same affect as the validation.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int GetOffset(int length)
- {
- int offset = _value;
- if (IsFromEnd)
- {
- // offset = length - (~value)
- // offset = length + (~(~value) + 1)
- // offset = length + value + 1
-
- offset += length + 1;
- }
- return offset;
- }
-
- /// Indicates whether the current Index object is equal to another object of the same type.
- /// An object to compare with this object
- public override bool Equals([NotNullWhen(true)] object? value) => value is Index && _value == ((Index)value)._value;
-
- /// Indicates whether the current Index object is equal to another Index object.
- /// An object to compare with this object
- public bool Equals(Index other) => _value == other._value;
-
- /// Returns the hash code for this instance.
- public override int GetHashCode() => _value;
-
- /// Converts integer number to an Index.
- public static implicit operator Index(int value) => FromStart(value);
-
- /// Converts the value of the current Index object to its equivalent string representation.
- public override string ToString()
- {
- if (IsFromEnd)
- return ToStringFromEnd();
-
- return ((uint)Value).ToString();
- }
-
- private string ToStringFromEnd()
- {
-#if (!NETSTANDARD2_0 && !NETFRAMEWORK)
- Span span = stackalloc char[11]; // 1 for ^ and 10 for longest possible uint value
- bool formatted = ((uint)Value).TryFormat(span.Slice(1), out int charsWritten);
- Debug.Assert(formatted);
- span[0] = '^';
- return new string(span.Slice(0, charsWritten + 1));
-#else
- return '^' + Value.ToString();
-#endif
- }
- }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/KeyValuePair.cs b/app/XDM/CoreFx.Polyfill/KeyValuePair.cs
deleted file mode 100644
index 28957c9..0000000
--- a/app/XDM/CoreFx.Polyfill/KeyValuePair.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Text;
-
-namespace System.Collections.Generic
-{
- // Provides the Create factory method for KeyValuePair.
- public static class KeyValuePair
- {
- // Creates a new KeyValuePair from the given values.
- public static KeyValuePair Create(TKey key, TValue value)
- {
- return new KeyValuePair(key, value);
- }
-
- ///
- /// Used by KeyValuePair.ToString to reduce generic code
- ///
- internal static string PairToString(object? key, object? value)
- {
- var s = new StringBuilder();
-
- s.Append('[');
-
- if (key != null)
- {
- s.Append(key.ToString());
- }
-
- s.Append(", ");
-
- if (value != null)
- {
- s.Append(value.ToString());
- }
-
- s.Append(']');
-
- return s.ToString();
- }
- }
-
- //// A KeyValuePair holds a key and a value from a dictionary.
- //// It is used by the IEnumerable implementation for both IDictionary
- //// and IReadOnlyDictionary.
- //[Serializable]
- //[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- //public readonly struct KeyValuePair
- //{
- // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
- // private readonly TKey key; // Do not rename (binary serialization)
- // [DebuggerBrowsable(DebuggerBrowsableState.Never)]
- // private readonly TValue value; // Do not rename (binary serialization)
-
- // public KeyValuePair(TKey key, TValue value)
- // {
- // this.key = key;
- // this.value = value;
- // }
-
- // public TKey Key => key;
-
- // public TValue Value => value;
-
- // public override string ToString()
- // {
- // return KeyValuePair.PairToString(Key, Value);
- // }
-
- // [EditorBrowsable(EditorBrowsableState.Never)]
- // public void Deconstruct(out TKey key, out TValue value)
- // {
- // key = Key;
- // value = Value;
- // }
- //}
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/NotNullWhenAttribute.cs b/app/XDM/CoreFx.Polyfill/NotNullWhenAttribute.cs
deleted file mode 100644
index 87bc9ce..0000000
--- a/app/XDM/CoreFx.Polyfill/NotNullWhenAttribute.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT license.
-
-#if NETFRAMEWORK || NETSTANDARD2_0
-
-namespace System.Diagnostics.CodeAnalysis
-{
- /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it.
- [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
- public sealed class NotNullWhenAttribute : Attribute
- {
- /// Initializes the attribute with the specified return value condition.
- ///
- /// The return value condition. If the method returns this value, the associated parameter will not be null.
- ///
- public NotNullWhenAttribute(bool returnValue)
- {
- ReturnValue = returnValue;
- }
-
- /// Gets the return value condition.
- public bool ReturnValue { get; }
- }
-}
-#endif
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/OSPlatform.cs b/app/XDM/CoreFx.Polyfill/OSPlatform.cs
deleted file mode 100644
index 392628f..0000000
--- a/app/XDM/CoreFx.Polyfill/OSPlatform.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-
-namespace System.Runtime.InteropServices
-{
- public readonly struct OSPlatform : IEquatable
- {
- public static OSPlatform FreeBSD { get; } = new OSPlatform("FREEBSD");
-
- public static OSPlatform Linux { get; } = new OSPlatform("LINUX");
-
- public static OSPlatform OSX { get; } = new OSPlatform("OSX");
-
- public static OSPlatform Windows { get; } = new OSPlatform("WINDOWS");
-
- internal string Name { get; }
-
- private OSPlatform(string osPlatform)
- {
- if (osPlatform == null) throw new ArgumentNullException(nameof(osPlatform));
- if (osPlatform.Length == 0) throw new ArgumentException("SR.Argument_EmptyValue", nameof(osPlatform));
-
- Name = osPlatform;
- }
-
- ///
- /// Creates a new OSPlatform instance.
- ///
- /// If you plan to call this method frequently, please consider caching its result.
- public static OSPlatform Create(string osPlatform)
- {
- return new OSPlatform(osPlatform);
- }
-
- public bool Equals(OSPlatform other)
- {
- return Equals(other.Name);
- }
-
- internal bool Equals(string? other)
- {
- return string.Equals(Name, other, StringComparison.OrdinalIgnoreCase);
- }
-
- public override bool Equals([NotNullWhen(true)] object? obj)
- {
- return obj is OSPlatform osPlatform && Equals(osPlatform);
- }
-
- public override int GetHashCode()
- {
- return Name == null ? 0 : StringComparer.OrdinalIgnoreCase.GetHashCode(Name);
- }
-
- public override string ToString()
- {
- return Name ?? string.Empty;
- }
-
- public static bool operator ==(OSPlatform left, OSPlatform right)
- {
- return left.Equals(right);
- }
-
- public static bool operator !=(OSPlatform left, OSPlatform right)
- {
- return !(left == right);
- }
- }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/ProcessStartInfoHelper.cs b/app/XDM/CoreFx.Polyfill/ProcessStartInfoHelper.cs
deleted file mode 100644
index 5798163..0000000
--- a/app/XDM/CoreFx.Polyfill/ProcessStartInfoHelper.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace CoreFx.Polyfill
-{
- public static class ProcessStartInfoHelper
- {
- public static string ArgumentListToArgsString(IList arguments)
- {
- var stringBuilder = new StringBuilder();
- foreach (var argument in arguments)
- {
- AppendArgument(stringBuilder, argument);
- }
- return stringBuilder.ToString();
- }
-
- public static void AppendArgument(StringBuilder stringBuilder, string argument)
- {
- if (stringBuilder.Length != 0)
- {
- stringBuilder.Append(' ');
- }
-
- // Parsing rules for non-argv[0] arguments:
- // - Backslash is a normal character except followed by a quote.
- // - 2N backslashes followed by a quote ==> N literal backslashes followed by unescaped quote
- // - 2N+1 backslashes followed by a quote ==> N literal backslashes followed by a literal quote
- // - Parsing stops at first whitespace outside of quoted region.
- // - (post 2008 rule): A closing quote followed by another quote ==> literal quote, and parsing remains in quoting mode.
- if (argument.Length != 0 && ContainsNoWhitespaceOrQuotes(argument))
- {
- // Simple case - no quoting or changes needed.
- stringBuilder.Append(argument);
- }
- else
- {
- stringBuilder.Append(Quote);
- int idx = 0;
- while (idx < argument.Length)
- {
- char c = argument[idx++];
- if (c == Backslash)
- {
- int numBackSlash = 1;
- while (idx < argument.Length && argument[idx] == Backslash)
- {
- idx++;
- numBackSlash++;
- }
-
- if (idx == argument.Length)
- {
- // We'll emit an end quote after this so must double the number of backslashes.
- stringBuilder.Append(Backslash, numBackSlash * 2);
- }
- else if (argument[idx] == Quote)
- {
- // Backslashes will be followed by a quote. Must double the number of backslashes.
- stringBuilder.Append(Backslash, numBackSlash * 2 + 1);
- stringBuilder.Append(Quote);
- idx++;
- }
- else
- {
- // Backslash will not be followed by a quote, so emit as normal characters.
- stringBuilder.Append(Backslash, numBackSlash);
- }
-
- continue;
- }
-
- if (c == Quote)
- {
- // Escape the quote so it appears as a literal. This also guarantees that we won't end up generating a closing quote followed
- // by another quote (which parses differently pre-2008 vs. post-2008.)
- stringBuilder.Append(Backslash);
- stringBuilder.Append(Quote);
- continue;
- }
-
- stringBuilder.Append(c);
- }
-
- stringBuilder.Append(Quote);
- }
- }
-
- private static bool ContainsNoWhitespaceOrQuotes(string s)
- {
- for (int i = 0; i < s.Length; i++)
- {
- char c = s[i];
- if (char.IsWhiteSpace(c) || c == Quote)
- {
- return false;
- }
- }
-
- return true;
- }
-
- private const char Quote = '\"';
- private const char Backslash = '\\';
- }
-}
diff --git a/app/XDM/CoreFx.Polyfill/Range.cs b/app/XDM/CoreFx.Polyfill/Range.cs
deleted file mode 100644
index 7c4449d..0000000
--- a/app/XDM/CoreFx.Polyfill/Range.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Numerics.Hashing;
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- /// Represent a range has start and end indexes.
- ///
- /// Range is used by the C# compiler to support the range syntax.
- ///
- /// int[] someArray = new int[5] { 1, 2, 3, 4, 5 };
- /// int[] subArray1 = someArray[0..2]; // { 1, 2 }
- /// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
- ///
- ///
- public readonly struct Range : IEquatable
- {
- /// Represent the inclusive start index of the Range.
- public Index Start { get; }
-
- /// Represent the exclusive end index of the Range.
- public Index End { get; }
-
- /// Construct a Range object using the start and end indexes.
- /// Represent the inclusive start index of the range.
- /// Represent the exclusive end index of the range.
- public Range(Index start, Index end)
- {
- Start = start;
- End = end;
- }
-
- /// Indicates whether the current Range object is equal to another object of the same type.
- /// An object to compare with this object
- public override bool Equals([NotNullWhen(true)] object? value) =>
- value is Range r &&
- r.Start.Equals(Start) &&
- r.End.Equals(End);
-
- /// Indicates whether the current Range object is equal to another Range object.
- /// An object to compare with this object
- public bool Equals(Range other) => other.Start.Equals(Start) && other.End.Equals(End);
-
- /// Returns the hash code for this instance.
- public override int GetHashCode()
- {
-#if (!NETSTANDARD2_0 && !NETFRAMEWORK)
- return HashCode.Combine(Start.GetHashCode(), End.GetHashCode());
-#else
- return HashHelpers.Combine(Start.GetHashCode(), End.GetHashCode());
-#endif
- }
-
- /// Converts the value of the current Range object to its equivalent string representation.
- public override string ToString()
- {
-#if (!NETSTANDARD2_0 && !NETFRAMEWORK)
- Span span = stackalloc char[2 + (2 * 11)]; // 2 for "..", then for each index 1 for '^' and 10 for longest possible uint
- int pos = 0;
-
- if (Start.IsFromEnd)
- {
- span[0] = '^';
- pos = 1;
- }
- bool formatted = ((uint)Start.Value).TryFormat(span.Slice(pos), out int charsWritten);
- Debug.Assert(formatted);
- pos += charsWritten;
-
- span[pos++] = '.';
- span[pos++] = '.';
-
- if (End.IsFromEnd)
- {
- span[pos++] = '^';
- }
- formatted = ((uint)End.Value).TryFormat(span.Slice(pos), out charsWritten);
- Debug.Assert(formatted);
- pos += charsWritten;
-
- return new string(span.Slice(0, pos));
-#else
- return Start.ToString() + ".." + End.ToString();
-#endif
- }
-
- /// Create a Range object starting from start index to the end of the collection.
- public static Range StartAt(Index start) => new Range(start, Index.End);
-
- /// Create a Range object starting from first element in the collection to the end Index.
- public static Range EndAt(Index end) => new Range(Index.Start, end);
-
- /// Create a Range object starting from first element to the end.
- public static Range All => new Range(Index.Start, Index.End);
-
- /// Calculate the start offset and length of range object using a collection length.
- /// The length of the collection that the range will be used with. length has to be a positive value.
- ///
- /// For performance reason, we don't validate the input length parameter against negative values.
- /// It is expected Range will be used with collections which always have non negative length/count.
- /// We validate the range is inside the length scope though.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public (int Offset, int Length) GetOffsetAndLength(int length)
- {
- int start;
- Index startIndex = Start;
- if (startIndex.IsFromEnd)
- start = length - startIndex.Value;
- else
- start = startIndex.Value;
-
- int end;
- Index endIndex = End;
- if (endIndex.IsFromEnd)
- end = length - endIndex.Value;
- else
- end = endIndex.Value;
-
- if ((uint)end > (uint)length || (uint)start > (uint)end)
- {
- throw new ArgumentOutOfRangeException("ExceptionArgument.length");
- }
-
- return (start, end - start);
- }
- }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/RuntimeInformation.cs b/app/XDM/CoreFx.Polyfill/RuntimeInformation.cs
deleted file mode 100644
index 46193dc..0000000
--- a/app/XDM/CoreFx.Polyfill/RuntimeInformation.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Reflection;
-
-namespace System.Runtime.InteropServices
-{
- public static partial class RuntimeInformation
- {
- ///
- /// Indicates whether the current application is running on the specified platform.
- ///
- public static bool IsOSPlatform(OSPlatform osPlatform) => IsOSPlatform(osPlatform.Name);
-
- ///
- /// Indicates whether the current application is running on the specified platform.
- ///
- /// Case-insensitive platform name. Examples: Browser, Linux, FreeBSD, Android, iOS, macOS, tvOS, watchOS, Windows.
- public static bool IsOSPlatform(string platform)
- {
- if (platform == null)
- {
- throw new ArgumentNullException(nameof(platform));
- }
- return platform.Equals("WINDOWS", StringComparison.OrdinalIgnoreCase);
- }
- }
-}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/SR.cs b/app/XDM/CoreFx.Polyfill/SR.cs
deleted file mode 100644
index a7f2fea..0000000
--- a/app/XDM/CoreFx.Polyfill/SR.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-//// Licensed to the .NET Foundation under one or more agreements.
-//// The .NET Foundation licenses this file to you under the MIT license.
-
-//#nullable enable
-//using System.Resources;
-
-//namespace System
-//{
-// internal static partial class SR
-// {
-// private static readonly bool s_usingResourceKeys = false;
-
-// // This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
-// // by default it returns the value of System.Resources.UseSystemResourceKeys AppContext switch or false if not specified.
-// // Native code generators can replace the value this returns based on user input at the time of native code generation.
-// // The Linker is also capable of replacing the value of this method when the application is being trimmed.
-// private static bool UsingResourceKeys() => s_usingResourceKeys;
-
-// internal static string GetResourceString(string resourceKey)
-// {
-// if (UsingResourceKeys())
-// {
-// return resourceKey;
-// }
-
-// string? resourceString = null;
-// try
-// {
-// resourceString =
-//#if SYSTEM_PRIVATE_CORELIB
-// InternalGetResourceString(resourceKey);
-//#else
-// ResourceManager.GetString(resourceKey);
-//#endif
-// }
-// catch (MissingManifestResourceException) { }
-
-// return resourceString!; // only null if missing resources
-// }
-
-// internal static string GetResourceString(string resourceKey, string defaultString)
-// {
-// string resourceString = GetResourceString(resourceKey);
-
-// return resourceKey == resourceString || resourceString == null ? defaultString : resourceString;
-// }
-
-// internal static string Format(string resourceFormat, object? p1)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1);
-// }
-
-// return string.Format(resourceFormat, p1);
-// }
-
-// internal static string Format(string resourceFormat, object? p1, object? p2)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1, p2);
-// }
-
-// return string.Format(resourceFormat, p1, p2);
-// }
-
-// internal static string Format(string resourceFormat, object? p1, object? p2, object? p3)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1, p2, p3);
-// }
-
-// return string.Format(resourceFormat, p1, p2, p3);
-// }
-
-// internal static string Format(string resourceFormat, params object?[]? args)
-// {
-// if (args != null)
-// {
-// if (UsingResourceKeys())
-// {
-// return resourceFormat + ", " + string.Join(", ", args);
-// }
-
-// return string.Format(resourceFormat, args);
-// }
-
-// return resourceFormat;
-// }
-
-// internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1);
-// }
-
-// return string.Format(provider, resourceFormat, p1);
-// }
-
-// internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1, p2);
-// }
-
-// return string.Format(provider, resourceFormat, p1, p2);
-// }
-
-// internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3)
-// {
-// if (UsingResourceKeys())
-// {
-// return string.Join(", ", resourceFormat, p1, p2, p3);
-// }
-
-// return string.Format(provider, resourceFormat, p1, p2, p3);
-// }
-
-// internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args)
-// {
-// if (args != null)
-// {
-// if (UsingResourceKeys())
-// {
-// return resourceFormat + ", " + string.Join(", ", args);
-// }
-
-// return string.Format(provider, resourceFormat, args);
-// }
-
-// return resourceFormat;
-// }
-// }
-//}
\ No newline at end of file
diff --git a/app/XDM/CoreFx.Polyfill/ShimCompatExtensions.cs b/app/XDM/CoreFx.Polyfill/ShimCompatExtensions.cs
deleted file mode 100644
index 82ae50c..0000000
--- a/app/XDM/CoreFx.Polyfill/ShimCompatExtensions.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-
-namespace System
-{
- public static class ShimCompatExtensions
- {
-
- public static string Join(char separator, IEnumerable values)
- {
- return string.Join(separator.ToString(), values);
- }
-
- public static bool ContainsKey(this IDictionary dict, TKey key)
- {
- return dict.TryGetValue(key, out _);
- }
-
- public static bool ContainsKey(this GroupCollection dict, string key)
- {
- try
- {
- return dict[key] != null;
- }
- catch
- {
- return false;
- }
- }
-
- public static TValue? GetValueOrDefault(this IDictionary dict, TKey key)
- {
- return GetValueOrDefault(dict, key, default(TValue)!);
- }
-
- ///
- /// Gets the value for a given key if a matching key exists in the dictionary.
- ///
- /// The key to search for.
- /// The default value to return if no matching key is found in the dictionary.
- ///
- /// The value for the key, or if no matching key was found.
- ///
- public static TValue GetValueOrDefault(this IDictionary dict, TKey key, TValue defaultValue)
- {
-
- TValue value;
- if (dict.TryGetValue(key, out value!))
- {
- return value;
- }
-
- return defaultValue;
- }
- }
-}
diff --git a/app/XDM/CoreFx.Polyfill/StringExtensions.cs b/app/XDM/CoreFx.Polyfill/StringExtensions.cs
deleted file mode 100644
index 72071fa..0000000
--- a/app/XDM/CoreFx.Polyfill/StringExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace CoreFx.Polyfill
-{
- public static class StringExtensions
- {
- public static string[] Split(this string str)
- {
- return str.Split(str.ToCharArray());
- }
- }
-}
diff --git a/app/XDM/CoreFx.Polyfill/ThrowHelper.cs b/app/XDM/CoreFx.Polyfill/ThrowHelper.cs
deleted file mode 100644
index 65e4d0b..0000000
--- a/app/XDM/CoreFx.Polyfill/ThrowHelper.cs
+++ /dev/null
@@ -1,1165 +0,0 @@
-//// Licensed to the .NET Foundation under one or more agreements.
-//// The .NET Foundation licenses this file to you under the MIT license.
-
-
-//// This file defines an internal static class used to throw exceptions in BCL code.
-//// The main purpose is to reduce code size.
-////
-//// The old way to throw an exception generates quite a lot IL code and assembly code.
-//// Following is an example:
-//// C# source
-//// throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
-//// IL code:
-//// IL_0003: ldstr "key"
-//// IL_0008: ldstr "ArgumentNull_Key"
-//// IL_000d: call string System.Environment::GetResourceString(string)
-//// IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
-//// IL_0017: throw
-//// which is 21bytes in IL.
-////
-//// So we want to get rid of the ldstr and call to Environment.GetResource in IL.
-//// In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
-//// argument name and resource name in a small integer. The source code will be changed to
-//// ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
-////
-//// The IL code will be 7 bytes.
-//// IL_0008: ldc.i4.4
-//// IL_0009: ldc.i4.4
-//// IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
-//// IL_000f: ldarg.0
-////
-//// This will also reduce the Jitted code size a lot.
-////
-//// It is very important we do this for generic classes because we can easily generate the same code
-//// multiple times for different instantiation.
-////
-
-//using System.Buffers;
-//using System.Collections.Generic;
-//using System.Diagnostics;
-//using System.Diagnostics.CodeAnalysis;
-//using System.IO;
-//using System.Runtime.CompilerServices;
-//using System.Runtime.Serialization;
-
-//namespace System
-//{
-// [StackTraceHidden]
-// internal static class ThrowHelper
-// {
-// [DoesNotReturn]
-// internal static void ThrowArrayTypeMismatchException()
-// {
-// throw new ArrayTypeMismatchException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidTypeWithPointersNotSupported(Type targetType)
-// {
-// throw new ArgumentException(SR.Format(SR.Argument_InvalidTypeWithPointersNotSupported, targetType));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowIndexOutOfRangeException()
-// {
-// throw new IndexOutOfRangeException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException()
-// {
-// throw new ArgumentOutOfRangeException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_DestinationTooShort()
-// {
-// throw new ArgumentException(SR.Argument_DestinationTooShort, "destination");
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_OverlapAlignmentMismatch()
-// {
-// throw new ArgumentException(SR.Argument_OverlapAlignmentMismatch);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_CannotExtractScalar(ExceptionArgument argument)
-// {
-// throw GetArgumentException(ExceptionResource.Argument_CannotExtractScalar, argument);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_TupleIncorrectType(object obj)
-// {
-// throw new ArgumentException(SR.Format(SR.ArgumentException_ValueTupleIncorrectType, obj.GetType()), "other");
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_IndexException()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.index,
-// ExceptionResource.ArgumentOutOfRange_Index);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_BadComparer(object? comparer)
-// {
-// throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.index,
-// ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowValueArgumentOutOfRange_NeedNonNegNumException()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.value,
-// ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowLengthArgumentOutOfRange_ArgumentOutOfRange_NeedNonNegNum()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.length,
-// ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.startIndex,
-// ExceptionResource.ArgumentOutOfRange_Index);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.count,
-// ExceptionResource.ArgumentOutOfRange_Count);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_Year()
-// {
-// throw GetArgumentOutOfRangeException(ExceptionArgument.year,
-// ExceptionResource.ArgumentOutOfRange_Year);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_Month(int month)
-// {
-// throw new ArgumentOutOfRangeException(nameof(month), month, SR.ArgumentOutOfRange_Month);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_DayNumber(int dayNumber)
-// {
-// throw new ArgumentOutOfRangeException(nameof(dayNumber), dayNumber, SR.ArgumentOutOfRange_DayNumber);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_BadYearMonthDay()
-// {
-// throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_BadHourMinuteSecond()
-// {
-// throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRange_TimeSpanTooLong()
-// {
-// throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowWrongKeyTypeArgumentException(T key, Type targetType)
-// {
-// // Generic key to move the boxing to the right hand side of throw
-// throw GetWrongKeyTypeArgumentException((object?)key, targetType);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowWrongValueTypeArgumentException(T value, Type targetType)
-// {
-// // Generic key to move the boxing to the right hand side of throw
-// throw GetWrongValueTypeArgumentException((object?)value, targetType);
-// }
-
-// private static ArgumentException GetAddingDuplicateWithKeyArgumentException(object? key)
-// {
-// return new ArgumentException(SR.Format(SR.Argument_AddingDuplicateWithKey, key));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowAddingDuplicateWithKeyArgumentException(T key)
-// {
-// // Generic key to move the boxing to the right hand side of throw
-// throw GetAddingDuplicateWithKeyArgumentException((object?)key);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowKeyNotFoundException(T key)
-// {
-// // Generic key to move the boxing to the right hand side of throw
-// throw GetKeyNotFoundException((object?)key);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException(ExceptionResource resource)
-// {
-// throw GetArgumentException(resource);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument)
-// {
-// throw GetArgumentException(resource, argument);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_HandleNotSync(string paramName)
-// {
-// throw new ArgumentException(SR.Arg_HandleNotSync, paramName);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_HandleNotAsync(string paramName)
-// {
-// throw new ArgumentException(SR.Arg_HandleNotAsync, paramName);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentNullException(ExceptionArgument argument)
-// {
-// throw new ArgumentNullException(GetArgumentName(argument));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentNullException(ExceptionResource resource)
-// {
-// throw new ArgumentNullException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentNullException(ExceptionArgument argument, ExceptionResource resource)
-// {
-// throw new ArgumentNullException(GetArgumentName(argument), GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument)
-// {
-// throw new ArgumentOutOfRangeException(GetArgumentName(argument));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
-// {
-// throw GetArgumentOutOfRangeException(argument, resource);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource)
-// {
-// throw GetArgumentOutOfRangeException(argument, paramNumber, resource);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowEndOfFileException()
-// {
-// throw CreateEndOfFileException();
-// }
-
-// internal static Exception CreateEndOfFileException() =>
-// new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException()
-// {
-// throw new InvalidOperationException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException(ExceptionResource resource)
-// {
-// throw GetInvalidOperationException(resource);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_OutstandingReferences()
-// {
-// throw new InvalidOperationException(SR.Memory_OutstandingReferences);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e)
-// {
-// throw new InvalidOperationException(GetResourceString(resource), e);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowSerializationException(ExceptionResource resource)
-// {
-// throw new SerializationException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowSecurityException(ExceptionResource resource)
-// {
-// throw new System.Security.SecurityException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowRankException(ExceptionResource resource)
-// {
-// throw new RankException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowNotSupportedException(ExceptionResource resource)
-// {
-// throw new NotSupportedException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowNotSupportedException_UnseekableStream()
-// {
-// throw new NotSupportedException(SR.NotSupported_UnseekableStream);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowNotSupportedException_UnreadableStream()
-// {
-// throw new NotSupportedException(SR.NotSupported_UnreadableStream);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowNotSupportedException_UnwritableStream()
-// {
-// throw new NotSupportedException(SR.NotSupported_UnwritableStream);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowUnauthorizedAccessException(ExceptionResource resource)
-// {
-// throw new UnauthorizedAccessException(GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource)
-// {
-// throw new ObjectDisposedException(objectName, GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowObjectDisposedException_StreamClosed(string? objectName)
-// {
-// throw new ObjectDisposedException(objectName, SR.ObjectDisposed_StreamClosed);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowObjectDisposedException_FileClosed()
-// {
-// throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowObjectDisposedException(ExceptionResource resource)
-// {
-// throw new ObjectDisposedException(null, GetResourceString(resource));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowNotSupportedException()
-// {
-// throw new NotSupportedException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowAggregateException(List exceptions)
-// {
-// throw new AggregateException(exceptions);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowOutOfMemoryException()
-// {
-// throw new OutOfMemoryException();
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_Argument_InvalidArrayType()
-// {
-// throw new ArgumentException(SR.Argument_InvalidArrayType);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentException_InvalidHandle(string? paramName)
-// {
-// throw new ArgumentException(SR.Arg_InvalidHandle, paramName);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_InvalidOperation_EnumNotStarted()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_InvalidOperation_EnumEnded()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_EnumCurrent(int index)
-// {
-// throw GetInvalidOperationException_EnumCurrent(index);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_InvalidOperation_NoValue()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_NoValue);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_HandleIsNotInitialized()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotInitialized);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowInvalidOperationException_HandleIsNotPinned()
-// {
-// throw new InvalidOperationException(SR.InvalidOperation_HandleIsNotPinned);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array? array, int offset, int count)
-// {
-// throw GetArraySegmentCtorValidationFailedException(array, offset, count);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowFormatException_BadFormatSpecifier()
-// {
-// throw new FormatException(SR.Argument_BadFormatSpecifier);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException_PrecisionTooLarge()
-// {
-// throw new ArgumentOutOfRangeException("precision", SR.Format(SR.Argument_PrecisionTooLarge, StandardFormat.MaxPrecision));
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException_SymbolDoesNotFit()
-// {
-// throw new ArgumentOutOfRangeException("symbol", SR.Argument_BadFormatSpecifier);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException_NeedPosNum(string? paramName)
-// {
-// throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_NeedPosNum);
-// }
-
-// [DoesNotReturn]
-// internal static void ThrowArgumentOutOfRangeException_NeedNonNegNum(string paramName)
-// {
-// throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_NeedNonNegNum);
-// }
-
-// [DoesNotReturn]
-// internal static void ArgumentOutOfRangeException_Enum_Value()
-// {
-// throw new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_Enum);
-// }
-
-// private static Exception GetArraySegmentCtorValidationFailedException(Array? array, int offset, int count)
-// {
-// if (array == null)
-// return new ArgumentNullException(nameof(array));
-// if (offset < 0)
-// return new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum);
-// if (count < 0)
-// return new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
-
-// Debug.Assert(array.Length - offset < count);
-// return new ArgumentException(SR.Argument_InvalidOffLen);
-// }
-
-// private static ArgumentException GetArgumentException(ExceptionResource resource)
-// {
-// return new ArgumentException(GetResourceString(resource));
-// }
-
-// private static InvalidOperationException GetInvalidOperationException(ExceptionResource resource)
-// {
-// return new InvalidOperationException(GetResourceString(resource));
-// }
-
-// private static ArgumentException GetWrongKeyTypeArgumentException(object? key, Type targetType)
-// {
-// return new ArgumentException(SR.Format(SR.Arg_WrongType, key, targetType), nameof(key));
-// }
-
-// private static ArgumentException GetWrongValueTypeArgumentException(object? value, Type targetType)
-// {
-// return new ArgumentException(SR.Format(SR.Arg_WrongType, value, targetType), nameof(value));
-// }
-
-// private static KeyNotFoundException GetKeyNotFoundException(object? key)
-// {
-// return new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key));
-// }
-
-// private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
-// {
-// return new ArgumentOutOfRangeException(GetArgumentName(argument), GetResourceString(resource));
-// }
-
-// private static ArgumentException GetArgumentException(ExceptionResource resource, ExceptionArgument argument)
-// {
-// return new ArgumentException(GetResourceString(resource), GetArgumentName(argument));
-// }
-
-// private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource)
-// {
-// return new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]", GetResourceString(resource));
-// }
-
-// private static InvalidOperationException GetInvalidOperationException_EnumCurrent(int index)
-// {
-// return new InvalidOperationException(
-// index < 0 ?
-// SR.InvalidOperation_EnumNotStarted :
-// SR.InvalidOperation_EnumEnded);
-// }
-
-// // Allow nulls for reference types and Nullable, but not for value types.
-// // Aggressively inline so the jit evaluates the if in place and either drops the call altogether
-// // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException
-// [MethodImpl(MethodImplOptions.AggressiveInlining)]
-// internal static void IfNullAndNullsAreIllegalThenThrow(object? value, ExceptionArgument argName)
-// {
-// // Note that default(T) is not equal to null for value types except when T is Nullable.
-// if (!(default(T) == null) && value == null)
-// ThrowHelper.ThrowArgumentNullException(argName);
-// }
-
-// // Throws if 'T' is disallowed in Vector in the Numerics namespace.
-// // If 'T' is allowed, no-ops. JIT will elide the method entirely if 'T'
-// // is supported and we're on an optimized release build.
-// [MethodImpl(MethodImplOptions.AggressiveInlining)]
-// internal static void ThrowForUnsupportedNumericsVectorBaseType() where T : struct
-// {
-// if (typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) &&
-// typeof(T) != typeof(short) && typeof(T) != typeof(ushort) &&
-// typeof(T) != typeof(int) && typeof(T) != typeof(uint) &&
-// typeof(T) != typeof(long) && typeof(T) != typeof(ulong) &&
-// typeof(T) != typeof(float) && typeof(T) != typeof(double) &&
-// typeof(T) != typeof(nint) && typeof(T) != typeof(nuint))
-// {
-// ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
-// }
-// }
-
-// // Throws if 'T' is disallowed in Vector64/128/256 in the Intrinsics namespace.
-// // If 'T' is allowed, no-ops. JIT will elide the method entirely if 'T'
-// // is supported and we're on an optimized release build.
-// [MethodImpl(MethodImplOptions.AggressiveInlining)]
-// internal static void ThrowForUnsupportedIntrinsicsVectorBaseType() where T : struct
-// {
-// if (typeof(T) != typeof(byte) && typeof(T) != typeof(sbyte) &&
-// typeof(T) != typeof(short) && typeof(T) != typeof(ushort) &&
-// typeof(T) != typeof(int) && typeof(T) != typeof(uint) &&
-// typeof(T) != typeof(long) && typeof(T) != typeof(ulong) &&
-// typeof(T) != typeof(float) && typeof(T) != typeof(double))
-// {
-// ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
-// }
-// }
-
-//#if false // Reflection-based implementation does not work for CoreRT/ProjectN
-// // This function will convert an ExceptionArgument enum value to the argument name string.
-// [MethodImpl(MethodImplOptions.NoInlining)]
-// private static string GetArgumentName(ExceptionArgument argument)
-// {
-// Debug.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument),
-// "The enum value is not defined, please check the ExceptionArgument Enum.");
-
-// return argument.ToString();
-// }
-//#endif
-
-// private static string GetArgumentName(ExceptionArgument argument)
-// {
-// switch (argument)
-// {
-// case ExceptionArgument.obj:
-// return "obj";
-// case ExceptionArgument.dictionary:
-// return "dictionary";
-// case ExceptionArgument.array:
-// return "array";
-// case ExceptionArgument.info:
-// return "info";
-// case ExceptionArgument.key:
-// return "key";
-// case ExceptionArgument.text:
-// return "text";
-// case ExceptionArgument.values:
-// return "values";
-// case ExceptionArgument.value:
-// return "value";
-// case ExceptionArgument.startIndex:
-// return "startIndex";
-// case ExceptionArgument.task:
-// return "task";
-// case ExceptionArgument.bytes:
-// return "bytes";
-// case ExceptionArgument.byteIndex:
-// return "byteIndex";
-// case ExceptionArgument.byteCount:
-// return "byteCount";
-// case ExceptionArgument.ch:
-// return "ch";
-// case ExceptionArgument.chars:
-// return "chars";
-// case ExceptionArgument.charIndex:
-// return "charIndex";
-// case ExceptionArgument.charCount:
-// return "charCount";
-// case ExceptionArgument.s:
-// return "s";
-// case ExceptionArgument.input:
-// return "input";
-// case ExceptionArgument.ownedMemory:
-// return "ownedMemory";
-// case ExceptionArgument.list:
-// return "list";
-// case ExceptionArgument.index:
-// return "index";
-// case ExceptionArgument.capacity:
-// return "capacity";
-// case ExceptionArgument.collection:
-// return "collection";
-// case ExceptionArgument.item:
-// return "item";
-// case ExceptionArgument.converter:
-// return "converter";
-// case ExceptionArgument.match:
-// return "match";
-// case ExceptionArgument.count:
-// return "count";
-// case ExceptionArgument.action:
-// return "action";
-// case ExceptionArgument.comparison:
-// return "comparison";
-// case ExceptionArgument.exceptions:
-// return "exceptions";
-// case ExceptionArgument.exception:
-// return "exception";
-// case ExceptionArgument.pointer:
-// return "pointer";
-// case ExceptionArgument.start:
-// return "start";
-// case ExceptionArgument.format:
-// return "format";
-// case ExceptionArgument.formats:
-// return "formats";
-// case ExceptionArgument.culture:
-// return "culture";
-// case ExceptionArgument.comparer:
-// return "comparer";
-// case ExceptionArgument.comparable:
-// return "comparable";
-// case ExceptionArgument.source:
-// return "source";
-// case ExceptionArgument.state:
-// return "state";
-// case ExceptionArgument.length:
-// return "length";
-// case ExceptionArgument.comparisonType:
-// return "comparisonType";
-// case ExceptionArgument.manager:
-// return "manager";
-// case ExceptionArgument.sourceBytesToCopy:
-// return "sourceBytesToCopy";
-// case ExceptionArgument.callBack:
-// return "callBack";
-// case ExceptionArgument.creationOptions:
-// return "creationOptions";
-// case ExceptionArgument.function:
-// return "function";
-// case ExceptionArgument.scheduler:
-// return "scheduler";
-// case ExceptionArgument.continuationAction:
-// return "continuationAction";
-// case ExceptionArgument.continuationFunction:
-// return "continuationFunction";
-// case ExceptionArgument.tasks:
-// return "tasks";
-// case ExceptionArgument.asyncResult:
-// return "asyncResult";
-// case ExceptionArgument.beginMethod:
-// return "beginMethod";
-// case ExceptionArgument.endMethod:
-// return "endMethod";
-// case ExceptionArgument.endFunction:
-// return "endFunction";
-// case ExceptionArgument.cancellationToken:
-// return "cancellationToken";
-// case ExceptionArgument.continuationOptions:
-// return "continuationOptions";
-// case ExceptionArgument.delay:
-// return "delay";
-// case ExceptionArgument.millisecondsDelay:
-// return "millisecondsDelay";
-// case ExceptionArgument.millisecondsTimeout:
-// return "millisecondsTimeout";
-// case ExceptionArgument.stateMachine:
-// return "stateMachine";
-// case ExceptionArgument.timeout:
-// return "timeout";
-// case ExceptionArgument.type:
-// return "type";
-// case ExceptionArgument.sourceIndex:
-// return "sourceIndex";
-// case ExceptionArgument.sourceArray:
-// return "sourceArray";
-// case ExceptionArgument.destinationIndex:
-// return "destinationIndex";
-// case ExceptionArgument.destinationArray:
-// return "destinationArray";
-// case ExceptionArgument.pHandle:
-// return "pHandle";
-// case ExceptionArgument.handle:
-// return "handle";
-// case ExceptionArgument.other:
-// return "other";
-// case ExceptionArgument.newSize:
-// return "newSize";
-// case ExceptionArgument.lowerBounds:
-// return "lowerBounds";
-// case ExceptionArgument.lengths:
-// return "lengths";
-// case ExceptionArgument.len:
-// return "len";
-// case ExceptionArgument.keys:
-// return "keys";
-// case ExceptionArgument.indices:
-// return "indices";
-// case ExceptionArgument.index1:
-// return "index1";
-// case ExceptionArgument.index2:
-// return "index2";
-// case ExceptionArgument.index3:
-// return "index3";
-// case ExceptionArgument.length1:
-// return "length1";
-// case ExceptionArgument.length2:
-// return "length2";
-// case ExceptionArgument.length3:
-// return "length3";
-// case ExceptionArgument.endIndex:
-// return "endIndex";
-// case ExceptionArgument.elementType:
-// return "elementType";
-// case ExceptionArgument.arrayIndex:
-// return "arrayIndex";
-// case ExceptionArgument.year:
-// return "year";
-// case ExceptionArgument.codePoint:
-// return "codePoint";
-// case ExceptionArgument.str:
-// return "str";
-// case ExceptionArgument.options:
-// return "options";
-// case ExceptionArgument.prefix:
-// return "prefix";
-// case ExceptionArgument.suffix:
-// return "suffix";
-// case ExceptionArgument.buffer:
-// return "buffer";
-// case ExceptionArgument.buffers:
-// return "buffers";
-// case ExceptionArgument.offset:
-// return "offset";
-// case ExceptionArgument.stream:
-// return "stream";
-// default:
-// Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum.");
-// return "";
-// }
-// }
-
-//#if false // Reflection-based implementation does not work for CoreRT/ProjectN
-// // This function will convert an ExceptionResource enum value to the resource string.
-// [MethodImpl(MethodImplOptions.NoInlining)]
-// private static string GetResourceString(ExceptionResource resource)
-// {
-// Debug.Assert(Enum.IsDefined(typeof(ExceptionResource), resource),
-// "The enum value is not defined, please check the ExceptionResource Enum.");
-
-// return SR.GetResourceString(resource.ToString());
-// }
-//#endif
-
-// private static string GetResourceString(ExceptionResource resource)
-// {
-// switch (resource)
-// {
-// case ExceptionResource.ArgumentOutOfRange_Index:
-// return SR.ArgumentOutOfRange_Index;
-// case ExceptionResource.ArgumentOutOfRange_IndexCount:
-// return SR.ArgumentOutOfRange_IndexCount;
-// case ExceptionResource.ArgumentOutOfRange_IndexCountBuffer:
-// return SR.ArgumentOutOfRange_IndexCountBuffer;
-// case ExceptionResource.ArgumentOutOfRange_Count:
-// return SR.ArgumentOutOfRange_Count;
-// case ExceptionResource.ArgumentOutOfRange_Year:
-// return SR.ArgumentOutOfRange_Year;
-// case ExceptionResource.Arg_ArrayPlusOffTooSmall:
-// return SR.Arg_ArrayPlusOffTooSmall;
-// case ExceptionResource.NotSupported_ReadOnlyCollection:
-// return SR.NotSupported_ReadOnlyCollection;
-// case ExceptionResource.Arg_RankMultiDimNotSupported:
-// return SR.Arg_RankMultiDimNotSupported;
-// case ExceptionResource.Arg_NonZeroLowerBound:
-// return SR.Arg_NonZeroLowerBound;
-// case ExceptionResource.ArgumentOutOfRange_GetCharCountOverflow:
-// return SR.ArgumentOutOfRange_GetCharCountOverflow;
-// case ExceptionResource.ArgumentOutOfRange_ListInsert:
-// return SR.ArgumentOutOfRange_ListInsert;
-// case ExceptionResource.ArgumentOutOfRange_NeedNonNegNum:
-// return SR.ArgumentOutOfRange_NeedNonNegNum;
-// case ExceptionResource.ArgumentOutOfRange_SmallCapacity:
-// return SR.ArgumentOutOfRange_SmallCapacity;
-// case ExceptionResource.Argument_InvalidOffLen:
-// return SR.Argument_InvalidOffLen;
-// case ExceptionResource.Argument_CannotExtractScalar:
-// return SR.Argument_CannotExtractScalar;
-// case ExceptionResource.ArgumentOutOfRange_BiggerThanCollection:
-// return SR.ArgumentOutOfRange_BiggerThanCollection;
-// case ExceptionResource.Serialization_MissingKeys:
-// return SR.Serialization_MissingKeys;
-// case ExceptionResource.Serialization_NullKey:
-// return SR.Serialization_NullKey;
-// case ExceptionResource.NotSupported_KeyCollectionSet:
-// return SR.NotSupported_KeyCollectionSet;
-// case ExceptionResource.NotSupported_ValueCollectionSet:
-// return SR.NotSupported_ValueCollectionSet;
-// case ExceptionResource.InvalidOperation_NullArray:
-// return SR.InvalidOperation_NullArray;
-// case ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted:
-// return SR.TaskT_TransitionToFinal_AlreadyCompleted;
-// case ExceptionResource.TaskCompletionSourceT_TrySetException_NullException:
-// return SR.TaskCompletionSourceT_TrySetException_NullException;
-// case ExceptionResource.TaskCompletionSourceT_TrySetException_NoExceptions:
-// return SR.TaskCompletionSourceT_TrySetException_NoExceptions;
-// case ExceptionResource.NotSupported_StringComparison:
-// return SR.NotSupported_StringComparison;
-// case ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported:
-// return SR.ConcurrentCollection_SyncRoot_NotSupported;
-// case ExceptionResource.Task_MultiTaskContinuation_NullTask:
-// return SR.Task_MultiTaskContinuation_NullTask;
-// case ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple:
-// return SR.InvalidOperation_WrongAsyncResultOrEndCalledMultiple;
-// case ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList:
-// return SR.Task_MultiTaskContinuation_EmptyTaskList;
-// case ExceptionResource.Task_Start_TaskCompleted:
-// return SR.Task_Start_TaskCompleted;
-// case ExceptionResource.Task_Start_Promise:
-// return SR.Task_Start_Promise;
-// case ExceptionResource.Task_Start_ContinuationTask:
-// return SR.Task_Start_ContinuationTask;
-// case ExceptionResource.Task_Start_AlreadyStarted:
-// return SR.Task_Start_AlreadyStarted;
-// case ExceptionResource.Task_RunSynchronously_Continuation:
-// return SR.Task_RunSynchronously_Continuation;
-// case ExceptionResource.Task_RunSynchronously_Promise:
-// return SR.Task_RunSynchronously_Promise;
-// case ExceptionResource.Task_RunSynchronously_TaskCompleted:
-// return SR.Task_RunSynchronously_TaskCompleted;
-// case ExceptionResource.Task_RunSynchronously_AlreadyStarted:
-// return SR.Task_RunSynchronously_AlreadyStarted;
-// case ExceptionResource.AsyncMethodBuilder_InstanceNotInitialized:
-// return SR.AsyncMethodBuilder_InstanceNotInitialized;
-// case ExceptionResource.Task_ContinueWith_ESandLR:
-// return SR.Task_ContinueWith_ESandLR;
-// case ExceptionResource.Task_ContinueWith_NotOnAnything:
-// return SR.Task_ContinueWith_NotOnAnything;
-// case ExceptionResource.Task_InvalidTimerTimeSpan:
-// return SR.Task_InvalidTimerTimeSpan;
-// case ExceptionResource.Task_Delay_InvalidMillisecondsDelay:
-// return SR.Task_Delay_InvalidMillisecondsDelay;
-// case ExceptionResource.Task_Dispose_NotCompleted:
-// return SR.Task_Dispose_NotCompleted;
-// case ExceptionResource.Task_ThrowIfDisposed:
-// return SR.Task_ThrowIfDisposed;
-// case ExceptionResource.Task_WaitMulti_NullTask:
-// return SR.Task_WaitMulti_NullTask;
-// case ExceptionResource.ArgumentException_OtherNotArrayOfCorrectLength:
-// return SR.ArgumentException_OtherNotArrayOfCorrectLength;
-// case ExceptionResource.ArgumentNull_Array:
-// return SR.ArgumentNull_Array;
-// case ExceptionResource.ArgumentNull_SafeHandle:
-// return SR.ArgumentNull_SafeHandle;
-// case ExceptionResource.ArgumentOutOfRange_EndIndexStartIndex:
-// return SR.ArgumentOutOfRange_EndIndexStartIndex;
-// case ExceptionResource.ArgumentOutOfRange_Enum:
-// return SR.ArgumentOutOfRange_Enum;
-// case ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported:
-// return SR.ArgumentOutOfRange_HugeArrayNotSupported;
-// case ExceptionResource.Argument_AddingDuplicate:
-// return SR.Argument_AddingDuplicate;
-// case ExceptionResource.Argument_InvalidArgumentForComparison:
-// return SR.Argument_InvalidArgumentForComparison;
-// case ExceptionResource.Arg_LowerBoundsMustMatch:
-// return SR.Arg_LowerBoundsMustMatch;
-// case ExceptionResource.Arg_MustBeType:
-// return SR.Arg_MustBeType;
-// case ExceptionResource.Arg_Need1DArray:
-// return SR.Arg_Need1DArray;
-// case ExceptionResource.Arg_Need2DArray:
-// return SR.Arg_Need2DArray;
-// case ExceptionResource.Arg_Need3DArray:
-// return SR.Arg_Need3DArray;
-// case ExceptionResource.Arg_NeedAtLeast1Rank:
-// return SR.Arg_NeedAtLeast1Rank;
-// case ExceptionResource.Arg_RankIndices:
-// return SR.Arg_RankIndices;
-// case ExceptionResource.Arg_RanksAndBounds:
-// return SR.Arg_RanksAndBounds;
-// case ExceptionResource.InvalidOperation_IComparerFailed:
-// return SR.InvalidOperation_IComparerFailed;
-// case ExceptionResource.NotSupported_FixedSizeCollection:
-// return SR.NotSupported_FixedSizeCollection;
-// case ExceptionResource.Rank_MultiDimNotSupported:
-// return SR.Rank_MultiDimNotSupported;
-// case ExceptionResource.Arg_TypeNotSupported:
-// return SR.Arg_TypeNotSupported;
-// case ExceptionResource.Argument_SpansMustHaveSameLength:
-// return SR.Argument_SpansMustHaveSameLength;
-// case ExceptionResource.Argument_InvalidFlag:
-// return SR.Argument_InvalidFlag;
-// case ExceptionResource.CancellationTokenSource_Disposed:
-// return SR.CancellationTokenSource_Disposed;
-// case ExceptionResource.Argument_AlignmentMustBePow2:
-// return SR.Argument_AlignmentMustBePow2;
-// default:
-// Debug.Fail("The enum value is not defined, please check the ExceptionResource Enum.");
-// return "";
-// }
-// }
-// }
-
-// //
-// // The convention for this enum is using the argument name as the enum name
-// //
-// internal enum ExceptionArgument
-// {
-// obj,
-// dictionary,
-// array,
-// info,
-// key,
-// text,
-// values,
-// value,
-// startIndex,
-// task,
-// bytes,
-// byteIndex,
-// byteCount,
-// ch,
-// chars,
-// charIndex,
-// charCount,
-// s,
-// input,
-// ownedMemory,
-// list,
-// index,
-// capacity,
-// collection,
-// item,
-// converter,
-// match,
-// count,
-// action,
-// comparison,
-// exceptions,
-// exception,
-// pointer,
-// start,
-// format,
-// formats,
-// culture,
-// comparer,
-// comparable,
-// source,
-// state,
-// length,
-// comparisonType,
-// manager,
-// sourceBytesToCopy,
-// callBack,
-// creationOptions,
-// function,
-// scheduler,
-// continuationAction,
-// continuationFunction,
-// tasks,
-// asyncResult,
-// beginMethod,
-// endMethod,
-// endFunction,
-// cancellationToken,
-// continuationOptions,
-// delay,
-// millisecondsDelay,
-// millisecondsTimeout,
-// stateMachine,
-// timeout,
-// type,
-// sourceIndex,
-// sourceArray,
-// destinationIndex,
-// destinationArray,
-// pHandle,
-// handle,
-// other,
-// newSize,
-// lowerBounds,
-// lengths,
-// len,
-// keys,
-// indices,
-// index1,
-// index2,
-// index3,
-// length1,
-// length2,
-// length3,
-// endIndex,
-// elementType,
-// arrayIndex,
-// year,
-// codePoint,
-// str,
-// options,
-// prefix,
-// suffix,
-// buffer,
-// buffers,
-// offset,
-// stream
-// }
-
-// //
-// // The convention for this enum is using the resource name as the enum name
-// //
-// internal enum ExceptionResource
-// {
-// ArgumentOutOfRange_Index,
-// ArgumentOutOfRange_IndexCount,
-// ArgumentOutOfRange_IndexCountBuffer,
-// ArgumentOutOfRange_Count,
-// ArgumentOutOfRange_Year,
-// Arg_ArrayPlusOffTooSmall,
-// NotSupported_ReadOnlyCollection,
-// Arg_RankMultiDimNotSupported,
-// Arg_NonZeroLowerBound,
-// ArgumentOutOfRange_GetCharCountOverflow,
-// ArgumentOutOfRange_ListInsert,
-// ArgumentOutOfRange_NeedNonNegNum,
-// ArgumentOutOfRange_SmallCapacity,
-// Argument_InvalidOffLen,
-// Argument_CannotExtractScalar,
-// ArgumentOutOfRange_BiggerThanCollection,
-// Serialization_MissingKeys,
-// Serialization_NullKey,
-// NotSupported_KeyCollectionSet,
-// NotSupported_ValueCollectionSet,
-// InvalidOperation_NullArray,
-// TaskT_TransitionToFinal_AlreadyCompleted,
-// TaskCompletionSourceT_TrySetException_NullException,
-// TaskCompletionSourceT_TrySetException_NoExceptions,
-// NotSupported_StringComparison,
-// ConcurrentCollection_SyncRoot_NotSupported,
-// Task_MultiTaskContinuation_NullTask,
-// InvalidOperation_WrongAsyncResultOrEndCalledMultiple,
-// Task_MultiTaskContinuation_EmptyTaskList,
-// Task_Start_TaskCompleted,
-// Task_Start_Promise,
-// Task_Start_ContinuationTask,
-// Task_Start_AlreadyStarted,
-// Task_RunSynchronously_Continuation,
-// Task_RunSynchronously_Promise,
-// Task_RunSynchronously_TaskCompleted,
-// Task_RunSynchronously_AlreadyStarted,
-// AsyncMethodBuilder_InstanceNotInitialized,
-// Task_ContinueWith_ESandLR,
-// Task_ContinueWith_NotOnAnything,
-// Task_InvalidTimerTimeSpan,
-// Task_Delay_InvalidMillisecondsDelay,
-// Task_Dispose_NotCompleted,
-// Task_ThrowIfDisposed,
-// Task_WaitMulti_NullTask,
-// ArgumentException_OtherNotArrayOfCorrectLength,
-// ArgumentNull_Array,
-// ArgumentNull_SafeHandle,
-// ArgumentOutOfRange_EndIndexStartIndex,
-// ArgumentOutOfRange_Enum,
-// ArgumentOutOfRange_HugeArrayNotSupported,
-// Argument_AddingDuplicate,
-// Argument_InvalidArgumentForComparison,
-// Arg_LowerBoundsMustMatch,
-// Arg_MustBeType,
-// Arg_Need1DArray,
-// Arg_Need2DArray,
-// Arg_Need3DArray,
-// Arg_NeedAtLeast1Rank,
-// Arg_RankIndices,
-// Arg_RanksAndBounds,
-// InvalidOperation_IComparerFailed,
-// NotSupported_FixedSizeCollection,
-// Rank_MultiDimNotSupported,
-// Arg_TypeNotSupported,
-// Argument_SpansMustHaveSameLength,
-// Argument_InvalidFlag,
-// CancellationTokenSource_Disposed,
-// Argument_AlignmentMustBePow2,
-// }
-//}
\ No newline at end of file
diff --git a/app/XDM/FFmpegCustomBuild/ReadME.txt b/app/XDM/FFmpegCustomBuild/ReadME.txt
new file mode 100644
index 0000000..ba861bb
--- /dev/null
+++ b/app/XDM/FFmpegCustomBuild/ReadME.txt
@@ -0,0 +1,2 @@
+Clone https://github.com/m-ab-s/media-autobuild_suite
+Put ffmpeg_options.txt inside build folder
\ No newline at end of file
diff --git a/app/XDM/FFmpegCustomBuild/ffmpeg_options.txt b/app/XDM/FFmpegCustomBuild/ffmpeg_options.txt
new file mode 100644
index 0000000..3b42bb3
--- /dev/null
+++ b/app/XDM/FFmpegCustomBuild/ffmpeg_options.txt
@@ -0,0 +1,16 @@
+# Lines starting with this character are ignored
+# To override some options specifically for the shared build, create a ffmpeg_options_shared.txt file.
+
+# Basic built-in options, can be removed if you delete "--disable-autodetect"
+--disable-everything
+--disable-network
+--disable-autodetect
+--enable-small
+--enable-demuxer=mov,mp4,m4a,3gp,3g2,mj2,matroska,webm,mpegts
+--enable-libmp3lame
+--enable-encoder=libmp3lame
+--enable-muxer=mp4,matroska,mpegts,mp3
+--enable-protocol=file,srt,concat
+--enable-bsfs
+--enable-filter=acopy,concat,copy
+--enable-decoder=vorbis,opus,aac,ac3
diff --git a/app/XDM/HttpServer/HttpServer.csproj b/app/XDM/HttpServer/HttpServer.csproj
deleted file mode 100644
index 965af94..0000000
--- a/app/XDM/HttpServer/HttpServer.csproj
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2;net5.0
- 9.0
- enable
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/XDM/Interop.WinHttp/Interop.WinHttp.csproj b/app/XDM/Interop.WinHttp/Interop.WinHttp.csproj
deleted file mode 100644
index 3f552f2..0000000
--- a/app/XDM/Interop.WinHttp/Interop.WinHttp.csproj
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2;net5.0
- 9.0
- enable
-
-
-
diff --git a/app/XDM/Interop.WinHttp/Interop.winhttp.cs b/app/XDM/Interop.WinHttp/Interop.winhttp.cs
deleted file mode 100644
index 335271f..0000000
--- a/app/XDM/Interop.WinHttp/Interop.winhttp.cs
+++ /dev/null
@@ -1,208 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Runtime.InteropServices;
-using System.Text;
-
- Interop
-{
- class Libraries
- {
- public const string WinHttp = "winhttp.dll";
- }
- internal static partial class WinHttp
- {
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern SafeWinHttpHandle WinHttpOpen(
- IntPtr userAgent,
- uint accessType,
- string? proxyName,
- string? proxyBypass, int flags);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpCloseHandle(
- IntPtr handle);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern SafeWinHttpHandle WinHttpConnect(
- SafeWinHttpHandle sessionHandle,
- string serverName,
- ushort serverPort,
- uint reserved);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern SafeWinHttpHandle WinHttpOpenRequest(
- SafeWinHttpHandle connectHandle,
- string verb,
- string objectName,
- string? version,
- string referrer,
- string acceptTypes,
- uint flags);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpAddRequestHeaders(
- SafeWinHttpHandle requestHandle,
-#pragma warning disable CA1838 // Uses pooled StringBuilder
- [In] StringBuilder headers,
-#pragma warning restore CA1838
- uint headersLength,
- uint modifiers);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpAddRequestHeaders(
- SafeWinHttpHandle requestHandle,
- string headers,
- uint headersLength,
- uint modifiers);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpSendRequest(
- SafeWinHttpHandle requestHandle,
- IntPtr headers,
- uint headersLength,
- IntPtr optional,
- uint optionalLength,
- uint totalLength,
- IntPtr context);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpReceiveResponse(
- SafeWinHttpHandle requestHandle,
- IntPtr reserved);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryDataAvailable(
- SafeWinHttpHandle requestHandle,
- IntPtr parameterIgnoredAndShouldBeNullForAsync);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpReadData(
- SafeWinHttpHandle requestHandle,
- IntPtr buffer,
- uint bufferSize,
- IntPtr parameterIgnoredAndShouldBeNullForAsync);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryHeaders(
- SafeWinHttpHandle requestHandle,
- uint infoLevel,
- string name,
- IntPtr buffer,
- ref uint bufferLength,
- ref uint index);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryHeaders(
- SafeWinHttpHandle requestHandle,
- uint infoLevel,
- string name,
- ref uint number,
- ref uint bufferLength,
- IntPtr index);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryOption(
- SafeWinHttpHandle handle,
- uint option,
- ref IntPtr buffer,
- ref uint bufferSize);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryOption(
- SafeWinHttpHandle handle,
- uint option,
- IntPtr buffer,
- ref uint bufferSize);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryOption(
- SafeWinHttpHandle handle,
- uint option,
- ref uint buffer,
- ref uint bufferSize);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpWriteData(
- SafeWinHttpHandle requestHandle,
- IntPtr buffer,
- uint bufferSize,
- IntPtr parameterIgnoredAndShouldBeNullForAsync);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpSetOption(
- SafeWinHttpHandle handle,
- uint option,
- ref uint optionData,
- uint optionLength = sizeof(uint));
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpSetOption(
- SafeWinHttpHandle handle,
- uint option,
- IntPtr optionData,
- uint optionLength);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpSetCredentials(
- SafeWinHttpHandle requestHandle,
- uint authTargets,
- uint authScheme,
- string? userName,
- string? password,
- IntPtr reserved);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpQueryAuthSchemes(
- SafeWinHttpHandle requestHandle,
- out uint supportedSchemes,
- out uint firstScheme,
- out uint authTarget);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpSetTimeouts(
- SafeWinHttpHandle handle,
- int resolveTimeout,
- int connectTimeout,
- int sendTimeout,
- int receiveTimeout);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpGetIEProxyConfigForCurrentUser(
- out WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool WinHttpGetProxyForUrl(
- SafeWinHttpHandle? sessionHandle, string url,
- ref WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions,
- out WINHTTP_PROXY_INFO proxyInfo);
-
- [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)]
- public static extern IntPtr WinHttpSetStatusCallback(
- SafeWinHttpHandle handle,
- WINHTTP_STATUS_CALLBACK callback,
- uint notificationFlags,
- IntPtr reserved);
- }
-}
diff --git a/app/XDM/Lang/Arabic (العربية).txt b/app/XDM/Lang/Arabic.txt
similarity index 100%
rename from app/XDM/Lang/Arabic (العربية).txt
rename to app/XDM/Lang/Arabic.txt
diff --git a/app/XDM/Lang/Chinese Traditional (繁體中文).txt b/app/XDM/Lang/Chinese Traditional.txt
similarity index 100%
rename from app/XDM/Lang/Chinese Traditional (繁體中文).txt
rename to app/XDM/Lang/Chinese Traditional.txt
diff --git a/app/XDM/Lang/Chinese simplified (简体中文).txt b/app/XDM/Lang/Chinese simplified.txt
similarity index 100%
rename from app/XDM/Lang/Chinese simplified (简体中文).txt
rename to app/XDM/Lang/Chinese simplified.txt
diff --git a/app/XDM/Lang/English.txt b/app/XDM/Lang/English.txt
index 96caa40..7ab9b9a 100644
--- a/app/XDM/Lang/English.txt
+++ b/app/XDM/Lang/English.txt
@@ -53,7 +53,7 @@ ND_ADDRESS=Address
ND_FILE=File
LBL_SAVE_IN=Save in
ND_IGNORE_URL=Do not capture download from this address
-ND_MORE=MORE...
+ND_MORE=More...
ND_DOWNLOAD_LATER=Download Later
ND_DOWNLOAD_NOW=Download Now
ND_AUTO_CAT=Automatically select based on file type
@@ -84,8 +84,8 @@ MSG_DOWNLOAD_FFMPEG=Download FFmpeg?
LBL_QUEUE_OPT3=Do not use queue
VID_PASTE_URL=Please paste video URL link here
SETTINGS_ADV=Advanced settings
-VID_CHK=Check/Uncheck All
-O_VID_FMT=Formats
+VID_CHK=Select all
+O_VID_FMT=Format
BAT_PATTERN=Pattern
BAT_LINKS=Links
BAT_SELECT_ITEMS=Select items to download
@@ -126,8 +126,8 @@ SETTINGS_GENERAL=General settings
SETTINGS_NETWORK=Network settings
SETTINGS_CRED=Password manager
SETTINGS_ADV=Advanced settings
-DESC_MONITORING_1=Please select browsers to monitor and make sure, browser addon is installed and enabled in respective browsers
-DESC_OTHER_BROWSERS=XDM can also be integrated into other Chromium based browser (SRWare Iron etc) or Mozilla based (Icewasel, Waterfox etc) browsers using below links
+DESC_MONITORING_1=Please make sure XDM extension is installed in your browser. To install the browser extension, please click on the buttons below or copy paste the link directly in the browser
+DESC_OTHER_BROWSERS=XDM can also be integrated into other Chromium based browser (Vivaldi, Brave browser etc) or Mozilla based (Icewasel, Waterfox etc) browsers using below links
DESC_CHROME=Chromium based browsers
DESC_MOZ=Firefox based browsers
DESC_FILETYPES=XDM will automatically take over downloads from browser for below file types
@@ -152,7 +152,7 @@ SETTINGS_FOLDER=Default download folder
SETTINGS_DARK_THEME=Use dark theme if possible (Require app restart)
SETTINGS_CAT_ADD=Add
SETTINGS_CAT_EDIT=Edit
-DESC_NET1=Connection timeout
+DESC_NET1=Connection timeout in seconds
DESC_NET2=Segments per download
NET_MAX_RETRY=Maximum retry limit
NET_SYSTEM_PROXY=Use system proxy settings
@@ -189,4 +189,31 @@ MSG_NO_UPDATE=No updates available/already upto date
MSG_UPDATED=Update successfull
MSG_ALREADY_RUNNING=An old version of XDM is already running
MSG_BROWSER_LAUNCH_FAILED=Unable to launch
-MSG_NATIVE_HOST_FAILED=Error installing native host
\ No newline at end of file
+MSG_NATIVE_HOST_FAILED=Error installing native host
+MSG_DONT_SHOW_AGAIN=Don't show this again
+MSG_NO_USERNAME=User name required
+MSG_REF_LINK_MSG=New download link is accepted
+MSG_CATEGORY=Category
+MSG_CAT_NAME_MISSING=Category name required
+MSG_CAT_FILE_TYPES_MISSING=File types required
+MSG_CAT_FOLDER_MISSING=Download folder required
+MSG_HOST_NAME_MISSING=Host name required
+MSG_QUALITY=Quality
+MSG_MP3=Mp3 Audio
+MSG_TIME=Time
+STAT_ASSEMBLING=Assembling
+STAT_WAITING=Waiting
+MSG_UPDATE_AVAILABLE=Update(s) available
+MSG_RESTORE=Restore Window
+MSG_DOUBLE_CLICK_ACTION=Double click on download item
+MSG_OPEN_FILE=Open file
+MSG_FALLBACK_UA=User agent to be used if download is added manually
+MSG_SAVE_AS_MP3=Save as MP3
+MSG_VID_WIKI_TEXT=If you are interested in downloading streaming video from the browser using XDM
+MSG_VID_WIKI_LINK=Please click here
+NO_REFRESH_LINK=Link refresh is not available for this download
+MSG_NO_VIDEO=No video found. However there might be other ways to download the video. Please click "Learn More" button for details.
+MSG_VIDEO_DOWNLOAD_HELP=Learn More
+MSG_READ_BROWSER_COOKIE=Read cookies from browser
+MSG_SELECT_FOLDER=Select
+MSG_IMPORT_DONE=Import complete
\ No newline at end of file
diff --git a/app/XDM/Lang/Farsi - Persian (فارسی).txt b/app/XDM/Lang/Farsi-Persian.txt
similarity index 100%
rename from app/XDM/Lang/Farsi - Persian (فارسی).txt
rename to app/XDM/Lang/Farsi-Persian.txt
diff --git a/app/XDM/Lang/French(Français).txt b/app/XDM/Lang/French.txt
similarity index 100%
rename from app/XDM/Lang/French(Français).txt
rename to app/XDM/Lang/French.txt
diff --git a/app/XDM/Lang/German(Deutsch).txt b/app/XDM/Lang/German.txt
similarity index 100%
rename from app/XDM/Lang/German(Deutsch).txt
rename to app/XDM/Lang/German.txt
diff --git a/app/XDM/Lang/Indonesian (Bahasa Indonesia).txt b/app/XDM/Lang/Indonesian.txt
similarity index 100%
rename from app/XDM/Lang/Indonesian (Bahasa Indonesia).txt
rename to app/XDM/Lang/Indonesian.txt
diff --git a/app/XDM/Lang/Korea (한국어).txt b/app/XDM/Lang/Korea.txt
similarity index 100%
rename from app/XDM/Lang/Korea (한국어).txt
rename to app/XDM/Lang/Korea.txt
diff --git a/app/XDM/Lang/Portuguese Brazil (Português (Brasil)).txt b/app/XDM/Lang/Portuguese Brazil.txt
similarity index 100%
rename from app/XDM/Lang/Portuguese Brazil (Português (Brasil)).txt
rename to app/XDM/Lang/Portuguese Brazil.txt
diff --git a/app/XDM/Lang/Romanian (ROMÂNĂ).txt b/app/XDM/Lang/Romanian.txt
similarity index 100%
rename from app/XDM/Lang/Romanian (ROMÂNĂ).txt
rename to app/XDM/Lang/Romanian.txt
diff --git a/app/XDM/Lang/Russian(Rусский).txt b/app/XDM/Lang/Russian.txt
similarity index 100%
rename from app/XDM/Lang/Russian(Rусский).txt
rename to app/XDM/Lang/Russian.txt
diff --git a/app/XDM/Lang/Serbian - Latin (Srpski (latinica)).txt b/app/XDM/Lang/Serbian - Latin.txt
similarity index 100%
rename from app/XDM/Lang/Serbian - Latin (Srpski (latinica)).txt
rename to app/XDM/Lang/Serbian - Latin.txt
diff --git a/app/XDM/Lang/Serbian Cyrillic (Српски (ћирилица)).txt b/app/XDM/Lang/Serbian Cyrillic.txt
similarity index 100%
rename from app/XDM/Lang/Serbian Cyrillic (Српски (ћирилица)).txt
rename to app/XDM/Lang/Serbian Cyrillic.txt
diff --git a/app/XDM/Lang/Spanish (Español).txt b/app/XDM/Lang/Spanish.txt
similarity index 100%
rename from app/XDM/Lang/Spanish (Español).txt
rename to app/XDM/Lang/Spanish.txt
diff --git a/app/XDM/Lang/Traditional Chinese - Taiwan (繁體中文(台灣)).txt b/app/XDM/Lang/Traditional Chinese - Taiwan.txt
similarity index 100%
rename from app/XDM/Lang/Traditional Chinese - Taiwan (繁體中文(台灣)).txt
rename to app/XDM/Lang/Traditional Chinese - Taiwan.txt
diff --git a/app/XDM/Lang/Turkish(Türkçe).txt b/app/XDM/Lang/Turkish.txt
similarity index 100%
rename from app/XDM/Lang/Turkish(Türkçe).txt
rename to app/XDM/Lang/Turkish.txt
diff --git a/app/XDM/Lang/Ukrainian(Українська).txt b/app/XDM/Lang/Ukrainian.txt
similarity index 100%
rename from app/XDM/Lang/Ukrainian(Українська).txt
rename to app/XDM/Lang/Ukrainian.txt
diff --git a/app/XDM/Lang/index.txt b/app/XDM/Lang/index.txt
new file mode 100644
index 0000000..3b84fec
--- /dev/null
+++ b/app/XDM/Lang/index.txt
@@ -0,0 +1,25 @@
+English=English.txt
+Arabic (العربية)=Arabic.txt
+Chinese simplified (简体中文)=Chinese simplified.txt
+Chinese Traditional (繁體中文)=Chinese Traditional.txt
+Czech=Czech.txt
+Farsi - Persian (فارسی)=Farsi-Persian.txt
+French(Français)=French.txt
+German(Deutsch)=German.txt
+Hungarian=Hungarian.txt
+Indonesian (Bahasa Indonesia)=Indonesian.txt
+Italian=Italian.txt
+Korea (한국어)=Korea.txt
+Malayalam=Malayalam.txt
+Nepali=Nepali.txt
+Polish=Polish.txt
+Portuguese Brazil (Português (Brasil))=Portuguese Brazil.txt
+Romanian (ROMÂNĂ)=Romanian.txt
+Russian(Rусский)=Russian.txt
+Serbian - Latin (Srpski (latinica))=Serbian - Latin.txt
+Serbian Cyrillic (Српски (ћирилица))=Serbian Cyrillic.txt
+Spanish (Español)=Spanish.txt
+Traditional Chinese - Taiwan (繁體中文(台灣))=Traditional Chinese - Taiwan.txt
+Turkish(Türkçe)=Turkish.txt
+Ukrainian(Українська)=Ukrainian.txt
+Vietnamese=Vietnamese.txt
\ No newline at end of file
diff --git a/app/XDM/MediaParser.Hls/MediaParser.csproj b/app/XDM/MediaParser.Hls/MediaParser.csproj
deleted file mode 100644
index 4b49013..0000000
--- a/app/XDM/MediaParser.Hls/MediaParser.csproj
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2;net5.0
- AnyCPU;x86
- 9.0
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 4.5.0
-
-
-
-
-
- 4.5.0
-
-
-
-
-
- 4.5.0
-
-
-
-
diff --git a/app/XDM/MockServer/MockServer.csproj b/app/XDM/MockServer/MockServer.csproj
index 913bf3e..74d6759 100644
--- a/app/XDM/MockServer/MockServer.csproj
+++ b/app/XDM/MockServer/MockServer.csproj
@@ -1,12 +1,17 @@
- net5.0;net4.5.2
- AnyCPU;x86
+ net5.0;
+ AnyCPU;x86;x64
9.0
enable
+
+ none
+ false
+
+
@@ -14,8 +19,4 @@
-
-
-
-
diff --git a/app/XDM/NativeMessagingHost/BlockingCollection.cs b/app/XDM/NativeMessagingHost/BlockingCollection.cs
new file mode 100644
index 0000000..127fe16
--- /dev/null
+++ b/app/XDM/NativeMessagingHost/BlockingCollection.cs
@@ -0,0 +1,39 @@
+#if NET35
+
+using System.Collections.Generic;
+using System.Threading;
+
+namespace NetFX.Polyfill2
+{
+ public class BlockingCollection
+ {
+ private object _queueLock = new();
+ private Queue _queue = new();
+ private AutoResetEvent _objectAvailableEvent = new(false);
+
+ public T Take()
+ {
+ lock (_queueLock)
+ {
+ if (_queue.Count > 0)
+ return _queue.Dequeue();
+ }
+
+ _objectAvailableEvent.WaitOne();
+
+ return Take();
+ }
+
+ public void Add(T obj)
+ {
+ lock (_queueLock)
+ {
+ _queue.Enqueue(obj);
+ }
+
+ _objectAvailableEvent.Set();
+ }
+ }
+}
+
+#endif
diff --git a/app/XDM/NativeMessagingHost/NativeMessagingHost.csproj b/app/XDM/NativeMessagingHost/NativeMessagingHost.csproj
index 1d79512..870fce2 100644
--- a/app/XDM/NativeMessagingHost/NativeMessagingHost.csproj
+++ b/app/XDM/NativeMessagingHost/NativeMessagingHost.csproj
@@ -2,30 +2,27 @@
Exe
- net3.5;net4.5;net4.7.2;net5.0
+ net3.5;net4.7.2;net6.0
true
9.0
- AnyCPU;x86
-
+
+
-
+
-
-
-
-
-
-
+
App.PostDotNet4.config
@@ -33,4 +30,11 @@
App.PreDotNet4.config
+
+ none
+ false
+
+
+
+
diff --git a/app/XDM/NativeMessagingHost/NativeMessagingHostApp.cs b/app/XDM/NativeMessagingHost/NativeMessagingHostApp.cs
index ae8d27c..e130bf3 100644
--- a/app/XDM/NativeMessagingHost/NativeMessagingHostApp.cs
+++ b/app/XDM/NativeMessagingHost/NativeMessagingHostApp.cs
@@ -6,11 +6,11 @@ using System.Text;
using System.Threading;
using System.Diagnostics;
using Newtonsoft.Json;
-using BrowserMonitoring;
using Newtonsoft.Json.Serialization;
+using BrowserMonitoring;
#if NET35
-using NetFX.Polyfill;
+using NetFX.Polyfill2;
#else
using System.Collections.Concurrent;
#endif
@@ -19,44 +19,66 @@ namespace NativeHost
{
public class NativeMessagingHostApp
{
+ static bool isFirefox = true;
static BlockingCollection receivedBrowserMessages = new();
static BlockingCollection queuedBrowserMessages = new();
static CamelCasePropertyNamesContractResolver cr = new();
- static StreamWriter log = new StreamWriter(new FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "native-host.log"), FileMode.Create));
+ //static StreamWriter log = new StreamWriter(new FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "native-host.log"), FileMode.Create));
static void Main(string[] args)
{
- //var json = BinaryToJson(new byte[0]);
+ try
+ {
+ var debugMode = Environment.GetEnvironmentVariable("XDM_DEBUG_MODE");
+ if (!string.IsNullOrEmpty(debugMode) && debugMode == "1")
+ {
+ var logFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "messaging-log.txt");
+ Trace.Listeners.Add(new TextWriterTraceListener(logFile, "myListener"));
+ Trace.AutoFlush = true;
+ }
+ Debug("Application_Startup");
+ if (args.Length > 0 && args[0].StartsWith("chrome-extension:"))
+ {
+ isFirefox = false;
+ }
+ }
+ catch { }
+ Debug("Process running from: " + AppDomain.CurrentDomain.BaseDirectory);
#if !NET35
- Debug(Environment.Is64BitProcess+"");
+ Debug("Is64BitProcess: " + Environment.Is64BitProcess);
#endif
try
{
- Debug("Trying to open mutex");
- using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
- Debug("Mutex opened");
- }
- catch
- {
- Debug("Mutex open failed, spawn xdm process...++");
- CreateXDMInstance();
- }
- Debug("next");
- try
- {
-
-
var inputReader = Console.OpenStandardInput();
var outputWriter = Console.OpenStandardOutput();
+
+ //var msg = ReadMessageBytes(inputReader);
+ //var message = Encoding.UTF8.GetString(msg);
+ //Debug(message);
+ try
+ {
+ Debug("Trying to open mutex");
+ using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
+ Debug("Mutex opened");
+ }
+ catch
+ {
+ Debug("Mutex open failed, spawn xdm process...++");
+ CreateXDMInstance();
+ }
+
var t1 = new Thread(() =>
{
+ Debug("t1 reading messages from stdin sent by browser: ");
try
{
while (true)
{
//read from process stdin and write to blocking queue,
//they will be sent to xdm once pipe handshake complets
- var msg = ReadMessageBytes(inputReader);
- Debug(Encoding.UTF8.GetString(msg));
+ Debug("Waiting for message - stdin...");
+ var msg = NativeMessageSerializer.ReadMessageBytes(inputReader, false);
+ Debug("Reading message from stdin - size: " + msg.Length);
+ Debug("Stdin - " + Encoding.UTF8.GetString(msg));
receivedBrowserMessages.Add(JsonToBinary(msg));
}
}
@@ -77,10 +99,12 @@ namespace NativeHost
{
//read from blocking queue and write to stdout,
//these messages were queued by xdm
- var msg = queuedBrowserMessages.Take();//doesn't make much sense to it async
+ var msg = queuedBrowserMessages.Take();
+ Debug("Sending to browser: " + Encoding.UTF8.GetString(msg));
var json = BinaryToJson(msg);
+ Debug("Sending to browser: ");
Debug(Encoding.UTF8.GetString(json));
- WriteMessage(outputWriter, json);
+ NativeMessageSerializer.WriteMessage(outputWriter, json, false);
}
}
catch (Exception exx)
@@ -101,21 +125,38 @@ namespace NativeHost
}
}
- private static void CreateXDMInstance()
+ private static void CreateXDMInstance(bool minimized = true)
{
try
{
- Debug("XDM instance creating...1");
- ProcessStartInfo psi = new()
+ var file = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ".."),
+ Environment.OSVersion.Platform == PlatformID.Win32NT ? "xdm-app.exe" : "xdm-app");
+ Debug("XDM instance creating...1 " + file);
+ if (isFirefox && Environment.OSVersion.Platform == PlatformID.Win32NT)
{
- FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "XDM.WinForm.UI.exe"),
- UseShellExecute = true,
- Arguments = "-m"
- };
+ var args = minimized ? " -m" : "";
+ if (!NativeProcess.Win32CreateProcess(file, $"\"{file}\"{args}"))
+ {
+ Debug("Win32 create process failed!");
+ }
+ }
+ else
+ {
+ ProcessStartInfo psi = new()
+ {
+ FileName = file,
+ UseShellExecute = true
+ };
- Debug("XDM instance creating...");
- Process.Start(psi);
- Debug("XDM instance created");
+ if (minimized)
+ {
+ psi.Arguments = "-m";
+ }
+
+ Debug("XDM instance creating...");
+ Process.Start(psi);
+ Debug("XDM instance created");
+ }
}
catch (Exception ex)
{
@@ -125,56 +166,58 @@ namespace NativeHost
private static void ProcessMessages()
{
- Debug("Log start");
+ Debug("start");
try
{
- NamedPipeServerStream inPipe = null;
- NamedPipeClientStream outPipe = null;
- while (true)
+ //NamedPipeServerStream inPipe = null;
+ NamedPipeClientStream pipe = null;
+ // while (true)
{
try
{
- var pipeName = Guid.NewGuid().ToString();
- inPipe = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
+ //var pipeName = Guid.NewGuid().ToString();
+ //inPipe = new NamedPipeServerStream(pipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
//start handshake with XDM
- outPipe = new NamedPipeClientStream(".", "XDM_Ipc_Browser_Monitoring_Pipe", PipeDirection.Out);
+ pipe = new NamedPipeClientStream(".", "XDM_Ipc_Browser_Monitoring_Pipe", PipeDirection.InOut, PipeOptions.Asynchronous);
Debug("start handshake with XDM");
- outPipe.Connect();
- WriteMessage(outPipe, pipeName);
- Debug("pipename: " + pipeName);
+ pipe.Connect();
+ //NativeMessageSerializer.WriteMessage(outPipe, pipeName);
+ //Debug("pipename: " + pipeName);
- inPipe.WaitForConnection();
- var syncMsgBytes = ReadMessageBytes(inPipe);
- Debug("No task message size: " + syncMsgBytes.Length);
+ //inPipe.WaitForConnection();
+ //var syncMsgBytes = NativeMessageSerializer.ReadMessageBytes(inPipe);
+ //Debug("No task message size: " + syncMsgBytes.Length);
- queuedBrowserMessages.Add(syncMsgBytes);
+ //queuedBrowserMessages.Add(syncMsgBytes);
//handshake with XDM is complete
Debug("handshake with XDM is complete");
using var waitHandle = new ManualResetEvent(false);
- //queue messages from xdm pipe for browser
+ //Direction: XDM ---> NativeHost
+ //Read messages from XDM's named pipe and add them to queuedBrowserMessages
var task1 = new Thread(() =>
{
try
{
while (true)
{
- var syncMsgBytes = ReadMessageBytes(inPipe);
- //Debug("Task1 message size: " + syncMsgBytes.Length);
+ var syncMsgBytes = NativeMessageSerializer.ReadMessageBytes(pipe);
+ Debug("Message received from XDM of size: " + syncMsgBytes.Length);
if (syncMsgBytes.Length == 0)
{
break;
}
+ Debug("Message from XDM: " + Encoding.UTF8.GetString(syncMsgBytes));
queuedBrowserMessages.Add(syncMsgBytes);
}
}
catch (Exception ex)
{
- Debug(ex.ToString());
+ Debug(ex.ToString(), ex);
queuedBrowserMessages.Add(Encoding.UTF8.GetBytes("{\"appExited\":\"true\"}"));
}
waitHandle.Set();
@@ -182,7 +225,8 @@ namespace NativeHost
}
);
- //queue messages to xdm pipe from browser
+ //Direction: NativeHost ---> XDM
+ //Take messages from receivedBrowserMessages and write them to XDM's named pipe
var task2 = new Thread(() =>
{
try
@@ -190,7 +234,7 @@ namespace NativeHost
while (true)
{
byte[] syncMsgBytes = null;
- Debug("Task2 reading from browser stdin...");
+ Debug("Task2 reading messages queued by browser...");
syncMsgBytes = receivedBrowserMessages.Take();
if (syncMsgBytes.Length == 2 && (char)syncMsgBytes[0] == '{' && (char)syncMsgBytes[1] == '}')
{
@@ -198,13 +242,14 @@ namespace NativeHost
throw new OperationCanceledException("Empty object");
}
//Debug("Task2 message size fron browser stdin: " + syncMsgBytes.Length);
- //Debug(Encoding.UTF8.GetString(syncMsgBytes));
- WriteMessage(outPipe, syncMsgBytes);
+ Debug("Sending message to XDM...");
+ NativeMessageSerializer.WriteMessage(pipe, syncMsgBytes);
+ Debug("Sent message to XDM");
}
}
catch (Exception ex)
{
- Debug(ex.ToString());
+ Debug(ex.ToString(), ex);
}
waitHandle.Set();
Debug("Task2 finished");
@@ -220,24 +265,29 @@ namespace NativeHost
}
catch (Exception ex)
{
- Debug(ex.ToString());
+ Debug(ex.ToString(), ex);
}
+ //try
+ //{
+ // inPipe.Disconnect();
+ //}
+ //catch { }
try
{
- inPipe.Disconnect();
+ pipe.Close();
}
catch { }
try
{
- outPipe.Dispose();
- }
- catch { }
- try
- {
- inPipe.Dispose();
+ pipe.Dispose();
}
catch { }
+ //try
+ //{
+ // inPipe.Dispose();
+ //}
+ //catch { }
}
}
catch (Exception exxxx)
@@ -246,67 +296,24 @@ namespace NativeHost
}
}
- private static void Debug(string msg)
+ private static void Debug(string msg, Exception? ex2 = null)
{
- try
+ Trace.WriteLine($"[xdm-native-messaging-host {DateTime.Now}] {msg}");
+ if (ex2 != null)
{
- log.WriteLine(msg);
- log.Flush();
- //File.AppendAllText(@"c:\log.txt", msg + "\r\n");
- Trace.WriteLine($"[{DateTime.Now}][NativeHost] {msg}");
- }
- catch(Exception ex)
- {
- log.WriteLine(ex.ToString());
- log.Flush();
+ Trace.WriteLine($"[xdm-native-messaging-host {DateTime.Now}] {ex2}");
}
}
- private static void WriteMessage(Stream pipe, string message)
- {
- var msgBytes = Encoding.UTF8.GetBytes(message);
- WriteMessage(pipe, msgBytes);
- }
-
- private static void WriteMessage(Stream pipe, byte[] msgBytes)
- {
- pipe.Write(BitConverter.GetBytes(msgBytes.Length), 0, 4);
- pipe.Write(msgBytes, 0, msgBytes.Length);
- pipe.Flush();
- }
-
- private static byte[] ReadMessageBytes(Stream pipe)
- {
- var b4 = new byte[4];
- ReadFully(pipe, b4, 4);
- var syncLength = BitConverter.ToInt32(b4, 0);
- var bytes = new byte[syncLength];
- ReadFully(pipe, bytes, syncLength);
- return bytes;
- }
-
- private static string ReadMessageString(Stream pipe)
- {
- var b4 = new byte[4];
- ReadFully(pipe, b4, 4);
- var syncLength = BitConverter.ToInt32(b4, 0);
- var bytes = new byte[syncLength];
- ReadFully(pipe, bytes, syncLength);
- return Encoding.UTF8.GetString(bytes);
- }
-
- private static void ReadFully(Stream stream, byte[] buf, int bytesToRead)
- {
- var rem = bytesToRead;
- var index = 0;
- while (rem > 0)
- {
- var c = stream.Read(buf, index, rem);
- if (c == 0) throw new IOException("Unexpected EOF");
- index += c;
- rem -= c;
- }
- }
+ //private static string ReadMessageString(Stream pipe)
+ //{
+ // var b4 = new byte[4];
+ // ReadFully(pipe, b4, 4);
+ // var syncLength = BitConverter.ToInt32(b4, 0);
+ // var bytes = new byte[syncLength];
+ // ReadFully(pipe, bytes, syncLength);
+ // return Encoding.UTF8.GetString(bytes);
+ //}
private static byte[] JsonToBinary(byte[] input)
{
diff --git a/app/XDM/NativeMessagingHost/NativeProcess.cs b/app/XDM/NativeMessagingHost/NativeProcess.cs
new file mode 100644
index 0000000..08e8daa
--- /dev/null
+++ b/app/XDM/NativeMessagingHost/NativeProcess.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace NativeHost
+{
+ internal static class NativeProcess
+ {
+ internal static bool Win32CreateProcess(string? file, string? args)
+ {
+ const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
+ const uint CREATE_BREAKAWAY_FROM_JOB = 0x01000000;
+ const uint CREATE_NEW_PROCESS_GROUP = 0x00000200;
+ PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
+ STARTUPINFO sInfo = new STARTUPINFO();
+ SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
+ SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES();
+ pSec.nLength = Marshal.SizeOf(pSec);
+ tSec.nLength = Marshal.SizeOf(tSec);
+
+ return CreateProcess(file, args,
+ ref pSec, ref tSec, false, CREATE_UNICODE_ENVIRONMENT | CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_PROCESS_GROUP,
+ IntPtr.Zero, null, ref sInfo, out pInfo);
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
+ internal static extern bool CreateProcess(
+ string? lpApplicationName,
+ string? lpCommandLine,
+ ref SECURITY_ATTRIBUTES lpProcessAttributes,
+ ref SECURITY_ATTRIBUTES lpThreadAttributes,
+ bool bInheritHandles,
+ uint dwCreationFlags,
+ IntPtr lpEnvironment,
+ string? lpCurrentDirectory,
+ [In] ref STARTUPINFO lpStartupInfo,
+ out PROCESS_INFORMATION lpProcessInformation);
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SECURITY_ATTRIBUTES
+ {
+ public int nLength;
+ public IntPtr lpSecurityDescriptor;
+ public int bInheritHandle;
+ }
+
+ // This also works with CharSet.Ansi as long as the calling function uses the same character set.
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct STARTUPINFO
+ {
+ public Int32 cb;
+ public string lpReserved;
+ public string lpDesktop;
+ public string lpTitle;
+ public Int32 dwX;
+ public Int32 dwY;
+ public Int32 dwXSize;
+ public Int32 dwYSize;
+ public Int32 dwXCountChars;
+ public Int32 dwYCountChars;
+ public Int32 dwFillAttribute;
+ public Int32 dwFlags;
+ public Int16 wShowWindow;
+ public Int16 cbReserved2;
+ public IntPtr lpReserved2;
+ public IntPtr hStdInput;
+ public IntPtr hStdOutput;
+ public IntPtr hStdError;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct PROCESS_INFORMATION
+ {
+ public IntPtr hProcess;
+ public IntPtr hThread;
+ public int dwProcessId;
+ public int dwThreadId;
+ }
+}
diff --git a/app/XDM/NetFX.Polyfill/ConcurrentDictionary.cs b/app/XDM/NetFX.Polyfill/ConcurrentDictionary.cs
deleted file mode 100644
index b3d63b1..0000000
--- a/app/XDM/NetFX.Polyfill/ConcurrentDictionary.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-//using System;
-//using System.Collections;
-//using System.Collections.Generic;
-//using System.Linq;
-//using System.Text;
-
-//namespace NetFX.Polyfill
-//{
-// public class ConcurrentDictionary : IDictionary
-// {
-// private Dictionary dictionary;
-
-// public V this[K key] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-
-// public ICollection Keys => throw new NotImplementedException();
-
-// public ICollection Values => throw new NotImplementedException();
-
-// public int Count => throw new NotImplementedException();
-
-// public bool IsReadOnly => throw new NotImplementedException();
-
-// public void Add(K key, V value)
-// {
-// throw new NotImplementedException();
-// }
-
-// public void Add(KeyValuePair item)
-// {
-// throw new NotImplementedException();
-// }
-
-// public void Clear()
-// {
-// throw new NotImplementedException();
-// }
-
-// public bool Contains(KeyValuePair item)
-// {
-// throw new NotImplementedException();
-// }
-
-// public bool ContainsKey(K key)
-// {
-// throw new NotImplementedException();
-// }
-
-// public void CopyTo(KeyValuePair[] array, int arrayIndex)
-// {
-// throw new NotImplementedException();
-// }
-
-// public IEnumerator> GetEnumerator()
-// {
-// lock (this)
-// {
-// foreach (var item in dictionary)
-// {
-// yield return item;
-// }
-// }
-// }
-
-// public bool Remove(K key)
-// {
-// lock (this)
-// {
-// return dictionary.Remove(key);
-// }
-// }
-
-// public bool Remove(KeyValuePair item)
-// {
-// lock (this)
-// {
-// return dictionary.Remove(item.Key);
-// }
-// }
-
-// public bool TryGetValue(K key, out V value)
-// {
-// lock (this)
-// {
-// return dictionary.TryGetValue(key, out value);
-// }
-// }
-
-// IEnumerator IEnumerable.GetEnumerator()
-// {
-// lock (this)
-// {
-// foreach (var item in dictionary)
-// {
-// yield return item;
-// }
-// }
-// }
-// }
-//}
diff --git a/app/XDM/NetFX.Polyfill/NetFX.Polyfill.csproj b/app/XDM/NetFX.Polyfill/NetFX.Polyfill.csproj
deleted file mode 100644
index fc22ec4..0000000
--- a/app/XDM/NetFX.Polyfill/NetFX.Polyfill.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2
- 9.0
- enable
- AnyCPU;x86
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/XDM/SerializeGenerator/Program.cs b/app/XDM/SerializeGenerator/Program.cs
deleted file mode 100644
index 99e128e..0000000
--- a/app/XDM/SerializeGenerator/Program.cs
+++ /dev/null
@@ -1,127 +0,0 @@
-//using System;
-//using System.Reflection;
-//using System.Text;
-//using XDM.Core.Lib.Common;
-
-//namespace SerializeGenerator
-//{
-// class Program
-// {
-// static int c = 1;
-// static void Main(string[] args)
-// {
-// var type = typeof(Config);
-
-// }
-
-// private static void GenerateCode(Type type, StringBuilder serializer, StringBuilder deserializer)
-// {
-// serializer.Append(@"
-// private static void WriteString(BinaryWriter w, string value, string name)
-// {
-// w.Write(name);
-// w.Write(STRING);
-// w.Write(value ?? string.Empty);
-// }
-
-// private static void WriteBoolean(BinaryWriter w, bool value, string name)
-// {
-// w.Write(name);
-// w.Write(BOOL);
-// w.Write(value);
-// }
-
-// private static void WriteInt32(BinaryWriter w, int value, string name)
-// {
-// w.Write(name);
-// w.Write(INT);
-// w.Write(value);
-// }
-
-// private static void WriteStringArray(BinaryWriter w, IEnumerable array, string name, int count)
-// {
-// w.Write(name);
-// w.Write(STRING_ARRAY);
-// w.Write((short)count);
-// foreach (var item in array)
-// {
-// w.Write(item);
-// }
-// }
-
-// private
-//");
-
-// foreach (var property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
-// {
-// if (property.PropertyType.IsArray || property.PropertyType.GetInterface("IEnumerable") != null)
-// {
-// if (property.PropertyType.IsArray)
-// {
-// serializer.Append($"var c{c++}=obj.{property.Name}?.Length??0;\r\n");
-// serializer.Append($"writer.Write(c{c});\r\n");
-// serializer.Append($"if(obj.{property.Name}!=null)" + "{foreach(var item in obj." + property.Name + "){");
-// //deserializer.Append($"var c{c++}=reader.ReadInt32();\r\n");
-// //deserializer.Append("if(c" + c + ">0){");
-
-// GenerateCode(property.PropertyType, serializer, deserializer);
-// serializer.Append("}}\r\n");
-
-// }
-// }
-
-// if (property.PropertyType == typeof(string)
-// || property.PropertyType == typeof(int)
-// || property.PropertyType == typeof(long)
-// || property.PropertyType == typeof(bool)
-// || property.PropertyType == typeof(double)
-// || property.PropertyType == typeof(float)
-// || property.PropertyType.IsEnum)
-// {
-// if (property.PropertyType == typeof(string))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name}??string.Empty);\r\n");
-// deserializer.Append($"obj.{property.Name}=Helper.ReadString(reader);\r\n");
-// }
-// else if (property.PropertyType.IsEnum)
-// {
-// serializer.Append($"writer.Write((int)obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=({property.PropertyType})reader.ReadInt32();\r\n");
-// }
-// else if (property.PropertyType == typeof(int))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=reader.ReadInt32();\r\n");
-// }
-// else if (property.PropertyType == typeof(long))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=reader.ReadInt64();\r\n");
-// }
-// else if (property.PropertyType == typeof(bool))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=reader.ReadBoolean();\r\n");
-// }
-// else if (property.PropertyType == typeof(double))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=reader.ReadDouble();\r\n");
-// }
-// else if (property.PropertyType == typeof(float))
-// {
-// serializer.Append($"writer.Write(obj.{property.Name});\r\n");
-// deserializer.Append($"obj.{property.Name}=reader.ReadFloat();\r\n");
-// }
-// }
-// else
-// {
-// if (property.PropertyType.IsValueType || property.PropertyType.IsClass)
-// {
-// GenerateCode(property.PropertyType, serializer, deserializer);
-// }
-// }
-// }
-// }
-// }
-//}
diff --git a/app/XDM/SerializeGenerator/SerializeGenerator.csproj b/app/XDM/SerializeGenerator/SerializeGenerator.csproj
deleted file mode 100644
index 4a1c035..0000000
--- a/app/XDM/SerializeGenerator/SerializeGenerator.csproj
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Exe
- net5.0
-
-
-
-
-
-
-
diff --git a/app/XDM/TraceLog/Log.cs b/app/XDM/TraceLog/Log.cs
deleted file mode 100644
index 974558a..0000000
--- a/app/XDM/TraceLog/Log.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Diagnostics;
-
-namespace TraceLog
-{
- public static class Log
- {
- public static void Debug(object obj, string message)
- {
- Trace.WriteLine(message + " : " + obj);
- }
-
- public static void Debug(string message)
- {
- Trace.WriteLine(message);
- }
- }
-}
diff --git a/app/XDM/TraceLog/TraceLog.csproj b/app/XDM/TraceLog/TraceLog.csproj
deleted file mode 100644
index c4c1ea1..0000000
--- a/app/XDM/TraceLog/TraceLog.csproj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- net3.5;net4.5;net4.7.2;net5.0
- 9.0
- enable
- AnyCPU;x86
-
-
-
diff --git a/app/XDM/Translations/TextResource.cs b/app/XDM/Translations/TextResource.cs
index 56f116d..f1c8fb7 100644
--- a/app/XDM/Translations/TextResource.cs
+++ b/app/XDM/Translations/TextResource.cs
@@ -10,12 +10,12 @@ namespace Translations
static TextResource()
{
- Load("English");
+ Load("English.txt");
}
public static void Load(string language)
{
- var file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("Lang", $"{language}.txt"));
+ var file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("Lang", $"{language}"));
if (File.Exists(file))
{
LoadTexts(file);
@@ -46,5 +46,10 @@ namespace Translations
texts[key] = val;
}
}
+
+ public static IEnumerable GetKeys()
+ {
+ return texts.Keys;
+ }
}
}
diff --git a/app/XDM/Translations/Translations.csproj b/app/XDM/Translations/Translations.csproj
index af58153..d06b294 100644
--- a/app/XDM/Translations/Translations.csproj
+++ b/app/XDM/Translations/Translations.csproj
@@ -2,9 +2,14 @@
net3.5;net4.5;net4.7.2;net5.0
- AnyCPU;x86
+ AnyCPU;x86;x64
9.0
enable
+
+ none
+ false
+
+
diff --git a/app/XDM/BrowserMonitor/BrowserMessageHandler.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/BrowserMessageHandler.cs
similarity index 86%
rename from app/XDM/BrowserMonitor/BrowserMessageHandler.cs
rename to app/XDM/XDM.App.Core/BrowserMonitoring/BrowserMessageHandler.cs
index 83782fa..19200db 100644
--- a/app/XDM/BrowserMonitor/BrowserMessageHandler.cs
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/BrowserMessageHandler.cs
@@ -32,10 +32,17 @@ namespace BrowserMonitoring
return;
}
- var rawMessage = envelop.Message;
- if (rawMessage == null)
+ if (envelop.MessageType == "custom")
{
- Log.Debug("Raw message is null");
+ var args = ArgsProcessor.ParseArgs(envelop.CustomData.Split('\r'));
+ ArgsProcessor.Process(app, args);
+ return;
+ }
+
+ var rawMessage = envelop.Message;
+ if (rawMessage == null && envelop.Messages == null)
+ {
+ Log.Debug("Raw message/messages is null");
return;
};
@@ -50,6 +57,17 @@ namespace BrowserMonitoring
}
break;
}
+ case "links":
+ {
+ var messages = new List(envelop.Messages.Length);
+ foreach (var msg in envelop.Messages)
+ {
+ var message = Parse(msg);
+ messages.Add(message);
+ }
+ app.AddBatchLinks(messages);
+ break;
+ }
case "video":
{
var message = Parse(rawMessage);
diff --git a/app/XDM/BrowserMonitor/BrowserMonitor.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/BrowserMonitor.cs
similarity index 100%
rename from app/XDM/BrowserMonitor/BrowserMonitor.cs
rename to app/XDM/XDM.App.Core/BrowserMonitoring/BrowserMonitor.cs
diff --git a/app/XDM/BrowserMonitor/IpcHttpHandler.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/IpcHttpHandler.cs
similarity index 55%
rename from app/XDM/BrowserMonitor/IpcHttpHandler.cs
rename to app/XDM/XDM.App.Core/BrowserMonitoring/IpcHttpHandler.cs
index d635588..e530ecf 100644
--- a/app/XDM/BrowserMonitor/IpcHttpHandler.cs
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/IpcHttpHandler.cs
@@ -40,7 +40,6 @@ namespace BrowserMonitoring
Log.Debug(ex.ToString());
app.AppUI.ShowMessageBox(null, TextResource.GetText("MSG_ALREADY_RUNNING"));
}
-
}).Start();
}
@@ -63,46 +62,59 @@ namespace BrowserMonitoring
switch (context.RequestPath)
{
case "/download":
- Log.Debug(Encoding.UTF8.GetString(context.RequestBody!));
- var message = Message.ParseMessage(Encoding.UTF8.GetString(context.RequestBody!));
- if (!(Helpers.IsBlockedHost(message.Url) || Helpers.IsCompressedJSorCSS(message.Url)))
{
- app.AddDownload(message);
- }
- break;
- case "/video":
- Console.WriteLine(Encoding.UTF8.GetString(context.RequestBody!));
- var message2 = Message.ParseMessage(Encoding.UTF8.GetString(context.RequestBody!));
- var contentType = message2.GetResponseHeaderFirstValue("Content-Type")?.ToLowerInvariant() ?? string.Empty;
-
- if (VideoUrlHelper.IsHLS(contentType))
- {
- VideoUrlHelper.ProcessHLSVideo(message2, app);
- }
-
- if (VideoUrlHelper.IsDASH(contentType))
- {
- VideoUrlHelper.ProcessDashVideo(message2, app);
- }
-
- if (!VideoUrlHelper.ProcessYtDashSegment(message2, app))
- {
- if (contentType != null && !(contentType.Contains("f4f") ||
- contentType.Contains("m4s") ||
- contentType.Contains("mp2t") || message2.Url.Contains("abst") ||
- message2.Url.Contains("f4x") || message2.Url.Contains(".fbcdn")
- || message2.Url.Contains("http://127.0.0.1:9614")))
+ var text = Encoding.UTF8.GetString(context.RequestBody!);
+ Log.Debug(text);
+ var message = Message.ParseMessage(text);
+ if (!(Helpers.IsBlockedHost(message.Url) || Helpers.IsCompressedJSorCSS(message.Url)))
{
- VideoUrlHelper.ProcessNormalVideo(message2, app);
+ app.AddDownload(message);
}
+ break;
}
- break;
- case "/item":
- foreach (var item in Encoding.UTF8.GetString(context.RequestBody!).Split(new char[] { '\r', '\n' }))
+ case "/video":
{
- app.AddVideoDownload(item);
+ var text = Encoding.UTF8.GetString(context.RequestBody!);
+ Log.Debug(text);
+ var message2 = Message.ParseMessage(Encoding.UTF8.GetString(context.RequestBody!));
+ var contentType = message2.GetResponseHeaderFirstValue("Content-Type")?.ToLowerInvariant() ?? string.Empty;
+ if (VideoUrlHelper.IsHLS(contentType))
+ {
+ VideoUrlHelper.ProcessHLSVideo(message2, app);
+ }
+ if (VideoUrlHelper.IsDASH(contentType))
+ {
+ VideoUrlHelper.ProcessDashVideo(message2, app);
+ }
+ if (!VideoUrlHelper.ProcessYtDashSegment(message2, app))
+ {
+ if (contentType != null && !(contentType.Contains("f4f") ||
+ contentType.Contains("m4s") ||
+ contentType.Contains("mp2t") || message2.Url.Contains("abst") ||
+ message2.Url.Contains("f4x") || message2.Url.Contains(".fbcdn")
+ || message2.Url.Contains("http://127.0.0.1:9614")))
+ {
+ VideoUrlHelper.ProcessNormalVideo(message2, app);
+ }
+ }
+ break;
+ }
+ case "/links":
+ {
+ var text = Encoding.UTF8.GetString(context.RequestBody!);
+ Log.Debug(text);
+ var arr = text.Split(new string[] { "\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries);
+ app.AddBatchLinks(arr.Select(str => Message.ParseMessage(str.Trim())).ToList());
+ break;
+ }
+ case "/item":
+ {
+ foreach (var item in Encoding.UTF8.GetString(context.RequestBody!).Split(new char[] { '\r', '\n' }))
+ {
+ app.AddVideoDownload(item);
+ }
+ break;
}
- break;
case "/clear":
app.ClearVideoList();
break;
diff --git a/app/XDM/XDM.App.Core/BrowserMonitoring/JsonMessageParser.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/JsonMessageParser.cs
new file mode 100644
index 0000000..deb56b9
--- /dev/null
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/JsonMessageParser.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Newtonsoft.Json;
+
+namespace BrowserMonitoring
+{
+ public class JsonMessageParser
+ {
+ private T? ReadProperty(JsonTextReader reader, string name)
+ {
+ if (reader.TokenType == JsonToken.PropertyName && reader.Value?.ToString() == name &&
+ reader.Read() && reader.Value != null)
+ {
+ return (T)reader.Value;
+ }
+ return default(T);
+ }
+
+ private bool IsObjectStart(JsonTextReader reader, string name)
+ {
+ return reader.TokenType == JsonToken.PropertyName && reader.Value?.ToString() == name &&
+ reader.Read() && reader.TokenType == JsonToken.StartObject;
+ }
+
+ private bool IsListStart(JsonTextReader reader, string name)
+ {
+ return reader.TokenType == JsonToken.PropertyName && reader.Value?.ToString() == name &&
+ reader.Read() && reader.TokenType == JsonToken.StartArray;
+ }
+
+ private void SkipUnknownParts(JsonTextReader reader)
+ {
+ if (reader.TokenType == JsonToken.PropertyName && reader.Value != null)
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.StartObject)
+ {
+ var n = 1;
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) n--;
+ if (reader.TokenType == JsonToken.StartObject) n++;
+ if (n == 0) return;
+ }
+ }
+ else if (reader.TokenType == JsonToken.StartArray)
+ {
+ var n = 1;
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndArray) n--;
+ if (reader.TokenType == JsonToken.StartArray) n++;
+ if (n == 0) return;
+ }
+ }
+ else if (reader.Value != null)
+ {
+ continue;
+ }
+ }
+ }
+ }
+
+ private RawBrowserMessage ReadMessageObject(JsonTextReader reader)
+ {
+ var msg = new RawBrowserMessage { Cookies = new(), ResponseHeaders = new(), RequestHeaders = new() };
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) break;
+ var url = ReadProperty(reader, "url");
+ if (url != null)
+ {
+ msg.Url = url;
+ }
+ if (IsObjectStart(reader, "cookies"))
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) break;
+ if (reader.TokenType == JsonToken.PropertyName && reader.Value != null)
+ {
+ var cookieName = (string)reader.Value;
+ if (reader.Read() && reader.TokenType == JsonToken.String)
+ {
+ var cookieValue = (string)reader.Value;
+ msg.Cookies[cookieName] = cookieValue;
+ }
+ }
+ }
+ }
+
+ if (IsObjectStart(reader, "responseHeaders"))// && IsListStart(reader, "realUA"))
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) break;
+ if (reader.TokenType == JsonToken.PropertyName && reader.Value != null)
+ {
+ var headerName = (string)reader.Value;
+ if (IsListStart(reader, headerName))
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndArray) break;
+ if (reader.TokenType == JsonToken.String)
+ {
+ if (msg.ResponseHeaders.TryGetValue(headerName, out var list))
+ {
+ list.Add((string)reader.Value);
+ }
+ else
+ {
+ msg.ResponseHeaders[headerName] = new() { (string)reader.Value };
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (IsObjectStart(reader, "requestHeaders"))
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) break;
+ if (reader.TokenType == JsonToken.PropertyName && reader.Value != null)
+ {
+ var headerName = (string)reader.Value;
+ if (IsListStart(reader, headerName))
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndArray) break;
+ if (reader.TokenType == JsonToken.String)
+ {
+ if (msg.RequestHeaders.TryGetValue(headerName, out var list))
+ {
+ list.Add((string)reader.Value);
+ }
+ else
+ {
+ msg.RequestHeaders[headerName] = new() { (string)reader.Value };
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ SkipUnknownParts(reader);
+ }
+ return msg;
+ }
+
+ public RawBrowserMessageEnvelop Parse(Stream stream)
+ {
+ var envelop = new RawBrowserMessageEnvelop();
+ var reader = new JsonTextReader(new StreamReader(stream));
+ if (reader.Read() && reader.TokenType == JsonToken.StartObject)
+ {
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndObject) break;
+ var messageType = ReadProperty(reader, "messageType");
+ if (messageType != null)
+ {
+ envelop.MessageType = messageType;
+ }
+ var customData = ReadProperty(reader, "customData");
+ if (customData != null)
+ {
+ envelop.CustomData = customData;
+ }
+ if (IsObjectStart(reader, "message"))
+ {
+ var msg = ReadMessageObject(reader);
+ envelop.Message = msg;
+ }
+ if (IsListStart(reader, "messages"))
+ {
+ var list = new List();
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndArray) break;
+ if (reader.TokenType == JsonToken.StartObject)
+ {
+ var msg = ReadMessageObject(reader);
+ list.Add(msg);
+ envelop.Messages = list.ToArray();
+ }
+ }
+ }
+ if (IsListStart(reader, "videoIds"))
+ {
+ var list = new List();
+ while (reader.Read())
+ {
+ if (reader.TokenType == JsonToken.EndArray) break;
+ if (reader.TokenType == JsonToken.StartObject)
+ {
+ var msg = ReadMessageObject(reader);
+ list.Add(msg);
+ envelop.Messages = list.ToArray();
+ }
+ }
+ }
+ SkipUnknownParts(reader);
+ }
+ }
+ return envelop;
+ }
+ }
+}
diff --git a/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingConfigurer.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingConfigurer.cs
new file mode 100644
index 0000000..18eff7c
--- /dev/null
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingConfigurer.cs
@@ -0,0 +1,108 @@
+using Microsoft.Win32;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using TraceLog;
+using XDM.Core.Lib.Common;
+
+namespace BrowserMonitoring
+{
+ internal static class NativeMessagingConfigurer
+ {
+ private static void CreateMessagingHostManifest(Browser browser, string appName, string manifestPath)
+ {
+ var allowedExtensions = browser == Browser.Firefox ? new[] {
+ "browser-mon@xdman.sourceforge.net"
+ } : new[] {
+ "chrome-extension://danmljfachfhpbfikjgedlfifabhofcj/",
+ "chrome-extension://dkckaoghoiffdbomfbbodbbgmhjblecj/",
+ "chrome-extension://ejpbcmllmliidhlpkcgbphhmaodjihnc/",
+ "chrome-extension://fogpiboapmefmkbodpmfnohfflonbgig/"
+ };
+ var folder = Path.GetDirectoryName(manifestPath)!;
+ if (!Directory.Exists(folder))
+ {
+ try
+ {
+ Directory.CreateDirectory(folder);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+ using var stream = new FileStream(manifestPath, FileMode.Create);
+ using var textWriter = new StreamWriter(stream);
+ using var writer = new JsonTextWriter(textWriter);
+ writer.Formatting = Formatting.Indented;
+ writer.WriteStartObject();
+ writer.WritePropertyName("name");
+ writer.WriteValue(appName);
+ writer.WritePropertyName("description");
+ writer.WriteValue("Native messaging host for Xtreme Download Manager");
+ writer.WritePropertyName("path");
+ writer.WriteValue(Path.Combine(
+ Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MessagingHost"),
+ Environment.OSVersion.Platform == PlatformID.Win32NT ?
+ "xdm-messaging-host.exe" : "xdm-messaging-host"));
+ writer.WritePropertyName("type");
+ writer.WriteValue("stdio");
+ writer.WritePropertyName(browser == Browser.Firefox ? "allowed_extensions" : "allowed_origins");
+ writer.WriteStartArray();
+ foreach (var extension in allowedExtensions)
+ {
+ writer.WriteValue(extension);
+ }
+ writer.WriteEndArray();
+ writer.WriteEndObject();
+ writer.Close();
+ }
+
+ public static void InstallNativeMessagingHost(Browser browser)
+ {
+ var appName = browser == Browser.Firefox ? "xdmff.native_host" :
+ "xdm_chrome.native_host";
+ var os = Environment.OSVersion.Platform;
+ if (os == PlatformID.Win32NT)
+ {
+ var manifestPath = Path.Combine(Config.DataDir, $"{appName}.json");
+ CreateMessagingHostManifest(browser, appName, manifestPath);
+ var regPath = (browser == Browser.Firefox ?
+ @"Software\Mozilla\NativeMessagingHosts\" :
+ @"SOFTWARE\Google\Chrome\NativeMessagingHosts");
+ using var regKey = Registry.CurrentUser.CreateSubKey(regPath);
+ using var key = regKey.CreateSubKey(appName, RegistryKeyPermissionCheck.ReadWriteSubTree);
+ key.SetValue(null, manifestPath);
+ }
+ else
+ {
+#if NET5_0_OR_GREATER
+ string manifestPath;
+ var home = Environment.GetEnvironmentVariable("HOME")!;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ manifestPath = Path.Combine(home, browser == Browser.Firefox ?
+ $"Library/Application Support/Mozilla/NativeMessagingHosts/{appName}.json" :
+ $"Library/Application Support/Google/Chrome/NativeMessagingHosts/{appName}.json");
+ }
+ else
+ {
+ manifestPath = Path.Combine(home, browser == Browser.Firefox ?
+ $".mozilla/native-messaging-hosts/{appName}.json" :
+ $".config/google-chrome/NativeMessagingHosts/{appName}.json");
+ }
+ Log.Debug($"Manifest file: {manifestPath}");
+ CreateMessagingHostManifest(browser, appName, manifestPath);
+#endif
+ }
+ }
+ }
+
+ public enum Browser
+ {
+ Chrome, Firefox, MSEdge
+ }
+}
diff --git a/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostChannel.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostChannel.cs
new file mode 100644
index 0000000..77c5a53
--- /dev/null
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostChannel.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO.Pipes;
+using System.Threading;
+using TraceLog;
+
+namespace BrowserMonitoring
+{
+ internal sealed class NativeMessagingHostChannel
+ {
+ private NamedPipeServerStream pipe;
+ internal event EventHandler? MessageReceived;
+ internal event EventHandler? Disconnected;
+ private Thread readerThread;
+
+ internal NativeMessagingHostChannel(NamedPipeServerStream pipe)
+ {
+ this.pipe = pipe;
+ readerThread = new Thread(() =>
+ {
+ try
+ {
+ ReadDataFromPipe();
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.ToString());
+ Disconnect();
+ }
+ this.Disconnected?.Invoke(this, EventArgs.Empty);
+ });
+ }
+
+ internal void Disconnect()
+ {
+ try
+ {
+ if (pipe.IsConnected)
+ {
+ pipe.Disconnect();
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.ToString());
+ }
+ }
+
+ internal void Publish(byte[] data)
+ {
+ try
+ {
+ NativeMessageSerializer.WriteMessage(pipe, data);
+ pipe.Flush();
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+
+ internal void ReadDataFromPipe()
+ {
+ while (true)
+ {
+ Log.Debug("Waiting for message from native host...");
+ var bytes = NativeMessageSerializer.ReadMessageBytes(pipe);
+ Log.Debug($"Message from native host {bytes.Length} bytes");
+ this.MessageReceived?.Invoke(this, new NativeMessageEventArgs(bytes));
+ }
+ }
+
+ internal void Start(byte[] initialConfig)
+ {
+ try
+ {
+ readerThread.Start();
+ NativeMessageSerializer.WriteMessage(pipe, initialConfig);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+ }
+
+ internal class NativeMessageEventArgs : EventArgs
+ {
+ private byte[] data;
+
+ internal NativeMessageEventArgs(byte[] data)
+ {
+ this.data = data;
+ }
+
+ internal byte[] Data => data;
+ }
+}
diff --git a/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostHandler.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostHandler.cs
new file mode 100644
index 0000000..bc90169
--- /dev/null
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/NativeMessagingHostHandler.cs
@@ -0,0 +1,367 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO.Pipes;
+using System.IO;
+using XDM.Core.Lib.Common;
+using System.Threading;
+#if NET35
+using NetFX.Polyfill;
+#else
+using System.Collections.Concurrent;
+#endif
+using TraceLog;
+
+namespace BrowserMonitoring
+{
+ public class NativeMessagingHostHandler : IDisposable
+ {
+ private int MaxPipeInstance = 254;
+ private static readonly string PipeName = "XDM_Ipc_Browser_Monitoring_Pipe";
+ private List connectedChannels = new();
+ //private List inPipes = new();
+ //private Dictionary inOutMap = new();
+ private readonly IApp app;
+ private static Mutex globalMutex;
+ // private readonly BlockingCollection Messages = new();
+ //private Thread WriterThread;
+ private Thread listenerThread;
+
+ public static void EnsureSingleInstance(IApp app)
+ {
+ try
+ {
+ using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
+ throw new InstanceAlreadyRunningException(@"XDM instance already running, Mutex exists 'Global\XDM_Active_Instance'");
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, "Exception in NativeMessagingHostHandler ctor");
+ if (ex is InstanceAlreadyRunningException)
+ {
+ if (app.Args != null && app.Args.Length > 0)
+ {
+ Log.Debug(ex, "Sending args to running instance");
+ SendArgsToRunningInstance(app.Args);
+ Environment.Exit(0);
+ }
+ throw;
+ }
+ }
+ globalMutex = new Mutex(true, @"Global\XDM_Active_Instance");
+ }
+
+ public NativeMessagingHostHandler(IApp app)
+ {
+ this.app = app;
+ EnsureSingleInstance(this.app);
+ }
+
+ public void BroadcastConfig()
+ {
+ var bytes = GetSyncBytes(app);
+ lock (this)
+ {
+ foreach (var channel in connectedChannels)
+ {
+ try
+ {
+ channel.Publish(bytes);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+ }
+ //Messages.Add(bytes);
+ }
+
+ public void StartPipedChannel()
+ {
+ listenerThread = new Thread(() =>
+ {
+ while (true)
+ {
+ var pipe =
+ new NamedPipeServerStream(PipeName,
+ PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances,
+ PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
+ Log.Debug("Waiting for native host pipe...");
+ pipe.WaitForConnection();
+ Log.Debug("Pipe request received");
+ lock (connectedChannels)
+ {
+ var channel = CreateChannel(pipe);
+ connectedChannels.Add(channel);
+ channel.Start(GetSyncBytes(app));
+ }
+ }
+ });
+ listenerThread.Start();
+ }
+
+ private NativeMessagingHostChannel CreateChannel(NamedPipeServerStream pipe)
+ {
+ var channel = new NativeMessagingHostChannel(pipe);
+ channel.MessageReceived += (sender, args) =>
+ {
+ try
+ {
+ using var br = new BinaryReader(new MemoryStream(args.Data));
+ var envelop = RawBrowserMessageEnvelop.Deserialize(br);
+ BrowserMessageHandler.Handle(app, envelop);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.ToString());
+ }
+ };
+ channel.Disconnected += (sender, bytes) =>
+ {
+ lock (connectedChannels)
+ {
+ connectedChannels.Remove((NativeMessagingHostChannel)sender);
+ }
+ };
+ return channel;
+ }
+
+ //public void StartPipedChannel()
+ //{
+ // WriterThread = new Thread(() =>
+ // {
+ // while (true)
+ // {
+ // //Log.Debug("Total messages to be sent to native host: " + Messages.Count);
+ // var bytes = Messages.Take();
+ // foreach (var key in inOutMap.Keys)
+ // {
+ // //Log.Debug("Sending message to native host");
+ // try
+ // {
+ // var outpipe = inOutMap[key];
+ // NativeMessageSerializer.WriteMessage(outpipe, bytes);
+ // //Log.Debug("Send message to native host successfully");
+ // }
+ // catch (Exception ex)
+ // {
+ // Log.Debug(ex, "Send message to native host failed");
+ // }
+ // }
+ // }
+ // });
+ // WriterThread.Start();
+ // new Thread(() =>
+ // {
+ // try
+ // {
+ // if (inPipes.Count == MaxPipeInstance)
+ // {
+ // Log.Debug("Max pipe count of " + MaxPipeInstance + " is reached");
+ // return;
+ // }
+ // var inPipe =
+ // new NamedPipeServerStream(PipeName,
+ // PipeDirection.In, NamedPipeServerStream.MaxAllowedServerInstances,
+ // PipeTransmissionMode.Byte, PipeOptions.WriteThrough);
+ // inPipes.Add(inPipe);
+ // var first = true;
+ // while (true)
+ // {
+ // Log.Debug("Waiting for native host pipe...");
+ // inPipe.WaitForConnection();
+ // Log.Debug("Pipe request received");
+
+ // if (first)
+ // {
+ // Log.Debug("Creating one more additional pipe");
+ // StartPipedChannel();
+ // first = false;
+ // }
+
+ // try
+ // {
+ // ConsumePipe(inPipe);
+ // }
+ // catch (Exception e)
+ // {
+ // inPipe.Disconnect();
+ // Log.Debug(e, "Error in message exchange");
+ // }
+ // Log.Debug("Terminated message exchange, will reuse the pipe");
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+ // Log.Debug(ex, "Error in message exchange flow");
+ // }
+ // }).Start();
+ //}
+
+ //private void ConsumePipe(NamedPipeServerStream inPipe)
+ //{
+ // try
+ // {
+ // Log.Debug("Initiate message handshake");
+ // var clientPipeName = Encoding.UTF8.GetString(NativeMessageSerializer.ReadMessageBytes(inPipe));
+ // Log.Debug("Client pipe: " + clientPipeName);
+ // if (clientPipeName.StartsWith("XDM-APP-"))
+ // {
+ // var command = NativeMessageSerializer.ReadMessageBytes(inPipe);
+ // var args = ArgsProcessor.ParseArgs(Encoding.UTF8.GetString(command).Split('\r'));
+ // ArgsProcessor.Process(app, args);
+ // return;
+ // }
+ // var outPipe = new NamedPipeClientStream(".", clientPipeName, PipeDirection.Out);
+ // outPipe.Connect();
+ // SendConfig(outPipe);
+ // inOutMap[inPipe] = outPipe;
+ // Log.Debug("Message handshake completed");
+ // while (true)
+ // {
+ // var text = NativeMessageSerializer.ReadMessageBytes(inPipe);
+ // using var ms = new MemoryStream(text);
+ // using var br = new BinaryReader(ms);
+ // // Log.Debug("{Text}", text);
+ // var envelop = RawBrowserMessageEnvelop.Deserialize(br);
+ // BrowserMessageHandler.Handle(app, envelop);
+ // }
+ // }
+ // finally
+ // {
+ // try
+ // {
+ // NamedPipeClientStream? op = null;
+ // lock (this)
+ // {
+ // if (inOutMap.TryGetValue(inPipe, out op))
+ // {
+ // inOutMap.Remove(inPipe);
+ // }
+ // }
+ // op?.Close();
+ // op?.Dispose();
+ // }
+ // catch { }
+ // }
+ //}
+
+ //private void SendConfig(Stream pipe)
+ //{
+ // var bytes = GetSyncBytes(app);
+ // NativeMessageSerializer.WriteMessage(pipe, bytes);
+ //}
+
+ //private static void ReadFully(Stream stream, byte[] buf, int bytesToRead)
+ //{
+ // var rem = bytesToRead;
+ // var index = 0;
+ // while (rem > 0)
+ // {
+ // var c = stream.Read(buf, index, rem);
+ // if (c == 0) throw new IOException("Unexpected EOF");
+ // index += c;
+ // rem -= c;
+ // }
+ //}
+
+ //private static byte[] ReadMessageBytes(Stream pipe)
+ //{
+ // var b4 = new byte[4];
+ // ReadFully(pipe, b4, 4);
+ // var syncLength = BitConverter.ToInt32(b4, 0);
+ // if (syncLength > 4 * 8196)
+ // {
+ // throw new ArgumentException($"Message length too long: {syncLength}");
+ // }
+ // var bytes = new byte[syncLength];
+ // ReadFully(pipe, bytes, syncLength);
+ // return bytes;
+ //}
+
+ //private static void WriteMessage(Stream pipe, string message)
+ //{
+ // var msgBytes = Encoding.UTF8.GetBytes(message);
+ // WriteMessage(pipe, msgBytes);
+ //}
+
+ //private static void WriteMessage(Stream pipe, byte[] msgBytes)
+ //{
+
+ // var bytes = BitConverter.GetBytes(msgBytes.Length);
+ // pipe.Write(bytes, 0, bytes.Length);
+ // pipe.Write(msgBytes, 0, msgBytes.Length);
+ // pipe.Flush();
+ //}
+
+ public void Dispose()
+ {
+ lock (connectedChannels)
+ {
+ foreach (var channel in connectedChannels)
+ {
+ channel.Disconnect();
+ }
+ }
+ //foreach (var pipe in inPipes)
+ //{
+ // try { pipe.Disconnect(); } catch { }
+ // try { pipe.Dispose(); } catch { }
+ //}
+ }
+
+ private static byte[] GetSyncBytes(IApp app)
+ {
+ var msg = new SyncMessage()
+ {
+ Enabled = Config.Instance.IsBrowserMonitoringEnabled,
+ BlockedHosts = Config.Instance.BlockedHosts,
+ VideoUrls = new string[0],
+ FileExts = Config.Instance.FileExtensions,
+ VidExts = Config.Instance.VideoExtensions,
+ VidList = app.GetVideoList(false).Select(a => new VideoItem
+ {
+ Id = a.ID,
+ Text = a.File,
+ Info = a.DisplayName
+ }).ToList(),
+ MimeList = new string[] { "video", "audio", "mpegurl", "f4m", "m3u8", "dash" },
+ BlockedMimeList = new string[] { "text/javascript", "application/javascript", "text/css", "text/html" },
+ VideoUrlsWithPostReq = new string[] { "ubei/v1/player?key=", "ubei/v1/next?key=" }
+ };
+ return msg.Serialize();
+ }
+
+ private static void SendArgsToRunningInstance(string[] args)
+ {
+ if (args == null || args.Length < 1) return;
+ try
+ {
+ using var npc =
+ new NamedPipeClientStream(".", PipeName, PipeDirection.Out);
+ npc.Connect();
+ var b = new MemoryStream();
+ var wb = new BinaryWriter(b);
+ wb.Write(Int32.MaxValue);
+ wb.Write(string.Join("\r", args));
+ wb.Close();
+ NativeMessageSerializer.WriteMessage(npc, b.ToArray());
+ npc.Flush();
+ npc.Close();
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+ }
+
+ public class InstanceAlreadyRunningException : Exception
+ {
+ public InstanceAlreadyRunningException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/app/XDM/BrowserMonitor/VideoUrlHelper.cs b/app/XDM/XDM.App.Core/BrowserMonitoring/VideoUrlHelper.cs
similarity index 86%
rename from app/XDM/BrowserMonitor/VideoUrlHelper.cs
rename to app/XDM/XDM.App.Core/BrowserMonitoring/VideoUrlHelper.cs
index cd1d247..6d9ef6f 100644
--- a/app/XDM/BrowserMonitor/VideoUrlHelper.cs
+++ b/app/XDM/XDM.App.Core/BrowserMonitoring/VideoUrlHelper.cs
@@ -86,7 +86,8 @@ namespace BrowserMonitoring
var displayInfo = new StreamingVideoDisplayInfo
{
Quality = $"[{fileExt.ToUpperInvariant()}] {size} {item.FormatDescription}",
- Size = item.Size
+ Size = item.Size,
+ CreationTime = DateTime.Now
};
//var displayText = $"[{fileExt.ToUpperInvariant()}] {size} {item.FormatDescription}";
@@ -117,7 +118,8 @@ namespace BrowserMonitoring
var displayInfo = new StreamingVideoDisplayInfo
{
Quality = $"[{fileExt.ToUpperInvariant()}] {size} {item.FormatDescription}",
- Size = item.Size
+ Size = item.Size,
+ CreationTime = DateTime.Now
};
list.Add((Info: mediaItem, DisplayInfo: displayInfo));
@@ -175,7 +177,8 @@ namespace BrowserMonitoring
Log.Debug("Display text dash: " + displayText);
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
- Quality = displayText
+ Quality = displayText,
+ CreationTime = DateTime.Now
}, mediaItem);
}
else
@@ -197,7 +200,8 @@ namespace BrowserMonitoring
Log.Debug("Display text hls: " + displayText);
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
- Quality = displayText
+ Quality = displayText,
+ CreationTime = DateTime.Now
}, mediaItem);
}
}
@@ -235,7 +239,8 @@ namespace BrowserMonitoring
Log.Debug("Display text hls: " + displayText);
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
- Quality = displayText
+ Quality = displayText,
+ CreationTime = DateTime.Now
}, mediaItem);
}
@@ -309,7 +314,8 @@ namespace BrowserMonitoring
Log.Debug("Display text hls: " + plc.Quality);
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
- Quality = displayText
+ Quality = displayText,
+ CreationTime = DateTime.Now
}, video);
}
}
@@ -336,7 +342,8 @@ namespace BrowserMonitoring
var displayText = $"[{container}]";
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
- Quality = displayText
+ Quality = displayText,
+ CreationTime = DateTime.Now
}, video);
}
}
@@ -432,22 +439,27 @@ namespace BrowserMonitoring
if (AddToQueue(info))
{
+ if (!info.IsVideo && mime.StartsWith("audio/"))
+ {
+ HandleDashAudio(info, app, message);
+ }
var di = GetDASHPair(info);
if (di == null)
{
return true;
}
- var video = new DualSourceHTTPDownloadInfo
- {
- Uri1 = di.Url,
- Uri2 = info.Url,
- Headers1 = di.Headers,
- Headers2 = info.Headers,
- File = Helpers.SanitizeFileName(message.File ?? Helpers.GetFileName(new Uri(message.Url))) + ".mkv",
- Cookies1 = di.Cookies,
- Cookies2 = info.Cookies,
- ContentLength = di.Length + info.Length
- };
+ var video = CreateDualSourceHTTPDownloadInfo(di, info, message);
+ // new DualSourceHTTPDownloadInfo
+ //{
+ // Uri1 = di.Url,
+ // Uri2 = info.Url,
+ // Headers1 = di.Headers,
+ // Headers2 = info.Headers,
+ // File = Helpers.SanitizeFileName(message.File ?? Helpers.GetFileName(new Uri(message.Url))) + ".mkv",
+ // Cookies1 = di.Cookies,
+ // Cookies2 = info.Cookies,
+ // ContentLength = di.Length + info.Length
+ //};
var size = di.Length + info.Length;
Log.Debug("Itag: " + info.ITag + " " + di.ITag);
@@ -457,7 +469,8 @@ namespace BrowserMonitoring
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
Quality = displayText,
- Size = size
+ Size = size,
+ CreationTime = DateTime.Now
}, video);
}
@@ -467,6 +480,62 @@ namespace BrowserMonitoring
return false;
}
+ private static void HandleDashAudio(DashInfo info, IApp app, Message message)
+ {
+ try
+ {
+ var size = info.Length;
+ Log.Debug("Itag: " + info.ITag + " " + info.ITag);
+ var name = Helpers.GetFileName(new Uri(info.Url));
+ var ext = Path.GetExtension(name);
+
+ if (string.IsNullOrEmpty(ext))
+ {
+ ext = info.Mime.Contains("webm") ? ".webm" : info.Mime.Contains("mp4") ? ".mp4" : "mkv";
+ }
+
+ var quality = ext.Substring(1)?.ToUpperInvariant();
+ var displayText = $"[{quality} AUDIO] {(size > 0 ? Helpers.FormatSize(size) : string.Empty)}";
+
+ var video = new SingleSourceHTTPDownloadInfo
+ {
+ Uri = info.Url,
+ Headers = info.Headers,
+ File = Helpers.SanitizeFileName(message.File ?? Helpers.GetFileName(new Uri(message.Url))) + ext,
+ Cookies = info.Cookies,
+ ContentLength = size,
+ ContentType = info.Mime
+ };
+
+ app.AddVideoNotification(new StreamingVideoDisplayInfo
+ {
+ Quality = displayText,
+ Size = size,
+ CreationTime = DateTime.Now
+ }, video);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, ex.Message);
+ }
+ }
+
+ private static DualSourceHTTPDownloadInfo CreateDualSourceHTTPDownloadInfo(DashInfo info1, DashInfo info2, Message message)
+ {
+ var (video, audio) = info1.IsVideo ? (info1, info2) : (info2, info1);
+ return new DualSourceHTTPDownloadInfo
+ {
+ Uri1 = video.Url,
+ Uri2 = audio.Url,
+ Headers1 = video.Headers,
+ Headers2 = audio.Headers,
+ File = Helpers.SanitizeFileName(message.File ?? Helpers.GetFileName(new Uri(message.Url))) + ".mkv",
+ Cookies1 = video.Cookies,
+ Cookies2 = audio.Cookies,
+ ContentLength = video.Length + audio.Length
+ };
+ }
+
internal static void ProcessNormalVideo(Message message2, IApp app)
{
if (IsMediaFragment(message2.GetRequestHeaderFirstValue("Referer")))
@@ -530,7 +599,8 @@ namespace BrowserMonitoring
app.AddVideoNotification(new StreamingVideoDisplayInfo
{
Quality = displayText,
- Size = size
+ Size = size,
+ CreationTime = DateTime.Now
}, video); ;
}
diff --git a/app/XDM/HttpServer/HttpParser.cs b/app/XDM/XDM.App.Core/HttpServer/HttpParser.cs
similarity index 100%
rename from app/XDM/HttpServer/HttpParser.cs
rename to app/XDM/XDM.App.Core/HttpServer/HttpParser.cs
diff --git a/app/XDM/HttpServer/HttpServer.cs b/app/XDM/XDM.App.Core/HttpServer/HttpServer.cs
similarity index 100%
rename from app/XDM/HttpServer/HttpServer.cs
rename to app/XDM/XDM.App.Core/HttpServer/HttpServer.cs
diff --git a/app/XDM/HttpServer/LineReader.cs b/app/XDM/XDM.App.Core/HttpServer/LineReader.cs
similarity index 100%
rename from app/XDM/HttpServer/LineReader.cs
rename to app/XDM/XDM.App.Core/HttpServer/LineReader.cs
diff --git a/app/XDM/HttpServer/RequestContext.cs b/app/XDM/XDM.App.Core/HttpServer/RequestContext.cs
similarity index 100%
rename from app/XDM/HttpServer/RequestContext.cs
rename to app/XDM/XDM.App.Core/HttpServer/RequestContext.cs
diff --git a/app/XDM/HttpServer/RequestContextEventArgs.cs b/app/XDM/XDM.App.Core/HttpServer/RequestContextEventArgs.cs
similarity index 100%
rename from app/XDM/HttpServer/RequestContextEventArgs.cs
rename to app/XDM/XDM.App.Core/HttpServer/RequestContextEventArgs.cs
diff --git a/app/XDM/HttpServer/ResponseStatus.cs b/app/XDM/XDM.App.Core/HttpServer/ResponseStatus.cs
similarity index 100%
rename from app/XDM/HttpServer/ResponseStatus.cs
rename to app/XDM/XDM.App.Core/HttpServer/ResponseStatus.cs
diff --git a/app/XDM/MediaParser.Hls/Dash/DashUtil.cs b/app/XDM/XDM.App.Core/MediaParser/Dash/DashUtil.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Dash/DashUtil.cs
rename to app/XDM/XDM.App.Core/MediaParser/Dash/DashUtil.cs
diff --git a/app/XDM/MediaParser.Hls/Dash/MpdParser.cs b/app/XDM/XDM.App.Core/MediaParser/Dash/MpdParser.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Dash/MpdParser.cs
rename to app/XDM/XDM.App.Core/MediaParser/Dash/MpdParser.cs
diff --git a/app/XDM/MediaParser.Hls/Dash/Representation.cs b/app/XDM/XDM.App.Core/MediaParser/Dash/Representation.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Dash/Representation.cs
rename to app/XDM/XDM.App.Core/MediaParser/Dash/Representation.cs
diff --git a/app/XDM/MediaParser.Hls/Hls/HlsHelper.cs b/app/XDM/XDM.App.Core/MediaParser/Hls/HlsHelper.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Hls/HlsHelper.cs
rename to app/XDM/XDM.App.Core/MediaParser/Hls/HlsHelper.cs
diff --git a/app/XDM/MediaParser.Hls/Hls/HlsMediaSegment.cs b/app/XDM/XDM.App.Core/MediaParser/Hls/HlsMediaSegment.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Hls/HlsMediaSegment.cs
rename to app/XDM/XDM.App.Core/MediaParser/Hls/HlsMediaSegment.cs
diff --git a/app/XDM/MediaParser.Hls/Hls/HlsParser.cs b/app/XDM/XDM.App.Core/MediaParser/Hls/HlsParser.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Hls/HlsParser.cs
rename to app/XDM/XDM.App.Core/MediaParser/Hls/HlsParser.cs
diff --git a/app/XDM/MediaParser.Hls/Hls/HlsPlaylist.cs b/app/XDM/XDM.App.Core/MediaParser/Hls/HlsPlaylist.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Hls/HlsPlaylist.cs
rename to app/XDM/XDM.App.Core/MediaParser/Hls/HlsPlaylist.cs
diff --git a/app/XDM/MediaParser.Hls/Hls/HlsPlaylistContainer.cs b/app/XDM/XDM.App.Core/MediaParser/Hls/HlsPlaylistContainer.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Hls/HlsPlaylistContainer.cs
rename to app/XDM/XDM.App.Core/MediaParser/Hls/HlsPlaylistContainer.cs
diff --git a/app/XDM/MediaParser.Hls/Util/UrlResolver.cs b/app/XDM/XDM.App.Core/MediaParser/Util/UrlResolver.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/Util/UrlResolver.cs
rename to app/XDM/XDM.App.Core/MediaParser/Util/UrlResolver.cs
diff --git a/app/XDM/MediaParser.Hls/YouTube/VideoFormatData.cs b/app/XDM/XDM.App.Core/MediaParser/YouTube/VideoFormatData.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/YouTube/VideoFormatData.cs
rename to app/XDM/XDM.App.Core/MediaParser/YouTube/VideoFormatData.cs
diff --git a/app/XDM/MediaParser.Hls/YouTube/YoutubeDataFormatParser.cs b/app/XDM/XDM.App.Core/MediaParser/YouTube/YoutubeDataFormatParser.cs
similarity index 100%
rename from app/XDM/MediaParser.Hls/YouTube/YoutubeDataFormatParser.cs
rename to app/XDM/XDM.App.Core/MediaParser/YouTube/YoutubeDataFormatParser.cs
diff --git a/app/XDM/NetFX.Polyfill/BlockingCollection.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/BlockingCollection.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/BlockingCollection.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/BlockingCollection.cs
diff --git a/app/XDM/NetFX.Polyfill/DictionaryExtensions.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/DictionaryExtensions.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/DictionaryExtensions.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/DictionaryExtensions.cs
diff --git a/app/XDM/NetFX.Polyfill/GroupCollectionExtension.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/GroupCollectionExtension.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/GroupCollectionExtension.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/GroupCollectionExtension.cs
diff --git a/app/XDM/NetFX.Polyfill/ProcessStartInfoHelper.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/ProcessStartInfoHelper.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/ProcessStartInfoHelper.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/ProcessStartInfoHelper.cs
diff --git a/app/XDM/NetFX.Polyfill/StreamExtension.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/StreamExtension.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/StreamExtension.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/StreamExtension.cs
diff --git a/app/XDM/NetFX.Polyfill/TupleElementNamesAttribute.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/TupleElementNamesAttribute.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/TupleElementNamesAttribute.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/TupleElementNamesAttribute.cs
diff --git a/app/XDM/NetFX.Polyfill/ValueTuplePolyfill.cs b/app/XDM/XDM.App.Core/NetFX.Polyfill/ValueTuplePolyfill.cs
similarity index 100%
rename from app/XDM/NetFX.Polyfill/ValueTuplePolyfill.cs
rename to app/XDM/XDM.App.Core/NetFX.Polyfill/ValueTuplePolyfill.cs
diff --git a/app/XDM/XDM.App.Core/TraceLog/Log.cs b/app/XDM/XDM.App.Core/TraceLog/Log.cs
new file mode 100644
index 0000000..8bc85ce
--- /dev/null
+++ b/app/XDM/XDM.App.Core/TraceLog/Log.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Diagnostics;
+
+namespace TraceLog
+{
+ public static class Log
+ {
+ public static void InitFileBasedTrace(string logfile)
+ {
+ try
+ {
+ Trace.WriteLine("Log init...");
+ //Trace.Listeners.RemoveAt(0);
+ Trace.Listeners.Add(new TextWriterTraceListener(logfile, "myListener"));
+ Trace.AutoFlush = true;
+ Trace.WriteLine("Log init...");
+ }
+ catch (Exception ex)
+ {
+ Trace.WriteLine(ex.ToString());
+ }
+ }
+
+ public static void Debug(object obj, string message)
+ {
+ Trace.WriteLine($"[xdm-{DateTime.Now.ToLongTimeString()}] {message} : {obj}");
+ //Trace.Flush();
+ }
+
+ public static void Debug(string message)
+ {
+ Trace.WriteLine($"[xdm-{DateTime.Now.ToLongTimeString()}] {message}");
+ //Trace.Flush();
+ }
+ }
+}
diff --git a/app/XDM/XDM.App.Core/Translations/ReadME.txt b/app/XDM/XDM.App.Core/Translations/ReadME.txt
new file mode 100644
index 0000000..6378e70
--- /dev/null
+++ b/app/XDM/XDM.App.Core/Translations/ReadME.txt
@@ -0,0 +1 @@
+Language files are stored in $(SOLUTION)\Lang directory
\ No newline at end of file
diff --git a/app/XDM/XDM.App.Core/Translations/TextResource.cs b/app/XDM/XDM.App.Core/Translations/TextResource.cs
new file mode 100644
index 0000000..f1c8fb7
--- /dev/null
+++ b/app/XDM/XDM.App.Core/Translations/TextResource.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Translations
+{
+ public static class TextResource
+ {
+ private static Dictionary texts = new();
+
+ static TextResource()
+ {
+ Load("English.txt");
+ }
+
+ public static void Load(string language)
+ {
+ var file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("Lang", $"{language}"));
+ if (File.Exists(file))
+ {
+ LoadTexts(file);
+ }
+ }
+
+ public static string GetText(string key)
+ {
+ if (texts.TryGetValue(key, out string? label) && label != null)
+ {
+ return label;
+ }
+ return string.Empty;
+ }
+
+ private static void LoadTexts(string path)
+ {
+ var lines = File.ReadAllLines(path);
+ foreach (var line in lines)
+ {
+ if (string.IsNullOrEmpty(line))
+ {
+ continue;
+ }
+ var index = line.IndexOf('=');
+ var key = line.Substring(0, index);
+ var val = line.Substring(index + 1);
+ texts[key] = val;
+ }
+ }
+
+ public static IEnumerable GetKeys()
+ {
+ return texts.Keys;
+ }
+ }
+}
diff --git a/app/XDM/XDM.App.Core/XDM.App.Core.projitems b/app/XDM/XDM.App.Core/XDM.App.Core.projitems
new file mode 100644
index 0000000..78310d5
--- /dev/null
+++ b/app/XDM/XDM.App.Core/XDM.App.Core.projitems
@@ -0,0 +1,196 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 5bbea202-65d2-481a-b457-6d8fcc8970d7
+
+
+ XDM.App.Core
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/XDM/XDM.App.Core/XDM.App.Core.shproj b/app/XDM/XDM.App.Core/XDM.App.Core.shproj
new file mode 100644
index 0000000..0a04caf
--- /dev/null
+++ b/app/XDM/XDM.App.Core/XDM.App.Core.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 5bbea202-65d2-481a-b457-6d8fcc8970d7
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/app/XDM/XDM.App.Core/XDM.Common.UI/BatchDownloadViewController.cs b/app/XDM/XDM.App.Core/XDM.Common.UI/BatchDownloadViewController.cs
new file mode 100644
index 0000000..7bb7603
--- /dev/null
+++ b/app/XDM/XDM.App.Core/XDM.Common.UI/BatchDownloadViewController.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using TraceLog;
+using Translations;
+using XDM.Core.Lib.Common;
+using XDM.Core.Lib.Downloader;
+using XDM.Core.Lib.Downloader.Progressive.SingleHttp;
+using XDM.Core.Lib.UI;
+
+namespace XDM.Common.UI
+{
+ public class BatchDownloadViewController
+ {
+ private IBatchDownloadView view;
+ public IAppUI AppUI { get; set; }
+ public IApp App { get; set; }
+ public int BatchSize { get; private set; } = 0;
+
+ public BatchDownloadViewController(IBatchDownloadView view, IApp app, IAppUI appUI)
+ {
+ this.view = view;
+ this.AppUI = appUI;
+ this.App = app;
+
+ var arr = new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
+ this.view.SetStartLetterRange(arr);
+ this.view.SetEndLetterRange(arr);
+ this.view.IsLetterMode = true;
+
+ this.view.PatternChanged += View_PatternChanged;
+ this.view.OkClicked += View_OkClicked;
+ }
+
+ private void View_OkClicked(object? sender, EventArgs e)
+ {
+ OnOKClicked();
+ }
+
+ private void View_PatternChanged(object? sender, EventArgs e)
+ {
+ OnBatchPatternChange();
+ }
+
+ public void Run()
+ {
+ this.view.ShowWindow();
+ }
+
+ private void OnOKClicked()
+ {
+ if (this.view.IsBatchMode)
+ {
+ var links = GenerateBatchLink()?.Select(x => (object)new SingleSourceHTTPDownloadInfo { Uri = x.ToString() });
+ if (links == null || !links.Any())
+ {
+ AppUI.ShowMessageBox(this.view, TextResource.GetText("BAT_SELECT_ITEMS"));
+ return;
+ }
+ this.view.DestroyWindow();
+ AppUI.ShowDownloadSelectionWindow(FileNameFetchMode.FileNameAndExtension, links);
+ //var dsvc = new DownloadSelectionViewController(this.view.CreateDownloadSelectionView(),
+ // App, AppUI, FileNameFetchMode.FileNameAndExtension, links);
+ //dsvc.Run();
+ //var window = new DownloadSelectionWindow(App, AppUI, Core.Lib.Downloader.FileNameFetchMode.FileNameAndExtension, links);
+ //this.Close();
+ //window.Show();
+ }
+ }
+
+ private void OnBatchPatternChange()
+ {
+ try
+ {
+ view.BatchAddress1 = view.BatchAddress2 = view.BatchAddressN = string.Empty;
+ var c = 0;
+ var last = string.Empty;
+ BatchSize = 0;
+ foreach (var url in GenerateBatchLink())
+ {
+ if (c == 0)
+ {
+ view.BatchAddress1 = url.ToString();
+ }
+ else if (c == 1)
+ {
+ view.BatchAddress2 = url.ToString();
+ }
+ last = url.ToString();
+ c++;
+ BatchSize++;
+ }
+ if (c > 1)
+ {
+ view.BatchAddressN = last;
+ }
+ }
+ catch (UriFormatException)
+ {
+ AppUI?.ShowMessageBox(this.view, TextResource.GetText("MSG_INVALID_URL"));
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, "Error");
+ }
+ }
+
+ public IEnumerable GenerateBatchLink()
+ {
+ if (!this.view.Url.Contains('*')) return Enumerable.Empty();
+ try
+ {
+ return GenerateBatchLink(this.view.Url);
+ }
+ catch (Exception ex)
+ {
+ Log.Debug(ex, "Error generating batch links");
+ return Enumerable.Empty();
+ }
+ }
+
+ private IEnumerable GenerateBatchLink(string url)
+ {
+ var list = new List();
+ if (this.view.IsLetterMode)
+ {
+ if (!(this.view.StartLetter.HasValue && this.view.EndLetter.HasValue)) throw new ArgumentException();
+ var startChar = this.view.StartLetter.Value;
+ var endChar = this.view.EndLetter.Value;
+
+ if (startChar >= endChar)
+ {
+ Log.Debug("startChar >= endChar");
+ return list;
+ }
+
+ for (var i = startChar; i <= endChar; i++)
+ {
+ list.Add(new Uri(url.Replace('*', i)));
+ }
+ }
+ else
+ {
+ var startNum = this.view.StartNumber;// ParseIntSafe(TxtNumberFrom.Text);
+ var endNum = this.view.EndNumber; //ParseIntSafe(TxtNumberTo.Text);
+
+ if (startNum >= endNum)
+ {
+ Log.Debug("startNum >= endNum");
+ return list;
+ }
+
+ for (var i = startNum; i <= endNum; i++)
+ {
+ var s = url.Replace("*",
+ this.view.IsUsingLeadingZero ? i.ToString($"D{this.view.LeadingZeroCount}") :
+ i.ToString());
+ list.Add(new Uri(s));
+ }
+ }
+ return list;
+ }
+ }
+}
diff --git a/app/XDM/XDM.Common.UI/CommonUtils.cs b/app/XDM/XDM.App.Core/XDM.Common.UI/CommonUtils.cs
similarity index 76%
rename from app/XDM/XDM.Common.UI/CommonUtils.cs
rename to app/XDM/XDM.App.Core/XDM.Common.UI/CommonUtils.cs
index 72ba29b..879adf7 100644
--- a/app/XDM/XDM.Common.UI/CommonUtils.cs
+++ b/app/XDM/XDM.App.Core/XDM.Common.UI/CommonUtils.cs
@@ -3,6 +3,7 @@ using TraceLog;
using Translations;
using XDM.Core.Lib.Common;
using XDM.Core.Lib.UI;
+using XDM.Core.Lib.Util;
namespace XDM.Common.UI
{
@@ -46,21 +47,18 @@ namespace XDM.Common.UI
internal static void OnFileBrowsed(object? sender, FileBrowsedEventArgs args)
{
- var file = Path.GetFileName(args.SelectedFile);
- var folder = Path.GetDirectoryName(args.SelectedFile)!;
- if (!Config.Instance.RecentFolders.Contains(folder))
+ var folder = args.SelectedFile;
+ if (string.IsNullOrEmpty(folder))
{
- Config.Instance.RecentFolders.Insert(0, folder);
+ return;
}
+ Helpers.UpdateRecentFolderList(folder);
if (sender != null)
{
var fileSelectable = (IFileSelectable)sender;
- fileSelectable.SelectedFileName = file;
fileSelectable.SetFolderValues(GetFolderValues());
fileSelectable.SeletedFolderIndex = 2;
}
- Config.Instance.FolderSelectionMode = FolderSelectionMode.Manual;
- Config.SaveConfig();
}
internal static void OnDropdownSelectionChanged(object? sender, FileBrowsedEventArgs args)
@@ -73,13 +71,14 @@ namespace XDM.Common.UI
{
Config.Instance.FolderSelectionMode = FolderSelectionMode.Auto;
}
- else
+ else if (!string.IsNullOrEmpty(args.SelectedFile))
{
Config.Instance.FolderSelectionMode = FolderSelectionMode.Manual;
- if (index != 1)
+ if (index > 1)
{
- Config.Instance.RecentFolders.Remove(args.SelectedFile);
- Config.Instance.RecentFolders.Insert(0, args.SelectedFile);
+ Config.Instance.UserSelectedDownloadFolder = args.SelectedFile;
+ //Config.Instance.RecentFolders.Remove(args.SelectedFile);
+ //Config.Instance.RecentFolders.Insert(0, args.SelectedFile);
}
}
Config.SaveConfig();
@@ -94,11 +93,8 @@ namespace XDM.Common.UI
Log.Debug($"Index value {index} is invalid for {Config.Instance.FolderSelectionMode}");
return null;
}
- if (index - 2 < Config.Instance.RecentFolders.Count)
- {
- return Config.Instance.RecentFolders[index - 2];
- }
- return Config.Instance.DefaultDownloadFolder;
+ return Config.Instance.RecentFolders.Count > 0 ? Config.Instance.RecentFolders[index - 2] :
+ Config.Instance.DefaultDownloadFolder;
}
}
}
diff --git a/app/XDM/XDM.Common.UI/ComponentUpdaterUI.cs b/app/XDM/XDM.App.Core/XDM.Common.UI/ComponentUpdaterUI.cs
similarity index 96%
rename from app/XDM/XDM.Common.UI/ComponentUpdaterUI.cs
rename to app/XDM/XDM.App.Core/XDM.Common.UI/ComponentUpdaterUI.cs
index 91e3281..bd19474 100644
--- a/app/XDM/XDM.Common.UI/ComponentUpdaterUI.cs
+++ b/app/XDM/XDM.App.Core/XDM.Common.UI/ComponentUpdaterUI.cs
@@ -51,7 +51,7 @@ namespace XDM.Common.UI
try
{
updaterUI.Inderminate = true;
- if (!UpdateChecker.GetAppUpdates(app.AppVerion, out IList updates, out _, this.updateMode))
+ if (!UpdateChecker.GetAppUpdates(app.AppVerion, out updates, out _, this.updateMode))
{
updaterUI.DownloadFailed(this, new DownloadFailedEventArgs(ErrorCode.Generic));
}
diff --git a/app/XDM/XDM.Common.UI/DownloadCompleteDialogHelper.cs b/app/XDM/XDM.App.Core/XDM.Common.UI/DownloadCompleteDialogHelper.cs
similarity index 55%
rename from app/XDM/XDM.Common.UI/DownloadCompleteDialogHelper.cs
rename to app/XDM/XDM.App.Core/XDM.Common.UI/DownloadCompleteDialogHelper.cs
index 414c376..3fe715d 100644
--- a/app/XDM/XDM.Common.UI/DownloadCompleteDialogHelper.cs
+++ b/app/XDM/XDM.App.Core/XDM.Common.UI/DownloadCompleteDialogHelper.cs
@@ -11,11 +11,21 @@ namespace XDM.Common.UI
dwnCmpldDlg.FolderText = folder;
dwnCmpldDlg.FileOpenClicked += (sender, args) =>
{
- Helpers.OpenFile(args.Path);
+ if (!string.IsNullOrEmpty(args.Path))
+ {
+ Helpers.OpenFile(args.Path!);
+ }
};
dwnCmpldDlg.FolderOpenClicked += (sender, args) =>
{
- Helpers.OpenFolder(args.Path, args.FileName);
+ if (!string.IsNullOrEmpty(args.Path))
+ {
+ Helpers.OpenFolder(args.Path!, args.FileName);
+ }
+ };
+ dwnCmpldDlg.DontShowAgainClickd += (sender, args) =>
+ {
+ Config.Instance.ShowDownloadCompleteWindow = false;
};
dwnCmpldDlg.ShowDownloadCompleteDialog();
}
diff --git a/app/XDM/XDM.App.Core/XDM.Common.UI/DownloadSelectionViewController.cs b/app/XDM/XDM.App.Core/XDM.Common.UI/DownloadSelectionViewController.cs
new file mode 100644
index 0000000..c13d3ea
--- /dev/null
+++ b/app/XDM/XDM.App.Core/XDM.Common.UI/DownloadSelectionViewController.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Translations;
+using XDM.Core.Lib.Common;
+using XDM.Core.Lib.Downloader;
+using XDM.Core.Lib.Downloader.Adaptive.Dash;
+using XDM.Core.Lib.Downloader.Adaptive.Hls;
+using XDM.Core.Lib.Downloader.Progressive.DualHttp;
+using XDM.Core.Lib.Downloader.Progressive.SingleHttp;
+using XDM.Core.Lib.UI;
+using XDM.Core.Lib.Util;
+
+namespace XDM.Common.UI
+{
+ public class DownloadSelectionViewController
+ {
+ private IDownloadSelectionView view;
+ private FileNameFetchMode mode;
+
+ public IAppUI AppUI { get; set; }
+ public IApp App { get; set; }
+
+ public DownloadSelectionViewController(IDownloadSelectionView view,
+ IApp app, IAppUI appUI,
+ FileNameFetchMode mode, IEnumerable