From 9a7834c330574bee8c173282e0c4a19bcf2a0066 Mon Sep 17 00:00:00 2001 From: 50501AZ Webmaster Date: Sat, 26 Jul 2025 23:57:34 -0700 Subject: [PATCH] Regex implementation (yet to be implemented) --- args/args.go | 3 +-- conf/conf.go | 7 ++++++ conf/readme.md | 2 +- conf/regex.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 conf/regex.go diff --git a/args/args.go b/args/args.go index 09806dd..a859ea2 100644 --- a/args/args.go +++ b/args/args.go @@ -16,8 +16,7 @@ var flagsParsed bool = false; /* what JSON file to read config values from */ var confLocation = flag.String("conf", "./config.txt", "Config file to read from") -/* Returns nil if flags are not parsed yet - @return set boolean will be true if argument is not nil */ +/* @return set boolean will be true if argument is not nil */ func GetConfLocation() (location string, set bool) { if confLocation == nil {return "", false} return *confLocation, true; diff --git a/conf/conf.go b/conf/conf.go index 730c801..5356b37 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -1,5 +1,8 @@ package conf +/* This file contains the Config object and its methods, which handle reading + from a config file and matching requests to the whitelist. */ + import ( "bufio" "errors" @@ -7,11 +10,14 @@ import ( "strings" ) +// import "fmt" + /* Object to handle what is in a JSON config */ type Config struct { configData map[string][]string; } +/* Opens and reads a file at the path */ func NewConfig(filePath string) (newConfig *Config, err error) { // Open file file, err := os.Open(filePath) @@ -34,4 +40,5 @@ func NewConfig(filePath string) (newConfig *Config, err error) { return &Config{configData: newConfigData}, nil; } +/* Gets a reference copy to the config data */ func (config Config) GetConfigData() map[string][]string {return config.configData;} \ No newline at end of file diff --git a/conf/readme.md b/conf/readme.md index 59e9e52..5e0863f 100644 --- a/conf/readme.md +++ b/conf/readme.md @@ -18,5 +18,5 @@ There is a regex-like behavior to these paths using the `*` and `?` characters. The `*` character matches to any number of path segments. The `?` character matches to only one segment. Here's some examples: -* `HZJWwB0TAjz6pjAHosII5ofR /+16028675309/*` will allow the bearer token to access any endpoint with the phone number `+16028675309` +* `HZJWwB0TAjz6pjAHosII5ofR /+16028675309/*` will allow the bearer token to access any endpoint with the phone number `+16028675309`. * `HZJWwB0TAjz6pjAHosII5ofR /+16028675309/direct/?/send` will allow the bearer token to send a direct message to anyone on that phone number. \ No newline at end of file diff --git a/conf/regex.go b/conf/regex.go new file mode 100644 index 0000000..4a1fb0a --- /dev/null +++ b/conf/regex.go @@ -0,0 +1,62 @@ +package conf + +/* This file contains regex helper functions for parsing configs */ + +import ( + "strings" +) + +/* Splits and normalises */ +func splitPath(path string) []string { + return strings.Split(strings.Trim(path, "/"), "/") +} + +/* Attempts to match a request path to a set of whitelisted paths + @return false for anything other than a valid match */ +func match(request string, matchTo []string) bool { + requestSplit := splitPath(request) + for _, matchToAttempt := range matchTo { + matchToAttemptSplit := splitPath(matchToAttempt); + if matchSegments(requestSplit, matchToAttemptSplit) { + return true; + } + } + + return false; +} + +/* Returns false for anything other than a valid match */ +func matchSegments(request []string, matchTo []string) bool { + /* This is a recursive function which, at each recursion level, matches the + path segments that are in the front of the request and matchTo lists + It matches identical strings, anything to &, and splits in two when + matching anything to *, to account for consuming or not consuming the * + at the current recursion level. */ + + // Recursion base case for perfect match + if len(request) == 0 && len(matchTo) == 0 {return true} + // End of path for one but not the other + if (len(request) & len(matchTo)) == 0 {return false} + + // Grab current path segments + requestCurrent := request[0]; + matchToCurrent := matchTo[0]; + + // & character and direct match have the same behavior + if (matchToCurrent == "&") || (requestCurrent == matchToCurrent) { + return matchSegments(request[1:], matchTo[1:]); + } + + // * character + if (matchToCurrent == "*") { + // These are split for performance + // Usually the * only refers to 1 or 2 things so putting consumption + // first is probably a better choice + if (matchSegments(request[1:], matchTo[1:])) {return true} + if (matchSegments(request[1:], matchTo)) {return true} + return false; + } + + // Code will reach here if there's no match for the current segment + return false; +} \ No newline at end of file diff --git a/main.go b/main.go index 3853754..1e18720 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ func main() { if !confLocationSet {log.Default().Print("No config value!"); return;} log.Default().Print("Reading config value from ", configLocation); + // Set up config config, err := conf.NewConfig(configLocation); if err != nil {log.Default().Print("Error reading config: ", err); return;} fmt.Println(config.GetConfigData())