Compare commits
No commits in common. "30d059b7af91a35fd20c9bb791e7f6801c8a5da1" and "48005123de46e78b59576f1648688a632e3154f8" have entirely different histories.
30d059b7af
...
48005123de
|
@ -5,7 +5,7 @@ use async_std::{fs::File, path::Path, prelude::*};
|
||||||
use chrono::{prelude::*, Duration};
|
use chrono::{prelude::*, Duration};
|
||||||
use futures::{StreamExt, TryStreamExt};
|
use futures::{StreamExt, TryStreamExt};
|
||||||
|
|
||||||
const MAX_UPLOAD_SECONDS: i64 = 31 * 24 * 60 * 60;
|
const MAX_UPLOAD_SECONDS: u64 = 31 * 24 * 60 * 60;
|
||||||
const DEFAULT_UPLOAD_SECONDS: u64 = 30 * 60;
|
const DEFAULT_UPLOAD_SECONDS: u64 = 30 * 60;
|
||||||
|
|
||||||
pub(crate) struct UploadConfig {
|
pub(crate) struct UploadConfig {
|
||||||
|
@ -64,60 +64,53 @@ pub(crate) async fn parse_multipart(
|
||||||
|
|
||||||
let original_name = original_name.ok_or_else(|| error::ErrorBadRequest("no content found"))?;
|
let original_name = original_name.ok_or_else(|| error::ErrorBadRequest("no content found"))?;
|
||||||
let kind = kind.ok_or_else(|| error::ErrorBadRequest("no content found"))?;
|
let kind = kind.ok_or_else(|| error::ErrorBadRequest("no content found"))?;
|
||||||
|
|
||||||
|
if original_name.len() > 255 {
|
||||||
|
return Err(error::ErrorBadRequest("filename is too long"));
|
||||||
|
}
|
||||||
let validated_keep_for: u64 = if let Some(keep_for) = keep_for {
|
let validated_keep_for: u64 = if let Some(keep_for) = keep_for {
|
||||||
keep_for
|
let seconds = keep_for.parse().map_err(|e| {
|
||||||
.parse()
|
error::ErrorBadRequest(format!("field keep_for is not a number: {}", e))
|
||||||
.map_err(|e| error::ErrorBadRequest(format!("field keep_for is not a number: {}", e)))?
|
})?;
|
||||||
|
if seconds > MAX_UPLOAD_SECONDS {
|
||||||
|
return Err(error::ErrorBadRequest(format!(
|
||||||
|
"maximum allowed validity is {} seconds, but you specified {} seconds",
|
||||||
|
MAX_UPLOAD_SECONDS, seconds
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
seconds
|
||||||
} else {
|
} else {
|
||||||
DEFAULT_UPLOAD_SECONDS
|
DEFAULT_UPLOAD_SECONDS
|
||||||
};
|
};
|
||||||
let valid_duration = Duration::seconds(validated_keep_for as i64);
|
let valid_duration = Duration::seconds(validated_keep_for as i64);
|
||||||
let now = Local::now();
|
let valid_till = Local::now() + valid_duration;
|
||||||
let valid_till = now + valid_duration;
|
|
||||||
|
|
||||||
let upload_config = UploadConfig {
|
check_auth_requirements(size, valid_duration, password, config)?;
|
||||||
|
|
||||||
|
Ok(UploadConfig {
|
||||||
original_name,
|
original_name,
|
||||||
valid_till,
|
valid_till,
|
||||||
kind,
|
kind,
|
||||||
delete_on_download,
|
delete_on_download,
|
||||||
};
|
})
|
||||||
|
|
||||||
check_requirements(&upload_config, size, password, now, config)?;
|
|
||||||
|
|
||||||
Ok(upload_config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_requirements(
|
fn check_auth_requirements(
|
||||||
upload_config: &UploadConfig,
|
|
||||||
size: u64,
|
size: u64,
|
||||||
|
validated_keep_for: Duration,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
now: DateTime<Local>,
|
|
||||||
config: &config::Config,
|
config: &config::Config,
|
||||||
) -> Result<(), error::Error> {
|
) -> Result<(), error::Error> {
|
||||||
if upload_config.original_name.len() > 255 {
|
|
||||||
return Err(error::ErrorBadRequest("filename is too long"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let valid_seconds = (upload_config.valid_till - now).num_seconds();
|
|
||||||
if valid_seconds > MAX_UPLOAD_SECONDS {
|
|
||||||
return Err(error::ErrorBadRequest(format!(
|
|
||||||
"maximum allowed validity is {} seconds, but you specified {} seconds",
|
|
||||||
MAX_UPLOAD_SECONDS, valid_seconds
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(no_auth_limits) = &config.no_auth_limits {
|
if let Some(no_auth_limits) = &config.no_auth_limits {
|
||||||
let requires_auth = valid_seconds > no_auth_limits.max_time.num_seconds()
|
let requires_auth = validated_keep_for > no_auth_limits.max_time
|
||||||
|| valid_seconds > no_auth_limits.large_file_max_time.num_seconds()
|
|| validated_keep_for > no_auth_limits.large_file_max_time
|
||||||
&& size > no_auth_limits.large_file_size;
|
&& size > no_auth_limits.large_file_size;
|
||||||
// hIGh sECUriTy paSsWoRD CHEck
|
|
||||||
if requires_auth && password.as_ref() != Some(&no_auth_limits.auth_password) {
|
if requires_auth && password.as_ref() != Some(&no_auth_limits.auth_password) {
|
||||||
return Err(error::ErrorBadRequest(
|
return Err(error::ErrorBadRequest(
|
||||||
"upload requires authentication, but authentication was incorrect",
|
"upload requires authentication, but authentication was incorrect",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,12 +176,13 @@ async fn write_to_file(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_original_filename(field: &actix_multipart::Field) -> Option<String> {
|
fn get_original_filename(field: &actix_multipart::Field) -> Option<String> {
|
||||||
field
|
field.content_disposition().and_then(|content_disposition| {
|
||||||
.content_disposition()?
|
content_disposition
|
||||||
.parameters
|
.parameters
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find_map(|param| match param {
|
.find_map(|param| match param {
|
||||||
DispositionParam::Filename(filename) => Some(filename),
|
DispositionParam::Filename(filename) => Some(filename),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,10 +73,6 @@ details {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
details summary {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus-within,
|
input:focus-within,
|
||||||
select:focus-within,
|
select:focus-within,
|
||||||
textarea:focus-within,
|
textarea:focus-within,
|
||||||
|
|
Loading…
Reference in New Issue