~ubuntu-branches/ubuntu/utopic/hockeypuck/utopic-proposed

« back to all changes in this revision

Viewing changes to openpgp/merge.go

  • Committer: Package Import Robot
  • Author(s): Casey Marshall
  • Date: 2014-04-13 20:06:01 UTC
  • Revision ID: package-import@ubuntu.com-20140413200601-oxdlqn1gy0x8m55u
Tags: 1.0~rel20140413+7a1892a~trusty
Hockeypuck 1.0 release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Hockeypuck - OpenPGP key server
 
3
   Copyright (C) 2012-2014  Casey Marshall
 
4
 
 
5
   This program is free software: you can redistribute it and/or modify
 
6
   it under the terms of the GNU Affero General Public License as published by
 
7
   the Free Software Foundation, version 3.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU Affero General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU Affero General Public License
 
15
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
*/
 
17
 
 
18
package openpgp
 
19
 
 
20
import (
 
21
        "errors"
 
22
)
 
23
 
 
24
type PacketRecordMap map[string]PacketRecord
 
25
 
 
26
var ErrMissingUuid error = errors.New("Packet record missing content-unique identifier")
 
27
 
 
28
func GetUuid(rec PacketRecord) string {
 
29
        switch r := rec.(type) {
 
30
        case *Pubkey:
 
31
                return r.RFingerprint
 
32
        case *Signature:
 
33
                return r.ScopedDigest
 
34
        case *UserId:
 
35
                return r.ScopedDigest
 
36
        case *UserAttribute:
 
37
                return r.ScopedDigest
 
38
        case *Subkey:
 
39
                return r.RFingerprint
 
40
        }
 
41
        return ""
 
42
}
 
43
 
 
44
func (m PacketRecordMap) Add(rec PacketRecord) error {
 
45
        uuid := GetUuid(rec)
 
46
        if uuid == "" {
 
47
                return ErrMissingUuid
 
48
        } else if _, ok := m[uuid]; !ok {
 
49
                m[uuid] = rec
 
50
        }
 
51
        return nil
 
52
}
 
53
 
 
54
// Map a tree of packet objects by strong hash.
 
55
func MapKey(pubkey *Pubkey) PacketRecordMap {
 
56
        m := make(PacketRecordMap)
 
57
        pubkey.Visit(m.Add)
 
58
        return m
 
59
}
 
60
 
 
61
// Merge the contents of srcKey into dstKey, modifying in-place.
 
62
// Packets in src not found in dst are appended to the matching parent.
 
63
// Conflicting packets and unmatched parents are ignored.
 
64
func MergeKey(dstKey *Pubkey, srcKey *Pubkey) {
 
65
        dstObjects := MapKey(dstKey)
 
66
        // Track source signable object in source traversal
 
67
        var srcSignable PacketRecord
 
68
        srcKey.Visit(func(srcObj PacketRecord) error {
 
69
                // Match in destination tree
 
70
                _, dstHas := dstObjects[GetUuid(srcObj)]
 
71
                switch so := srcObj.(type) {
 
72
                case *Pubkey:
 
73
                        srcSignable = so
 
74
                case *Subkey:
 
75
                        srcSignable = so
 
76
                        if !dstHas {
 
77
                                dstKey.subkeys = append(dstKey.subkeys, so)
 
78
                        }
 
79
                case *UserId:
 
80
                        srcSignable = so
 
81
                        if !dstHas {
 
82
                                dstKey.userIds = append(dstKey.userIds, so)
 
83
                        }
 
84
                case *UserAttribute:
 
85
                        srcSignable = so
 
86
                        if !dstHas {
 
87
                                dstKey.userAttributes = append(dstKey.userAttributes, so)
 
88
                        }
 
89
                case *Signature:
 
90
                        dstParent, dstHasParent := dstObjects[GetUuid(srcSignable)]
 
91
                        dstSignable, isSignable := dstParent.(Signable)
 
92
                        if !dstHas && dstHasParent && isSignable {
 
93
                                dstSignable.AddSignature(so)
 
94
                        }
 
95
                }
 
96
                return nil
 
97
        })
 
98
        dstKey.updateDigests()
 
99
        Resolve(dstKey)
 
100
}