From c6112c9c749af56d5278f87a2eecc3aa322f0b46 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Thu, 26 Apr 2018 22:15:09 +0200 Subject: [PATCH] Match() uses 'matchString()' and 'matchWildcards()' and now works as expected --- internal/uri/parser/private.go | 112 +++++++++++++++++++++++++++++++++ internal/uri/parser/public.go | 90 +++----------------------- 2 files changed, 119 insertions(+), 83 deletions(-) diff --git a/internal/uri/parser/private.go b/internal/uri/parser/private.go index e6066d2..aa06646 100644 --- a/internal/uri/parser/private.go +++ b/internal/uri/parser/private.go @@ -1,6 +1,7 @@ package parser import ( + "strings" "fmt" ) @@ -100,4 +101,115 @@ func (s Scheme) optimise() (Scheme, error) { return rshift, nil +} + + +// matchString checks the STRING matchers from an URI +// it returns a boolean : false when not matching, true eitherway +// it returns a cleared uri, without STRING data +func (s Scheme) matchString(uri string) (string, bool) { + + /* (1) Initialise variables */ + clr := uri // contains cleared input string + minOff := 0 // minimum offset + + /* (2) Iterate over strings */ + for _, m := range s { + + + ls := len(m.pat) + + // {1} If not STRING matcher -> ignore // + if ls == 0 { continue } + + // {2} Get offset in URI (else -1) // + off := strings.Index(clr, m.pat) + if off < 0 { return "", false } + + // {3} Fail on invalid offset range // + if off < minOff { return "", false } + + // {4} Check for trailing '/' // + hasSlash := 0 + if off+ls < len(clr) && clr[off+ls] == '/' { + hasSlash = 1 + } + + // {5} Remove the current string (+trailing slash) from the URI // + beg, end := clr[:off], clr[off+ls+hasSlash:] + clr = fmt.Sprintf("%s\a/%s", beg, end) // separate matches by '\a' character + + // {6} Update offset range // + minOff = len(beg) + 2 - 1 // +2 slash separators + // -1 because strings begin with 1 slash already + + } + + /* (3) If exists, remove trailing '/' */ + if clr[len(clr)-1] == '/' { + clr = clr[:len(clr)-1] + } + + /* (4) If exists, remove trailing '\a' */ + if clr[len(clr)-1] == '\a' { + clr = clr[:len(clr)-1] + } + + return clr, true + +} + + +// matchWildcards check the WILCARDS (non-string) matchers from +// a cleared URI. it returns if the string matches +// + it sets the matchers buffers for later extraction +func (s Scheme) matchWildcards(clear string) bool { + + /* (1) Extract wildcards (ref) */ + wildcards := make(Scheme, 0, maxMatch) + + for _, m := range s { + if len(m.pat) == 0 { + m.buf = nil // flush buffers + wildcards = append(wildcards, m) + } + } + + /* (2) If no wildcards -> match */ + if len(wildcards) == 0 { + return true + } + + /* (3) Break uri by '\a' characters */ + matches := strings.Split(clear, "\a")[1:] + + /* (4) Iterate over matches */ + for n, match := range matches { + + // {1} If no more matcher // + if n >= len(wildcards) { + return false + } + + // {2} Split by '/' // + data := strings.Split(match, "/")[1:] // from index 1 because it begins with '/' + + // {3} If required and missing // + if wildcards[n].req && len(data) < 1 { + return false + } + + // {4} If not multi but got multi // + if !wildcards[n].mul && len(data) > 1 { + return false + } + + // {5} Store data into matcher // + wildcards[n].buf = data + + } + + /* (5) Match */ + return true + } \ No newline at end of file diff --git a/internal/uri/parser/public.go b/internal/uri/parser/public.go index c16a352..8f8cfeb 100644 --- a/internal/uri/parser/public.go +++ b/internal/uri/parser/public.go @@ -47,94 +47,18 @@ func (s Scheme) Match(str string) bool { /* (1) Nothing -> match all */ if len(s) == 0 { return true } - /* (2) Init variables */ - wc := make(Scheme, 0, maxMatch) // conrains wildcards - clr := str // contains cleared input string - minOff := 0 // minimum offset - - /* (3) Iterate over strings */ - for _, m := range s { - - ls := len(m.pat) - - // if not string -> ignore - if ls == 0 { - wc = append(wc, m) - continue - } - - // get offset if contained, else -1 - off := strings.Index(clr, m.pat) - if off < 0 { return false } - - // if invalid offset range -> fail - if off < minOff { return false } - - // check if trailing '/' - slash := 0 - if off+ls < len(clr) && clr[off+ls] == '/' { - slash = 1 - } - - // exclude this string (+trailing slash if set) - // fmt.Printf("remove: '%s'\n", clr[off:off+ls+slash]) - beg, end := clr[:off], clr[off+ls+slash:] - clr = fmt.Sprintf("%s//%s", beg, end) - // fmt.Printf("clr: '%s'\n", clr) - - // update offset range - minOff = len(beg) + 2 - 1 // +2 slash separators - // -1 because strings begin with 1 slash already - - } - - /* (4) If no wildcard -> match */ - if len(wc) == 0 { - return true - } - - // flush wildcard buffers - for _, w := range wc { w.buf = nil } - - /* (5) Break the clear string apart */ - matches := strings.Split(clr, "//")[1:] - - // fail if missing matches - if len(matches) < len(wc) { + /* (2) Check for string match */ + clearURI, match := s.matchString(str) + if !match { return false } - nwc := 0 - for _, m := range matches { - - // ignore empty - if len(m) == 0 { continue } - - // no matcher for this match - if nwc >= len(wc){ return false } - - // split by '/' - parts := strings.Split(m, "/") - - // if required and missing -> does not match - if wc[nwc].req && len(parts) < 1 { - return false - } - - // if not multi but multi -> does not match - if !wc[nwc].mul && len(parts) > 1 { - return false - } - - // store into wilcard matcher - wc[nwc].buf = parts - - // increment wildcard count - nwc++ - + /* (3) Check for non-string match (wildcards) */ + match = s.matchWildcards(clearURI) + if !match { + return false } - return true }