From d371903a7dd21f3eb3c546dbf24a1a5052823175 Mon Sep 17 00:00:00 2001 From: Nir Izraeli Date: Sat, 18 Mar 2017 23:19:03 +0200 Subject: [PATCH 1/2] Rename 'dialog' to 'ui', make it a parameter Signed-off-by: Nir Izraeli --- idaplugin/rematch/actions/base.py | 50 ++++++++++++--------------- idaplugin/rematch/actions/login.py | 21 +++++------ idaplugin/rematch/actions/project.py | 3 -- idaplugin/rematch/actions/settings.py | 3 -- idaplugin/rematch/plugin.py | 14 ++++---- 5 files changed, 40 insertions(+), 51 deletions(-) diff --git a/idaplugin/rematch/actions/base.py b/idaplugin/rematch/actions/base.py index 49809eba5..350e422de 100755 --- a/idaplugin/rematch/actions/base.py +++ b/idaplugin/rematch/actions/base.py @@ -7,20 +7,19 @@ class Action(idaapi.action_handler_t): """Actions are objects registered to IDA's interface and added to the rematch menu and toolbar""" - dialog = None - reject_handler = None finish_handler = None submit_handler = None response_handler = None exception_handler = None - def __init__(self): + def __init__(self, ui_class): self._icon = None - self.dlg = None + self.ui_class = ui_class + self.ui = None def __repr__(self): - return "".format(self.get_id()) + return "".format(self.get_id(), self.ui_class) def __del__(self): if self._icon: @@ -81,23 +80,20 @@ def get_action_path(self): return '/'.join(t) - @classmethod - def register(cls): - action = cls() - r = idaapi.register_action(action.get_desc()) + def register(self): + r = idaapi.register_action(self.get_desc()) if not r: - log('actions').warn("failed registering %s: %s", cls, r) + log('actions').warn("failed registering %s: %s", self, r) return idaapi.attach_action_to_menu( - action.get_action_path(), - action.get_id(), + self.get_action_path(), + self.get_id(), idaapi.SETMENU_APP) r = idaapi.attach_action_to_toolbar( "AnalysisToolBar", - action.get_id()) + self.get_id()) if not r: - log('actions').warn("registration of %s failed: %s", cls, r) - return action + log('actions').warn("registration of %s failed: %s", self, r) def update(self, ctx): return idaapi.AST_ENABLE if self.enabled(ctx) else idaapi.AST_DISABLE @@ -107,25 +103,25 @@ def activate(self, ctx): if self.running(): return - if callable(self.dialog): - self.dlg = self.dialog(reject_handler=self.reject_handler, - submit_handler=self.submit_handler, - response_handler=self.response_handler, - exception_handler=self.exception_handler) + if callable(self.ui_class): + self.ui = self.ui_class(reject_handler=self.reject_handler, + submit_handler=self.submit_handler, + response_handler=self.response_handler, + exception_handler=self.exception_handler) if self.finish_handler: - self.dlg.finished.connect(self.finish_handler) - self.dlg.finished.connect(self.close_dialog) - self.dlg.finished.connect(self.force_update) - self.dlg.show() + self.ui.finished.connect(self.finish_handler) + self.ui.finished.connect(self.close_dialog) + self.ui.finished.connect(self.force_update) + self.ui.show() else: log('actions').warn("%s: no activation", self.__class__) def running(self): - return self.dlg is not None + return self.ui is not None def close_dialog(self): - del self.dlg - self.dlg = None + del self.ui + self.ui = None @staticmethod def force_update(): diff --git a/idaplugin/rematch/actions/login.py b/idaplugin/rematch/actions/login.py index a235ddb4e..7799b220d 100755 --- a/idaplugin/rematch/actions/login.py +++ b/idaplugin/rematch/actions/login.py @@ -3,16 +3,13 @@ from .. import config from .. import exceptions -from ..dialogs.login import LoginDialog - class LoginAction(base.UnauthAction): name = "&Login" group = "User" - dialog = LoginDialog - def __init__(self): - super(LoginAction, self).__init__() + def __init__(self, *args, **kwargs): + super(LoginAction, self).__init__(*args, **kwargs) self.username = None self.password = None self.server = None @@ -34,8 +31,8 @@ def submit_handler(self, username, password, server, remember): def handle_login(self, response): del response - self.dlg.statusLbl.setText("Connected!") - self.dlg.statusLbl.setStyleSheet("color: green;") + self.ui.statusLbl.setText("Connected!") + self.ui.statusLbl.setStyleSheet("color: green;") config['login']['username'] = self.username config['login']['server'] = self.server @@ -45,17 +42,17 @@ def handle_login(self, response): config['login']['password'] = "" config.save() - self.dlg.accept() + self.ui.accept() def handle_exception(self, exception): if isinstance(exception, (exceptions.ConnectionException, exceptions.ServerException)): - self.dlg.statusLbl.setText("Connection to server failed.") - self.dlg.statusLbl.setStyleSheet("color: blue;") + self.ui.statusLbl.setText("Connection to server failed.") + self.ui.statusLbl.setStyleSheet("color: blue;") elif isinstance(exception, (exceptions.QueryException, exceptions.AuthenticationException)): - self.dlg.statusLbl.setText("Invalid user name or password.") - self.dlg.statusLbl.setStyleSheet("color: red;") + self.ui.statusLbl.setText("Invalid user name or password.") + self.ui.statusLbl.setStyleSheet("color: red;") class LogoutAction(base.AuthAction): diff --git a/idaplugin/rematch/actions/project.py b/idaplugin/rematch/actions/project.py index 4906d2fa4..be1885677 100755 --- a/idaplugin/rematch/actions/project.py +++ b/idaplugin/rematch/actions/project.py @@ -1,5 +1,4 @@ from . import base -from ..dialogs.project import AddProjectDialog, AddFileDialog from .. import netnode from .. import network @@ -8,7 +7,6 @@ class AddProjectAction(base.AuthAction): name = "&Add project" group = "Project" - dialog = AddProjectDialog @staticmethod def submit_handler(name, description, private, bind_current): @@ -31,7 +29,6 @@ def response_handler(cls, response): class AddFileAction(base.UnboundFileAction): name = "&Add file" group = "Project" - dialog = AddFileDialog @staticmethod def submit_handler(project, name, md5hash, description, shareidb): diff --git a/idaplugin/rematch/actions/settings.py b/idaplugin/rematch/actions/settings.py index d1b4bdb89..084e086a6 100755 --- a/idaplugin/rematch/actions/settings.py +++ b/idaplugin/rematch/actions/settings.py @@ -3,12 +3,9 @@ from . import base from .. import config -from ..dialogs.settings import SettingsDialog - class SettingsAction(base.Action): name = "&Settings" - dialog = SettingsDialog @staticmethod def submit_handler(autocheck, autoupdate, autologin, autologout, debug): diff --git a/idaplugin/rematch/plugin.py b/idaplugin/rematch/plugin.py index ad8208227..98ad74fb6 100755 --- a/idaplugin/rematch/plugin.py +++ b/idaplugin/rematch/plugin.py @@ -4,6 +4,7 @@ from . import config, user from . import actions +from . import dialogs from . import update @@ -47,15 +48,16 @@ def setup(self): self.menu = QtWidgets.QMenu("Rematch") self.get_mainwindow().menuWidget().addMenu(self.menu) - actions.login.LoginAction.register() - actions.login.LogoutAction.register() + actions.login.LoginAction(dialogs.login.LoginDialog).register() + actions.login.LogoutAction(None).register() - actions.project.AddProjectAction.register() - actions.project.AddFileAction.register() + actions.project.AddProjectAction(dialogs.project. + AddProjectDialog).register() + actions.project.AddFileAction(dialogs.project.AddFileDialog).register() - actions.match.MatchAction.register() + actions.match.MatchAction(dialogs.match.MatchDialog).register() - actions.settings.SettingsAction.register() + actions.settings.SettingsAction(dialogs.settings.SettingsDialog).register() # set up status bar self.statusbar_label = QtWidgets.QLabel("Rematch loaded") From 60fcaee1de3a352776c18d93b7a5ac1219975a81 Mon Sep 17 00:00:00 2001 From: Nir Izraeli Date: Sun, 26 Mar 2017 02:07:19 +0300 Subject: [PATCH 2/2] Split IDAAction out of Action, seperate generic action related concepts from IDA's internals Signed-off-by: Nir Izraeli --- idaplugin/rematch/actions/base.py | 30 ++++++++++++++++++--------- idaplugin/rematch/actions/settings.py | 2 +- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/idaplugin/rematch/actions/base.py b/idaplugin/rematch/actions/base.py index 350e422de..dc1de6c5a 100755 --- a/idaplugin/rematch/actions/base.py +++ b/idaplugin/rematch/actions/base.py @@ -4,9 +4,7 @@ import idc -class Action(idaapi.action_handler_t): - """Actions are objects registered to IDA's interface and added to the - rematch menu and toolbar""" +class Action(): reject_handler = None finish_handler = None submit_handler = None @@ -14,14 +12,29 @@ class Action(idaapi.action_handler_t): exception_handler = None def __init__(self, ui_class): - self._icon = None self.ui_class = ui_class self.ui = None + def __repr__(self): + return "".format(self.ui_class) + + def running(self): + return self.ui is not None + + +class IDAAction(idaapi.action_handler_t, Action): + """Actions are objects registered to IDA's interface and added to the + rematch menu and toolbar""" + + def __init__(self, *args, **kwargs): + super(IDAAction, self).__init__(*args, **kwargs) + self._icon = None + def __repr__(self): return "".format(self.get_id(), self.ui_class) def __del__(self): + super(IDAAction, self).__del__() if self._icon: idaapi.free_custom_icon(self._icon) @@ -116,9 +129,6 @@ def activate(self, ctx): else: log('actions').warn("%s: no activation", self.__class__) - def running(self): - return self.ui is not None - def close_dialog(self): del self.ui self.ui = None @@ -132,7 +142,7 @@ def force_update(): idaapi.request_refresh(iwid_all) -class IdbAction(Action): +class IdbAction(IDAAction): """This action is only available when an idb file is loaded""" @staticmethod def enabled(ctx): @@ -140,7 +150,7 @@ def enabled(ctx): return bool(idc.GetIdbPath()) -class UnauthAction(Action): +class UnauthAction(IDAAction): """This action is only available when a user is logged off""" @staticmethod def enabled(ctx): @@ -148,7 +158,7 @@ def enabled(ctx): return not bool(user['is_authenticated']) -class AuthAction(Action): +class AuthAction(IDAAction): """This action is only available when a user is logged in""" @staticmethod def enabled(ctx): diff --git a/idaplugin/rematch/actions/settings.py b/idaplugin/rematch/actions/settings.py index 084e086a6..fcb9b41db 100755 --- a/idaplugin/rematch/actions/settings.py +++ b/idaplugin/rematch/actions/settings.py @@ -4,7 +4,7 @@ from .. import config -class SettingsAction(base.Action): +class SettingsAction(base.IDAAction): name = "&Settings" @staticmethod