Update dependencies (#166)

This commit is contained in:
Tobias Schmitz 2022-03-21 03:50:14 +01:00 committed by GitHub
parent 39c8cf7595
commit 90fd6bbcc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 490 additions and 408 deletions

721
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -11,61 +11,60 @@ bundle-sqlite = ["libsqlite3-sys"]
ui = ["native-windows-gui", "native-windows-derive"] ui = ["native-windows-gui", "native-windows-derive"]
[dependencies] [dependencies]
actix-files = { version = "0.4" } actix-files = { version = "0.5" }
actix-web = { version = "3" } actix-web = { version = "3" }
actix-web-httpauth = { version = "0.5.0" } actix-web-httpauth = { version = "0.5.1" }
anyhow = "1.0.35" anyhow = "1.0.52"
ape = "0.3.0" ape = "0.4.0"
base64 = "0.13" base64 = "0.13"
branca = "0.10.0" branca = "0.10.0"
cookie = { version = "0.14", features = ["signed", "key-expansion"] } cookie = { version = "0.14", features = ["signed", "key-expansion"] }
crossbeam-channel = "0.5" crossbeam-channel = "0.5"
diesel_migrations = { version = "1.4", features = ["sqlite"] } diesel_migrations = { version = "1.4", features = ["sqlite"] }
futures-util = { version = "0.3" } futures-util = { version = "0.3" }
getopts = "0.2.15" getopts = "0.2.21"
http = "0.2.2" http = "0.2.6"
id3 = "0.6.6" id3 = "1.0.2"
libsqlite3-sys = { version = "0.18", features = ["bundled", "bundled-windows"], optional = true } libsqlite3-sys = { version = "0.22", features = ["bundled", "bundled-windows"], optional = true }
lewton = "0.10.1" lewton = "0.10.2"
log = "0.4.5" log = "0.4.14"
metaflac = "0.2.3" metaflac = "0.2.5"
mp3-duration = "0.1.9" mp3-duration = "0.1.10"
mp4ameta = "0.10.0" mp4ameta = "0.11.0"
num_cpus = "1.13.0" num_cpus = "1.13.1"
opus_headers = "0.1.2" opus_headers = "0.1.2"
percent-encoding = "2.1" percent-encoding = "2.1"
pbkdf2 = "0.6" pbkdf2 = "0.10"
rand = "0.7" rand = "0.8"
rayon = "1.3" rayon = "1.5"
regex = "1.3.9" regex = "1.5.4"
rustfm-scrobble = "1.1.1" rustfm-scrobble = "1.1.1"
serde = { version = "1.0.111", features = ["derive"] } serde = { version = "1.0.133", features = ["derive"] }
serde_derive = "1.0.111" serde_derive = "1.0.133"
serde_json = "1.0.53" serde_json = "1.0.74"
simplelog = "0.8.0" simplelog = "0.11.1"
thiserror = "1.0.19" thiserror = "1.0.30"
time = "0.2"
toml = "0.5" toml = "0.5"
ureq = "1.5" ureq = "1.5.5"
url = "2.1" url = "2.2"
[dependencies.diesel] [dependencies.diesel]
version = "1.4.5" version = "1.4.8"
default_features = false default_features = false
features = ["libsqlite3-sys", "r2d2", "sqlite", "64-column-tables"] features = ["libsqlite3-sys", "r2d2", "sqlite", "64-column-tables"]
[dependencies.image] [dependencies.image]
version = "0.23.12" version = "0.23.14"
default_features = false default_features = false
features = ["bmp", "gif", "jpeg", "png"] features = ["bmp", "gif", "jpeg", "png"]
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
native-windows-gui = {version = "1.0.7", default-features = false, features = ["cursor", "image-decoder", "message-window", "menu", "tray-notification"], optional = true } native-windows-gui = {version = "1.0.12", default-features = false, features = ["cursor", "image-decoder", "message-window", "menu", "tray-notification"], optional = true }
native-windows-derive = {version = "1.0.2", optional = true } native-windows-derive = {version = "1.0.4", optional = true }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
daemonize = "0.4.1" daemonize = "0.4.1"
sd-notify = "0.1.0" sd-notify = "0.3.0"
[target.'cfg(windows)'.build-dependencies] [target.'cfg(windows)'.build-dependencies]
winres = "0.1" winres = "0.1"

View file

@ -1,4 +1,5 @@
use anyhow::*; use anyhow::{anyhow, Result};
use id3::TagLike;
use lewton::inside_ogg::OggStreamReader; use lewton::inside_ogg::OggStreamReader;
use log::error; use log::error;
use regex::Regex; use regex::Regex;
@ -65,24 +66,23 @@ impl From<id3::Tag> for SongTags {
pub fn read(path: &Path) -> Option<SongTags> { pub fn read(path: &Path) -> Option<SongTags> {
let data = match utils::get_audio_format(path) { let data = match utils::get_audio_format(path) {
Some(AudioFormat::AIFF) => Some(read_aiff(path)), Some(AudioFormat::AIFF) => read_aiff(path),
Some(AudioFormat::APE) => Some(read_ape(path)), Some(AudioFormat::APE) => read_ape(path),
Some(AudioFormat::FLAC) => Some(read_flac(path)), Some(AudioFormat::FLAC) => read_flac(path),
Some(AudioFormat::MP3) => Some(read_mp3(path)), Some(AudioFormat::MP3) => read_mp3(path),
Some(AudioFormat::MP4) => Some(read_mp4(path)), Some(AudioFormat::MP4) => read_mp4(path),
Some(AudioFormat::MPC) => Some(read_ape(path)), Some(AudioFormat::MPC) => read_ape(path),
Some(AudioFormat::OGG) => Some(read_vorbis(path)), Some(AudioFormat::OGG) => read_vorbis(path),
Some(AudioFormat::OPUS) => Some(read_opus(path)), Some(AudioFormat::OPUS) => read_opus(path),
Some(AudioFormat::WAVE) => Some(read_wave(path)), Some(AudioFormat::WAVE) => read_wave(path),
None => None, None => return None,
}; };
match data { match data {
Some(Ok(d)) => Some(d), Ok(d) => Some(d),
Some(Err(e)) => { Err(e) => {
error!("Error while reading file metadata for '{:?}': {}", path, e); error!("Error while reading file metadata for '{:?}': {}", path, e);
None None
} }
None => None,
} }
} }
@ -123,7 +123,7 @@ fn read_mp3(path: &Path) -> Result<SongTags> {
} }
fn read_aiff(path: &Path) -> Result<SongTags> { fn read_aiff(path: &Path) -> Result<SongTags> {
let tag = id3::Tag::read_from_aiff(&path).or_else(|error| { let tag = id3::Tag::read_from_aiff_path(&path).or_else(|error| {
if let Some(tag) = error.partial_tag { if let Some(tag) = error.partial_tag {
Ok(tag) Ok(tag)
} else { } else {
@ -134,7 +134,7 @@ fn read_aiff(path: &Path) -> Result<SongTags> {
} }
fn read_wave(path: &Path) -> Result<SongTags> { fn read_wave(path: &Path) -> Result<SongTags> {
let tag = id3::Tag::read_from_wav(&path).or_else(|error| { let tag = id3::Tag::read_from_wav_path(&path).or_else(|error| {
if let Some(tag) = error.partial_tag { if let Some(tag) = error.partial_tag {
Ok(tag) Ok(tag)
} else { } else {
@ -173,7 +173,7 @@ fn read_ape_x_of_y(item: &ape::Item) -> Option<u32> {
} }
fn read_ape(path: &Path) -> Result<SongTags> { fn read_ape(path: &Path) -> Result<SongTags> {
let tag = ape::read(path)?; let tag = ape::read_from_path(path)?;
let artist = tag.item("Artist").and_then(read_ape_string); let artist = tag.item("Artist").and_then(read_ape_string);
let album = tag.item("Album").and_then(read_ape_string); let album = tag.item("Album").and_then(read_ape_string);
let album_artist = tag.item("Album artist").and_then(read_ape_string); let album_artist = tag.item("Album artist").and_then(read_ape_string);
@ -338,7 +338,7 @@ fn read_mp4(path: &Path) -> Result<SongTags> {
lyricist: tag.take_lyricist(), lyricist: tag.take_lyricist(),
composer: tag.take_composer(), composer: tag.take_composer(),
genre: tag.take_genre(), genre: tag.take_genre(),
label: tag.take_string(&label_ident).next(), label: tag.take_strings_of(&label_ident).next(),
}) })
} }

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::bail;
use diesel::dsl::sql; use diesel::dsl::sql;
use diesel::prelude::*; use diesel::prelude::*;
use diesel::sql_types; use diesel::sql_types;
@ -108,7 +108,7 @@ impl Index {
Ok(virtual_songs.collect::<Vec<_>>()) Ok(virtual_songs.collect::<Vec<_>>())
} }
pub fn get_random_albums(&self, count: i64) -> Result<Vec<Directory>> { pub fn get_random_albums(&self, count: i64) -> anyhow::Result<Vec<Directory>> {
use self::directories::dsl::*; use self::directories::dsl::*;
let vfs = self.vfs_manager.get_vfs()?; let vfs = self.vfs_manager.get_vfs()?;
let connection = self.db.connect()?; let connection = self.db.connect()?;
@ -123,7 +123,7 @@ impl Index {
Ok(virtual_directories.collect::<Vec<_>>()) Ok(virtual_directories.collect::<Vec<_>>())
} }
pub fn get_recent_albums(&self, count: i64) -> Result<Vec<Directory>> { pub fn get_recent_albums(&self, count: i64) -> anyhow::Result<Vec<Directory>> {
use self::directories::dsl::*; use self::directories::dsl::*;
let vfs = self.vfs_manager.get_vfs()?; let vfs = self.vfs_manager.get_vfs()?;
let connection = self.db.connect()?; let connection = self.db.connect()?;
@ -138,7 +138,7 @@ impl Index {
Ok(virtual_directories.collect::<Vec<_>>()) Ok(virtual_directories.collect::<Vec<_>>())
} }
pub fn search(&self, query: &str) -> Result<Vec<CollectionFile>> { pub fn search(&self, query: &str) -> anyhow::Result<Vec<CollectionFile>> {
let vfs = self.vfs_manager.get_vfs()?; let vfs = self.vfs_manager.get_vfs()?;
let connection = self.db.connect()?; let connection = self.db.connect()?;
let like_test = format!("%{}%", query); let like_test = format!("%{}%", query);
@ -181,7 +181,7 @@ impl Index {
Ok(output) Ok(output)
} }
pub fn get_song(&self, virtual_path: &Path) -> Result<Song> { pub fn get_song(&self, virtual_path: &Path) -> anyhow::Result<Song> {
let vfs = self.vfs_manager.get_vfs()?; let vfs = self.vfs_manager.get_vfs()?;
let connection = self.db.connect()?; let connection = self.db.connect()?;

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::Error;
use crossbeam_channel::Receiver; use crossbeam_channel::Receiver;
use diesel::prelude::*; use diesel::prelude::*;
use log::error; use log::error;

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::Result;
use log::{error, info}; use log::{error, info};
use std::time; use std::time;

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::{bail, Result};
use image::DynamicImage; use image::DynamicImage;
use std::path::Path; use std::path::Path;
@ -21,9 +21,7 @@ pub fn read(image_path: &Path) -> Result<DynamicImage> {
} }
fn read_ape(_: &Path) -> Result<DynamicImage> { fn read_ape(_: &Path) -> Result<DynamicImage> {
Err(crate::Error::msg( bail!("Embedded images are not supported in APE files");
"Embedded images are not supported in APE files",
))
} }
fn read_flac(path: &Path) -> Result<DynamicImage> { fn read_flac(path: &Path) -> Result<DynamicImage> {
@ -33,10 +31,10 @@ fn read_flac(path: &Path) -> Result<DynamicImage> {
return Ok(image::load_from_memory(&p.data)?); return Ok(image::load_from_memory(&p.data)?);
} }
Err(crate::Error::msg(format!( bail!(
"Embedded flac artwork not found for file: {}", "Embedded flac artwork not found for file: {}",
path.display() path.display()
))) );
} }
fn read_mp3(path: &Path) -> Result<DynamicImage> { fn read_mp3(path: &Path) -> Result<DynamicImage> {
@ -46,13 +44,13 @@ fn read_mp3(path: &Path) -> Result<DynamicImage> {
} }
fn read_aiff(path: &Path) -> Result<DynamicImage> { fn read_aiff(path: &Path) -> Result<DynamicImage> {
let tag = id3::Tag::read_from_aiff(path)?; let tag = id3::Tag::read_from_aiff_path(path)?;
read_id3(&path, &tag) read_id3(&path, &tag)
} }
fn read_wave(path: &Path) -> Result<DynamicImage> { fn read_wave(path: &Path) -> Result<DynamicImage> {
let tag = id3::Tag::read_from_wav(path)?; let tag = id3::Tag::read_from_wav_path(path)?;
read_id3(&path, &tag) read_id3(&path, &tag)
} }
@ -62,34 +60,30 @@ fn read_id3(path: &Path, tag: &id3::Tag) -> Result<DynamicImage> {
return Ok(image::load_from_memory(&p.data)?); return Ok(image::load_from_memory(&p.data)?);
} }
Err(crate::Error::msg(format!( bail!(
"Embedded id3 artwork not found for file: {}", "Embedded id3 artwork not found for file: {}",
path.display() path.display()
))) );
} }
fn read_mp4(path: &Path) -> Result<DynamicImage> { fn read_mp4(path: &Path) -> Result<DynamicImage> {
let tag = mp4ameta::Tag::read_from_path(path)?; let tag = mp4ameta::Tag::read_from_path(path)?;
match tag.artwork().and_then(|d| d.image_data()) { match tag.artwork().map(|d| d.data) {
Some(v) => Ok(image::load_from_memory(v)?), Some(v) => Ok(image::load_from_memory(v)?),
_ => Err(crate::Error::msg(format!( _ => bail!(
"Embedded mp4 artwork not found for file: {}", "Embedded mp4 artwork not found for file: {}",
path.display() path.display()
))), ),
} }
} }
fn read_vorbis(_: &Path) -> Result<DynamicImage> { fn read_vorbis(_: &Path) -> Result<DynamicImage> {
Err(crate::Error::msg( bail!("Embedded images are not supported in Vorbis files");
"Embedded images are not supported in Vorbis files",
))
} }
fn read_opus(_: &Path) -> Result<DynamicImage> { fn read_opus(_: &Path) -> Result<DynamicImage> {
Err(crate::Error::msg( bail!("Embedded images are not supported in Opus files");
"Embedded images are not supported in Opus files",
))
} }
#[test] #[test]

View file

@ -1,13 +1,14 @@
use anyhow::anyhow; use anyhow::anyhow;
use diesel::prelude::*; use diesel::prelude::*;
use pbkdf2::password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString};
use pbkdf2::Pbkdf2;
use rand::rngs::OsRng;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use super::*; use super::*;
use crate::app::settings::AuthSecret; use crate::app::settings::AuthSecret;
use crate::db::DB; use crate::db::DB;
const HASH_ITERATIONS: u32 = 10000;
#[derive(Clone)] #[derive(Clone)]
pub struct Manager { pub struct Manager {
// TODO make this private and move preferences methods in this file // TODO make this private and move preferences methods in this file
@ -238,9 +239,18 @@ fn hash_password(password: &str) -> Result<String, Error> {
if password.is_empty() { if password.is_empty() {
return Err(Error::EmptyPassword); return Err(Error::EmptyPassword);
} }
pbkdf2::pbkdf2_simple(password, HASH_ITERATIONS).map_err(|_| Error::Unspecified) let salt = SaltString::generate(&mut OsRng);
match Pbkdf2.hash_password(password.as_bytes(), &salt) {
Ok(h) => Ok(h.to_string()),
Err(_) => Err(Error::Unspecified),
}
} }
fn verify_password(password_hash: &str, attempted_password: &str) -> bool { fn verify_password(password_hash: &str, attempted_password: &str) -> bool {
pbkdf2::pbkdf2_check(attempted_password, password_hash).is_ok() match PasswordHash::new(password_hash) {
Ok(h) => Pbkdf2
.verify_password(attempted_password.as_bytes(), &h)
.is_ok(),
Err(_) => false,
}
} }

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::{bail, Result};
use core::ops::Deref; use core::ops::Deref;
use regex::Regex; use regex::Regex;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,4 +1,4 @@
use anyhow::*; use anyhow::{bail, Error, Result};
use diesel::r2d2::{self, ConnectionManager, PooledConnection}; use diesel::r2d2::{self, ConnectionManager, PooledConnection};
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnection;
use diesel::RunQueryDsl; use diesel::RunQueryDsl;

View file

@ -6,9 +6,11 @@ extern crate diesel;
#[macro_use] #[macro_use]
extern crate diesel_migrations; extern crate diesel_migrations;
use anyhow::*; use anyhow::Result;
use log::info; use log::info;
use simplelog::{CombinedLogger, LevelFilter, SharedLogger, TermLogger, TerminalMode, WriteLogger}; use simplelog::{
ColorChoice, CombinedLogger, LevelFilter, SharedLogger, TermLogger, TerminalMode, WriteLogger,
};
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
@ -54,6 +56,7 @@ fn init_logging<T: AsRef<Path>>(log_level: LevelFilter, log_file_path: &Option<T
log_level, log_level,
log_config.clone(), log_config.clone(),
TerminalMode::Mixed, TerminalMode::Mixed,
ColorChoice::Auto,
)]; )];
if let Some(path) = log_file_path { if let Some(path) = log_file_path {

View file

@ -1,14 +1,15 @@
use std::time::Duration;
use cookie::Cookie; use cookie::Cookie;
use headers::{self, HeaderMapExt}; use headers::{self, HeaderMapExt};
use http::{Response, StatusCode}; use http::{Response, StatusCode};
use time::Duration;
use crate::service::dto; use crate::service::dto;
use crate::service::test::{constants::*, protocol, ServiceType, TestService}; use crate::service::test::{constants::*, protocol, ServiceType, TestService};
use crate::test_name; use crate::test_name;
fn validate_added_cookies<T>(response: &Response<T>) { fn validate_added_cookies<T>(response: &Response<T>) {
let twenty_years = Duration::days(365 * 20); let twenty_years = Duration::from_secs(20 * 365 * 24 * 60 * 60);
let cookies: Vec<Cookie> = response let cookies: Vec<Cookie> = response
.headers() .headers()