Skip to content

Commit ea0e251

Browse files
Merge pull request #63 from davidchalifoux/illegal-characters
fix(download): Replace illegal characters in file and folder names by default when downloading. This can be disabled with --no-replace.
2 parents dfd802d + d500663 commit ea0e251

File tree

2 files changed

+84
-10
lines changed

2 files changed

+84
-10
lines changed

src/main.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ fn cli() -> Command {
135135
.required(false)
136136
.num_args(0)
137137
)
138+
.arg(
139+
Arg::new("no-replace")
140+
.long("no-replace")
141+
.help("Disable character replacement of files with illegal characters")
142+
.required(false)
143+
.num_args(0)
144+
)
138145
)
139146
.subcommand(
140147
Command::new("delete")
@@ -519,15 +526,21 @@ fn main() {
519526
require_auth(&client, &config);
520527

521528
let recursive = sub_matches.get_flag("recursive");
522-
529+
let no_replace = sub_matches.get_flag("no-replace");
523530
let path = sub_matches.get_one::<String>("path");
524-
525531
let file_id = sub_matches
526532
.get_one("FILE_ID")
527533
.expect("missing file_id argument");
528534

529-
put::files::download(&client, &config.api_token, *file_id, recursive, path)
530-
.expect("downloading file(s)");
535+
put::files::download(
536+
&client,
537+
&config.api_token,
538+
*file_id,
539+
recursive,
540+
path,
541+
no_replace,
542+
)
543+
.expect("downloading file(s)");
531544
}
532545
Some(("delete", sub_matches)) => {
533546
require_auth(&client, &config);

src/put/files.rs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,55 @@ pub fn get_extractions(client: &Client, api_token: &String) -> Result<Extraction
177177
Ok(response)
178178
}
179179

180-
// Downloads a file or folder
180+
struct ReplaceChar<'a> {
181+
from: &'a str,
182+
to: &'a str,
183+
}
184+
185+
/// Replaces illegal characters in a file name
186+
fn replace_illegal_chars(name: &str) -> String {
187+
let mut name: String = name.to_owned();
188+
189+
const ILLEGAL_CHARS: [ReplaceChar<'_>; 7] = [
190+
ReplaceChar { from: "<", to: "" },
191+
ReplaceChar { from: ">", to: "" },
192+
ReplaceChar {
193+
from: ":",
194+
to: " - ",
195+
},
196+
ReplaceChar {
197+
from: "\"",
198+
to: "\'",
199+
},
200+
ReplaceChar { from: "|", to: "" },
201+
ReplaceChar { from: "?", to: "" },
202+
ReplaceChar { from: "*", to: "" },
203+
];
204+
205+
for replacement in ILLEGAL_CHARS {
206+
name = name.replace(replacement.from, replacement.to);
207+
}
208+
209+
name
210+
}
211+
212+
/// Downloads a file or folder
213+
///
214+
/// # Arguments
215+
///
216+
/// * `client` - The reqwest client
217+
/// * `api_token` - The user's API token
218+
/// * `file_id` - The ID of the file or folder to download
219+
/// * `recursive` - Recursively download the folder
220+
/// * `path` - The path to save the file or folder to
221+
/// * `no_replace` - Do not replace illegal characters in the file name
181222
pub fn download(
182223
client: &Client,
183224
api_token: &String,
184225
file_id: i64,
185226
recursive: bool,
186227
path: Option<&String>,
228+
no_replace: bool,
187229
) -> Result<(), Error> {
188230
let files: FilesResponse =
189231
put::files::list(client, api_token, file_id).expect("querying files");
@@ -194,16 +236,27 @@ pub fn download(
194236
match recursive {
195237
true => {
196238
// Recursively download the folder
197-
let directory_path: String = match path {
239+
let mut directory_path: String = match path {
198240
Some(p) => format!("{}/{}", p, files.parent.name), // Use the provided path if there is one
199241
None => format!("./{}", files.parent.name),
200242
};
201243

244+
if !no_replace {
245+
directory_path = replace_illegal_chars(&directory_path);
246+
}
247+
202248
fs::create_dir_all(directory_path.clone()).expect("creating directory");
203249

204250
for file in files.files {
205-
download(client, api_token, file.id, true, Some(&directory_path))
206-
.expect("downloading file recursively");
251+
download(
252+
client,
253+
api_token,
254+
file.id,
255+
true,
256+
Some(&directory_path),
257+
no_replace,
258+
)
259+
.expect("downloading file recursively");
207260
}
208261
}
209262
false => {
@@ -215,11 +268,15 @@ pub fn download(
215268

216269
println!("ZIP created!");
217270

218-
let output_path: String = match path {
271+
let mut output_path: String = match path {
219272
Some(p) => format!("{}/{}.zip", p, files.parent.name),
220273
None => format!("./{}.zip", files.parent.name),
221274
};
222275

276+
if !no_replace {
277+
output_path = replace_illegal_chars(&output_path);
278+
}
279+
223280
println!("Downloading: {}", files.parent.name);
224281
println!("Saving to: {}\n", output_path);
225282

@@ -245,11 +302,15 @@ pub fn download(
245302
let url_response: UrlResponse =
246303
put::files::url(client, api_token, file_id).expect("creating download URL");
247304

248-
let output_path: String = match path {
305+
let mut output_path: String = match path {
249306
Some(p) => format!("{}/{}", p, files.parent.name),
250307
None => format!("./{}", files.parent.name),
251308
};
252309

310+
if !no_replace {
311+
output_path = replace_illegal_chars(&output_path);
312+
}
313+
253314
println!("Downloading: {}", files.parent.name);
254315
println!("Saving to: {}\n", output_path);
255316

0 commit comments

Comments
 (0)