aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cache/src/backends/filesystem.rs5
-rw-r--r--cache/src/helper.rs20
-rw-r--r--import/src/tmdb.rs33
-rw-r--r--import/src/trakt.rs2
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");