From 3fd954d185ef4637f882ca2801f9f5fdcb93117b Mon Sep 17 00:00:00 2001
From: Adlyq <2833154405@qq.com>
Date: Sun, 3 Sep 2023 22:00:37 +0800
Subject: [PATCH] feat: regexp2

---
 constant/rewrite.go |  2 +-
 rewrite/handler.go  | 17 +++++++++++------
 rewrite/parser.go   |  6 +++---
 rewrite/rewrite.go  | 21 +++++++++++++--------
 4 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/constant/rewrite.go b/constant/rewrite.go
index 06adde35..4caf0d8c 100644
--- a/constant/rewrite.go
+++ b/constant/rewrite.go
@@ -1,7 +1,7 @@
 package constant
 
 import (
-	"regexp"
+	regexp "github.com/dlclark/regexp2"
 )
 
 var RewriteTypeMapping = map[string]RewriteType{
diff --git a/rewrite/handler.go b/rewrite/handler.go
index ddbafeb9..2912a1d1 100644
--- a/rewrite/handler.go
+++ b/rewrite/handler.go
@@ -181,16 +181,21 @@ func matchRewriteRule(url string, isRequest bool) (rr C.Rewrite, sub []string, f
 	rewrites := tunnel.Rewrites()
 	if isRequest {
 		found = rewrites.SearchInRequest(func(r C.Rewrite) bool {
-			sub = r.URLRegx().FindStringSubmatch(url)
-			if len(sub) != 0 {
-				rr = r
-				return true
+			sub, err := r.URLRegx().FindStringMatch(url)
+			if err != nil {
+				return false
 			}
-			return false
+
+			rr = r
+			var groups []string
+			for _, fg := range sub.Groups() {
+				groups = append(groups, fg.String())
+			}
+			return true
 		})
 	} else {
 		found = rewrites.SearchInResponse(func(r C.Rewrite) bool {
-			if r.URLRegx().FindString(url) != "" {
+			if b, err := r.URLRegx().MatchString(url); b && err == nil {
 				rr = r
 				return true
 			}
diff --git a/rewrite/parser.go b/rewrite/parser.go
index f97134d3..09cf0396 100644
--- a/rewrite/parser.go
+++ b/rewrite/parser.go
@@ -1,7 +1,7 @@
 package rewrites
 
 import (
-	"regexp"
+	regexp "github.com/dlclark/regexp2"
 	"strings"
 
 	C "github.com/Dreamacro/clash/constant"
@@ -22,7 +22,7 @@ func ParseRewrite(line string) (C.Rewrite, error) {
 		err error
 	)
 
-	urlRegx, err = regexp.Compile(strings.Trim(url, " "))
+	urlRegx, err = regexp.Compile(strings.Trim(url, " "), regexp.None)
 	if err != nil {
 		return nil, err
 	}
@@ -50,7 +50,7 @@ func ParseRewrite(line string) (C.Rewrite, error) {
 			rulePayload = rs[0]
 			break
 		} else {
-			ruleRegx, err = regexp.Compile(rs[0])
+			ruleRegx, err = regexp.Compile(rs[0], regexp.None)
 			if err != nil {
 				return nil, err
 			}
diff --git a/rewrite/rewrite.go b/rewrite/rewrite.go
index d88d4efe..b53870ee 100644
--- a/rewrite/rewrite.go
+++ b/rewrite/rewrite.go
@@ -2,7 +2,7 @@ package rewrites
 
 import (
 	"errors"
-	"regexp"
+	regexp "github.com/dlclark/regexp2"
 	"strconv"
 	"strings"
 
@@ -61,18 +61,23 @@ func (r *RewriteRule) ReplaceSubPayload(oldData string) string {
 		return oldData
 	}
 
-	sub := r.ruleRegx.FindStringSubmatch(oldData)
-	l := len(sub)
-
-	if l == 0 {
+	sub, err := r.ruleRegx.FindStringMatch(oldData)
+	if err != nil {
 		return oldData
 	}
 
-	for i := 1; i < l; i++ {
-		payload = strings.ReplaceAll(payload, "$"+strconv.Itoa(i), sub[i])
+	var groups []string
+	for _, fg := range sub.Groups() {
+		groups = append(groups, fg.String())
 	}
 
-	return strings.ReplaceAll(oldData, sub[0], payload)
+	l := len(groups)
+
+	for i := 1; i < l; i++ {
+		payload = strings.ReplaceAll(payload, "$"+strconv.Itoa(i), groups[i])
+	}
+
+	return strings.ReplaceAll(oldData, groups[0], payload)
 }
 
 func NewRewriteRule(urlRegx *regexp.Regexp, ruleType C.RewriteType, ruleRegx *regexp.Regexp, rulePayload string) *RewriteRule {