fix: Replace old defaults path system with a new one

#1767
This commit is contained in:
WerWolv
2024-06-22 10:44:55 +02:00
parent beef0fff33
commit b60a262b58
41 changed files with 461 additions and 356 deletions

View File

@@ -2,6 +2,7 @@
#include <hex/api/event_manager.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <nlohmann/json.hpp>
@@ -197,7 +198,7 @@ namespace hex {
constexpr static auto AchievementsFile = "achievements.json";
void AchievementManager::loadProgress() {
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
for (const auto &directory : paths::Config.read()) {
auto path = directory / AchievementsFile;
if (!wolv::io::fs::exists(path)) {
@@ -246,7 +247,7 @@ namespace hex {
if (json.empty())
return;
for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) {
for (const auto &directory : paths::Config.write()) {
auto path = directory / AchievementsFile;
wolv::io::File file(path, wolv::io::File::Mode::Create);

View File

@@ -4,6 +4,7 @@
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <hex/ui/view.hpp>
#include <hex/data_processor/node.hpp>
@@ -101,7 +102,7 @@ namespace hex {
void load() {
bool loaded = false;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
for (const auto &dir : paths::Config.read()) {
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Read);
if (file.isValid()) {
@@ -142,7 +143,7 @@ namespace hex {
if (result.empty()) {
return;
}
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
for (const auto &dir : paths::Config.write()) {
wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create);
if (file.isValid()) {
@@ -153,7 +154,7 @@ namespace hex {
}
void clear() {
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
for (const auto &dir : paths::Config.write()) {
wolv::io::fs::remove(dir / SettingsFile);
}
}
@@ -595,7 +596,7 @@ namespace hex {
);
}
runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns));
runtime.setIncludePaths(paths::PatternsInclude.read() | paths::Patterns.read());
for (const auto &[ns, name, paramCount, callback, dangerous] : impl::getFunctions()) {
if (dangerous)

View File

@@ -1,13 +1,15 @@
#include <hex/api/layout_manager.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/ui/view.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/string.hpp>
#include <imgui.h>
#include <hex/api/content_registry.hpp>
#include <hex/ui/view.hpp>
namespace hex {
@@ -40,10 +42,7 @@ namespace hex {
fileName += ".hexlyt";
std::fs::path layoutPath;
for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
if (!hex::fs::isPathWritable(path))
continue;
for (const auto &path : paths::Layouts.write()) {
layoutPath = path / fileName;
}
@@ -109,7 +108,7 @@ namespace hex {
void LayoutManager::reload() {
s_layouts->clear();
for (const auto &directory : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) {
for (const auto &directory : paths::Layouts.read()) {
for (const auto &entry : std::fs::directory_iterator(directory)) {
const auto &path = entry.path();

View File

@@ -5,6 +5,7 @@
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/string.hpp>
@@ -306,7 +307,7 @@ namespace hex {
bool PluginManager::loadLibraries() {
bool success = true;
for (const auto &loadPath : fs::getDefaultPaths(fs::ImHexPath::Libraries))
for (const auto &loadPath : paths::Libraries.read())
success = PluginManager::loadLibraries(loadPath) && success;
return success;

View File

@@ -3,6 +3,7 @@
#include <hex/helpers/logger.hpp>
#include <hex/helpers/auto_reset.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/io/file.hpp>
@@ -25,7 +26,7 @@ namespace hex {
.builtin = false
}).first;
for (const auto &workspaceFolder : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) {
for (const auto &workspaceFolder : paths::Workspaces.write()) {
const auto workspacePath = workspaceFolder / (name + ".hexws");
if (exportToFile(workspacePath)) {
s_currentWorkspace->second.path = workspacePath;
@@ -157,7 +158,7 @@ namespace hex {
void WorkspaceManager::reload() {
WorkspaceManager::reset();
for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) {
for (const auto &defaultPath : paths::Workspaces.read()) {
for (const auto &entry : std::fs::directory_iterator(defaultPath)) {
if (!entry.is_regular_file()) {
continue;

View File

@@ -0,0 +1,150 @@
#include <hex/helpers/default_paths.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/project_file_manager.hpp>
#if defined(OS_WINDOWS)
#include <windows.h>
#include <shlobj.h>
#elif defined(OS_LINUX) || defined(OS_WEB)
#include <xdg.hpp>
# endif
namespace hex::paths {
std::vector<std::fs::path> getDataPaths(bool includeSystemFolders) {
std::vector<std::fs::path> paths;
#if defined(OS_WINDOWS)
// In the portable Windows version, we just use the executable directory
// Prevent the use of the AppData folder here
if (!ImHexApi::System::isPortableVersion()) {
PWSTR wAppDataPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
paths.emplace_back(wAppDataPath);
CoTaskMemFree(wAppDataPath);
}
}
#elif defined(OS_MACOS)
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath());
#elif defined(OS_LINUX) || defined(OS_WEB)
paths.push_back(xdg::DataHomeDir());
auto dataDirs = xdg::DataDirs();
std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths));
#endif
#if defined(OS_MACOS)
if (includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) {
paths.push_back(*executablePath);
}
}
#else
for (auto &path : paths)
path = path / "imhex";
if (ImHexApi::System::isPortableVersion() || includeSystemFolders) {
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(executablePath->parent_path());
}
#endif
// Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::ranges::copy(additionalDirs, std::back_inserter(paths));
// Add the project file directory to the path, if one is loaded
if (ProjectFile::hasPath()) {
paths.push_back(ProjectFile::getPath().parent_path());
}
return paths;
}
std::vector<std::fs::path> getConfigPaths(bool includeSystemFolders) {
#if defined(OS_WINDOWS)
return getDataPaths(includeSystemFolders);
#elif defined(OS_MACOS)
return getDataPaths(includeSystemFolders);
#elif defined(OS_LINUX) || defined(OS_WEB)
return {xdg::ConfigHomeDir() / "imhex"};
#endif
}
static std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, const std::fs::path &folder) {
for (auto &path : paths)
path = path / folder;
return paths;
}
static std::vector<std::fs::path> getPluginPaths() {
std::vector<std::fs::path> paths = getDataPaths(true);
// Add the system plugin directory to the path if one was provided at compile time
#if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION)
paths.push_back(SYSTEM_PLUGINS_LOCATION);
#endif
return paths;
}
namespace impl {
std::vector<std::fs::path> DefaultPath::read() const {
auto result = this->all();
std::erase_if(result, [](const auto &entryPath) {
return !wolv::io::fs::isDirectory(entryPath);
});
return result;
}
std::vector<std::fs::path> DefaultPath::write() const {
auto result = this->read();
std::erase_if(result, [](const auto &entryPath) {
return !hex::fs::isPathWritable(entryPath);
});
return result;
}
std::vector<std::fs::path> ConfigPath::all() const {
return appendPath(getConfigPaths(false), m_postfix);
}
std::vector<std::fs::path> DataPath::all() const {
return appendPath(getConfigPaths(true), m_postfix);
}
std::vector<std::fs::path> DataPath::write() const {
auto result = appendPath(getConfigPaths(false), m_postfix);
std::erase_if(result, [](const auto &entryPath) {
return !hex::fs::isPathWritable(entryPath);
});
return result;
}
std::vector<std::fs::path> PluginPath::all() const {
return appendPath(getPluginPaths(), m_postfix);
}
}
}

View File

@@ -286,170 +286,6 @@ namespace hex::fs {
#endif
std::vector<std::fs::path> getDataPaths() {
std::vector<std::fs::path> paths;
#if defined(OS_WINDOWS)
// In the portable Windows version, we just use the executable directory
// Prevent the use of the AppData folder here
if (!ImHexApi::System::isPortableVersion()) {
PWSTR wAppDataPath = nullptr;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) {
paths.emplace_back(wAppDataPath);
CoTaskMemFree(wAppDataPath);
}
}
#elif defined(OS_MACOS)
paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath());
#elif defined(OS_LINUX) || defined(OS_WEB)
paths.push_back(xdg::DataHomeDir());
auto dataDirs = xdg::DataDirs();
std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths));
#endif
#if defined(OS_MACOS)
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(*executablePath);
#else
for (auto &path : paths)
path = path / "imhex";
if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value())
paths.push_back(executablePath->parent_path());
#endif
// Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::ranges::copy(additionalDirs, std::back_inserter(paths));
// Add the project file directory to the path, if one is loaded
if (ProjectFile::hasPath()) {
paths.push_back(ProjectFile::getPath().parent_path());
}
return paths;
}
static std::vector<std::fs::path> getConfigPaths() {
#if defined(OS_WINDOWS)
return getDataPaths();
#elif defined(OS_MACOS)
return getDataPaths();
#elif defined(OS_LINUX) || defined(OS_WEB)
return {xdg::ConfigHomeDir() / "imhex"};
#endif
}
std::vector<std::fs::path> appendPath(std::vector<std::fs::path> paths, const std::fs::path &folder) {
for (auto &path : paths)
path = path / folder;
return paths;
}
std::vector<std::fs::path> getPluginPaths() {
std::vector<std::fs::path> paths = getDataPaths();
// Add the system plugin directory to the path if one was provided at compile time
#if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION)
paths.push_back(SYSTEM_PLUGINS_LOCATION);
#endif
return paths;
}
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting) {
std::vector<std::fs::path> result;
// Return the correct path based on the ImHexPath enum
switch (path) {
case ImHexPath::END:
return { };
case ImHexPath::Constants:
result = appendPath(getDataPaths(), "constants");
break;
case ImHexPath::Config:
result = appendPath(getConfigPaths(), "config");
break;
case ImHexPath::Backups:
result = appendPath(getDataPaths(), "backups");
break;
case ImHexPath::Encodings:
result = appendPath(getDataPaths(), "encodings");
break;
case ImHexPath::Logs:
result = appendPath(getDataPaths(), "logs");
break;
case ImHexPath::Plugins:
result = appendPath(getPluginPaths(), "plugins");
break;
case ImHexPath::Libraries:
result = appendPath(getPluginPaths(), "lib");
break;
case ImHexPath::Resources:
result = appendPath(getDataPaths(), "resources");
break;
case ImHexPath::Magic:
result = appendPath(getDataPaths(), "magic");
break;
case ImHexPath::Patterns:
result = appendPath(getDataPaths(), "patterns");
break;
case ImHexPath::PatternsInclude:
result = appendPath(getDataPaths(), "includes");
break;
case ImHexPath::Yara:
result = appendPath(getDataPaths(), "yara");
break;
case ImHexPath::YaraAdvancedAnalysis:
result = appendPath(getDefaultPaths(ImHexPath::Yara), "advanced_analysis");
break;
case ImHexPath::Recent:
result = appendPath(getConfigPaths(), "recent");
break;
case ImHexPath::Scripts:
result = appendPath(getDataPaths(), "scripts");
break;
case ImHexPath::Inspectors:
result = appendPath(getDefaultPaths(ImHexPath::Scripts), "inspectors");
break;
case ImHexPath::Nodes:
result = appendPath(getDefaultPaths(ImHexPath::Scripts), "nodes");
break;
case ImHexPath::Themes:
result = appendPath(getDataPaths(), "themes");
break;
case ImHexPath::Layouts:
result = appendPath(getDataPaths(), "layouts");
break;
case ImHexPath::Workspaces:
result = appendPath(getDataPaths(), "workspaces");
break;
}
// Remove all paths that don't exist if requested
if (!listNonExisting) {
std::erase_if(result, [](const auto &entryPath) {
return !wolv::io::fs::isDirectory(entryPath);
});
}
return result;
}
bool isPathWritable(const std::fs::path &path) {
constexpr static auto TestFileName = "__imhex__tmp__";

View File

@@ -2,8 +2,10 @@
#include <hex/api/task_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/io/file.hpp>
@@ -80,7 +82,7 @@ namespace hex::log {
void redirectToFile() {
if (s_loggerFile.isValid()) return;
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Logs, true)) {
for (const auto &path : paths::Logs.all()) {
wolv::io::fs::createDirectories(path);
s_loggerFile = wolv::io::File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))), wolv::io::File::Mode::Create);
s_loggerFile.disableBuffering();

View File

@@ -3,6 +3,7 @@
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/logger.hpp>
#include <hex/helpers/default_paths.hpp>
#include <wolv/utils/guards.hpp>
#include <wolv/utils/string.hpp>
@@ -29,7 +30,7 @@ namespace hex::magic {
std::string magicFiles;
std::error_code error;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
for (const auto &dir : paths::Magic.read()) {
for (const auto &entry : std::fs::directory_iterator(dir, error)) {
auto path = std::fs::absolute(entry.path());
@@ -64,12 +65,12 @@ namespace hex::magic {
if (magicFiles->empty())
return true;
std::array<char, 1024> cwd = { 0x00 };
std::array<char, 1024> cwd = { };
if (getcwd(cwd.data(), cwd.size()) == nullptr)
return false;
std::optional<std::fs::path> magicFolder;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
for (const auto &dir : paths::Magic.write()) {
if (std::fs::exists(dir) && fs::isPathWritable(dir)) {
magicFolder = dir;
break;