Files
cadcraft/crates/engine/src/doc_path.rs
T
aiongg 8fe7c421ea Xrefs and data links: follow stored paths only on this computer or the drawing's share
Xref paths saved in a drawing (on open, on Reload, in the External
References list, XOPEN, nested xrefs) and table data-link paths re-read by
DATALINKUPDATE go through doc_path::resolve (craft-docpath): relative
paths resolve beside the drawing that stores them, and paths to other
computers, devices and URLs are not opened. Such an xref is Unresolved
with the reason, unless a file of its name is beside the host drawing.
Paths given to XATTACH, -XREF Path and DATALINK are used as given.

One load of xrefs reads at most 1 GB from referenced files in total.
2026-10-16 17:18:34 +00:00

39 lines
1.9 KiB
Rust

//! Paths stored in a drawing: xref paths and table data links.
//!
//! Such a path reaches the file system only through [`resolve`]: a relative path is taken from
//! the drawing's folder, and only files on this computer, or on the network share the drawing
//! itself is on, are opened (see `craft_docpath`). A refused path is handled like a missing file,
//! with the reason in its status. Paths the user gives a command (XATTACH, -XREF Path, DATALINK)
//! are their own choice and are used as given.
use std::path::{Path, PathBuf};
pub use craft_docpath::Refused;
/// The file to open for `stored`, a path or `file:` URL stored in the drawing saved at
/// `document` (`None` for a drawing without a file).
///
/// A result that isn't absolute is refused as [`Refused::Invalid`]: without a document a
/// relative path would depend on the working directory, and a Windows drive path names no file
/// on other platforms.
pub fn resolve(stored: &str, document: Option<&Path>) -> Result<PathBuf, Refused> {
let document = document.filter(|d| !d.as_os_str().is_empty()).map(|d| std::path::absolute(d).unwrap_or_else(|_| d.to_path_buf()));
let path = craft_docpath::resolve(stored.trim(), document.as_deref())?;
if path.is_absolute() { Ok(path) } else { Err(Refused::Invalid) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn relative_paths_resolve_beside_the_drawing_and_other_computers_are_refused() {
let doc = std::env::temp_dir().join("plans").join("host.dxf");
assert_eq!(resolve("parts/a.dxf", Some(&doc)), Ok(std::env::temp_dir().join("plans").join("parts").join("a.dxf")));
assert_eq!(resolve("a.dxf", None), Err(Refused::Invalid));
assert_eq!(resolve(r"\\192.0.2.1\share\a.dxf", Some(&doc)), Err(Refused::Network));
assert_eq!(resolve("file://192.0.2.1/s/a.dxf", Some(&doc)), Err(Refused::Network));
assert_eq!(resolve("//192.0.2.1/s/a.dxf", None), Err(Refused::Network));
}
}