gitee.com/lonely0422/gometalinter.git@v3.0.1-0.20190307123442-32416ab75314+incompatible/_linters/src/github.com/nbutton23/zxcvbn-go/matching/dateMatchers.go (about)

     1  package matching
     2  
     3  import (
     4  	"regexp"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/nbutton23/zxcvbn-go/entropy"
     9  	"github.com/nbutton23/zxcvbn-go/match"
    10  )
    11  
    12  const (
    13  	DATESEP_MATCHER_NAME        = "DATESEP"
    14  	DATEWITHOUTSEP_MATCHER_NAME = "DATEWITHOUT"
    15  )
    16  
    17  func FilterDateSepMatcher(m match.Matcher) bool {
    18  	return m.ID == DATESEP_MATCHER_NAME
    19  }
    20  
    21  func FilterDateWithoutSepMatcher(m match.Matcher) bool {
    22  	return m.ID == DATEWITHOUTSEP_MATCHER_NAME
    23  }
    24  
    25  func checkDate(day, month, year int64) (bool, int64, int64, int64) {
    26  	if (12 <= month && month <= 31) && day <= 12 {
    27  		day, month = month, day
    28  	}
    29  
    30  	if day > 31 || month > 12 {
    31  		return false, 0, 0, 0
    32  	}
    33  
    34  	if !((1900 <= year && year <= 2019) || (0 <= year && year <= 99)) {
    35  		return false, 0, 0, 0
    36  	}
    37  
    38  	return true, day, month, year
    39  }
    40  
    41  func dateSepMatcher(password string) []match.Match {
    42  	dateMatches := dateSepMatchHelper(password)
    43  
    44  	var matches []match.Match
    45  	for _, dateMatch := range dateMatches {
    46  		match := match.Match{
    47  			I:              dateMatch.I,
    48  			J:              dateMatch.J,
    49  			Entropy:        entropy.DateEntropy(dateMatch),
    50  			DictionaryName: "date_match",
    51  			Token:          dateMatch.Token,
    52  		}
    53  
    54  		matches = append(matches, match)
    55  	}
    56  
    57  	return matches
    58  }
    59  func dateSepMatchHelper(password string) []match.DateMatch {
    60  
    61  	var matches []match.DateMatch
    62  
    63  	matcher := regexp.MustCompile(DATE_RX_YEAR_SUFFIX)
    64  	for _, v := range matcher.FindAllString(password, len(password)) {
    65  		splitV := matcher.FindAllStringSubmatch(v, len(v))
    66  		i := strings.Index(password, v)
    67  		j := i + len(v)
    68  		day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
    69  		month, _ := strconv.ParseInt(splitV[0][2], 10, 16)
    70  		year, _ := strconv.ParseInt(splitV[0][6], 10, 16)
    71  		match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]}
    72  		matches = append(matches, match)
    73  	}
    74  
    75  	matcher = regexp.MustCompile(DATE_RX_YEAR_PREFIX)
    76  	for _, v := range matcher.FindAllString(password, len(password)) {
    77  		splitV := matcher.FindAllStringSubmatch(v, len(v))
    78  		i := strings.Index(password, v)
    79  		j := i + len(v)
    80  		day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
    81  		month, _ := strconv.ParseInt(splitV[0][6], 10, 16)
    82  		year, _ := strconv.ParseInt(splitV[0][2], 10, 16)
    83  		match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j, Token: password[i:j]}
    84  		matches = append(matches, match)
    85  	}
    86  
    87  	var out []match.DateMatch
    88  	for _, match := range matches {
    89  		if valid, day, month, year := checkDate(match.Day, match.Month, match.Year); valid {
    90  			match.Pattern = "date"
    91  			match.Day = day
    92  			match.Month = month
    93  			match.Year = year
    94  			out = append(out, match)
    95  		}
    96  	}
    97  	return out
    98  
    99  }
   100  
   101  type DateMatchCandidate struct {
   102  	DayMonth string
   103  	Year     string
   104  	I, J     int
   105  }
   106  
   107  type DateMatchCandidateTwo struct {
   108  	Day   string
   109  	Month string
   110  	Year  string
   111  	I, J  int
   112  }
   113  
   114  func dateWithoutSepMatch(password string) []match.Match {
   115  	dateMatches := dateWithoutSepMatchHelper(password)
   116  
   117  	var matches []match.Match
   118  	for _, dateMatch := range dateMatches {
   119  		match := match.Match{
   120  			I:              dateMatch.I,
   121  			J:              dateMatch.J,
   122  			Entropy:        entropy.DateEntropy(dateMatch),
   123  			DictionaryName: "date_match",
   124  			Token:          dateMatch.Token,
   125  		}
   126  
   127  		matches = append(matches, match)
   128  	}
   129  
   130  	return matches
   131  }
   132  
   133  //TODO Has issues with 6 digit dates
   134  func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) {
   135  	matcher := regexp.MustCompile(DATE_WITHOUT_SEP_MATCH)
   136  	for _, v := range matcher.FindAllString(password, len(password)) {
   137  		i := strings.Index(password, v)
   138  		j := i + len(v)
   139  		length := len(v)
   140  		lastIndex := length - 1
   141  		var candidatesRoundOne []DateMatchCandidate
   142  
   143  		if length <= 6 {
   144  			//2-digit year prefix
   145  			candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j))
   146  
   147  			//2-digityear suffix
   148  			candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-2], v[lastIndex-2:], i, j))
   149  		}
   150  		if length >= 6 {
   151  			//4-digit year prefix
   152  			candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j))
   153  
   154  			//4-digit year sufix
   155  			candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-3], v[lastIndex-3:], i, j))
   156  		}
   157  
   158  		var candidatesRoundTwo []DateMatchCandidateTwo
   159  		for _, c := range candidatesRoundOne {
   160  			if len(c.DayMonth) == 2 {
   161  				candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:1], c.Year, c.I, c.J))
   162  			} else if len(c.DayMonth) == 3 {
   163  				candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:2], c.Year, c.I, c.J))
   164  				candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:0], c.DayMonth[1:3], c.Year, c.I, c.J))
   165  			} else if len(c.DayMonth) == 4 {
   166  				candidatesRoundTwo = append(candidatesRoundTwo, buildDateMatchCandidateTwo(c.DayMonth[0:2], c.DayMonth[2:4], c.Year, c.I, c.J))
   167  			}
   168  		}
   169  
   170  		for _, candidate := range candidatesRoundTwo {
   171  			intDay, err := strconv.ParseInt(candidate.Day, 10, 16)
   172  			if err != nil {
   173  				continue
   174  			}
   175  
   176  			intMonth, err := strconv.ParseInt(candidate.Month, 10, 16)
   177  
   178  			if err != nil {
   179  				continue
   180  			}
   181  
   182  			intYear, err := strconv.ParseInt(candidate.Year, 10, 16)
   183  			if err != nil {
   184  				continue
   185  			}
   186  
   187  			if ok, _, _, _ := checkDate(intDay, intMonth, intYear); ok {
   188  				matches = append(matches, match.DateMatch{Token: password, Pattern: "date", Day: intDay, Month: intMonth, Year: intYear, I: i, J: j})
   189  			}
   190  
   191  		}
   192  	}
   193  
   194  	return matches
   195  }
   196  
   197  func buildDateMatchCandidate(dayMonth, year string, i, j int) DateMatchCandidate {
   198  	return DateMatchCandidate{DayMonth: dayMonth, Year: year, I: i, J: j}
   199  }
   200  
   201  func buildDateMatchCandidateTwo(day, month string, year string, i, j int) DateMatchCandidateTwo {
   202  
   203  	return DateMatchCandidateTwo{Day: day, Month: month, Year: year, I: i, J: j}
   204  }