mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Moved some environment version detections to Interop.
This commit is contained in:
@@ -62,19 +62,12 @@ namespace DiscImageChef.Core.Logging
|
|||||||
|
|
||||||
PlatformID platId = DetectOS.GetRealPlatformID();
|
PlatformID platId = DetectOS.GetRealPlatformID();
|
||||||
string platVer = DetectOS.GetVersion();
|
string platVer = DetectOS.GetVersion();
|
||||||
Type monoRunType = Type.GetType("Mono.Runtime");
|
|
||||||
|
|
||||||
logSw.WriteLine("################# System information #################");
|
logSw.WriteLine("################# System information #################");
|
||||||
logSw.WriteLine("{0} {1} ({2}-bit)", DetectOS.GetPlatformName(platId, platVer), platVer,
|
logSw.WriteLine("{0} {1} ({2}-bit)", DetectOS.GetPlatformName(platId, platVer), platVer,
|
||||||
Environment.Is64BitOperatingSystem ? 64 : 32);
|
Environment.Is64BitOperatingSystem ? 64 : 32);
|
||||||
if(monoRunType != null)
|
if(DetectOS.IsMono)
|
||||||
{
|
logSw.WriteLine("Mono {0}", Version.GetMonoVersion());
|
||||||
string monoVer = "unknown version";
|
|
||||||
MethodInfo monoDisplayName =
|
|
||||||
monoRunType.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
|
||||||
if(monoDisplayName != null) monoVer = (string)monoDisplayName.Invoke(null, null);
|
|
||||||
logSw.WriteLine("Mono {0}", monoVer);
|
|
||||||
}
|
|
||||||
else logSw.WriteLine(".NET Framework {0}", Environment.Version);
|
else logSw.WriteLine(".NET Framework {0}", Environment.Version);
|
||||||
|
|
||||||
logSw.WriteLine();
|
logSw.WriteLine();
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ namespace DiscImageChef.Devices.Linux
|
|||||||
IntPtr buf = Marshal.AllocHGlobal(4096);
|
IntPtr buf = Marshal.AllocHGlobal(4096);
|
||||||
int resultSize;
|
int resultSize;
|
||||||
|
|
||||||
if(DetectOS.Is64Bit())
|
if(DetectOS.Is64Bit)
|
||||||
{
|
{
|
||||||
long result64 = Extern.readlink64(path, buf, 4096);
|
long result64 = Extern.readlink64(path, buf, 4096);
|
||||||
if(result64 <= 0) return null;
|
if(result64 <= 0) return null;
|
||||||
|
|||||||
@@ -45,6 +45,18 @@ namespace DiscImageChef.Interop
|
|||||||
{
|
{
|
||||||
public static class DetectOS
|
public static class DetectOS
|
||||||
{
|
{
|
||||||
|
public static readonly bool IsMono = Type.GetType("Mono.Runtime") != null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the underlying runtime runs in 64-bit mode
|
||||||
|
/// </summary>
|
||||||
|
public static readonly bool Is64Bit = IntPtr.Size == 8;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the underlying runtime runs in 32-bit mode
|
||||||
|
/// </summary>
|
||||||
|
public static readonly bool Is32Bit = IntPtr.Size == 4;
|
||||||
|
|
||||||
[DllImport("libc", SetLastError = true)]
|
[DllImport("libc", SetLastError = true)]
|
||||||
static extern int uname(out utsname name);
|
static extern int uname(out utsname name);
|
||||||
|
|
||||||
@@ -69,11 +81,11 @@ namespace DiscImageChef.Interop
|
|||||||
// TODO: Differentiate Linux, Android, Tizen
|
// TODO: Differentiate Linux, Android, Tizen
|
||||||
case "Linux":
|
case "Linux":
|
||||||
{
|
{
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
return PlatformID.Android;
|
return PlatformID.Android;
|
||||||
#else
|
#else
|
||||||
return PlatformID.Linux;
|
return PlatformID.Linux;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
case "Darwin":
|
case "Darwin":
|
||||||
{
|
{
|
||||||
@@ -88,8 +100,8 @@ namespace DiscImageChef.Interop
|
|||||||
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
|
throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
int length = Marshal.ReadInt32(pLen);
|
int length = Marshal.ReadInt32(pLen);
|
||||||
IntPtr pStr = Marshal.AllocHGlobal(length);
|
IntPtr pStr = Marshal.AllocHGlobal(length);
|
||||||
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
|
osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0);
|
||||||
if(osxError != 0)
|
if(osxError != 0)
|
||||||
{
|
{
|
||||||
@@ -104,8 +116,8 @@ namespace DiscImageChef.Interop
|
|||||||
Marshal.FreeHGlobal(pStr);
|
Marshal.FreeHGlobal(pStr);
|
||||||
Marshal.FreeHGlobal(pLen);
|
Marshal.FreeHGlobal(pLen);
|
||||||
|
|
||||||
if(machine != null && (machine.StartsWith("iPad", StringComparison.Ordinal) ||
|
if(machine != null && (machine.StartsWith("iPad", StringComparison.Ordinal) ||
|
||||||
machine.StartsWith("iPod", StringComparison.Ordinal) ||
|
machine.StartsWith("iPod", StringComparison.Ordinal) ||
|
||||||
machine.StartsWith("iPhone", StringComparison.Ordinal)))
|
machine.StartsWith("iPhone", StringComparison.Ordinal)))
|
||||||
return PlatformID.iOS;
|
return PlatformID.iOS;
|
||||||
|
|
||||||
@@ -115,53 +127,37 @@ namespace DiscImageChef.Interop
|
|||||||
case "FreeBSD":
|
case "FreeBSD":
|
||||||
case "GNU/kFreeBSD": return PlatformID.FreeBSD;
|
case "GNU/kFreeBSD": return PlatformID.FreeBSD;
|
||||||
case "DragonFly": return PlatformID.DragonFly;
|
case "DragonFly": return PlatformID.DragonFly;
|
||||||
case "Haiku": return PlatformID.Haiku;
|
case "Haiku": return PlatformID.Haiku;
|
||||||
case "HP-UX": return PlatformID.HPUX;
|
case "HP-UX": return PlatformID.HPUX;
|
||||||
case "AIX": return PlatformID.AIX;
|
case "AIX": return PlatformID.AIX;
|
||||||
case "OS400": return PlatformID.OS400;
|
case "OS400": return PlatformID.OS400;
|
||||||
case "IRIX":
|
case "IRIX":
|
||||||
case "IRIX64": return PlatformID.IRIX;
|
case "IRIX64": return PlatformID.IRIX;
|
||||||
case "Minix": return PlatformID.Minix;
|
case "Minix": return PlatformID.Minix;
|
||||||
case "NetBSD": return PlatformID.NetBSD;
|
case "NetBSD": return PlatformID.NetBSD;
|
||||||
case "NONSTOP_KERNEL": return PlatformID.NonStop;
|
case "NONSTOP_KERNEL": return PlatformID.NonStop;
|
||||||
case "OpenBSD": return PlatformID.OpenBSD;
|
case "OpenBSD": return PlatformID.OpenBSD;
|
||||||
case "QNX": return PlatformID.QNX;
|
case "QNX": return PlatformID.QNX;
|
||||||
case "SINIX-Y": return PlatformID.SINIX;
|
case "SINIX-Y": return PlatformID.SINIX;
|
||||||
case "SunOS": return PlatformID.Solaris;
|
case "SunOS": return PlatformID.Solaris;
|
||||||
case "OSF1": return PlatformID.Tru64;
|
case "OSF1": return PlatformID.Tru64;
|
||||||
case "ULTRIX": return PlatformID.Ultrix;
|
case "ULTRIX": return PlatformID.Ultrix;
|
||||||
case "SCO_SV": return PlatformID.OpenServer;
|
case "SCO_SV": return PlatformID.OpenServer;
|
||||||
case "UnixWare": return PlatformID.UnixWare;
|
case "UnixWare": return PlatformID.UnixWare;
|
||||||
case "Interix":
|
case "Interix":
|
||||||
case "UWIN-W7": return PlatformID.Win32NT;
|
case "UWIN-W7": return PlatformID.Win32NT;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
|
if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) ||
|
||||||
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
|
unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) ||
|
||||||
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
|
unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) ||
|
||||||
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal)) return PlatformID.Win32NT;
|
unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal)) return PlatformID.Win32NT;
|
||||||
|
|
||||||
return PlatformID.Unknown;
|
return PlatformID.Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the underlying runtime runs in 64-bit mode
|
|
||||||
/// </summary>
|
|
||||||
public static bool Is64Bit()
|
|
||||||
{
|
|
||||||
return IntPtr.Size == 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the underlying runtime runs in 32-bit mode
|
|
||||||
/// </summary>
|
|
||||||
public static bool Is32Bit()
|
|
||||||
{
|
|
||||||
return IntPtr.Size == 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)
|
/// Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -188,8 +184,8 @@ namespace DiscImageChef.Interop
|
|||||||
if(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2 ||
|
if(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2 ||
|
||||||
Environment.OSVersion.Version.Major > 6)
|
Environment.OSVersion.Version.Major > 6)
|
||||||
return FileVersionInfo
|
return FileVersionInfo
|
||||||
.GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
|
.GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
|
||||||
"KERNEL32.DLL")).ProductVersion;
|
"KERNEL32.DLL")).ProductVersion;
|
||||||
|
|
||||||
return environ;
|
return environ;
|
||||||
default: return environ;
|
default: return environ;
|
||||||
@@ -206,16 +202,16 @@ namespace DiscImageChef.Interop
|
|||||||
{
|
{
|
||||||
switch(id)
|
switch(id)
|
||||||
{
|
{
|
||||||
case PlatformID.AIX: return "AIX";
|
case PlatformID.AIX: return "AIX";
|
||||||
case PlatformID.Android: return "Android";
|
case PlatformID.Android: return "Android";
|
||||||
case PlatformID.DragonFly: return "DragonFly BSD";
|
case PlatformID.DragonFly: return "DragonFly BSD";
|
||||||
case PlatformID.FreeBSD: return "FreeBSD";
|
case PlatformID.FreeBSD: return "FreeBSD";
|
||||||
case PlatformID.Haiku: return "Haiku";
|
case PlatformID.Haiku: return "Haiku";
|
||||||
case PlatformID.HPUX: return "HP/UX";
|
case PlatformID.HPUX: return "HP/UX";
|
||||||
case PlatformID.Hurd: return "Hurd";
|
case PlatformID.Hurd: return "Hurd";
|
||||||
case PlatformID.iOS: return "iOS";
|
case PlatformID.iOS: return "iOS";
|
||||||
case PlatformID.IRIX: return "IRIX";
|
case PlatformID.IRIX: return "IRIX";
|
||||||
case PlatformID.Linux: return "Linux";
|
case PlatformID.Linux: return "Linux";
|
||||||
case PlatformID.MacOSX:
|
case PlatformID.MacOSX:
|
||||||
if(string.IsNullOrEmpty(version)) return "macOS";
|
if(string.IsNullOrEmpty(version)) return "macOS";
|
||||||
|
|
||||||
@@ -227,52 +223,52 @@ namespace DiscImageChef.Interop
|
|||||||
|
|
||||||
return "Mac OS X";
|
return "Mac OS X";
|
||||||
|
|
||||||
case PlatformID.Minix: return "MINIX";
|
case PlatformID.Minix: return "MINIX";
|
||||||
case PlatformID.NetBSD: return "NetBSD";
|
case PlatformID.NetBSD: return "NetBSD";
|
||||||
case PlatformID.NonStop: return "NonStop OS";
|
case PlatformID.NonStop: return "NonStop OS";
|
||||||
case PlatformID.OpenBSD: return "OpenBSD";
|
case PlatformID.OpenBSD: return "OpenBSD";
|
||||||
case PlatformID.OpenServer: return "SCO OpenServer";
|
case PlatformID.OpenServer: return "SCO OpenServer";
|
||||||
case PlatformID.OS400: return "OS/400";
|
case PlatformID.OS400: return "OS/400";
|
||||||
case PlatformID.PlayStation3: return "Sony CellOS";
|
case PlatformID.PlayStation3: return "Sony CellOS";
|
||||||
case PlatformID.PlayStation4: return "Sony Orbis OS";
|
case PlatformID.PlayStation4: return "Sony Orbis OS";
|
||||||
case PlatformID.QNX: return "QNX";
|
case PlatformID.QNX: return "QNX";
|
||||||
case PlatformID.SINIX: return "SINIX";
|
case PlatformID.SINIX: return "SINIX";
|
||||||
case PlatformID.Solaris: return "Sun Solaris";
|
case PlatformID.Solaris: return "Sun Solaris";
|
||||||
case PlatformID.Tizen: return "Samsung Tizen";
|
case PlatformID.Tizen: return "Samsung Tizen";
|
||||||
case PlatformID.Tru64: return "Tru64 UNIX";
|
case PlatformID.Tru64: return "Tru64 UNIX";
|
||||||
case PlatformID.Ultrix: return "Ultrix";
|
case PlatformID.Ultrix: return "Ultrix";
|
||||||
case PlatformID.Unix: return "UNIX";
|
case PlatformID.Unix: return "UNIX";
|
||||||
case PlatformID.UnixWare: return "SCO UnixWare";
|
case PlatformID.UnixWare: return "SCO UnixWare";
|
||||||
case PlatformID.Wii: return "Nintendo Wii";
|
case PlatformID.Wii: return "Nintendo Wii";
|
||||||
case PlatformID.WiiU: return "Nintendo Wii U";
|
case PlatformID.WiiU: return "Nintendo Wii U";
|
||||||
case PlatformID.Win32NT:
|
case PlatformID.Win32NT:
|
||||||
if(string.IsNullOrEmpty(version)) return "Windows NT/2000/XP/Vista/7/10";
|
if(string.IsNullOrEmpty(version)) return "Windows NT/2000/XP/Vista/7/10";
|
||||||
if(version.StartsWith("3.", StringComparison.Ordinal) ||
|
if(version.StartsWith("3.", StringComparison.Ordinal) ||
|
||||||
version.StartsWith("4.", StringComparison.Ordinal)) return "Windows NT";
|
version.StartsWith("4.", StringComparison.Ordinal)) return "Windows NT";
|
||||||
if(version.StartsWith("5.0", StringComparison.Ordinal)) return "Windows 2000";
|
if(version.StartsWith("5.0", StringComparison.Ordinal)) return "Windows 2000";
|
||||||
if(version.StartsWith("5.1", StringComparison.Ordinal)) return "Windows XP";
|
if(version.StartsWith("5.1", StringComparison.Ordinal)) return "Windows XP";
|
||||||
if(version.StartsWith("5.2", StringComparison.Ordinal)) return "Windows 2003";
|
if(version.StartsWith("5.2", StringComparison.Ordinal)) return "Windows 2003";
|
||||||
if(version.StartsWith("6.0", StringComparison.Ordinal)) return "Windows Vista";
|
if(version.StartsWith("6.0", StringComparison.Ordinal)) return "Windows Vista";
|
||||||
if(version.StartsWith("6.1", StringComparison.Ordinal)) return "Windows 7";
|
if(version.StartsWith("6.1", StringComparison.Ordinal)) return "Windows 7";
|
||||||
if(version.StartsWith("6.2", StringComparison.Ordinal)) return "Windows 8";
|
if(version.StartsWith("6.2", StringComparison.Ordinal)) return "Windows 8";
|
||||||
if(version.StartsWith("6.3", StringComparison.Ordinal)) return "Windows 8.1";
|
if(version.StartsWith("6.3", StringComparison.Ordinal)) return "Windows 8.1";
|
||||||
if(version.StartsWith("10.0", StringComparison.Ordinal)) return "Windows 10";
|
if(version.StartsWith("10.0", StringComparison.Ordinal)) return "Windows 10";
|
||||||
|
|
||||||
return "Windows NT/2000/XP/Vista/7/10";
|
return "Windows NT/2000/XP/Vista/7/10";
|
||||||
case PlatformID.Win32S: return "Windows 3.x with win32s";
|
case PlatformID.Win32S: return "Windows 3.x with win32s";
|
||||||
case PlatformID.Win32Windows:
|
case PlatformID.Win32Windows:
|
||||||
if(string.IsNullOrEmpty(version)) return "Windows 9x/Me";
|
if(string.IsNullOrEmpty(version)) return "Windows 9x/Me";
|
||||||
if(version.StartsWith("4.0", StringComparison.Ordinal)) return "Windows 95";
|
if(version.StartsWith("4.0", StringComparison.Ordinal)) return "Windows 95";
|
||||||
if(version.StartsWith("4.10.2222", StringComparison.Ordinal)) return "Windows 98 SE";
|
if(version.StartsWith("4.10.2222", StringComparison.Ordinal)) return "Windows 98 SE";
|
||||||
if(version.StartsWith("4.1", StringComparison.Ordinal)) return "Windows 98";
|
if(version.StartsWith("4.1", StringComparison.Ordinal)) return "Windows 98";
|
||||||
if(version.StartsWith("4.9", StringComparison.Ordinal)) return "Windows Me";
|
if(version.StartsWith("4.9", StringComparison.Ordinal)) return "Windows Me";
|
||||||
|
|
||||||
return "Windows 9x/Me";
|
return "Windows 9x/Me";
|
||||||
case PlatformID.WinCE: return "Windows CE/Mobile";
|
case PlatformID.WinCE: return "Windows CE/Mobile";
|
||||||
case PlatformID.WindowsPhone: return "Windows Phone";
|
case PlatformID.WindowsPhone: return "Windows Phone";
|
||||||
case PlatformID.Xbox: return "Xbox OS";
|
case PlatformID.Xbox: return "Xbox OS";
|
||||||
case PlatformID.zOS: return "z/OS";
|
case PlatformID.zOS: return "z/OS";
|
||||||
default: return id.ToString();
|
default: return id.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,23 +281,28 @@ namespace DiscImageChef.Interop
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// System name
|
/// System name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string sysname;
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string sysname;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Node name
|
/// Node name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string nodename;
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string nodename;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Release level
|
/// Release level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string release;
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string release;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version level
|
/// Version level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string version;
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string version;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hardware level
|
/// Hardware level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string machine;
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||||
|
public string machine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,10 @@
|
|||||||
// Copyright © 2011-2018 Natalia Portillo
|
// Copyright © 2011-2018 Natalia Portillo
|
||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime;
|
||||||
|
|
||||||
namespace DiscImageChef.Interop
|
namespace DiscImageChef.Interop
|
||||||
{
|
{
|
||||||
public static class Version
|
public static class Version
|
||||||
@@ -48,5 +52,28 @@ namespace DiscImageChef.Interop
|
|||||||
{
|
{
|
||||||
return typeof(Version).Assembly.GetName().Version.ToString();
|
return typeof(Version).Assembly.GetName().Version.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetNetCoreVersion()
|
||||||
|
{
|
||||||
|
Assembly assembly = typeof(GCSettings).Assembly;
|
||||||
|
string[] assemblyPath =
|
||||||
|
assembly.CodeBase.Split(new[] {'/', '\\'}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
|
||||||
|
if(netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
|
||||||
|
return assemblyPath[netCoreAppIndex + 1];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetMonoVersion()
|
||||||
|
{
|
||||||
|
if(!DetectOS.IsMono) return null;
|
||||||
|
|
||||||
|
MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")
|
||||||
|
?.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
|
if(monoDisplayName != null) return (string)monoDisplayName.Invoke(null, null);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user