|  | // Copyright 2016 The rust-url developers. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | 
|  | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | 
|  | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | 
|  | // option. This file may not be copied, modified, or distributed | 
|  | // except according to those terms. | 
|  |  | 
|  | //! Getters and setters for URL components implemented per https://url.spec.whatwg.org/#api | 
|  | //! | 
|  | //! Unless you need to be interoperable with web browsers, | 
|  | //! you probably want to use `Url` method instead. | 
|  |  | 
|  | use {Url, Position, Host, ParseError, idna}; | 
|  | use parser::{Parser, SchemeType, default_port, Context, Input}; | 
|  |  | 
|  | /// https://url.spec.whatwg.org/#dom-url-domaintoascii | 
|  | pub fn domain_to_ascii(domain: &str) -> String { | 
|  | match Host::parse(domain) { | 
|  | Ok(Host::Domain(domain)) => domain, | 
|  | _ => String::new(), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// https://url.spec.whatwg.org/#dom-url-domaintounicode | 
|  | pub fn domain_to_unicode(domain: &str) -> String { | 
|  | match Host::parse(domain) { | 
|  | Ok(Host::Domain(ref domain)) => { | 
|  | let (unicode, _errors) = idna::domain_to_unicode(domain); | 
|  | unicode | 
|  | } | 
|  | _ => String::new(), | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-href | 
|  | pub fn href(url: &Url) -> &str { | 
|  | url.as_str() | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-href | 
|  | pub fn set_href(url: &mut Url, value: &str) -> Result<(), ParseError> { | 
|  | *url = Url::parse(value)?; | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-origin | 
|  | pub fn origin(url: &Url) -> String { | 
|  | url.origin().ascii_serialization() | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-protocol | 
|  | #[inline] | 
|  | pub fn protocol(url: &Url) -> &str { | 
|  | &url.as_str()[..url.scheme().len() + ":".len()] | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-protocol | 
|  | pub fn set_protocol(url: &mut Url, mut new_protocol: &str) -> Result<(), ()> { | 
|  | // The scheme state in the spec ignores everything after the first `:`, | 
|  | // but `set_scheme` errors if there is more. | 
|  | if let Some(position) = new_protocol.find(':') { | 
|  | new_protocol = &new_protocol[..position]; | 
|  | } | 
|  | url.set_scheme(new_protocol) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-username | 
|  | #[inline] | 
|  | pub fn username(url: &Url) -> &str { | 
|  | url.username() | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-username | 
|  | pub fn set_username(url: &mut Url, new_username: &str) -> Result<(), ()> { | 
|  | url.set_username(new_username) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-password | 
|  | #[inline] | 
|  | pub fn password(url: &Url) -> &str { | 
|  | url.password().unwrap_or("") | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-password | 
|  | pub fn set_password(url: &mut Url, new_password: &str) -> Result<(), ()> { | 
|  | url.set_password(if new_password.is_empty() { None } else { Some(new_password) }) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-host | 
|  | #[inline] | 
|  | pub fn host(url: &Url) -> &str { | 
|  | &url[Position::BeforeHost..Position::AfterPort] | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-host | 
|  | pub fn set_host(url: &mut Url, new_host: &str) -> Result<(), ()> { | 
|  | if url.cannot_be_a_base() { | 
|  | return Err(()) | 
|  | } | 
|  | let host; | 
|  | let opt_port; | 
|  | { | 
|  | let scheme = url.scheme(); | 
|  | let result = Parser::parse_host(Input::new(new_host), SchemeType::from(scheme)); | 
|  | match result { | 
|  | Ok((h, remaining)) => { | 
|  | host = h; | 
|  | opt_port = if let Some(remaining) = remaining.split_prefix(':') { | 
|  | Parser::parse_port(remaining, || default_port(scheme), Context::Setter) | 
|  | .ok().map(|(port, _remaining)| port) | 
|  | } else { | 
|  | None | 
|  | }; | 
|  | } | 
|  | Err(_) => return Err(()) | 
|  | } | 
|  | } | 
|  | url.set_host_internal(host, opt_port); | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-hostname | 
|  | #[inline] | 
|  | pub fn hostname(url: &Url) -> &str { | 
|  | url.host_str().unwrap_or("") | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-hostname | 
|  | pub fn set_hostname(url: &mut Url, new_hostname: &str) -> Result<(), ()> { | 
|  | if url.cannot_be_a_base() { | 
|  | return Err(()) | 
|  | } | 
|  | let result = Parser::parse_host(Input::new(new_hostname), SchemeType::from(url.scheme())); | 
|  | if let Ok((host, _remaining)) = result { | 
|  | url.set_host_internal(host, None); | 
|  | Ok(()) | 
|  | } else { | 
|  | Err(()) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-port | 
|  | #[inline] | 
|  | pub fn port(url: &Url) -> &str { | 
|  | &url[Position::BeforePort..Position::AfterPort] | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-port | 
|  | pub fn set_port(url: &mut Url, new_port: &str) -> Result<(), ()> { | 
|  | let result; | 
|  | { | 
|  | // has_host implies !cannot_be_a_base | 
|  | let scheme = url.scheme(); | 
|  | if !url.has_host() || url.host() == Some(Host::Domain("")) || scheme == "file" { | 
|  | return Err(()) | 
|  | } | 
|  | result = Parser::parse_port(Input::new(new_port), || default_port(scheme), Context::Setter) | 
|  | } | 
|  | if let Ok((new_port, _remaining)) = result { | 
|  | url.set_port_internal(new_port); | 
|  | Ok(()) | 
|  | } else { | 
|  | Err(()) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-pathname | 
|  | #[inline] | 
|  | pub fn pathname(url: &Url) -> &str { | 
|  | url.path() | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-pathname | 
|  | pub fn set_pathname(url: &mut Url, new_pathname: &str) { | 
|  | if !url.cannot_be_a_base() { | 
|  | url.set_path(new_pathname) | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-search | 
|  | pub fn search(url: &Url) -> &str { | 
|  | trim(&url[Position::AfterPath..Position::AfterQuery]) | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-search | 
|  | pub fn set_search(url: &mut Url, new_search: &str) { | 
|  | url.set_query(match new_search { | 
|  | "" => None, | 
|  | _ if new_search.starts_with('?') => Some(&new_search[1..]), | 
|  | _ => Some(new_search), | 
|  | }) | 
|  | } | 
|  |  | 
|  | /// Getter for https://url.spec.whatwg.org/#dom-url-hash | 
|  | pub fn hash(url: &Url) -> &str { | 
|  | trim(&url[Position::AfterQuery..]) | 
|  | } | 
|  |  | 
|  | /// Setter for https://url.spec.whatwg.org/#dom-url-hash | 
|  | pub fn set_hash(url: &mut Url, new_hash: &str) { | 
|  | if url.scheme() != "javascript" { | 
|  | url.set_fragment(match new_hash { | 
|  | "" => None, | 
|  | _ if new_hash.starts_with('#') => Some(&new_hash[1..]), | 
|  | _ => Some(new_hash), | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | fn trim(s: &str) -> &str { | 
|  | if s.len() == 1 { | 
|  | "" | 
|  | } else { | 
|  | s | 
|  | } | 
|  | } |