Skip to content

Commit 508ac32

Browse files
committed
finishing config function and upload solidify.
1 parent ab5cc11 commit 508ac32

19 files changed

Lines changed: 447 additions & 82 deletions

__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
from .revengai import RevengAIPlugin
33

44
plugin = RevengAIPlugin()
5-
log_info("RevEng.AI Plugin loaded successfully")
5+
log_info("RevEng.AI | Plugin loaded successfully")

features/base_auth_feature.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from abc import ABC, abstractmethod
2+
from binaryninja import BinaryView
3+
4+
class BaseAuthFeature(ABC):
5+
def __init__(self, config=None):
6+
self.config = config
7+
8+
@abstractmethod
9+
def register(self):
10+
pass
11+
12+
def is_valid(self, bv: BinaryView):
13+
return self.config.is_configured == "True"

features/configuration/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
from binaryninja import PluginCommand, log_info
22
from .config import Config
3-
from .config_dialog import ApiKeyWizard
3+
from .config_dialog import ConfigDialog
4+
from ..base_auth_feature import BaseAuthFeature
45

5-
class ConfigurationFeature:
6+
class ConfigurationFeature():
67
def __init__(self):
78
self.config = Config()
8-
log_info("RevEng.AI Configuration Feature initialized")
9+
log_info("RevEng.AI | Configuration Feature initialized")
910

1011
def register(self):
1112
PluginCommand.register(
1213
"RevEng.AI\\Configure",
1314
"Configure RevEng.AI settings",
1415
self.show_configuration
1516
)
16-
log_info("RevEng.AI Configuration Feature registered")
17-
17+
1818
def show_configuration(self, bv):
19-
log_info("Opening RevEng.AI configuration wizard")
20-
wizard = ApiKeyWizard(self.config)
19+
log_info("RevEng.AI | Opening configuration wizard")
20+
wizard = ConfigDialog(self.config)
2121
wizard.exec_()
22-
22+
2323
def get_config(self):
2424
return self.config

features/configuration/config.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def __init__(self):
77
self.api_key = ""
88
self.host = ""
99
self.current_analysis = None
10+
self.is_configured = None
1011
self._load_config()
1112

1213

@@ -28,42 +29,45 @@ def _load_config(self):
2829
"type" : "string",\
2930
"default" : "",\
3031
"description" : "Current Analysis ID"}')
32+
settings.register_setting("revengai.is_configured",
33+
'{"title" : "Is Configured",\
34+
"type" : "string",\
35+
"default" : "False",\
36+
"description" : "Configuration Status"}')
3137

3238
self.host = settings.get_string("revengai.host", None)
3339
self.api_key = settings.get_string("revengai.api_key", None)
3440
self.current_analysis = settings.get_string("revengai.current_analysis", None)
41+
self.is_configured = settings.get_string("revengai.is_configured", None)
3542

3643
re_conf["apikey"] = self.api_key
3744
re_conf["host"] = self.host
3845

3946

4047
def save_config(self) -> bool:
41-
log_info(f"Saving configuration: {self.host} {self.api_key[:4]}...")
42-
if self.current_analysis:
43-
settings.set_string("revengai.current_analysis", self.current_analysis)
44-
4548
try:
49+
log_info(f"RevEng.AI | Testing configuration: {self.host} {self.api_key[:4]}...")
4650
re_conf["apikey"] = self.api_key
4751
re_conf["host"] = self.host
48-
log_info(f"Saving configuration: {re_conf['apikey']} {re_conf['host']}")
4952
RE_authentication()
50-
log_info(f"Authentication successful")
53+
log_info("RevEng.AI | Authentication successful!")
54+
self.is_configured = "True"
55+
5156
settings = Settings()
5257
settings.set_string("revengai.host", self.host)
5358
settings.set_string("revengai.api_key", self.api_key)
59+
settings.set_string("revengai.is_configured", self.is_configured)
60+
5461
return True
5562

5663
except Exception as e:
57-
log_info(f"Failed to save API key: {str(e)}")
64+
log_info(f"RevEng.AI | Failed to save API key: {str(e)}")
5865
return False
5966

6067

6168
def clear_config(self):
6269
self.api_key = ""
6370
self.host = ""
6471
self.current_analysis = None
72+
self.is_configured = False
6573
self.save_config()
66-
67-
68-
def is_configured(self):
69-
return bool(self.api_key and self.host)

features/configuration/config_dialog.py

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,39 @@
11
from PySide6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
22
QLineEdit, QPushButton, QMessageBox, QProgressDialog, QProgressBar)
3-
from PySide6.QtCore import Qt
3+
from PySide6.QtCore import Qt, QThread, Signal
44
from PySide6.QtGui import QPixmap
55
from binaryninja import log_info, log_error, log_warn
66
import os
77

8-
class ApiKeyWizard(QDialog):
8+
class ConfigSaveThread(QThread):
9+
finished = Signal(bool, str)
10+
11+
def __init__(self, config, api_key, host):
12+
super().__init__()
13+
self.config = config
14+
self.api_key = api_key
15+
self.host = host
16+
17+
def run(self):
18+
try:
19+
self.config.api_key = self.api_key
20+
self.config.host = self.host
21+
success = self.config.save_config()
22+
23+
if not success:
24+
self.finished.emit(False, "API key not valid or host not reachable.")
25+
else:
26+
self.finished.emit(True, "")
27+
28+
except Exception as e:
29+
self.finished.emit(False, str(e))
30+
31+
class ConfigDialog(QDialog):
932
def __init__(self, config):
1033
super().__init__()
1134
self.config = config
35+
self.save_thread = None
36+
self.progress = None
1237
self.init_ui()
1338

1439
def init_ui(self):
@@ -98,7 +123,7 @@ def save_config(self):
98123
host = self.host_input.text().strip()
99124

100125
if not api_key:
101-
log_warn("API Key field is empty")
126+
log_warn("RevEng.AI | API Key field is empty")
102127
QMessageBox.warning(
103128
self,
104129
"RevEng.AI Configuration",
@@ -108,7 +133,7 @@ def save_config(self):
108133
return
109134

110135
if not host:
111-
log_warn("Host URL field is empty")
136+
log_warn("RevEng.AI | Host URL field is empty")
112137
QMessageBox.warning(
113138
self,
114139
"RevEng.AI Configuration",
@@ -117,63 +142,53 @@ def save_config(self):
117142
)
118143
return
119144

120-
try:
121-
progress = QProgressDialog("Testing API key...", None, 0, 0, self)
122-
progress.setWindowTitle("RevEng.AI Configuration")
123-
progress.setWindowModality(Qt.WindowModal)
124-
progress.setCancelButton(None)
125-
progress.setMinimumWidth(400)
126-
progress.setMinimumHeight(100)
127-
progress.findChild(QProgressBar).setMinimumWidth(250)
128-
progress.findChild(QProgressBar).setMinimumHeight(20)
129-
progress.setStyleSheet("""
130-
QProgressDialog {
131-
background-color: white;
132-
color: black;
133-
}
134-
QProgressBar {
135-
border: 1px solid #cccccc;
136-
border-radius: 4px;
137-
text-align: center;
138-
background-color: #f0f0f0;
139-
min-width: 250px;
140-
min-height: 20px;
141-
}
142-
QProgressBar::chunk {
143-
background-color: #007bff;
144-
border-radius: 3px;
145-
}
146-
QLabel {
147-
color: black;
148-
font-size: 13px;
149-
padding: 10px;
150-
}
151-
""")
152-
progress.show()
153-
154-
self.config.api_key = api_key
155-
self.config.host = host
156-
key_try = self.config.save_config()
157-
158-
progress.close()
159-
160-
if not key_try:
161-
raise Exception("API key not valid or host not reachable.")
162-
163-
log_info("RevEng.AI configuration saved successfully!")
145+
# Create and show progress dialog
146+
self.progress = QProgressDialog("Testing API key...", None, 0, 0, self)
147+
self.progress.setWindowTitle("RevEng.AI Configuration")
148+
self.progress.setWindowModality(Qt.WindowModal)
149+
self.progress.setCancelButton(None)
150+
self.progress.setMinimumWidth(400)
151+
self.progress.setMinimumHeight(100)
152+
self.progress.findChild(QProgressBar).setMinimumWidth(250)
153+
self.progress.findChild(QProgressBar).setMinimumHeight(20)
154+
self.progress.setStyleSheet("""
155+
QProgressBar {
156+
border: 1px solid #cccccc;
157+
border-radius: 4px;
158+
text-align: center;
159+
background-color: #f0f0f0;
160+
min-width: 250px;
161+
min-height: 20px;
162+
}
163+
QProgressBar::chunk {
164+
background-color: #007bff;
165+
border-radius: 3px;
166+
}
167+
""")
168+
169+
self.save_thread = ConfigSaveThread(self.config, api_key, host)
170+
self.save_thread.finished.connect(self._on_save_finished)
171+
self.save_thread.start()
172+
173+
self.progress.show()
174+
175+
def _on_save_finished(self, success, error_message):
176+
self.progress.close()
177+
178+
if success:
179+
log_info("RevEng.AI | Configuration saved successfully!")
164180
QMessageBox.information(
165181
self,
166182
"RevEng.AI Configuration",
167183
"Configuration saved successfully!\nYou can now start using RevEng.AI services.",
168184
QMessageBox.Ok
169185
)
170186
self.accept()
171-
172-
except Exception as e:
173-
log_error(f"Failed to save RevEng.AI configuration: {str(e)}")
187+
else:
188+
log_error(f"RevEng.AI | Failed to save configuration: {error_message}")
174189
QMessageBox.critical(
175190
self,
176191
"RevEng.AI Configuration Error",
177-
f"Failed to save configuration: {str(e)}",
192+
f"Failed to save configuration: {error_message}",
178193
QMessageBox.Ok
179194
)

features/upload/__init__.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
from binaryninja import PluginCommand, log_info, log_error
1+
from binaryninja import PluginCommand, log_info, BinaryView
22
from .upload import BinaryUploader
33
from .upload_dialog import UploadDialog
4-
from ...utils.config_validator import validate_config
4+
from ..base_auth_feature import BaseAuthFeature
55

6-
class UploadFeature:
6+
class UploadFeature(BaseAuthFeature):
77
def __init__(self, config=None):
8-
self.config = config
8+
super().__init__(config)
99
self.uploader = BinaryUploader(config)
10-
log_info("RevEng.AI Process Feature initialized")
10+
log_info("RevEng.AI | Process Feature initialized")
1111

1212
def register(self):
1313
PluginCommand.register(
1414
"RevEng.AI\\Process Binary",
1515
"Process current binary to RevEng.AI for analysis",
16-
self.show_upload_dialog
16+
self.show_upload_dialog,
17+
self.is_valid
1718
)
18-
log_info("RevEng.AI Process feature registered")
19+
log_info("RevEng.AI | Process Feature registered")
1920

2021
def show_upload_dialog(self, bv):
21-
if not validate_config(self.config):
22-
return
2322
dialog = UploadDialog(self.config, self.uploader, bv)
2423
if dialog.exec() == UploadDialog.Accepted:
2524
self.uploader.upload_binary(bv, dialog.get_upload_options())

features/upload/upload.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ def get_models(self):
1717

1818
def upload_binary(self, bv: BinaryView, options: dict):
1919
try:
20+
log_info(f"Uploading binary {bv.file.filename} with options: {options}")
21+
log_info(f"Options: {options}")
22+
log_info(f"Binary size: {bv.file}")
2023

2124
# TODO: Implement actual upload logic here
2225
# This will involve:

revengai.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44

55
class RevengAIPlugin:
66
def __init__(self):
7-
log_info("Initializing RevEng.AI Plugin")
7+
log_info("RevEng.AI | Initializing plugin")
88
self.config_feature = ConfigurationFeature()
99
self.upload_feature = UploadFeature(self.config_feature.get_config())
1010
self._register_features()
1111

1212
def _register_features(self):
13+
log_info("RevEng.AI | Registering features")
1314
self.config_feature.register()
1415
self.upload_feature.register()
1516

tests/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Test package for RevEng.AI Binary Ninja plugin.
3+
"""
2.4 KB
Binary file not shown.

0 commit comments

Comments
 (0)