Skip to content

Commit 3de87a7

Browse files
Enhance FileNameFriendly with comprehensive character sanitization
- Use Path.GetInvalidFileNameChars() for comprehensive sanitization - Now handles all invalid filename characters including IPv6 brackets - Improved XML documentation with explicit character list - Added edge case tests for IPv6 and IPv4 with ports - Enhanced existing tests to verify no invalid characters remain Implements code review recommendations from PR #31 Co-authored-by: Chrissy LeMaire <[email protected]>
1 parent 10b6070 commit 3de87a7

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

project/dbatools.Tests/Parameter/DbaInstanceParamaterTest.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,48 @@ public void TestFileNameFriendly()
273273
var regular = new DbaInstanceParameter("server\\instance");
274274
Assert.AreEqual("server_instance", regular.FileNameFriendly);
275275
Assert.IsFalse(regular.FileNameFriendly.Contains("\\"));
276+
277+
// Test that all results contain no invalid filename characters
278+
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
279+
Assert.IsFalse(npDot.FileNameFriendly.IndexOfAny(invalidChars) >= 0);
280+
Assert.IsFalse(npDotInstance.FileNameFriendly.IndexOfAny(invalidChars) >= 0);
281+
Assert.IsFalse(tcpInstance.FileNameFriendly.IndexOfAny(invalidChars) >= 0);
282+
Assert.IsFalse(withPort.FileNameFriendly.IndexOfAny(invalidChars) >= 0);
283+
Assert.IsFalse(regular.FileNameFriendly.IndexOfAny(invalidChars) >= 0);
284+
}
285+
286+
/// <summary>
287+
/// Tests that FileNameFriendly handles edge cases including IPv6 addresses
288+
/// </summary>
289+
[TestMethod]
290+
public void TestFileNameFriendlyEdgeCases()
291+
{
292+
// Test with IPv6 address (contains colons and brackets)
293+
var ipv6 = new DbaInstanceParameter("::1");
294+
var invalidChars = System.IO.Path.GetInvalidFileNameChars();
295+
Assert.IsFalse(ipv6.FileNameFriendly.IndexOfAny(invalidChars) >= 0,
296+
"IPv6 address FileNameFriendly should not contain invalid filename characters");
297+
298+
// Test with IPv6 address and port
299+
var ipv6Port = new DbaInstanceParameter("[::1]:1433");
300+
Assert.IsFalse(ipv6Port.FileNameFriendly.IndexOfAny(invalidChars) >= 0,
301+
"IPv6 with port FileNameFriendly should not contain invalid filename characters");
302+
303+
// Test with regular IPv6 address
304+
var ipv6Full = new DbaInstanceParameter("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
305+
Assert.IsFalse(ipv6Full.FileNameFriendly.IndexOfAny(invalidChars) >= 0,
306+
"Full IPv6 address FileNameFriendly should not contain invalid filename characters");
307+
308+
// Test with IPv4 address and port (contains colon)
309+
var ipv4Port = new DbaInstanceParameter("192.168.1.1:1433");
310+
Assert.IsFalse(ipv4Port.FileNameFriendly.IndexOfAny(invalidChars) >= 0,
311+
"IPv4 with port FileNameFriendly should not contain invalid filename characters");
312+
313+
// Test that the results are not empty
314+
Assert.IsFalse(string.IsNullOrWhiteSpace(ipv6.FileNameFriendly));
315+
Assert.IsFalse(string.IsNullOrWhiteSpace(ipv6Port.FileNameFriendly));
316+
Assert.IsFalse(string.IsNullOrWhiteSpace(ipv6Full.FileNameFriendly));
317+
Assert.IsFalse(string.IsNullOrWhiteSpace(ipv4Port.FileNameFriendly));
276318
}
277319
}
278320
}

project/dbatools/Parameter/DbaInstanceParameter.cs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.IO;
3+
using System.Linq;
24
using System.Management.Automation;
35
using System.Net;
46
using System.Net.NetworkInformation;
@@ -119,7 +121,9 @@ public string FullSmoName
119121
}
120122

121123
/// <summary>
122-
/// Full name of the instance sanitized for use in file names, replacing invalid characters
124+
/// Full name of the instance sanitized for use in file names.
125+
/// Replaces all Windows invalid filename characters (including : \ / | ? * " &lt; &gt;) with underscores.
126+
/// Safe to use as part of a filename or path component.
123127
/// </summary>
124128
[ParameterContract(ParameterContractType.Field, ParameterContractBehavior.Mandatory)]
125129
public string FileNameFriendly
@@ -129,10 +133,33 @@ public string FileNameFriendly
129133
string temp = _ComputerName;
130134
if (_NetworkProtocol == SqlConnectionProtocol.NP) { temp = "NP_" + temp; }
131135
if (_NetworkProtocol == SqlConnectionProtocol.TCP) { temp = "TCP_" + temp; }
132-
if (!String.IsNullOrEmpty(_InstanceName) && _Port > 0) { return String.Format(@"{0}_{1}_{2}", temp, _InstanceName, _Port); }
133-
if (_Port > 0) { return temp + "_" + _Port; }
134-
if (!String.IsNullOrEmpty(_InstanceName)) { return temp + "_" + _InstanceName; }
135-
return temp;
136+
137+
string result;
138+
if (!String.IsNullOrEmpty(_InstanceName) && _Port > 0)
139+
{
140+
result = String.Format(@"{0}_{1}_{2}", temp, _InstanceName, _Port);
141+
}
142+
else if (_Port > 0)
143+
{
144+
result = temp + "_" + _Port;
145+
}
146+
else if (!String.IsNullOrEmpty(_InstanceName))
147+
{
148+
result = temp + "_" + _InstanceName;
149+
}
150+
else
151+
{
152+
result = temp;
153+
}
154+
155+
// Sanitize any remaining invalid filename characters
156+
char[] invalidChars = Path.GetInvalidFileNameChars();
157+
foreach (char c in invalidChars)
158+
{
159+
result = result.Replace(c, '_');
160+
}
161+
162+
return result;
136163
}
137164
}
138165

0 commit comments

Comments
 (0)