mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Support ancient .NET in FileTypes
This commit is contained in:
@@ -94,7 +94,16 @@ namespace SabreTools.FileTypes.Archives
|
||||
var gz = new gZip();
|
||||
ZipReturn ret = gz.ZipFileOpen(this.Filename);
|
||||
ret = gz.ZipFileOpenReadStream(0, out Stream gzstream, out ulong streamSize);
|
||||
#if NET20 || NET35
|
||||
byte[] buffer = new byte[32768];
|
||||
int read;
|
||||
while ((read = gzstream.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
outstream.Write(buffer, 0, read);
|
||||
}
|
||||
#else
|
||||
gzstream.CopyTo(outstream);
|
||||
#endif
|
||||
|
||||
// Dispose of the streams
|
||||
outstream.Dispose();
|
||||
@@ -319,7 +328,9 @@ namespace SabreTools.FileTypes.Archives
|
||||
br.ReadBytes(16); // headermd5
|
||||
br.ReadBytes(4); // headercrc
|
||||
br.ReadUInt64(); // headersz
|
||||
#if NET40_OR_GREATER
|
||||
br.Dispose();
|
||||
#endif
|
||||
|
||||
// If the header is not correct, return a blank rom
|
||||
bool correct = true;
|
||||
@@ -382,7 +393,9 @@ namespace SabreTools.FileTypes.Archives
|
||||
headermd5 = br.ReadBytes(16);
|
||||
headercrc = br.ReadBytes(4);
|
||||
headersz = br.ReadUInt64();
|
||||
#if NET40_OR_GREATER
|
||||
br.Dispose();
|
||||
#endif
|
||||
|
||||
// If the header is not correct, return a blank rom
|
||||
bool correct = true;
|
||||
@@ -497,7 +510,9 @@ namespace SabreTools.FileTypes.Archives
|
||||
sw.Write((uint)(baseFile.Size ?? 0));
|
||||
|
||||
// Dispose of everything
|
||||
#if NET40_OR_GREATER
|
||||
sw.Dispose();
|
||||
#endif
|
||||
outputStream.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SabreTools.Core;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace SabreTools.FileTypes.Archives
|
||||
{
|
||||
@@ -45,6 +46,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override bool CopyAll(string outDir)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool encounteredErrors = true;
|
||||
|
||||
// If we have an invalid file
|
||||
@@ -82,6 +84,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return encounteredErrors;
|
||||
#else
|
||||
// TODO: Support RAR archives in old .NET
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -128,6 +134,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override (MemoryStream?, string?) CopyToStream(string entryName)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
MemoryStream? ms = new();
|
||||
string? realEntry = null;
|
||||
|
||||
@@ -157,6 +164,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return (ms, realEntry);
|
||||
#else
|
||||
// TODO: Support RAR archives in old .NET
|
||||
return (null, null);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -166,6 +177,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override List<BaseFile>? GetChildren()
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
// If we have an invalid file
|
||||
if (this.Filename == null)
|
||||
return null;
|
||||
@@ -211,11 +223,16 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return found;
|
||||
#else
|
||||
// TODO: Support RAR archives in old .NET
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetEmptyFolders()
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
List<string> empties = [];
|
||||
|
||||
// If we have an invalid file
|
||||
@@ -251,6 +268,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return empties;
|
||||
#else
|
||||
// TODO: Support RAR archives in old .NET
|
||||
return [];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
zr = zf.ZipFileOpenReadStream(i, out Stream readStream, out ulong streamsize);
|
||||
|
||||
// Create the rest of the path, if needed
|
||||
if (!string.IsNullOrWhiteSpace(Path.GetDirectoryName(zf.GetLocalFile(i).Filename)))
|
||||
if (!string.IsNullOrEmpty(Path.GetDirectoryName(zf.GetLocalFile(i).Filename)))
|
||||
Directory.CreateDirectory(Path.Combine(outDir, Path.GetDirectoryName(zf.GetLocalFile(i).Filename)!));
|
||||
|
||||
// If the entry ends with a directory separator, continue to the next item, if any
|
||||
@@ -492,7 +492,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(inputStream.Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -571,7 +571,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(inputStream.Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -715,7 +715,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)new FileInfo(inputFiles[index]).Length;
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -799,7 +799,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(new FileInfo(inputFiles[-index - 1]).Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Core.Tools;
|
||||
using Compress;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Writers;
|
||||
#endif
|
||||
|
||||
namespace SabreTools.FileTypes.Archives
|
||||
{
|
||||
@@ -50,6 +51,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override bool CopyAll(string outDir)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool encounteredErrors = true;
|
||||
|
||||
try
|
||||
@@ -83,6 +85,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return encounteredErrors;
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -129,6 +135,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override (MemoryStream?, string?) CopyToStream(string entryName)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
MemoryStream? ms = new();
|
||||
string? realEntry = null;
|
||||
|
||||
@@ -154,6 +161,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return (ms, realEntry);
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return (null, null);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -163,7 +174,8 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override List<BaseFile>? GetChildren()
|
||||
{
|
||||
List<BaseFile> found = new();
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
List<BaseFile> found = [];
|
||||
string? gamename = Path.GetFileNameWithoutExtension(this.Filename);
|
||||
|
||||
try
|
||||
@@ -204,12 +216,17 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return found;
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override List<string> GetEmptyFolders()
|
||||
{
|
||||
List<string> empties = new();
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
List<string> empties = [];
|
||||
|
||||
try
|
||||
{
|
||||
@@ -240,6 +257,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return empties;
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return [];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -262,6 +283,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override bool Write(Stream? inputStream, string outDir, BaseFile? baseFile)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool success = false;
|
||||
string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}");
|
||||
|
||||
@@ -291,7 +313,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
{
|
||||
// Get temporary date-time if possible
|
||||
DateTime? usableDate = null;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out DateTime dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out DateTime dt))
|
||||
usableDate = dt;
|
||||
|
||||
// Copy the input stream to the output
|
||||
@@ -340,7 +362,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
|
||||
// Get temporary date-time if possible
|
||||
DateTime? usableDate = null;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out DateTime dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out DateTime dt))
|
||||
usableDate = dt;
|
||||
|
||||
// If we have the input file, add it now
|
||||
@@ -388,11 +410,16 @@ namespace SabreTools.FileTypes.Archives
|
||||
File.Move(tempFile, archiveFileName);
|
||||
|
||||
return success;
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Write(List<string> inputFiles, string outDir, List<BaseFile>? baseFiles)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool success = false;
|
||||
string tempFile = Path.Combine(outDir, $"tmp{Guid.NewGuid()}");
|
||||
|
||||
@@ -454,7 +481,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
|
||||
// Get temporary date-time if possible
|
||||
DateTime? usableDate = null;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out DateTime dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out DateTime dt))
|
||||
usableDate = dt;
|
||||
|
||||
// Copy the input stream to the output
|
||||
@@ -512,7 +539,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
{
|
||||
// Get temporary date-time if possible
|
||||
DateTime? usableDate = null;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out DateTime dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out DateTime dt))
|
||||
usableDate = dt;
|
||||
|
||||
// Copy the input file to the output
|
||||
@@ -557,6 +584,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
File.Move(tempFile, archiveFileName);
|
||||
|
||||
return true;
|
||||
#else
|
||||
// TODO: Support tape archives in old .NET
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using SabreTools.Core;
|
||||
using SabreTools.Core.Tools;
|
||||
using SabreTools.IO;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Compressors.Xz;
|
||||
#endif
|
||||
|
||||
namespace SabreTools.FileTypes.Archives
|
||||
{
|
||||
@@ -67,6 +68,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override bool CopyAll(string outDir)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool encounteredErrors = true;
|
||||
|
||||
try
|
||||
@@ -102,6 +104,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return encounteredErrors;
|
||||
#else
|
||||
// TODO: Support XZ archives in old .NET
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -148,6 +154,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override (MemoryStream?, string?) CopyToStream(string entryName)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
MemoryStream? ms = new();
|
||||
string? realEntry;
|
||||
|
||||
@@ -178,6 +185,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return (ms, realEntry);
|
||||
#else
|
||||
// TODO: Support XZ archives in old .NET
|
||||
return (null, null);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -187,9 +198,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override List<BaseFile>? GetChildren()
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
if (_children == null || _children.Count == 0)
|
||||
{
|
||||
_children = new List<BaseFile>();
|
||||
_children = [];
|
||||
|
||||
string? gamename = Path.GetFileNameWithoutExtension(this.Filename);
|
||||
|
||||
@@ -239,6 +251,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return _children;
|
||||
#else
|
||||
// TODO: Support XZ archives in old .NET
|
||||
return [];
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -320,6 +336,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
public override bool Write(Stream? inputStream, string outDir, BaseFile? baseFile)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
bool success = false;
|
||||
|
||||
// If the stream is not readable, return
|
||||
@@ -355,6 +372,10 @@ namespace SabreTools.FileTypes.Archives
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
// TODO: Support XZ archives in old .NET
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
zr = zf.ZipFileOpenReadStream(i, false, out Stream? readStream, out ulong streamsize, out ushort cm);
|
||||
|
||||
// Create the rest of the path, if needed
|
||||
if (!string.IsNullOrWhiteSpace(Path.GetDirectoryName(zf.GetLocalFile(i).Filename)))
|
||||
if (!string.IsNullOrEmpty(Path.GetDirectoryName(zf.GetLocalFile(i).Filename)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine(outDir, Path.GetDirectoryName(zf.GetLocalFile(i).Filename)!));
|
||||
}
|
||||
@@ -450,7 +450,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(inputStream.Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -524,7 +524,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(inputStream.Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFile.Date) && DateTime.TryParse(baseFile.Date.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -666,7 +666,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(new FileInfo(inputFiles[index]).Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[index].Date) && DateTime.TryParse(baseFiles[index].Date?.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
@@ -750,7 +750,7 @@ namespace SabreTools.FileTypes.Archives
|
||||
ulong istreamSize = (ulong)(new FileInfo(inputFiles[-index - 1]).Length);
|
||||
|
||||
DateTime dt = DateTime.Now;
|
||||
if (UseDates && !string.IsNullOrWhiteSpace(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out dt))
|
||||
if (UseDates && !string.IsNullOrEmpty(baseFiles[-index - 1].Date) && DateTime.TryParse(baseFiles[-index - 1].Date?.Replace('\\', '/'), out dt))
|
||||
{
|
||||
long msDosDateTime = DateTimeHelper.ConvertToMsDosTimeFormat(dt);
|
||||
TimeStamps ts = new() { ModTime = msDosDateTime };
|
||||
|
||||
Reference in New Issue
Block a user