From ca5c3d7c541f7aa89c42db312d12e634cdc41460 Mon Sep 17 00:00:00 2001 From: sigoden Date: Mon, 22 Jul 2024 08:02:32 +0800 Subject: [PATCH] feat: base64 index-data to avoid misencoding (#421) --- assets/index.js | 2 +- src/auth.rs | 6 +++--- src/server.rs | 8 ++++++-- tests/utils.rs | 7 +++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/assets/index.js b/assets/index.js index b35500b..4143021 100644 --- a/assets/index.js +++ b/assets/index.js @@ -108,7 +108,7 @@ window.addEventListener("DOMContentLoaded", async () => { return; } - DATA = JSON.parse($indexData.innerHTML); + DATA = JSON.parse(atob($indexData.innerHTML)); DIR_EMPTY_NOTE = PARAMS.q ? 'No results' : DATA.dir_exists ? 'Empty folder' : 'Folder will be created when a file is uploaded'; await ready(); diff --git a/src/auth.rs b/src/auth.rs index 58a8bd9..3640f6c 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,7 +1,7 @@ use crate::{args::Args, server::Response, utils::unix_now}; use anyhow::{anyhow, bail, Result}; -use base64::{engine::general_purpose, Engine as _}; +use base64::{engine::general_purpose::STANDARD, Engine as _}; use headers::HeaderValue; use hyper::{header::WWW_AUTHENTICATE, Method}; use indexmap::IndexMap; @@ -287,7 +287,7 @@ pub fn www_authenticate(res: &mut Response, args: &Args) -> Result<()> { pub fn get_auth_user(authorization: &HeaderValue) -> Option { if let Some(value) = strip_prefix(authorization.as_bytes(), b"Basic ") { - let value: Vec = general_purpose::STANDARD.decode(value).ok()?; + let value: Vec = STANDARD.decode(value).ok()?; let parts: Vec<&str> = std::str::from_utf8(&value).ok()?.split(':').collect(); Some(parts[0].to_string()) } else if let Some(value) = strip_prefix(authorization.as_bytes(), b"Digest ") { @@ -306,7 +306,7 @@ pub fn check_auth( auth_pass: &str, ) -> Option<()> { if let Some(value) = strip_prefix(authorization.as_bytes(), b"Basic ") { - let value: Vec = general_purpose::STANDARD.decode(value).ok()?; + let value: Vec = STANDARD.decode(value).ok()?; let parts: Vec<&str> = std::str::from_utf8(&value).ok()?.split(':').collect(); if parts[0] != auth_user { diff --git a/src/server.rs b/src/server.rs index 55e6273..404ada4 100644 --- a/src/server.rs +++ b/src/server.rs @@ -10,6 +10,7 @@ use crate::Args; use anyhow::{anyhow, Result}; use async_zip::{tokio::write::ZipFileWriter, Compression, ZipDateTime, ZipEntryBuilder}; +use base64::{engine::general_purpose::STANDARD, Engine as _}; use bytes::Bytes; use chrono::{LocalResult, TimeZone, Utc}; use futures_util::{pin_mut, TryStreamExt}; @@ -931,13 +932,14 @@ impl Server { }; res.headers_mut() .typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8)); + let index_data = STANDARD.encode(serde_json::to_string(&data)?); let output = self .html .replace( "__ASSETS_PREFIX__", &format!("{}{}", self.args.uri_prefix, self.assets_prefix), ) - .replace("__INDEX_DATA__", &serde_json::to_string(&data)?); + .replace("__INDEX_DATA__", &index_data); res.headers_mut() .typed_insert(ContentLength(output.as_bytes().len() as u64)); if head_only { @@ -1179,12 +1181,14 @@ impl Server { } else { res.headers_mut() .typed_insert(ContentType::from(mime_guess::mime::TEXT_HTML_UTF_8)); + + let index_data = STANDARD.encode(serde_json::to_string(&data)?); self.html .replace( "__ASSETS_PREFIX__", &format!("{}{}", self.args.uri_prefix, self.assets_prefix), ) - .replace("__INDEX_DATA__", &serde_json::to_string(&data)?) + .replace("__INDEX_DATA__", &index_data) }; res.headers_mut() .typed_insert(ContentLength(output.as_bytes().len() as u64)); diff --git a/tests/utils.rs b/tests/utils.rs index 1bccefa..30c6437 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -1,3 +1,4 @@ +use base64::{engine::general_purpose::STANDARD, Engine as _}; use indexmap::IndexSet; use serde_json::Value; @@ -48,7 +49,7 @@ pub fn retrieve_index_paths(content: &str) -> IndexSet { #[allow(dead_code)] pub fn retrieve_edit_file(content: &str) -> Option { - let value = retrieve_json(content)?; + let value = retrieve_json(content).unwrap(); let value = value.get("editable").unwrap(); Some(value.as_bool().unwrap()) } @@ -73,7 +74,9 @@ pub fn retrieve_json(content: &str) -> Option { let end_index = line[start_content_index..].find(end_tag)?; let end_content_index = start_content_index + end_index; - let value = line[start_content_index..end_content_index].parse().ok()?; + let value = &line[start_content_index..end_content_index]; + let value = STANDARD.decode(value).ok()?; + let value = serde_json::from_slice(&value).ok()?; Some(value) }