diff --git a/utils/coreutils.go b/utils/coreutils.go
index 6ac6b8cd6..f734c3895 100644
--- a/utils/coreutils.go
+++ b/utils/coreutils.go
@@ -226,10 +226,10 @@ func ParseZeroRatingSubject(rateSubj string) (time.Duration, error) {
return time.ParseDuration(durStr)
}
-// Used to parse extra fields definition into regexp rules
-func ParseSearchReplaceRegexp(strRule string) (*regexp.Regexp, string, error) {
+// Used to parse extra fields definition search regexp rule and replace template
+func ParseSearchReplaceStr(strRule string) (*regexp.Regexp, string, error) {
// String rule expected in the form ~hdr_name:s/match_rule/replace_rule/
- getRuleRgxp := regexp.MustCompile(`:s\/(.+[^\\])\/(.+[^\\])\/`) // Make sure the separator / is not escaped in the rule
+ getRuleRgxp := regexp.MustCompile(`~\w+:s\/(.+[^\\])\/(.+[^\\])\/`) // Make sure the separator / is not escaped in the rule
allMatches := getRuleRgxp.FindStringSubmatch(strRule)
if len(allMatches) != 3 { // Second and third groups are of interest to us
return nil, "", errors.New("Invalid Search&Replace rule.")
@@ -242,9 +242,9 @@ func ParseSearchReplaceRegexp(strRule string) (*regexp.Regexp, string, error) {
}
// Used to expand string sources, eg: extra fields
-func RegexpSearchReplace(src string, searchRl *regexp.Regexp, replaceTpl string) string {
+func RegexpSearchReplace(src string, searchRgxp *regexp.Regexp, replaceTpl string) string {
res := []byte{}
- match := searchRl.FindStringSubmatchIndex(src)
- res = searchRl.ExpandString(res, replaceTpl, src, match)
+ match := searchRgxp.FindStringSubmatchIndex(src)
+ res = searchRgxp.ExpandString(res, replaceTpl, src, match)
return string(res)
}
diff --git a/utils/utils_test.go b/utils/utils_test.go
index 1e5bcefb0..0ac912dbd 100644
--- a/utils/utils_test.go
+++ b/utils/utils_test.go
@@ -19,6 +19,8 @@ along with this program. If not, see
package utils
import (
+ "reflect"
+ "regexp"
"testing"
"time"
)
@@ -385,3 +387,46 @@ func TestParseZeroRatingSubject(t *testing.T) {
}
}
}
+
+func TestParseSearchReplaceStr(t *testing.T) {
+ // Normal case
+ strRule := `~sip_redirected_to:s/sip:\+49(\d+)@/0$1/`
+ srchRgxp, replaceTpl, err := ParseSearchReplaceStr(strRule)
+ if srchRgxp == nil || len(replaceTpl) == 0 || err != nil {
+ t.Error("Could not parse the str rule")
+ } else if !reflect.DeepEqual(srchRgxp, regexp.MustCompile(`sip:\+49(\d+)@`)) {
+ t.Error("Unexpected regexp search parsed")
+ } else if replaceTpl != "0$1" {
+ t.Error("Unexpected replace template parsed")
+ }
+ // Missing ~ prefix
+ strRule = `sip_redirected_to:s/sip:\+49(\d+)@/0$1/`
+ if _, _, err := ParseSearchReplaceStr(strRule); err == nil {
+ t.Error("Parse error, srchrepl rule does not start with ~")
+ }
+ // Separator escaped
+ strRule = `~sip_redirected_to:s\/sip:\+49(\d+)@/0$1/`
+ if _, _, err := ParseSearchReplaceStr(strRule); err == nil {
+ t.Error("Parse error, srchrepl rule does not contain correct number of separators")
+ }
+ // One extra separator but escaped
+ strRule = `~sip_redirected_to:s/sip:\+49(\d+)\/@/0$1/`
+ srchRgxp, replaceTpl, err = ParseSearchReplaceStr(strRule)
+ if srchRgxp == nil || len(replaceTpl) == 0 || err != nil {
+ t.Error("Could not parse the str rule")
+ } else if !reflect.DeepEqual(srchRgxp, regexp.MustCompile(`sip:\+49(\d+)\/@`)) {
+ t.Error("Unexpected regexp search parsed")
+ } else if replaceTpl != "0$1" {
+ t.Error("Unexpected replace template parsed")
+ }
+}
+
+func TestRegexpSearchReplace(t *testing.T) {
+ srchRgxp := regexp.MustCompile(`sip:\+49(\d+)@(\d*\.\d*\.\d*\.\d*)`)
+ replaceTpl := "0$1@$2"
+ source := ""
+ expectOut := "086517174963@127.0.0.1"
+ if outStr := RegexpSearchReplace(source, srchRgxp, replaceTpl); outStr != expectOut {
+ t.Error("Unexpected output from SearchReplace: ", outStr)
+ }
+}