]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/golang.org/x/crypto/openpgp/packet/userid.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / crypto / openpgp / packet / userid.go
CommitLineData
c680a8e1
RS
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
5package packet
6
7import (
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>"
16type 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
22func 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 '>'
34func 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
67func (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.
80func (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>".
91func 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}