github.com/yaling888/clash@v1.53.0/mitm/rewrite.go (about)

     1  package mitm
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"strings"
     7  
     8  	regexp "github.com/dlclark/regexp2"
     9  
    10  	C "github.com/yaling888/clash/constant"
    11  )
    12  
    13  var errInvalid = errors.New("invalid rewrite rule")
    14  
    15  type RewriteRule struct {
    16  	urlRegx     *regexp.Regexp
    17  	ruleType    C.RewriteType
    18  	ruleRegx    []*regexp.Regexp
    19  	rulePayload []string
    20  }
    21  
    22  func (r *RewriteRule) URLRegx() *regexp.Regexp {
    23  	return r.urlRegx
    24  }
    25  
    26  func (r *RewriteRule) RuleType() C.RewriteType {
    27  	return r.ruleType
    28  }
    29  
    30  func (r *RewriteRule) RuleRegx() []*regexp.Regexp {
    31  	return r.ruleRegx
    32  }
    33  
    34  func (r *RewriteRule) RulePayload() []string {
    35  	return r.rulePayload
    36  }
    37  
    38  func (r *RewriteRule) ReplaceURLPayload(matchSub []string) string {
    39  	if len(r.RulePayload()) == 0 {
    40  		return ""
    41  	}
    42  	url := r.RulePayload()[0]
    43  	l := len(matchSub)
    44  	if l < 2 {
    45  		return url
    46  	}
    47  
    48  	for i := 1; i < l; i++ {
    49  		url = strings.ReplaceAll(url, "$"+strconv.Itoa(i), matchSub[i])
    50  	}
    51  	return url
    52  }
    53  
    54  func (r *RewriteRule) ReplaceSubPayload(oldData string) (string, bool) {
    55  	if r.ruleRegx == nil || r.rulePayload == nil {
    56  		return oldData, false
    57  	}
    58  
    59  	var (
    60  		ok      bool
    61  		payload string
    62  	)
    63  	for i, pl := 0, len(r.rulePayload); i < len(r.ruleRegx); i++ {
    64  		regx := r.ruleRegx[i]
    65  		if i < pl {
    66  			payload = r.rulePayload[i]
    67  		}
    68  
    69  		// sub := r.ruleRegx.FindStringSubmatch(oldData) // std
    70  		sub := findStringSubmatch(regx, oldData)
    71  		l := len(sub)
    72  
    73  		if l == 0 {
    74  			continue
    75  		}
    76  
    77  		ok = true
    78  		newPayload := payload
    79  		for j := 1; j < l; j++ {
    80  			newPayload = strings.ReplaceAll(newPayload, "$"+strconv.Itoa(j), sub[j])
    81  		}
    82  
    83  		oldData = strings.ReplaceAll(oldData, sub[0], newPayload)
    84  	}
    85  
    86  	return oldData, ok
    87  }
    88  
    89  func NewRewriteRule(urlRegx *regexp.Regexp, ruleType C.RewriteType, ruleRegx []*regexp.Regexp, rulePayload []string) *RewriteRule {
    90  	return &RewriteRule{
    91  		urlRegx:     urlRegx,
    92  		ruleType:    ruleType,
    93  		ruleRegx:    ruleRegx,
    94  		rulePayload: rulePayload,
    95  	}
    96  }
    97  
    98  var _ C.Rewrite = (*RewriteRule)(nil)