From ee9da4fc61cefde4dbede0529429beec7fa1eb58 Mon Sep 17 00:00:00 2001 From: ArshiAAkhavan Date: Sun, 31 Jan 2021 16:33:45 +0330 Subject: [PATCH] add absolute and relative file path validator functions for Unix & Windows with tests --- patterns.go | 4 +++ validator.go | 21 ++++++++++++++++ validator_test.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/patterns.go b/patterns.go index 106ed94..ad2fb48 100644 --- a/patterns.go +++ b/patterns.go @@ -42,6 +42,8 @@ const ( SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$` WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` UnixPath string = `^(/[^/\x00]*)+/?$` + WinARPath string = `^(?:(?:[a-zA-Z]:|\\\\[a-z0-9_.$●-]+\\[a-z0-9_.$●-]+)\\|\\?[^\\/:*?"<>|\r\n]+\\?)(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$` + UnixARPath string = `^((\.{0,2}/)?([^/\x00]*))+/?$` Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$" tagName string = "valid" hasLowerCase string = ".*[[:lower:]]" @@ -97,6 +99,8 @@ var ( rxSSN = regexp.MustCompile(SSN) rxWinPath = regexp.MustCompile(WinPath) rxUnixPath = regexp.MustCompile(UnixPath) + rxARWinPath = regexp.MustCompile(WinARPath) + rxARUnixPath = regexp.MustCompile(UnixARPath) rxSemver = regexp.MustCompile(Semver) rxHasLowerCase = regexp.MustCompile(hasLowerCase) rxHasUpperCase = regexp.MustCompile(hasUpperCase) diff --git a/validator.go b/validator.go index 5c918fc..45417b4 100644 --- a/validator.go +++ b/validator.go @@ -509,6 +509,27 @@ func IsFilePath(str string) (bool, int) { return false, Unknown } +//IsWinFilePath checks both relative & absolute paths in Windows +func IsWinFilePath(str string) bool { + if rxARWinPath.MatchString(str) { + //check windows path limit see: + // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + if len(str[3:]) > 32767 { + return false + } + return true + } + return false +} + +//IsUnixFilePath checks both relative & absolute paths in Unix +func IsUnixFilePath(str string) bool { + if rxARUnixPath.MatchString(str) { + return true + } + return false +} + // IsDataURI checks if a string is base64 encoded data URI such as an image func IsDataURI(str string) bool { dataURI := strings.Split(str, ",") diff --git a/validator_test.go b/validator_test.go index e624b2c..2ac1f7f 100644 --- a/validator_test.go +++ b/validator_test.go @@ -1976,6 +1976,69 @@ func TestFilePath(t *testing.T) { } } +func TestIsWinFilePath(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"c:\\" + strings.Repeat("a", 32767), true}, //See http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath + {"c:\\" + strings.Repeat("a", 32768), false}, + {"c:\\path\\file (x86)\\bar", true}, + {"c:\\path\\file", true}, + {"c:\\path\\file:exe", false}, + {"C:\\", true}, + {"c:\\path\\file\\", true}, + {"..\\path\\file\\", true}, + {"c:/path/file/", false}, + {"a bc", true}, + {"abc.jd", true}, + {"abc.jd:$#%# dsd", false}, + } + for _, test := range tests { + actual := IsWinFilePath(test.param) + if actual != test.expected { + t.Errorf("Expected IsWinFilePath(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + +func TestIsUnixFilePath(t *testing.T) { + t.Parallel() + + var tests = []struct { + param string + expected bool + }{ + {"c:/path/file/", true}, //relative path + {"../path/file/", true}, //relative path + {"../../path/file/", true}, //relative path + {"./path/file/", true}, //relative path + {"./file.dghdg", true}, //relative path + {"/path/file/", true}, + {"/path/file:SAMPLE/", true}, + {"/path/file:/.txt", true}, + {"/path", true}, + {"/path/__bc/file.txt", true}, + {"/path/a--ac/file.txt", true}, + {"/_path/file.txt", true}, + {"/path/__bc/file.txt", true}, + {"/path/a--ac/file.txt", true}, + {"/__path/--file.txt", true}, + {"/path/a bc", true}, + {"a bc", true}, + {"abc.jd", true}, + {"abc.jd:$#%# dsd", true}, + } + for _, test := range tests { + actual := IsUnixFilePath(test.param) + if actual != test.expected { + t.Errorf("Expected IsUnixFilePath(%q) to be %v, got %v", test.param, test.expected, actual) + } + } +} + func TestIsLatitude(t *testing.T) { t.Parallel()