1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) 2019 Maxime “pep” Buquet <pep@bouah.net>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use crate::core::{Base64, FromXml, IntoXml};
use crate::date::DateTime;
use crate::ns::OX;
use crate::pubsub::PubSubPayload;

/// Pubkey element to be used in PubSub publish payloads.
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = OX, name = "pubkey")]
pub struct PubKey {
    /// Last updated date
    #[xml(attribute)]
    pub date: Option<DateTime>,

    /// Public key as bytes
    #[xml(child(namespace = OX, name = "data", extract(text(codec = Base64))))]
    pub data: Vec<u8>,
}

impl PubSubPayload for PubKey {}

/// Public key metadata
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = OX, name = "pubkey-metadata")]
pub struct PubKeyMeta {
    /// OpenPGP v4 fingerprint
    #[xml(attribute = "v4-fingerprint")]
    pub v4fingerprint: String,

    /// Time the key was published or updated
    #[xml(attribute)]
    pub date: DateTime,
}

/// List of public key metadata
#[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
#[xml(namespace = OX, name = "public-key-list")]
pub struct PubKeysMeta {
    /// Public keys
    #[xml(children)]
    pub pubkeys: Vec<PubKeyMeta>,
}

impl PubSubPayload for PubKeysMeta {}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ns;
    use crate::pubsub::{
        pubsub::{Item, Publish},
        NodeName,
    };
    use crate::Element;
    use std::str::FromStr;

    #[test]
    fn pubsub_publish_pubkey_data() {
        let pubkey = PubKey {
            date: None,
            data: (&"Foo").as_bytes().to_vec(),
        };
        println!("Foo1: {:?}", pubkey);

        let pubsub = Publish {
            node: NodeName(format!("{}:{}", ns::OX_PUBKEYS, "some-fingerprint")),
            items: vec![Item::new(None, None, Some(pubkey))],
        };
        println!("Foo2: {:?}", pubsub);
    }

    #[test]
    fn pubsub_publish_pubkey_meta() {
        let pubkeymeta = PubKeysMeta {
            pubkeys: vec![PubKeyMeta {
                v4fingerprint: "some-fingerprint".to_owned(),
                date: DateTime::from_str("2019-03-30T18:30:25Z").unwrap(),
            }],
        };
        println!("Foo1: {:?}", pubkeymeta);

        let pubsub = Publish {
            node: NodeName("foo".to_owned()),
            items: vec![Item::new(None, None, Some(pubkeymeta))],
        };
        println!("Foo2: {:?}", pubsub);
    }

    #[test]
    fn test_serialize_pubkey() {
        let reference: Element = "<pubkey xmlns='urn:xmpp:openpgp:0'><data>AAAA</data></pubkey>"
            .parse()
            .unwrap();

        let pubkey = PubKey {
            date: None,
            data: b"\0\0\0".to_vec(),
        };

        let serialized: Element = pubkey.into();
        assert_eq!(serialized, reference);
    }
}