2023-12-23 00:11:16 -06:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO;
|
2023-01-06 22:12:03 -06:00
|
|
|
|
using System.Text.RegularExpressions;
|
2023-12-23 17:39:37 -06:00
|
|
|
|
using YamlDotNet.Core.Tokens;
|
|
|
|
|
|
using static System.Environment;
|
2024-01-07 15:31:09 -06:00
|
|
|
|
using System.Collections.Generic;
|
2023-01-06 22:12:03 -06:00
|
|
|
|
|
|
|
|
|
|
namespace LANCommander.SDK.Extensions
|
|
|
|
|
|
{
|
|
|
|
|
|
public static class StringExtensions
|
|
|
|
|
|
{
|
|
|
|
|
|
public static string SanitizeFilename(this string filename, string replacement = "")
|
|
|
|
|
|
{
|
2023-01-07 12:57:58 -06:00
|
|
|
|
var colonInTitle = new Regex(@"(\w)(: )(\w)");
|
2023-01-06 22:12:03 -06:00
|
|
|
|
var removeInvalidChars = new Regex($"[{Regex.Escape(new string(Path.GetInvalidFileNameChars()))}]", RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant);
|
|
|
|
|
|
|
2023-01-07 12:57:58 -06:00
|
|
|
|
filename = colonInTitle.Replace(filename, "$1 - $3");
|
|
|
|
|
|
filename = removeInvalidChars.Replace(filename, replacement);
|
2025-05-04 16:10:32 -05:00
|
|
|
|
|
|
|
|
|
|
if (filename.EndsWith('.'))
|
|
|
|
|
|
filename = filename.Substring(0, filename.Length - 1);
|
2023-01-07 12:57:58 -06:00
|
|
|
|
|
|
|
|
|
|
return filename;
|
2023-01-06 22:12:03 -06:00
|
|
|
|
}
|
2023-12-23 00:11:16 -06:00
|
|
|
|
|
|
|
|
|
|
internal static bool ContainsIgnoreCase(this string input, string search)
|
|
|
|
|
|
{
|
|
|
|
|
|
return input.IndexOf(search, StringComparison.OrdinalIgnoreCase) != -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-26 01:56:21 -06:00
|
|
|
|
public static string ExpandEnvironmentVariables(this string path, string installDirectory, bool skipSlashes = false)
|
2023-12-23 17:39:37 -06:00
|
|
|
|
{
|
|
|
|
|
|
path = path.Replace("{InstallDir}", installDirectory);
|
2024-01-26 01:56:21 -06:00
|
|
|
|
|
|
|
|
|
|
if (!skipSlashes)
|
|
|
|
|
|
path = path.Replace('/', Path.DirectorySeparatorChar);
|
2023-12-23 17:39:37 -06:00
|
|
|
|
|
|
|
|
|
|
SpecialFolder[] supportedSpecialFolders = new SpecialFolder[]
|
|
|
|
|
|
{
|
|
|
|
|
|
SpecialFolder.CommonApplicationData,
|
|
|
|
|
|
SpecialFolder.CommonDesktopDirectory,
|
|
|
|
|
|
SpecialFolder.CommonDocuments,
|
|
|
|
|
|
SpecialFolder.CommonMusic,
|
|
|
|
|
|
SpecialFolder.CommonPictures,
|
|
|
|
|
|
SpecialFolder.CommonPrograms,
|
|
|
|
|
|
SpecialFolder.CommonStartMenu,
|
|
|
|
|
|
SpecialFolder.CommonStartup,
|
|
|
|
|
|
SpecialFolder.CommonVideos,
|
|
|
|
|
|
SpecialFolder.Desktop,
|
|
|
|
|
|
SpecialFolder.Fonts,
|
|
|
|
|
|
SpecialFolder.MyDocuments,
|
|
|
|
|
|
SpecialFolder.MyMusic,
|
|
|
|
|
|
SpecialFolder.MyPictures,
|
|
|
|
|
|
SpecialFolder.MyVideos,
|
|
|
|
|
|
SpecialFolder.StartMenu
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
foreach (SpecialFolder folder in supportedSpecialFolders)
|
|
|
|
|
|
{
|
|
|
|
|
|
path = Regex.Replace(path, $"%{folder}%", Environment.GetFolderPath(folder));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
path = Environment.ExpandEnvironmentVariables(path);
|
|
|
|
|
|
|
2026-05-24 18:55:57 -05:00
|
|
|
|
return path.TrimEnd(Path.DirectorySeparatorChar);
|
2023-12-23 17:39:37 -06:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-26 18:06:25 -06:00
|
|
|
|
public static string DeflateEnvironmentVariables(this string path, string installDirectory)
|
2023-12-23 00:11:16 -06:00
|
|
|
|
{
|
|
|
|
|
|
path = path.Replace(installDirectory.TrimEnd(Path.DirectorySeparatorChar), "{InstallDir}");
|
|
|
|
|
|
|
2023-12-23 17:39:37 -06:00
|
|
|
|
SpecialFolder[] supportedSpecialFolders = new SpecialFolder[]
|
|
|
|
|
|
{
|
|
|
|
|
|
SpecialFolder.CommonApplicationData,
|
|
|
|
|
|
SpecialFolder.CommonDesktopDirectory,
|
|
|
|
|
|
SpecialFolder.CommonDocuments,
|
|
|
|
|
|
SpecialFolder.CommonMusic,
|
|
|
|
|
|
SpecialFolder.CommonPictures,
|
|
|
|
|
|
SpecialFolder.CommonPrograms,
|
|
|
|
|
|
SpecialFolder.CommonStartMenu,
|
|
|
|
|
|
SpecialFolder.CommonStartup,
|
|
|
|
|
|
SpecialFolder.CommonVideos,
|
|
|
|
|
|
SpecialFolder.Desktop,
|
|
|
|
|
|
SpecialFolder.Fonts,
|
|
|
|
|
|
SpecialFolder.MyDocuments,
|
|
|
|
|
|
SpecialFolder.MyMusic,
|
|
|
|
|
|
SpecialFolder.MyPictures,
|
|
|
|
|
|
SpecialFolder.MyVideos,
|
|
|
|
|
|
SpecialFolder.StartMenu
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
foreach (SpecialFolder folder in supportedSpecialFolders)
|
|
|
|
|
|
{
|
|
|
|
|
|
var value = (string)(Environment.GetFolderPath(folder));
|
|
|
|
|
|
|
|
|
|
|
|
path = Regex.Replace(path, Regex.Escape(value), $"%{folder}%", RegexOptions.IgnoreCase);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-23 00:11:16 -06:00
|
|
|
|
// These are the ones we're going to support. They are ordered in likeliness they'll be used.
|
|
|
|
|
|
// These paths get complicated, but we'll do our best.
|
|
|
|
|
|
string[] supportedVariables = new string[]
|
|
|
|
|
|
{
|
|
|
|
|
|
"TEMP",
|
|
|
|
|
|
"TMP",
|
|
|
|
|
|
"LOCALAPPDATA",
|
|
|
|
|
|
"APPDATA",
|
|
|
|
|
|
"USERPROFILE",
|
|
|
|
|
|
"PUBLIC",
|
|
|
|
|
|
"ProgramData",
|
|
|
|
|
|
"CommonProgramFiles(x86)",
|
|
|
|
|
|
"CommonProgramFiles",
|
|
|
|
|
|
"ProgramFiles(x86)",
|
|
|
|
|
|
"ProgramFiles",
|
|
|
|
|
|
"SystemRoot",
|
|
|
|
|
|
"windir",
|
|
|
|
|
|
"USERNAME",
|
|
|
|
|
|
"SystemDrive"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var variable in supportedVariables)
|
|
|
|
|
|
{
|
|
|
|
|
|
var value = (string)(Environment.GetEnvironmentVariable(variable));
|
|
|
|
|
|
|
|
|
|
|
|
path = Regex.Replace(path, Regex.Escape(value), $"%{variable}%", RegexOptions.IgnoreCase);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
|
}
|
2025-03-10 21:44:51 -05:00
|
|
|
|
|
|
|
|
|
|
public static string FastReverse(this string input)
|
|
|
|
|
|
{
|
|
|
|
|
|
return string.Create(input.Length, input, (chars, state) => {
|
|
|
|
|
|
var pos = 0;
|
|
|
|
|
|
for (int i = state.Length -1 ; i >=0 ; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
chars[pos++] = state[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2023-01-06 22:12:03 -06:00
|
|
|
|
}
|
|
|
|
|
|
}
|