Merge branch 'compat'

This commit is contained in:
Emmanuel Gil Peyrot 2019-01-13 12:00:36 +01:00
commit 2347b36c89
18 changed files with 106 additions and 28 deletions

View file

@ -2,26 +2,39 @@ stages:
- build - build
- test - test
variables:
FEATURES: ""
rust-latest-build: rust-latest-build:
stage: build stage: build
image: rust:latest image: rust:latest
script: script:
- cargo build --verbose - cargo build --verbose --no-default-features --features=$FEATURES
rust-nightly-build: rust-nightly-build:
stage: build stage: build
image: rustlang/rust:nightly image: rustlang/rust:nightly
script: script:
- cargo build --verbose - cargo build --verbose --no-default-features --features=$FEATURES
rust-latest-test: rust-latest-test:
stage: test stage: test
image: rust:latest image: rust:latest
script: script:
- cargo test --verbose - cargo test --verbose --no-default-features --features=$FEATURES
rust-nightly-test: rust-nightly-test:
stage: test stage: test
image: rustlang/rust:nightly image: rustlang/rust:nightly
script: script:
- cargo test --verbose - cargo test --verbose --no-default-features --features=$FEATURES
"rust-latest-test with features=disable-validation":
extends: rust-latest-test
variables:
FEATURES: "disable-validation"
"rust-nightly-test with features=disable-validation":
extends: rust-nightly-test
variables:
FEATURES: "disable-validation"

View file

@ -28,3 +28,5 @@ try_from = "0.3.2"
[features] [features]
# Build xmpp-parsers to make components instead of clients. # Build xmpp-parsers to make components instead of clients.
component = [] component = []
# Disable validation of unknown attributes.
disable-validation = []

View file

@ -18,6 +18,7 @@ impl MessagePayload for Attention {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[cfg(not(feature = "disable-validation"))]
use crate::error::Error; use crate::error::Error;
use minidom::Element; use minidom::Element;
use try_from::TryFrom; use try_from::TryFrom;
@ -33,6 +34,7 @@ mod tests {
Attention::try_from(elem).unwrap(); Attention::try_from(elem).unwrap();
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_child() { fn test_invalid_child() {
let elem: Element = "<attention xmlns='urn:xmpp:attention:0'><coucou/></attention>" let elem: Element = "<attention xmlns='urn:xmpp:attention:0'><coucou/></attention>"
@ -46,6 +48,7 @@ mod tests {
assert_eq!(message, "Unknown child in attention element."); assert_eq!(message, "Unknown child in attention element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<attention xmlns='urn:xmpp:attention:0' coucou=''/>" let elem: Element = "<attention xmlns='urn:xmpp:attention:0' coucou=''/>"

View file

@ -112,6 +112,7 @@ mod tests {
assert_eq!(bind, Bind::None); assert_eq!(bind, Bind::None);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_resource() { fn test_invalid_resource() {
let elem: Element = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource attr='coucou'>resource</resource></bind>" let elem: Element = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource attr='coucou'>resource</resource></bind>"

View file

@ -155,14 +155,6 @@ mod tests {
}, },
]; ];
let request_elem = elem.clone();
let error = BlocklistRequest::try_from(request_elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown child in blocklist element.");
let result_elem = elem.clone(); let result_elem = elem.clone();
let result = BlocklistResult::try_from(result_elem).unwrap(); let result = BlocklistResult::try_from(result_elem).unwrap();
assert_eq!(result.items, two_items); assert_eq!(result.items, two_items);
@ -176,6 +168,7 @@ mod tests {
assert_eq!(unblock.items, two_items); assert_eq!(unblock.items, two_items);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid() { fn test_invalid() {
let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>" let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>"
@ -217,4 +210,16 @@ mod tests {
}; };
assert_eq!(message, "Unknown attribute in unblock element."); assert_eq!(message, "Unknown attribute in unblock element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test]
fn test_non_empty_blocklist_request() {
let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();
let error = BlocklistRequest::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown child in blocklist element.");
}
} }

View file

@ -233,6 +233,7 @@ mod tests {
); );
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_child() { fn test_invalid_child() {
let elem: Element = "<c xmlns='http://jabber.org/protocol/caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash></c>".parse().unwrap(); let elem: Element = "<c xmlns='http://jabber.org/protocol/caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash></c>".parse().unwrap();

View file

@ -63,6 +63,7 @@ mod tests {
assert_eq!(message, "This is not a chatstate element."); assert_eq!(message, "This is not a chatstate element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_child() { fn test_invalid_child() {
let elem: Element = "<gone xmlns='http://jabber.org/protocol/chatstates'><coucou/></gone>" let elem: Element = "<gone xmlns='http://jabber.org/protocol/chatstates'><coucou/></gone>"
@ -76,6 +77,7 @@ mod tests {
assert_eq!(message, "Unknown child in chatstate element."); assert_eq!(message, "Unknown child in chatstate element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<inactive xmlns='http://jabber.org/protocol/chatstates' coucou=''/>" let elem: Element = "<inactive xmlns='http://jabber.org/protocol/chatstates' coucou=''/>"

View file

@ -510,14 +510,6 @@ mod tests {
}; };
assert_eq!(message, "Unknown child in received element."); assert_eq!(message, "Unknown child in received element.");
let elem: Element = "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''/>".parse().unwrap();
let error = Received::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in received element.");
let elem: Element = let elem: Element =
"<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator'/>" "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator'/>"
.parse() .parse()
@ -538,6 +530,18 @@ mod tests {
assert_eq!(message, "Unknown value for 'creator' attribute."); assert_eq!(message, "Unknown value for 'creator' attribute.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test]
fn test_invalid_received() {
let elem: Element = "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''/>".parse().unwrap();
let error = Received::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in received element.");
}
#[test] #[test]
fn test_checksum() { fn test_checksum() {
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator'><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap(); let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator'><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap();
@ -575,14 +579,6 @@ mod tests {
}; };
assert_eq!(message, "This is not a file element."); assert_eq!(message, "This is not a file element.");
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap();
let error = Checksum::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in checksum element.");
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator'><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap(); let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator'><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap();
let error = Checksum::try_from(elem).unwrap_err(); let error = Checksum::try_from(elem).unwrap_err();
let message = match error { let message = match error {
@ -600,6 +596,18 @@ mod tests {
assert_eq!(message, "Unknown value for 'creator' attribute."); assert_eq!(message, "Unknown value for 'creator' attribute.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test]
fn test_invalid_checksum() {
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap();
let error = Checksum::try_from(elem).unwrap_err();
let message = match error {
Error::ParseError(string) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in checksum element.");
}
#[test] #[test]
fn test_range() { fn test_range() {
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5'/>" let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5'/>"
@ -627,7 +635,11 @@ mod tests {
assert_eq!(range2.offset, 2048); assert_eq!(range2.offset, 2048);
assert_eq!(range2.length, Some(1024)); assert_eq!(range2.length, Some(1024));
assert_eq!(range2.hashes, hashes); assert_eq!(range2.hashes, hashes);
}
#[cfg(not(feature = "disable-validation"))]
#[test]
fn test_invalid_range() {
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5' coucou=''/>" let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5' coucou=''/>"
.parse() .parse()
.unwrap(); .unwrap();

View file

@ -248,6 +248,7 @@ macro_rules! check_ns_only {
macro_rules! check_no_children { macro_rules! check_no_children {
($elem:ident, $name:tt) => { ($elem:ident, $name:tt) => {
#[cfg(not(feature = "disable-validation"))]
for _ in $elem.children() { for _ in $elem.children() {
return Err(crate::error::Error::ParseError(concat!( return Err(crate::error::Error::ParseError(concat!(
"Unknown child in ", "Unknown child in ",
@ -260,6 +261,7 @@ macro_rules! check_no_children {
macro_rules! check_no_attributes { macro_rules! check_no_attributes {
($elem:ident, $name:tt) => { ($elem:ident, $name:tt) => {
#[cfg(not(feature = "disable-validation"))]
for _ in $elem.attrs() { for _ in $elem.attrs() {
return Err(crate::error::Error::ParseError(concat!( return Err(crate::error::Error::ParseError(concat!(
"Unknown attribute in ", "Unknown attribute in ",
@ -272,6 +274,7 @@ macro_rules! check_no_attributes {
macro_rules! check_no_unknown_attributes { macro_rules! check_no_unknown_attributes {
($elem:ident, $name:tt, [$($attr:tt),*]) => ( ($elem:ident, $name:tt, [$($attr:tt),*]) => (
#[cfg(not(feature = "disable-validation"))]
for (_attr, _) in $elem.attrs() { for (_attr, _) in $elem.attrs() {
$( $(
if _attr == $attr { if _attr == $attr {

View file

@ -45,6 +45,7 @@ mod tests {
Replace::try_from(elem).unwrap(); Replace::try_from(elem).unwrap();
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0' coucou=''/>" let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0' coucou=''/>"

View file

@ -142,6 +142,7 @@ mod tests {
assert_eq!(elem, elem2); assert_eq!(elem, elem2);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_muc_invalid_attribute() { fn test_muc_invalid_attribute() {
let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>" let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>"

View file

@ -303,6 +303,7 @@ mod tests {
assert!(elem.compare_to(&elem2)); assert!(elem.compare_to(&elem2));
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = " let elem: Element = "
@ -343,6 +344,7 @@ mod tests {
assert_eq!(message, "Required attribute 'code' missing."); assert_eq!(message, "Required attribute 'code' missing.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_status_invalid_child() { fn test_status_invalid_child() {
let elem: Element = " let elem: Element = "
@ -513,6 +515,7 @@ mod tests {
assert_eq!(reason.0, "Reason".to_owned()); assert_eq!(reason.0, "Reason".to_owned());
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_reason_invalid_attribute() { fn test_reason_invalid_attribute() {
let elem: Element = " let elem: Element = "
@ -528,6 +531,7 @@ mod tests {
assert_eq!(message, "Unknown attribute in reason element.".to_owned()); assert_eq!(message, "Unknown attribute in reason element.".to_owned());
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_reason_invalid() { fn test_reason_invalid() {
let elem: Element = " let elem: Element = "
@ -545,6 +549,7 @@ mod tests {
assert_eq!(message, "Unknown child in reason element.".to_owned()); assert_eq!(message, "Unknown child in reason element.".to_owned());
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_item_invalid_attr() { fn test_item_invalid_attr() {
let elem: Element = " let elem: Element = "

View file

@ -14,6 +14,7 @@ generate_elem_id!(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[cfg(not(feature = "disable-validation"))]
use crate::error::Error; use crate::error::Error;
use minidom::Element; use minidom::Element;
use try_from::TryFrom; use try_from::TryFrom;
@ -48,6 +49,7 @@ mod tests {
assert_eq!(elem1, elem2); assert_eq!(elem1, elem2);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid() { fn test_invalid() {
let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick'><coucou/></nick>" let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick'><coucou/></nick>"
@ -61,6 +63,7 @@ mod tests {
assert_eq!(message, "Unknown child in nick element."); assert_eq!(message, "Unknown child in nick element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick' coucou=''/>" let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick' coucou=''/>"

View file

@ -20,6 +20,7 @@ impl IqGetPayload for Ping {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[cfg(not(feature = "disable-validation"))]
use crate::error::Error; use crate::error::Error;
use minidom::Element; use minidom::Element;
use try_from::TryFrom; use try_from::TryFrom;
@ -42,6 +43,7 @@ mod tests {
assert_eq!(elem1, elem2); assert_eq!(elem1, elem2);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid() { fn test_invalid() {
let elem: Element = "<ping xmlns='urn:xmpp:ping'><coucou/></ping>" let elem: Element = "<ping xmlns='urn:xmpp:ping'><coucou/></ping>"
@ -55,6 +57,7 @@ mod tests {
assert_eq!(message, "Unknown child in ping element."); assert_eq!(message, "Unknown child in ping element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<ping xmlns='urn:xmpp:ping' coucou=''/>".parse().unwrap(); let elem: Element = "<ping xmlns='urn:xmpp:ping' coucou=''/>".parse().unwrap();

View file

@ -570,6 +570,7 @@ mod tests {
assert!(payload.is("test", "invalid")); assert!(payload.is("test", "invalid"));
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_status_child() { fn test_invalid_status_child() {
#[cfg(not(feature = "component"))] #[cfg(not(feature = "component"))]
@ -589,6 +590,7 @@ mod tests {
assert_eq!(message, "Unknown child in status element."); assert_eq!(message, "Unknown child in status element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
#[cfg(not(feature = "component"))] #[cfg(not(feature = "component"))]

View file

@ -420,6 +420,7 @@ mod tests {
assert_eq!(message, "Unknown child in event element."); assert_eq!(message, "Unknown child in event element.");
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid_attribute() { fn test_invalid_attribute() {
let elem: Element = "<event xmlns='http://jabber.org/protocol/pubsub#event' coucou=''/>" let elem: Element = "<event xmlns='http://jabber.org/protocol/pubsub#event' coucou=''/>"

View file

@ -245,6 +245,7 @@ mod tests {
assert_eq!(roster.items[0].subscription, Subscription::Remove); assert_eq!(roster.items[0].subscription, Subscription::Remove);
} }
#[cfg(not(feature = "disable-validation"))]
#[test] #[test]
fn test_invalid() { fn test_invalid() {
let elem: Element = "<query xmlns='jabber:iq:roster'><coucou/></query>" let elem: Element = "<query xmlns='jabber:iq:roster'><coucou/></query>"

View file

@ -288,4 +288,23 @@ mod tests {
String::from("Call 212-555-1212 for assistance.") String::from("Call 212-555-1212 for assistance.")
); );
} }
/// Some servers apparently use a non-namespaced 'lang' attribute, which is invalid as not part
/// of the schema. This tests whether we can parse it when disabling validation.
#[cfg(feature = "disable-validation")]
#[test]
fn invalid_failure_with_non_prefixed_text_lang() {
let elem: Element = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-sasl' lang='en'>Invalid username or password</text>
</failure>"
.parse()
.unwrap();
let failure = Failure::try_from(elem).unwrap();
assert_eq!(failure.defined_condition, DefinedCondition::NotAuthorized);
assert_eq!(
failure.texts[""],
String::from("Invalid username or password")
);
}
} }