amuz.es/src/go/misc@v1.0.1/strutil/mask.go (about)

     1  package strutil
     2  
     3  import (
     4  	"math"
     5  	"regexp"
     6  	"strings"
     7  	"unicode/utf8"
     8  )
     9  
    10  var (
    11  	// EmailRegex is the standard email address format.
    12  	EmailRegex = regexp.MustCompile(`^([^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*)@(?:(?:[a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})$`)
    13  	// DigitRegex represents a digit.
    14  	DigitRegex = regexp.MustCompile(`\d`)
    15  )
    16  
    17  // MaskText is a masking function for hide sensitive data.
    18  func MaskText(src string) (val string) {
    19  
    20  	var dst strings.Builder
    21  	defer func(ptr *string) { *ptr = dst.String() }(&val)
    22  
    23  	// email
    24  	if ret := EmailRegex.FindAllStringSubmatchIndex(src, -1); len(ret) > 0 {
    25  		start := src[:ret[0][2]]
    26  		username := src[ret[0][2]:ret[0][3]]
    27  		end := src[ret[0][3]:]
    28  		length := utf8.RuneCountInString(username)
    29  		_, firstCharLength := utf8.DecodeRuneInString(username)
    30  		_, lastCharLength := utf8.DecodeLastRuneInString(username)
    31  		_, secondLastCharLength := utf8.DecodeLastRuneInString(username[:len(username)-lastCharLength])
    32  		dst.WriteString(start)
    33  		if length > 3 {
    34  			dst.WriteString(username[:firstCharLength])
    35  			for i := 0; i < length-3; i++ {
    36  				dst.WriteByte('*')
    37  			}
    38  			dst.WriteString(username[len(username)-(secondLastCharLength+lastCharLength):])
    39  		} else {
    40  			dst.WriteByte('*')
    41  			dst.WriteString(username[firstCharLength:])
    42  		}
    43  		dst.WriteString(end)
    44  	} else if ret = DigitRegex.FindAllStringSubmatchIndex(src, -1); len(ret) > 2 {
    45  		var (
    46  			offset     = 0
    47  			factor     = float64(len(ret)) / 3.0
    48  			pos        = int(math.Floor(factor))
    49  			fillLength = int(math.Ceil(factor))
    50  		)
    51  		for i := pos; i < pos+fillLength; i++ {
    52  			dst.WriteString(src[offset:ret[i][0]])
    53  			dst.WriteByte('*')
    54  			offset = ret[i][1]
    55  		}
    56  		dst.WriteString(src[offset:])
    57  	} else {
    58  		length := utf8.RuneCountInString(src)
    59  		_, firstCharLength := utf8.DecodeRuneInString(src)
    60  		_, lastCharLength := utf8.DecodeLastRuneInString(src)
    61  		if length > 2 {
    62  			dst.WriteString(src[:firstCharLength])
    63  			for i := 0; i < length-2; i++ {
    64  				dst.WriteByte('*')
    65  			}
    66  			dst.WriteString(src[len(src)-lastCharLength:])
    67  		} else if length > 0 {
    68  			dst.WriteByte('*')
    69  			dst.WriteString(src[firstCharLength:])
    70  		}
    71  	}
    72  
    73  	return
    74  }