...
1
2
3
4
5 package packet
6
7 import (
8 "io"
9 "strings"
10 )
11
12
13
14
15 type UserId struct {
16 Id string
17
18 Name, Comment, Email string
19 }
20
21 func hasInvalidCharacters(s string) bool {
22 for _, c := range s {
23 switch c {
24 case '(', ')', '<', '>', 0:
25 return true
26 }
27 }
28 return false
29 }
30
31
32
33 func NewUserId(name, comment, email string) *UserId {
34
35
36
37
38
39
40 if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
41 return nil
42 }
43
44 uid := new(UserId)
45 uid.Name, uid.Comment, uid.Email = name, comment, email
46 uid.Id = name
47 if len(comment) > 0 {
48 if len(uid.Id) > 0 {
49 uid.Id += " "
50 }
51 uid.Id += "("
52 uid.Id += comment
53 uid.Id += ")"
54 }
55 if len(email) > 0 {
56 if len(uid.Id) > 0 {
57 uid.Id += " "
58 }
59 uid.Id += "<"
60 uid.Id += email
61 uid.Id += ">"
62 }
63 return uid
64 }
65
66 func (uid *UserId) parse(r io.Reader) (err error) {
67
68 b, err := io.ReadAll(r)
69 if err != nil {
70 return
71 }
72 uid.Id = string(b)
73 uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
74 return
75 }
76
77
78
79 func (uid *UserId) Serialize(w io.Writer) error {
80 err := serializeHeader(w, packetTypeUserId, len(uid.Id))
81 if err != nil {
82 return err
83 }
84 _, err = w.Write([]byte(uid.Id))
85 return err
86 }
87
88
89
90 func parseUserId(id string) (name, comment, email string) {
91 var n, c, e struct {
92 start, end int
93 }
94 var state int
95
96 for offset, rune := range id {
97 switch state {
98 case 0:
99
100 n.start = offset
101 state = 1
102 fallthrough
103 case 1:
104
105 if rune == '(' {
106 state = 2
107 n.end = offset
108 } else if rune == '<' {
109 state = 5
110 n.end = offset
111 }
112 case 2:
113
114 c.start = offset
115 state = 3
116 fallthrough
117 case 3:
118
119 if rune == ')' {
120 state = 4
121 c.end = offset
122 }
123 case 4:
124
125 if rune == '<' {
126 state = 5
127 }
128 case 5:
129
130 e.start = offset
131 state = 6
132 fallthrough
133 case 6:
134
135 if rune == '>' {
136 state = 7
137 e.end = offset
138 }
139 default:
140
141 }
142 }
143 switch state {
144 case 1:
145
146 n.end = len(id)
147 case 3:
148
149 c.end = len(id)
150 case 6:
151
152 e.end = len(id)
153 }
154
155 name = strings.TrimSpace(id[n.start:n.end])
156 comment = strings.TrimSpace(id[c.start:c.end])
157 email = strings.TrimSpace(id[e.start:e.end])
158 return
159 }
160
View as plain text