~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

A site's file is named in UTF-8, and a refused path says why

Merged chadtmiller.com asked to merge into feature/pages from chadtmiller.com/knotless:pages/paths
crates/knotless/src/site.rs+20−3
@@ -128,7 +128,8 @@ pub fn valid_path(path: &str) -> bool {
}
/// Every file under `dir`, by its path from it, in order. A link is
/// refused rather than followed, so a site holds what the directory does.
/// refused rather than followed, so a site holds what the directory does,
/// and so is a name that is not UTF-8, as two such could read as one path.
pub fn walk(dir: &Path) -> Result<Vec<(String, PathBuf)>> {
let mut found = Vec::new();
let mut dirs = vec![(String::new(), dir.to_path_buf())];
@@ -137,7 +138,8 @@ pub fn walk(dir: &Path) -> Result<Vec<(String, PathBuf)>> {
for entry in std::fs::read_dir(&at).with_context(reading)? {
let entry = entry.with_context(reading)?;
let path = entry.path();
let name = entry.file_name().to_string_lossy().into_owned();
let utf8 = format!("{}: a site's file is named in UTF-8", path.display());
let name = entry.file_name().into_string().ok().context(utf8)?;
let kind = entry.file_type().with_context(reading)?;
let named = format!("{prefix}{name}");
if kind.is_dir() {
@@ -208,7 +210,9 @@ pub async fn deploy(ctx: &Ctx, url: &RepoUrl, spec: Deploy) -> Result<Deployed>
let mut measured = Vec::new();
for (path, at) in found {
if !valid_path(&path) {
bail!("{path:?} is longer than a site's path can be, {MAX_PATH} bytes");
bail!(
"{path:?} cannot be a site's path: at most {MAX_PATH} bytes, with no empty, . or .. part"
);
}
let (size, sha256) = sha256_file(&at)?;
measured.push((path, at, size, sha256));
@@ -355,4 +359,17 @@ mod tests {
assert_eq!(content_type("data.bin"), None);
assert_eq!(content_type("dir.d/README"), None);
}
// Two names that are not UTF-8 could read as one path, so neither is
// taken. Linux alone lets a file be named so.
#[cfg(target_os = "linux")]
#[test]
fn a_name_not_in_utf8_is_refused() {
use std::os::unix::ffi::OsStrExt;
let dir = tempfile::tempdir().unwrap();
let name = std::ffi::OsStr::from_bytes(b"a\xff.html");
std::fs::write(dir.path().join(name), b"").unwrap();
let refused = walk(dir.path()).unwrap_err().to_string();
assert!(refused.contains("named in UTF-8"), "{refused}");
}
}
crates/knotless/tests/cli.rs+1−1
@@ -1477,7 +1477,7 @@ fn sites() {
let missing = s.path("missing").to_string_lossy().into_owned();
let refused = [
(vec![empty.as_str()], "a site holds 1 to 2000 files"),
(vec![deep.as_str()], "longer than a site's path can be"),
(vec![deep.as_str()], "cannot be a site's path"),
(vec![linked.as_str()], "not links"),
(vec![missing.as_str()], "reading"),
(