2017-06-25 21:03:48 +01:00
// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// 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/.
2025-12-29 15:11:20 +01:00
use xso ::{ AsXml , FromXml } ;
2018-12-18 15:27:30 +01:00
use crate ::data_forms ::DataForm ;
2018-12-18 15:32:05 +01:00
use crate ::iq ::{ IqGetPayload , IqResultPayload , IqSetPayload } ;
2018-12-18 15:27:30 +01:00
use crate ::ns ;
2017-06-25 21:03:48 +01:00
2025-12-29 15:11:20 +01:00
/// Entity requests registration fields from host.
#[ derive(FromXml, AsXml, Debug, Clone) ]
#[ xml(namespace = ns::REGISTER, name = " query " ) ]
pub struct FieldsQuery ;
2018-08-08 19:15:25 +02:00
2025-12-29 15:11:20 +01:00
impl IqGetPayload for FieldsQuery { }
2018-08-08 19:15:25 +02:00
2025-12-29 15:11:20 +01:00
/// Entity requests cancellation of existing registration.
#[ derive(FromXml, AsXml, Debug, Clone) ]
#[ xml(namespace = ns::REGISTER, name = " query " ) ]
pub struct RemoveQuery {
/// Whether to remove that registration.
// TODO: we should be able to remove that flag and make this type a zero-sized type.
#[ xml(flag) ]
2017-06-25 21:03:48 +01:00
pub remove : bool ,
2025-12-29 15:11:20 +01:00
}
impl IqSetPayload for RemoveQuery { }
/// Query for registering against a service, the legacy way.
#[ derive(FromXml, AsXml, Debug, Clone) ]
#[ xml(namespace = ns::REGISTER, name = " query " ) ]
pub struct LegacyQuery {
/// Whether this account is already registered
#[ xml(flag) ]
pub registered : bool ,
/// Instructions to be presented to entities implementing this legacy element.
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub instructions : Option < String > ,
/// Account name associated with the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub username : Option < String > ,
/// Familiar name of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub nick : Option < String > ,
/// Password or secret for the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub password : Option < String > ,
/// Full name of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub name : Option < String > ,
/// Given name of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub first : Option < String > ,
/// Family name of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub last : Option < String > ,
/// Email address of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub email : Option < String > ,
/// Street portion of a physical or mailing address
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub address : Option < String > ,
/// Locality portion of a physical or mailing address
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub city : Option < String > ,
/// Region portion of a physical or mailing address
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub state : Option < String > ,
/// Postal code portion of a physical or mailing address
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub zip : Option < String > ,
/// Telephone number of the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub phone : Option < String > ,
/// URL to web page describing the user
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub url : Option < String > ,
/// Some date (e.g., birth date, hire date, sign-up date)
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub date : Option < String > ,
/// Free-form text field (obsolete)
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub misc : Option < String > ,
/// Free-form text field (obsolete)
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub text : Option < String > ,
/// Session key for transaction (obsolete)
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub key : Option < String > ,
}
impl IqSetPayload for LegacyQuery { }
impl IqResultPayload for LegacyQuery { }
/// Query for registering against a service.
#[ derive(FromXml, AsXml, Debug, Clone) ]
#[ xml(namespace = ns::REGISTER, name = " query " ) ]
pub struct FormQuery {
/// Legacy instructions fallback for entities which don’ t understand the form.
#[ xml(extract(default, fields(text(type_ = String)))) ]
pub instructions : Option < String > ,
2018-08-08 19:15:25 +02:00
/// A data form the user must fill before being allowed to register.
2025-12-29 15:11:20 +01:00
#[ xml(child) ]
pub form : DataForm ,
2017-06-25 21:03:48 +01:00
// Not yet implemented.
//pub oob: Option<Oob>,
}
2025-12-29 15:11:20 +01:00
impl IqSetPayload for FormQuery { }
impl IqResultPayload for FormQuery { }
2017-06-25 21:03:48 +01:00
#[ cfg(test) ]
mod tests {
use super ::* ;
2025-12-29 15:11:20 +01:00
use crate ::data_forms ::DataFormType ;
use minidom ::Element ;
2017-06-25 21:03:48 +01:00
2018-10-28 13:10:48 +01:00
#[ cfg(target_pointer_width = " 32 " ) ]
#[ test ]
fn test_size ( ) {
2025-12-29 15:11:20 +01:00
assert_size! ( RemoveQuery , 1 ) ;
assert_size! ( LegacyQuery , 220 ) ;
assert_size! ( FormQuery , 52 ) ;
2018-10-28 13:10:48 +01:00
}
#[ cfg(target_pointer_width = " 64 " ) ]
2018-10-26 14:26:16 +02:00
#[ test ]
fn test_size ( ) {
2025-12-29 15:11:20 +01:00
assert_size! ( RemoveQuery , 1 ) ;
assert_size! ( LegacyQuery , 440 ) ;
assert_size! ( FormQuery , 104 ) ;
2018-10-26 14:26:16 +02:00
}
2017-06-25 21:03:48 +01:00
#[ test ]
fn test_simple ( ) {
let elem : Element = " <query xmlns='jabber:iq:register'/> " . parse ( ) . unwrap ( ) ;
2025-12-29 15:11:20 +01:00
FieldsQuery ::try_from ( elem ) . unwrap ( ) ;
let elem : Element = " <query xmlns='jabber:iq:register'><remove/></query> "
. parse ( )
. unwrap ( ) ;
let query = RemoveQuery ::try_from ( elem ) . unwrap ( ) ;
assert_eq! ( query . remove , true ) ;
let elem : Element = " <query xmlns='jabber:iq:register'/> " . parse ( ) . unwrap ( ) ;
let query = LegacyQuery ::try_from ( elem ) . unwrap ( ) ;
assert_eq! ( query . first , None ) ;
let elem : Element =
" <query xmlns='jabber:iq:register'><x xmlns='jabber:x:data' type='submit'/></query> "
. parse ( )
. unwrap ( ) ;
let query = FormQuery ::try_from ( elem ) . unwrap ( ) ;
assert! ( query . instructions . is_none ( ) ) ;
assert! ( query . form . fields . is_empty ( ) ) ;
2017-06-25 21:03:48 +01:00
}
#[ test ]
fn test_ex2 ( ) {
2022-03-22 23:29:25 +01:00
let elem : Element = r #" <query xmlns='jabber:iq:register'>
2017-06-25 21:03:48 +01:00
< instructions >
Choose a username and password for use with this service .
Please also provide your email address .
< / instructions >
< username / >
< password / >
< email / >
< / query >
2018-12-18 15:32:05 +01:00
" #
. parse ( )
. unwrap ( ) ;
2025-12-29 15:11:20 +01:00
let query = LegacyQuery ::try_from ( elem ) . unwrap ( ) ;
2017-06-25 21:03:48 +01:00
assert_eq! ( query . registered , false ) ;
2025-12-29 15:11:20 +01:00
assert_eq! ( query . instructions . unwrap ( ) , " \n Choose a username and password for use with this service. \n Please also provide your email address. \n " ) ;
assert_eq! ( query . username . unwrap ( ) , " " ) ;
assert_eq! ( query . password . unwrap ( ) , " " ) ;
assert_eq! ( query . email . unwrap ( ) , " " ) ;
assert_eq! ( query . name , None ) ;
2017-06-25 21:03:48 +01:00
// FIXME: HashMap doesn’ t keep the order right.
//let elem2 = query.into();
//assert_eq!(elem, elem2);
}
#[ test ]
fn test_ex9 ( ) {
2019-12-07 20:37:33 +01:00
let elem : Element = " <query xmlns='jabber:iq:register'><instructions>Use the enclosed form to register. If your Jabber client does not support Data Forms, visit http://www.shakespeare.lit/contests.php</instructions><x xmlns='jabber:x:data' type='form'><title>Contest Registration</title><instructions>Please provide the following information to sign up for our special contests!</instructions><field type='hidden' var='FORM_TYPE'><value>jabber:iq:register</value></field><field label='Given Name' var='first'><required/></field><field label='Family Name' var='last'><required/></field><field label='Email Address' var='email'><required/></field><field type='list-single' label='Gender' var='x-gender'><option label='Male'><value>M</value></option><option label='Female'><value>F</value></option></field></x></query> "
2018-12-18 15:32:05 +01:00
. parse ( )
. unwrap ( ) ;
2017-06-25 21:03:48 +01:00
let elem1 = elem . clone ( ) ;
2025-12-29 15:11:20 +01:00
let query = FormQuery ::try_from ( elem ) . unwrap ( ) ;
assert! ( query . instructions . is_some ( ) ) ;
let form = query . form . clone ( ) ;
assert_eq! (
form . instructions . unwrap ( ) ,
" Please provide the following information to sign up for our special contests! "
) ;
assert_eq! ( form . type_ , DataFormType ::Form ) ;
2017-06-25 21:03:48 +01:00
let elem2 = query . into ( ) ;
2019-11-29 14:33:17 +01:00
assert_eq! ( elem1 , elem2 ) ;
2017-06-25 21:03:48 +01:00
}
#[ test ]
fn test_ex10 ( ) {
2019-12-07 20:37:33 +01:00
let elem : Element = " <query xmlns='jabber:iq:register'><x xmlns='jabber:x:data' type='submit'><field type='hidden' var='FORM_TYPE'><value>jabber:iq:register</value></field><field label='Given Name' var='first'><value>Juliet</value></field><field label='Family Name' var='last'><value>Capulet</value></field><field label='Email Address' var='email'><value>juliet@capulet.com</value></field><field type='list-single' label='Gender' var='x-gender'><value>F</value></field></x></query> "
2018-12-18 15:32:05 +01:00
. parse ( )
. unwrap ( ) ;
2017-06-25 21:03:48 +01:00
let elem1 = elem . clone ( ) ;
2025-12-29 15:11:20 +01:00
let query = FormQuery ::try_from ( elem ) . unwrap ( ) ;
2017-06-25 21:03:48 +01:00
let elem2 = query . into ( ) ;
2019-11-29 14:33:17 +01:00
assert_eq! ( elem1 , elem2 ) ;
2017-06-25 21:03:48 +01:00
}
}