-
Notifications
You must be signed in to change notification settings - Fork 106
Expand file tree
/
Copy pathextract_lorem.rs
More file actions
48 lines (43 loc) · 1.48 KB
/
extract_lorem.rs
File metadata and controls
48 lines (43 loc) · 1.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use std::{error::Error, io::Read};
fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<_> = std::env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {:?} <filename>", args[0]);
return Err("Wrong usage".into());
}
// Constrain the file path to the current directory and prevent directory traversal.
let base_dir = std::path::Path::new(".");
let requested_path = base_dir.join(&*args[1]);
let fname = match std::fs::canonicalize(&requested_path) {
Ok(p) => {
if !p.starts_with(base_dir) {
eprintln!("Error: invalid filename (outside allowed directory)");
return Err("Invalid filename".into());
}
p
}
Err(e) => {
println!("Error: cannot access {:?}: {e}", args[1]);
return Err(e.into());
}
};
let zipfile = match std::fs::File::open(&fname) {
Ok(f) => f,
Err(e) => {
println!("Error: failed to open {:?}: {e}", fname.display());
return Err(e.into());
}
};
let mut archive = zip::ZipArchive::new(zipfile).unwrap();
let mut file = match archive.by_name("test/lorem_ipsum.txt") {
Ok(file) => file,
Err(e) => {
println!("File test/lorem_ipsum.txt not found");
return Err(e.into());
}
};
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
println!("{contents}");
Ok(())
}