From 02c71cc67dc1954eecbbdd69d25fa9d7525e926a Mon Sep 17 00:00:00 2001 From: Morgan Willcock Date: Sun, 26 Jul 2020 00:41:08 +0100 Subject: [PATCH 1/2] Editor: Add validation functions for project paths --- Editor/AGS.Editor/AGSEditor.csproj | 1 + .../AGS.Editor/Components/ScriptsComponent.cs | 3 +- .../AGS.Editor/GUI/StartNewGameWizardPage2.cs | 101 ++++++++++-------- Editor/AGS.Editor/Utils/Utilities.cs | 15 --- Editor/AGS.Editor/Utils/Validation.cs | 57 ++++++++++ 5 files changed, 115 insertions(+), 62 deletions(-) create mode 100644 Editor/AGS.Editor/Utils/Validation.cs diff --git a/Editor/AGS.Editor/AGSEditor.csproj b/Editor/AGS.Editor/AGSEditor.csproj index e8c8abf771d..dd3e295955c 100644 --- a/Editor/AGS.Editor/AGSEditor.csproj +++ b/Editor/AGS.Editor/AGSEditor.csproj @@ -331,6 +331,7 @@ + Designer frmMain.cs diff --git a/Editor/AGS.Editor/Components/ScriptsComponent.cs b/Editor/AGS.Editor/Components/ScriptsComponent.cs index 720194199ed..23461942c99 100644 --- a/Editor/AGS.Editor/Components/ScriptsComponent.cs +++ b/Editor/AGS.Editor/Components/ScriptsComponent.cs @@ -5,6 +5,7 @@ using System.Text; using System.Windows.Forms; using System.Xml; +using AGS.Editor.Utils; using AGS.Types; using WeifenLuo.WinFormsUI.Docking; @@ -523,7 +524,7 @@ private void ScriptRenamed(string oldScriptName, ProjectTreeItem renamedItem) return; } - if (!Utilities.DoesFileNameContainOnlyValidCharacters(renamedScript.FileName)) + if (!Validation.FilenameIsValid(renamedScript.FileName)) { _guiController.ShowMessage("The file name '" + renamedScript.FileName + "' contains some invalid characters. You cannot use some characters like : and / in script file names.", MessageBoxIcon.Warning); renamedScript.FileName = oldScriptName; diff --git a/Editor/AGS.Editor/GUI/StartNewGameWizardPage2.cs b/Editor/AGS.Editor/GUI/StartNewGameWizardPage2.cs index 3dcf7f2da84..446b09473c5 100644 --- a/Editor/AGS.Editor/GUI/StartNewGameWizardPage2.cs +++ b/Editor/AGS.Editor/GUI/StartNewGameWizardPage2.cs @@ -7,6 +7,7 @@ using System.IO; using System.Text; using System.Windows.Forms; +using AGS.Editor.Utils; namespace AGS.Editor { @@ -40,56 +41,64 @@ public string GetFullPath() } } - private bool VerifyPathContainsValidCharacters() - { - foreach (char c in GetFullPath()) - { - foreach (char invalidChar in Path.GetInvalidPathChars()) - { - if (invalidChar == c) - { - return false; - } - } - } - if (!txtCreateInFolder.Text.Contains(@"\")) - { - // Path must contain at least one \ - return false; - } - if (!txtCreateInFolder.Text.Contains(":")) - { - // Path must contain at least one : - return false; - } - return true; - } - public override bool NextButtonPressed() { - if ((txtFileName.Text.Length > 0) && - (txtFriendlyName.Text.Length > 0) && - (txtCreateInFolder.Text.Length > 0)) + if (txtFriendlyName.TextLength == 0) + { + Factory.GUIController.ShowMessage("You must enter a name for your game", MessageBoxIcon.Warning); + return false; + } + + if (txtFileName.TextLength == 0) + { + Factory.GUIController.ShowMessage("You must enter a file name for your game", MessageBoxIcon.Warning); + return false; + } + + if (txtCreateInFolder.TextLength == 0) + { + Factory.GUIController.ShowMessage("You must choose a directory where the game project will be created", MessageBoxIcon.Warning); + return false; + } + + if (!Validation.FilenameIsValid(txtFileName.Text) || + !Validation.StringIsAsciiCharactersOnly(txtFileName.Text)) + { + Factory.GUIController.ShowMessage("The file name you have specified includes some invalid characters. Please use just letters and numbers", MessageBoxIcon.Warning); + return false; + } + + if (!Validation.PathIsValid(txtCreateInFolder.Text)) + { + Factory.GUIController.ShowMessage("The path to the directory you have specified includes some invalid characters", MessageBoxIcon.Warning); + return false; + } + + string fullpath; + try + { + fullpath = Path.Combine(txtCreateInFolder.Text, txtFileName.Text); + } + catch { - if (!Utilities.DoesFileNameContainOnlyValidCharacters(txtFileName.Text)) - { - Factory.GUIController.ShowMessage("The file name you have specified includes some invalid characters. Please use just letters and numbers.", MessageBoxIcon.Warning); - return false; - } - if (!VerifyPathContainsValidCharacters()) - { - Factory.GUIController.ShowMessage("The folder name you have specified includes some invalid characters. Please use just letters and numbers.", MessageBoxIcon.Warning); - return false; - } - if (Directory.Exists(GetFullPath())) - { - Factory.GUIController.ShowMessage("The directory '" + GetFullPath() + "', already exists. Please choose another file name.", MessageBoxIcon.Warning); - return false; - } - return true; + Factory.GUIController.ShowMessage("Error combining full project path" , MessageBoxIcon.Error); + return false; } - Factory.GUIController.ShowMessage("You must type in a file name and a game name to continue.", MessageBoxIcon.Information); - return false; + + if (!Validation.PathIsAbsolute(fullpath) || + !Validation.PathIsAbsoluteDriveLetter(fullpath)) + { + Factory.GUIController.ShowMessage("The project directory must be an absolute path that starts with a drive letter", MessageBoxIcon.Warning); + return false; + } + + if (!Validation.PathIsAvailable(fullpath)) + { + Factory.GUIController.ShowMessage("The chosen project directory already exists", MessageBoxIcon.Warning); + return false; + } + + return true; } public override string TitleText diff --git a/Editor/AGS.Editor/Utils/Utilities.cs b/Editor/AGS.Editor/Utils/Utilities.cs index 609b80ff40b..1b6937f4ccb 100644 --- a/Editor/AGS.Editor/Utils/Utilities.cs +++ b/Editor/AGS.Editor/Utils/Utilities.cs @@ -223,21 +223,6 @@ public static void CopyFileAndSetDestinationWritable(string sourceFileName, stri File.SetAttributes(destFileName, FileAttributes.Archive); } - public static bool DoesFileNameContainOnlyValidCharacters(string fileName) - { - foreach (char c in fileName) - { - foreach (char invalidChar in Path.GetInvalidFileNameChars()) - { - if (invalidChar == c) - { - return false; - } - } - } - return true; - } - public static void CopyFont(int fromSlot, int toSlot) { if (fromSlot == toSlot) diff --git a/Editor/AGS.Editor/Utils/Validation.cs b/Editor/AGS.Editor/Utils/Validation.cs new file mode 100644 index 00000000000..1b5fafbc68d --- /dev/null +++ b/Editor/AGS.Editor/Utils/Validation.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; + +namespace AGS.Editor.Utils +{ + public class Validation + { + public static bool FilenameIsValid(string filename) + { + return !(filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0); + } + + public static bool PathIsAvailable(string path) + { + if (File.Exists(path)) + return false; + + if (Directory.Exists(path)) + return false; + + return true; + } + + public static bool PathIsAbsoluteDriveLetter(string path) + { + return Regex.IsMatch(path, @"^[a-zA-Z]:\\"); + } + + public static bool PathIsAbsolute(string path) + { + bool rooted = false; + + try + { + rooted = Path.IsPathRooted(path); + } + catch (ArgumentException) + { + // pass + } + + return rooted; + } + + public static bool PathIsValid(string path) + { + return !(path.IndexOfAny(Path.GetInvalidPathChars()) >= 0); + } + + public static bool StringIsAsciiCharactersOnly(string fileName) + { + return !fileName.Any(c => c > 127); + } + } +} From 4a957f9e66e7cbeb2658b696e1b0fd5f4f0b1adf Mon Sep 17 00:00:00 2001 From: Morgan Willcock Date: Sun, 26 Jul 2020 15:50:59 +0100 Subject: [PATCH 2/2] Types: Approximate game filename validation --- Editor/AGS.Types/Settings.cs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Editor/AGS.Types/Settings.cs b/Editor/AGS.Types/Settings.cs index 7d4dae504c5..fbf47ca419b 100644 --- a/Editor/AGS.Types/Settings.cs +++ b/Editor/AGS.Types/Settings.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Drawing; using System.IO; +using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml; @@ -159,7 +160,25 @@ public void GenerateNewGameID() public string GameFileName { get { return _gameFileName; } - set { _gameFileName = value; } + set + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentException("Game file name cannot be empty"); + } + + if (value.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) + { + throw new ArgumentException("Game file name contains invalid characters"); + } + + if (value.Any(c => c > 127)) + { + throw new ArgumentException("Game file name should only contain letters and numbers"); + } + + _gameFileName = value; + } } [DisplayName(PROPERTY_GAME_NAME)]