From 19b46f66eab7aedc1e3af1ec7fb4628d3b52ad65 Mon Sep 17 00:00:00 2001 From: Jean-Marc MEESSEN Date: Sun, 3 Dec 2023 22:05:38 +0100 Subject: [PATCH] Improve POTA ref validation (#112) --- fleprocess/validate.go | 19 ++++++++++--------- fleprocess/validate_test.go | 38 ++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/fleprocess/validate.go b/fleprocess/validate.go index d6da3d6..fea9ab2 100644 --- a/fleprocess/validate.go +++ b/fleprocess/validate.go @@ -23,8 +23,6 @@ import ( "time" ) -var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`) - // ValidateSota verifies whether the supplied string is a valid SOTA reference. // The syntax is: AA/NN-CCC: Association/Name-3-digit numeric Code (e.g. G/CE-001). func ValidateSota(inputStr string) (ref, errorMsg string) { @@ -37,7 +35,7 @@ func ValidateSota(inputStr string) (ref, errorMsg string) { return wrongInputStr, errorMsg } -var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`) +var validSotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,3}/[A-Z]{2}-[\d]{3}$`) // ValidateWwff verifies whether the supplied string is a valid WWFF reference. // The syntax is: AAFF-CCCC: AA = national prefix, CCCC = 4-digit numeric code (e.g. ONFF-0001). @@ -51,11 +49,12 @@ func ValidateWwff(inputStr string) (ref, errorMsg string) { return wrongInputStr, errorMsg } -var validPotaRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}[\d]{0,1}-[\d]{4,5}$`) +var validWwffRegexp = regexp.MustCompile(`^[\d]{0,1}[A-Z]{1,2}FF-[\d]{4}$`) -// ValidatePota verifies whether the supplied string is a valid POTA reference. +// ValidatePota verifies whether the supplied string is a valid POTA reference. If valid, the error +// message is empty. // The syntax is: AA-CCCCC: AA = national prefix, CCCCC = 4 or 5-digit numeric code (e.g. ON-00001). -// Note that the national prefix can start with a number, must have 1 or 2, and can end with a number +// The national prefix is composed of letters and digits and is of at least 1 char and at most 5 char length. func ValidatePota(inputStr string) (ref, errorMsg string) { inputStr = strings.ToUpper(strings.TrimSpace(inputStr)) wrongInputStr := "*" + inputStr @@ -66,7 +65,7 @@ func ValidatePota(inputStr string) (ref, errorMsg string) { return wrongInputStr, errorMsg } -var validGridRegexp = regexp.MustCompile("(?i)^[a-z]{2}[0-9]{2}([a-z]{2})?$") +var validPotaRegexp = regexp.MustCompile(`^[0-9A-Z]{1,5}-[\d]{4,5}$`) // ValidateGridLocator verifies that the supplied is a valid Maidenhead locator reference // (either in 4 or 6 position). The returned grid case is normalized (first two letters @@ -97,6 +96,8 @@ func ValidateGridLocator(grid string) (processedGrid, errorMsg string) { return processedGrid, errorMsg } +var validGridRegexp = regexp.MustCompile("(?i)^[a-z]{2}[0-9]{2}([a-z]{2})?$") + var validCallRegexp = regexp.MustCompile(`[\d]{0,1}[A-Z]{1,2}\d([A-Z]{1,4}|\d{3,3}|\d{1,3}[A-Z])[A-Z]{0,5}`) var validPrefixRegexp = regexp.MustCompile(`\A[a-zA-Z0-9]{1,3}$`) @@ -144,8 +145,6 @@ func ValidateCall(sign string) (call, errorMsg string) { return wrongSign, "[" + sign + "] is invalid: too many '/'" } -var splitDateRegexp = regexp.MustCompile(`[-/ .]`) - // NormalizeDate takes what looks like a date and normalises it to "YYYY-MM-DD" func NormalizeDate(inputStr string) (date, errorMsg string) { //Try to split the string @@ -192,6 +191,8 @@ func NormalizeDate(inputStr string) (date, errorMsg string) { return date, "" } +var splitDateRegexp = regexp.MustCompile(`[-/ .]`) + // ValidateDate verifies whether the string is a valid date (YYYY-MM-DD). func ValidateDate(inputStr string) (ref, errorMsg string) { diff --git a/fleprocess/validate_test.go b/fleprocess/validate_test.go index f46c785..ddae1a4 100644 --- a/fleprocess/validate_test.go +++ b/fleprocess/validate_test.go @@ -63,6 +63,42 @@ func TestValidateWwff(t *testing.T) { } } +var pota_prefixes_list = []string{ + "YA", "ZA", "7X", "C3", "D2", "VP2E", "CE9", "V2", "AR", "EK", "P4", "VK", "OE", "4J", "CU", "C6", + "A9", "T33", "S2", "8P", "EV", "ON", "V3", "TY", "VP9", "A5", "CP", "T9", "A2", "PY", "V85", "LZ", + "XT", "9U5", "XU", "TJ", "VE", "D4", "ZF", "TL", "TT", "CA", "BY", "HK", "D6", "TI", "TU", "9A", + "CO", "PJ2", "5B", "OK", "P5", "OU", "J2", "J7", "HI", "HC", "SU", "YS", "G", "3C", "E3", "ES", "ET", + "VP8", "OY", "DA", "3D2", "OH", "F", "V6", "TR", "4L", "9G1", "SV", "OX", "J3", "TG", "GU", "3X", + "J5", "8R", "HH", "HR", "HA", "TF", "VU", "YB", "EP", "YI", "EI", "GD", "4X", "I", "6Y", "JA", "GJ", + "JY", "UL", "5Z4", "3DA", "T31", "9K2", "UM", "XW", "YL", "OD5", "7P8", "EL", "5A", "HB0", "LY", + "LX", "XX9", "5R", "7Q7", "9M", "8Q6", "TZ", "9H", "V7", "5T", "3B8", "XE", "UO", "JT", "4O", "VP2M", + "CN", "C9", "XZ2", "V5", "C2", "9N", "PA", "ZL", "YN", "5U", "5N", "E6", "Z3", "GI", "LA", "A4", "AP", + "T8", "ZC6", "HP", "P29", "ZP", "OA", "DU", "SP", "CT", "A7", "Z6", "TN", "YO", "RU", "9X5", "5W", + "T7", "S9", "HZ", "GM", "6W", "YT", "S79", "9L1", "9V", "PJ7", "OM", "S5", "H44", "T5", "ZR", "HL", + "ST0", "1A0KM", "EA", "4S7", "V4", "J6", "J8", "ST", "PZ", "SM", "HB", "YK", "EY", "BV", "5H3", "HS", + "C5", "4W", "5V", "A3", "9Y", "3V8", "TA", "EZ", "VP5", "T2", "5X", "UA", "A6", "4U1UN", "K", "K", + "CV", "UI", "YJ8", "HV", "YV", "XV2", "GW", "S0", "7O", "9J2", "Z2", +} + +// Explicit prefix test because of issue #111 and #108 +func Test_Pota_prefix(t *testing.T) { + test_failed := false + invalidRefs := "" + for _, pota_prefix := range pota_prefixes_list { + pota_ref := pota_prefix + "-0001" + _, errMsg := ValidatePota(pota_ref) + + if errMsg != "" { + test_failed = true + invalidRefs = invalidRefs + pota_ref + " validation failed \n" + } + + } + if test_failed { + t.Error(invalidRefs) + } +} + func TestValidatePota(t *testing.T) { type args struct { inputStr string @@ -97,7 +133,7 @@ func TestValidatePota(t *testing.T) { "Good ref (country ref containing a digit)", args{inputStr: "E7-0258"}, "E7-0258", "", - }, + }, { "Good ref (5 digit park)", args{inputStr: "k-10177"},