Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix file and folder sanitization for file-related commands #556

Merged
merged 2 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 20 additions & 12 deletions Source/v2/Meadow.CLI/Commands/Current/App/AppTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,34 @@ internal static async Task<bool> TrimApplication(string path,
return true;
}

internal static string SanitiseMeadowFilename(string fileName)
internal static string SanitizeMeadowFolderName(string fileName)
{
return SanitizeMeadowFilename(fileName) + '/';
}

internal static string SanitizeMeadowFilename(string fileName)
{
fileName = fileName.Replace('\\', Path.DirectorySeparatorChar);
fileName = fileName.Replace('/', Path.DirectorySeparatorChar);

var folder = Path.GetDirectoryName(fileName);

if (string.IsNullOrWhiteSpace(folder))
{
folder = MeadowRootFolder;
folder = Path.DirectorySeparatorChar + MeadowRootFolder;
}
else
{
if (folder.EndsWith('/') == false)
{
folder += "/";
}
if (folder.StartsWith('/') == false)
{
folder = $"/{folder}";
}
if (folder.Contains(MeadowRootFolder) == false)
if (!folder.StartsWith(Path.DirectorySeparatorChar))
{
folder = $"/{MeadowRootFolder}{folder}";
if (!folder.StartsWith($"{MeadowRootFolder}"))
{
folder = $"{Path.DirectorySeparatorChar}{MeadowRootFolder}{Path.DirectorySeparatorChar}{folder}";
}
else
{
folder = $"{Path.DirectorySeparatorChar}{folder}";
}
}
}

Expand Down
27 changes: 9 additions & 18 deletions Source/v2/Meadow.Cli/Commands/Current/File/FileDeleteCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,9 @@ protected override async ValueTask ExecuteCommand()
await device.RuntimeDisable(CancellationToken);
}

// get a list of files in the target folder
var folder = Path.GetDirectoryName(MeadowFile)!.Replace(Path.DirectorySeparatorChar, '/');
if (string.IsNullOrWhiteSpace(folder))
{
folder = $"/{AppTools.MeadowRootFolder}/";
}
Logger?.LogInformation($"Looking for file {MeadowFile}...");

var folder = AppTools.SanitizeMeadowFolderName(Path.GetDirectoryName(MeadowFile)!);

var fileList = await connection.GetFileList($"{folder}", false, CancellationToken);

Expand All @@ -55,29 +52,23 @@ protected override async ValueTask ExecuteCommand()

var exists = fileList?.Any(f => Path.GetFileName(f.Name) == requested) ?? false;

var file = AppTools.SanitizeMeadowFilename(MeadowFile);

if (!exists)
{
Logger?.LogError($"File '{MeadowFile}' not found on device.");
Logger?.LogError($"File '{file}' not found on device");
}
else
{
var wasRuntimeEnabled = await device.IsRuntimeEnabled(CancellationToken);

if (wasRuntimeEnabled)
{
Logger?.LogError($"The runtime must be disabled before doing any file management. Use 'meadow runtime disable' first.");
return;
}

Logger?.LogInformation($"Deleting file '{MeadowFile}' from device...");
await device.DeleteFile(AppTools.SanitiseMeadowFilename(MeadowFile), CancellationToken);
Logger?.LogInformation($"Deleting file '{file}' from device...");
await device.DeleteFile(file, CancellationToken);
}
}
}

private async Task DeleteFileRecursive(IMeadowDevice device, string directoryname, MeadowFileInfo fileInfo, CancellationToken cancellationToken)
{
var meadowFile = AppTools.SanitiseMeadowFilename(Path.Combine(directoryname, fileInfo.Name));
var meadowFile = AppTools.SanitizeMeadowFilename(Path.Combine(directoryname, fileInfo.Name));
if (fileInfo.IsDirectory)
{
// Add a backslash as we're a directory and not a file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protected override async ValueTask ExecuteCommand()

Logger?.LogInformation($"Reading file '{MeadowFile}' from device...\n");

var data = await device.ReadFileString(AppTools.SanitiseMeadowFilename(MeadowFile), CancellationToken);
var data = await device.ReadFileString(AppTools.SanitizeMeadowFilename(MeadowFile), CancellationToken);

if (data == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override async ValueTask ExecuteCommand()

if (Folder != null)
{
Folder = AppTools.SanitiseMeadowFilename(Folder);
Folder = AppTools.SanitizeMeadowFolderName(Folder);

Logger?.LogInformation($"Getting file list from '{Folder}'...");
}
Expand Down
10 changes: 9 additions & 1 deletion Source/v2/Meadow.Cli/Commands/Current/File/FileReadCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ protected override async ValueTask ExecuteCommand()
var device = await GetCurrentDevice();
var connection = await GetCurrentConnection();

var state = await device.IsRuntimeEnabled(CancellationToken);

if (state == true)
{
Logger?.LogInformation($"{Strings.DisablingRuntime}...");
await device.RuntimeDisable(CancellationToken);
}

var received = 0;

connection.FileBytesReceived += (s, count) =>
Expand All @@ -43,7 +51,7 @@ protected override async ValueTask ExecuteCommand()
await device.RuntimeDisable();
}

var success = await device.ReadFile(AppTools.SanitiseMeadowFilename(MeadowFile), LocalFile, CancellationToken);
var success = await device.ReadFile(AppTools.SanitizeMeadowFilename(MeadowFile), LocalFile, CancellationToken);

if (success)
{
Expand Down
19 changes: 15 additions & 4 deletions Source/v2/Meadow.Cli/Commands/Current/File/FileWriteCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ protected override async ValueTask ExecuteCommand()
var connection = await GetCurrentConnection();
var device = await GetCurrentDevice();

var state = await device.IsRuntimeEnabled(CancellationToken);

if (state == true)
{
Logger?.LogInformation($"{Strings.DisablingRuntime}...");
await device.RuntimeDisable(CancellationToken);
}

if (TargetFileNames.Any() && Files.Count != TargetFileNames.Count)
{
Logger?.LogError($"Number of files to write ({Files.Count}) does not match the number of target file names ({TargetFileNames.Count}).");
Expand All @@ -40,8 +48,11 @@ protected override async ValueTask ExecuteCommand()
{
var p = e.completed / (double)e.total * 100d;

// Console instead of Logger due to line breaking for progress bar
Console?.Output.Write($"Writing {e.fileName}: {p:0}% \r");
if (!double.IsNaN(p))
{
// Console instead of Logger due to line breaking for progress bar
Console?.Output.Write($"Writing {e.fileName}: {p:0}% \r");
}
};

Logger?.LogInformation($"Writing {Files.Count} file{(Files.Count > 1 ? "s" : "")} to device...");
Expand All @@ -54,7 +65,7 @@ protected override async ValueTask ExecuteCommand()
}
else
{
var targetFileName = AppTools.SanitiseMeadowFilename(GetTargetFileName(i));
var targetFileName = AppTools.SanitizeMeadowFilename(GetTargetFileName(i));

Logger?.LogInformation(
$"Writing '{Files[i]}' as '{targetFileName}' to device");
Expand Down Expand Up @@ -85,4 +96,4 @@ private string GetTargetFileName(int i)

return new FileInfo(Files[i]).Name;
}
}
}
12 changes: 10 additions & 2 deletions Source/v2/Meadow.Cli/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,21 @@
"commandName": "Project",
"commandLineArgs": "file list"
},
"File List folder": {
"commandName": "Project",
"commandLineArgs": "file list Temp"
},
"File List verbose": {
"commandName": "Project",
"commandLineArgs": "file list --verbose"
},
"File Delete": {
"commandName": "Project",
"commandLineArgs": "file delete Juego.pdb"
"commandLineArgs": "file delete /yo2.txt"
},
"File Delete folder": {
"commandName": "Project",
"commandLineArgs": "file delete /Temp/yo3.txt"
},
"File Delete All": {
"commandName": "Project",
Expand All @@ -105,7 +113,7 @@
},
"File Write": {
"commandName": "Project",
"commandLineArgs": "file write -f \"f:\\temp\\test.txt\""
"commandLineArgs": "file write -f .\\yo2.txt"
},
"Firmware List": {
"commandName": "Project",
Expand Down
Loading