diff options
| author | Brian Potchik <brian@vector35.com> | 2026-03-30 08:50:13 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2026-03-30 08:51:28 -0400 |
| commit | 5a99579b1a903d3738bb82450ec40c52f1ea5594 (patch) | |
| tree | d8fa40427b662ea8d04d101180b82681b231347e | |
| parent | e5c73ffdf3d1914596f0ffd1c989330657934627 (diff) | |
This reverts commit 7228ba0b889765bc3474fbd5475870e24efc79ca.
| -rw-r--r-- | ui/containerbrowser.h | 5 | ||||
| -rw-r--r-- | ui/containeropenrequest.h | 47 | ||||
| -rw-r--r-- | view/macho/universaltransform.cpp | 9 |
3 files changed, 57 insertions, 4 deletions
diff --git a/ui/containerbrowser.h b/ui/containerbrowser.h index 363e5446..b9ba278f 100644 --- a/ui/containerbrowser.h +++ b/ui/containerbrowser.h @@ -15,6 +15,7 @@ #include <vector> +class ContainerOpenRequest; class ContainerTreeModel : public QAbstractItemModel { @@ -121,4 +122,8 @@ public: bool openWithOptionsRequested() const { return m_openWithOptionsRequested; } static std::vector<TransformContextRef> openContainerFile(const QString& path, bool forceShowDialog = false, bool* outOpenWithOptions = nullptr); + + // Show the container browser dialog for the given open request. + // Returns the selected contexts, or empty if the user cancelled. + static std::vector<TransformContextRef> showBrowser(ContainerOpenRequest& request, bool* outOpenWithOptions = nullptr); }; diff --git a/ui/containeropenrequest.h b/ui/containeropenrequest.h new file mode 100644 index 00000000..5067534d --- /dev/null +++ b/ui/containeropenrequest.h @@ -0,0 +1,47 @@ +#pragma once + +#include "uitypes.h" + +#include <optional> +#include <string> +#include <vector> + + +// Captures user settings and intent for opening a container file, and provides +// policy decisions (e.g. whether to show the container browser) after processing. +class BINARYNINJAUIAPI ContainerOpenRequest +{ +public: + enum Action { + Cancel, + AutoOpen, + BrowseContainer, + SelectArchitecture, + }; + + explicit ContainerOpenRequest(const std::string& path, bool forceContainerBrowser = false); + + TransformSessionRef session() const { return m_session; } + + // Create the session, process it, and determine what action the caller + // should take. Returns Cancel if the session could not be created. + Action resolve(); + + // Get the default selection from a processed session. If no selection has + // been made (e.g. because the session auto-opened), selects the current leaf. + std::vector<TransformContextRef> selectedContexts(); + + // When the container is a universal binary, the available architectures and the + // index of the preferred one (if any). + const std::vector<TransformContextRef>& architectureContexts() const { return m_archContexts; } + std::optional<size_t> preferredArchitectureIndex() const { return m_preferredArch; } + +private: + Action resolveUniversal(TransformContextRef universalCtx); + + TransformSessionRef m_session; + std::vector<TransformContextRef> m_archContexts; + std::optional<size_t> m_preferredArch; + bool m_forceContainerBrowser = false; + bool m_autoOpen = false; +}; diff --git a/view/macho/universaltransform.cpp b/view/macho/universaltransform.cpp index 3309d853..33164215 100644 --- a/view/macho/universaltransform.cpp +++ b/view/macho/universaltransform.cpp @@ -266,19 +266,20 @@ bool UniversalTransform::DecodeWithContext(Ref<TransformContext> context, const architectures.push_back(archName); } - if (!context->IsInteractive()) + // TODO: It is surprising that this is UniversalTransform's responsibility. + if (!BinaryNinja::IsUIEnabled()) { + // When headless, filter to the preferred architecture if one is configured. vector<string> archPref = context->GetSettings()->Get<vector<string>>("files.universal.architecturePreference"); if (auto result = find_first_of(archPref.begin(), archPref.end(), architectures.begin(), architectures.end()); result != archPref.end()) { - // Filter to preferred architecture to support container auto-open policy size_t archIndex = find(architectures.begin(), architectures.end(), *result) - architectures.begin(); context->SetAvailableFiles({architectures[archIndex]}); return false; } - // Preserve original headless load behavior when no architecturePreference is specified - if (!BinaryNinja::IsUIEnabled() && archPref.empty() && architectures.size()) + // Load the first architecture if no preference is found. + if (archPref.empty() && architectures.size()) { context->SetAvailableFiles({architectures[0]}); return false; |
