From fc94bd411a46847f24e56b9fa2a524ccf1f5d8b6 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sat, 7 Jan 2017 00:23:16 -0500 Subject: [PATCH 1/3] Allow for more complicated directory paths --- src/context/context.rs | 45 +++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/context/context.rs b/src/context/context.rs index 607653c..7c794f5 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -133,20 +133,6 @@ impl Context { .iter().rposition(|&b| b == b'/' || b == b':') .map_or(cwd.len(), |i| i + 1)] .to_vec() - } else if path.starts_with(b"./") { - let mut canon = cwd.clone(); - if ! canon.ends_with(b"/") { - canon.push(b'/'); - } - canon.extend_from_slice(&path[2..]); - canon - } else if path.starts_with(b"../") { - let mut canon = cwd[..cwd[..cwd.len() - 1] - .iter().rposition(|&b| b == b'/' || b == b':') - .map_or(cwd.len(), |i| i + 1)] - .to_vec(); - canon.extend_from_slice(&path[3..]); - canon } else if path.starts_with(b"/") { let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec(); canon.extend_from_slice(&path); @@ -157,8 +143,35 @@ impl Context { canon.push(b'/'); } canon.extend_from_slice(&path); - canon - } + // NOTE: assumes the scheme does not include anything like "../" or "./" + let rparts = canon.split(|&c| c == b'/') + .filter(|&part| part != b".") + .rev() + .scan(0, |nskip, part| { + if part == b".." { + *nskip += 1; + Some(None) + } else { + if *nskip > 0 { + *nskip -= 1; + Some(None) + } else { + Some(Some(part)) + } + } + }) + .filter_map(|x| x) + .collect::>(); + let mut result = rparts + .iter() + .rev() + .fold(Vec::new(), |mut vec, &part| { + vec.extend_from_slice(part); + vec.push(b'/'); + vec + }); + result.pop(); // remove extra '/' + result } else { path.to_vec() } From 046d8ac0c55994d89e71209e3bfd2b9cd8e1d38a Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sat, 7 Jan 2017 00:49:45 -0500 Subject: [PATCH 2/3] Fix typo and add functionality to more properly handle the parent of the root of the filesystem --- src/context/context.rs | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/context/context.rs b/src/context/context.rs index 7c794f5..be8ffe7 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -144,34 +144,46 @@ impl Context { } canon.extend_from_slice(&path); // NOTE: assumes the scheme does not include anything like "../" or "./" - let rparts = canon.split(|&c| c == b'/') - .filter(|&part| part != b".") - .rev() - .scan(0, |nskip, part| { - if part == b".." { - *nskip += 1; - Some(None) - } else { - if *nskip > 0 { - *nskip -= 1; - Some(None) + let mut result = { + let rparts = canon.split(|&c| c == b'/') + .filter(|&part| part != b".") + .rev() + .scan(0, |nskip, part| { + if part == b".." { + *nskip += 1; + Some(None) } else { - Some(Some(part)) + if *nskip > 0 { + *nskip -= 1; + Some(None) + } else { + Some(Some(part)) + } } - } - }) - .filter_map(|x| x) - .collect::>(); - let mut result = rparts - .iter() - .rev() - .fold(Vec::new(), |mut vec, &part| { - vec.extend_from_slice(part); - vec.push(b'/'); - vec - }); + }) + .filter_map(|x| x) + .collect::>(); + rparts + .iter() + .rev() + .fold(Vec::new(), |mut vec, &part| { + vec.extend_from_slice(part); + vec.push(b'/'); + vec + }) + }; result.pop(); // remove extra '/' - result + if result.len() == 0 { + // replace with the root of the schema if it's empty + let pos = canon.iter() + .position(|&b| b == b':') + .map_or(canon.len(), |p| p + 1); + canon.truncate(pos); + canon + } else { + result + } + } } else { path.to_vec() } From b0cafc18907a59e7eaea2abc913140a61d92fa60 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sat, 7 Jan 2017 08:00:16 -0500 Subject: [PATCH 3/3] Correctly handle relative paths starting from the root directory --- src/context/context.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/context/context.rs b/src/context/context.rs index be8ffe7..b594b60 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -133,25 +133,27 @@ impl Context { .iter().rposition(|&b| b == b'/' || b == b':') .map_or(cwd.len(), |i| i + 1)] .to_vec() - } else if path.starts_with(b"/") { - let mut canon = cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec(); - canon.extend_from_slice(&path); - canon } else { - let mut canon = cwd.clone(); - if ! canon.ends_with(b"/") { - canon.push(b'/'); - } + let mut canon = if !path.starts_with(b"/") { + let mut c = cwd.clone(); + if ! c.ends_with(b"/") { + c.push(b'/'); + } + c + } else { + cwd[..cwd.iter().position(|&b| b == b':').map_or(1, |i| i + 1)].to_vec() + }; + canon.extend_from_slice(&path); // NOTE: assumes the scheme does not include anything like "../" or "./" let mut result = { - let rparts = canon.split(|&c| c == b'/') + let parts = canon.split(|&c| c == b'/') .filter(|&part| part != b".") .rev() .scan(0, |nskip, part| { if part == b".." { *nskip += 1; - Some(None) + Some(None) } else { if *nskip > 0 { *nskip -= 1; @@ -163,7 +165,7 @@ impl Context { }) .filter_map(|x| x) .collect::>(); - rparts + parts .iter() .rev() .fold(Vec::new(), |mut vec, &part| { @@ -173,11 +175,12 @@ impl Context { }) }; result.pop(); // remove extra '/' + + // replace with the root of the schema if it's empty if result.len() == 0 { - // replace with the root of the schema if it's empty let pos = canon.iter() - .position(|&b| b == b':') - .map_or(canon.len(), |p| p + 1); + .position(|&b| b == b':') + .map_or(canon.len(), |p| p + 1); canon.truncate(pos); canon } else {