sanitize-filename-0.5.0/.cargo_vcs_info.json0000644000000001360000000000100144420ustar { "git": { "sha1": "4b9e27674a327fd330558e0c2c906d823e3ef772" }, "path_in_vcs": "" }sanitize-filename-0.5.0/.gitignore000075500000000000000000000000231046102023000152200ustar 00000000000000/target **/*.rs.bk sanitize-filename-0.5.0/Cargo.lock0000644000000033650000000000100124240ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] [[package]] name = "lazy_static" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" dependencies = [ "version_check", ] [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "regex" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "sanitize-filename" version = "0.5.0" dependencies = [ "lazy_static", "regex", ] [[package]] name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" sanitize-filename-0.5.0/Cargo.toml0000644000000016570000000000100124510ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "sanitize-filename" version = "0.5.0" authors = ["Jacob Brown "] description = "A simple filename sanitizer, based on Node's sanitize-filename" readme = "README.md" keywords = [ "filename", "sanitizer", ] license = "MIT" repository = "https://github.com/kardeiz/sanitize-filename" [dependencies.lazy_static] version = "1" [dependencies.regex] version = "1.9" features = [ "std", "unicode-case", ] default-features = false sanitize-filename-0.5.0/Cargo.toml.orig000075500000000000000000000006661046102023000161340ustar 00000000000000[package] authors = ["Jacob Brown "] name = "sanitize-filename" version = "0.5.0" keywords = ["filename", "sanitizer"] license = "MIT" readme = "README.md" repository = "https://github.com/kardeiz/sanitize-filename" description = "A simple filename sanitizer, based on Node's sanitize-filename" [dependencies] lazy_static = "1" regex = { version = "1.9", default-features = false, features = ["std", "unicode-case"] } sanitize-filename-0.5.0/README.md000075500000000000000000000022621046102023000145160ustar 00000000000000# sanitize-filename A basic filename sanitizer, based on Node's [sanitize-filename](https://www.npmjs.com/package/sanitize-filename). Use like: ```rust extern crate sanitize_filename; fn main() { println!("{}", sanitize_filename::sanitize("some-user-defined/../../../string")); // prints some-user-defined......string } ``` You can also configure a few basic options: ```rust let options = sanitize_filename::Options { truncate: true, // true by default, truncates to 255 bytes windows: true, // default value depends on the OS, removes reserved names like `con` from start of strings on Windows replacement: "" // str to replace sanitized chars/strings }; let sanitized = sanitize_filename::sanitize_with_options("some-user-defined/../../../string", options); ``` Also provides a basic command line binary. Use like: ```bash cargo install sanitize-filename sanitize-filename my_filename.txt ``` ``` Pass a file name to clean to the program (also reads STDIN) FLAGS: -r, --replace Replacement characters --windows, --no-windows Whether to handle filenames for Windows --truncate, --no-truncate Whether to truncate file names to 255 bytes ``` sanitize-filename-0.5.0/src/lib.rs000075500000000000000000000152631046102023000151470ustar 00000000000000extern crate regex; #[macro_use] extern crate lazy_static; use regex::{Regex, RegexBuilder}; lazy_static! { static ref ILLEGAL_RE: Regex = Regex::new(r#"[/\?<>\\:\*\|":]"#).unwrap(); static ref CONTROL_RE: Regex = Regex::new(r#"[\x00-\x1f\x80-\x9f]"#).unwrap(); static ref RESERVED_RE: Regex = Regex::new(r#"^\.+$"#).unwrap(); static ref WINDOWS_RESERVED_RE: Regex = RegexBuilder::new(r#"(?i)^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$"#) .case_insensitive(true) .build() .unwrap(); static ref WINDOWS_TRAILING_RE: Regex = Regex::new(r#"[\. ]+$"#).unwrap(); } #[derive(Clone)] pub struct Options<'a> { pub windows: bool, pub truncate: bool, pub replacement: &'a str } impl<'a> Default for Options<'a> { fn default() -> Self { Options { windows: cfg!(windows), truncate: true, replacement: "" } } } pub fn sanitize>(name: S) -> String { sanitize_with_options(name, Options::default()) } pub fn sanitize_with_options>(name: S, options: Options) -> String { let Options { windows, truncate, replacement } = options; let name = name.as_ref(); let name = ILLEGAL_RE.replace_all(&name, replacement); let name = CONTROL_RE.replace_all(&name, replacement); let name = RESERVED_RE.replace(&name, replacement); let collect = |name: ::std::borrow::Cow| { if truncate && name.len() > 255 { let mut end = 255; loop { if name.is_char_boundary(end) { break; } end -= 1; } String::from(&name[..end]) } else { String::from(name) } }; if windows { let name = WINDOWS_RESERVED_RE.replace(&name, replacement); let name = WINDOWS_TRAILING_RE.replace(&name, replacement); collect(name) } else { collect(name) } } #[derive(Clone)] pub struct OptionsForCheck { pub windows: bool, pub truncate: bool, } impl Default for OptionsForCheck { fn default() -> Self { OptionsForCheck { windows: cfg!(windows), truncate: true, } } } pub fn is_sanitized>(name: S) -> bool { is_sanitized_with_options(name, OptionsForCheck::default()) } pub fn is_sanitized_with_options>(name: S, options: OptionsForCheck) -> bool { let OptionsForCheck { windows, truncate } = options; let name = name.as_ref(); if ILLEGAL_RE.is_match(&name) { return false; } if CONTROL_RE.is_match(&name) { return false; } if RESERVED_RE.is_match(&name) { return false; } if truncate && name.len() > 255 { return false; } if windows { if WINDOWS_RESERVED_RE.is_match(&name) { return false; } if WINDOWS_TRAILING_RE.is_match(&name) { return false; } } return true; } #[cfg(test)] mod tests { // From https://github.com/parshap/node-sanitize-filename/blob/master/test.js static NAMES: &'static [&'static str] = &[ "the quick brown fox jumped over the lazy dog", "résumé", "hello\u{0000}world", "hello\nworld", "semi;colon.js", ";leading-semi.js", "slash\\.js", "slash/.js", "col:on.js", "star*.js", "question?.js", "quote\".js", "singlequote'.js", "brackts.js", "p|pes.js", "plus+.js", "'five and six(); let shorter = ::std::iter::repeat('a').take(255).collect::(); assert_eq!(super::sanitize_with_options(long, options.clone()), shorter); // is_sanitized let options = super::OptionsForCheck { windows: true, truncate: true, }; for (idx, name) in NAMES.iter().enumerate() { assert_eq!(super::is_sanitized_with_options(name, options.clone()), NAMES_IS_SANITIZED[idx]); } let long = ::std::iter::repeat('a').take(300).collect::(); assert_eq!(super::is_sanitized_with_options(long, options.clone()), false); } }sanitize-filename-0.5.0/src/main.rs000075500000000000000000000030261046102023000153170ustar 00000000000000extern crate sanitize_filename; fn main() -> Result<(), ::std::io::Error> { let mut input = None; let mut set_replacement = false; let mut replacement = None; let mut truncate = None; let mut windows = None; for arg in ::std::env::args().skip(1) { if set_replacement { replacement = Some(arg); set_replacement = false; } else if arg == "-r" || arg == "--replace" { set_replacement = true; } else if arg == "--truncate" { truncate = Some(true); } else if arg == "--no-truncate" { truncate = Some(false); } else if arg == "--windows" { windows = Some(true); } else if arg == "--no-windows" { windows = Some(false); } else if arg == "-" { input = None; } else { input = Some(arg); } } let input = if let Some(input) = input { input } else { let mut buffer = String::new(); ::std::io::Read::read_to_string(&mut ::std::io::stdin(), &mut buffer)?; buffer }; let mut options = sanitize_filename::Options::default(); if let Some(ref replacement) = replacement { options.replacement = replacement; } if let Some(windows) = windows { options.windows = windows; } if let Some(truncate) = truncate { options.truncate = truncate; } let output = sanitize_filename::sanitize_with_options(input, options); println!("{}", &output); Ok(()) }