]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/golang.org/x/crypto/openpgp/packet/userid.go
vendor: github.com/hashicorp/terraform/...@v0.10.0
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / crypto / openpgp / packet / userid.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package packet
6
7 import (
8 "io"
9 "io/ioutil"
10 "strings"
11 )
12
13 // UserId contains text that is intended to represent the name and email
14 // address of the key holder. See RFC 4880, section 5.11. By convention, this
15 // takes the form "Full Name (Comment) <email@example.com>"
16 type UserId struct {
17 Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
18
19 Name, Comment, Email string
20 }
21
22 func hasInvalidCharacters(s string) bool {
23 for _, c := range s {
24 switch c {
25 case '(', ')', '<', '>', 0:
26 return true
27 }
28 }
29 return false
30 }
31
32 // NewUserId returns a UserId or nil if any of the arguments contain invalid
33 // characters. The invalid characters are '\x00', '(', ')', '<' and '>'
34 func NewUserId(name, comment, email string) *UserId {
35 // RFC 4880 doesn't deal with the structure of userid strings; the
36 // name, comment and email form is just a convention. However, there's
37 // no convention about escaping the metacharacters and GPG just refuses
38 // to create user ids where, say, the name contains a '('. We mirror
39 // this behaviour.
40
41 if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
42 return nil
43 }
44
45 uid := new(UserId)
46 uid.Name, uid.Comment, uid.Email = name, comment, email
47 uid.Id = name
48 if len(comment) > 0 {
49 if len(uid.Id) > 0 {
50 uid.Id += " "
51 }
52 uid.Id += "("
53 uid.Id += comment
54 uid.Id += ")"
55 }
56 if len(email) > 0 {
57 if len(uid.Id) > 0 {
58 uid.Id += " "
59 }
60 uid.Id += "<"
61 uid.Id += email
62 uid.Id += ">"
63 }
64 return uid
65 }
66
67 func (uid *UserId) parse(r io.Reader) (err error) {
68 // RFC 4880, section 5.11
69 b, err := ioutil.ReadAll(r)
70 if err != nil {
71 return
72 }
73 uid.Id = string(b)
74 uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
75 return
76 }
77
78 // Serialize marshals uid to w in the form of an OpenPGP packet, including
79 // header.
80 func (uid *UserId) Serialize(w io.Writer) error {
81 err := serializeHeader(w, packetTypeUserId, len(uid.Id))
82 if err != nil {
83 return err
84 }
85 _, err = w.Write([]byte(uid.Id))
86 return err
87 }
88
89 // parseUserId extracts the name, comment and email from a user id string that
90 // is formatted as "Full Name (Comment) <email@example.com>".
91 func parseUserId(id string) (name, comment, email string) {
92 var n, c, e struct {
93 start, end int
94 }
95 var state int
96
97 for offset, rune := range id {
98 switch state {
99 case 0:
100 // Entering name
101 n.start = offset
102 state = 1
103 fallthrough
104 case 1:
105 // In name
106 if rune == '(' {
107 state = 2
108 n.end = offset
109 } else if rune == '<' {
110 state = 5
111 n.end = offset
112 }
113 case 2:
114 // Entering comment
115 c.start = offset
116 state = 3
117 fallthrough
118 case 3:
119 // In comment
120 if rune == ')' {
121 state = 4
122 c.end = offset
123 }
124 case 4:
125 // Between comment and email
126 if rune == '<' {
127 state = 5
128 }
129 case 5:
130 // Entering email
131 e.start = offset
132 state = 6
133 fallthrough
134 case 6:
135 // In email
136 if rune == '>' {
137 state = 7
138 e.end = offset
139 }
140 default:
141 // After email
142 }
143 }
144 switch state {
145 case 1:
146 // ended in the name
147 n.end = len(id)
148 case 3:
149 // ended in comment
150 c.end = len(id)
151 case 6:
152 // ended in email
153 e.end = len(id)
154 }
155
156 name = strings.TrimSpace(id[n.start:n.end])
157 comment = strings.TrimSpace(id[c.start:c.end])
158 email = strings.TrimSpace(id[e.start:e.end])
159 return
160 }