github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/base64_finder.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"encoding/base64"
     8  	"regexp"
     9  	"strings"
    10  )
    11  
    12  type Base64Finder struct {
    13  	input        string
    14  	lines        []string
    15  	base64blocks []string
    16  }
    17  
    18  var b64FindRE = regexp.MustCompile(`^\s*(([a-zA-Z0-9/+_-]+)(={0,3}))\s*$`)
    19  
    20  func NewBase64Finder(i string) *Base64Finder {
    21  	return &Base64Finder{input: i}
    22  }
    23  
    24  func (s *Base64Finder) split() {
    25  	s.lines = strings.Split(s.input, "\n")
    26  }
    27  
    28  func (s *Base64Finder) findAll() {
    29  	i := 0
    30  	for i >= 0 {
    31  		var msg string
    32  		msg, i = s.findOne(i)
    33  		if len(msg) > 0 {
    34  			s.base64blocks = append(s.base64blocks, msg)
    35  		}
    36  	}
    37  }
    38  
    39  func (s *Base64Finder) search(searchFor []byte, url bool) bool {
    40  
    41  	var encoding *base64.Encoding
    42  
    43  	if url {
    44  		encoding = base64.URLEncoding
    45  	} else {
    46  		encoding = base64.StdEncoding
    47  	}
    48  
    49  	i := 0
    50  	for i >= 0 {
    51  		var msg string
    52  		msg, i = s.findOne(i)
    53  		if len(msg) > 0 {
    54  			buf, err := encoding.DecodeString(msg)
    55  			if err == nil && FastByteArrayEq(searchFor, buf) {
    56  				return true
    57  			}
    58  		}
    59  	}
    60  
    61  	return false
    62  }
    63  
    64  func (s *Base64Finder) findOne(i int) (string, int) {
    65  	var parts []string
    66  	l := len(s.lines)
    67  	state := 0
    68  
    69  	for ; i < l; i++ {
    70  		line := s.lines[i]
    71  		match := b64FindRE.FindStringSubmatch(line)
    72  		if match != nil {
    73  			state = 1
    74  			parts = append(parts, match[1])
    75  			if len(match[3]) > 0 {
    76  				// A terminal "=" character means jump on out
    77  				i++
    78  				break
    79  			}
    80  		} else if state == 1 {
    81  			break
    82  		}
    83  
    84  		// wait until next time
    85  	}
    86  	if i == l {
    87  		i = -1
    88  	}
    89  	ret := strings.Join(parts, "")
    90  	return ret, i
    91  }
    92  
    93  func (s *Base64Finder) Run() []string {
    94  	s.split()
    95  	s.findAll()
    96  	return s.base64blocks
    97  }
    98  
    99  func FindBase64Blocks(s string) []string {
   100  	eng := NewBase64Finder(s)
   101  	return eng.Run()
   102  }
   103  
   104  func FindFirstBase64Block(s string) string {
   105  	v := FindBase64Blocks(s)
   106  	if len(v) > 0 {
   107  		return v[0]
   108  	}
   109  	return ""
   110  }
   111  
   112  var snipRE = regexp.MustCompile(`(([a-zA-Z0-9/+_-]+)(={0,3}))`)
   113  
   114  func FindBase64Snippets(s string) []string {
   115  	return snipRE.FindAllString(s, -1)
   116  }
   117  
   118  func FindBase64Block(s string, pattern []byte, url bool) bool {
   119  	eng := NewBase64Finder(s)
   120  	eng.split()
   121  	return eng.search(pattern, url)
   122  }