#include #include #include #if defined(OS_WINDOWS) #include #include #elif defined(OS_LINUX) || defined(OS_WEB) #include # endif namespace hex::paths { std::vector getDataPaths(bool includeSystemFolders) { std::vector 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 getConfigPaths(bool includeSystemFolders) { #if defined(OS_WINDOWS) return getDataPaths(includeSystemFolders); #elif defined(OS_MACOS) return getDataPaths(includeSystemFolders); #elif defined(OS_LINUX) || defined(OS_WEB) hex::unused(includeSystemFolders); return {xdg::ConfigHomeDir() / "imhex"}; #endif } static std::vector appendPath(std::vector paths, std::fs::path folder) { folder.make_preferred(); for (auto &path : paths) path = path / folder; return paths; } static std::vector getPluginPaths() { std::vector 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 DefaultPath::read() const { auto result = this->all(); std::erase_if(result, [](const auto &entryPath) { return !wolv::io::fs::isDirectory(entryPath); }); return result; } std::vector DefaultPath::write() const { auto result = this->read(); std::erase_if(result, [](const auto &entryPath) { return !hex::fs::isPathWritable(entryPath); }); return result; } std::vector ConfigPath::all() const { return appendPath(getConfigPaths(false), m_postfix); } std::vector DataPath::all() const { return appendPath(getDataPaths(true), m_postfix); } std::vector DataPath::write() const { auto result = appendPath(getDataPaths(false), m_postfix); std::erase_if(result, [](const auto &entryPath) { return !hex::fs::isPathWritable(entryPath); }); return result; } std::vector PluginPath::all() const { return appendPath(getPluginPaths(), m_postfix); } } }