aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-29 14:45:25 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-29 14:45:25 +0100
commitde8d69d2886ae50e28da210fc690c99457a804bb (patch)
treeb9d4fca9acd7d5fb844f4c76c8c338770d943df7
parent0d9dc5672b0ba0c6c9988b0422837ceb00a5d7b8 (diff)
downloadjellything-de8d69d2886ae50e28da210fc690c99457a804bb.tar
jellything-de8d69d2886ae50e28da210fc690c99457a804bb.tar.bz2
jellything-de8d69d2886ae50e28da210fc690c99457a804bb.tar.zst
more seeking code + expire cookies
-rw-r--r--Cargo.lock177
-rw-r--r--matroska/src/write.rs8
-rw-r--r--remuxer/src/import/mod.rs3
-rw-r--r--remuxer/src/lib.rs26
-rw-r--r--remuxer/src/segment_extractor.rs24
-rw-r--r--remuxer/src/trim_writer.rs18
-rw-r--r--server/Cargo.toml3
-rw-r--r--server/src/config.rs4
-rw-r--r--server/src/routes/mod.rs4
-rw-r--r--server/src/routes/ui/account/mod.rs11
-rw-r--r--server/src/routes/ui/account/session.rs32
-rw-r--r--server/src/routes/ui/error.rs5
-rw-r--r--server/src/routes/ui/home.rs2
-rw-r--r--server/src/routes/ui/player.rs6
14 files changed, 269 insertions, 54 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8422aa7..2e814aa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -47,6 +47,15 @@ dependencies = [
]
[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "anyhow"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -354,6 +363,22 @@ dependencies = [
]
[[package]]
+name = "chrono"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-integer",
+ "num-traits",
+ "serde",
+ "time 0.1.45",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
name = "cipher"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -401,6 +426,16 @@ dependencies = [
]
[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
+[[package]]
name = "concurrent-queue"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -423,11 +458,17 @@ dependencies = [
"rand 0.8.5",
"sha2",
"subtle",
- "time",
+ "time 0.3.17",
"version_check",
]
[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
+[[package]]
name = "cpufeatures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -498,6 +539,50 @@ dependencies = [
]
[[package]]
+name = "cxx"
+version = "1.0.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "devise"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -769,7 +854,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
@@ -932,6 +1017,30 @@ dependencies = [
]
[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1033,6 +1142,7 @@ dependencies = [
"argon2",
"async-std",
"chashmap",
+ "chrono",
"env_logger",
"jellycommon",
"jellyremuxer",
@@ -1094,6 +1204,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1199,7 +1318,7 @@ checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
@@ -1234,6 +1353,25 @@ dependencies = [
]
[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1671,7 +1809,7 @@ dependencies = [
"serde",
"state",
"tempfile",
- "time",
+ "time 0.3.17",
"tokio",
"tokio-stream",
"tokio-util",
@@ -1718,7 +1856,7 @@ dependencies = [
"smallvec 1.10.0",
"stable-pattern",
"state",
- "time",
+ "time 0.3.17",
"tokio",
"uncased",
]
@@ -1762,6 +1900,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
+name = "scratch"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
+
+[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1978,6 +2122,17 @@ dependencies = [
[[package]]
name = "time"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+dependencies = [
+ "libc",
+ "wasi 0.10.0+wasi-snapshot-preview1",
+ "winapi",
+]
+
+[[package]]
+name = "time"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
@@ -2186,6 +2341,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2247,6 +2408,12 @@ dependencies = [
[[package]]
name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
diff --git a/matroska/src/write.rs b/matroska/src/write.rs
index 2555380..8fc17c3 100644
--- a/matroska/src/write.rs
+++ b/matroska/src/write.rs
@@ -76,7 +76,13 @@ impl<W: Write> EbmlWriter<W> {
impl<W: Seek> Seek for EbmlWriter<W> {
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
- self.inner.seek(pos)
+ self.inner.seek(pos)?;
+ match pos {
+ std::io::SeekFrom::Start(s) => self.position = s as usize,
+ std::io::SeekFrom::End(_) => unimplemented!(),
+ std::io::SeekFrom::Current(s) => self.position += s as usize,
+ }
+ Ok(self.position as u64)
}
}
diff --git a/remuxer/src/import/mod.rs b/remuxer/src/import/mod.rs
index 01b211b..49a9aa5 100644
--- a/remuxer/src/import/mod.rs
+++ b/remuxer/src/import/mod.rs
@@ -210,12 +210,13 @@ fn import_read_segment(
"simple block: track={} tso={}",
block.track, block.timestamp_off
);
+ debug!("{pts} {}", block.timestamp_off);
seek_index
.entry(block.track)
.or_insert(SeekIndex { blocks: vec![] })
.blocks
.push(BlockIndex {
- pts: pts + block.timestamp_off as u64,
+ pts: (pts as i64 + block.timestamp_off as i64) as u64,
source_off: position,
size: block.data.len(),
});
diff --git a/remuxer/src/lib.rs b/remuxer/src/lib.rs
index 03d469e..0034cf8 100644
--- a/remuxer/src/lib.rs
+++ b/remuxer/src/lib.rs
@@ -7,16 +7,12 @@ pub mod import;
pub mod segment_extractor;
pub mod trim_writer;
-use crate::{
- segment_extractor::{AbsoluteBlock, SegmentExtractIter},
- trim_writer::TrimWriter,
-};
+use crate::{segment_extractor::SegmentExtractIter, trim_writer::TrimWriter};
use anyhow::{anyhow, Context};
use jellycommon::{BlockIndex, ItemInfo, SeekIndex, SourceTrack, SourceTrackKind};
use jellymatroska::{
block::Block,
read::EbmlReader,
- unflatten::Unflatten,
write::{vint_length, EbmlWriter},
Master, MatroskaTag,
};
@@ -188,10 +184,11 @@ impl RemuxerContext {
break;
}
p += 1; // simpleblock tag
- p += vint_length(1 + 2 + 1 + best_block.size as u64); // simpleblock size vint
- p += 1 + 2 + 1; // block {tracknum, pts_off, flags}
- // TODO does not work, if more than 127 tracks are present
- p += best_block.size; // block payload
+ let simpleblock_size = 1 + 2 + 1 // block {tracknum, pts_off, flags}
+ // TODO does not work, if more than 127 tracks are present
+ + best_block.size; // block payload
+ p += vint_length(simpleblock_size as u64); // simpleblock size vint
+ p += simpleblock_size;
cluster.push((best_index, best_block))
}
info!("segment layout computed ({} clusters)", clusters.len());
@@ -225,11 +222,12 @@ impl RemuxerContext {
let segment_start_position = output.position();
let mut skip = 0;
- for cluster in &segment_layout {
- if (cluster.position + segment_start_position) > range.start {
+ for (i, cluster) in segment_layout.iter().enumerate() {
+ if (cluster.position + segment_start_position) < range.start {
+ skip += i;
+ } else {
break;
}
- skip += 1;
}
if skip != 0 {
info!("skipping {skip} clusters");
@@ -237,7 +235,6 @@ impl RemuxerContext {
}
struct ReaderD<'a> {
- _info: SourceTrack,
peek: Option<Block>,
stream: SegmentExtractIter<'a>,
mapped: u64,
@@ -258,7 +255,6 @@ impl RemuxerContext {
mapped: inp.mapped,
peek: Some(stream.next()?),
stream,
- _info: inp.info.clone(),
});
}
info!(
@@ -266,7 +262,7 @@ impl RemuxerContext {
(Instant::now() - timing_cp).as_millis()
);
- for (cluster_index, cluster) in segment_layout.into_iter().skip(skip).enumerate() {
+ for (cluster_index, cluster) in segment_layout.into_iter().enumerate().skip(skip) {
info!(
"writing cluster {cluster_index} (pts_base={}) with {} blocks",
cluster.timestamp,
diff --git a/remuxer/src/segment_extractor.rs b/remuxer/src/segment_extractor.rs
index 095bdfe..c44a511 100644
--- a/remuxer/src/segment_extractor.rs
+++ b/remuxer/src/segment_extractor.rs
@@ -1,24 +1,22 @@
-use anyhow::{anyhow, Result};
+use anyhow::{anyhow, bail, Result};
use jellymatroska::{block::Block, read::EbmlReader, unflatten::IterWithPos, MatroskaTag};
use log::{debug, trace};
-use std::collections::VecDeque;
-pub struct AbsoluteBlock {
- pub pts_base: u64,
- pub inner: Block,
-}
+// pub struct AbsoluteBlock {
+// pub pts_base: u64,
+// pub inner: Block,
+// }
+// impl AbsoluteBlock {
+// pub fn pts(&self) -> u64 {
+// self.inner.timestamp_off as u64 + self.pts_base
+// }
+// }
pub struct SegmentExtractIter<'a> {
segment: &'a mut EbmlReader,
extract: u64,
}
-impl AbsoluteBlock {
- pub fn pts(&self) -> u64 {
- self.inner.timestamp_off as u64 + self.pts_base
- }
-}
-
impl<'a> SegmentExtractIter<'a> {
pub fn new(segment: &'a mut EbmlReader, extract: u64) -> Self {
Self { segment, extract }
@@ -31,6 +29,7 @@ impl<'a> SegmentExtractIter<'a> {
MatroskaTag::Void(_) => (),
MatroskaTag::Crc32(_) => (),
MatroskaTag::Cluster(_) => (),
+ MatroskaTag::Timestamp(_) => (),
MatroskaTag::SimpleBlock(buf) | MatroskaTag::Block(buf) => {
let block = Block::parse(&buf)?;
if block.track == self.extract {
@@ -38,6 +37,7 @@ impl<'a> SegmentExtractIter<'a> {
return Ok(block);
}
}
+ MatroskaTag::Cues(_) => bail!("reached cues, this is the end"),
_ => debug!("(rs) tag ignored: {item:?}"),
}
}
diff --git a/remuxer/src/trim_writer.rs b/remuxer/src/trim_writer.rs
index 65d3589..bed90e7 100644
--- a/remuxer/src/trim_writer.rs
+++ b/remuxer/src/trim_writer.rs
@@ -4,7 +4,7 @@ use std::{
};
use anyhow::anyhow;
-use log::warn;
+use log::{trace, warn};
pub struct TrimWriter<W> {
inner: W,
@@ -36,12 +36,16 @@ impl<W: Write> Write for TrimWriter<W> {
));
}
- let buf = &buf[start..end];
- if !buf.is_empty() {
- self.inner.write_all(buf)?;
- self.position += buf.len()
- }
- Ok(buf.len())
+ let tbuf = &buf[start..end];
+ Ok(if !tbuf.is_empty() {
+ trace!("trim={start}..{end} avail={}", buf.len());
+ let sz = self.inner.write(tbuf)?;
+ self.position += sz;
+ sz
+ } else {
+ trace!("skip={}", buf.len());
+ buf.len()
+ })
}
fn flush(&mut self) -> std::io::Result<()> {
diff --git a/server/Cargo.toml b/server/Cargo.toml
index a3214fa..954161f 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -17,6 +17,7 @@ once_cell = "1.17.0"
chashmap = "2.2.2"
argon2 = "0.4.1"
rand = "0.8.5"
+chrono = { version = "0.4.23", features = ["serde"] }
async-std = "1.12.0"
rocket = { version = "0.5.0-rc.2", features = ["secrets"] }
@@ -28,4 +29,4 @@ sled = "0.34.7"
typed-sled = "0.2.3"
[features]
-bypass-auth = [] \ No newline at end of file
+bypass-auth = []
diff --git a/server/src/config.rs b/server/src/config.rs
index 4b61960..0de7e90 100644
--- a/server/src/config.rs
+++ b/server/src/config.rs
@@ -10,13 +10,15 @@ use std::{fs::File, path::PathBuf};
pub struct GlobalConfig {
pub brand: String,
pub slogan: String,
- pub asset_dir: PathBuf,
+ pub asset_path: PathBuf,
pub database_path: PathBuf,
pub library_path: PathBuf,
+
pub admin_username: String,
pub admin_password: String,
pub cookie_key: String,
+ pub login_expire: i64,
}
pub fn load_global_config() -> GlobalConfig {
diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs
index d1bf7fc..c567d94 100644
--- a/server/src/routes/mod.rs
+++ b/server/src/routes/mod.rs
@@ -48,7 +48,7 @@ pub fn build_rocket(
Box::pin(async {})
}))
.register("/", catchers![r_catch])
- .mount("/assets", FileServer::from(&CONF.asset_dir))
+ .mount("/assets", FileServer::from(&CONF.asset_path))
.mount(
"/",
routes![
@@ -77,5 +77,5 @@ pub fn build_rocket(
#[get("/favicon.ico")]
fn r_favicon() -> MyResult<File> {
- Ok(File::open(CONF.asset_dir.join("favicon.ico"))?)
+ Ok(File::open(CONF.asset_path.join("favicon.ico"))?)
}
diff --git a/server/src/routes/ui/account/mod.rs b/server/src/routes/ui/account/mod.rs
index e7031ff..63c01c5 100644
--- a/server/src/routes/ui/account/mod.rs
+++ b/server/src/routes/ui/account/mod.rs
@@ -6,6 +6,8 @@
pub mod admin;
pub mod session;
+use self::session::SessionCookie;
+
use super::{error::MyError, layout::LayoutPage};
use crate::{
database::{Database, User},
@@ -157,7 +159,14 @@ pub fn r_account_login_post(
Err(anyhow!("invalid password"))?
}
- jar.add_private(Cookie::build("user", user.name).permanent().finish());
+ jar.add_private(
+ Cookie::build(
+ "user",
+ serde_json::to_string(&SessionCookie::new(user.name)).unwrap(),
+ )
+ .permanent()
+ .finish(),
+ );
Ok(Redirect::found(uri!(r_home())))
}
diff --git a/server/src/routes/ui/account/session.rs b/server/src/routes/ui/account/session.rs
index 6059311..6795c06 100644
--- a/server/src/routes/ui/account/session.rs
+++ b/server/src/routes/ui/account/session.rs
@@ -5,19 +5,36 @@
*/
use crate::{
database::{Database, User},
- routes::ui::error::MyError,
+ routes::ui::error::MyError, CONF,
};
use anyhow::anyhow;
+use chrono::{DateTime, Duration, Utc};
use rocket::{
outcome::Outcome,
request::{self, FromRequest},
Request, State,
};
+use serde::{Deserialize, Serialize};
pub struct Session {
pub user: User,
}
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct SessionCookie {
+ name: String,
+ expire: DateTime<Utc>,
+}
+
+impl SessionCookie {
+ pub fn new(name: String) -> Self {
+ Self {
+ name,
+ expire: Utc::now() + Duration::days(CONF.login_expire),
+ }
+ }
+}
+
impl Session {
pub async fn from_request_ut(req: &Request<'_>) -> Result<Self, MyError> {
#[cfg(not(feature = "bypass-auth"))]
@@ -26,14 +43,21 @@ impl Session {
.get_private("user")
.ok_or(anyhow!("login required"))?;
#[cfg(not(feature = "bypass-auth"))]
- let username = cookie.value();
+ let cookie = serde_json::from_str::<SessionCookie>(cookie.value())?;
#[cfg(feature = "bypass-auth")]
- let username = crate::CONF.admin_username.to_string();
+ let cookie = SessionCookie {
+ name: crate::CONF.admin_username.to_string(),
+ expire: Utc::now() + Duration::days(CONF.login_expire),
+ };
+
+ if cookie.expire < Utc::now() {
+ Err(anyhow!("cookie expired"))?;
+ }
let db = req.guard::<&State<Database>>().await.unwrap();
let user = db
.users
- .get(&username.to_string())?
+ .get(&cookie.name.to_string())?
.ok_or(anyhow!("user not found"))?;
Ok(Session { user })
diff --git a/server/src/routes/ui/error.rs b/server/src/routes/ui/error.rs
index 59e322a..7913e1a 100644
--- a/server/src/routes/ui/error.rs
+++ b/server/src/routes/ui/error.rs
@@ -70,3 +70,8 @@ impl From<sled::Error> for MyError {
MyError(anyhow::anyhow!("{err}"))
}
}
+impl From<serde_json::Error> for MyError {
+ fn from(err: serde_json::Error) -> Self {
+ MyError(anyhow::anyhow!("{err}"))
+ }
+}
diff --git a/server/src/routes/ui/home.rs b/server/src/routes/ui/home.rs
index a8d9c65..f81e04f 100644
--- a/server/src/routes/ui/home.rs
+++ b/server/src/routes/ui/home.rs
@@ -25,7 +25,7 @@ pub fn r_home(_sess: Session, library: &State<Library>) -> DynLayoutPage {
#[get("/", rank = 2)]
pub async fn r_home_unpriv() -> MyResult<DynLayoutPage<'static>> {
- let front = read_to_string(CONF.asset_dir.join("front.htm")).await?;
+ let front = read_to_string(CONF.asset_path.join("front.htm")).await?;
Ok(LayoutPage {
title: "Home".to_string(),
content: markup::new! {
diff --git a/server/src/routes/ui/player.rs b/server/src/routes/ui/player.rs
index 866787a..20b451f 100644
--- a/server/src/routes/ui/player.rs
+++ b/server/src/routes/ui/player.rs
@@ -95,11 +95,11 @@ pub fn player_conf<'a>(item: Arc<Item>) -> MyResult<DynLayoutPage<'a>> {
fieldset.subtitles {
legend { "Subtitles" }
- @for (i, (tid, track)) in sub_tracks.iter().enumerate() {
- input[type="radio", id=tid, name="s", value=tid, checked=i==0];
+ @for (_i, (tid, track)) in sub_tracks.iter().enumerate() {
+ input[type="radio", id=tid, name="s", value=tid];
label[for=tid] { @format!("{track}") } br;
}
- input[type="radio", id="s-none", name="s", value=""];
+ input[type="radio", id="s-none", name="s", value="", checked=true];
label[for="s-none"] { "No subtitles" }
}