Skip to content

Commit eb3f20d

Browse files
Fix setting file hosts to None
1 parent 6e5df8f commit eb3f20d

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

url/src/lib.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -1813,8 +1813,10 @@ impl Url {
18131813
return Err(ParseError::SetHostOnCannotBeABaseUrl);
18141814
}
18151815

1816+
let scheme_type = SchemeType::from(self.scheme());
1817+
18161818
if let Some(host) = host {
1817-
if host.is_empty() && SchemeType::from(self.scheme()).is_special() {
1819+
if host.is_empty() && scheme_type.is_special() && !scheme_type.is_file() {
18181820
return Err(ParseError::EmptyHost);
18191821
}
18201822
let mut host_substr = host;
@@ -1838,15 +1840,20 @@ impl Url {
18381840
self.set_host_internal(Host::parse_opaque(host_substr)?, None);
18391841
}
18401842
} else if self.has_host() {
1841-
let scheme_type = SchemeType::from(self.scheme());
1842-
if scheme_type.is_special() {
1843+
if scheme_type.is_special() && !scheme_type.is_file() {
18431844
return Err(ParseError::EmptyHost);
18441845
} else if self.serialization.len() == self.path_start as usize {
18451846
self.serialization.push('/');
18461847
}
18471848
debug_assert!(self.byte_at(self.scheme_end) == b':');
18481849
debug_assert!(self.byte_at(self.path_start) == b'/');
1849-
let new_path_start = self.scheme_end + 1;
1850+
1851+
let new_path_start = if scheme_type.is_file() {
1852+
self.scheme_end + 3
1853+
} else {
1854+
self.scheme_end + 1
1855+
};
1856+
18501857
self.serialization
18511858
.drain(new_path_start as usize..self.path_start as usize);
18521859
let offset = self.path_start - new_path_start;
@@ -2730,6 +2737,7 @@ fn path_to_file_url_segments_windows(
27302737
let host_start = serialization.len() + 1;
27312738
let host_end;
27322739
let host_internal;
2740+
27332741
match components.next() {
27342742
Some(Component::Prefix(ref p)) => match p.kind() {
27352743
Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => {
@@ -2750,7 +2758,6 @@ fn path_to_file_url_segments_windows(
27502758
}
27512759
_ => return Err(()),
27522760
},
2753-
27542761
_ => return Err(()),
27552762
}
27562763

@@ -2759,19 +2766,23 @@ fn path_to_file_url_segments_windows(
27592766
if component == Component::RootDir {
27602767
continue;
27612768
}
2769+
27622770
path_only_has_prefix = false;
27632771
// FIXME: somehow work with non-unicode?
27642772
let component = component.as_os_str().to_str().ok_or(())?;
2773+
27652774
serialization.push('/');
27662775
serialization.extend(percent_encode(component.as_bytes(), PATH_SEGMENT));
27672776
}
2777+
27682778
// A windows drive letter must end with a slash.
27692779
if serialization.len() > host_start
27702780
&& parser::is_windows_drive_letter(&serialization[host_start..])
27712781
&& path_only_has_prefix
27722782
{
27732783
serialization.push('/');
27742784
}
2785+
27752786
Ok((host_end, host_internal))
27762787
}
27772788

@@ -2795,23 +2806,28 @@ fn file_url_segments_to_pathbuf(
27952806
} else {
27962807
Vec::new()
27972808
};
2809+
27982810
for segment in segments {
27992811
bytes.push(b'/');
28002812
bytes.extend(percent_decode(segment.as_bytes()));
28012813
}
2814+
28022815
// A windows drive letter must end with a slash.
28032816
if bytes.len() > 2
28042817
&& matches!(bytes[bytes.len() - 2], b'a'..=b'z' | b'A'..=b'Z')
28052818
&& matches!(bytes[bytes.len() - 1], b':' | b'|')
28062819
{
28072820
bytes.push(b'/');
28082821
}
2822+
28092823
let os_str = OsStr::from_bytes(&bytes);
28102824
let path = PathBuf::from(os_str);
2825+
28112826
debug_assert!(
28122827
path.is_absolute(),
28132828
"to_file_path() failed to produce an absolute Path"
28142829
);
2830+
28152831
Ok(path)
28162832
}
28172833

url/tests/unit.rs

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ fn test_set_empty_host() {
4343
assert_eq!(base.as_str(), "moz:/baz");
4444
base.set_host(Some("servo")).unwrap();
4545
assert_eq!(base.as_str(), "moz://servo/baz");
46+
47+
let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
48+
base.set_host(None).unwrap();
49+
assert_eq!(base.as_str(), "file:///share/foo/bar");
50+
51+
let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
52+
base.set_host(Some("foo")).unwrap();
53+
assert_eq!(base.as_str(), "file://foo/share/foo/bar");
4654
}
4755

4856
#[test]

0 commit comments

Comments
 (0)