aboutsummaryrefslogtreecommitdiffstats
path: root/filamento/src/caps.rs
diff options
context:
space:
mode:
Diffstat (limited to 'filamento/src/caps.rs')
-rw-r--r--filamento/src/caps.rs117
1 files changed, 105 insertions, 12 deletions
diff --git a/filamento/src/caps.rs b/filamento/src/caps.rs
index a0709eb..49d05ba 100644
--- a/filamento/src/caps.rs
+++ b/filamento/src/caps.rs
@@ -13,10 +13,41 @@ use stanza::{
use tracing::trace;
use crate::{
- disco::{Identity, Info, identity::Category},
- error::{CapsDecodeError, CapsEncodeError, HashNodeConversionError},
+ disco::{
+ Identity, Info,
+ identity::{self, Category},
+ },
+ error::{CapsDecodeError, CapsEncodeError, CapsNodeConversionError, HashNodeConversionError},
};
+pub const CLIENT_URI: &str = "https://bunny.garden/filamento";
+
+// <c xmlns="http://jabber.org/protocol/caps" hash="sha-1" ver="mSavc/SLnHm8zazs5RlcbD/iXoc=" node="https://bunny.garden/filamento"/>
+pub fn c() -> C {
+ caps(CLIENT_URI.to_string(), client_info().into()).unwrap()
+}
+
+pub fn caps_node() -> String {
+ caps_to_node(c())
+}
+
+pub fn client_info() -> Info {
+ Info {
+ node: None,
+ features: vec![
+ "http://jabber.org/protocol/disco#items".to_string(),
+ "http://jabber.org/protocol/disco#info".to_string(),
+ "http://jabber.org/protocol/caps".to_string(),
+ "http://jabber.org/protocol/nick".to_string(),
+ "http://jabber.org/protocol/nick+notify".to_string(),
+ ],
+ identities: vec![Identity {
+ name: Some("filamento 0.1.0".to_string()),
+ category: Category::Client(identity::Client::PC),
+ }],
+ }
+}
+
pub fn caps(node: String, query: info::Query) -> Result<xep_0115::C, CapsEncodeError> {
let mut string = String::new();
@@ -113,7 +144,7 @@ pub fn caps(node: String, query: info::Query) -> Result<xep_0115::C, CapsEncodeE
})
}
-pub fn caps2(query: info::Query) -> xep_0390::C {
+pub fn encode_caps2(query: info::Query) -> String {
let mut string = String::new();
// features string
@@ -181,6 +212,16 @@ pub fn caps2(query: info::Query) -> xep_0390::C {
let extensions_string = extensions.concat();
string.push_str(&extensions_string);
string.push('\x1c');
+ string
+}
+
+pub fn encode_info_base64(info: info::Query) -> String {
+ let string = encode_caps2(info);
+ BASE64_STANDARD.encode(string)
+}
+
+pub fn caps2(query: info::Query) -> xep_0390::C {
+ let string = encode_caps2(query);
let mut sha256 = Sha256::new();
@@ -209,7 +250,7 @@ pub fn caps2(query: info::Query) -> xep_0390::C {
}
/// takes a base64 encoded cached caps string and converts it into a disco info result
-pub fn info(info: String) -> Result<Info, CapsDecodeError> {
+pub fn decode_info_base64(info: String) -> Result<Info, CapsDecodeError> {
let info = String::from_utf8(BASE64_STANDARD.decode(info)?)?;
let mut strings = info.split_terminator('\x1c');
@@ -255,6 +296,22 @@ pub fn info(info: String) -> Result<Info, CapsDecodeError> {
})
}
+pub fn caps_to_node(caps: C) -> String {
+ caps.node + "#" + caps.ver.as_str()
+}
+
+pub fn node_to_caps(node: String) -> Result<C, CapsNodeConversionError> {
+ let (node, ver) = node
+ .rsplit_once('#')
+ .ok_or(CapsNodeConversionError::MissingHashtag)?;
+ Ok(C {
+ ext: None,
+ hash: "sha-1".to_string(),
+ node: node.to_string(),
+ ver: ver.to_string(),
+ })
+}
+
pub fn hash_to_node(hash: xep_0300::Hash) -> String {
let mut string = String::from("urn:xmpp:caps#");
string.push_str(&hash.algo.to_string());
@@ -276,12 +333,6 @@ pub fn node_to_hash(node: String) -> Result<Hash, HashNodeConversionError> {
})
}
-static CLIENT_INFO: Info = Info {
- node: None,
- features: vec![],
- identities: vec![],
-};
-
#[cfg(test)]
mod tests {
use peanuts::{Writer, element::IntoElement};
@@ -390,9 +441,51 @@ mod tests {
items: Vec::new(),
}],
};
- let caps = caps("https://macaw.chat".to_string(), info).unwrap();
+ let test_caps = caps("https://macaw.chat".to_string(), info).unwrap();
+ let stdout = tokio::io::stdout();
+ let mut writer = Writer::new(stdout);
+ writer.write(&test_caps).await.unwrap();
+ }
+
+ #[tokio::test]
+ pub async fn test_gen_client_caps() {
let stdout = tokio::io::stdout();
let mut writer = Writer::new(stdout);
- writer.write(&caps).await;
+ // let info = info::Query {
+ // node: Some("https://bunny.garden/filamento".to_string()),
+ // features: vec![
+ // Feature {
+ // var: "http://jabber.org/protocol/disco#items".to_string(),
+ // },
+ // Feature {
+ // var: "http://jabber.org/protocol/disco#info".to_string(),
+ // },
+ // Feature {
+ // var: "http://jabber.org/protocol/caps".to_string(),
+ // },
+ // Feature {
+ // var: "http://jabber.org/protocol/nick".to_string(),
+ // },
+ // Feature {
+ // var: "http://jabber.org/protocol/nick+notify".to_string(),
+ // },
+ // ],
+ // identities: vec![Identity {
+ // category: "client".to_string(),
+ // name: Some("filamento 0.1.0".to_string()),
+ // r#type: "pc".to_string(),
+ // lang: None,
+ // }],
+ // extensions: vec![],
+ // };
+ let info: info::Query = client_info().into();
+ let client_caps = caps(CLIENT_URI.to_string(), info.clone()).unwrap();
+ writer.write(&client_caps).await.unwrap();
+ let node = caps_to_node(client_caps);
+ println!("client caps node: `{}`", node);
+ let client_caps_base64 = encode_info_base64(info);
+ println!("client caps: `{}`", client_caps_base64);
+ let client_caps = decode_info_base64(client_caps_base64).unwrap();
+ println!("client caps: `{:?}`", client_caps);
}
}