diff --git a/utils/consts.go b/utils/consts.go index 17313729e..5891e363c 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -724,6 +724,7 @@ const ( MetaSIPURIUser = "*sipuri_user" E164DomainConverter = "*e164Domain" E164Converter = "*e164" + UrlDecConverter = "*urldecode" MetaReload = "*reload" MetaLoad = "*load" MetaFloat64 = "*float64" diff --git a/utils/dataconverter.go b/utils/dataconverter.go index 65844eba1..e2865a913 100644 --- a/utils/dataconverter.go +++ b/utils/dataconverter.go @@ -25,6 +25,7 @@ import ( "fmt" "math/rand" "net" + "net/url" "strconv" "strings" "time" @@ -106,6 +107,8 @@ func NewDataConverter(params string) (conv DataConverter, err error) { return new(e164DomainConverter), nil case params == E164Converter: return new(e164Converter), nil + case params == UrlDecConverter: + return new(UrlDecodeConverter), nil case strings.HasPrefix(params, MetaLibPhoneNumber): if len(params) == len(MetaLibPhoneNumber) { return NewPhoneNumberConverter(EmptyString) @@ -752,3 +755,15 @@ func (sc StripConverter) Convert(in any) (any, error) { return EmptyString, errors.New("strip converter: invalid side parameter") } } + +// UrlDecodeConverter converts an URL with encoded special characters back to original string. +type UrlDecodeConverter struct{} + +func (UrlDecodeConverter) Convert(in any) (any, error) { + urlStr := IfaceAsString(in) + query, err := url.QueryUnescape(urlStr) + if err != nil { + return nil, err + } + return query, nil +} diff --git a/utils/dataconverter_test.go b/utils/dataconverter_test.go index a7df03030..aa53b46dd 100644 --- a/utils/dataconverter_test.go +++ b/utils/dataconverter_test.go @@ -1643,3 +1643,52 @@ func TestStripConverter(t *testing.T) { }) } } + +func TestURlConverter(t *testing.T) { + tests := []struct { + name string + input string + expected string + isError bool + }{ + { + name: "Decode string with escaped $ character", + input: "123%24123", + expected: "123$123", + isError: false, + }, + { + name: "Wrong escaped character", + input: "a%2Fdestination%user%26password%2Cid", + expected: "invalid URL escape \"%us\"", + isError: true, + }, + { + name: "Decode string with multiple escaped characters", + input: "query=%40special%23characters%24", + expected: "query=@special#characters$", + isError: false, + }, + } + conv, err := NewDataConverter(UrlDecConverter) + if err != nil { + t.Fatal(err) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rcv, err := conv.Convert(tt.input) + if (err != nil) != tt.isError { + t.Errorf("Convert() error =%v,expected err %v", err, tt.isError) + } + if tt.isError { + if err.Error() != tt.expected { + t.Errorf("expected error message: %s, received: %s", tt.expected, err.Error()) + } + return + } + if rcv != tt.expected { + t.Errorf("expected: %q, received: %q", tt.expected, rcv) + } + }) + } +}