Exemple #1
0
    def __init__(self,parent):
        super(HelpDialog,self).__init__(parent)

        title = _("A bit of help")
        self.setWindowTitle(title)
        top_layout = QVBoxLayout()
        self.title_widget = TitleWidget(title,self)
        top_layout.addWidget(self.title_widget)

        browser = QTextBrowser()

        import os.path
        from koi.Configurator import resource_dir

        with open( os.path.join(resource_dir,"manual.html"), encoding='utf-8') as input:
            html = input.read()
        browser.setHtml(html)

        # browser.setLineWrapMode(QTextEdit.NoWrap)
        #         browser.setHtml("""<h1>Tables</h1>
        #
        # In tables you can edit, don't forget these few useful shortcuts :
        # <ul>
        # <li><b>F5</b> : will insert a line under your cursor</li>
        # <li><b>Shift + F5</b> : will append a line at the end of the table</li>
        # <li><b>F8</b> : will delete the line under your cursor (if you're allowed to)</li>
        # <li><b>F1</b> and <b>Shift + F1</b> : will allow you to move up/move down a row </li>
        # </ul>
        # """)
        # browser.setMinimumWidth(browser.document().documentLayout().documentSize().toSize().width())
        browser.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        top_layout.addWidget(browser)

        self.buttons = QDialogButtonBox()
        self.buttons.addButton( QDialogButtonBox.Ok)

        top_layout.addWidget(self.buttons)
        self.setLayout(top_layout)
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)
Exemple #2
0
class Form(QMainWindow):
    def __init__(self, title, message, parent=None):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        self.setWindowTitle("{} — {}".format(title,
                                             QApplication.applicationName()))
        self.browser = QTextBrowser()
        self.browser.setOpenExternalLinks(False)
        self.browser.setOpenLinks(False)
        self.browser.setHtml(message)
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Close")
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.closeButton)
        hbox.addStretch()
        layout.addWidget(self.browser)
        layout.addLayout(hbox)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.browser.setFocus()
        self.closeButton.clicked.connect(self.close)
Exemple #3
0
class Form(QDialog):
    def __init__(self, state, parent=None):
        super().__init__(parent)
        self.setWindowModality(Qt.WindowModal)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.state = state
        self.createWidgets()
        self.layoutWidgets()
        self.initialize()
        if parent is not None:
            self.resize(max(400,
                            parent.width() // 2), max(400,
                                                      parent.height() // 3))
        self.setWindowTitle("Information — {}".format(
            QApplication.applicationName()))
        settings = QSettings()
        self.updateToolTips(
            bool(
                int(
                    settings.value(Gopt.Key.ShowDialogToolTips,
                                   Gopt.Default.ShowDialogToolTips))))

    def createWidgets(self):
        self.browser = QTextBrowser()
        self.tooltips.append((self.browser, """<p><b>Information</b></p>
<p>Show basic information about the current index.</p>"""))
        self.browser.zoomIn(1)
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Close")
        self.tooltips.append((self.closeButton, """<p><b>Close</b></p>
<p>Close the dialog.</p>"""))
        self.closeButton.clicked.connect(self.reject)

    def layoutWidgets(self):
        layout = QVBoxLayout()
        layout.addWidget(self.browser, 1)
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.closeButton)
        hbox.addStretch()
        layout.addLayout(hbox)
        self.setLayout(layout)

    def initialize(self):
        locale = QLocale()
        model = self.state.model
        if not bool(model):
            self.browser.setHtml("<font color=red>Information can only "
                                 "be shown if an index is open</font>")
            return

        top, total, _ = self.state.indicatorCounts()
        fullname = QDir.toNativeSeparators(os.path.abspath(model.filename))
        creator = model.config(Gconf.Key.Creator)
        created = model.config("Created")
        created = locale.toString(
            QDateTime.fromString(created, "yyyy-MM-dd HH:mm:ss"))
        updated = locale.toString(QFileInfo(model.filename).lastModified())
        size = os.path.getsize(model.filename)
        KB = 1024
        MB = KB * KB
        if size < MB:
            size = "~{:,} KB ({:,} bytes)".format(round(size / KB), size)
        else:
            size = "~{:,} MB ({:,} bytes)".format(round(size / MB), size)
        filename = re.sub(r"\.xix$", "", os.path.basename(fullname),
                          re.IGNORECASE)
        version = str(model.version())
        secs = self.state.workTime + int(time.monotonic() -
                                         self.state.startTime)
        hours, secs = divmod(secs, 3600)
        if hours:
            worktime = "{:,}h{}'".format(hours, secs // 60)
        else:
            worktime = "{}'".format(secs // 60)
        uuid = model.config(UUID)
        LEFT_STYLE = """ style="
margin-right: 0;
padding-right: 0;
spacing-right: 0;
border-right: 0;
"
"""
        RIGHT_STYLE = """ style="
margin-left: 0;
padding-left: 0;
spacing-left: 0;
border-left: 0;
"
"""
        color1 = "#DDDDFF"
        color2 = "#EEEEFF"
        STYLE = ' style="background-color: {};"'
        texts = [
            """<html><table border=0 style="
background-color: {};
">""".format(color1)
        ]
        for i, (name, value, right, debug) in enumerate((
            ("Index", filename, False, False),
            ("Creator", creator, False, False),
            ("Filename", fullname, False, False),
            ("Size", size, False, False),
            ("Created", created, False, False),
            ("Updated", updated, False, False),
            ("Total Entries", "{:,}".format(total), True, False),
            ("Main Entries", "{:,}".format(top), True, False),
            ("Subentries", "{:,}".format(total - top), True, False),
            ("Worktime", worktime, True, False),
            (None, None, False, False),
            ("Index Format", version, True, False),
            ("Index UUID", uuid, True, True),
        )):
            if debug and not self.state.window.debug:
                continue
            if name is None:
                color1 = "#EEEEEE"
                color2 = "#DDDDDD"
                continue
            style = STYLE.format(color1 if i % 2 == 0 else color2)
            align = " align=right" if right else ""
            texts.append("""<tr{}><td{}>{}&nbsp;&nbsp;</td>
<td{}{}>{}</td></tr>""".format(style, LEFT_STYLE, html.escape(name), align,
                               RIGHT_STYLE, html.escape(value)))
        texts.append("</table></html>")
        self.browser.setHtml("".join(texts))
Exemple #4
0
class Form(QMainWindow):

    requestGotoEid = Signal(str, int)  # uuid, eid

    def __init__(self, state, eids, uuid, name, parent=None):
        super().__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        self.setWindowTitle("Check “{}” — {}".format(
            name, QApplication.applicationName()))
        self.state = state
        self.uuid = uuid
        self.loadSaveSize = False
        self.createWidgets(eids, name)
        self.layoutWidgets()
        self.createConnections()
        self.browser.setFocus()

    def createWidgets(self, eids, name):
        self.browser = QTextBrowser()
        self.browser.setOpenExternalLinks(False)
        self.browser.setOpenLinks(False)
        text = ["<html>"]
        if not eids:
            text.append("<font color=darkgreen>No entries match the "
                        "“{}” check.</font>".format(name))
        else:
            self.loadSaveSize = True
            text.append("<p><font color=navy>{:,} entries match the "
                        "“{}” check.</font></p>".format(len(eids), name))
            for eid in eids:
                entry = self.state.model.entry(eid)
                if entry:
                    term = Lib.elidePatchHtml(entry.term, self.state)
                    prefix = "{} ".format(MAIN_INDICATOR if entry.peid ==
                                          ROOT else SUB_INDICATOR)
                    text.append('{}<a href="{}">{}</a><br>'.format(
                        prefix, eid, term))
        text.append("</html>")
        self.browser.setHtml("".join(text))
        self.closeButton = QPushButton(QIcon(":/dialog-close.svg"), "&Close")

    def layoutWidgets(self):
        layout = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addStretch()
        hbox.addWidget(self.closeButton)
        hbox.addStretch()
        layout.addWidget(self.browser)
        layout.addLayout(hbox)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        if self.loadSaveSize:
            settings = QSettings()
            self.resize(
                QSize(
                    settings.value(Gopt.Key.CheckForm_Size,
                                   Gopt.Default.CheckForm_Size)))

    def createConnections(self):
        self.browser.anchorClicked.connect(self.gotoEid)
        self.closeButton.clicked.connect(self.close)

    def closeEvent(self, event=None):
        if self.loadSaveSize:
            settings = QSettings()
            settings.setValue(Gopt.Key.CheckForm_Size, self.size())
        super().closeEvent(event)

    def gotoEid(self, link):
        self.requestGotoEid.emit(self.uuid, int(link.toString()))
Exemple #5
0
class WinApiWidget(QtGui.QWidget):
    """
    A widget for allowing easy access to Windows API information. Front-end to the I{idascope.core.WinApiProvider}.
    """

    def __init__(self, parent):
        QtGui.QWidget.__init__(self)
        print "[|] loading WinApiWidget"
        self.parent = parent
        self.name = "WinAPI Browsing"
        self.icon = QIcon(self.parent.config.icon_file_path + "winapi.png")
        self.search_icon = QIcon(self.parent.config.icon_file_path + "search.png")
        self.back_icon = QIcon(self.parent.config.icon_file_path + "back.png")
        self.forward_icon = QIcon(self.parent.config.icon_file_path + "forward.png")
        self.online_icon = QIcon(self.parent.config.icon_file_path + "online.png")
        self.ida_proxy = self.parent.ida_proxy
        self.QtGui = QtGui
        self.QtCore = QtCore
        self.winapi = self.parent.winapi_provider
        self.old_keyword_initial = ""
        self.winapi.registerDataReceiver(self.populateBrowserWindow)
        self._createGui()
        self._updateAvailability()
        self._registerHotkeys()

    def _updateAvailability(self):
        """
        Adjust the availability of this widget by checking if the keyword database has been loaded or
        online mode is enabled.
        """
        if not self.winapi.hasOfflineMsdnAvailable() and \
            not self.winapi.hasOnlineMsdnAvailable():
            self.browser_window.setHtml("<p><font color=\"#FF0000\">Offline MSDN database is not available. To use " \
                + "it, have a look at the installation instructions located in the manual: " \
                + "IDAscope/documentation/manual.html. Online mode is deactivated as well.</font></p>")
            self.search_button.setEnabled(False)
            self.api_chooser_lineedit.setEnabled(False)
        else:
            self.browser_window.setHtml("<p>Enter a search term in the above field to search offline/online MSDN.</p>")
            self.search_button.setEnabled(True)
            self.api_chooser_lineedit.setEnabled(True)

    def _registerHotkeys(self):
        """
        Register hotkeys with IDAscope in order to ease the use of this widget.
        """
        self.parent.registerHotkey(self.parent.config.winapi_shortcut, self._navigateToHighlightedIdentifier)

    def _createGui(self):
        """
        Create the GUI for this widget and all of its components.
        """
        self._createBackButton()
        self._createNextButton()
        self._createOnlineButton()
        self._createApiChooserLineedit()
        self._createSearchButton()
        self._createBrowserWindow()

        winapi_layout = QtGui.QVBoxLayout()
        selection_widget = QtGui.QWidget()
        selection_layout = QtGui.QHBoxLayout()
        selection_layout.addWidget(self.online_button)
        selection_layout.addWidget(self.back_button)
        selection_layout.addWidget(self.next_button)
        selection_layout.addWidget(self.api_chooser_lineedit)
        selection_layout.addWidget(self.search_button)
        selection_widget.setLayout(selection_layout)
        winapi_layout.addWidget(selection_widget)
        winapi_layout.addWidget(self.browser_window)
        self.setLayout(winapi_layout)

    def _createBackButton(self):
        """
        Create a back button to allow easier browsing
        """
        self.back_button = QtGui.QPushButton(self.back_icon, "", self)
        self.back_button.setToolTip("Go back to previously accessed content.")
        self.back_button.resize(self.back_button.sizeHint())
        self.back_button.setEnabled(False)
        self.back_button.clicked.connect(self._onBackButtonClicked)

    def _createNextButton(self):
        """
        Create a next button to allow easier browsing
        """
        self.next_button = QtGui.QPushButton(self.forward_icon, "", self)
        self.next_button.setToolTip("Go forward to previously accessed content.")
        self.next_button.resize(self.next_button.sizeHint())
        self.next_button.setEnabled(False)
        self.next_button.clicked.connect(self._onNextButtonClicked)

    def _createOnlineButton(self):
        """
        Create a next button to allow easier browsing
        """
        self.online_button = QtGui.QPushButton(self.online_icon, "", self)
        self.online_button.setCheckable(True)
        if self.winapi.hasOnlineMsdnAvailable():
            self.online_button.setChecked(QtCore.Qt.Checked)
        self.online_button.setToolTip("Enable/disable MSDN online lookup.")
        self.online_button.resize(self.online_button.sizeHint())
        self.online_button.clicked.connect(self._onOnlineButtonClicked)

    def _createApiChooserLineedit(self):
        """
        Create the I{QLineEdit }used for selecting API names. This includes a QCompleter to make suggestions based on
        the keyword database.
        """
        self.api_chooser_lineedit = QLineEdit()
        self.api_chooser_lineedit.returnPressed.connect(self.populateBrowserWindow)
        self.api_chooser_lineedit.textChanged.connect(self._updateCompleterModel)

        completer = QCompleter()
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        completer.setModelSorting(QCompleter.CaseSensitivelySortedModel)
        self.completer_model = QStringListModel([])
        completer.setModel(self.completer_model)
        self.api_chooser_lineedit.setCompleter(completer)

    def _createSearchButton(self):
        """
        Create a search button besides the QLineEdit.
        """
        self.search_button = QtGui.QPushButton(self.search_icon, "", self)
        self.search_button.setToolTip("Search for the chosen API name, structure or whatever WinAPI documentation " \
            + "might have for you.")
        self.search_button.resize(self.search_button.sizeHint())
        self.search_button.clicked.connect(self._onSearchButtonClicked)

    def _createBrowserWindow(self):
        """
        Create the browser window with a I{QTextBrowser}. This display component is chosen over I{QWebView} because
        WebKit is not included in the standard PySide installation as distributed with IDA Pro.
        """
        self.browser_window = QTextBrowser()
        self.browser_window.anchorClicked.connect(self._browserAnchorClicked)

    def _updateCompleterModel(self):
        """
        Update the completer model used to make suggestions. The model is only updated if anything is entered into the
        search line and the initial character differs from the previous initial character.
        """
        keyword_data = []
        api_chooser_text = self.api_chooser_lineedit.text()
        if len(api_chooser_text) > 0:
            keyword_initial = api_chooser_text[0].lower()
            if keyword_initial != self.old_keyword_initial:
                self.old_keyword_initial = keyword_initial
                keyword_data = self.winapi.getKeywordsForInitial(keyword_initial)
                self.completer_model.setStringList(keyword_data)

    def populateBrowserWindow(self, content=""):
        """
        Populate the browser window based upon the entered term in the search line.
        @param content: the content to render in the browser
        @type content: str
        """
        if content == "":
            api_chooser_text = self.api_chooser_lineedit.text()
            if len(api_chooser_text) > 0:
                content = self.winapi.getKeywordContent(api_chooser_text)
        self.browser_window.setHtml(content)
        self._updateHistoryButtonState()

    def _onSearchButtonClicked(self):
        """
        Action that is performed when the search button is clicked. This will populate the browser window.
        """
        self.populateBrowserWindow()

    def _onBackButtonClicked(self):
        """
        Action that is performed when the search button is clicked. This will populate the browser window.
        """
        document_content, anchor = self.winapi.getPreviousDocumentContent()
        if document_content != "":
            self.browser_window.setHtml(document_content)
        self.browser_window.scrollToAnchor(anchor)
        self._updateHistoryButtonState()

    def _onNextButtonClicked(self):
        """
        Action that is performed when the search button is clicked. This will populate the browser window.
        """
        document_content, anchor = self.winapi.getNextDocumentContent()
        if document_content != "":
            self.browser_window.setHtml(document_content)
        self.browser_window.scrollToAnchor(anchor)
        self._updateHistoryButtonState()

    def _onOnlineButtonClicked(self):
        """
        Action that is performed when the search button is clicked. This will populate the browser window.
        """
        self.winapi.setOnlineMsdnEnabled(not self.winapi.hasOnlineMsdnAvailable())
        self._updateAvailability()

    def _browserAnchorClicked(self, url):
        """
        Callback for the case an anchor (or any link) within the browser window is clicked. This will fetch
        document content and anchor based on the URL of the link and update the browser window.
        @param url: a URL as triggered by the callback
        @type url: QUrl
        """
        document_content, anchor = self.winapi.getLinkedDocumentContent(url)
        if document_content != "":
            self.browser_window.setHtml(document_content)
        self.browser_window.scrollToAnchor(anchor)
        self._updateHistoryButtonState()

    def navigate(self, api_name):
        """
        A function exposed in order to allow the widget to be navigated to an arbitrary API name.
        @param api_name: the API name to navigate the widget to.
        @type api_name: str
        """
        self.api_chooser_lineedit.setText(api_name)
        self.populateBrowserWindow()

    def _navigateToHighlightedIdentifier(self):
        """
        A function exposed to allow navigating the widget to the currently highlighted identifier from the IDA view.
        """
        if self.winapi.hasOfflineMsdnAvailable():
            highlighted_identifier = Misc.cleanCountingSuffix(self.ida_proxy.get_highlighted_identifier())
            highlighted_identifier = self.parent.semantic_identifier.lookupDisplayApiName(highlighted_identifier)
            self.navigate(highlighted_identifier)
            self.parent.setTabFocus(self.name)

    def _updateHistoryButtonState(self):
        """
        Update the button state (enabled/disabled) according to availability of history information from the
        WinApiProvider
        """
        self.back_button.setEnabled(self.winapi.hasBackwardHistory())
        self.next_button.setEnabled(self.winapi.hasForwardHistory())