2023-02-10 23:17:21 +00:00
|
|
|
use std::{cmp, io::ErrorKind, str::FromStr};
|
2021-12-08 17:54:55 +00:00
|
|
|
|
2022-02-26 23:34:57 +00:00
|
|
|
use actix_web::HttpRequest;
|
2022-02-27 00:50:29 +00:00
|
|
|
use time::Duration;
|
2022-02-26 23:34:57 +00:00
|
|
|
use tokio::fs;
|
2023-02-10 23:17:21 +00:00
|
|
|
use url::Url;
|
2021-12-08 17:54:55 +00:00
|
|
|
|
|
|
|
use crate::config::Config;
|
|
|
|
|
|
|
|
const INDEX_HTML: &str = include_str!("../template/index.html");
|
|
|
|
const AUTH_HIDE_JS: &str = include_str!("../template/auth-hide.js");
|
2022-07-02 23:02:27 +00:00
|
|
|
const AUTH_SNIPPET_HTML: &str = include_str!("../snippet/auth.html.snippet");
|
|
|
|
const MAX_SIZE_SNIPPET_HTML: &str = include_str!("../snippet/max_size.html.snippet");
|
2023-02-10 23:17:21 +00:00
|
|
|
|
2023-02-10 23:16:51 +00:00
|
|
|
const ABUSE_SNIPPET_HTML: &str = include_str!("../snippet/abuse.html.snippet");
|
2021-12-08 17:54:55 +00:00
|
|
|
|
2023-02-10 23:17:21 +00:00
|
|
|
const UPLOAD_HTML: &str = include_str!("../template/upload.html");
|
|
|
|
const UPLOAD_SHORT_HTML: &str = include_str!("../template/upload-short.html");
|
|
|
|
|
|
|
|
const TEXT_VIEW_HTML: &str = include_str!("../template/text-view.html");
|
|
|
|
const URL_VIEW_HTML: &str = include_str!("../template/url-view.html");
|
|
|
|
|
|
|
|
pub fn build_uploaded_html(
|
|
|
|
req: &HttpRequest,
|
|
|
|
id: &str,
|
|
|
|
name: Option<&str>,
|
|
|
|
config: &Config,
|
|
|
|
) -> String {
|
|
|
|
let upload_html = if name.is_some() {
|
|
|
|
UPLOAD_SHORT_HTML
|
|
|
|
.replace("{link}", &get_file_url(req, id, name))
|
|
|
|
.replace("{shortlink}", &get_file_url(req, id, None))
|
|
|
|
} else {
|
|
|
|
UPLOAD_HTML.replace("{link}", &get_file_url(req, id, name))
|
|
|
|
};
|
|
|
|
insert_abuse_template(upload_html, None, config)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_file_url(req: &HttpRequest, id: &str, name: Option<&str>) -> String {
|
|
|
|
let host = get_host_url(req);
|
|
|
|
if let Some(name) = name {
|
|
|
|
let encoded_name = urlencoding::encode(name);
|
|
|
|
format!("{host}/{id}/{encoded_name}")
|
|
|
|
} else {
|
|
|
|
format!("{host}/{id}")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_html_view_template(content: &str, req: &HttpRequest, config: &Config) -> String {
|
|
|
|
let encoded = htmlescape::encode_minimal(content);
|
|
|
|
let html = if !content.trim().contains(['\n', '\r']) && Url::from_str(content.trim()).is_ok() {
|
|
|
|
let attribute_encoded = htmlescape::encode_attribute(content);
|
|
|
|
URL_VIEW_HTML
|
|
|
|
.replace("{link_content}", &encoded)
|
|
|
|
.replace("{link_attribute}", &attribute_encoded)
|
|
|
|
} else {
|
|
|
|
TEXT_VIEW_HTML.replace("{text}", &encoded)
|
|
|
|
};
|
|
|
|
insert_abuse_template(html, Some(req), config)
|
|
|
|
}
|
|
|
|
|
2021-12-08 17:54:55 +00:00
|
|
|
pub async fn write_prefillable_templates(config: &Config) {
|
|
|
|
let index_path = config.static_dir.join("index.html");
|
2022-07-02 23:02:27 +00:00
|
|
|
fs::write(index_path, build_index_html(config))
|
2021-12-08 17:54:55 +00:00
|
|
|
.await
|
|
|
|
.expect("could not write index.html to static folder");
|
2022-07-02 23:02:27 +00:00
|
|
|
|
|
|
|
let auth_hide_path = config.static_dir.join("auth-hide.js");
|
|
|
|
if let Some(auth_hide_js) = build_auth_hide_js(config) {
|
2022-02-26 23:34:57 +00:00
|
|
|
fs::write(auth_hide_path, auth_hide_js)
|
2021-12-08 17:54:55 +00:00
|
|
|
.await
|
|
|
|
.expect("could not write auth-hide.js to static folder");
|
2022-02-26 23:34:57 +00:00
|
|
|
} 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"),
|
|
|
|
}
|
2021-12-08 17:54:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_index_html(config: &Config) -> String {
|
2022-07-02 23:02:27 +00:00
|
|
|
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}", "");
|
|
|
|
}
|
2023-02-10 23:16:51 +00:00
|
|
|
html = insert_abuse_template(html, None, config);
|
2022-07-02 23:02:27 +00:00
|
|
|
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 {
|
2022-11-04 10:37:10 +00:00
|
|
|
html = html.replace("{max_size_snippet}", "");
|
2022-07-02 23:02:27 +00:00
|
|
|
};
|
|
|
|
html
|
2021-12-08 17:54:55 +00:00
|
|
|
}
|
|
|
|
|
2023-02-10 23:16:51 +00:00
|
|
|
pub fn insert_abuse_template(html: String, req: Option<&HttpRequest>, config: &Config) -> String {
|
|
|
|
if let Some(abuse_mail) = &config.abuse_mail {
|
|
|
|
let url = if let Some(req) = req {
|
|
|
|
format!("{host}{path}", host = get_host_url(req), path = req.uri())
|
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
};
|
|
|
|
// urlencoding::encode(data)
|
|
|
|
html.replace("{abuse}", ABUSE_SNIPPET_HTML.trim_end())
|
|
|
|
.replace("{abusemail}", abuse_mail)
|
|
|
|
.replace("{url}", &urlencoding::encode(&url))
|
|
|
|
} else {
|
|
|
|
html.replace("{abuse}", "")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 17:54:55 +00:00
|
|
|
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));
|
2022-10-07 13:52:12 +00:00
|
|
|
format!("{value}{prefix}B")
|
2021-12-08 17:54:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn render_duration(duration: Duration) -> String {
|
2022-02-27 00:50:29 +00:00
|
|
|
let days = duration.whole_days();
|
|
|
|
let hours = duration.whole_hours() % 24;
|
|
|
|
let minutes = duration.whole_minutes() % 60;
|
|
|
|
let seconds = duration.whole_seconds() % 60;
|
2021-12-08 17:54:55 +00:00
|
|
|
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<String> {
|
|
|
|
match number {
|
|
|
|
0 => None,
|
2022-10-07 13:52:12 +00:00
|
|
|
1 => Some(format!("{number} {word}")),
|
|
|
|
_ => Some(format!("{number} {word}{suffix}")),
|
2021-12-08 17:54:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_auth_hide_js(config: &Config) -> Option<String> {
|
|
|
|
if let Some(no_auth_limits) = &config.no_auth_limits {
|
|
|
|
let auth_hide_js = AUTH_HIDE_JS
|
|
|
|
.replace(
|
|
|
|
"{no_auth_max_time}",
|
2022-02-27 00:50:29 +00:00
|
|
|
&no_auth_limits.max_time.whole_seconds().to_string(),
|
2021-12-08 17:54:55 +00:00
|
|
|
)
|
|
|
|
.replace(
|
|
|
|
"{no_auth_large_file_max_time}",
|
2022-02-27 00:50:29 +00:00
|
|
|
&no_auth_limits
|
|
|
|
.large_file_max_time
|
|
|
|
.whole_seconds()
|
|
|
|
.to_string(),
|
2021-12-08 17:54:55 +00:00
|
|
|
)
|
|
|
|
.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"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-26 23:34:57 +00:00
|
|
|
pub fn get_host_url(req: &HttpRequest) -> String {
|
2021-12-08 17:54:55 +00:00
|
|
|
let conn = req.connection_info();
|
|
|
|
format!("{}://{}", conn.scheme(), conn.host())
|
|
|
|
}
|