1
0
mirror of https://github.com/golang/go synced 2024-11-25 01:57:56 -07:00

crypto/openpgp/packet: add UserId packet type

This was split from CL 4124054

R=bradfitzgo
CC=golang-dev
https://golang.org/cl/4126057
This commit is contained in:
Adam Langley 2011-02-07 21:40:33 -05:00
parent e26b741523
commit 1b8d373463
2 changed files with 147 additions and 0 deletions

View File

@ -0,0 +1,105 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"io"
"io/ioutil"
"os"
"strings"
)
// UserId contains text that is intended to represent the name and email
// address of the key holder. See RFC 4880, section 5.11. By convention, this
// takes the form "Full Name (Comment) <email@example.com>"
type UserId struct {
Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
Name, Comment, Email string
}
func (uid *UserId) parse(r io.Reader) (err os.Error) {
// RFC 4880, section 5.11
b, err := ioutil.ReadAll(r)
if err != nil {
return
}
uid.Id = string(b)
uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
return
}
// parseUserId extracts the name, comment and email from a user id string that
// is formatted as "Full Name (Comment) <email@example.com>".
func parseUserId(id string) (name, comment, email string) {
var n, c, e struct {
start, end int
}
var state int
for offset, rune := range id {
switch state {
case 0:
// Entering name
n.start = offset
state = 1
fallthrough
case 1:
// In name
if rune == '(' {
state = 2
n.end = offset
} else if rune == '<' {
state = 5
n.end = offset
}
case 2:
// Entering comment
c.start = offset
state = 3
fallthrough
case 3:
// In comment
if rune == ')' {
state = 4
c.end = offset
}
case 4:
// Between comment and email
if rune == '<' {
state = 5
}
case 5:
// Entering email
e.start = offset
state = 6
fallthrough
case 6:
// In email
if rune == '>' {
state = 7
e.end = offset
}
default:
// After email
}
}
switch state {
case 1:
// ended in the name
n.end = len(id)
case 3:
// ended in comment
c.end = len(id)
case 6:
// ended in email
e.end = len(id)
}
name = strings.TrimSpace(id[n.start:n.end])
comment = strings.TrimSpace(id[c.start:c.end])
email = strings.TrimSpace(id[e.start:e.end])
return
}

View File

@ -0,0 +1,42 @@
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"testing"
)
var userIdTests = []struct {
id string
name, comment, email string
}{
{"", "", "", ""},
{"John Smith", "John Smith", "", ""},
{"John Smith ()", "John Smith", "", ""},
{"John Smith () <>", "John Smith", "", ""},
{"(comment", "", "comment", ""},
{"(comment)", "", "comment", ""},
{"<email", "", "", "email"},
{"<email> sdfk", "", "", "email"},
{" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
{" John Smith < email > lksdfj", "John Smith", "", "email"},
{"(<foo", "", "<foo", ""},
{"René Descartes (العربي)", "René Descartes", "العربي", ""},
}
func TestParseUserId(t *testing.T) {
for i, test := range userIdTests {
name, comment, email := parseUserId(test.id)
if name != test.name {
t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
}
if comment != test.comment {
t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
}
if email != test.email {
t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
}
}
}