Skip to content

Commit 3720946

Browse files
committed
Chore: Minor refactoring
1 parent 620315e commit 3720946

File tree

5 files changed

+106
-152
lines changed

5 files changed

+106
-152
lines changed

Source/NETworkManager.Profiles/ProfileManager.cs

Lines changed: 10 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -197,17 +197,21 @@ private static void ProfilesUpdated(bool profilesChanged = true)
197197

198198
/// <summary>
199199
/// Method to get the path of the profiles folder.
200-
/// Priority: 1. Policy override, 2. Custom user path (from SettingsInfo), 3. Portable/default.
200+
/// Priority:
201+
/// 1. Policy override (for IT administrators)
202+
/// 2. Custom user-configured path (not available in portable mode)
203+
/// 3. Portable (same directory as the application) or default location (Documents folder)
201204
/// </summary>
202205
/// <returns>Path to the profiles folder.</returns>
203206
public static string GetProfilesFolderLocation()
204207
{
205208
// 1. Policy override takes precedence (for IT administrators)
206209
if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.Profiles_FolderLocation))
207210
{
208-
var validatedPath = ValidateProfilesFolderPath(
211+
var validatedPath = DirectoryHelper.ValidateFolderPath(
209212
PolicyManager.Current.Profiles_FolderLocation,
210213
"Policy-provided",
214+
nameof(PolicyInfo.Profiles_FolderLocation),
211215
"next priority");
212216

213217
if (validatedPath != null)
@@ -216,11 +220,12 @@ public static string GetProfilesFolderLocation()
216220

217221
// 2. Custom user-configured path (not available in portable mode)
218222
if (!ConfigurationManager.Current.IsPortable &&
219-
!string.IsNullOrWhiteSpace(SettingsManager.Current?.Profiles_CustomProfilesFolderLocation))
223+
!string.IsNullOrWhiteSpace(SettingsManager.Current?.Profiles_FolderLocation))
220224
{
221-
var validatedPath = ValidateProfilesFolderPath(
222-
SettingsManager.Current.Profiles_CustomProfilesFolderLocation,
225+
var validatedPath = DirectoryHelper.ValidateFolderPath(
226+
SettingsManager.Current.Profiles_FolderLocation,
223227
"Custom",
228+
nameof(SettingsInfo.Profiles_FolderLocation),
224229
"default location");
225230

226231
if (validatedPath != null)
@@ -253,67 +258,6 @@ public static string GetPortableProfilesFolderLocation()
253258
return Path.Combine(AssemblyManager.Current.Location, ProfilesFolderName);
254259
}
255260

256-
/// <summary>
257-
/// Validates a profiles folder path for correctness and accessibility.
258-
/// </summary>
259-
/// <param name="path">The path to validate.</param>
260-
/// <param name="pathSource">Description of the path source for logging (e.g., "Policy-provided", "Custom").</param>
261-
/// <param name="fallbackMessage">Message describing what happens on validation failure (e.g., "next priority", "default location").</param>
262-
/// <returns>The validated full path if valid; otherwise, null.</returns>
263-
private static string ValidateProfilesFolderPath(string path, string pathSource, string fallbackMessage)
264-
{
265-
// Expand environment variables first (e.g. %userprofile%\profiles -> C:\Users\...\profiles)
266-
path = Environment.ExpandEnvironmentVariables(path);
267-
268-
// Validate that the path is rooted (absolute)
269-
if (!Path.IsPathRooted(path))
270-
{
271-
Log.Error($"{pathSource} Profiles_FolderLocation is not an absolute path: {path}. Falling back to {fallbackMessage}.");
272-
return null;
273-
}
274-
275-
// Validate that the path doesn't contain invalid characters
276-
try
277-
{
278-
// This will throw ArgumentException, NotSupportedException, SecurityException, PathTooLongException, or IOException if the path is invalid
279-
var fullPath = Path.GetFullPath(path);
280-
281-
// Check if the path is a directory (not a file)
282-
if (File.Exists(fullPath))
283-
{
284-
Log.Error($"{pathSource} Profiles_FolderLocation is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
285-
return null;
286-
}
287-
288-
return Path.TrimEndingDirectorySeparator(fullPath);
289-
}
290-
catch (ArgumentException ex)
291-
{
292-
Log.Error($"{pathSource} Profiles_FolderLocation contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
293-
return null;
294-
}
295-
catch (NotSupportedException ex)
296-
{
297-
Log.Error($"{pathSource} Profiles_FolderLocation format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
298-
return null;
299-
}
300-
catch (SecurityException ex)
301-
{
302-
Log.Error($"Insufficient permissions to access {pathSource} Profiles_FolderLocation: {path}. Falling back to {fallbackMessage}.", ex);
303-
return null;
304-
}
305-
catch (PathTooLongException ex)
306-
{
307-
Log.Error($"{pathSource} Profiles_FolderLocation path is too long: {path}. Falling back to {fallbackMessage}.", ex);
308-
return null;
309-
}
310-
catch (IOException ex)
311-
{
312-
Log.Error($"{pathSource} Profiles_FolderLocation caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
313-
return null;
314-
}
315-
}
316-
317261
/// <summary>
318262
/// Method to get the path of the profiles backup folder.
319263
/// </summary>

Source/NETworkManager.Settings/SettingsInfo.cs

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,22 @@ public bool Experimental_EnableExperimentalFeatures
576576
}
577577
}
578578

579-
// Profiles
579+
// Profiles
580+
private string _profiles_FolderLocation;
581+
582+
public string Profiles_FolderLocation
583+
{
584+
get => _profiles_FolderLocation;
585+
set
586+
{
587+
if (value == _profiles_FolderLocation)
588+
return;
589+
590+
_profiles_FolderLocation = value;
591+
OnPropertyChanged();
592+
}
593+
}
594+
580595
private string _profiles_LastSelected;
581596

582597
public string Profiles_LastSelected
@@ -622,25 +637,6 @@ public int Profiles_MaximumNumberOfBackups
622637
}
623638
}
624639

625-
private string _profiles_CustomProfilesFolderLocation;
626-
627-
/// <summary>
628-
/// Custom profiles folder location set by the user.
629-
/// When set, overrides the default profiles folder location.
630-
/// </summary>
631-
public string Profiles_CustomProfilesFolderLocation
632-
{
633-
get => _profiles_CustomProfilesFolderLocation;
634-
set
635-
{
636-
if (value == _profiles_CustomProfilesFolderLocation)
637-
return;
638-
639-
_profiles_CustomProfilesFolderLocation = value;
640-
OnPropertyChanged();
641-
}
642-
}
643-
644640
// Settings
645641
private bool _settings_IsDailyBackupEnabled = GlobalStaticConfiguration.Settings_IsDailyBackupEnabled;
646642

Source/NETworkManager.Settings/SettingsManager.cs

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System;
66
using System.IO;
77
using System.Linq;
8-
using System.Security;
98
using System.Text.Json;
109
using System.Text.Json.Serialization;
1110
using System.Xml.Serialization;
@@ -74,16 +73,21 @@ public static class SettingsManager
7473

7574
/// <summary>
7675
/// Method to get the path of the settings folder.
76+
/// Priority:
77+
/// 1. Policy override (for IT administrators)
78+
/// 2. Custom user-configured path (not available in portable mode)
79+
/// 3. Portable (same directory as the application) or default location (Documents folder)
7780
/// </summary>
7881
/// <returns>Path to the settings folder.</returns>
7982
public static string GetSettingsFolderLocation()
8083
{
8184
// 1. Policy override takes precedence (for IT administrators)
8285
if (!string.IsNullOrWhiteSpace(PolicyManager.Current?.Settings_FolderLocation))
8386
{
84-
var validatedPath = ValidateSettingsFolderPath(
87+
var validatedPath = DirectoryHelper.ValidateFolderPath(
8588
PolicyManager.Current.Settings_FolderLocation,
8689
"Policy-provided",
90+
nameof(PolicyInfo.Settings_FolderLocation),
8791
"next priority");
8892

8993
if (validatedPath != null)
@@ -94,9 +98,10 @@ public static string GetSettingsFolderLocation()
9498
if (!ConfigurationManager.Current.IsPortable &&
9599
!string.IsNullOrWhiteSpace(LocalSettingsManager.Current?.Settings_FolderLocation))
96100
{
97-
var validatedPath = ValidateSettingsFolderPath(
101+
var validatedPath = DirectoryHelper.ValidateFolderPath(
98102
LocalSettingsManager.Current.Settings_FolderLocation,
99103
"Custom",
104+
nameof(LocalSettingsInfo.Settings_FolderLocation),
100105
"default location");
101106

102107
if (validatedPath != null)
@@ -129,67 +134,6 @@ public static string GetPortableSettingsFolderLocation()
129134
return Path.Combine(AssemblyManager.Current.Location, SettingsFolderName);
130135
}
131136

132-
/// <summary>
133-
/// Validates a settings folder path for correctness and accessibility.
134-
/// </summary>
135-
/// <param name="path">The path to validate.</param>
136-
/// <param name="pathSource">Description of the path source for logging (e.g., "Policy-provided", "Custom").</param>
137-
/// <param name="fallbackMessage">Message describing what happens on validation failure (e.g., "next priority", "default location").</param>
138-
/// <returns>The validated full path if valid; otherwise, null.</returns>
139-
private static string ValidateSettingsFolderPath(string path, string pathSource, string fallbackMessage)
140-
{
141-
// Expand environment variables first (e.g. %userprofile%\settings -> C:\Users\...\settings)
142-
path = Environment.ExpandEnvironmentVariables(path);
143-
144-
// Validate that the path is rooted (absolute)
145-
if (!Path.IsPathRooted(path))
146-
{
147-
Log.Error($"{pathSource} Settings_FolderLocation is not an absolute path: {path}. Falling back to {fallbackMessage}.");
148-
return null;
149-
}
150-
151-
// Validate that the path doesn't contain invalid characters
152-
try
153-
{
154-
// This will throw ArgumentException, NotSupportedException, SecurityException, PathTooLongException, or IOException if the path is invalid
155-
var fullPath = Path.GetFullPath(path);
156-
157-
// Check if the path is a directory (not a file)
158-
if (File.Exists(fullPath))
159-
{
160-
Log.Error($"{pathSource} Settings_FolderLocation is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
161-
return null;
162-
}
163-
164-
return Path.TrimEndingDirectorySeparator(fullPath);
165-
}
166-
catch (ArgumentException ex)
167-
{
168-
Log.Error($"{pathSource} Settings_FolderLocation contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
169-
return null;
170-
}
171-
catch (NotSupportedException ex)
172-
{
173-
Log.Error($"{pathSource} Settings_FolderLocation format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
174-
return null;
175-
}
176-
catch (SecurityException ex)
177-
{
178-
Log.Error($"Insufficient permissions to access {pathSource} Settings_FolderLocation: {path}. Falling back to {fallbackMessage}.", ex);
179-
return null;
180-
}
181-
catch (PathTooLongException ex)
182-
{
183-
Log.Error($"{pathSource} Settings_FolderLocation path is too long: {path}. Falling back to {fallbackMessage}.", ex);
184-
return null;
185-
}
186-
catch (IOException ex)
187-
{
188-
Log.Error($"{pathSource} Settings_FolderLocation caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
189-
return null;
190-
}
191-
}
192-
193137
/// <summary>
194138
/// Method to get the path of the settings backup folder.
195139
/// </summary>

Source/NETworkManager.Utilities/DirectoryHelper.cs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.IO;
3+
using System.Security;
4+
using log4net;
35

46
namespace NETworkManager.Utilities;
57

@@ -8,6 +10,11 @@ namespace NETworkManager.Utilities;
810
/// </summary>
911
public static class DirectoryHelper
1012
{
13+
/// <summary>
14+
/// Logger for logging.
15+
/// </summary>
16+
private static readonly ILog Log = LogManager.GetLogger(typeof(DirectoryHelper));
17+
1118
/// <summary>
1219
/// Create a directory with subdirectories and resolve environment variables.
1320
/// </summary>
@@ -16,4 +23,67 @@ public static void CreateWithEnvironmentVariables(string path)
1623
{
1724
Directory.CreateDirectory(Environment.ExpandEnvironmentVariables(path));
1825
}
26+
27+
/// <summary>
28+
/// Validates a folder path for correctness and accessibility.
29+
/// Expands environment variables, checks that the path is absolute,
30+
/// validates characters, and ensures it does not point to a file.
31+
/// </summary>
32+
/// <param name="path">The path to validate.</param>
33+
/// <param name="pathSource">Description of the path source for logging (e.g., "Policy-provided", "Custom").</param>
34+
/// <param name="propertyName">Name of the property being validated for logging (e.g., "Settings_FolderLocation").</param>
35+
/// <param name="fallbackMessage">Message describing what happens on validation failure (e.g., "next priority", "default location").</param>
36+
/// <returns>The validated full path if valid; otherwise, null.</returns>
37+
public static string ValidateFolderPath(string path, string pathSource, string propertyName, string fallbackMessage)
38+
{
39+
// Expand environment variables first (e.g. %userprofile%\settings -> C:\Users\...\settings)
40+
path = Environment.ExpandEnvironmentVariables(path);
41+
42+
// Validate that the path is rooted (absolute)
43+
if (!Path.IsPathRooted(path))
44+
{
45+
Log.Error($"{pathSource} {propertyName} is not an absolute path: {path}. Falling back to {fallbackMessage}.");
46+
return null;
47+
}
48+
49+
// Validate that the path doesn't contain invalid characters
50+
try
51+
{
52+
var fullPath = Path.GetFullPath(path);
53+
54+
// Check if the path is a directory (not a file)
55+
if (File.Exists(fullPath))
56+
{
57+
Log.Error($"{pathSource} {propertyName} is a file, not a directory: {path}. Falling back to {fallbackMessage}.");
58+
return null;
59+
}
60+
61+
return Path.TrimEndingDirectorySeparator(fullPath);
62+
}
63+
catch (ArgumentException ex)
64+
{
65+
Log.Error($"{pathSource} {propertyName} contains invalid characters: {path}. Falling back to {fallbackMessage}.", ex);
66+
return null;
67+
}
68+
catch (NotSupportedException ex)
69+
{
70+
Log.Error($"{pathSource} {propertyName} format is not supported: {path}. Falling back to {fallbackMessage}.", ex);
71+
return null;
72+
}
73+
catch (SecurityException ex)
74+
{
75+
Log.Error($"Insufficient permissions to access {pathSource} {propertyName}: {path}. Falling back to {fallbackMessage}.", ex);
76+
return null;
77+
}
78+
catch (PathTooLongException ex)
79+
{
80+
Log.Error($"{pathSource} {propertyName} path is too long: {path}. Falling back to {fallbackMessage}.", ex);
81+
return null;
82+
}
83+
catch (IOException ex)
84+
{
85+
Log.Error($"{pathSource} {propertyName} caused an I/O error: {path}. Falling back to {fallbackMessage}.", ex);
86+
return null;
87+
}
88+
}
1989
}

Source/NETworkManager/ViewModels/SettingsProfilesViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ private async Task ChangeLocationAction()
243243
SettingsManager.Save();
244244

245245
// Set new location in SettingsInfo
246-
SettingsManager.Current.Profiles_CustomProfilesFolderLocation = Location;
246+
SettingsManager.Current.Profiles_FolderLocation = Location;
247247
SettingsManager.Save();
248248

249249
// Restart the application
@@ -275,7 +275,7 @@ private async Task RestoreDefaultLocationActionAsync()
275275
SettingsManager.Save();
276276

277277
// Clear custom location to revert to default
278-
SettingsManager.Current.Profiles_CustomProfilesFolderLocation = null;
278+
SettingsManager.Current.Profiles_FolderLocation = null;
279279
SettingsManager.Save();
280280

281281
// Restart the application

0 commit comments

Comments
 (0)