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