mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 09:28:11 +00:00
downloads work
This commit is contained in:
1 parent
d9018028ab
commit
ba4871118b
1 file changed
+39
-17
@@ -15,46 +15,47 @@ pub async fn download_url_to_user_download_dir(
|
||||
app_prefs: &AppPreferences,
|
||||
) -> Result<PathBuf, ArtcraftError> {
|
||||
|
||||
let url_path = match url.to_file_path() {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
error!("Could not get file path from URL: {:?}", err);
|
||||
return Err(ArtcraftError::AnyhowError(anyhow!("Could not get file path from URL: {:?}", err)));
|
||||
}
|
||||
};
|
||||
let path_segments = url.path_segments()
|
||||
.ok_or_else(|| ArtcraftError::AnyhowError(anyhow!("URL does not have path segments (1): {:?}", url)))?;
|
||||
|
||||
let url_file_name = url_path
|
||||
.file_name()
|
||||
.ok_or(ArtcraftError::AnyhowError(anyhow!(
|
||||
"No file name for path: {:?} at url: {:?}", &url_path, &url)))?
|
||||
.to_str()
|
||||
.ok_or(ArtcraftError::AnyhowError(anyhow!(
|
||||
"No file name for path: {:?} at url: {:?}", &url_path, &url)))?
|
||||
let mut url_file_name = path_segments.last()
|
||||
.ok_or_else(|| ArtcraftError::AnyhowError(anyhow!("URL does not have path segments (2): {:?}", url)))?
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
if !url_file_name.starts_with("artcraft") {
|
||||
url_file_name = format!("artcraft_{}", url_file_name);
|
||||
}
|
||||
|
||||
let url_file_name = url_file_name;
|
||||
|
||||
check_url_file_name_for_downloadability(&url_file_name)?;
|
||||
|
||||
let download_directory = app_prefs
|
||||
.preferred_download_directory
|
||||
.download_directory(app_data_root);
|
||||
|
||||
info!("Pushing path `{}` onto downloaded directory `{:?}`", url_file_name, download_directory);
|
||||
|
||||
let download_filename = {
|
||||
let mut download_filename = download_directory.clone();
|
||||
download_filename.push(&url_file_name);
|
||||
download_directory
|
||||
download_filename
|
||||
};
|
||||
|
||||
info!("Download filename: `{:?}`", download_filename);
|
||||
|
||||
if download_filename.exists() {
|
||||
return Err(ArtcraftError::CannotDownloadFilePathAlreadyExists { path: download_filename }.into());
|
||||
}
|
||||
|
||||
|
||||
info!("Downloading bytes from url: {:?}", url);
|
||||
|
||||
let response = reqwest::get(url.clone()).await?;
|
||||
let response_bytes = response.bytes().await?;
|
||||
|
||||
info!("Writing file: {:?}", download_filename);
|
||||
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
@@ -68,6 +69,16 @@ pub async fn download_url_to_user_download_dir(
|
||||
|
||||
// TODO: This likely needs more protections.
|
||||
fn check_url_file_name_for_downloadability(filename: &str) -> Result<(), ArtcraftError> {
|
||||
if filename.trim().is_empty() {
|
||||
error!("Download filename is empty!");
|
||||
return Err(ArtcraftError::BadDownloadFilename { path: "".into() }.into());
|
||||
}
|
||||
|
||||
if !filename.is_ascii() {
|
||||
error!("Download filename is not completely ASCII: {:?}", filename);
|
||||
return Err(ArtcraftError::BadDownloadFilename { path: filename.into() }.into());
|
||||
}
|
||||
|
||||
if filename.contains("/")
|
||||
|| filename.contains("..")
|
||||
|| filename.contains("\\")
|
||||
@@ -76,6 +87,17 @@ fn check_url_file_name_for_downloadability(filename: &str) -> Result<(), Artcraf
|
||||
return Err(ArtcraftError::BadDownloadFilename { path: filename.into() }.into());
|
||||
}
|
||||
|
||||
if filename.contains("'")
|
||||
|| filename.contains("\"")
|
||||
|| filename.contains("%")
|
||||
|| filename.contains("<")
|
||||
|| filename.contains(">")
|
||||
|| filename.contains("|")
|
||||
{
|
||||
error!("Download filename has dangerous path components: {:?}", filename);
|
||||
return Err(ArtcraftError::BadDownloadFilename { path: filename.into() }.into());
|
||||
}
|
||||
|
||||
if filename.ends_with("apk")
|
||||
|| filename.ends_with("app")
|
||||
|| filename.ends_with("bat")
|
||||
|
||||
Reference in new issue
Block a user