Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created February 1, 2019 23:12
Show Gist options
  • Save mjs3339/4662b4f46d32a1f9441e592d31b76d96 to your computer and use it in GitHub Desktop.
Save mjs3339/4662b4f46d32a1f9441e592d31b76d96 to your computer and use it in GitHub Desktop.
C# Pathhelper, Analyze Path Construction Without Touching Path
public static class Pathhelper
{
[Flags]
[Serializable]
public enum DeviceTypes
{
None = 0,
CDRom = 1,
InvalidCDRom = 2,
PhysicalDrive = 4,
InvalidPhysicalDrive = 8,
GUID = 16,
InvalidGUID = 32,
HDC = 64,
InvalidHDC = 128,
USB = 256,
InvalidUSB = 512,
Volume = 1024,
InvalidVolume = 2048,
Drive = 4096,
InvalidDrive = 8192
}
[Flags]
[Serializable]
public enum FSTypes
{
None = 0,
InvalidDrive = 1,
Drive = 2,
InvalidDirectory = 4,
Directory = 8,
InvalidFile = 16,
File = 32,
Device = 64,
InvalidPath = 128
}
private static readonly char[] InvalidPathChars =
{
'\"', '<', '>', '|', '\0', (char) 1, (char) 2, (char) 3, (char) 4, (char) 5,
(char) 6, (char) 7, (char) 8, (char) 9, (char) 10, (char) 11, (char) 12, (char) 13,
(char) 14, (char) 15, (char) 16, (char) 17, (char) 18, (char) 19, (char) 20,
(char) 21, (char) 22, (char) 23, (char) 24, (char) 25, (char) 26, (char) 27,
(char) 28, (char) 29, (char) 30, (char) 31, '*', '?'
};
private static readonly char[] InvalidFileChars =
{
'\"', '<', '>', '|', '\0', (char) 1, (char) 2, (char) 3, (char) 4, (char) 5,
(char) 6, (char) 7, (char) 8, (char) 9, (char) 10, (char) 11, (char) 12, (char) 13,
(char) 14, (char) 15, (char) 16, (char) 17, (char) 18, (char) 19, (char) 20,
(char) 21, (char) 22, (char) 23, (char) 24, (char) 25, (char) 26, (char) 27,
(char) 28, (char) 29, (char) 30, (char) 31, ':', '*', '?', '\\', '/'
};
public static List<string> Path_Reason = new List<string>();
public static List<string> Device_Reason = new List<string>();
public static FSTypes PathTypes {get; private set;}
public static DeviceTypes DeviceType{get; private set;}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GetVolumeNameForVolumeMountPoint(string
lpszVolumeMountPoint, [Out] StringBuilder lpszVolumeName,
int cchBufferLength);
private static string GetVolumeName(string drive)
{
var sb = new StringBuilder(1024);
if(!GetVolumeNameForVolumeMountPoint(drive, sb, sb.Capacity))
return null;
return sb.ToString();
}
private static Dictionary<string, string> GetValidMountPoints()
{
var vols = new Dictionary<string, string>();
for(var c = 'c'; c <= 'z'; c++)
{
var r = GetVolumeName(c + @":\");
if(r != null)
vols.Add(c.ToString(), r);
}
return vols;
}
private static string[] GetValidMountPointsGUIDs()
{
return GetValidMountPoints().Select(p => IsolateGuid(p.Value)).Where(s => !string.IsNullOrEmpty(s)).ToArray();
}
private static string IsolateGuid(string str)
{
var s = string.Empty;
var index = str.IndexOf("{", StringComparison.Ordinal);
if(index != -1)
{
var eindex = str.IndexOf("}", index + 1, StringComparison.Ordinal);
if(eindex != -1)
s = str.Substring(index, eindex - index + 1);
}
return s;
}
private static bool IsValidDriveChar(char value)
{
if(value >= 'A' && value <= 'Z')
return true;
return value >= 'a' && value <= 'z';
}
private static bool IsPathRooted(string path)
{
if(path == null)
return false;
var length = path.Length;
return length >= 1 && (path[0] == '\\' || path[0] == '/') || length >= 2 && path[1] == ':';
}
private static bool IsPathDevice(string path)
{
return path.Length >= 4 && path[0] == '\\' && (path[1] == '\\' || path[1] == '?') && path[2] == '?' && path[3] == '\\' || path.Length >= 4 && path[0] == '\\' && path[1] == '\\' && (path[2] == '.' || path[2] == '?') && path[3] == '\\';
}
private static void ParseDevice(string path)
{
if(path.Length == 6)
if(path[5] == ':')
{
if(IsValidDriveChar(path[4]))
DeviceType = DeviceTypes.Drive;
else
Path_Reason.Add($"Invalid drive character in Device path:{path[4]}{path[5]}");
return;
}
if(path.IndexOf("volume", StringComparison.OrdinalIgnoreCase) != -1)
{
var lid = IsolateGuid(path);
var vmp = GetValidMountPointsGUIDs();
var PathContainsValidGUID = false;
if(!string.IsNullOrEmpty(lid))
if(lid.Length == 38)
foreach(var mp in vmp)
if(mp.IndexOf(lid, StringComparison.OrdinalIgnoreCase) != -1)
{
PathContainsValidGUID = true;
break;
}
if(PathContainsValidGUID)
{
DeviceType = DeviceTypes.Volume;
}
else
{
Path_Reason.Add($"Invalid GUID in Device path GUID:{lid}");
DeviceType = DeviceTypes.InvalidVolume;
}
return;
}
if(path.IndexOf("hdc", StringComparison.OrdinalIgnoreCase) != -1)
DeviceType = DeviceTypes.HDC;
if(path.IndexOf("cdrom", StringComparison.OrdinalIgnoreCase) != -1)
DeviceType = DeviceTypes.CDRom;
if(path.IndexOf("PhysicalDrive", StringComparison.OrdinalIgnoreCase) != -1)
DeviceType = DeviceTypes.PhysicalDrive;
if(path.IndexOf("usb", StringComparison.OrdinalIgnoreCase) != -1)
DeviceType = DeviceTypes.USB;
var guid = IsolateGuid(path);
if(!string.IsNullOrEmpty(guid) && guid.Length == 38)
DeviceType = DeviceTypes.GUID;
}
public static bool ContainsDirectory(string path)
{
if(path == null)
return false;
if(!IsValidPath(path))
return false;
var pos = path.LastIndexOf('\\');
if(pos == -1 || pos + 1 > path.Length)
return false;
if(IsPathRooted(path))
{
var dcsp = path.IndexOf(':') + 1;
var dn = path.Substring(dcsp, pos + 1 - dcsp);
if(dn.Length >= 1)
return true;
}
else
{
var dn = path.Substring(0, pos + 1);
if(dn.Length >= 1)
return true;
}
return false;
}
public static bool ContainsRoot(string path)
{
if(path == null)
return false;
if(!IsValidPath(path))
return false;
return IsPathRooted(path);
}
public static bool ContainsFile(string path)
{
if(path == null)
return false;
if(!IsValidPath(path))
return false;
return GetFileName(path) != null;
}
public static string GetDirectoryName(string path)
{
if(path == null)
return null;
if(!IsValidPath(path))
return null;
var pos = path.LastIndexOf('\\');
if(pos == -1 || pos + 1 > path.Length)
return null;
return path.Substring(0, pos + 1);
}
public static string GetOnlyDirectoryName(string path)
{
if(path == null)
return null;
if(!IsValidPath(path))
return null;
if(path.Length <= 3)
return null;
var pos = path.LastIndexOf('\\');
if(pos == -1 || pos + 1 > path.Length)
return null;
if(!IsPathRooted(path))
{
if(pos != 2)
return path.Substring(0, pos + 1);
return path.Substring(0) + "\\";
}
if(pos != 2)
return path.Substring(2, pos - 1);
return path.Substring(2) + "\\";
}
private static bool IsValidPath(string path)
{
Path_Reason.Clear();
PathTypes = FSTypes.None;
DeviceType = DeviceTypes.None;
if(string.IsNullOrEmpty(path))
{
Path_Reason.Add("Path name is NULL or Empty.");
return false;
}
if(path.Trim() == string.Empty)
{
Path_Reason.Add("Path name contains only white space.");
return false;
}
if(IsPathDevice(path))
return true;
if(path.Length < 2)
{
Path_Reason.Add("Path name is to short.");
return false;
}
if(!IsValidDriveChar(path[0]))
{
Path_Reason.Add($"Path names Drive character contains invalid character:{path[0]}");
return false;
}
if(path.Length >= 3)
{
if(path[1] != ':')
{
Path_Reason.Add("Path name is missing either a volume separator.");
return false;
}
if(path[2] != '\\')
{
Path_Reason.Add("Path name is missing either a Directory separator.");
return false;
}
}
else
{
if(path.Length >= 2)
if(path[1] != ':')
{
Path_Reason.Add("Path name is missing either a volume separator.");
return false;
}
}
if(!IsPathRooted(path))
{
Path_Reason.Add("Path name is not rooted.");
return false;
}
return true;
}
private static string GetFileName(string path)
{
if(!IsValidPath(path))
return null;
if(path == null)
return null;
if(path.Length <= 3)
return null;
var length = path.Length;
for(var i = length; --i >= 0;)
{
var ch = path[i];
if(ch == '\\' || ch == '/' || ch == ':')
return path.Substring(i + 1, length - i - 1);
}
return null;
}
public static bool GetPathType(string path)
{
if(!IsValidPath(path))
{
PathTypes = FSTypes.InvalidPath;
return false;
}
if(IsPathDevice(path))
{
ParseDevice(path);
PathTypes |= FSTypes.Device;
return true;
}
if(path.Length >= 3)
if(IsValidDriveChar(path[0]))
PathTypes |= FSTypes.Drive;
var d = GetDirectoryName(path);
if(d != null)
if(d.IndexOfAny(InvalidPathChars) >= 0)
{
Path_Reason.Add($"Path name contains a directory name which contains invalid characters:'{d}'");
PathTypes |= FSTypes.InvalidDirectory;
}
else
{
PathTypes |= FSTypes.Directory;
}
var f = GetFileName(path);
if(!string.IsNullOrEmpty(f))
if(f.IndexOfAny(InvalidFileChars) >= 0)
{
Path_Reason.Add($"Path name contains a file name which contains invalid characters:'{f}'");
PathTypes |= FSTypes.InvalidFile;
}
else
{
PathTypes |= FSTypes.File;
}
if(!((PathTypes & FSTypes.InvalidDirectory) != 0 && (PathTypes & FSTypes.InvalidDrive) != 0 && (PathTypes & FSTypes.InvalidFile) != 0 && (PathTypes & FSTypes.InvalidPath) != 0))
{
Path_Reason.Add("Path name is Valid.");
return true;
}
Path_Reason.Add("Path name is InValid for an unknown reason.");
return false;
}
public static bool ContainsDrive(string path)
{
GetPathType(path);
return(PathTypes & FSTypes.Drive) != 0;
}
public static bool IsDevice(string path)
{
GetPathType(path);
return(PathTypes & FSTypes.Device) != 0;
}
public static bool IsValid(string path)
{
GetPathType(path);
return(PathTypes & FSTypes.InvalidPath) == 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment