1// Copyright (C) 2019 Maxime “pep” Buquet <pep@bouah.net>
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6use crate::data_forms::{DataForm, DataFormType, Field, FieldType};
7use crate::ns;
8use crate::util::error::Error;
9use try_from::TryFrom;
10
11/// Structure representing a `http://jabber.org/network/serverinfo` form type.
12#[derive(Debug, Clone)]
13pub struct ServerInfo {
14 /// Abuse addresses
15 pub abuse: Vec<String>,
16
17 /// Admin addresses
18 pub admin: Vec<String>,
19
20 /// Feedback addresses
21 pub feedback: Vec<String>,
22
23 /// Sales addresses
24 pub sales: Vec<String>,
25
26 /// Security addresses
27 pub security: Vec<String>,
28
29 /// Support addresses
30 pub support: Vec<String>,
31}
32
33impl TryFrom<DataForm> for ServerInfo {
34 type Err = Error;
35
36 fn try_from(form: DataForm) -> Result<ServerInfo, Error> {
37 if form.type_ != DataFormType::Result_ {
38 return Err(Error::ParseError("Wrong type of form."));
39 }
40 if form.form_type != Some(String::from(ns::SERVER_INFO)) {
41 return Err(Error::ParseError("Wrong FORM_TYPE for form."));
42 }
43 let mut server_info = ServerInfo {
44 abuse: vec![],
45 admin: vec![],
46 feedback: vec![],
47 sales: vec![],
48 security: vec![],
49 support: vec![],
50 };
51 for field in form.fields {
52 if field.type_ != FieldType::ListMulti {
53 return Err(Error::ParseError("Field is not of the required type."));
54 }
55 if field.var == "abuse-addresses" {
56 server_info.abuse = field.values;
57 } else if field.var == "admin-addresses" {
58 server_info.admin = field.values;
59 } else if field.var == "feedback-addresses" {
60 server_info.feedback = field.values;
61 } else if field.var == "sales-addresses" {
62 server_info.sales = field.values;
63 } else if field.var == "security-addresses" {
64 server_info.security = field.values;
65 } else if field.var == "support-addresses" {
66 server_info.support = field.values;
67 } else {
68 return Err(Error::ParseError("Unknown form field var."));
69 }
70 }
71
72 Ok(server_info)
73 }
74}
75
76impl From<ServerInfo> for DataForm {
77 fn from(server_info: ServerInfo) -> DataForm {
78 DataForm {
79 type_: DataFormType::Result_,
80 form_type: Some(String::from(ns::SERVER_INFO)),
81 title: None,
82 instructions: None,
83 fields: vec![
84 Field {
85 var: String::from("FORM_TYPE"),
86 type_: FieldType::Hidden,
87 label: None,
88 required: false,
89 options: vec![],
90 values: vec![String::from(ns::SERVER_INFO)],
91 media: vec![],
92 },
93 generate_address_field("abuse-addresses", server_info.abuse),
94 generate_address_field("admin-addresses", server_info.admin),
95 generate_address_field("feedback-addresses", server_info.feedback),
96 generate_address_field("sales-addresses", server_info.sales),
97 generate_address_field("security-addresses", server_info.security),
98 generate_address_field("support-addresses", server_info.support),
99 ],
100 }
101 }
102}
103
104/// Generate `Field` for addresses
105pub fn generate_address_field<S: Into<String>>(var: S, values: Vec<String>) -> Field {
106 Field {
107 var: var.into(),
108 type_: FieldType::ListMulti,
109 label: None,
110 required: false,
111 options: vec![],
112 values,
113 media: vec![],
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::data_forms::{DataForm, DataFormType, Field, FieldType};
121
122 #[cfg(target_pointer_width = "32")]
123 #[test]
124 fn test_size() {
125 assert_size!(ServerInfo, 72);
126 }
127
128 #[cfg(target_pointer_width = "64")]
129 #[test]
130 fn test_size() {
131 assert_size!(ServerInfo, 144);
132 }
133
134 #[test]
135 fn test_simple() {
136 let form = DataForm {
137 type_: DataFormType::Result_,
138 form_type: Some(String::from(ns::SERVER_INFO)),
139 title: None,
140 instructions: None,
141 fields: vec![
142 Field {
143 var: String::from("FORM_TYPE"),
144 type_: FieldType::Hidden,
145 label: None,
146 required: false,
147 options: vec![],
148 values: vec![String::from(ns::SERVER_INFO)],
149 media: vec![],
150 },
151 Field {
152 var: String::from("abuse-addresses"),
153 type_: FieldType::ListMulti,
154 label: None,
155 required: false,
156 options: vec![],
157 values: vec![],
158 media: vec![],
159 },
160 Field {
161 var: String::from("admin-addresses"),
162 type_: FieldType::ListMulti,
163 label: None,
164 required: false,
165 options: vec![],
166 values: vec![
167 String::from("xmpp:admin@foo.bar"),
168 String::from("https://foo.bar/chat/"),
169 String::from("mailto:admin@foo.bar"),
170 ],
171 media: vec![],
172 },
173 Field {
174 var: String::from("feedback-addresses"),
175 type_: FieldType::ListMulti,
176 label: None,
177 required: false,
178 options: vec![],
179 values: vec![],
180 media: vec![],
181 },
182 Field {
183 var: String::from("sales-addresses"),
184 type_: FieldType::ListMulti,
185 label: None,
186 required: false,
187 options: vec![],
188 values: vec![],
189 media: vec![],
190 },
191 Field {
192 var: String::from("security-addresses"),
193 type_: FieldType::ListMulti,
194 label: None,
195 required: false,
196 options: vec![],
197 values: vec![
198 String::from("xmpp:security@foo.bar"),
199 String::from("mailto:security@foo.bar"),
200 ],
201 media: vec![],
202 },
203 Field {
204 var: String::from("support-addresses"),
205 type_: FieldType::ListMulti,
206 label: None,
207 required: false,
208 options: vec![],
209 values: vec![String::from("mailto:support@foo.bar")],
210 media: vec![],
211 },
212 ],
213 };
214
215 let server_info = ServerInfo {
216 abuse: vec![],
217 admin: vec![
218 String::from("xmpp:admin@foo.bar"),
219 String::from("https://foo.bar/chat/"),
220 String::from("mailto:admin@foo.bar"),
221 ],
222 feedback: vec![],
223 sales: vec![],
224 security: vec![
225 String::from("xmpp:security@foo.bar"),
226 String::from("mailto:security@foo.bar"),
227 ],
228 support: vec![String::from("mailto:support@foo.bar")],
229 };
230
231 // assert_eq!(DataForm::from(server_info), form);
232 // assert_eq!(ServerInfo::try_from(form), Ok(form));
233 }
234}