]>
Commit | Line | Data |
---|---|---|
c680a8e1 RS |
1 | // Copyright 2013 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 | "bytes" | |
9 | "image" | |
10 | "image/jpeg" | |
11 | "io" | |
12 | "io/ioutil" | |
13 | ) | |
14 | ||
15 | const UserAttrImageSubpacket = 1 | |
16 | ||
17 | // UserAttribute is capable of storing other types of data about a user | |
18 | // beyond name, email and a text comment. In practice, user attributes are typically used | |
19 | // to store a signed thumbnail photo JPEG image of the user. | |
20 | // See RFC 4880, section 5.12. | |
21 | type UserAttribute struct { | |
22 | Contents []*OpaqueSubpacket | |
23 | } | |
24 | ||
25 | // NewUserAttributePhoto creates a user attribute packet | |
26 | // containing the given images. | |
27 | func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { | |
28 | uat = new(UserAttribute) | |
29 | for _, photo := range photos { | |
30 | var buf bytes.Buffer | |
31 | // RFC 4880, Section 5.12.1. | |
32 | data := []byte{ | |
33 | 0x10, 0x00, // Little-endian image header length (16 bytes) | |
34 | 0x01, // Image header version 1 | |
35 | 0x01, // JPEG | |
36 | 0, 0, 0, 0, // 12 reserved octets, must be all zero. | |
37 | 0, 0, 0, 0, | |
38 | 0, 0, 0, 0} | |
39 | if _, err = buf.Write(data); err != nil { | |
40 | return | |
41 | } | |
42 | if err = jpeg.Encode(&buf, photo, nil); err != nil { | |
43 | return | |
44 | } | |
45 | uat.Contents = append(uat.Contents, &OpaqueSubpacket{ | |
46 | SubType: UserAttrImageSubpacket, | |
47 | Contents: buf.Bytes()}) | |
48 | } | |
49 | return | |
50 | } | |
51 | ||
52 | // NewUserAttribute creates a new user attribute packet containing the given subpackets. | |
53 | func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { | |
54 | return &UserAttribute{Contents: contents} | |
55 | } | |
56 | ||
57 | func (uat *UserAttribute) parse(r io.Reader) (err error) { | |
58 | // RFC 4880, section 5.13 | |
59 | b, err := ioutil.ReadAll(r) | |
60 | if err != nil { | |
61 | return | |
62 | } | |
63 | uat.Contents, err = OpaqueSubpackets(b) | |
64 | return | |
65 | } | |
66 | ||
67 | // Serialize marshals the user attribute to w in the form of an OpenPGP packet, including | |
68 | // header. | |
69 | func (uat *UserAttribute) Serialize(w io.Writer) (err error) { | |
70 | var buf bytes.Buffer | |
71 | for _, sp := range uat.Contents { | |
72 | sp.Serialize(&buf) | |
73 | } | |
74 | if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { | |
75 | return err | |
76 | } | |
77 | _, err = w.Write(buf.Bytes()) | |
78 | return | |
79 | } | |
80 | ||
81 | // ImageData returns zero or more byte slices, each containing | |
82 | // JPEG File Interchange Format (JFIF), for each photo in the | |
107c1cdb | 83 | // user attribute packet. |
c680a8e1 RS |
84 | func (uat *UserAttribute) ImageData() (imageData [][]byte) { |
85 | for _, sp := range uat.Contents { | |
86 | if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { | |
87 | imageData = append(imageData, sp.Contents[16:]) | |
88 | } | |
89 | } | |
90 | return | |
91 | } |