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_path = config.static_dir.join("index.html"); fs::write(index_path, build_index_html(config)) .await .expect("could not write index.html to static folder"); let auth_hide_path = config.static_dir.join("auth-hide.js"); if let Some(auth_hide_js) = build_auth_hide_js(config) { 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 mut html = INDEX_HTML.to_owned(); if let Some(limit) = config.no_auth_limits.as_ref() { html = html .replace("{auth_snippet}", AUTH_SNIPPET_HTML.trim_end()) .replace("{auth_time}", &render_duration(limit.max_time)) .replace( "{auth_large_time}", &render_duration(limit.large_file_max_time), ) .replace( "{auth_large_size}", &render_file_size(limit.large_file_size), ); } else { html = html.replace("{auth_snippet}", ""); } if let Some(max_file_size) = config.max_file_size { html = html .replace("{max_size_snippet}", MAX_SIZE_SNIPPET_HTML.trim_end()) .replace("{max_size}", &render_file_size(max_file_size)); } else { html = html.replace("{max_size_snippet}", ""); }; html } 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!("{value}{prefix}B") } 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()) }