use std::{cmp, io::ErrorKind}; use actix_web::HttpRequest; use time::Duration; use tokio::fs; use crate::config::Config; const INDEX_HTML: &str = include_str!("../template/index.html"); const AUTH_HIDE_JS: &str = include_str!("../template/auth-hide.js"); const AUTH_SNIPPET_HTML: &str = include_str!("../snippet/auth.html.snippet"); const MAX_SIZE_SNIPPET_HTML: &str = include_str!("../snippet/max_size.html.snippet"); pub async fn write_prefillable_templates(config: &Config) { let index_html = build_index_html(config); let auth_hide_js = build_auth_hide_js(config); let index_path = config.static_dir.join("index.html"); let auth_hide_path = config.static_dir.join("auth-hide.js"); fs::write(index_path, index_html) .await .expect("could not write index.html to static folder"); if let Some(auth_hide_js) = auth_hide_js { fs::write(auth_hide_path, auth_hide_js) .await .expect("could not write auth-hide.js to static folder"); } else { match fs::remove_file(auth_hide_path).await { Err(err) if err.kind() == ErrorKind::NotFound => {} r => r.expect("could not delete auth-hide.js from static folder"), } } } fn build_index_html(config: &Config) -> String { let auth_snippet = config .no_auth_limits .as_ref() .map_or("", |_| AUTH_SNIPPET_HTML); let max_size_snippet = config .max_file_size .as_ref() .map_or("", |_| MAX_SIZE_SNIPPET_HTML); INDEX_HTML .replace("{max_size_snippet}", max_size_snippet) .replace( "{max_size}", &render_file_size(config.max_file_size.unwrap_or(0)), ) .replace("{auth_snippet}", auth_snippet) .replace( "{auth_time}", &config .no_auth_limits .as_ref() .map(|limit| limit.max_time) .map_or("".into(), render_duration), ) .replace( "{auth_large_time}", &config .no_auth_limits .as_ref() .map(|limit| limit.large_file_max_time) .map_or("".into(), render_duration), ) .replace( "{auth_large_size}", &config .no_auth_limits .as_ref() .map(|limit| limit.large_file_size) .map_or("".into(), render_file_size), ) } fn render_file_size(size: u64) -> String { let magnitude = cmp::min((size as f64).log(1024.0) as u32, 5); let prefix = ["", "ki", "Mi", "Gi", "Ti", "Pi"][magnitude as usize]; let value = size / (1024_u64.pow(magnitude)); format!("{}{}B", value, prefix) } fn render_duration(duration: Duration) -> String { let days = duration.whole_days(); let hours = duration.whole_hours() % 24; let minutes = duration.whole_minutes() % 60; let seconds = duration.whole_seconds() % 60; let mut elements = vec![]; if let Some(name) = pluralize(days, "tag", "e") { elements.push(name); } if let Some(name) = pluralize(hours, "stunde", "n") { elements.push(name); } if let Some(name) = pluralize(minutes, "minute", "n") { elements.push(name); } if let Some(name) = pluralize(seconds, "sekunde", "n") { elements.push(name); } elements.join("+") } fn pluralize(number: i64, word: &str, suffix: &str) -> Option { match number { 0 => None, 1 => Some(format!("{} {}", number, word)), _ => Some(format!("{} {}{}", number, word, suffix)), } } fn build_auth_hide_js(config: &Config) -> Option { if let Some(no_auth_limits) = &config.no_auth_limits { let auth_hide_js = AUTH_HIDE_JS .replace( "{no_auth_max_time}", &no_auth_limits.max_time.whole_seconds().to_string(), ) .replace( "{no_auth_large_file_max_time}", &no_auth_limits .large_file_max_time .whole_seconds() .to_string(), ) .replace( "{no_auth_large_file_size}", &no_auth_limits.large_file_size.to_string(), ); Some(auth_hide_js) // Ok(HttpResponse::Ok() // .content_type("application/javascript") // .body(auth_hide_js)) } else { None // Err(error::ErrorNotFound("file not found")) } } pub fn get_host_url(req: &HttpRequest) -> String { let conn = req.connection_info(); format!("{}://{}", conn.scheme(), conn.host()) }