diff options
| -rw-r--r-- | cache/src/backends/filesystem.rs | 5 | ||||
| -rw-r--r-- | cache/src/helper.rs | 20 | ||||
| -rw-r--r-- | import/src/tmdb.rs | 33 | ||||
| -rw-r--r-- | import/src/trakt.rs | 2 |
4 files changed, 36 insertions, 24 deletions
diff --git a/cache/src/backends/filesystem.rs b/cache/src/backends/filesystem.rs index 9a9db9c..ec242d2 100644 --- a/cache/src/backends/filesystem.rs +++ b/cache/src/backends/filesystem.rs @@ -5,7 +5,7 @@ */ use crate::{Config, backends::CacheStorage}; -use anyhow::Result; +use anyhow::{Result, bail}; use rand::random; use std::{ fs::{File, create_dir_all, rename}, @@ -34,6 +34,9 @@ impl CacheStorage for Filesystem { Ok(()) } fn read(&self, key: &str) -> Result<Option<Vec<u8>>> { + if key.contains("..") || key.starts_with("/") { + bail!("invalid key") + } match File::open(self.0.join(key)) { Ok(mut f) => { let mut data = Vec::new(); diff --git a/cache/src/helper.rs b/cache/src/helper.rs index 8f73e1e..46ef661 100644 --- a/cache/src/helper.rs +++ b/cache/src/helper.rs @@ -31,16 +31,22 @@ impl<T: Hash> Display for HashKey<T> { } } +const SAFE_CHARS: percent_encoding::AsciiSet = percent_encoding::CONTROLS + .add(b'.') + .add(b'%') + .add(b'/') + .add(b'#') + .add(b'?') + .add(b'@'); + pub struct EscapeKey<T>(pub T); impl<T: Display> Display for EscapeKey<T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - percent_encoding::utf8_percent_encode( - &self.0.to_string(), - percent_encoding::NON_ALPHANUMERIC, - ) + // TODO perf + f.write_str( + &percent_encoding::utf8_percent_encode(&self.0.to_string(), &SAFE_CHARS) + .to_string() + .replace("%", "@"), ) } } diff --git a/import/src/tmdb.rs b/import/src/tmdb.rs index 219c1f6..3d6e832 100644 --- a/import/src/tmdb.rs +++ b/import/src/tmdb.rs @@ -5,7 +5,7 @@ */ use crate::USER_AGENT; use anyhow::{anyhow, bail, Context, Result}; -use jellycache::{cache_memory, cache_store, HashKey}; +use jellycache::{cache_memory, cache_store, EscapeKey, HashKey}; use jellycommon::{ chrono::{format::Parsed, Utc}, Asset, @@ -108,20 +108,23 @@ impl Tmdb { .context("tmdb person images") } pub fn image(&self, path: &str, rt: &Handle) -> Result<Asset> { - cache_store(format!("ext/tmdb/image/{path}.json"), move || { - rt.block_on(async { - info!("downloading image {path:?}"); - Ok(self - .image_client - .get(format!("https://image.tmdb.org/t/p/original{path}")) - .send() - .await? - .error_for_status()? - .bytes() - .await? - .to_vec()) - }) - }) + cache_store( + format!("ext/tmdb/image/{}.image", EscapeKey(path)), + move || { + rt.block_on(async { + info!("downloading image {path:?}"); + Ok(self + .image_client + .get(format!("https://image.tmdb.org/t/p/original{path}")) + .send() + .await? + .error_for_status()? + .bytes() + .await? + .to_vec()) + }) + }, + ) .context("tmdb image download") .map(Asset) } diff --git a/import/src/trakt.rs b/import/src/trakt.rs index a241725..270c589 100644 --- a/import/src/trakt.rs +++ b/import/src/trakt.rs @@ -101,7 +101,7 @@ impl Trakt { } pub fn show_seasons(&self, id: u64, rt: &Handle) -> Result<Arc<Vec<TraktSeason>>> { - cache_memory(&format!("ext/trakt/seasons/{id}"), move || { + cache_memory(&format!("ext/trakt/seasons/{id}.json"), move || { rt.block_on(async { info!("trakt seasons {id:?}"); let url = format!("https://api.trakt.tv/shows/{id}/seasons?extended=full"); |