diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..d4ecef5 --- /dev/null +++ b/utils.go @@ -0,0 +1,64 @@ +package irc + +import ( + "bytes" + "fmt" + "regexp" + "strings" +) + +// MaskToRegex converts an irc mask to a go Regexp for more convenient +// use. This should never return an error, but we have this here just +// in case. +func MaskToRegex(rawMask string) (*regexp.Regexp, error) { + backslashed := false + unprocessed := rawMask + buf := &bytes.Buffer{} + buf.WriteByte('^') + + for len(unprocessed) > 0 { + i := strings.IndexAny(unprocessed, "\\?*") + if i < 0 { + if backslashed { + buf.WriteString(regexp.QuoteMeta("\\")) + backslashed = false + } + + buf.WriteString(regexp.QuoteMeta(unprocessed)) + unprocessed = "" + break + } + + if backslashed && i > 0 { + buf.WriteString(regexp.QuoteMeta("\\")) + backslashed = false + } else if backslashed && i == 0 { + buf.WriteString(regexp.QuoteMeta(string(unprocessed[0]))) + unprocessed = unprocessed[1:] + backslashed = false + continue + } + + buf.WriteString(regexp.QuoteMeta(unprocessed[:i])) + + switch unprocessed[i] { + case '\\': + backslashed = true + case '?': + buf.WriteString(".") + case '*': + buf.WriteString(".*") + } + + unprocessed = unprocessed[i+1:] + fmt.Println(unprocessed) + } + + if backslashed { + buf.WriteString(regexp.QuoteMeta("\\")) + } + + buf.WriteByte('$') + + return regexp.Compile(buf.String()) +} diff --git a/utils_test.go b/utils_test.go new file mode 100644 index 0000000..bb973a4 --- /dev/null +++ b/utils_test.go @@ -0,0 +1,61 @@ +package irc + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMaskToRegex(t *testing.T) { + var testCases = []struct { + Input string + Expect string + }{ + { // Empty should be fine + Input: "", + Expect: "^$", + }, + { // EVERYONE! + Input: "*!*@*", + Expect: "^.*!.*@.*$", + }, + { + Input: "", + Expect: "^$", + }, + { + Input: "", + Expect: "^$", + }, + { // Escape the slash + Input: "a\\\\b", + Expect: "^a\\\\b$", + }, + { // Escape a * + Input: "a\\*b", + Expect: "^a\\*b$", + }, + { // Escape a ? + Input: "a\\?b", + Expect: "^a\\?b$", + }, + { // Single slash in the middle of a string should be a slash + Input: "a\\b", + Expect: "^a\\\\b$", + }, + { // Single slash should just match a single slash + Input: "\\", + Expect: "^\\\\$", + }, + { + Input: "\\a?", + Expect: "^\\\\a.$", + }, + } + + for _, testCase := range testCases { + ret, err := MaskToRegex(testCase.Input) + assert.NoError(t, err) + assert.Equal(t, testCase.Expect, ret.String()) + } +}