1
0
mirror of synced 2024-11-28 01:20:51 +01:00

impr: Bundle default magic file with application

This commit is contained in:
WerWolv 2023-10-29 19:43:40 +01:00
parent 80ca6bf177
commit c444ad9280
8 changed files with 100 additions and 14 deletions

View File

@ -45,7 +45,7 @@ macro(add_imhex_plugin)
)
# Setup a romfs for the plugin
set(LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/romfs)
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/romfs)
set(LIBROMFS_PROJECT_NAME ${IMHEX_PLUGIN_NAME})
add_subdirectory(${IMHEX_BASE_FOLDER}/lib/external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/libromfs)
set_target_properties(${LIBROMFS_LIBRARY} PROPERTIES POSITION_INDEPENDENT_CODE ON)
@ -54,3 +54,9 @@ macro(add_imhex_plugin)
# Add the new plugin to the main dependency list so it gets built by default
add_dependencies(imhex_all ${IMHEX_PLUGIN_NAME})
endmacro()
macro(add_romfs_resource input output)
configure_file(${input} ${CMAKE_CURRENT_BINARY_DIR}/romfs/${output} COPYONLY)
list(APPEND LIBROMFS_RESOURCE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/romfs)
endmacro()

@ -1 +1 @@
Subproject commit 03365d8c5a43baa22cc6bbd5725db15a3038d035
Subproject commit fd79e86893e1b71b8d53cd59310a95748388555b

View File

@ -38,8 +38,8 @@ namespace hex::fs {
}
// With help from https://github.com/owncloud/client/blob/cba22aa34b3677406e0499aadd126ce1d94637a2/src/gui/openfilemanager.cpp
void openFileExternal(const std::fs::path &filePath) {
// Make sure the file exists before trying to open it
if (!wolv::io::fs::exists(filePath))
return;
@ -57,6 +57,7 @@ namespace hex::fs {
}
void openFolderExternal(const std::fs::path &dirPath) {
// Make sure the folder exists before trying to open it
if (!wolv::io::fs::exists(dirPath))
return;
@ -74,6 +75,7 @@ namespace hex::fs {
}
void openFolderWithSelectionExternal(const std::fs::path &selectedFilePath) {
// Make sure the file exists before trying to open it
if (!wolv::io::fs::exists(selectedFilePath))
return;
@ -198,13 +200,18 @@ namespace hex::fs {
#else
bool openFileBrowser(DialogMode mode, const std::vector<ItemFilter> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath, bool multiple) {
// Turn the content of the ItemFilter objects into something NFD understands
std::vector<nfdfilteritem_t> validExtensionsNfd;
for (const auto &extension : validExtensions) {
validExtensionsNfd.emplace_back(nfdfilteritem_t{ extension.name.c_str(), extension.spec.c_str() });
}
// Clear errors from previous runs
NFD::ClearError();
// Try to initialize NFD
if (NFD::Init() != NFD_OKAY) {
// Handle errors if initialization failed
log::error("NFD init returned an error: {}", NFD::GetError());
if (s_fileBrowserErrorCallback != nullptr) {
auto error = NFD::GetError();
@ -216,7 +223,9 @@ namespace hex::fs {
NFD::UniquePathU8 outPath;
NFD::UniquePathSet outPaths;
nfdresult_t result;
nfdresult_t result = NFD_ERROR;
// Open the correct file dialog based on the mode
switch (mode) {
case DialogMode::Open:
if (multiple)
@ -230,17 +239,20 @@ namespace hex::fs {
case DialogMode::Folder:
result = NFD::PickFolder(outPath, defaultPath.empty() ? nullptr : defaultPath.c_str());
break;
default:
std::unreachable();
}
if (result == NFD_OKAY){
if(outPath != nullptr) {
// Handle the path if the dialog was opened in single mode
if (outPath != nullptr) {
// Call the provided callback with the path
callback(reinterpret_cast<char8_t*>(outPath.get()));
}
// Handle multiple paths if the dialog was opened in multiple mode
if (outPaths != nullptr) {
nfdpathsetsize_t numPaths = 0;
if (NFD::PathSet::Count(outPaths, numPaths) == NFD_OKAY) {
// Loop over all returned paths and call the callback with each of them
for (size_t i = 0; i < numPaths; i++) {
NFD::UniquePathSetPath path;
if (NFD::PathSet::GetPath(outPaths, i, path) == NFD_OKAY)
@ -249,9 +261,14 @@ namespace hex::fs {
}
}
} else if (result == NFD_ERROR) {
// Handle errors that occurred during the file dialog call
log::error("Requested file dialog returned an error: {}", NFD::GetError());
if (s_fileBrowserErrorCallback != nullptr)
s_fileBrowserErrorCallback(NFD::GetError() ? NFD::GetError() : "No details");
if (s_fileBrowserErrorCallback != nullptr) {
auto error = NFD::GetError();
s_fileBrowserErrorCallback(error != nullptr ? error : "No details");
}
}
NFD::Quit();
@ -266,6 +283,8 @@ namespace hex::fs {
#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))) {
@ -303,9 +322,11 @@ namespace hex::fs {
#endif
// Add additional data directories to the path
auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths();
std::copy(additionalDirs.begin(), additionalDirs.end(), 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());
}
@ -332,9 +353,12 @@ namespace hex::fs {
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);
paths.push_back(SYSTEM_PLUGINS_LOCATION);
#endif
return paths;
}
@ -342,6 +366,7 @@ namespace hex::fs {
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 { };
@ -398,6 +423,7 @@ namespace hex::fs {
break;
}
// Remove all paths that don't exist if requested
if (!listNonExisting) {
result.erase(std::remove_if(result.begin(), result.end(), [](const auto &path) {
return !wolv::io::fs::isDirectory(path);
@ -409,6 +435,9 @@ namespace hex::fs {
bool isPathWritable(const std::fs::path &path) {
constexpr static auto TestFileName = "__imhex__tmp__";
// Try to open the __imhex__tmp__ file in the given path
// If one does exist already, try to delete it
{
wolv::io::File file(path / TestFileName, wolv::io::File::Mode::Read);
if (file.isValid()) {
@ -417,6 +446,8 @@ namespace hex::fs {
}
}
// Try to create a new file in the given path
// If that fails, or the file cannot be deleted anymore afterward; the path is not writable
wolv::io::File file(path / TestFileName, wolv::io::File::Mode::Create);
bool result = file.isValid();
if (!file.remove())
@ -427,16 +458,19 @@ namespace hex::fs {
std::fs::path toShortPath(const std::fs::path &path) {
#if defined(OS_WINDOWS)
// Get the size of the short path
size_t size = GetShortPathNameW(path.c_str(), nullptr, 0);
if (size == 0)
return path;
// Get the short path
std::wstring newPath(size, 0x00);
GetShortPathNameW(path.c_str(), newPath.data(), newPath.size());
newPath.pop_back();
return newPath;
#else
// Other supported platforms don't have short paths
return path;
#endif
}

View File

@ -30,15 +30,22 @@ namespace hex::magic {
std::error_code error;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
for (const auto &entry : std::fs::recursive_directory_iterator(dir, error)) {
for (const auto &entry : std::fs::directory_iterator(dir, error)) {
auto path = std::fs::absolute(entry.path());
if (entry.is_regular_file() && ((sourceFiles && path.extension().empty()) || (!sourceFiles && path.extension() == ".mgc"))) {
magicFiles += wolv::util::toUTF8String(wolv::io::fs::toShortPath(path)) + MAGIC_PATH_SEPARATOR;
if (sourceFiles) {
if (path.extension().empty() || entry.is_directory())
magicFiles += wolv::util::toUTF8String(path) + MAGIC_PATH_SEPARATOR;
} else {
if (path.extension() == ".mgc")
magicFiles += wolv::util::toUTF8String(path) + MAGIC_PATH_SEPARATOR;
}
}
}
if (!magicFiles.empty())
magicFiles.pop_back();
if (error)
return std::nullopt;
else
@ -46,7 +53,7 @@ namespace hex::magic {
}
bool compile() {
magic_t ctx = magic_open(MAGIC_NONE);
magic_t ctx = magic_open(MAGIC_CHECK);
ON_SCOPE_EXIT { magic_close(ctx); };
auto magicFiles = getMagicFiles(true);
@ -75,6 +82,9 @@ namespace hex::magic {
return false;
auto result = magic_compile(ctx, magicFiles->c_str()) == 0;
if (!result) {
log::error("Failed to compile magic files \"{}\": {}", *magicFiles, magic_error(ctx));
}
if (chdir(cwd.data()) != 0)
return false;

View File

@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.16)
include(ImHexPlugin)
find_file(DEFAULT_MAGIC_FILE_PATH magic.mgc HINTS ${MAGIC_INCLUDE_DIRS}/../share/misc)
if (DEFAULT_MAGIC_FILE_PATH)
add_romfs_resource(${DEFAULT_MAGIC_FILE_PATH} auto_extract/magic/magic.mgc)
endif ()
add_imhex_plugin(
NAME
builtin
@ -36,6 +41,7 @@ add_imhex_plugin(
source/content/file_handlers.cpp
source/content/project.cpp
source/content/achievements.cpp
source/content/file_extraction.cpp
source/content/providers/file_provider.cpp
source/content/providers/gdb_provider.cpp

View File

@ -0,0 +1,26 @@
#include <hex/helpers/fs.hpp>
#include <wolv/io/file.hpp>
#include <romfs/romfs.hpp>
namespace hex::plugin::builtin {
void extractBundledFiles() {
for (const auto &romfsPath : romfs::list("auto_extract")) {
for (const auto &imhexPath : fs::getDataPaths()) {
wolv::io::File file(imhexPath, wolv::io::File::Mode::Create);
if (!file.isValid())
continue;
auto data = romfs::get(romfsPath).span<u8>();
file.writeBuffer(data.data(), data.size());
if (file.getSize() == data.size())
break;
}
}
}
}

View File

@ -47,6 +47,8 @@ namespace hex::plugin::builtin {
void handleBorderlessWindowMode();
void extractBundledFiles();
}
IMHEX_PLUGIN_SUBCOMMANDS() {
@ -107,6 +109,8 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
registerMainMenuEntries();
handleBorderlessWindowMode();
extractBundledFiles();
}
// This is the default plugin