1
0
mirror of synced 2024-11-27 17:10:51 +01:00

feat: Added Auto Updater for Windows, macOS and Ubuntu (#1377)

This commit is contained in:
Nik 2023-10-21 20:40:24 +02:00 committed by GitHub
parent c46e445a04
commit f114239f51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 390 additions and 92 deletions

View File

@ -98,7 +98,7 @@ macro(configurePackingResources)
endif()
if (WIN32)
set(APPLICATION_TYPE)
set(APPLICATION_TYPE WIN32)
set(IMHEX_ICON "${IMHEX_BASE_FOLDER}/resources/resource.rc")
if (CREATE_PACKAGE)

View File

@ -536,6 +536,13 @@ namespace hex {
* @return Git commit branch
*/
std::string getCommitBranch();
enum class UpdateType {
Stable,
Nightly
};
bool updateImHex(UpdateType updateType);
}
/**

View File

@ -11,15 +11,4 @@ namespace hex {
return fmt::format(fmt::runtime(format), args...);
}
template<typename... Args>
inline void print(std::string_view format, Args... args) {
fmt::print(fmt::runtime(format), args...);
}
template<typename... Args>
inline void println(std::string_view format, Args... args) {
fmt::print(fmt::runtime(format), args...);
fmt::print("\n");
}
}

View File

@ -19,6 +19,7 @@ namespace hex::log {
wolv::io::File& getFile();
bool isRedirected();
[[maybe_unused]] void redirectToFile();
[[maybe_unused]] void enableColorPrinting();
extern std::mutex g_loggerMutex;
@ -50,8 +51,7 @@ namespace hex::log {
fmt::print(dest, "{}", std::string(ProjectNameLength > 10 ? 0 : 10 - ProjectNameLength, ' '));
}
template<typename... T>
[[maybe_unused]] void print(const fmt::text_style &ts, const std::string &level, const std::string &fmt, auto... args) {
[[maybe_unused]] void print(const fmt::text_style &ts, const std::string &level, const std::string &fmt, auto && ... args) {
std::scoped_lock lock(impl::g_loggerMutex);
auto dest = impl::getDestination();
@ -66,7 +66,7 @@ namespace hex::log {
}
[[maybe_unused]] void debug(const std::string &fmt, auto &&...args) {
[[maybe_unused]] void debug(const std::string &fmt, auto && ... args) {
#if defined(DEBUG)
hex::log::print(fg(fmt::color::light_green) | fmt::emphasis::bold, "[DEBUG]", fmt, args...);
#else
@ -74,20 +74,39 @@ namespace hex::log {
#endif
}
[[maybe_unused]] void info(const std::string &fmt, auto &&...args) {
[[maybe_unused]] void info(const std::string &fmt, auto && ... args) {
hex::log::print(fg(fmt::color::cadet_blue) | fmt::emphasis::bold, "[INFO] ", fmt, args...);
}
[[maybe_unused]] void warn(const std::string &fmt, auto &&...args) {
[[maybe_unused]] void warn(const std::string &fmt, auto && ... args) {
hex::log::print(fg(fmt::color::orange) | fmt::emphasis::bold, "[WARN] ", fmt, args...);
}
[[maybe_unused]] void error(const std::string &fmt, auto &&...args) {
[[maybe_unused]] void error(const std::string &fmt, auto && ... args) {
hex::log::print(fg(fmt::color::red) | fmt::emphasis::bold, "[ERROR]", fmt, args...);
}
[[maybe_unused]] void fatal(const std::string &fmt, auto &&...args) {
[[maybe_unused]] void fatal(const std::string &fmt, auto && ... args) {
hex::log::print(fg(fmt::color::purple) | fmt::emphasis::bold, "[FATAL]", fmt, args...);
}
[[maybe_unused]] void print(const std::string &fmt, auto && ... args) {
std::scoped_lock lock(impl::g_loggerMutex);
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}", message);
fflush(dest);
}
[[maybe_unused]] void println(const std::string &fmt, auto && ... args) {
std::scoped_lock lock(impl::g_loggerMutex);
auto dest = impl::getDestination();
auto message = fmt::format(fmt::runtime(fmt), args...);
fmt::print(dest, "{}\n", message);
fflush(dest);
}
}

View File

@ -59,7 +59,8 @@ namespace hex {
[[nodiscard]] std::string toByteString(u64 bytes);
[[nodiscard]] std::string makePrintable(u8 c);
void runCommand(const std::string &command);
void startProgram(const std::string &command);
int executeCommand(const std::string &command);
void openWebpage(std::string url);
[[nodiscard]] std::string encodeByteString(const std::vector<u8> &bytes);

View File

@ -5,8 +5,10 @@
#include <hex/api/task.hpp>
#include <hex/providers/provider.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/utils.hpp>
#include <wolv/io/file.hpp>
#include <wolv/utils/string.hpp>
#include <utility>
#include <unistd.h>
@ -639,6 +641,44 @@ namespace hex {
#endif
}
bool updateImHex(UpdateType updateType) {
// Get the path of the updater executable
std::fs::path executablePath;
for (const auto &entry : std::fs::directory_iterator(wolv::io::fs::getExecutablePath()->parent_path())) {
if (entry.path().filename().string().starts_with("imhex-updater")) {
executablePath = entry.path();
break;
}
}
if (executablePath.empty() || !wolv::io::fs::exists(executablePath))
return false;
std::string updateTypeString;
switch (updateType) {
case UpdateType::Stable:
updateTypeString = "latest";
break;
case UpdateType::Nightly:
updateTypeString = "nightly";
break;
}
EventManager::subscribe<EventImHexClosing>([executablePath, updateTypeString] {
hex::executeCommand(
hex::format("{} {}",
wolv::util::toUTF8String(executablePath),
updateTypeString
)
);
});
ImHexApi::System::closeImHex();
return true;
}
}
namespace ImHexApi::Messaging {

View File

@ -4,6 +4,10 @@
#include <wolv/io/file.hpp>
#if defined(OS_WINDOWS)
#include <Windows.h>
#endif
namespace hex::log::impl {
static wolv::io::File s_loggerFile;
@ -36,6 +40,19 @@ namespace hex::log::impl {
}
}
void enableColorPrinting() {
#if defined(OS_WINDOWS)
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (::GetConsoleMode(hConsole, &mode) == TRUE) {
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT;
::SetConsoleMode(hConsole, mode);
}
}
#endif
}
std::vector<LogEntry>& getLogEntries() {
static std::vector<LogEntry> logEntries;

View File

@ -313,7 +313,7 @@ namespace hex {
return std::to_string(value).substr(0, 5) + Suffixes[suffixIndex];
}
void runCommand(const std::string &command) {
void startProgram(const std::string &command) {
#if defined(OS_WINDOWS)
hex::unused(system(hex::format("start {0}", command).c_str()));
@ -326,6 +326,10 @@ namespace hex {
#endif
}
int executeCommand(const std::string &command) {
return ::system(command.c_str());
}
void openWebpage(std::string url) {
if (!url.contains("://"))
url = "https://" + url;

View File

@ -8,3 +8,7 @@ add_subdirectory(gui)
if (WIN32)
add_subdirectory(forwarder)
endif ()
if (NOT EMSCRIPTEN)
add_subdirectory(updater)
endif ()

View File

@ -28,8 +28,11 @@
#include <fmt/format.h>
void handleConsoleWindow() {
void setupConsoleWindow() {
// Get the handle of the console window
HWND consoleWindow = ::GetConsoleWindow();
// Get console process ID
DWORD processId = 0;
::GetWindowThreadProcessId(consoleWindow, &processId);
@ -48,6 +51,11 @@ void handleConsoleWindow() {
::SetConsoleMode(hConsole, mode);
}
}
// Set the __IMHEX_FORWARD_CONSOLE__ environment variable,
// to let ImHex know that it was launched from the forwarder
// and that it should forward it's console output to us
::SetEnvironmentVariableA("__IMHEX_FORWARD_CONSOLE__", "1");
}
}
@ -57,23 +65,26 @@ int launchExecutable() {
auto executableFullPath = executablePath->parent_path() / "imhex-gui.exe";
::PROCESS_INFORMATION process = { };
::STARTUPINFOW startupInfo = { };
startupInfo.cb = sizeof(STARTUPINFOW);
::STARTUPINFOW startupInfo = { .cb = sizeof(::STARTUPINFOW) };
// Create a new process for imhex-gui.exe with the same command line as the current process
if (::CreateProcessW(executableFullPath.wstring().c_str(), ::GetCommandLineW(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startupInfo, &process) == FALSE) {
// Handle error if the process could not be created
// Get formatted error message from the OS
auto errorCode = ::GetLastError();
auto errorMessageString = std::system_category().message(errorCode);
// Generate error message
auto errorMessage = fmt::format("Failed to start ImHex:\n\nError code: 0x{:08X}\n\n{}", errorCode, errorMessageString);
// Display a message box with the error
::MessageBoxA(nullptr, errorMessage.c_str(), "ImHex Forwarder", MB_OK | MB_ICONERROR);
return EXIT_FAILURE;
}
// Wait for the main ImHex process to exit
::WaitForSingleObject(process.hProcess, INFINITE);
::CloseHandle(process.hProcess);
@ -81,8 +92,7 @@ int launchExecutable() {
}
int main() {
handleConsoleWindow();
auto result = launchExecutable();
setupConsoleWindow();
return result;
return launchExecutable();
}

View File

@ -32,7 +32,7 @@ namespace hex::crash {
void resetCrashHandlers();
static void sendNativeMessage(const std::string& message) {
hex::nativeErrorMessage(hex::format("ImHex crashed during its loading.\nError: {}", message));
hex::nativeErrorMessage(hex::format("ImHex crashed during initial setup!\nError: {}", message));
}
// Function that decides what should happen on a crash
@ -136,15 +136,14 @@ namespace hex::crash {
// Reset crash handlers, so we can't have a recursion if this code crashes
resetCrashHandlers();
handleCrash("Uncaught exception!");
// Print the current exception info
try {
std::rethrow_exception(std::current_exception());
} catch (std::exception &ex) {
std::string exceptionStr = hex::format("{}()::what() -> {}", llvm::itaniumDemangle(typeid(ex).name(), nullptr, nullptr, nullptr), ex.what());
log::fatal("Program terminated with uncaught exception: {}", exceptionStr);
handleCrash(exceptionStr);
log::fatal("Program terminated with uncaught exception: {}", exceptionStr);
}
triggerSafeShutdown();

View File

@ -18,6 +18,7 @@
#include <wolv/io/fs.hpp>
#include <wolv/utils/guards.hpp>
#include <fcntl.h>
#if defined(OS_WEB)
#include <emscripten.h>

View File

@ -26,6 +26,7 @@
#include <windowsx.h>
#include <shobjidl.h>
#include <wrl/client.h>
#include <fcntl.h>
#include <csignal>
#include <cstdio>
@ -231,22 +232,52 @@ namespace hex {
}
static void reopenConsoleHandle(u32 stdHandleNumber, i32 stdFileDescriptor, FILE *stdStream) {
// Get the Windows handle for the standard stream
HANDLE handle = ::GetStdHandle(stdHandleNumber);
// Redirect the standard stream to the relevant console stream
if (stdFileDescriptor == STDIN_FILENO)
freopen("CONIN$", "rt", stdStream);
else
freopen("CONOUT$", "wt", stdStream);
// Disable buffering
setvbuf(stdStream, nullptr, _IONBF, 0);
// Reopen the standard stream as a file descriptor
auto unboundFd = [stdFileDescriptor, handle]{
if (stdFileDescriptor == STDIN_FILENO)
return _open_osfhandle(intptr_t(handle), _O_RDONLY);
else
return _open_osfhandle(intptr_t(handle), _O_WRONLY);
}();
// Duplicate the file descriptor to the standard stream
dup2(unboundFd, stdFileDescriptor);
}
void Window::initNative() {
HWND consoleWindow = ::GetConsoleWindow();
DWORD processId = 0;
::GetWindowThreadProcessId(consoleWindow, &processId);
if (GetCurrentProcessId() == processId) {
ShowWindow(consoleWindow, SW_HIDE);
log::impl::redirectToFile();
// Check for the __IMHEX_FORWARD_CONSOLE__ environment variable that was set by the forwarder application
// If it's present attach to its console window
if (hex::getEnvironmentVariable("__IMHEX_FORWARD_CONSOLE__") == "1") {
::AttachConsole(ATTACH_PARENT_PROCESS);
// Reopen stdin, stdout and stderr to the console
reopenConsoleHandle(STD_INPUT_HANDLE, STDIN_FILENO, stdin);
reopenConsoleHandle(STD_OUTPUT_HANDLE, STDOUT_FILENO, stdout);
// Explicitly don't forward stderr because some libraries like to write to it
// with no way to disable it (e.g., libmagic)
/*
reopenConsoleHandle(STD_ERROR_HANDLE, STDERR_FILENO, stderr);
*/
// Enable ANSI colors in the console
log::impl::enableColorPrinting();
} else {
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (::GetConsoleMode(hConsole, &mode) == TRUE) {
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT;
::SetConsoleMode(hConsole, mode);
}
}
log::impl::redirectToFile();
}
ImHexApi::System::impl::setBorderlessWindowMode(true);
@ -256,11 +287,6 @@ namespace hex {
if (std::fs::exists(path))
AddDllDirectory(path.c_str());
}
// Various libraries sadly directly print to stderr with no way to disable it
// We redirect stderr to NUL to prevent this
freopen("NUL:", "w", stderr);
setvbuf(stderr, nullptr, _IONBF, 0);
}
void Window::setupNativeWindow() {

View File

@ -0,0 +1,15 @@
project(updater)
add_executable(updater ${APPLICATION_TYPE}
source/main.cpp
)
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
target_link_libraries(updater PRIVATE libimhex libwolv-io ${FMT_LIBRARIES})
add_dependencies(imhex_all updater)
set_target_properties(updater PROPERTIES
OUTPUT_NAME "imhex-updater"
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../..
CXX_VISIBILITY_PRESET hidden
POSITION_INDEPENDENT_CODE ON
)

View File

@ -0,0 +1,167 @@
#include <hex/api_urls.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/helpers/http_requests.hpp>
#include <hex/helpers/utils.hpp>
using namespace std::literals::string_literals;
std::string getUpdateUrl(std::string_view versionType, std::string_view operatingSystem) {
// Get the latest version info from the ImHex API
auto response = hex::HttpRequest("GET",
ImHexApiURL + fmt::format("/update/{}/{}",
versionType,
operatingSystem
)
).execute().get();
const auto &data = response.getData();
// Make sure we got a valid response
if (!response.isSuccess()) {
hex::log::error("Failed to get latest version info: ({}) {}", response.getStatusCode(), data);
return { };
}
return data;
}
std::optional<std::fs::path> downloadUpdate(const std::string &url, const std::string &type) {
// Download the update
auto response = hex::HttpRequest("GET", url).downloadFile().get();
// Make sure we got a valid response
if (!response.isSuccess()) {
hex::log::error("Failed to download update");
return std::nullopt;
}
const auto &data = response.getData();
// Write the update to a file
std::fs::path filePath;
{
constexpr static auto UpdateFileName = "update.hexupd";
// Loop over all available paths
wolv::io::File file;
for (const auto &path : hex::fs::getDefaultPaths(hex::fs::ImHexPath::Config)) {
// Remove any existing update files
wolv::io::fs::remove(path / UpdateFileName);
// If a valid location hasn't been found already, try to create a new file
if (!file.isValid())
file = wolv::io::File(path / UpdateFileName, wolv::io::File::Mode::Create);
}
// If the update data can't be written to any of the default paths, the update cannot continue
if (!file.isValid()) {
hex::log::error("Failed to create update file");
return std::nullopt;
}
// Write the downloaded update data to the file
file.writeVector(data);
// Save the path to the update file
filePath = file.getPath();
}
return filePath;
}
std::string getUpdateType() {
#if defined (OS_WINDOWS)
if (!hex::ImHexApi::System::isPortableVersion())
return "win-msi";
#elif defined (OS_MACOS)
return "mac-dmg";
#elif defined (OS_LINUX)
if (hex::executeCommand("lsb_release -a | grep Ubuntu") == 0) {
if (hex::executeCommand("lsb_release -a | grep 22.") == 0)
return "linux-deb-22.04";
else if (hex::executeCommand("lsb_release -a | grep 23.") == 0)
return "linux-deb-23.04";
}
#endif
return "";
}
int installUpdate(const std::string &type, std::fs::path updatePath) {
struct UpdateHandler {
const char *type;
const char *extension;
const char *command;
};
constexpr static auto UpdateHandlers = {
UpdateHandler { "win-msi", ".msi", "msiexec /fa {} /passive" },
UpdateHandler { "macos-dmg", ".dmg", "hdiutil attach {}" },
UpdateHandler { "linux-deb-22.04", ".deb", "sudo apt update && sudo apt install -y --fix-broken {}" },
UpdateHandler { "linux-deb-23.04", ".deb", "sudo apt update && sudo apt install -y --fix-broken {}" },
};
for (const auto &handler : UpdateHandlers) {
if (type == handler.type) {
// Rename the update file to the correct extension
updatePath.replace_extension(handler.extension);
std::fs::rename(updatePath, updatePath);
// Install the update using the correct command
hex::startProgram(hex::format(handler.command, updatePath.string()));
return EXIT_SUCCESS;
}
}
// If the installation type isn't handled here, the detected installation type doesn't support updates through the updater
hex::log::error("Install type cannot be updated");
// Open the latest release page in the default browser to allow the user to manually update
hex::openWebpage("https://github.com/WerWolv/ImHex/releases/latest");
return EXIT_FAILURE;
}
int main(int argc, char **argv) {
hex::log::impl::enableColorPrinting();
// Check we have the correct number of arguments
if (argc != 2) {
hex::log::error("Failed to start updater: Invalid arguments");
return EXIT_FAILURE;
}
// Read the version type from the arguments
const auto versionType = argv[1];
hex::log::info("Updater started with version type: {}", versionType);
// Query the update type
const auto updateType = getUpdateType();
hex::log::info("Detected OS String: {}", updateType);
// Make sure we got a valid update type
if (updateType.empty()) {
hex::log::error("Failed to detect installation type");
return EXIT_FAILURE;
}
// Get the url to the requested update from the ImHex API
const auto updateUrl = getUpdateUrl(versionType, updateType);
if (updateUrl.empty()) {
hex::log::error("Failed to get update URL");
return EXIT_FAILURE;
}
hex::log::info("Update URL found: {}", updateUrl);
// Download the update file
auto updatePath = downloadUpdate(updateUrl, updateType);
if (!updatePath.has_value())
return EXIT_FAILURE;
// Install the update
return installUpdate(updateType, *updatePath);
}

View File

@ -26,7 +26,7 @@ namespace hex::plugin::builtin {
void handleVersionCommand(const std::vector<std::string> &args) {
hex::unused(args);
hex::print(romfs::get("logo.ans").string(),
hex::log::print(std::string(romfs::get("logo.ans").string()),
ImHexApi::System::getImHexVersion(),
ImHexApi::System::getCommitBranch(), ImHexApi::System::getCommitHash(),
__DATE__, __TIME__,
@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
void handleHelpCommand(const std::vector<std::string> &args) {
hex::unused(args);
hex::print(
hex::log::print(
"ImHex - A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.\n"
"\n"
"usage: imhex [subcommand] [options]\n"
@ -54,7 +54,7 @@ namespace hex::plugin::builtin {
for (const auto &plugin : PluginManager::getPlugins()) {
for (const auto &subCommand : plugin.getSubCommands()) {
hex::println(" --{}{: <{}} {}", subCommand.commandKey, "", longestCommand - subCommand.commandKey.size(), subCommand.commandDesc);
hex::log::println(" --{}{: <{}} {}", subCommand.commandKey, "", longestCommand - subCommand.commandKey.size(), subCommand.commandDesc);
}
}
@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
void handleOpenCommand(const std::vector<std::string> &args) {
if (args.empty()) {
hex::println("No files provided to open.");
hex::log::println("No files provided to open.");
std::exit(EXIT_FAILURE);
}
@ -89,8 +89,8 @@ namespace hex::plugin::builtin {
void handleCalcCommand(const std::vector<std::string> &args) {
if (args.empty()) {
hex::println("No expression provided!");
hex::println("Example: imhex --calc \"5 * 7\"");
hex::log::println("No expression provided!");
hex::log::println("Example: imhex --calc \"5 * 7\"");
std::exit(EXIT_FAILURE);
}
@ -100,9 +100,9 @@ namespace hex::plugin::builtin {
auto result = evaluator.evaluate(input);
if (!result.has_value())
hex::println("{}\n> '{}'", evaluator.getLastError().value(), input);
hex::log::println("{}\n> '{}'", evaluator.getLastError().value(), input);
else
hex::println("{}", result.value());
hex::log::println("{}", result.value());
std::exit(EXIT_SUCCESS);
}
@ -110,19 +110,19 @@ namespace hex::plugin::builtin {
void handlePluginsCommand(const std::vector<std::string> &args) {
hex::unused(args);
hex::println("Loaded plugins:");
hex::log::println("Loaded plugins:");
for (const auto &plugin : PluginManager::getPlugins()) {
hex::print("- ");
hex::log::print("- ");
if (plugin.isBuiltinPlugin())
hex::print("\033[1;43m{}\033[0m", plugin.getPluginName());
hex::log::print("\033[1;43m{}\033[0m", plugin.getPluginName());
else
hex::print("\033[1m{}\033[0m", plugin.getPluginName());
hex::log::print("\033[1m{}\033[0m", plugin.getPluginName());
hex::println(" by {}", plugin.getPluginAuthor());
hex::log::println(" by {}", plugin.getPluginAuthor());
hex::println(" \033[2;3m{}\033[0m", plugin.getPluginDescription());
hex::log::println(" \033[2;3m{}\033[0m", plugin.getPluginDescription());
}
std::exit(EXIT_SUCCESS);
@ -130,8 +130,8 @@ namespace hex::plugin::builtin {
void handleHashCommand(const std::vector<std::string> &args) {
if (args.size() != 2) {
hex::println("usage: imhex --hash <algorithm> <file>");
hex::println("Available algorithms: md5, sha1, sha224, sha256, sha384, sha512");
hex::log::println("usage: imhex --hash <algorithm> <file>");
hex::log::println("Available algorithms: md5, sha1, sha224, sha256, sha384, sha512");
std::exit(EXIT_FAILURE);
}
@ -140,7 +140,7 @@ namespace hex::plugin::builtin {
wolv::io::File file(filePath, wolv::io::File::Mode::Read);
if (!file.isValid()) {
hex::println("Failed to open file: {}", wolv::util::toUTF8String(filePath));
hex::log::println("Failed to open file: {}", wolv::util::toUTF8String(filePath));
std::exit(EXIT_FAILURE);
}
@ -162,20 +162,20 @@ namespace hex::plugin::builtin {
} else if (algorithm == "sha512") {
result = toVector(hex::crypt::sha512(file.readVector()));
} else {
hex::println("Unknown algorithm: {}", algorithm);
hex::println("Available algorithms: md5, sha1, sha224, sha256, sha384, sha512");
hex::log::println("Unknown algorithm: {}", algorithm);
hex::log::println("Available algorithms: md5, sha1, sha224, sha256, sha384, sha512");
std::exit(EXIT_FAILURE);
}
hex::println("{}({}) = {}", algorithm, wolv::util::toUTF8String(filePath.filename()), hex::crypt::encode16(result));
hex::log::println("{}({}) = {}", algorithm, wolv::util::toUTF8String(filePath.filename()), hex::crypt::encode16(result));
std::exit(EXIT_SUCCESS);
}
void handleEncodeCommand(const std::vector<std::string> &args) {
if (args.size() != 2) {
hex::println("usage: imhex --encode <algorithm> <string>");
hex::println("Available algorithms: base64, hex");
hex::log::println("usage: imhex --encode <algorithm> <string>");
hex::log::println("Available algorithms: base64, hex");
std::exit(EXIT_FAILURE);
}
@ -189,19 +189,19 @@ namespace hex::plugin::builtin {
} else if (algorithm == "hex") {
result = hex::crypt::encode16(data);
} else {
hex::println("Unknown algorithm: {}", algorithm);
hex::println("Available algorithms: base64, hex");
hex::log::println("Unknown algorithm: {}", algorithm);
hex::log::println("Available algorithms: base64, hex");
std::exit(EXIT_FAILURE);
}
hex::println("encode_{}({}) = {}", algorithm, args[1], result);
hex::log::println("encode_{}({}) = {}", algorithm, args[1], result);
std::exit(EXIT_SUCCESS);
}
void handleDecodeCommand(const std::vector<std::string> &args) {
if (args.size() != 2) {
hex::println("usage: imhex --decode <algorithm> <string>");
hex::println("Available algorithms: base64, hex");
hex::log::println("usage: imhex --decode <algorithm> <string>");
hex::log::println("Available algorithms: base64, hex");
std::exit(EXIT_FAILURE);
}
@ -216,24 +216,24 @@ namespace hex::plugin::builtin {
auto base16 = hex::crypt::decode16(std::string(data.begin(), data.end()));
result = std::string(base16.begin(), base16.end());
} else {
hex::println("Unknown algorithm: {}", algorithm);
hex::println("Available algorithms: base64, hex");
hex::log::println("Unknown algorithm: {}", algorithm);
hex::log::println("Available algorithms: base64, hex");
std::exit(EXIT_FAILURE);
}
hex::print("decode_{}({}) = {}", algorithm, args[1], result);
hex::log::print("decode_{}({}) = {}", algorithm, args[1], result);
std::exit(EXIT_SUCCESS);
}
void handleMagicCommand(const std::vector<std::string> &args) {
if (args.size() != 2) {
hex::println("usage: imhex --magic <operation> <file>");
hex::println("Available operations: mime, desc");
hex::log::println("usage: imhex --magic <operation> <file>");
hex::log::println("Available operations: mime, desc");
std::exit(EXIT_FAILURE);
}
if (!magic::compile()) {
hex::print("Failed to compile magic database!");
hex::log::print("Failed to compile magic database!");
std::exit(EXIT_FAILURE);
}
@ -242,7 +242,7 @@ namespace hex::plugin::builtin {
wolv::io::File file(filePath, wolv::io::File::Mode::Read);
if (!file.isValid()) {
hex::println("Failed to open file: {}", wolv::util::toUTF8String(filePath));
hex::log::println("Failed to open file: {}", wolv::util::toUTF8String(filePath));
std::exit(EXIT_FAILURE);
}
@ -250,13 +250,13 @@ namespace hex::plugin::builtin {
if (operation == "mime") {
auto result = magic::getMIMEType(data);
hex::println("{}", result);
hex::log::println("{}", result);
} else if (operation == "desc") {
auto result = magic::getDescription(data);
hex::println("{}", result);
hex::log::println("{}", result);
} else {
hex::println("Unknown operation: {}", operation);
hex::println("Available operations: mime, desc");
hex::log::println("Unknown operation: {}", operation);
hex::log::println("Available operations: mime, desc");
std::exit(EXIT_FAILURE);
}

View File

@ -52,7 +52,7 @@ namespace hex::plugin::builtin {
return hex::format("hex.builtin.command.cmd.result"_lang, input.data());
},
[](auto input) {
hex::runCommand(input);
hex::executeCommand(input);
});
ContentRegistry::CommandPaletteCommands::addHandler(

View File

@ -211,7 +211,7 @@ namespace hex::plugin::builtin {
ImGui::UnderlinedText("hex.builtin.welcome.header.update"_lang);
{
if (ImGui::DescriptionButton("hex.builtin.welcome.update.title"_lang, hex::format("hex.builtin.welcome.update.desc"_lang, ImHexApi::System::getInitArguments()["update-available"]).c_str(), ImVec2(ImGui::GetContentRegionAvail().x * 0.8F, 0)))
hex::openWebpage("hex.builtin.welcome.update.link"_lang);
ImHexApi::System::updateImHex(ImHexApi::System::UpdateType::Stable);
}
}

View File

@ -19,9 +19,8 @@ GLFW_ICON ICON dist/windows/icon.ico
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "🔍 A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM."
VALUE "CompanyName", "WerWolv"
VALUE "FileDescription", "ImHex Hex Editor"
VALUE "FileDescription", "ImHex Hex Editor 🔍"
VALUE "LegalCopyright", "WerWolv 2020-2023"
VALUE "OriginalFilename", "imhex.exe"
VALUE "ProductName", "ImHex"