diff --git a/NEWS b/NEWS index b7b96af42..01f5fecc1 100644 --- a/NEWS +++ b/NEWS @@ -25,10 +25,17 @@ ver 0.24 (not yet released) * static partition configuration * remove Haiku support -ver 0.23.11 (not yet released) +ver 0.23.11 (2022/11/28) +* database + - simple: move default database to ~/.cache/mpd/db from ~/.cache/mpd.db + - simple: default "cache_directory" to ~/.cache/mpd/mounts * macOS: fix build failure "no archive members specified" +* Windows + - fix crash bug (stack buffer overflow) after I/O errors + - fix path traversal bug because backslash was allowed in playlist names * Android/Windows - update OpenSSL to 3.0.7 + - re-enable CURL's verbose error strings ver 0.23.10 (2022/10/14) * storage diff --git a/python/build/libs.py b/python/build/libs.py index f50e164c6..4f35588e8 100644 --- a/python/build/libs.py +++ b/python/build/libs.py @@ -399,7 +399,6 @@ curl = CmakeProject( [ '-DBUILD_CURL_EXE=OFF', '-DBUILD_SHARED_LIBS=OFF', - '-DCURL_DISABLE_VERBOSE_STRINGS=ON', '-DCURL_DISABLE_LDAP=ON', '-DCURL_DISABLE_TELNET=ON', '-DCURL_DISABLE_DICT=ON', diff --git a/src/PlaylistFile.cxx b/src/PlaylistFile.cxx index 145a0f570..e5dbeee3b 100644 --- a/src/PlaylistFile.cxx +++ b/src/PlaylistFile.cxx @@ -82,6 +82,9 @@ spl_valid_name(const char *name_utf8) */ return std::strchr(name_utf8, '/') == nullptr && +#ifdef _WIN32 + std::strchr(name_utf8, '\\') == nullptr && +#endif std::strchr(name_utf8, '\n') == nullptr && std::strchr(name_utf8, '\r') == nullptr; } diff --git a/src/StateFileConfig.cxx b/src/StateFileConfig.cxx index 40d0c2fc4..51e7bf075 100644 --- a/src/StateFileConfig.cxx +++ b/src/StateFileConfig.cxx @@ -32,7 +32,7 @@ StateFileConfig::StateFileConfig(const ConfigData &config) { #ifdef ANDROID if (path.IsNull()) { - const auto cache_dir = GetUserCacheDir(); + const auto cache_dir = GetAppCacheDir(); if (cache_dir.IsNull()) return; diff --git a/src/db/Configured.cxx b/src/db/Configured.cxx index 04efc874d..8af80bf66 100644 --- a/src/db/Configured.cxx +++ b/src/db/Configured.cxx @@ -24,6 +24,7 @@ #include "config/Param.hxx" #include "config/Block.hxx" #include "fs/AllocatedPath.hxx" +#include "fs/FileSystem.hxx" #include "fs/StandardDirectory.hxx" #include "util/RuntimeError.hxx" @@ -51,17 +52,30 @@ CreateConfiguredDatabase(const ConfigData &config, } else { /* if there is no override, use the cache directory */ - const AllocatedPath cache_dir = GetUserCacheDir(); + const AllocatedPath cache_dir = GetAppCacheDir(); if (cache_dir.IsNull()) return nullptr; - const auto db_file = cache_dir / Path::FromFS(PATH_LITERAL("mpd.db")); + const auto db_file = cache_dir / Path::FromFS(PATH_LITERAL("db")); auto db_file_utf8 = db_file.ToUTF8(); if (db_file_utf8.empty()) return nullptr; ConfigBlock block; block.AddBlockParam("path", std::move(db_file_utf8), -1); + + { + const auto mounts_dir = cache_dir + / Path::FromFS(PATH_LITERAL("mounts")); + CreateDirectoryNoThrow(mounts_dir); + + if (auto mounts_dir_utf8 = mounts_dir.ToUTF8(); + !mounts_dir_utf8.empty()) + block.AddBlockParam("cache_directory", + std::move(mounts_dir_utf8), + -1); + } + return DatabaseGlobalInit(main_event_loop, io_event_loop, listener, block); } diff --git a/src/fs/FileSystem.hxx b/src/fs/FileSystem.hxx index 8844c96b0..c9fa5ff11 100644 --- a/src/fs/FileSystem.hxx +++ b/src/fs/FileSystem.hxx @@ -67,6 +67,16 @@ StatFile(Path file, struct stat &buf, bool follow_symlinks = true) #endif +static inline bool +CreateDirectoryNoThrow(Path path) noexcept +{ +#ifdef _WIN32 + return CreateDirectory(path.c_str(), nullptr); +#else + return mkdir(path.c_str(), 0777); +#endif +} + /** * Truncate a file that exists already. Throws std::system_error on * error. diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx index 4782b4da9..07397cc77 100644 --- a/src/fs/StandardDirectory.cxx +++ b/src/fs/StandardDirectory.cxx @@ -53,6 +53,12 @@ #include "Main.hxx" #endif +#ifdef USE_XDG +#include "Version.h" // for PACKAGE_NAME +#define APP_FILENAME PATH_LITERAL(PACKAGE_NAME) +static constexpr Path app_filename = Path::FromFS(APP_FILENAME); +#endif + #if !defined(_WIN32) && !defined(ANDROID) class PasswdEntry { @@ -284,6 +290,24 @@ GetUserCacheDir() noexcept #endif } +AllocatedPath +GetAppCacheDir() noexcept +{ +#ifdef USE_XDG + if (const auto user_dir = GetUserCacheDir(); !user_dir.IsNull()) { + auto dir = user_dir / app_filename; + CreateDirectoryNoThrow(dir); + return dir; + } + + return nullptr; +#elif defined(ANDROID) + return context->GetCacheDir(Java::GetEnv()); +#else + return nullptr; +#endif +} + AllocatedPath GetUserRuntimeDir() noexcept { @@ -297,7 +321,7 @@ GetUserRuntimeDir() noexcept AllocatedPath GetAppRuntimeDir() noexcept { -#ifdef __linux__ +#if defined(__linux__) && !defined(ANDROID) /* systemd specific; see systemd.exec(5) */ if (const char *runtime_directory = getenv("RUNTIME_DIRECTORY")) if (auto dir = Split(std::string_view{runtime_directory}, ':').first; @@ -307,8 +331,8 @@ GetAppRuntimeDir() noexcept #ifdef USE_XDG if (const auto user_dir = GetUserRuntimeDir(); !user_dir.IsNull()) { - auto dir = user_dir / Path::FromFS("mpd"); - mkdir(dir.c_str(), 0700); + auto dir = user_dir / app_filename; + CreateDirectoryNoThrow(dir); return dir; } #endif diff --git a/src/fs/StandardDirectory.hxx b/src/fs/StandardDirectory.hxx index 4ad06643f..e48ad53e6 100644 --- a/src/fs/StandardDirectory.hxx +++ b/src/fs/StandardDirectory.hxx @@ -43,6 +43,13 @@ GetUserMusicDir() noexcept; AllocatedPath GetUserCacheDir() noexcept; +/** + * Obtains cache directory for this application. + */ +[[gnu::const]] +AllocatedPath +GetAppCacheDir() noexcept; + /** * Obtains the runtime directory for the current user. */ diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index fe6e4ae7c..3434c4d30 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -499,8 +499,15 @@ CurlInputStream::InitEasy() request->SetVerifyPeer(verify_peer); request->SetVerifyHost(verify_host); request->SetOption(CURLOPT_HTTPHEADER, request_headers.Get()); - request->SetProxyVerifyPeer(verify_peer); - request->SetProxyVerifyHost(verify_host); + + try { + request->SetProxyVerifyPeer(verify_peer); + request->SetProxyVerifyHost(verify_host); + } catch (...) { + /* these methods fail if libCURL was compiled with + CURL_DISABLE_PROXY; ignore silently */ + } + request->SetConnectTimeout(connect_timeout); request->SetOption(CURLOPT_VERBOSE, verbose ? 1 : 0); diff --git a/src/system/Error.hxx b/src/system/Error.hxx index d629e0a08..01ff29b9f 100644 --- a/src/system/Error.hxx +++ b/src/system/Error.hxx @@ -91,8 +91,11 @@ FormatLastError(DWORD code, const char *fmt, Args&&... args) noexcept { char buffer[512]; const auto end = buffer + sizeof(buffer); - size_t length = snprintf(buffer, sizeof(buffer) - 128, + constexpr std::size_t max_prefix = sizeof(buffer) - 128; + size_t length = snprintf(buffer, max_prefix, fmt, std::forward(args)...); + if (length >= max_prefix) + length = max_prefix - 1; char *p = buffer + length; *p++ = ':'; *p++ = ' ';