diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index b9b1090e082..df69bc77fd0 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -11,6 +11,7 @@ use std::ops; use std::str; use std::str::FromStr; use util::mem::HeapSizeOf; +use util::str::is_token; /// Encapsulates the IDL `ByteString` type. #[derive(JSTraceable, Clone, Eq, PartialEq, HeapSizeOf)] @@ -49,35 +50,7 @@ impl ByteString { /// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17). pub fn is_token(&self) -> bool { let ByteString(ref vec) = *self; - if vec.is_empty() { - return false; // A token must be at least a single character - } - vec.iter().all(|&x| { - // http://tools.ietf.org/html/rfc2616#section-2.2 - match x { - 0...31 | 127 => false, // CTLs - 40 | - 41 | - 60 | - 62 | - 64 | - 44 | - 59 | - 58 | - 92 | - 34 | - 47 | - 91 | - 93 | - 63 | - 61 | - 123 | - 125 | - 32 => false, // separators - x if x > 127 => false, // non-CHARs - _ => true, - } - }) + is_token(vec) } /// Returns whether `self` is a `field-value`, as defined by diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index d70b633f0d5..c9658a1b5c2 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -36,11 +36,12 @@ use net_traits::unwrap_websocket_protocol; use net_traits::{WebSocketCommunicate, WebSocketConnectData, WebSocketDomAction, WebSocketNetworkEvent}; use script_thread::ScriptThreadEventCategory::WebSocketEvent; use script_thread::{CommonScriptMsg, Runnable, ScriptChan}; +use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; use std::ptr; use std::thread; -use util::str::DOMString; +use util::str::{DOMString, is_token}; use websocket::client::request::Url; use websocket::header::{Headers, WebSocketProtocol}; use websocket::ws::util::url::parse_url; @@ -220,17 +221,13 @@ impl WebSocket { for (i, protocol) in protocols.iter().enumerate() { // https://tools.ietf.org/html/rfc6455#section-4.1 // Handshake requirements, step 10 - if protocol.is_empty() { + + if protocols[i + 1..].iter().any(|p| p.eq_ignore_ascii_case(protocol)) { return Err(Error::Syntax); } - if protocols[i + 1..].iter().any(|p| p == protocol) { - return Err(Error::Syntax); - } - - // TODO: also check that no separator characters are used // https://tools.ietf.org/html/rfc6455#section-4.1 - if protocol.chars().any(|c| c < '\u{0021}' || c > '\u{007E}') { + if !is_token(protocol.as_bytes()) { return Err(Error::Syntax); } } diff --git a/components/util/str.rs b/components/util/str.rs index 0b1e863a8de..dc3b8df1762 100644 --- a/components/util/str.rs +++ b/components/util/str.rs @@ -565,3 +565,37 @@ pub fn search_index(index: usize, indices: CharIndices) -> isize { } character_count } + +/// Returns whether `s` is a `token`, as defined by +/// [RFC 2616](http://tools.ietf.org/html/rfc2616#page-17). +pub fn is_token(s: &[u8]) -> bool { + if s.is_empty() { + return false; // A token must be at least a single character + } + s.iter().all(|&x| { + // http://tools.ietf.org/html/rfc2616#section-2.2 + match x { + 0...31 | 127 => false, // CTLs + 40 | + 41 | + 60 | + 62 | + 64 | + 44 | + 59 | + 58 | + 92 | + 34 | + 47 | + 91 | + 93 | + 63 | + 61 | + 123 | + 125 | + 32 => false, // separators + x if x > 127 => false, // non-CHARs + _ => true, + } + }) +} diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index e31d211057f..d1d5c65385e 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -33316,7 +33316,22 @@ }, "local_changes": { "deleted": [], - "items": {}, + "items": { + "testharness": { + "websockets/Create-asciiSep-protocol-string.htm": [ + { + "path": "websockets/Create-asciiSep-protocol-string.htm", + "url": "/websockets/Create-asciiSep-protocol-string.htm" + } + ], + "websockets/Create-protocols-repeated-case-insensitive.htm": [ + { + "path": "websockets/Create-protocols-repeated-case-insensitive.htm", + "url": "/websockets/Create-protocols-repeated-case-insensitive.htm" + } + ] + } + }, "reftest_nodes": {} }, "reftest_nodes": { diff --git a/tests/wpt/web-platform-tests/websockets/Create-asciiSep-protocol-string.htm b/tests/wpt/web-platform-tests/websockets/Create-asciiSep-protocol-string.htm new file mode 100644 index 00000000000..7309009d052 --- /dev/null +++ b/tests/wpt/web-platform-tests/websockets/Create-asciiSep-protocol-string.htm @@ -0,0 +1,21 @@ + + +
+