add vendoring
This commit is contained in:
88
vendor/github.com/jhillyerd/enmime/internal/stringutil/addr.go
generated
vendored
Normal file
88
vendor/github.com/jhillyerd/enmime/internal/stringutil/addr.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package stringutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/mail"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// JoinAddress formats a slice of Address structs such that they can be used in a To or Cc header.
|
||||
func JoinAddress(addrs []mail.Address) string {
|
||||
if len(addrs) == 0 {
|
||||
return ""
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
for i, a := range addrs {
|
||||
if i > 0 {
|
||||
_, _ = buf.WriteString(", ")
|
||||
}
|
||||
_, _ = buf.WriteString(a.String())
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// EnsureCommaDelimitedAddresses is used by AddressList to ensure that address lists are properly
|
||||
// delimited.
|
||||
func EnsureCommaDelimitedAddresses(s string) string {
|
||||
// This normalizes the whitespace, but may interfere with CFWS (comments with folding whitespace)
|
||||
// RFC-5322 3.4.0:
|
||||
// because some legacy implementations interpret the comment,
|
||||
// comments generally SHOULD NOT be used in address fields
|
||||
// to avoid confusing such implementations.
|
||||
s = strings.Join(strings.Fields(s), " ")
|
||||
|
||||
inQuotes := false
|
||||
inDomain := false
|
||||
escapeSequence := false
|
||||
sb := strings.Builder{}
|
||||
for i, r := range s {
|
||||
if escapeSequence {
|
||||
escapeSequence = false
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
if r == '"' {
|
||||
inQuotes = !inQuotes
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
if inQuotes {
|
||||
if r == '\\' {
|
||||
escapeSequence = true
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if r == '@' {
|
||||
inDomain = true
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
if inDomain {
|
||||
if r == ';' {
|
||||
inDomain = false
|
||||
if i == len(s)-1 {
|
||||
// omit trailing semicolon
|
||||
continue
|
||||
}
|
||||
|
||||
sb.WriteRune(',')
|
||||
continue
|
||||
}
|
||||
if r == ',' {
|
||||
inDomain = false
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
if r == ' ' {
|
||||
inDomain = false
|
||||
sb.WriteRune(',')
|
||||
sb.WriteRune(r)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.WriteRune(r)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
39
vendor/github.com/jhillyerd/enmime/internal/stringutil/find.go
generated
vendored
Normal file
39
vendor/github.com/jhillyerd/enmime/internal/stringutil/find.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package stringutil
|
||||
|
||||
// FindUnquoted returns the indexes of the instance of v in s, or empty slice if v is not present in s.
|
||||
// It ignores v present inside quoted runs.
|
||||
func FindUnquoted(s string, v rune, quote rune) []int {
|
||||
escaped := false
|
||||
quoted := false
|
||||
indexes := make([]int, 0)
|
||||
quotedIndexes := make([]int, 0)
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
switch rune(s[i]) {
|
||||
case escape:
|
||||
escaped = !escaped // escape can escape itself.
|
||||
case quote:
|
||||
if escaped {
|
||||
escaped = false
|
||||
continue
|
||||
}
|
||||
|
||||
quoted = !quoted
|
||||
if !quoted {
|
||||
quotedIndexes = quotedIndexes[:0] // drop possible indices inside quoted segment
|
||||
}
|
||||
case v:
|
||||
escaped = false
|
||||
if quoted {
|
||||
quotedIndexes = append(quotedIndexes, i)
|
||||
} else {
|
||||
indexes = append(indexes, i)
|
||||
}
|
||||
default:
|
||||
escaped = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return append(indexes, quotedIndexes...)
|
||||
}
|
||||
45
vendor/github.com/jhillyerd/enmime/internal/stringutil/split.go
generated
vendored
Normal file
45
vendor/github.com/jhillyerd/enmime/internal/stringutil/split.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package stringutil
|
||||
|
||||
const escape = '\\'
|
||||
|
||||
// SplitUnquoted slices s into all substrings separated by sep and returns a slice of
|
||||
// the substrings between those separators.
|
||||
//
|
||||
// If s does not contain sep and sep is not empty, SplitUnquoted returns a
|
||||
// slice of length 1 whose only element is s.
|
||||
//
|
||||
// It ignores sep present inside quoted runs.
|
||||
func SplitUnquoted(s string, sep rune, quote rune) []string {
|
||||
return splitUnquoted(s, sep, quote, false)
|
||||
}
|
||||
|
||||
// SplitAfterUnquoted slices s into all substrings after each instance of sep and
|
||||
// returns a slice of those substrings.
|
||||
//
|
||||
// If s does not contain sep and sep is not empty, SplitAfterUnquoted returns
|
||||
// a slice of length 1 whose only element is s.
|
||||
//
|
||||
// It ignores sep present inside quoted runs.
|
||||
func SplitAfterUnquoted(s string, sep rune, quote rune) []string {
|
||||
return splitUnquoted(s, sep, quote, true)
|
||||
}
|
||||
|
||||
func splitUnquoted(s string, sep rune, quote rune, preserveSep bool) []string {
|
||||
ixs := FindUnquoted(s, sep, quote)
|
||||
if len(ixs) == 0 {
|
||||
return []string{s}
|
||||
}
|
||||
|
||||
start := 0
|
||||
result := make([]string, 0, len(ixs)+1)
|
||||
for _, ix := range ixs {
|
||||
end := ix
|
||||
if preserveSep {
|
||||
end++
|
||||
}
|
||||
result = append(result, s[start:end])
|
||||
start = ix + 1
|
||||
}
|
||||
|
||||
return append(result, s[start:])
|
||||
}
|
||||
24
vendor/github.com/jhillyerd/enmime/internal/stringutil/uuid.go
generated
vendored
Normal file
24
vendor/github.com/jhillyerd/enmime/internal/stringutil/uuid.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package stringutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var uuidRand = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
var uuidMutex = &sync.Mutex{}
|
||||
|
||||
// UUID generates a random UUID according to RFC 4122.
|
||||
func UUID() string {
|
||||
uuid := make([]byte, 16)
|
||||
uuidMutex.Lock()
|
||||
_, _ = uuidRand.Read(uuid)
|
||||
uuidMutex.Unlock()
|
||||
// variant bits; see section 4.1.1
|
||||
uuid[8] = uuid[8]&^0xc0 | 0x80
|
||||
// version 4 (pseudo-random); see section 4.1.3
|
||||
uuid[6] = uuid[6]&^0xf0 | 0x40
|
||||
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
|
||||
}
|
||||
36
vendor/github.com/jhillyerd/enmime/internal/stringutil/wrap.go
generated
vendored
Normal file
36
vendor/github.com/jhillyerd/enmime/internal/stringutil/wrap.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package stringutil
|
||||
|
||||
// Wrap builds a byte slice from strs, wrapping on word boundaries before max chars
|
||||
func Wrap(max int, strs ...string) []byte {
|
||||
input := make([]byte, 0)
|
||||
output := make([]byte, 0)
|
||||
for _, s := range strs {
|
||||
input = append(input, []byte(s)...)
|
||||
}
|
||||
if len(input) < max {
|
||||
// Doesn't need to be wrapped
|
||||
return input
|
||||
}
|
||||
ls := -1 // Last seen space index
|
||||
lw := -1 // Last written byte index
|
||||
ll := 0 // Length of current line
|
||||
for i := 0; i < len(input); i++ {
|
||||
ll++
|
||||
switch input[i] {
|
||||
case ' ', '\t':
|
||||
ls = i
|
||||
}
|
||||
if ll >= max {
|
||||
if ls >= 0 {
|
||||
output = append(output, input[lw+1:ls]...)
|
||||
output = append(output, '\r', '\n', ' ')
|
||||
lw = ls // Jump over the space we broke on
|
||||
ll = 1 // Count leading space above
|
||||
// Rewind
|
||||
i = lw + 1
|
||||
ls = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
return append(output, input[lw+1:]...)
|
||||
}
|
||||
Reference in New Issue
Block a user