using System.Text;
namespace Daybreak.Shared.Utils;
///
/// Helpers for producing Windows compatible computer names.
///
public static class ComputerNameUtils
{
///
/// Maximum length of a Windows NetBIOS computer name, matching the Win32 MAX_COMPUTERNAME_LENGTH constant.
///
public const int MaxComputerNameLength = 15;
///
/// Name used when no valid computer name can be derived from the host.
///
public const string FallbackComputerName = "DAYBREAK";
///
/// Converts an arbitrary host name into a name that Win32 GetComputerName can return.
///
///
/// GetComputerNameW is documented to fill a buffer of MAX_COMPUTERNAME_LENGTH + 1 characters, so callers
/// size their buffers accordingly. When the configured name is longer, the call fails with
/// ERROR_BUFFER_OVERFLOW and leaves the caller's buffer untouched, which applications such as GWToolbox
/// observe as an empty computer name. Wine's own wineboot upper-cases and truncates the Linux host name
/// for the same reason, so this method reproduces that behaviour.
///
/// The host name to sanitize.
/// An upper-case, at most characters long, non-empty computer name.
public static string SanitizeComputerName(string? name)
{
if (name is null)
{
return FallbackComputerName;
}
var builder = new StringBuilder(MaxComputerNameLength);
foreach (var c in name)
{
if (builder.Length >= MaxComputerNameLength)
{
break;
}
if (char.IsAsciiLetterOrDigit(c))
{
builder.Append(char.ToUpperInvariant(c));
}
else if (c is '-' or '_')
{
builder.Append(c);
}
}
// A computer name may not start or end with a separator.
while (builder.Length > 0 && builder[^1] is '-' or '_')
{
builder.Length--;
}
var sanitized = builder.ToString().TrimStart('-', '_');
return sanitized.Length is 0 ? FallbackComputerName : sanitized;
}
}