server/lib: can now have custom-files which clients can access if they know the path.

This commit is contained in:
Mark 2023-10-26 16:35:58 +02:00
parent f61f52fdc7
commit 273eac4b43
3 changed files with 35 additions and 11 deletions

View File

@ -26,6 +26,12 @@ pub struct Database {
albums: HashMap<AlbumId, Album>,
songs: HashMap<SongId, Song>,
covers: HashMap<CoverId, Cover>,
/// clients can access files in this directory if they know the relative path.
/// can be used to embed custom images in tags of songs/albums/artists.
/// None -> no access
/// Some(None) -> access to lib_directory
/// Some(Some(path)) -> access to path
pub custom_files: Option<Option<PathBuf>>,
// These will be used for autosave once that gets implemented
db_data_file_change_first: Option<Instant>,
db_data_file_change_last: Option<Instant>,
@ -374,6 +380,7 @@ impl Database {
albums: HashMap::new(),
songs: HashMap::new(),
covers: HashMap::new(),
custom_files: None,
db_data_file_change_first: None,
db_data_file_change_last: None,
queue: QueueContent::Folder(0, vec![], String::new()).into(),
@ -392,6 +399,7 @@ impl Database {
albums: HashMap::new(),
songs: HashMap::new(),
covers: HashMap::new(),
custom_files: None,
db_data_file_change_first: None,
db_data_file_change_last: None,
queue: QueueContent::Folder(0, vec![], String::new()).into(),
@ -412,6 +420,7 @@ impl Database {
albums: ToFromBytes::from_bytes(&mut file)?,
songs: ToFromBytes::from_bytes(&mut file)?,
covers: ToFromBytes::from_bytes(&mut file)?,
custom_files: None,
db_data_file_change_first: None,
db_data_file_change_last: None,
queue: QueueContent::Folder(0, vec![], String::new()).into(),

View File

@ -1,6 +1,8 @@
use std::{
fs,
io::BufRead,
io::{BufReader, Read, Write},
path::Path,
sync::{Arc, Mutex},
};
@ -118,16 +120,24 @@ pub fn handle_one_connection_as_get(
writeln!(connection.get_mut(), "no data")?;
}
}
"song-file-blocking" => {
if let Some(bytes) =
request
.next()
.and_then(|id| id.parse().ok())
.and_then(|id| {
let db = db.lock().unwrap();
db.get_song(&id).and_then(|song| song.cached_data_now(&db))
})
{
"custom-file" => {
if let Some(bytes) = request.next().and_then(|path| {
let db = db.lock().unwrap();
let mut parent = match &db.custom_files {
None => None,
Some(None) => Some(db.lib_directory.clone()),
Some(Some(p)) => Some(p.clone()),
};
// check for malicious paths
if Path::new(path).is_absolute() {
parent = None;
}
if let Some(parent) = parent {
fs::read(parent.join(path)).ok()
} else {
None
}
}) {
writeln!(connection.get_mut(), "len: {}", bytes.len())?;
connection.get_mut().write_all(&bytes)?;
} else {

View File

@ -31,13 +31,17 @@ struct Args {
/// requires the `assets/` folder to be present!
#[arg(long)]
web: Option<SocketAddr>,
/// allow clients to access files in this directory, or the lib_dir if not specified.
#[arg(long)]
custom_files: Option<Option<PathBuf>>,
}
#[tokio::main]
async fn main() {
// parse args
let args = Args::parse();
let database = if args.init {
let mut database = if args.init {
Database::new_empty(args.dbfile, args.lib_dir)
} else {
match Database::load_database(args.dbfile.clone(), args.lib_dir.clone()) {
@ -51,6 +55,7 @@ async fn main() {
}
}
};
database.custom_files = args.custom_files;
// database can be shared by multiple threads using Arc<Mutex<_>>
let database = Arc::new(Mutex::new(database));
if args.tcp.is_some() || args.web.is_some() {