binaryninja/
repository.rs

1//! Interaction with plugin repositories to install and manage plugins.
2
3mod manager;
4mod plugin;
5
6use std::ffi::c_char;
7use std::fmt::Debug;
8use std::path::{Path, PathBuf};
9use std::ptr::NonNull;
10
11use binaryninjacore_sys::*;
12
13use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
14use crate::string::{BnString, IntoCStr};
15
16pub use manager::RepositoryManager;
17pub use plugin::{
18    Extension, ExtensionVersion, ExtensionVersionPlatform, PluginDependencyConflict,
19    PluginDependencyConflictStatus, PluginDependencyRequirement,
20};
21
22pub type PluginType = BNPluginType;
23pub type PluginStatus = BNPluginStatus;
24
25#[repr(transparent)]
26pub struct Repository {
27    handle: NonNull<BNRepository>,
28}
29
30impl Repository {
31    pub(crate) unsafe fn from_raw(handle: NonNull<BNRepository>) -> Self {
32        Self { handle }
33    }
34
35    pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNRepository>) -> Ref<Self> {
36        Ref::new(Self { handle })
37    }
38
39    /// String URL of the git repository where the plugin repository's are stored
40    pub fn url(&self) -> String {
41        let result = unsafe { BNRepositoryGetUrl(self.handle.as_ptr()) };
42        assert!(!result.is_null());
43        unsafe { BnString::into_string(result as *mut c_char) }
44    }
45
46    /// String local path to store the given plugin repository
47    pub fn path(&self) -> PathBuf {
48        let result = unsafe { BNRepositoryGetRepoPath(self.handle.as_ptr()) };
49        assert!(!result.is_null());
50        let result_str = unsafe { BnString::into_string(result as *mut c_char) };
51        PathBuf::from(result_str)
52    }
53
54    /// List of RepoPlugin objects contained within this repository
55    pub fn plugins(&self) -> Array<Extension> {
56        let mut count = 0;
57        let result = unsafe { BNRepositoryGetPlugins(self.handle.as_ptr(), &mut count) };
58        assert!(!result.is_null());
59        unsafe { Array::new(result, count, ()) }
60    }
61
62    pub fn plugin_by_path(&self, path: &Path) -> Option<Ref<Extension>> {
63        let path = path.to_cstr();
64        let result = unsafe { BNRepositoryGetPluginByPath(self.handle.as_ptr(), path.as_ptr()) };
65        NonNull::new(result).map(|h| unsafe { Extension::ref_from_raw(h) })
66    }
67
68    /// String full path the repository
69    pub fn full_path(&self) -> PathBuf {
70        let result = unsafe { BNRepositoryGetPluginsPath(self.handle.as_ptr()) };
71        assert!(!result.is_null());
72        let result_str = unsafe { BnString::into_string(result as *mut c_char) };
73        PathBuf::from(result_str)
74    }
75}
76
77impl Debug for Repository {
78    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79        f.debug_struct("Repository")
80            .field("url", &self.url())
81            .field("path", &self.path())
82            .field("full_path", &self.full_path())
83            .field("plugins", &self.plugins().to_vec())
84            .finish()
85    }
86}
87
88impl ToOwned for Repository {
89    type Owned = Ref<Self>;
90
91    fn to_owned(&self) -> Self::Owned {
92        unsafe { <Self as RefCountable>::inc_ref(self) }
93    }
94}
95
96unsafe impl RefCountable for Repository {
97    unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
98        Self::ref_from_raw(NonNull::new(BNNewRepositoryReference(handle.handle.as_ptr())).unwrap())
99    }
100
101    unsafe fn dec_ref(handle: &Self) {
102        BNFreeRepository(handle.handle.as_ptr())
103    }
104}
105
106impl CoreArrayProvider for Repository {
107    type Raw = *mut BNRepository;
108    type Context = ();
109    type Wrapped<'a> = Guard<'a, Self>;
110}
111
112unsafe impl CoreArrayProviderInner for Repository {
113    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
114        BNFreeRepositoryManagerRepositoriesList(raw)
115    }
116
117    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
118        Guard::new(Self::from_raw(NonNull::new(*raw).unwrap()), context)
119    }
120}
121
122impl CoreArrayProvider for PluginType {
123    type Raw = BNPluginType;
124    type Context = ();
125    type Wrapped<'a> = Self;
126}
127
128unsafe impl CoreArrayProviderInner for PluginType {
129    unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
130        BNFreePluginTypes(raw)
131    }
132
133    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
134        *raw
135    }
136}