-
Notifications
You must be signed in to change notification settings - Fork 261
/
Copy pathPathVerifier.cs
167 lines (140 loc) · 5.14 KB
/
PathVerifier.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
using System.Linq;
namespace System.IO.Abstractions.TestingHelpers;
using XFS = MockUnixSupport;
/// <summary>
/// Provides helper methods for verifying paths.
/// </summary>
#if FEATURE_SERIALIZABLE
[Serializable]
#endif
public class PathVerifier
{
private static readonly char[] AdditionalInvalidPathChars = { '*', '?' };
private readonly IMockFileDataAccessor _mockFileDataAccessor;
/// <summary>
/// Creates a new verifier instance.
/// </summary>
public PathVerifier(IMockFileDataAccessor mockFileDataAccessor)
{
_mockFileDataAccessor = mockFileDataAccessor ?? throw new ArgumentNullException(nameof(mockFileDataAccessor));
}
/// <summary>
/// Determines whether the given path is legal.
/// </summary>
public void IsLegalAbsoluteOrRelative(string path, string paramName)
{
if (path == null)
{
throw new ArgumentNullException(paramName, StringResources.Manager.GetString("VALUE_CANNOT_BE_NULL"));
}
if (path == string.Empty)
{
throw new ArgumentException("Empty file name is not legal.", paramName);
}
if (path.Trim() == string.Empty)
{
throw CommonExceptions.PathIsNotOfALegalForm(paramName);
}
if (XFS.IsWindowsPlatform() && !IsValidUseOfVolumeSeparatorChar(path))
{
throw CommonExceptions.InvalidUseOfVolumeSeparator();
}
if (ExtractFileName(path).IndexOfAny(_mockFileDataAccessor.Path.GetInvalidFileNameChars()) > -1)
{
throw CommonExceptions.IllegalCharactersInPath();
}
var filePath = ExtractFilePath(path);
if (HasIllegalCharacters(filePath, checkAdditional: false))
{
throw CommonExceptions.IllegalCharactersInPath();
}
}
private static bool IsValidUseOfVolumeSeparatorChar(string path)
{
var lastVolSepIndex = path.LastIndexOf(Path.VolumeSeparatorChar);
return lastVolSepIndex == -1 || lastVolSepIndex == 1 && char.IsLetter(path[0]);
}
private string ExtractFileName(string fullFileName)
{
return fullFileName.Split(
_mockFileDataAccessor.Path.DirectorySeparatorChar,
_mockFileDataAccessor.Path.AltDirectorySeparatorChar).Last();
}
private string ExtractFilePath(string fullFileName)
{
var extractFilePath = fullFileName.Split(
_mockFileDataAccessor.Path.DirectorySeparatorChar,
_mockFileDataAccessor.Path.AltDirectorySeparatorChar);
return string.Join(_mockFileDataAccessor.Path.DirectorySeparatorChar.ToString(), extractFilePath.Take(extractFilePath.Length - 1));
}
/// <summary>
/// Determines whether the given path contains illegal characters.
/// </summary>
public bool HasIllegalCharacters(string path, bool checkAdditional)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
var invalidPathChars = _mockFileDataAccessor.Path.GetInvalidPathChars();
if (checkAdditional)
{
return path.IndexOfAny(invalidPathChars.Concat(AdditionalInvalidPathChars).ToArray()) >= 0;
}
return path.IndexOfAny(invalidPathChars) >= 0;
}
/// <summary>
/// Throws an excpetion if the given path contains invalid characters.
/// </summary>
public void CheckInvalidPathChars(string path, bool checkAdditional = false)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
if (HasIllegalCharacters(path, checkAdditional))
{
throw CommonExceptions.IllegalCharactersInPath();
}
}
/// <summary>
/// Determines the normalized drive name used for drive identification.
/// </summary>
/// <exception cref="ArgumentException">Thrown if the <paramref name="name"/> is not a valid drive name.</exception>
public string NormalizeDriveName(string name)
{
return TryNormalizeDriveName(name, out var result)
? result
: throw new ArgumentException(
@"Object must be a root directory (""C:\"") or a drive letter (""C"").");
}
/// <summary>
/// Tries to determine the normalized drive name used for drive identification.
/// </summary>
public bool TryNormalizeDriveName(string name, out string result)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
const string DRIVE_SEPARATOR = @":\";
if (name.Length == 1
|| (name.Length == 2 && name[1] == ':')
|| (name.Length == 3 && _mockFileDataAccessor.StringOperations.EndsWith(name, DRIVE_SEPARATOR)))
{
name = name[0] + DRIVE_SEPARATOR;
}
else
{
CheckInvalidPathChars(name);
name = _mockFileDataAccessor.Path.GetPathRoot(name);
if (string.IsNullOrEmpty(name) || _mockFileDataAccessor.StringOperations.StartsWith(name, @"\\"))
{
result = null;
return false;
}
}
result = name;
return true;
}
}