Esempio n. 1
0
class TagPanel(JPanel, DocumentListener):
    __metaclass__ = Singleton

    def __init__(self):
        super(TagPanel, self).__init__()
        self._text_field = None

    def changeUpdate(self, event):
        self._update()

    def insertUpdate(self, event):
        self._update()

    def removeUpdate(self, event):
        self._update()

    def display(self, values):
        self.add(JLabel('<html><b>Tags:</b></html>'))
        self._text_field = JTextField()
        self._text_field.setColumns(20)
        self._text_field.setEditable(True)
        self._text_field.setText(InfrastructureHelpers.join(values['tags']))
        self._text_field.getDocument().addDocumentListener(self)
        self.add(self._text_field)

    def _update(self):
        Application.get_instance().execute(SetDomainDictValueCommand(
            SetDomainDictValueCommand.TYPE_VISIBLE_ITEMS,
            'tags',
            InfrastructureHelpers.split(self._text_field.getText())
        ))
Esempio n. 2
0
    def _initializeGui(self, callbacks):
        tab = JPanel()

        jLabel1 = JLabel("Original Hash:")
        jLabel2 = JLabel("Original message:")
        jLabel3 = JLabel("Message to append:")
        jLabel5 = JLabel("Max key length:")
        jTextField1 = JTextField("")
        jTextField2 = JTextField("")
        jTextField3 = JTextField("")
        jTextField4 = JTextField("128")
        jLabel4 = JLabel("Hashing functions")
        jCheckBox1 = JCheckBox("MD4")
        jCheckBox2 = JCheckBox("MD5")
        jCheckBox3 = JCheckBox("SHA1")
        jCheckBox4 = JCheckBox("SHA256")
        jCheckBox5 = JCheckBox("SHA512")
        jCheckBox1.setEnabled(False)
        jCheckBox2.setEnabled(False)
        jCheckBox3.setEnabled(False)
        jCheckBox4.setEnabled(False)
        jCheckBox5.setEnabled(False)
        jScrollPane1 = JScrollPane()
        jTable1 = JTable()
        jButton1 = JButton("Generate", actionPerformed=self.generate_attack)
        jButton1.setEnabled(False)
        jButton2 = JButton("Copy messages", actionPerformed=self.copy_messages)
        jButton3 = JButton("Copy hashes", actionPerformed=self.copy_hashes)

        self._tab = tab
        self._textfields = {
            "original_hash": jTextField1,
            "original_msg": jTextField2,
            "append_msg": jTextField3,
            "max_key_len": jTextField4,
        }
        self._checkboxes = {
            md4: jCheckBox1,
            md5: jCheckBox2,
            sha1: jCheckBox3,
            sha256: jCheckBox4,
            sha512: jCheckBox5,
        }

        self._table = jTable1
        self._extensions = {}
        self._hashes, self._messages = [], []

        # Hash field change event
        jTextField1.getDocument().addDocumentListener(HashChangeListener(self._checkboxes, self._textfields['original_hash'], jButton1))

        # Table columns
        jTable1.setModel(DefaultTableModel([],["#", "Type","New Message", "Hash"]))
        jScrollPane1.setViewportView(jTable1)
        # Table column width
        jTable1.getColumnModel().getColumn(0).setMaxWidth(50)
        jTable1.getColumnModel().getColumn(1).setMaxWidth(60)

        layout = GroupLayout(tab)
        tab.setLayout(layout)

        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(24, 24, 24)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel5)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2)
                    .addComponent(jLabel3))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addComponent(jTextField3, GroupLayout.DEFAULT_SIZE, 425, 32767)
                    .addComponent(jTextField2)
                    .addComponent(jTextField1)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jTextField4, GroupLayout.PREFERRED_SIZE, 88, GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, 32767)))
                .addGap(30, 30, 30)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jCheckBox1)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jCheckBox2)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jCheckBox3)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jCheckBox4)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jCheckBox5))
                    .addComponent(jLabel4)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jButton1)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton3)
                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jButton2)))
                .addGap(167, 167, 167))
            .addComponent(jScrollPane1)
        )
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(26, 26, 26)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jTextField1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                        .addComponent(jCheckBox2)
                        .addComponent(jCheckBox3)
                        .addComponent(jCheckBox1)
                        .addComponent(jCheckBox4)
                        .addComponent(jCheckBox5)))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField3, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3))
                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(jTextField4, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton2)
                    .addComponent(jButton3)
                    .addComponent(jButton1))
                .addGap(13, 13, 13)
                .addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 971, 32767))
        )

        callbacks.customizeUiComponent(tab)
        callbacks.addSuiteTab(self)
Esempio n. 3
0
class BurpExtender(IBurpExtender, ITab, IHttpListener,
                   IMessageEditorController, AbstractTableModel,
                   ActionListener, DocumentListener):

    #
    # implement IBurpExtender
    #

    def registerExtenderCallbacks(self, callbacks):

        # keep a reference to our callbacks object
        self._callbacks = callbacks

        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()

        # set our extension name
        callbacks.setExtensionName("Response Clusterer")

        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()

        # main split pane
        self._main_jtabedpane = JTabbedPane()

        # The split pane with the log and request/respponse details
        self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT)

        # table of log entries
        logTable = Table(self)
        scrollPane = JScrollPane(logTable)
        self._splitpane.setLeftComponent(scrollPane)

        # List of log entries
        self._log_entries = []

        # tabs with request/response viewers
        tabs = JTabbedPane()
        self._requestViewer = callbacks.createMessageEditor(self, False)
        self._responseViewer = callbacks.createMessageEditor(self, False)
        tabs.addTab("Request", self._requestViewer.getComponent())
        tabs.addTab("Response", self._responseViewer.getComponent())
        self._splitpane.setRightComponent(tabs)

        #Setup the options
        self._optionsJPanel = JPanel()
        gridBagLayout = GridBagLayout()
        gbc = GridBagConstraints()
        self._optionsJPanel.setLayout(gridBagLayout)

        self.max_clusters = 500
        self.JLabel_max_clusters = JLabel("Maximum amount of clusters: ")
        gbc.gridy = 0
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_max_clusters, gbc)
        self.JTextField_max_clusters = JTextField(str(self.max_clusters), 5)
        self.JTextField_max_clusters.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_max_clusters, gbc)
        callbacks.customizeUiComponent(self.JLabel_max_clusters)
        callbacks.customizeUiComponent(self.JTextField_max_clusters)

        self.similarity = 0.95
        self.JLabel_similarity = JLabel("Similarity (between 0 and 1)")
        gbc.gridy = 1
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_similarity, gbc)
        self.JTextField_similarity = JTextField(str(self.similarity), 5)
        self.JTextField_similarity.getDocument().addDocumentListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_similarity, gbc)
        callbacks.customizeUiComponent(self.JLabel_similarity)
        callbacks.customizeUiComponent(self.JTextField_similarity)

        self.use_quick_similar = False
        self.JLabel_use_quick_similar = JLabel(
            "Use set intersection of space splitted tokens for similarity (default: optimized difflib.SequenceMatcher.quick_ratio)"
        )
        gbc.gridy = 2
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_use_quick_similar, gbc)
        self.JCheckBox_use_quick_similar = JCheckBox("")
        self.JCheckBox_use_quick_similar.addActionListener(self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JCheckBox_use_quick_similar, gbc)
        callbacks.customizeUiComponent(self.JCheckBox_use_quick_similar)

        self.response_max_size = 10 * 1024  #10kb
        self.JLabel_response_max_size = JLabel("Response max size (bytes)")
        gbc.gridy = 3
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_response_max_size, gbc)
        self.JTextField_response_max_size = JTextField(
            str(self.response_max_size), 5)
        self.JTextField_response_max_size.getDocument().addDocumentListener(
            self)
        gbc.gridx = 1
        self._optionsJPanel.add(self.JTextField_response_max_size, gbc)
        callbacks.customizeUiComponent(self.JLabel_response_max_size)
        callbacks.customizeUiComponent(self.JTextField_response_max_size)

        self.uninteresting_mime_types = ('JPEG', 'CSS', 'GIF', 'script', 'GIF',
                                         'PNG', 'image')
        self.uninteresting_status_codes = ()
        self.uninteresting_url_file_extensions = ('js', 'css', 'zip', 'war',
                                                  'jar', 'doc', 'docx', 'xls',
                                                  'xlsx', 'pdf', 'exe', 'dll',
                                                  'png', 'jpeg', 'jpg', 'bmp',
                                                  'tif', 'tiff', 'gif', 'webp',
                                                  'm3u', 'mp4', 'm4a', 'ogg',
                                                  'aac', 'flac', 'mp3', 'wav',
                                                  'avi', 'mov', 'mpeg', 'wmv',
                                                  'swf', 'woff', 'woff2')

        about = "<html>"
        about += "Author: floyd, @floyd_ch, http://www.floyd.ch<br>"
        about += "modzero AG, http://www.modzero.ch<br>"
        about += "<br>"
        about += "<h3>Getting an overview of the tested website</h3>"
        about += "<p style=\"width:500px\">"
        about += "This plugin clusters all response bodies by similarity and shows a summary, one request/response per cluster. "
        about += 'Adjust similarity in the options if you get too few or too many entries in the "One member of each cluster" '
        about += "tab. The plugin will allow a tester to get an overview of the tested website's responses from all tools (scanner, proxy, etc.). "
        about += "As similarity comparison "
        about += "can use a lot of ressources, only small, in-scope responses that have interesting response codes, "
        about += "file extensions and mime types are processed. "
        about += "</p>"
        about += "</html>"
        self.JLabel_about = JLabel(about)
        self.JLabel_about.setLayout(GridBagLayout())
        self._aboutJPanel = JScrollPane(self.JLabel_about)

        # customize our UI components
        callbacks.customizeUiComponent(self._splitpane)
        callbacks.customizeUiComponent(logTable)
        callbacks.customizeUiComponent(scrollPane)
        callbacks.customizeUiComponent(tabs)

        # add the splitpane and options to the main jtabedpane
        self._main_jtabedpane.addTab("One member of each cluster", None,
                                     self._splitpane, None)
        self._main_jtabedpane.addTab("Options", None, self._optionsJPanel,
                                     None)
        self._main_jtabedpane.addTab("About & README", None, self._aboutJPanel,
                                     None)

        # clusters will grow up to self.max_clusters response bodies...
        self._clusters = set()
        self.Similarity = Similarity()

        # Now load the already stored
        with self._lock:
            log_entries_from_storage = self.load_project_setting("log_entries")
            if log_entries_from_storage:
                for toolFlag, req, resp, url in log_entries_from_storage:
                    try:
                        self.add_new_log_entry(toolFlag, req, resp, url)
                    except Exception as e:
                        print "Exception when deserializing a stored log entry", toolFlag, url
                        print e

        # Important: Do this at the very end (otherwise we could run into troubles locking up entire threads)
        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        # register ourselves as an HTTP listener
        callbacks.registerHttpListener(self)

    #
    # implement what happens when options are changed
    #

    def changedUpdate(self, document):
        pass

    def removeUpdate(self, document):
        self.actionPerformed(None)

    def insertUpdate(self, document):
        self.actionPerformed(None)

    def actionPerformed(self, actionEvent):
        self.use_quick_similar = self.JCheckBox_use_quick_similar.isSelected()
        try:
            self.max_clusters = int(self.JTextField_max_clusters.getText())
        except:
            self.JTextField_max_clusters.setText("200")

        try:
            self.similarity = float(self.JTextField_similarity.getText())
            if self.similarity > 1.0 or self.similarity < 0.0:
                self.JTextField_similarity.setText("0.9")
        except:
            self.JTextField_similarity.setText("0.9")

        try:
            self.response_max_size = float(
                self.JTextField_response_max_size.getText())
            if self.response_max_size < 0.0:
                self.JTextField_response_max_size.setText(str(10 * 1024))
        except:
            self.JTextField_response_max_size.setText(str(10 * 1024))

        print self.JCheckBox_use_quick_similar.isSelected(
        ), self.JTextField_max_clusters.getText(
        ), self.JTextField_similarity.getText(
        ), self.JTextField_response_max_size.getText()

    #
    # implement ITab
    #

    def getTabCaption(self):
        return "Response Clusterer"

    def getUiComponent(self):
        return self._main_jtabedpane

    #
    # implement IHttpListener
    #

    def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo):
        if not messageIsRequest:
            if len(self._clusters) >= self.max_clusters:
                return
            resp = messageInfo.getResponse()
            if len(resp) >= self.response_max_size:
                print "Message was too long"
                return
            iResponseInfo = self._helpers.analyzeResponse(resp)
            mime_type = iResponseInfo.getStatedMimeType()
            if mime_type in self.uninteresting_mime_types:
                print "Mime type", mime_type, "is ignored"
                return
            if iResponseInfo.getStatusCode(
            ) in self.uninteresting_status_codes:
                print "Status code", iResponseInfo.getStatusCode(
                ), "is ignored"
                return
            req = messageInfo.getRequest()
            iRequestInfo = self._helpers.analyzeRequest(messageInfo)
            if not iRequestInfo.getUrl():
                print "iRequestInfo.getUrl() returned None, so bailing out of analyzing this request"
                return
            if '.' in iRequestInfo.getUrl().getFile() and iRequestInfo.getUrl(
            ).getFile().split(
                    '.')[-1] in self.uninteresting_url_file_extensions:
                print iRequestInfo.getUrl().getFile().split(
                    '.')[-1], "is an ignored file extension"
                return
            if not self._callbacks.isInScope(iRequestInfo.getUrl()):
                print iRequestInfo.getUrl(), "is not in scope"
                return
            body = resp[iResponseInfo.getBodyOffset():]
            with self._lock:
                similarity_func = self.Similarity.similar
                if self.use_quick_similar:
                    similarity_func = self.Similarity.quick_similar
                start_time = time.time()
                for response_code, item in self._clusters:
                    if not response_code == iResponseInfo.getStatusCode():
                        #Different response codes -> different clusters
                        continue
                    if similarity_func(str(body), str(item), self.similarity):
                        return  #break
                else:  #when no break/return occures in the for loop
                    self.add_new_log_entry(toolFlag, req, resp,
                                           iRequestInfo.getUrl().toString())
                    self.save_project_setting("log_entries", self._log_entries)
                taken_time = time.time() - start_time
                if taken_time > 0.5:
                    print "Plugin took", taken_time, "seconds to process request... body length:", len(
                        body), "current cluster length:", len(self._clusters)
                    print "URL:", str(iRequestInfo.getUrl()),

    def add_new_log_entry(self, toolFlag, request, response, service_url):
        self._log_entries.append((toolFlag, request, response, service_url))
        iResponseInfo = self._helpers.analyzeResponse(response)
        body = response[iResponseInfo.getBodyOffset():]
        self._clusters.add((iResponseInfo.getStatusCode(), str(body)))
        row = self._log.size()
        service = CustomHttpService(service_url)
        r = CustomRequestResponse(None, None, service, request, response)
        iRequestInfo = self._helpers.analyzeRequest(r)
        self._log.add(
            LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(r),
                     iRequestInfo.getUrl()))
        self.fireTableRowsInserted(row, row)

    #
    # extend AbstractTableModel
    #

    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 2

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "Tool"
        if columnIndex == 1:
            return "URL"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        logEntry = self._log.get(rowIndex)
        if columnIndex == 0:
            return self._callbacks.getToolName(logEntry._tool)
        if columnIndex == 1:
            return logEntry._url.toString()
        return ""

    #
    # implement IMessageEditorController
    # this allows our request/response viewers to obtain details about the messages being displayed
    #

    def getHttpService(self):
        return self._currentlyDisplayedItem.getHttpService()

    def getRequest(self):
        return self._currentlyDisplayedItem.getRequest()

    def getResponse(self):
        return self._currentlyDisplayedItem.getResponse()

    def save_project_setting(self, name, value):
        value = pickle.dumps(value).encode("base64")
        request = "GET /"+name+" HTTP/1.0\r\n\r\n" \
                  "You can ignore this item in the site map. It was created by the ResponseClusterer extension. The \n" \
                  "reason is that the Burp API is missing a certain functionality to save settings. \n" \
                  "TODO Burp API limitation: This is a hackish way to be able to store project-scope settings.\n" \
                  "We don't want to restore requests/responses of tabs in a totally different Burp project.\n" \
                  "However, unfortunately there is no saveExtensionProjectSetting in the Burp API :(\n" \
                  "So we have to abuse the addToSiteMap API to store project-specific things\n" \
                  "Even when using this hack we currently cannot persist Collaborator interaction checks\n" \
                  "(IBurpCollaboratorClientContext is not serializable and Threads loose their Python class\n" \
                  "functionality when unloaded) due to Burp API limitations."
        response = None
        if value:
            response = "HTTP/1.1 200 OK\r\n" + value
        rr = CustomRequestResponse(
            name, '',
            CustomHttpService('http://responseclustererextension.local/'),
            request, response)
        self._callbacks.addToSiteMap(rr)

    def load_project_setting(self, name):
        rrs = self._callbacks.getSiteMap(
            'http://responseclustererextension.local/' + name)
        if rrs:
            rr = rrs[0]
            if rr.getResponse():
                val = "\r\n".join(
                    FloydsHelpers.jb2ps(rr.getResponse()).split("\r\n")[1:])
                return pickle.loads(val.decode("base64"))
            else:
                return None
        else:
            return None
Esempio n. 4
0
class MPConfig(TreeSelectionListener):
    """The MPConfig component initializes the KConfig library with the requested configuration,
    and buildst the GUI, consisting of a "Load" and a "Save as" buttons, a search field, "show all"
    checkbox, tree view and information text view."""
    def __init__(self,
                 kconfig_file="Kconfig",
                 config_file=".config",
                 systemLogger=None):
        """[summary]

        Parameters
        ----------
            kconfig_file : string (default: "Kconfig")
                The Kconfig configuration file
            config_file : string (default: ".config")
                The save file which will be used for loading and saving the settings
            systemLogger (default: None)
                A system logger object. If None then print statements are used for logging.
        """
        global log
        if systemLogger:
            log = systemLogger

        # Load Kconfig configuration files
        self.kconfig = Kconfig(kconfig_file)
        setKConfig(self.kconfig)

        if os.path.isfile(config_file):
            log.info(self.kconfig.load_config(config_file))
        elif os.path.isfile(".config"):
            log.info(self.kconfig.load_config(".config"))

        self.tree = KConfigTree(self.kconfig)
        self.tree.addTreeSelectionListener(self.treeSelectionChanged)
        jTreeSP = JScrollPane(self.tree)

        self.jta = JTextArea()
        self.jta.setEditable(False)
        jTextSP = JScrollPane(self.jta)

        toolPanel = JPanel()
        toolPanel.setLayout(BoxLayout(toolPanel, BoxLayout.X_AXIS))
        toolPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0))

        toolPanel.add(JLabel("Search: "))

        jSearchPanel = JPanel()
        jSearchPanel.setLayout(BoxLayout(jSearchPanel, BoxLayout.X_AXIS))
        self.jSearchField = JTextField()
        jSearchPanel.setBackground(self.jSearchField.getBackground())
        jSearchPanel.setBorder(self.jSearchField.getBorder())
        self.jSearchField.setBorder(None)
        self.jSearchField.getDocument().addDocumentListener(
            SearchListener(self.tree))
        jSearchPanel.add(self.jSearchField)

        clearSearchButton = JButton(u'\u00d7',
                                    actionPerformed=self.clearSearch)
        d = clearSearchButton.getPreferredSize()
        clearSearchButton.setPreferredSize(Dimension(d.height, d.height))
        clearSearchButton.setBackground(self.jSearchField.getBackground())
        clearSearchButton.setBorder(None)
        clearSearchButton.setOpaque(False)
        clearSearchButton.setContentAreaFilled(False)
        clearSearchButton.setFocusPainted(False)
        jSearchPanel.add(clearSearchButton)

        toolPanel.add(jSearchPanel)

        self.showAllCheckBox = JCheckBox("Show all",
                                         actionPerformed=self.OnShowAllCheck)
        toolPanel.add(self.showAllCheckBox)

        splitPane = JSplitPane(JSplitPane.VERTICAL_SPLIT, jTreeSP, jTextSP)
        splitPane.setOneTouchExpandable(True)
        splitPane.setDividerLocation(300)

        treePanel = JPanel(BorderLayout())
        treePanel.add(toolPanel, BorderLayout.NORTH)
        treePanel.add(splitPane, BorderLayout.CENTER)

        loadSavePanel = JPanel()
        loadSavePanel.setLayout(BoxLayout(loadSavePanel, BoxLayout.X_AXIS))
        loadSavePanel.add(
            JButton("Load", actionPerformed=self.loadConfigDialog))
        loadSavePanel.add(
            JButton("Save as", actionPerformed=self.writeConfigDialog))

        self.rootPanel = JPanel()
        self.rootPanel.setLayout(BorderLayout())
        self.rootPanel.add(loadSavePanel, BorderLayout.PAGE_START)
        self.rootPanel.add(treePanel, BorderLayout.CENTER)

    def clearSearch(self, event):
        self.jSearchField.setText("")

    def OnShowAllCheck(self, event):
        self.tree.setShowAll(self.showAllCheckBox.isSelected())
        self.tree.doSearch(self.jSearchField.getText()
                           )  # Must repeat the search if one is active

    def treeSelectionChanged(self, event):
        """When the user selects a new node in the tree, show info about the selected node
        in the info text area below the tree."""
        path = event.getNewLeadSelectionPath()
        if path:
            comp = path.getLastPathComponent()
            if isinstance(comp, DefaultMutableTreeNode):
                nodeData = comp.getUserObject()
                if isinstance(nodeData, TreeNodeData):
                    self.jta.setText(getNodeInfoString(nodeData.knode))
                    self.jta.setCaretPosition(0)

    def getPane(self):
        """Return the panel containing all the other components that is set up in __init__()."""
        return self.rootPanel

    def writeConfig(self, fileName):
        """Write the current configuration to the file specified."""
        self.kconfig.write_config(fileName)  # Save full configuration
        #self.kconfig.write_min_config(fileName) # Save minimal configuration

    def loadConfig(self, fileName):
        """Load configuration settings from the file specified."""
        if os.path.isfile(fileName):
            log.info(self.kconfig.load_config(fileName))
            self.tree.createKconfShadowModel(self.kconfig)
            self.tree.updateTree()

    def writeConfigDialog(self, e):
        """Open a file dialog to save configuration"""
        fileChooser = JFileChooser(os.getcwd())
        retval = fileChooser.showSaveDialog(None)
        if retval == JFileChooser.APPROVE_OPTION:
            f = fileChooser.getSelectedFile()
            self.writeConfig(f.getPath())

    def loadConfigDialog(self, e):
        """Open a file dialog to select configuration to load"""
        fileChooser = JFileChooser(os.getcwd())
        retval = fileChooser.showOpenDialog(None)
        if retval == JFileChooser.APPROVE_OPTION:
            f = fileChooser.getSelectedFile()
            log.info("Selected file: " + f.getPath())
            self.loadConfig(f.getPath())
Esempio n. 5
0
class NewZoneDialog(JDialog, ActionListener, WindowListener):
    """Dialog for favourite zone editing
    """
    def __init__(self, parent, title, modal, app):
        from java.awt import CardLayout
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 7, 7)
        self.getContentPane().setBorder(border)
        self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))

        self.FAVAREALAYERNAME = "Favourite zone editing"

        info = JLabel(self.app.strings.getString("Create_a_new_favourite_zone"))
        info.setAlignmentX(Component.LEFT_ALIGNMENT)

        #Name
        nameLbl = JLabel(self.app.strings.getString("fav_zone_name"))
        self.nameTextField = JTextField(20)
        self.nameTextField.setMaximumSize(self.nameTextField.getPreferredSize())
        self.nameTextField.setToolTipText(self.app.strings.getString("fav_zone_name_tooltip"))
        namePanel = JPanel()
        namePanel.setLayout(BoxLayout(namePanel, BoxLayout.X_AXIS))
        namePanel.add(nameLbl)
        namePanel.add(Box.createHorizontalGlue())
        namePanel.add(self.nameTextField)

        #Country
        countryLbl = JLabel(self.app.strings.getString("fav_zone_country"))
        self.countryTextField = JTextField(20)
        self.countryTextField.setMaximumSize(self.countryTextField.getPreferredSize())
        self.countryTextField.setToolTipText(self.app.strings.getString("fav_zone_country_tooltip"))
        countryPanel = JPanel()
        countryPanel.setLayout(BoxLayout(countryPanel, BoxLayout.X_AXIS))
        countryPanel.add(countryLbl)
        countryPanel.add(Box.createHorizontalGlue())
        countryPanel.add(self.countryTextField)

        #Type
        modeLbl = JLabel(self.app.strings.getString("fav_zone_type"))
        RECTPANEL = "rectangle"
        POLYGONPANEL = "polygon"
        BOUNDARYPANEL = "boundary"
        self.modesStrings = [RECTPANEL, POLYGONPANEL, BOUNDARYPANEL]
        modesComboModel = DefaultComboBoxModel()
        for i in (self.app.strings.getString("rectangle"),
                  self.app.strings.getString("delimited_by_a_closed_way"),
                  self.app.strings.getString("delimited_by_an_administrative_boundary")):
            modesComboModel.addElement(i)
        self.modesComboBox = JComboBox(modesComboModel,
                                       actionListener=self,
                                       editable=False)

        #- Rectangle
        self.rectPanel = JPanel()
        self.rectPanel.setLayout(BoxLayout(self.rectPanel, BoxLayout.Y_AXIS))

        capturePane = JPanel()
        capturePane.setLayout(BoxLayout(capturePane, BoxLayout.X_AXIS))
        capturePane.setAlignmentX(Component.LEFT_ALIGNMENT)

        josmP = JPanel()
        self.captureRBtn = JRadioButton(self.app.strings.getString("capture_area"))
        self.captureRBtn.addActionListener(self)
        self.captureRBtn.setSelected(True)
        self.bboxFromJosmBtn = JButton(self.app.strings.getString("get_current_area"),
                                       actionPerformed=self.on_bboxFromJosmBtn_clicked)
        self.bboxFromJosmBtn.setToolTipText(self.app.strings.getString("get_capture_area_tooltip"))
        josmP.add(self.bboxFromJosmBtn)
        capturePane.add(self.captureRBtn)
        capturePane.add(Box.createHorizontalGlue())
        capturePane.add(self.bboxFromJosmBtn)

        manualPane = JPanel()
        manualPane.setLayout(BoxLayout(manualPane, BoxLayout.X_AXIS))
        manualPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.manualRBtn = JRadioButton(self.app.strings.getString("use_this_bbox"))
        self.manualRBtn.addActionListener(self)
        self.bboxTextField = JTextField(20)
        self.bboxTextField.setMaximumSize(self.bboxTextField.getPreferredSize())
        self.bboxTextField.setToolTipText(self.app.strings.getString("fav_bbox_tooltip"))
        self.bboxTextFieldDefaultBorder = self.bboxTextField.getBorder()
        self.bboxTextField.getDocument().addDocumentListener(TextListener(self))
        manualPane.add(self.manualRBtn)
        manualPane.add(Box.createHorizontalGlue())
        manualPane.add(self.bboxTextField)

        group = ButtonGroup()
        group.add(self.captureRBtn)
        group.add(self.manualRBtn)

        previewPane = JPanel()
        previewPane.setLayout(BoxLayout(previewPane, BoxLayout.X_AXIS))
        previewPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        bboxPreviewInfo = JTextField(self.app.strings.getString("coordinates"),
                                     editable=0,
                                     border=None)
        bboxPreviewInfo.setMaximumSize(bboxPreviewInfo.getPreferredSize())
        self.bboxPreviewTextField = JTextField(20,
                                               editable=0,
                                               border=None)
        self.bboxPreviewTextField.setMaximumSize(self.bboxPreviewTextField.getPreferredSize())
        previewPane.add(bboxPreviewInfo)
        previewPane.add(Box.createHorizontalGlue())
        previewPane.add(self.bboxPreviewTextField)

        self.rectPanel.add(capturePane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.rectPanel.add(manualPane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 20)))
        self.rectPanel.add(previewPane)

        #- Polygon (closed way) drawn by hand
        self.polygonPanel = JPanel(BorderLayout())
        self.polygonPanel.setLayout(BoxLayout(self.polygonPanel, BoxLayout.Y_AXIS))

        polyInfo = JLabel("<html>%s</html>" % self.app.strings.getString("polygon_info"))
        polyInfo.setFont(polyInfo.getFont().deriveFont(Font.ITALIC))
        polyInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        editPolyPane = JPanel()
        editPolyPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        editPolyBtn = JButton(self.app.strings.getString("create_fav_layer"),
                              actionPerformed=self.create_new_zone_editing_layer)
        editPolyBtn.setToolTipText(self.app.strings.getString("create_fav_layer_tooltip"))
        editPolyPane.add(editPolyBtn)

        self.polygonPanel.add(polyInfo)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.polygonPanel.add(editPolyPane)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))

        #- Administrative Boundary
        self.boundaryPanel = JPanel()
        self.boundaryPanel.setLayout(BoxLayout(self.boundaryPanel, BoxLayout.Y_AXIS))

        boundaryInfo = JLabel("<html>%s</html>" % app.strings.getString("boundary_info"))
        boundaryInfo.setFont(boundaryInfo.getFont().deriveFont(Font.ITALIC))
        boundaryInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        boundaryTagsPanel = JPanel(GridLayout(3, 3, 5, 5))
        boundaryTagsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        boundaryTagsPanel.add(JLabel("name ="))
        self.nameTagTextField = JTextField(20)
        boundaryTagsPanel.add(self.nameTagTextField)
        boundaryTagsPanel.add(JLabel("admin_level ="))
        self.adminLevelTagTextField = JTextField(20)
        self.adminLevelTagTextField.setToolTipText(self.app.strings.getString("adminLevel_tooltip"))
        boundaryTagsPanel.add(self.adminLevelTagTextField)
        boundaryTagsPanel.add(JLabel(self.app.strings.getString("other_tag")))
        self.optionalTagTextField = JTextField(20)
        self.optionalTagTextField.setToolTipText("key=value")
        boundaryTagsPanel.add(self.optionalTagTextField)

        downloadBoundariesPane = JPanel()
        downloadBoundariesPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        downloadBoundariesBtn = JButton(self.app.strings.getString("download_boundary"),
                                        actionPerformed=self.on_downloadBoundariesBtn_clicked)
        downloadBoundariesBtn.setToolTipText(self.app.strings.getString("download_boundary_tooltip"))
        downloadBoundariesPane.add(downloadBoundariesBtn)

        self.boundaryPanel.add(boundaryInfo)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.boundaryPanel.add(boundaryTagsPanel)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.boundaryPanel.add(downloadBoundariesPane)

        self.editingPanels = {"rectangle": self.rectPanel,
                              "polygon": self.polygonPanel,
                              "boundary": self.boundaryPanel}

        #Main buttons
        self.okBtn = JButton(self.app.strings.getString("OK"),
                             ImageProvider.get("ok"),
                             actionPerformed=self.on_okBtn_clicked)
        self.cancelBtn = JButton(self.app.strings.getString("cancel"),
                                 ImageProvider.get("cancel"),
                                 actionPerformed=self.close_dialog)
        self.previewBtn = JButton(self.app.strings.getString("Preview_zone"),
                                  actionPerformed=self.on_previewBtn_clicked)
        self.previewBtn.setToolTipText(self.app.strings.getString("preview_zone_tooltip"))
        okBtnSize = self.okBtn.getPreferredSize()
        viewBtnSize = self.previewBtn.getPreferredSize()
        viewBtnSize.height = okBtnSize.height
        self.previewBtn.setPreferredSize(viewBtnSize)

        #layout
        self.add(info)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        namePanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(namePanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        countryPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(countryPanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        modeLbl.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(modeLbl)
        self.add(Box.createRigidArea(Dimension(0, 5)))

        self.add(self.modesComboBox)
        self.modesComboBox.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        self.configPanel = JPanel(CardLayout())
        self.configPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5))
        self.configPanel.add(self.rectPanel, RECTPANEL)
        self.configPanel.add(self.polygonPanel, POLYGONPANEL)
        self.configPanel.add(self.boundaryPanel, BOUNDARYPANEL)
        self.configPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(self.configPanel)
        buttonsPanel = JPanel()
        buttonsPanel.add(self.okBtn)
        buttonsPanel.add(self.cancelBtn)
        buttonsPanel.add(self.previewBtn)
        buttonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(buttonsPanel)

        self.addWindowListener(self)
        self.pack()

    def update_gui_from_preferences(self):
        self.nameTextField.setText(self.app.newZone.name)
        #Reset rectangle mode
        bboxStr = ",".join(["%0.4f" % x for x in self.app.newZone.bbox])
        self.bboxTextField.setText(bboxStr)
        self.bboxPreviewTextField.setText(bboxStr)
        self.bboxFromJosmBtn.setEnabled(True)
        self.bboxTextField.setEnabled(False)

        #Reset polygon mode
        self.polygonAsString = ""

        #Reset boundary mode
        self.boundaryAsString = ""

        self.modesComboBox.setSelectedIndex(0)

    def actionPerformed(self, e):
        #Show the panel for configuring the favourite area of the
        #selected type
        if e.getSource() == self.modesComboBox:
            cl = self.configPanel.getLayout()
            selectedMode = self.modesStrings[self.modesComboBox.selectedIndex]
            cl.show(self.configPanel, selectedMode)
        #Activate bbox input for rectangular favourite zone mode
        elif e.getSource() == self.captureRBtn:
            self.bboxFromJosmBtn.setEnabled(True)
            self.bboxTextField.setEnabled(False)
        else:
            self.bboxFromJosmBtn.setEnabled(False)
            self.bboxTextField.setEnabled(True)

    def on_bboxFromJosmBtn_clicked(self, widget):
        """Read bbox currently shown in JOSM
        """
        bbox = self.app.get_frame_bounds()
        self.bboxPreviewTextField.setText(",".join(["%0.4f" % x for x in bbox]))

### Manage layer for creating a new favourite zone from polygon or boundary
    def create_new_zone_editing_layer(self, e=None):
        """Open a new dataset where the user can draw a closed way to
           delimit the favourite area
        """
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.setActiveLayer(layer)
        else:
            Main.main.addLayer(OsmDataLayer(DataSet(), self.FAVAREALAYERNAME, None))
        Main.main.parent.toFront()

    def get_new_zone_editing_layer(self):
        """Check if the layer for editing the favourite area yet exists
        """
        for layer in self.app.mv.getAllLayers():
            if layer.getName() == self.FAVAREALAYERNAME:
                return layer
        return None

    def remove_new_zone_editing_layer(self):
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.removeLayer(layer)

    def on_zone_edited(self):
        """Read ways that delimit the favourite area and convert them to
           jts geometry
        """
        if self.modesComboBox.getSelectedIndex() == 0:
            mode = "rectangle"
        elif self.modesComboBox.getSelectedIndex() == 1:
            mode = "polygon"
        elif self.modesComboBox.getSelectedIndex() == 2:
            mode = "boundary"

        if mode in ("polygon", "boundary"):
            layer = self.get_new_zone_editing_layer()
            if layer is not None:
                self.app.mv.setActiveLayer(layer)
            else:
                if mode == "polygon":
                    msg = self.app.strings.getString("polygon_fav_layer_missing_msg")
                else:
                    msg = self.app.strings.getString("boundary_fav_layer_missing_msg")
                JOptionPane.showMessageDialog(self,
                                              msg,
                                              self.app.strings.getString("Warning"),
                                              JOptionPane.WARNING_MESSAGE)
                return

            dataset = self.app.mv.editLayer.data
            areaWKT = self.read_area_from_osm_ways(mode, dataset)
            if areaWKT is None:
                print "I could not read the new favourite area."
            else:
                if mode == "polygon":
                    self.polygonAsString = areaWKT
                else:
                    self.boundaryAsString = areaWKT
        return mode

    def read_area_from_osm_ways(self, mode, dataset):
        """Read way in favourite area editing layer and convert them to
           WKT
        """
        converter = JTSConverter(False)
        lines = [converter.convert(way) for way in dataset.ways]
        polygonizer = Polygonizer()
        polygonizer.add(lines)
        polygons = polygonizer.getPolygons()
        multipolygon = GeometryFactory().createMultiPolygon(list(polygons))
        multipolygonWKT = WKTWriter().write(multipolygon)
        if multipolygonWKT == "MULTIPOLYGON EMPTY":
            if mode == "polygon":
                msg = self.app.strings.getString("empty_ways_polygon_msg")
            else:
                msg = self.app.strings.getString("empty_ways_boundaries_msg")
            JOptionPane.showMessageDialog(self,
                msg,
                self.app.strings.getString("Warning"),
                JOptionPane.WARNING_MESSAGE)
            return
        return multipolygonWKT

    def on_downloadBoundariesBtn_clicked(self, e):
        """Download puter ways of administrative boundaries from
           Overpass API
        """
        adminLevel = self.adminLevelTagTextField.getText()
        name = self.nameTagTextField.getText()
        optional = self.optionalTagTextField.getText()
        if (adminLevel, name, optional) == ("", "", ""):
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("enter_a_tag_msg"),
                                          self.app.strings.getString("Warning"),
                                          JOptionPane.WARNING_MESSAGE)
            return
        optTag = ""
        if optional.find("=") != -1:
            if len(optional.split("=")) == 2:
                key, value = optional.split("=")
                optTag = '["%s"="%s"]' % (URLEncoder.encode(key, "UTF-8"),
                                          URLEncoder.encode(value.replace(" ", "%20"), "UTF-8"))
        self.create_new_zone_editing_layer()
        overpassurl = 'http://127.0.0.1:8111/import?url='
        overpassurl += 'http://overpass-api.de/api/interpreter?data='
        overpassquery = 'relation["admin_level"="%s"]' % adminLevel
        overpassquery += '["name"="%s"]' % URLEncoder.encode(name, "UTF-8")
        overpassquery += '%s;(way(r:"outer");node(w););out meta;' % optTag
        overpassurl += overpassquery.replace(" ", "%20")
        print overpassurl
        self.app.send_to_josm(overpassurl)

### Buttons ############################################################
    def create_new_zone(self, mode):
        """Read data entered on gui and create a new zone
        """
        name = self.nameTextField.getText()
        country = self.countryTextField.getText().upper()

        #error: name
        if name.replace(" ", "") == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("missing_name_warning"),
                                          self.app.strings.getString("missing_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False
        if name in [z.name for z in self.app.tempZones]:
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("duplicate_name_warning"),
                                          self.app.strings.getString("duplicate_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #zone type
        zType = mode
        #error: geometry type not defined
        if zType == "polygon" and self.polygonAsString == ""\
            or zType == "boundary" and self.boundaryAsString == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("zone_not_correctly_build_warning"),
                                          self.app.strings.getString("zone_not_correctly_build_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #geometry string
        if zType == "rectangle":
            geomString = self.bboxPreviewTextField.getText()
        elif zType == "polygon":
            geomString = self.polygonAsString
        else:
            geomString = self.boundaryAsString

        self.app.newZone = Zone(self.app, name, zType, geomString, country)
        #self.app.newZone.print_info()
        return True

    def on_okBtn_clicked(self, event):
        """Add new zone to temp zones
        """
        mode = self.on_zone_edited()
        if self.create_new_zone(mode):
            self.app.tempZones.append(self.app.newZone)
            self.app.preferencesFrame.zonesTable.getModel().addRow([self.app.newZone.country,
                                                                    self.app.newZone.icon,
                                                                    self.app.newZone.name])
            maxIndex = len(self.app.tempZones) - 1
            self.app.preferencesFrame.zonesTable.setRowSelectionInterval(maxIndex,
                                                                         maxIndex)
            self.close_dialog()
            self.app.preferencesFrame.check_removeBtn_status()
            self.app.preferencesFrame.zonesTable.scrollRectToVisible(
                self.app.preferencesFrame.zonesTable.getCellRect(
                    self.app.preferencesFrame.zonesTable.getRowCount() - 1, 0, True))

    def on_previewBtn_clicked(self, e):
        """Show the favourite area on a map
        """
        mode = self.on_zone_edited()
        if not self.create_new_zone(mode):
            return
        zone = self.app.newZone

        if zone.zType == "rectangle":
            wktString = zone.bbox_to_wkt_string()
        else:
            wktString = zone.wktGeom
        script = '/*http://stackoverflow.com/questions/11954401/wkt-and-openlayers*/'
        script += '\nfunction init() {'
        script += '\n    var map = new OpenLayers.Map({'
        script += '\n        div: "map",'
        script += '\n        projection: new OpenLayers.Projection("EPSG:900913"),'
        script += '\n        displayProjection: new OpenLayers.Projection("EPSG:4326"),'
        script += '\n        layers: ['
        script += '\n            new OpenLayers.Layer.OSM()'
        script += '\n            ]'
        script += '\n    });'
        script += '\n    var wkt = new OpenLayers.Format.WKT();'
        script += '\n    var polygonFeature = wkt.read("%s");' % wktString
        script += '\n    var vectors = new OpenLayers.Layer.Vector("Favourite area");'
        script += '\n    map.addLayer(vectors);'
        script += '\n    polygonFeature.geometry.transform(map.displayProjection, map.getProjectionObject());'
        script += '\n    vectors.addFeatures([polygonFeature]);'
        script += '\n    map.zoomToExtent(vectors.getDataExtent());'
        script += '\n};'
        scriptFile = open(File.separator.join([self.app.SCRIPTDIR,
                                              "html",
                                              "script.js"]), "w")
        scriptFile.write(script)
        scriptFile.close()
        OpenBrowser.displayUrl(File.separator.join([self.app.SCRIPTDIR,
                                                   "html",
                                                   "favourite_area.html"]))

    def windowClosing(self, windowEvent):
        self.close_dialog()

    def close_dialog(self, e=None):
        #delete favourite zone editing layer if present
        self.remove_new_zone_editing_layer()
        self.dispose()
        self.app.preferencesFrame.setEnabled(True)
        self.app.preferencesFrame.toFront()
Esempio n. 6
0
class BurpExtender(IBurpExtender, ITab, IContextMenuFactory, DocumentListener, ChangeListener):

    #
    # implement IBurpExtender
    #
    def	registerExtenderCallbacks(self, callbacks):
        print "PhantomJS RIA Crawler extension"
        print "Nikolay Matyunin @autorak <*****@*****.**>"

        # keep a reference to our callbacks object and helpers object
        self._callbacks = callbacks
        self._helpers = callbacks.getHelpers()

        # extension name
        callbacks.setExtensionName("Phantom RIA Crawler")

        # Create Tab UI components
        self._jPanel = JPanel()
        self._jPanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

        _titleLabel = JLabel("Phantom RIA Crawler", SwingConstants.LEFT)
        _titleLabelFont = _titleLabel.font
        _titleLabelFont = _titleLabelFont.deriveFont(Font.BOLD, 12);
        _titleLabel.setFont(_titleLabelFont);
        _titleLabel.setForeground(Color(230, 142, 11))

        self._addressTextField = JTextField('')
        self._addressTextField.setColumns(50)
        _addressTextLabel = JLabel("Target URL:", SwingConstants.RIGHT)
        self._addressTextField.getDocument().addDocumentListener(self)

        self._phantomJsPathField = JTextField('phantomjs') # TODO: set permanent config value
        self._phantomJsPathField.setColumns(50)
        _phantomJsPathLabel = JLabel("PhantomJS path:", SwingConstants.RIGHT)

        self._startButton = JToggleButton('Start', actionPerformed=self.startToggled)
        self._startButton.setEnabled(False)

        _requestsMadeLabel = JLabel("DEPs found:", SwingConstants.RIGHT)
        self._requestsMadeInfo = JLabel("", SwingConstants.LEFT)
        _statesFoundLabel = JLabel("States found:", SwingConstants.RIGHT)
        self._statesFoundInfo = JLabel("", SwingConstants.LEFT)

        _separator = JSeparator(SwingConstants.HORIZONTAL)

        _configLabel = JLabel("Crawling configuration:")
        self._configButton = JButton("Load config", actionPerformed=self.loadConfigClicked)
        self._configFile = ""

        _listenersLabel= JLabel("Burp proxy listener:", SwingConstants.RIGHT)
        self._listenersCombo = JComboBox()
        self._configTimer = Timer(5000, None)
        self._configTimer.actionPerformed = self._configUpdated
        self._configTimer.stop()
        self._configUpdated(None)

        self._commandClient = CommandClient(self)

        # Layout management
        self._groupLayout = GroupLayout(self._jPanel)
        self._jPanel.setLayout(self._groupLayout)
        self._groupLayout.setAutoCreateGaps(True)
        self._groupLayout.setAutoCreateContainerGaps(True)

        self._groupLayout.setHorizontalGroup(self._groupLayout.createParallelGroup()
            .addComponent(_titleLabel)
            .addGroup(self._groupLayout.createSequentialGroup()
                .addComponent(_addressTextLabel)
                .addGroup(self._groupLayout.createParallelGroup()
                    .addComponent(self._addressTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addGroup(self._groupLayout.createSequentialGroup()
                        .addComponent(_requestsMadeLabel)
                        .addComponent(self._requestsMadeInfo))
                    .addGroup(self._groupLayout.createSequentialGroup()
                        .addComponent(_statesFoundLabel)
                        .addComponent(self._statesFoundInfo)))
                .addComponent(self._startButton))
            .addComponent(_separator)
            .addGroup(self._groupLayout.createSequentialGroup()
                .addComponent(_configLabel)
                .addComponent(self._configButton))
            .addGroup(self._groupLayout.createSequentialGroup()
                .addComponent(_phantomJsPathLabel)
                .addComponent(self._phantomJsPathField, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
            .addGroup(self._groupLayout.createSequentialGroup()
                .addComponent(_listenersLabel)
                .addComponent(self._listenersCombo, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
        )

        self._groupLayout.setVerticalGroup(self._groupLayout.createSequentialGroup()
            .addComponent(_titleLabel)
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_addressTextLabel)
                .addComponent(self._addressTextField)
                .addComponent(self._startButton))
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_requestsMadeLabel)
                .addComponent(self._requestsMadeInfo))
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_statesFoundLabel)
                .addComponent(self._statesFoundInfo))
            .addComponent(_separator, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_configLabel)
                .addComponent(self._configButton))
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_phantomJsPathLabel)
                .addComponent(self._phantomJsPathField))
            .addGroup(self._groupLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(_listenersLabel)
                .addComponent(self._listenersCombo))
        )

        self._groupLayout.linkSize(SwingConstants.HORIZONTAL, _configLabel, _phantomJsPathLabel);
        self._groupLayout.linkSize(SwingConstants.HORIZONTAL, _configLabel, _listenersLabel);
        self._groupLayout.linkSize(SwingConstants.HORIZONTAL, _statesFoundLabel, _requestsMadeLabel);


        # context menu data
        self._contextMenuData = None;
        self._running = False;

        # register callbacks
        callbacks.customizeUiComponent(self._jPanel)
        callbacks.registerContextMenuFactory(self)
        callbacks.addSuiteTab(self)

        return

    #
    # implement ITab and Tab ChangeListener
    #
    def getTabCaption(self):
        return "Phantom RIA Crawler"
    def getUiComponent(self):
        return self._jPanel
    def stateChanged(self, ev):
        self._configUpdated()

    def _configUpdated(self, ev):
        config = self._callbacks.saveConfig()

        # update proxy listeners
        index = 0
        listeners = DefaultComboBoxModel()
        while (("proxy.listener" + str(index)) in config):
            listenerItem = config["proxy.listener" + str(index)]
            listenerItems = listenerItem.split(".")
            if (listenerItems[0] == "1"):
                address = ".".join(listenerItems[2][1:].split("|"))
                if (len(address) == 0):
                    address = "127.0.0.1"
                listeners.addElement(address + " : " + listenerItems[1])

            index = index + 1
        self._listenersCombo.setModel(listeners)
        return;

    #
    # implement button actions
    #
    def startToggled(self, ev):
        if (self._startButton.getModel().isSelected()):
            try:
                os.chdir(sys.path[0] + os.sep + "riacrawler" + os.sep + "scripts")
            except Exception as e:
                print >> sys.stderr, "RIA crawler scripts loading error", "I/O error({0}): {1}".format(e.errno, e.strerror)
                self._startButton.setSelected(False)
                return

            phantomJsPath = self._phantomJsPathField.text
            target = self._addressTextField.text

            config = "crawler.config"
            if (self._configFile):
                config = self._configFile

            listenerAddress = self._listenersCombo.getSelectedItem().replace(" ", "")
            p = Popen("{0} --proxy={3} main.js --target={1} --config={2}".format(phantomJsPath, target, config, listenerAddress), shell=True)
            self._running = True
            self._requestsMadeInfo.setText("")
            self._statesFoundInfo.setText("")
            self._commandClient.startCrawling()
        else:
            if (self._running):
                self._commandClient.stopCrawling()
            self._running = False

    def syncCrawlingState(self, result):
        print "RIA crawling state: ", result
        self._requestsMadeInfo.setText(str(result["requests_made"]))
        self._statesFoundInfo.setText(str(result["states_detected"]))
        if (result["running"] == False):
            self._commandClient.stopCrawling()
            self._running = False
            self._startButton.setSelected(False)

    def loadConfigClicked(self, ev):
        openFile = JFileChooser();
        openFile.showOpenDialog(None);
        self._configFile = openFile.getSelectedFile()

    #
    # implement DocumentListener for _addressTextField
    #
    def removeUpdate(self, ev):
        self.updateStartButton()
    def insertUpdate(self, ev):
        self.updateStartButton()
    def updateStartButton(self):
        self._startButton.setEnabled(len(self._addressTextField.text) > 0)


    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, contextMenuInvocation):
        menuItemList = ArrayList()

        context = contextMenuInvocation.getInvocationContext()
        if (context == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST or context == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST or
            context == IContextMenuInvocation.CONTEXT_PROXY_HISTORY or context == IContextMenuInvocation.CONTEXT_TARGET_SITE_MAP_TABLE):

            self._contextMenuData = contextMenuInvocation.getSelectedMessages()
            menuItemList.add(JMenuItem("Send to Phantom RIA Crawler", actionPerformed = self.menuItemClicked))

        return menuItemList


    def menuItemClicked(self, event):
        if (self._running == True):
            self._callbacks.issueAlert("Can't set data to Phantom RIA Crawler: crawling is running already.")
            return;

        dataIsSet = False;
        for message in self._contextMenuData:
            request = self._helpers.analyzeRequest(message)

            url = request.getUrl().toString()
            print url
            if (url):
                dataisSet = True;
                self._addressTextField.setText(url)
Esempio n. 7
0
class ConfigurableConfigPanel(ConfigPanel, ActionListener, DocumentListener, ChangeListener):
    """ generated source for class ConfigurableConfigPanel """
    serialVersionUID = 1L
    associatedFile = File()
    associatedFileField = JTextField()
    params = JSONObject()
    savedParams = str()
    loadButton = JButton()
    saveAsButton = JButton()
    saveButton = JButton()
    name = JTextField()
    strategy = JComboBox()
    metagameStrategy = JComboBox()
    stateMachine = JComboBox()
    cacheStateMachine = JCheckBox()
    maxPlys = JSpinner()
    heuristicFocus = JSpinner()
    heuristicMobility = JSpinner()
    heuristicOpponentFocus = JSpinner()
    heuristicOpponentMobility = JSpinner()
    mcDecayRate = JSpinner()
    rightPanel = JPanel()

    def __init__(self):
        """ generated source for method __init__ """
        super(ConfigurableConfigPanel, self).__init__(GridBagLayout())
        leftPanel = JPanel(GridBagLayout())
        leftPanel.setBorder(TitledBorder("Major Parameters"))
        self.rightPanel = JPanel(GridBagLayout())
        self.rightPanel.setBorder(TitledBorder("Minor Parameters"))
        self.strategy = JComboBox([None]*)
        self.metagameStrategy = JComboBox([None]*)
        self.stateMachine = JComboBox([None]*)
        self.cacheStateMachine = JCheckBox()
        self.maxPlys = JSpinner(SpinnerNumberModel(1, 1, 100, 1))
        self.heuristicFocus = JSpinner(SpinnerNumberModel(1, 0, 10, 1))
        self.heuristicMobility = JSpinner(SpinnerNumberModel(1, 0, 10, 1))
        self.heuristicOpponentFocus = JSpinner(SpinnerNumberModel(1, 0, 10, 1))
        self.heuristicOpponentMobility = JSpinner(SpinnerNumberModel(1, 0, 10, 1))
        self.mcDecayRate = JSpinner(SpinnerNumberModel(0, 0, 99, 1))
        self.name = JTextField()
        self.name.setColumns(20)
        self.name.setText("Player #" + Random().nextInt(100000))
        self.loadButton = JButton(loadButtonMethod())
        self.saveButton = JButton(saveButtonMethod())
        self.saveAsButton = JButton(saveAsButtonMethod())
        self.associatedFileField = JTextField()
        self.associatedFileField.setEnabled(False)
        buttons = JPanel()
        buttons.add(self.loadButton)
        buttons.add(self.saveButton)
        buttons.add(self.saveAsButton)
        nRow = 0
        leftPanel.add(JLabel("Name"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_0 = nRow
        nRow += 1
        leftPanel.add(self.name, GridBagConstraints(1, __nRow_0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, Insets(5, 5, 5, 5), 5, 5))
        leftPanel.add(JLabel("Gaming Strategy"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_1 = nRow
        nRow += 1
        leftPanel.add(self.strategy, GridBagConstraints(1, __nRow_1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, Insets(5, 5, 5, 5), 5, 5))
        leftPanel.add(JLabel("Metagame Strategy"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_2 = nRow
        nRow += 1
        leftPanel.add(self.metagameStrategy, GridBagConstraints(1, __nRow_2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, Insets(5, 5, 5, 5), 5, 5))
        leftPanel.add(JLabel("State Machine"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_3 = nRow
        nRow += 1
        leftPanel.add(self.stateMachine, GridBagConstraints(1, __nRow_3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, Insets(5, 5, 5, 5), 5, 5))
        __nRow_4 = nRow
        nRow += 1
        leftPanel.add(buttons, GridBagConstraints(1, __nRow_4, 2, 1, 1.0, 1.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, Insets(5, 5, 0, 5), 0, 0))
        leftPanel.add(self.associatedFileField, GridBagConstraints(0, nRow, 2, 1, 1.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.HORIZONTAL, Insets(0, 5, 5, 5), 0, 0))
        layoutRightPanel()
        add(leftPanel, GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, Insets(5, 5, 5, 5), 5, 5))
        add(self.rightPanel, GridBagConstraints(1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, Insets(5, 5, 5, 5), 5, 5))
        self.params = JSONObject()
        syncJSONtoUI()
        self.strategy.addActionListener(self)
        self.metagameStrategy.addActionListener(self)
        self.stateMachine.addActionListener(self)
        self.cacheStateMachine.addActionListener(self)
        self.maxPlys.addChangeListener(self)
        self.heuristicFocus.addChangeListener(self)
        self.heuristicMobility.addChangeListener(self)
        self.heuristicOpponentFocus.addChangeListener(self)
        self.heuristicOpponentMobility.addChangeListener(self)
        self.mcDecayRate.addChangeListener(self)
        self.name.getDocument().addDocumentListener(self)

    def layoutRightPanel(self):
        """ generated source for method layoutRightPanel """
        nRow = 0
        self.rightPanel.removeAll()
        self.rightPanel.add(JLabel("State machine cache?"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_5 = nRow
        nRow += 1
        self.rightPanel.add(self.cacheStateMachine, GridBagConstraints(1, __nRow_5, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        if self.strategy.getSelectedItem().__str__() == "Heuristic":
        __nRow_6 = nRow
        nRow += 1
        __nRow_7 = nRow
        nRow += 1
        __nRow_8 = nRow
        nRow += 1
        __nRow_9 = nRow
        nRow += 1
        __nRow_10 = nRow
        nRow += 1
            self.rightPanel.add(JLabel("Max plys?"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.maxPlys, GridBagConstraints(1, __nRow_6, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(JLabel("Focus Heuristic Weight"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.heuristicFocus, GridBagConstraints(1, __nRow_7, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(JLabel("Mobility Heuristic Weight"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.heuristicMobility, GridBagConstraints(1, __nRow_8, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(JLabel("Opponent Focus Heuristic Weight"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.heuristicOpponentFocus, GridBagConstraints(1, __nRow_9, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(JLabel("Opponent Mobility Heuristic Weight"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.heuristicOpponentMobility, GridBagConstraints(1, __nRow_10, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        if self.strategy.getSelectedItem().__str__() == "Monte Carlo":
        __nRow_11 = nRow
        nRow += 1
            self.rightPanel.add(JLabel("Goal Decay Rate"), GridBagConstraints(0, nRow, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
            self.rightPanel.add(self.mcDecayRate, GridBagConstraints(1, __nRow_11, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        __nRow_12 = nRow
        nRow += 1
        self.rightPanel.add(JLabel(), GridBagConstraints(2, __nRow_12, 1, 1, 1.0, 1.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, Insets(5, 5, 5, 5), 5, 5))
        self.rightPanel.repaint()

    @SuppressWarnings("unchecked")
    def getParameter(self, name, defaultValue):
        """ generated source for method getParameter """
        try:
            if self.params.has(name):
                return self.params.get(name)
            else:
                return defaultValue
        except JSONException as je:
            return defaultValue

    def actionPerformed(self, arg0):
        """ generated source for method actionPerformed """
        if arg0.getSource() == self.strategy:
            self.layoutRightPanel()
        syncJSONtoUI()

    def changedUpdate(self, e):
        """ generated source for method changedUpdate """
        syncJSONtoUI()

    def insertUpdate(self, e):
        """ generated source for method insertUpdate """
        syncJSONtoUI()

    def removeUpdate(self, e):
        """ generated source for method removeUpdate """
        syncJSONtoUI()

    def stateChanged(self, arg0):
        """ generated source for method stateChanged """
        syncJSONtoUI()

    def syncJSONtoUI(self):
        """ generated source for method syncJSONtoUI """
        if settingUI:
            return
        self.params = getJSONfromUI()
        self.saveButton.setEnabled(self.savedParams == None or not self.params.__str__() == self.savedParams)

    def getJSONfromUI(self):
        """ generated source for method getJSONfromUI """
        newParams = JSONObject()
        try:
            if not self.name.getText().isEmpty():
                newParams.put("name", self.name.getText())
            newParams.put("strategy", self.strategy.getSelectedItem().__str__())
            newParams.put("metagameStrategy", self.metagameStrategy.getSelectedItem().__str__())
            newParams.put("stateMachine", self.stateMachine.getSelectedItem().__str__())
            newParams.put("cacheStateMachine", self.cacheStateMachine.isSelected())
            newParams.put("maxPlys", self.maxPlys.getModel().getValue())
            newParams.put("heuristicFocus", self.heuristicFocus.getModel().getValue())
            newParams.put("heuristicMobility", self.heuristicMobility.getModel().getValue())
            newParams.put("heuristicOpponentFocus", self.heuristicOpponentFocus.getModel().getValue())
            newParams.put("heuristicOpponentMobility", self.heuristicOpponentMobility.getModel().getValue())
            newParams.put("mcDecayRate", self.mcDecayRate.getModel().getValue())
        except JSONException as je:
            je.printStackTrace()
        return newParams

    settingUI = False

    def setUIfromJSON(self):
        """ generated source for method setUIfromJSON """
        self.settingUI = True
        try:
            if self.params.has("name"):
                self.name.setText(self.params.getString("name"))
            if self.params.has("strategy"):
                self.strategy.setSelectedItem(self.params.getString("strategy"))
            if self.params.has("metagameStrategy"):
                self.metagameStrategy.setSelectedItem(self.params.getString("metagameStrategy"))
            if self.params.has("stateMachine"):
                self.stateMachine.setSelectedItem(self.params.getString("stateMachine"))
            if self.params.has("cacheStateMachine"):
                self.cacheStateMachine.setSelected(self.params.getBoolean("cacheStateMachine"))
            if self.params.has("maxPlys"):
                self.maxPlys.getModel().setValue(self.params.getInt("maxPlys"))
            if self.params.has("heuristicFocus"):
                self.heuristicFocus.getModel().setValue(self.params.getInt("heuristicFocus"))
            if self.params.has("heuristicMobility"):
                self.heuristicMobility.getModel().setValue(self.params.getInt("heuristicMobility"))
            if self.params.has("heuristicOpponentFocus"):
                self.heuristicOpponentFocus.getModel().setValue(self.params.getInt("heuristicOpponentFocus"))
            if self.params.has("heuristicOpponentMobility"):
                self.heuristicOpponentMobility.getModel().setValue(self.params.getInt("heuristicOpponentMobility"))
            if self.params.has("mcDecayRate"):
                self.mcDecayRate.getModel().setValue(self.params.getInt("mcDecayRate"))
        except JSONException as je:
            je.printStackTrace()
        finally:
            self.settingUI = False

    def loadParamsJSON(self, fromFile):
        """ generated source for method loadParamsJSON """
        if not fromFile.exists():
            return
        self.associatedFile = fromFile
        self.associatedFileField.setText(self.associatedFile.getPath())
        self.params = JSONObject()
        try:
            try:
                while (line = br.readLine()) != None:
                    pdata.append(line)
            finally:
                br.close()
            self.params = JSONObject(pdata.__str__())
            self.savedParams = self.params.__str__()
            self.setUIfromJSON()
            self.syncJSONtoUI()
        except Exception as e:
            e.printStackTrace()

    def saveParamsJSON(self, saveAs):
        """ generated source for method saveParamsJSON """
        try:
            if saveAs or self.associatedFile == None:
                fc.setFileFilter(PlayerFilter())
                if returnVal == JFileChooser.APPROVE_OPTION and fc.getSelectedFile() != None:
                    if toFile.__name__.contains("."):
                        self.associatedFile = File(toFile.getParentFile(), toFile.__name__.substring(0, toFile.__name__.lastIndexOf(".")) + ".player")
                    else:
                        self.associatedFile = File(toFile.getParentFile(), toFile.__name__ + ".player")
                    self.associatedFileField.setText(self.associatedFile.getPath())
                else:
                    return
            bw.write(self.params.__str__())
            bw.close()
            self.savedParams = self.params.__str__()
            self.syncJSONtoUI()
        except IOException as ie:
            ie.printStackTrace()

    def saveButtonMethod(self):
        """ generated source for method saveButtonMethod """
        return AbstractAction("Save")

    def saveAsButtonMethod(self):
        """ generated source for method saveAsButtonMethod """
        return AbstractAction("Save As")

    def loadButtonMethod(self):
        """ generated source for method loadButtonMethod """
        return AbstractAction("Load")

    class PlayerFilter(FileFilter):
        """ generated source for class PlayerFilter """
        def accept(self, f):
            """ generated source for method accept """
            if f.isDirectory():
                return True
            return f.__name__.endsWith(".player")

        def getDescription(self):
            """ generated source for method getDescription """
            return "GGP Players (*.player)"
Esempio n. 8
0
class PreferencesFrame(JFrame, ActionListener, WindowListener, ItemListener,
                       HyperlinkListener):
    """Dialog with preferences
    """
    def __init__(self, parent, title, app):
        from javax.swing import JCheckBox, JRadioButton, ButtonGroup
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 5, 7)
        self.getContentPane().setBorder(border)
        self.getContentPane().setLayout(BorderLayout(0, 5))
        self.tabbedPane = JTabbedPane()

        #1 Tab: general
        panel1 = JPanel()
        panel1.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        panel1.setLayout(BoxLayout(panel1, BoxLayout.PAGE_AXIS))

        #Checkbutton to enable/disable update check when script starts
        self.updateCBtn = JCheckBox(self.app.strings.getString("updateCBtn"))
        self.updateCBtn.setToolTipText(
            self.app.strings.getString("updateCBtn_tooltip"))

        #Download tools
        downloadBtn = JButton(self.app.strings.getString("updatesBtn"),
                              ImageProvider.get("dialogs", "refresh"),
                              actionPerformed=self.on_downloadBtn_clicked)
        downloadBtn.setToolTipText(
            self.app.strings.getString("updatesBtn_tooltip"))

        #Checkbuttons for enabling/disabling tools
        toolsPanel = JPanel(BorderLayout(0, 5))
        title = self.app.strings.getString("enable_disable_tools")
        toolsPanel.setBorder(BorderFactory.createTitledBorder(title))
        infoLbl = JLabel(self.app.strings.getString("JOSM_restart_warning"))
        infoLbl.setFont(infoLbl.getFont().deriveFont(Font.ITALIC))
        toolsPanel.add(infoLbl, BorderLayout.PAGE_START)

        toolsStatusPane = JPanel(GridLayout(len(self.app.realTools), 0))
        self.toolsCBtns = []
        for tool in self.app.realTools:
            toolCBtn = JCheckBox()
            toolCBtn.addItemListener(self)
            toolLbl = JLabel(tool.title, tool.bigIcon, JLabel.LEFT)
            self.toolsCBtns.append(toolCBtn)

            toolPane = JPanel()
            toolPane.setLayout(BoxLayout(toolPane, BoxLayout.X_AXIS))
            toolPane.add(toolCBtn)
            toolPane.add(toolLbl)
            toolsStatusPane.add(toolPane)
        toolsPanel.add(toolsStatusPane, BorderLayout.CENTER)

        #Radiobuttons for enabling/disabling layers when a new one
        #is added
        layersPanel = JPanel(GridLayout(0, 1))
        title = self.app.strings.getString("errors_layers_manager")
        layersPanel.setBorder(BorderFactory.createTitledBorder(title))
        errorLayersLbl = JLabel(
            self.app.strings.getString("errors_layers_info"))
        errorLayersLbl.setFont(errorLayersLbl.getFont().deriveFont(
            Font.ITALIC))
        layersPanel.add(errorLayersLbl)
        self.layersRBtns = {}
        group = ButtonGroup()
        for mode in self.app.layersModes:
            layerRBtn = JRadioButton(self.app.strings.getString("%s" % mode))
            group.add(layerRBtn)
            layersPanel.add(layerRBtn)
            self.layersRBtns[mode] = layerRBtn

        #Max number of errors text field
        self.maxErrorsNumberTextField = JTextField()
        self.maxErrorsNumberTextField.setToolTipText(
            self.app.strings.getString("maxErrorsNumberTextField_tooltip"))
        self.maxErrorsNumberTFieldDefaultBorder = self.maxErrorsNumberTextField.getBorder(
        )
        self.maxErrorsNumberTextField.getDocument().addDocumentListener(
            ErrNumTextListener(self))

        #layout
        self.updateCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(self.updateCBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        downloadBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(downloadBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        toolsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(toolsPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        layersPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(layersPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        maxErrP = JPanel(BorderLayout(5, 0))
        maxErrP.add(JLabel(self.app.strings.getString("max_errors_number")),
                    BorderLayout.LINE_START)
        maxErrP.add(self.maxErrorsNumberTextField, BorderLayout.CENTER)
        p = JPanel(BorderLayout())
        p.add(maxErrP, BorderLayout.PAGE_START)
        p.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_1_title"), None,
                               panel1, None)

        #2 Tab: favourite zones
        panel2 = JPanel(BorderLayout(5, 15))
        panel2.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))

        #status
        topPanel = JPanel()
        topPanel.setLayout(BoxLayout(topPanel, BoxLayout.Y_AXIS))
        infoPanel = HtmlPanel(self.app.strings.getString("fav_zones_info"))
        infoPanel.getEditorPane().addHyperlinkListener(self)
        infoPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.favZoneStatusCBtn = JCheckBox(
            self.app.strings.getString("activate_fav_area"),
            actionListener=self)
        self.favZoneStatusCBtn.setToolTipText(
            self.app.strings.getString("activate_fav_area_tooltip"))
        self.favZoneStatusCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        topPanel.add(infoPanel)
        topPanel.add(Box.createRigidArea(Dimension(0, 10)))
        topPanel.add(self.favZoneStatusCBtn)
        #table
        self.zonesTable = JTable()
        tableSelectionModel = self.zonesTable.getSelectionModel()
        tableSelectionModel.addListSelectionListener(ZonesTableListener(self))
        columns = [
            "",
            self.app.strings.getString("Type"),
            self.app.strings.getString("Name")
        ]
        tableModel = ZonesTableModel([], columns)
        self.zonesTable.setModel(tableModel)
        self.scrollPane = JScrollPane(self.zonesTable)
        #map
        self.zonesMap = JMapViewer()
        self.zonesMap.setZoomContolsVisible(False)
        self.zonesMap.setMinimumSize(Dimension(100, 200))

        #buttons
        self.removeBtn = JButton(self.app.strings.getString("Remove"),
                                 ImageProvider.get("dialogs", "delete"),
                                 actionPerformed=self.on_removeBtn_clicked)
        self.removeBtn.setToolTipText(
            self.app.strings.getString("remove_tooltip"))
        newBtn = JButton(self.app.strings.getString("New"),
                         ImageProvider.get("dialogs", "add"),
                         actionPerformed=self.on_newBtn_clicked)
        newBtn.setToolTipText(self.app.strings.getString("new_tooltip"))

        #layout
        panel2.add(topPanel, BorderLayout.PAGE_START)
        panel2.add(self.scrollPane, BorderLayout.LINE_START)
        panel2.add(self.zonesMap, BorderLayout.CENTER)
        self.buttonsPanel = JPanel()
        self.buttonsPanel.add(self.removeBtn)
        self.buttonsPanel.add(newBtn)
        panel2.add(self.buttonsPanel, BorderLayout.PAGE_END)

        self.tabbedPane.addTab(self.app.strings.getString("tab_2_title"), None,
                               panel2, None)

        #3 Tab Tools options
        panel3 = JPanel()
        panel3.setLayout(BoxLayout(panel3, BoxLayout.Y_AXIS))
        panel3.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        for tool in self.app.realTools:
            if hasattr(tool, 'prefs'):
                p = JPanel(FlowLayout(FlowLayout.LEFT))
                p.setBorder(BorderFactory.createTitledBorder(tool.title))
                p.add(tool.prefsGui)
                panel3.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_3_title"), None,
                               panel3, None)

        self.add(self.tabbedPane, BorderLayout.CENTER)

        exitPanel = JPanel()
        saveBtn = JButton(self.app.strings.getString("OK"),
                          ImageProvider.get("ok"),
                          actionPerformed=self.on_saveBtn_clicked)
        cancelBtn = JButton(self.app.strings.getString("cancel"),
                            ImageProvider.get("cancel"),
                            actionPerformed=self.on_cancelBtn_clicked)
        saveBtn.setToolTipText(self.app.strings.getString("save_preferences"))
        saveBtn.setAlignmentX(0.5)
        exitPanel.add(saveBtn)
        exitPanel.add(cancelBtn)
        self.add(exitPanel, BorderLayout.PAGE_END)

        self.addWindowListener(self)
        self.pack()

    def windowClosing(self, windowEvent):
        self.on_cancelBtn_clicked()

    def hyperlinkUpdate(self, e):
        if e.getEventType() == HyperlinkEvent.EventType.ACTIVATED:
            OpenBrowser.displayUrl(e.getURL().toString())

    def itemStateChanged(self, e):
        """A ttol has been activated/deactivated.
           Check if at least one tool is on.
        """
        if all(not button.isSelected() for button in self.toolsCBtns):
            JOptionPane.showMessageDialog(
                Main.parent,
                self.app.strings.getString("tools_disabled_warning"),
                self.app.strings.getString("tools_disabled_warning_title"),
                JOptionPane.WARNING_MESSAGE)
            source = e.getItemSelectable()
            source.setSelected(True)

    def actionPerformed(self, e=None):
        """Enable/disable favourite zones panel
        """
        for container in (self.scrollPane, self.buttonsPanel):
            self.enableComponents(container,
                                  self.favZoneStatusCBtn.isSelected())
        if self.favZoneStatusCBtn.isSelected():
            self.check_removeBtn_status()

    def enableComponents(self, container, enable):
        components = container.getComponents()
        for component in components:
            component.setEnabled(enable)
            if isinstance(component, Container):
                self.enableComponents(component, enable)

    def on_downloadBtn_clicked(self, e):
        update_checker.Updater(self.app, "manual")

    def clean_map(self):
        """Remove all rectangles and polygons from the map
        """
        self.zonesMap.removeAllMapRectangles()
        self.zonesMap.removeAllMapPolygons()

    def update_gui_from_preferences(self):
        """Update gui status of preferences frame from config file
        """
        #print "\n- updating Preferences gui"
        onOff = {"on": True, "off": False}
        #1 Tab
        #check for update
        self.updateCBtn.setSelected(onOff[self.app.checkUpdate])

        #tools status, enabled or not
        for toolIndex, tool in enumerate(self.app.realTools):
            if "tool.%s" % tool.name in self.app.properties.keys():
                configstatus = self.app.properties.getProperty("tool.%s" %
                                                               tool.name)
            else:
                configstatus = "on"  # new tool
            self.toolsCBtns[toolIndex].setSelected(onOff[configstatus])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            button.setSelected(mode == self.app.layersMode)

        #max errors number
        self.maxErrorsNumberTextField.setText(str(self.app.maxErrorsNumber))

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()

        #2 Tab
        #favourite area
        self.update_favourite_area_gui_from_preferences()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                tool.prefsGui.update_gui(tool.prefs)

    def update_favourite_area_gui_from_preferences(self):
        #status
        self.favZoneStatusCBtn.setSelected(self.app.favouriteZoneStatus)
        #table
        #store zones to a temporary list, used to store changes
        #and save them when preferences dialog is closed
        self.app.tempZones = list(self.app.zones)
        self.zonesTable.getModel().setNumRows(0)
        for zone in self.app.tempZones:
            self.zonesTable.getModel().addRow(
                [zone.country, zone.icon, zone.name])
        if self.app.favZone is not None:
            selectedRow = self.app.tempZones.index(self.app.favZone)
            self.zonesTable.setRowSelectionInterval(selectedRow, selectedRow)
        self.zonesTable.getColumnModel().getColumn(0).setMaxWidth(30)
        self.zonesTable.getColumnModel().getColumn(1).setMaxWidth(50)
        #enable or disable favourite zone buttons
        self.actionPerformed()

### fav area editing buttons ###########################################

    def on_removeBtn_clicked(self, e):
        rowsNum = self.zonesTable.getSelectedRows()
        rowsNum.reverse()
        for rowNum in rowsNum:
            del self.app.tempZones[rowNum]
            self.zonesTable.getModel().removeRow(rowNum)
        if len(self.app.tempZones) != 0:
            if rowNum == 0:
                self.zonesTable.setRowSelectionInterval(0, 0)
            else:
                self.zonesTable.setRowSelectionInterval(rowNum - 1, rowNum - 1)
        self.check_removeBtn_status()

    def check_removeBtn_status(self):
        if self.app.tempZones != [] and len(
                self.zonesTable.getSelectedRows()) != 0:
            self.removeBtn.setEnabled(True)
        else:
            self.removeBtn.setEnabled(False)
            self.clean_map()

    def on_newBtn_clicked(self, e):
        try:
            self.newZoneDialog
        except AttributeError:
            self.newZoneDialog = NewZoneDialog(self.app)
        bbox = self.app.get_frame_bounds()
        self.app.newZone = Zone(self.app,
                                self.app.strings.getString("New_zone"),
                                "rectangle",
                                ",".join(["%0.4f" % x for x in bbox]), "")
        self.newZoneDialog.update_gui_from_preferences()
        self.newZoneDialog.show()

### Exit from preferences ##############################################

    def on_cancelBtn_clicked(self, event=None):
        if hasattr(self, "newZoneDialog") and self.newZoneDialog.isVisible():
            self.newZoneDialog.close_dialog()
        self.dispose()

    def on_saveBtn_clicked(self, event):
        """Read preferences from gui and save them to config.properties
           file
        """
        #print "\n- saving preferences to config file"
        onOff = {True: "on", False: "off"}

        #1 Tab
        #check for update
        self.app.properties.setProperty("check_for_update",
                                        onOff[self.updateCBtn.isSelected()])
        #tools status
        for toolIndex, tool in enumerate(self.app.realTools):
            prop = "tool.%s" % tool.name
            toolCBtn = self.toolsCBtns[toolIndex]
            self.app.properties.setProperty(prop, onOff[toolCBtn.isSelected()])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            if button.isSelected():
                self.app.properties.setProperty("layers_mode", mode)
                break

        #max errors number
        try:
            num = Integer.parseInt(self.maxErrorsNumberTextField.getText())
        except NumberFormatException:
            num = ""
        self.app.properties.setProperty("max_errors_number", str(num))

        #2 Tab
        #Favourite zones
        changes = {
            "new": [z for z in self.app.tempZones if not z in self.app.zones],
            "deleted":
            [z for z in self.app.zones if not z in self.app.tempZones]
        }
        #delete files of removed favourite zones
        for zone in changes["deleted"]:
            f = File(
                File.separator.join([
                    self.app.SCRIPTDIR, "configuration", "favourite_zones",
                    "%s.txt" % zone.name
                ]))
            f.delete()
        #create files for new favourite zones
        for zone in changes["new"]:
            print "\nsave new zone", zone.name
            fileName = File.separator.join([
                self.app.SCRIPTDIR, "configuration", "favourite_zones",
                "%s.txt" % zone.name
            ])
            f = open(fileName, "w")
            zoneData = zone.geomString
            if zone.country != "":
                zoneData += "|" + zone.country
            f.write(zoneData.encode("utf-8"))
            f.close()

        self.app.zones = self.app.tempZones
        if len(self.app.zones) == 0:
            self.app.favZone = None
            self.app.properties.setProperty("favourite_area.name", "")
            self.favZoneStatusCBtn.setSelected(False)
        else:
            if len(self.zonesTable.getSelectedRows()) == 0:
                self.app.favZone = self.app.zones[0]
            else:
                self.app.favZone = self.app.zones[
                    self.zonesTable.getSelectedRows()[0]]
            self.app.properties.setProperty("favourite_area.name",
                                            self.app.favZone.name)
        favZoneStatus = self.favZoneStatusCBtn.isSelected()
        self.app.properties.setProperty("favourite_area.status",
                                        onOff[favZoneStatus])
        self.app.favouriteZoneStatus = favZoneStatus

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                for pref, value in tool.prefsGui.read_gui().iteritems():
                    prefKey = "tool.%s.%s" % (tool.name, pref)
                    self.app.properties.setProperty(prefKey, value)

        self.app.save_config()
        self.dispose()
Esempio n. 9
0
class NewZoneDialog(JDialog, ActionListener, WindowListener):
    """Dialog for favourite zone editing
    """
    def __init__(self, app):
        from java.awt import Dialog
        from java.awt import CardLayout
        JDialog.__init__(self,
                         app.preferencesFrame,
                         app.strings.getString("Create_a_new_favourite_zone"),
                         Dialog.ModalityType.DOCUMENT_MODAL)
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 7, 7)
        self.getContentPane().setBorder(border)
        self.setLayout(BoxLayout(self.getContentPane(), BoxLayout.Y_AXIS))

        self.FAVAREALAYERNAME = "Favourite zone editing"

        info = JLabel(self.app.strings.getString("Create_a_new_favourite_zone"))
        info.setAlignmentX(Component.LEFT_ALIGNMENT)

        #Name
        nameLbl = JLabel(self.app.strings.getString("fav_zone_name"))
        self.nameTextField = JTextField(20)
        self.nameTextField.setMaximumSize(self.nameTextField.getPreferredSize())
        self.nameTextField.setToolTipText(self.app.strings.getString("fav_zone_name_tooltip"))
        namePanel = JPanel()
        namePanel.setLayout(BoxLayout(namePanel, BoxLayout.X_AXIS))
        namePanel.add(nameLbl)
        namePanel.add(Box.createHorizontalGlue())
        namePanel.add(self.nameTextField)

        #Country
        countryLbl = JLabel(self.app.strings.getString("fav_zone_country"))
        self.countryTextField = JTextField(20)
        self.countryTextField.setMaximumSize(self.countryTextField.getPreferredSize())
        self.countryTextField.setToolTipText(self.app.strings.getString("fav_zone_country_tooltip"))
        countryPanel = JPanel()
        countryPanel.setLayout(BoxLayout(countryPanel, BoxLayout.X_AXIS))
        countryPanel.add(countryLbl)
        countryPanel.add(Box.createHorizontalGlue())
        countryPanel.add(self.countryTextField)

        #Type
        modeLbl = JLabel(self.app.strings.getString("fav_zone_type"))
        RECTPANEL = "rectangle"
        POLYGONPANEL = "polygon"
        BOUNDARYPANEL = "boundary"
        self.modesStrings = [RECTPANEL, POLYGONPANEL, BOUNDARYPANEL]
        modesComboModel = DefaultComboBoxModel()
        for i in (self.app.strings.getString("rectangle"),
                  self.app.strings.getString("delimited_by_a_closed_way"),
                  self.app.strings.getString("delimited_by_an_administrative_boundary")):
            modesComboModel.addElement(i)
        self.modesComboBox = JComboBox(modesComboModel,
                                       actionListener=self,
                                       editable=False)

        #- Rectangle
        self.rectPanel = JPanel()
        self.rectPanel.setLayout(BoxLayout(self.rectPanel, BoxLayout.Y_AXIS))

        capturePane = JPanel()
        capturePane.setLayout(BoxLayout(capturePane, BoxLayout.X_AXIS))
        capturePane.setAlignmentX(Component.LEFT_ALIGNMENT)

        josmP = JPanel()
        self.captureRBtn = JRadioButton(self.app.strings.getString("capture_area"))
        self.captureRBtn.addActionListener(self)
        self.captureRBtn.setSelected(True)
        self.bboxFromJosmBtn = JButton(self.app.strings.getString("get_current_area"),
                                       actionPerformed=self.on_bboxFromJosmBtn_clicked)
        self.bboxFromJosmBtn.setToolTipText(self.app.strings.getString("get_capture_area_tooltip"))
        josmP.add(self.bboxFromJosmBtn)
        capturePane.add(self.captureRBtn)
        capturePane.add(Box.createHorizontalGlue())
        capturePane.add(self.bboxFromJosmBtn)

        manualPane = JPanel()
        manualPane.setLayout(BoxLayout(manualPane, BoxLayout.X_AXIS))
        manualPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.manualRBtn = JRadioButton(self.app.strings.getString("use_this_bbox"))
        self.manualRBtn.addActionListener(self)
        self.bboxTextField = JTextField(20)
        self.bboxTextField.setMaximumSize(self.bboxTextField.getPreferredSize())
        self.bboxTextField.setToolTipText(self.app.strings.getString("fav_bbox_tooltip"))
        self.bboxTextFieldDefaultBorder = self.bboxTextField.getBorder()
        self.bboxTextField.getDocument().addDocumentListener(TextListener(self))
        manualPane.add(self.manualRBtn)
        manualPane.add(Box.createHorizontalGlue())
        manualPane.add(self.bboxTextField)

        group = ButtonGroup()
        group.add(self.captureRBtn)
        group.add(self.manualRBtn)

        previewPane = JPanel()
        previewPane.setLayout(BoxLayout(previewPane, BoxLayout.X_AXIS))
        previewPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        bboxPreviewInfo = JTextField(self.app.strings.getString("coordinates"),
                                     editable=0,
                                     border=None)
        bboxPreviewInfo.setMaximumSize(bboxPreviewInfo.getPreferredSize())
        self.bboxPreviewTextField = JTextField(20,
                                               editable=0,
                                               border=None)
        self.bboxPreviewTextField.setMaximumSize(self.bboxPreviewTextField.getPreferredSize())
        previewPane.add(bboxPreviewInfo)
        previewPane.add(Box.createHorizontalGlue())
        previewPane.add(self.bboxPreviewTextField)

        self.rectPanel.add(capturePane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.rectPanel.add(manualPane)
        self.rectPanel.add(Box.createRigidArea(Dimension(0, 20)))
        self.rectPanel.add(previewPane)

        #- Polygon (closed way) drawn by hand
        self.polygonPanel = JPanel(BorderLayout())
        self.polygonPanel.setLayout(BoxLayout(self.polygonPanel, BoxLayout.Y_AXIS))

        polyInfo = JLabel("<html>%s</html>" % self.app.strings.getString("polygon_info"))
        polyInfo.setFont(polyInfo.getFont().deriveFont(Font.ITALIC))
        polyInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        editPolyPane = JPanel()
        editPolyPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        editPolyBtn = JButton(self.app.strings.getString("create_fav_layer"),
                              actionPerformed=self.create_new_zone_editing_layer)
        editPolyBtn.setToolTipText(self.app.strings.getString("create_fav_layer_tooltip"))
        editPolyPane.add(editPolyBtn)

        self.polygonPanel.add(polyInfo)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.polygonPanel.add(editPolyPane)
        self.polygonPanel.add(Box.createRigidArea(Dimension(0, 15)))

        #- Administrative Boundary
        self.boundaryPanel = JPanel()
        self.boundaryPanel.setLayout(BoxLayout(self.boundaryPanel, BoxLayout.Y_AXIS))

        boundaryInfo = JLabel("<html>%s</html>" % app.strings.getString("boundary_info"))
        boundaryInfo.setFont(boundaryInfo.getFont().deriveFont(Font.ITALIC))
        boundaryInfo.setAlignmentX(Component.LEFT_ALIGNMENT)

        boundaryTagsPanel = JPanel(GridLayout(3, 3, 5, 5))
        boundaryTagsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        boundaryTagsPanel.add(JLabel("name ="))
        self.nameTagTextField = JTextField(20)
        boundaryTagsPanel.add(self.nameTagTextField)
        boundaryTagsPanel.add(UrlLabel("http://wiki.openstreetmap.org/wiki/Key:admin_level#admin_level", "admin_level ="))
        self.adminLevelTagTextField = JTextField(20)
        self.adminLevelTagTextField.setToolTipText(self.app.strings.getString("adminLevel_tooltip"))
        boundaryTagsPanel.add(self.adminLevelTagTextField)
        boundaryTagsPanel.add(JLabel(self.app.strings.getString("other_tag")))
        self.optionalTagTextField = JTextField(20)
        self.optionalTagTextField.setToolTipText("key=value")
        boundaryTagsPanel.add(self.optionalTagTextField)

        downloadBoundariesPane = JPanel()
        downloadBoundariesPane.setAlignmentX(Component.LEFT_ALIGNMENT)
        downloadBoundariesBtn = JButton(self.app.strings.getString("download_boundary"),
                                        actionPerformed=self.on_downloadBoundariesBtn_clicked)
        downloadBoundariesBtn.setToolTipText(self.app.strings.getString("download_boundary_tooltip"))
        downloadBoundariesPane.add(downloadBoundariesBtn)

        self.boundaryPanel.add(boundaryInfo)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 15)))
        self.boundaryPanel.add(boundaryTagsPanel)
        self.boundaryPanel.add(Box.createRigidArea(Dimension(0, 10)))
        self.boundaryPanel.add(downloadBoundariesPane)

        self.editingPanels = {"rectangle": self.rectPanel,
                              "polygon": self.polygonPanel,
                              "boundary": self.boundaryPanel}

        #Main buttons
        self.okBtn = JButton(self.app.strings.getString("OK"),
                             ImageProvider.get("ok"),
                             actionPerformed=self.on_okBtn_clicked)
        self.cancelBtn = JButton(self.app.strings.getString("cancel"),
                                 ImageProvider.get("cancel"),
                                 actionPerformed=self.close_dialog)
        self.previewBtn = JButton(self.app.strings.getString("Preview_zone"),
                                  actionPerformed=self.on_previewBtn_clicked)
        self.previewBtn.setToolTipText(self.app.strings.getString("preview_zone_tooltip"))
        okBtnSize = self.okBtn.getPreferredSize()
        viewBtnSize = self.previewBtn.getPreferredSize()
        viewBtnSize.height = okBtnSize.height
        self.previewBtn.setPreferredSize(viewBtnSize)

        #layout
        self.add(info)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        namePanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(namePanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        countryPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(countryPanel)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        modeLbl.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(modeLbl)
        self.add(Box.createRigidArea(Dimension(0, 5)))

        self.add(self.modesComboBox)
        self.modesComboBox.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(Box.createRigidArea(Dimension(0, 15)))

        self.configPanel = JPanel(CardLayout())
        self.configPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5))
        self.configPanel.add(self.rectPanel, RECTPANEL)
        self.configPanel.add(self.polygonPanel, POLYGONPANEL)
        self.configPanel.add(self.boundaryPanel, BOUNDARYPANEL)
        self.configPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(self.configPanel)
        buttonsPanel = JPanel()
        buttonsPanel.add(self.okBtn)
        buttonsPanel.add(self.cancelBtn)
        buttonsPanel.add(self.previewBtn)
        buttonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.add(buttonsPanel)

        self.addWindowListener(self)
        self.pack()

    def update_gui_from_preferences(self):
        self.nameTextField.setText(self.app.newZone.name)
        #Reset rectangle mode
        bboxStr = ",".join(["%0.4f" % x for x in self.app.newZone.bbox])
        self.bboxTextField.setText(bboxStr)
        self.bboxPreviewTextField.setText(bboxStr)
        self.bboxFromJosmBtn.setEnabled(True)
        self.bboxTextField.setEnabled(False)

        #Reset polygon mode
        self.polygonAsString = ""

        #Reset boundary mode
        self.boundaryAsString = ""

        self.modesComboBox.setSelectedIndex(0)

    def actionPerformed(self, e):
        #Show the panel for configuring the favourite area of the
        #selected type
        if e.getSource() == self.modesComboBox:
            cl = self.configPanel.getLayout()
            selectedMode = self.modesStrings[self.modesComboBox.selectedIndex]
            cl.show(self.configPanel, selectedMode)
        #Activate bbox input for rectangular favourite zone mode
        elif e.getSource() == self.captureRBtn:
            self.bboxFromJosmBtn.setEnabled(True)
            self.bboxTextField.setEnabled(False)
        else:
            self.bboxFromJosmBtn.setEnabled(False)
            self.bboxTextField.setEnabled(True)

    def on_bboxFromJosmBtn_clicked(self, widget):
        """Read bbox currently shown in JOSM
        """
        bbox = self.app.get_frame_bounds()
        self.bboxPreviewTextField.setText(",".join(["%0.4f" % x for x in bbox]))

### Manage layer for creating a new favourite zone from polygon or boundary
    def create_new_zone_editing_layer(self, e=None):
        """Open a new dataset where the user can draw a closed way to
           delimit the favourite area
        """
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.setActiveLayer(layer)
        else:
            Main.main.addLayer(OsmDataLayer(DataSet(), self.FAVAREALAYERNAME, None))
        Main.main.parent.toFront()

    def get_new_zone_editing_layer(self):
        """Check if the layer for editing the favourite area yet exists
        """
        for layer in self.app.mv.getAllLayers():
            if layer.getName() == self.FAVAREALAYERNAME:
                return layer
        return None

    def remove_new_zone_editing_layer(self):
        layer = self.get_new_zone_editing_layer()
        if layer is not None:
            self.app.mv.removeLayer(layer)

    def on_zone_edited(self):
        """Read ways that delimit the favourite area and convert them to
           jts geometry
        """
        if self.modesComboBox.getSelectedIndex() == 0:
            mode = "rectangle"
        elif self.modesComboBox.getSelectedIndex() == 1:
            mode = "polygon"
        elif self.modesComboBox.getSelectedIndex() == 2:
            mode = "boundary"

        if mode in ("polygon", "boundary"):
            layer = self.get_new_zone_editing_layer()
            if layer is not None:
                self.app.mv.setActiveLayer(layer)
            else:
                if mode == "polygon":
                    msg = self.app.strings.getString("polygon_fav_layer_missing_msg")
                else:
                    msg = self.app.strings.getString("boundary_fav_layer_missing_msg")
                JOptionPane.showMessageDialog(self,
                                              msg,
                                              self.app.strings.getString("Warning"),
                                              JOptionPane.WARNING_MESSAGE)
                return

            dataset = self.app.mv.editLayer.data
            areaWKT = self.read_area_from_osm_ways(mode, dataset)
            if areaWKT is None:
                print "I could not read the new favourite area."
            else:
                if mode == "polygon":
                    self.polygonAsString = areaWKT
                else:
                    self.boundaryAsString = areaWKT
        return mode

    def read_area_from_osm_ways(self, mode, dataset):
        """Read way in favourite area editing layer and convert them to
           WKT
        """
        converter = JTSConverter(False)
        lines = [converter.convert(way) for way in dataset.ways]
        polygonizer = Polygonizer()
        polygonizer.add(lines)
        polygons = polygonizer.getPolygons()
        multipolygon = GeometryFactory().createMultiPolygon(list(polygons))
        multipolygonWKT = WKTWriter().write(multipolygon)
        if multipolygonWKT == "MULTIPOLYGON EMPTY":
            if mode == "polygon":
                msg = self.app.strings.getString("empty_ways_polygon_msg")
            else:
                msg = self.app.strings.getString("empty_ways_boundaries_msg")
            JOptionPane.showMessageDialog(self,
                msg,
                self.app.strings.getString("Warning"),
                JOptionPane.WARNING_MESSAGE)
            return
        return multipolygonWKT

    def on_downloadBoundariesBtn_clicked(self, e):
        """Download puter ways of administrative boundaries from
           Overpass API
        """
        adminLevel = self.adminLevelTagTextField.getText()
        name = self.nameTagTextField.getText()
        optional = self.optionalTagTextField.getText()
        if (adminLevel, name, optional) == ("", "", ""):
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("enter_a_tag_msg"),
                                          self.app.strings.getString("Warning"),
                                          JOptionPane.WARNING_MESSAGE)
            return
        optTag = ""
        if optional.find("=") != -1:
            if len(optional.split("=")) == 2:
                key, value = optional.split("=")
                optTag = '["%s"="%s"]' % (URLEncoder.encode(key, "UTF-8"),
                                          URLEncoder.encode(value.replace(" ", "%20"), "UTF-8"))
        self.create_new_zone_editing_layer()
        overpassurl = 'http://127.0.0.1:8111/import?url='
        overpassurl += 'http://overpass-api.de/api/interpreter?data='
        overpassquery = 'relation["admin_level"="%s"]' % adminLevel
        overpassquery += '["name"="%s"]' % URLEncoder.encode(name, "UTF-8")
        overpassquery += '%s;(way(r:"outer");node(w););out meta;' % optTag
        overpassurl += overpassquery.replace(" ", "%20")
        print overpassurl
        self.app.send_to_josm(overpassurl)

### Buttons ############################################################
    def create_new_zone(self, mode):
        """Read data entered on gui and create a new zone
        """
        name = self.nameTextField.getText()
        country = self.countryTextField.getText().upper()

        #error: name
        if name.replace(" ", "") == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("missing_name_warning"),
                                          self.app.strings.getString("missing_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False
        if name in [z.name for z in self.app.tempZones]:
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("duplicate_name_warning"),
                                          self.app.strings.getString("duplicate_name_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #zone type
        zType = mode
        #error: geometry type not defined
        if zType == "polygon" and self.polygonAsString == ""\
            or zType == "boundary" and self.boundaryAsString == "":
            JOptionPane.showMessageDialog(self,
                                          self.app.strings.getString("zone_not_correctly_build_warning"),
                                          self.app.strings.getString("zone_not_correctly_build_warning_title"),
                                          JOptionPane.WARNING_MESSAGE)
            return False

        #geometry string
        if zType == "rectangle":
            geomString = self.bboxPreviewTextField.getText()
        elif zType == "polygon":
            geomString = self.polygonAsString
        else:
            geomString = self.boundaryAsString

        self.app.newZone = Zone(self.app, name, zType, geomString, country)
        #self.app.newZone.print_info()
        return True

    def on_okBtn_clicked(self, event):
        """Add new zone to temp zones
        """
        mode = self.on_zone_edited()
        if self.create_new_zone(mode):
            self.app.tempZones.append(self.app.newZone)
            self.app.preferencesFrame.zonesTable.getModel().addRow([self.app.newZone.country,
                                                                    self.app.newZone.icon,
                                                                    self.app.newZone.name])
            maxIndex = len(self.app.tempZones) - 1
            self.app.preferencesFrame.zonesTable.setRowSelectionInterval(maxIndex,
                                                                         maxIndex)
            self.close_dialog()
            self.app.preferencesFrame.check_removeBtn_status()
            self.app.preferencesFrame.zonesTable.scrollRectToVisible(
                self.app.preferencesFrame.zonesTable.getCellRect(
                    self.app.preferencesFrame.zonesTable.getRowCount() - 1, 0, True))

    def on_previewBtn_clicked(self, e):
        """Show the favourite area on a map
        """
        mode = self.on_zone_edited()
        if not self.create_new_zone(mode):
            return
        zone = self.app.newZone

        if zone.zType == "rectangle":
            wktString = zone.bbox_to_wkt_string()
        else:
            wktString = zone.wktGeom
        script = '/*http://stackoverflow.com/questions/11954401/wkt-and-openlayers*/'
        script += '\nfunction init() {'
        script += '\n    var map = new OpenLayers.Map({'
        script += '\n        div: "map",'
        script += '\n        projection: new OpenLayers.Projection("EPSG:900913"),'
        script += '\n        displayProjection: new OpenLayers.Projection("EPSG:4326"),'
        script += '\n        layers: ['
        script += '\n            new OpenLayers.Layer.OSM()'
        script += '\n            ]'
        script += '\n    });'
        script += '\n    var wkt = new OpenLayers.Format.WKT();'
        script += '\n    var polygonFeature = wkt.read("%s");' % wktString
        script += '\n    var vectors = new OpenLayers.Layer.Vector("Favourite area");'
        script += '\n    map.addLayer(vectors);'
        script += '\n    polygonFeature.geometry.transform(map.displayProjection, map.getProjectionObject());'
        script += '\n    vectors.addFeatures([polygonFeature]);'
        script += '\n    map.zoomToExtent(vectors.getDataExtent());'
        script += '\n};'
        scriptFile = open(File.separator.join([self.app.SCRIPTDIR,
                                              "html",
                                              "script.js"]), "w")
        scriptFile.write(script)
        scriptFile.close()
        OpenBrowser.displayUrl(File.separator.join([self.app.SCRIPTDIR,
                                                   "html",
                                                   "favourite_area.html"]))

    def windowClosing(self, windowEvent):
        self.close_dialog()

    def close_dialog(self, e=None):
        #delete favourite zone editing layer if present
        self.remove_new_zone_editing_layer()
        self.dispose()
        self.app.preferencesFrame.toFront()
Esempio n. 10
0
class PreferencesFrame(JFrame, ActionListener, WindowListener, ItemListener, HyperlinkListener):
    """Dialog with preferences
    """
    def __init__(self, parent, title, app):
        from javax.swing import JCheckBox, JRadioButton, ButtonGroup
        self.app = app
        border = BorderFactory.createEmptyBorder(5, 7, 5, 7)
        self.getContentPane().setBorder(border)
        self.getContentPane().setLayout(BorderLayout(0, 5))
        self.tabbedPane = JTabbedPane()

        #1 Tab: general
        panel1 = JPanel()
        panel1.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        panel1.setLayout(BoxLayout(panel1, BoxLayout.PAGE_AXIS))

        #Checkbutton to enable/disable update check when script starts
        self.updateCBtn = JCheckBox(self.app.strings.getString("updateCBtn"))
        self.updateCBtn.setToolTipText(self.app.strings.getString("updateCBtn_tooltip"))

        #Download tools
        downloadBtn = JButton(self.app.strings.getString("updatesBtn"),
                              ImageProvider.get("dialogs", "refresh"),
                              actionPerformed=self.on_downloadBtn_clicked)
        downloadBtn.setToolTipText(self.app.strings.getString("updatesBtn_tooltip"))

        #Checkbuttons for enabling/disabling tools
        toolsPanel = JPanel(BorderLayout(0, 5))
        title = self.app.strings.getString("enable_disable_tools")
        toolsPanel.setBorder(BorderFactory.createTitledBorder(title))
        infoLbl = JLabel(self.app.strings.getString("JOSM_restart_warning"))
        infoLbl.setFont(infoLbl.getFont().deriveFont(Font.ITALIC))
        toolsPanel.add(infoLbl, BorderLayout.PAGE_START)

        toolsStatusPane = JPanel(GridLayout(len(self.app.realTools), 0))
        self.toolsCBtns = []
        for tool in self.app.realTools:
            toolCBtn = JCheckBox()
            toolCBtn.addItemListener(self)
            toolLbl = JLabel(tool.title, tool.bigIcon, JLabel.LEFT)
            self.toolsCBtns.append(toolCBtn)

            toolPane = JPanel()
            toolPane.setLayout(BoxLayout(toolPane, BoxLayout.X_AXIS))
            toolPane.add(toolCBtn)
            toolPane.add(toolLbl)
            toolsStatusPane.add(toolPane)
        toolsPanel.add(toolsStatusPane, BorderLayout.CENTER)

        #Radiobuttons for enabling/disabling layers when a new one
        #is added
        layersPanel = JPanel(GridLayout(0, 1))
        title = self.app.strings.getString("errors_layers_manager")
        layersPanel.setBorder(BorderFactory.createTitledBorder(title))
        errorLayersLbl = JLabel(self.app.strings.getString("errors_layers_info"))
        errorLayersLbl.setFont(errorLayersLbl.getFont().deriveFont(Font.ITALIC))
        layersPanel.add(errorLayersLbl)
        self.layersRBtns = {}
        group = ButtonGroup()
        for mode in self.app.layersModes:
            layerRBtn = JRadioButton(self.app.strings.getString("%s" % mode))
            group.add(layerRBtn)
            layersPanel.add(layerRBtn)
            self.layersRBtns[mode] = layerRBtn

        #Max number of errors text field
        self.maxErrorsNumberTextField = JTextField()
        self.maxErrorsNumberTextField.setToolTipText(self.app.strings.getString("maxErrorsNumberTextField_tooltip"))
        self.maxErrorsNumberTFieldDefaultBorder = self.maxErrorsNumberTextField.getBorder()
        self.maxErrorsNumberTextField.getDocument().addDocumentListener(ErrNumTextListener(self))

        #layout
        self.updateCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(self.updateCBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        downloadBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(downloadBtn)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        toolsPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(toolsPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        layersPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(layersPanel)
        panel1.add(Box.createRigidArea(Dimension(0, 15)))
        maxErrP = JPanel(BorderLayout(5, 0))
        maxErrP.add(JLabel(self.app.strings.getString("max_errors_number")), BorderLayout.LINE_START)
        maxErrP.add(self.maxErrorsNumberTextField, BorderLayout.CENTER)
        p = JPanel(BorderLayout())
        p.add(maxErrP, BorderLayout.PAGE_START)
        p.setAlignmentX(Component.LEFT_ALIGNMENT)
        panel1.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_1_title"),
                          None,
                          panel1,
                          None)

        #2 Tab: favourite zones
        panel2 = JPanel(BorderLayout(5, 15))
        panel2.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))

        #status
        topPanel = JPanel()
        topPanel.setLayout(BoxLayout(topPanel, BoxLayout.Y_AXIS))
        infoPanel = HtmlPanel(self.app.strings.getString("fav_zones_info"))
        infoPanel.getEditorPane().addHyperlinkListener(self)
        infoPanel.setAlignmentX(Component.LEFT_ALIGNMENT)
        self.favZoneStatusCBtn = JCheckBox(self.app.strings.getString("activate_fav_area"),
                                           actionListener=self)
        self.favZoneStatusCBtn.setToolTipText(self.app.strings.getString("activate_fav_area_tooltip"))
        self.favZoneStatusCBtn.setAlignmentX(Component.LEFT_ALIGNMENT)
        topPanel.add(infoPanel)
        topPanel.add(Box.createRigidArea(Dimension(0, 10)))
        topPanel.add(self.favZoneStatusCBtn)
        #table
        self.zonesTable = JTable()
        tableSelectionModel = self.zonesTable.getSelectionModel()
        tableSelectionModel.addListSelectionListener(ZonesTableListener(self))
        columns = ["",
                   self.app.strings.getString("Type"),
                   self.app.strings.getString("Name")]
        tableModel = ZonesTableModel([], columns)
        self.zonesTable.setModel(tableModel)
        self.scrollPane = JScrollPane(self.zonesTable)
        #map
        self.zonesMap = JMapViewer()
        self.zonesMap.setZoomContolsVisible(False)
        self.zonesMap.setMinimumSize(Dimension(100, 200))

        #buttons
        self.removeBtn = JButton(self.app.strings.getString("Remove"),
                            ImageProvider.get("dialogs", "delete"),
                            actionPerformed=self.on_removeBtn_clicked)
        self.removeBtn.setToolTipText(self.app.strings.getString("remove_tooltip"))
        newBtn = JButton(self.app.strings.getString("New"),
                         ImageProvider.get("dialogs", "add"),
                         actionPerformed=self.on_newBtn_clicked)
        newBtn.setToolTipText(self.app.strings.getString("new_tooltip"))

        #layout
        panel2.add(topPanel, BorderLayout.PAGE_START)
        panel2.add(self.scrollPane, BorderLayout.LINE_START)
        panel2.add(self.zonesMap, BorderLayout.CENTER)
        self.buttonsPanel = JPanel()
        self.buttonsPanel.add(self.removeBtn)
        self.buttonsPanel.add(newBtn)
        panel2.add(self.buttonsPanel, BorderLayout.PAGE_END)

        self.tabbedPane.addTab(self.app.strings.getString("tab_2_title"),
                          None,
                          panel2,
                          None)

        #3 Tab Tools options
        panel3 = JPanel()
        panel3.setLayout(BoxLayout(panel3, BoxLayout.Y_AXIS))
        panel3.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7))
        for tool in self.app.realTools:
            if hasattr(tool, 'prefs'):
                p = JPanel(FlowLayout(FlowLayout.LEFT))
                p.setBorder(BorderFactory.createTitledBorder(tool.title))
                p.add(tool.prefsGui)
                panel3.add(p)

        self.tabbedPane.addTab(self.app.strings.getString("tab_3_title"),
                          None,
                          panel3,
                          None)

        self.add(self.tabbedPane, BorderLayout.CENTER)

        exitPanel = JPanel()
        saveBtn = JButton(self.app.strings.getString("OK"),
                          ImageProvider.get("ok"),
                          actionPerformed=self.on_saveBtn_clicked)
        cancelBtn = JButton(self.app.strings.getString("cancel"),
                            ImageProvider.get("cancel"),
                            actionPerformed=self.on_cancelBtn_clicked)
        saveBtn.setToolTipText(self.app.strings.getString("save_preferences"))
        saveBtn.setAlignmentX(0.5)
        exitPanel.add(saveBtn)
        exitPanel.add(cancelBtn)
        self.add(exitPanel, BorderLayout.PAGE_END)

        self.addWindowListener(self)
        self.pack()

    def windowClosing(self, windowEvent):
        self.on_cancelBtn_clicked()

    def hyperlinkUpdate(self, e):
        if e.getEventType() == HyperlinkEvent.EventType.ACTIVATED:
            OpenBrowser.displayUrl(e.getURL().toString())

    def itemStateChanged(self, e):
        """A ttol has been activated/deactivated.
           Check if at least one tool is on.
        """
        if all(not button.isSelected() for button in self.toolsCBtns):
            JOptionPane.showMessageDialog(
                Main.parent,
                self.app.strings.getString("tools_disabled_warning"),
                self.app.strings.getString("tools_disabled_warning_title"),
                JOptionPane.WARNING_MESSAGE)
            source = e.getItemSelectable()
            source.setSelected(True)

    def actionPerformed(self, e=None):
        """Enable/disable favourite zones panel
        """
        for container in (self.scrollPane, self.buttonsPanel):
            self.enableComponents(container, self.favZoneStatusCBtn.isSelected())
        if self.favZoneStatusCBtn.isSelected():
            self.check_removeBtn_status()

    def enableComponents(self, container, enable):
        components = container.getComponents()
        for component in components:
            component.setEnabled(enable)
            if isinstance(component, Container):
                self.enableComponents(component, enable)

    def on_downloadBtn_clicked(self, e):
        update_checker.Updater(self.app, "manual")

    def clean_map(self):
        """Remove all rectangles and polygons from the map
        """
        self.zonesMap.removeAllMapRectangles()
        self.zonesMap.removeAllMapPolygons()

    def update_gui_from_preferences(self):
        """Update gui status of preferences frame from config file
        """
        #print "\n- updating Preferences gui"
        onOff = {"on": True, "off": False}
        #1 Tab
        #check for update
        self.updateCBtn.setSelected(onOff[self.app.checkUpdate])

        #tools status, enabled or not
        for toolIndex, tool in enumerate(self.app.realTools):
            if "tool.%s" % tool.name in self.app.properties.keys():
                configstatus = self.app.properties.getProperty("tool.%s" % tool.name)
            else:
                configstatus = "on"     # new tool
            self.toolsCBtns[toolIndex].setSelected(onOff[configstatus])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            button.setSelected(mode == self.app.layersMode)

        #max errors number
        self.maxErrorsNumberTextField.setText(str(self.app.maxErrorsNumber))

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()

        #2 Tab
        #favourite area
        self.update_favourite_area_gui_from_preferences()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                tool.prefsGui.update_gui(tool.prefs)

    def update_favourite_area_gui_from_preferences(self):
        #status
        self.favZoneStatusCBtn.setSelected(self.app.favouriteZoneStatus)
        #table
        #store zones to a temporary list, used to store changes
        #and save them when preferences dialog is closed
        self.app.tempZones = list(self.app.zones)
        self.zonesTable.getModel().setNumRows(0)
        for zone in self.app.tempZones:
            self.zonesTable.getModel().addRow([zone.country,
                                               zone.icon,
                                               zone.name])
        if self.app.favZone is not None:
            selectedRow = self.app.tempZones.index(self.app.favZone)
            self.zonesTable.setRowSelectionInterval(selectedRow, selectedRow)
        self.zonesTable.getColumnModel().getColumn(0).setMaxWidth(30)
        self.zonesTable.getColumnModel().getColumn(1).setMaxWidth(50)
        #enable or disable favourite zone buttons
        self.actionPerformed()

### fav area editing buttons ###########################################
    def on_removeBtn_clicked(self, e):
        rowsNum = self.zonesTable.getSelectedRows()
        rowsNum.reverse()
        for rowNum in rowsNum:
            del self.app.tempZones[rowNum]
            self.zonesTable.getModel().removeRow(rowNum)
        if len(self.app.tempZones) != 0:
            if rowNum == 0:
                self.zonesTable.setRowSelectionInterval(0, 0)
            else:
                self.zonesTable.setRowSelectionInterval(rowNum - 1, rowNum - 1)
        self.check_removeBtn_status()

    def check_removeBtn_status(self):
        if self.app.tempZones != [] and len(self.zonesTable.getSelectedRows()) != 0:
            self.removeBtn.setEnabled(True)
        else:
            self.removeBtn.setEnabled(False)
            self.clean_map()

    def on_newBtn_clicked(self, e):
        try:
            self.newZoneDialog
        except AttributeError:
            self.newZoneDialog = NewZoneDialog(self.app)
        bbox = self.app.get_frame_bounds()
        self.app.newZone = Zone(self.app,
                                self.app.strings.getString("New_zone"),
                                "rectangle",
                                ",".join(["%0.4f" % x for x in bbox]),
                                "")
        self.newZoneDialog.update_gui_from_preferences()
        self.newZoneDialog.show()

### Exit from preferences ##############################################
    def on_cancelBtn_clicked(self, event=None):
        if hasattr(self, "newZoneDialog") and self.newZoneDialog.isVisible():
            self.newZoneDialog.close_dialog()
        self.dispose()

    def on_saveBtn_clicked(self, event):
        """Read preferences from gui and save them to config.properties
           file
        """
        #print "\n- saving preferences to config file"
        onOff = {True: "on", False: "off"}

        #1 Tab
        #check for update
        self.app.properties.setProperty("check_for_update",
                                        onOff[self.updateCBtn.isSelected()])
        #tools status
        for toolIndex, tool in enumerate(self.app.realTools):
            prop = "tool.%s" % tool.name
            toolCBtn = self.toolsCBtns[toolIndex]
            self.app.properties.setProperty(prop,
                                            onOff[toolCBtn.isSelected()])

        #layers preferences
        for mode, button in self.layersRBtns.iteritems():
            if button.isSelected():
                self.app.properties.setProperty("layers_mode", mode)
                break

        #max errors number
        try:
            num = Integer.parseInt(self.maxErrorsNumberTextField.getText())
        except NumberFormatException:
            num = ""
        self.app.properties.setProperty("max_errors_number", str(num))

        #2 Tab
        #Favourite zones
        changes = {"new": [z for z in self.app.tempZones if not z in self.app.zones],
                   "deleted": [z for z in self.app.zones if not z in self.app.tempZones]}
        #delete files of removed favourite zones
        for zone in changes["deleted"]:
            f = File(File.separator.join([self.app.SCRIPTDIR,
                                          "configuration",
                                          "favourite_zones",
                                          "%s.txt" % zone.name]))
            f.delete()
        #create files for new favourite zones
        for zone in changes["new"]:
            print "\nsave new zone", zone.name
            fileName = File.separator.join([self.app.SCRIPTDIR,
                                            "configuration",
                                            "favourite_zones",
                                            "%s.txt" % zone.name])
            f = open(fileName, "w")
            zoneData = zone.geomString
            if zone.country != "":
                zoneData += "|" + zone.country
            f.write(zoneData.encode("utf-8"))
            f.close()

        self.app.zones = self.app.tempZones
        if len(self.app.zones) == 0:
            self.app.favZone = None
            self.app.properties.setProperty("favourite_area.name",
                                            "")
            self.favZoneStatusCBtn.setSelected(False)
        else:
            if len(self.zonesTable.getSelectedRows()) == 0:
                self.app.favZone = self.app.zones[0]
            else:
                self.app.favZone = self.app.zones[self.zonesTable.getSelectedRows()[0]]
            self.app.properties.setProperty("favourite_area.name",
                                            self.app.favZone.name)
        favZoneStatus = self.favZoneStatusCBtn.isSelected()
        self.app.properties.setProperty("favourite_area.status", onOff[favZoneStatus])
        self.app.favouriteZoneStatus = favZoneStatus

        #stats panel
        self.app.dlg.update_favourite_zone_indicator()
        self.app.dlg.update_statsPanel_status()

        #3 Tab
        #tools preferences
        for tool in self.app.allTools:
            if hasattr(tool, 'prefs') and tool.prefsGui is not None:
                for pref, value in tool.prefsGui.read_gui().iteritems():
                    prefKey = "tool.%s.%s" % (tool.name, pref)
                    self.app.properties.setProperty(prefKey, value)

        self.app.save_config()
        self.dispose()
Esempio n. 11
0
class BurpExtender(IBurpExtender, ITab, DocumentListener, ActionListener, IScannerInsertionPointProvider):

    def	registerExtenderCallbacks(self, callbacks):
        print "Extension loaded!"
        self._callbacks = callbacks

        self._helpers = callbacks.getHelpers()

        callbacks.setExtensionName("HttpFuzzer")

        #Abusing functionality here :(
        #I would have prefered to have it implemented as an active scan module
        callbacks.registerScannerInsertionPointProvider(self)

        self._newline = "\r\n"

        #Options:
        self._random_mutations = 0
        self._known_fuzz_string_mutations = 0
        self._custom_fuzz_strings = None

        self._known_fuzz_strings = [
            "A" * 256,
            "A" * 1024,
            "A" * 4096,
            "A" * 20000,
            "A" * 65535,
            "%x" * 256,
            "%n" * 256 ,
            "%s" * 256,
            "%s%n%x%d" * 256,
            "%s" * 256,
            "%.1024d",
            "%.2048d",
            "%.4096d",
            "%.8200d",
            "%99999999999s",
            "%99999999999d",
            "%99999999999x",
            "%99999999999n",
            "%99999999999s" * 200,
            "%99999999999d" * 200,
            "%99999999999x" * 200,
            "%99999999999n" * 200,
            "%08x" * 100,
            "%%20s" * 200,
            "%%20x" * 200,
            "%%20n" * 200,
            "%%20d" * 200,
            "%#0123456x%08x%x%s%p%n%d%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%#0123456x%%x%%s%%p%%n%%d%%o%%u%%c%%h%%l%%q%%j%%z%%Z%%t%%i%%e%%g%%f%%a%%C%%S%%08x",
            "'",
            "\\",
            "<",
            "+",
            "%",
            "$",
            "`"
        ]

        #End Options

        #UI START

        self._main_jtabedpane = JTabbedPane()

        #Setup the options
        self._optionsJPanel = JPanel()
        gridBagLayout = GridBagLayout();
        gbc = GridBagConstraints()
        self._optionsJPanel.setLayout(gridBagLayout)

        self.JLabel_random_mutations = JLabel("Number of random bit and byte mutations: ")
        gbc.gridy += 1
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_random_mutations, gbc)
        gbc.gridx = 1
        self.JTextField_random_mutations = JTextField(str(self._random_mutations), 6)
        self.JTextField_random_mutations.getDocument().addDocumentListener(self)
        self._optionsJPanel.add(self.JTextField_random_mutations, gbc)
        callbacks.customizeUiComponent(self.JLabel_random_mutations)
        callbacks.customizeUiComponent(self.JTextField_random_mutations)

        self.JLabel_known_fuzz_string_mutations = JLabel("Number of tests with known fuzzing strings: ")
        gbc.gridy += 1
        gbc.gridx = 0
        self._optionsJPanel.add(self.JLabel_known_fuzz_string_mutations, gbc)
        gbc.gridx = 1
        self.JTextField_known_fuzz_string_mutations = JTextField(str(self._known_fuzz_string_mutations), 6)
        self.JTextField_known_fuzz_string_mutations.getDocument().addDocumentListener(self)
        self._optionsJPanel.add(self.JTextField_known_fuzz_string_mutations, gbc)
        callbacks.customizeUiComponent(self.JLabel_known_fuzz_string_mutations)
        callbacks.customizeUiComponent(self.JTextField_known_fuzz_string_mutations)

        self._filepath = ''
        self.JLabel_filepath = JLabel("Replacement for known fuzzing strings (one per line): ")
        gbc.gridy += 1
        gbc.gridx = 0
        gbc.gridwidth = 1
        self._optionsJPanel.add(self.JLabel_filepath, gbc)
        gbc.gridx = 1
        self.JTextField_filepath = JTextField(self._filepath, 25)
        self.JTextField_filepath.getDocument().addDocumentListener(self)
        self._optionsJPanel.add(self.JTextField_filepath, gbc)
        gbc.gridx = 2
        self.FileChooserButton_filepath = FileChooserButton()
        self.FileChooserButton_filepath.setup(self.JTextField_filepath, "Choose")
        self._optionsJPanel.add(self.FileChooserButton_filepath, gbc)
        callbacks.customizeUiComponent(self.JLabel_filepath)
        callbacks.customizeUiComponent(self.JTextField_filepath)
        callbacks.customizeUiComponent(self.FileChooserButton_filepath)

        about = "<html>"
        about += "Author: floyd, @floyd_ch, http://www.floyd.ch<br>"
        about += "<br>"
        about += "<h3>A simple random fuzzer</h3>"
        about += "<p style=\"width:500px\">"
        about += "This plugin adds ActiveScan checks. "
        about += "Using this fuzzer with any standard HTTP server (Apache, Nginx, etc.) is usually useless, but can be fun. "
        about += "It can be used to see the different error conditions a server and the web application code can run into. "
        about += "However, if you are targeting an embedded device HTTP server or anything more exotic you might be more lucky. "
        about += "The plugin does not do any checks and doesn't add any issues. It is recommended to install the Collect500, "
        about += "ResponseClusterer, Logger++ and Error Message Checks plugin. Additionally it is recommended to attach a debugger to the "
        about += "target program on the server (or use strace or another tool of your choice). <br>"
        about += "In it's default configuration the plugin will not do anything, as it is not considered efficient to fuzz every actively scanned request. "
        about += "You need to specify a higher value for the number of tests in the options tab to enable fuzzing. "
        about += "</p>"
        about += "</html>"
        self.JLabel_about = JLabel(about)
        self.JLabel_about.setLayout(GridBagLayout())
        self._aboutJPanel = JScrollPane(self.JLabel_about)

        # customize our UI components
        callbacks.customizeUiComponent(self._main_jtabedpane)
        callbacks.customizeUiComponent(self._optionsJPanel)
        callbacks.customizeUiComponent(self._aboutJPanel)

        self._main_jtabedpane.addTab("Options", None, self._optionsJPanel, None)
        self._main_jtabedpane.addTab("About & README", None, self._aboutJPanel, None)

        # add the custom tab to Burp's UI
        callbacks.addSuiteTab(self)

        #UI END
        print "Extension registered!"

    #
    # UI: implement ITab
    #

    def getTabCaption(self):
        return "HttpFuzzer"

    def getUiComponent(self):
        return self._main_jtabedpane

    #
    # UI: implement what happens when options are changed
    #

    def changedUpdate(self, document):
        pass

    def removeUpdate(self, document):
        self.insertUpdate(document)

    def insertUpdate(self, document):
        filepath = self.JTextField_filepath.getText().encode("utf-8")
        if filepath:
            try:
                self._custom_fuzz_strings = file(filepath, "rb").readlines()
            except:
                print "ERROR: Couldn't read file"
                self._custom_fuzz_strings = None
        print filepath

        try:
            self._random_mutations = int(self.JTextField_random_mutations.getText())
        except:
            print "Exception,", self.JTextField_random_mutations.getText(), "is not numeric"
            self._random_mutations = 0
        try:
            self._known_fuzz_string_mutations = int(self.JTextField_known_fuzz_string_mutations.getText())
        except:
            print "Exception,", self.JTextField_known_fuzz_string_mutations.getText(), "is not numeric"
            self._known_fuzz_string_mutations = 0
        print self._random_mutations, self._known_fuzz_string_mutations

    def actionPerformed(self, actionEvent):
        self.insertUpdate(None)

    #TODO: Is there another way to simply say "each active scanned HTTP request once"?
    #it seems not: https://support.portswigger.net/customer/en/portal/questions/16776337-confusion-on-insertionpoints-active-scan-module?new=16776337
    #So we are going to abuse a functionality of Burp called IScannerInsertionPoint
    #which is by coincidence always called once per request for every actively scanned item (with baseRequestResponse)
    #this is an ugly hack as the percentage of active scan is simply stuck until this plugin is done
    def getInsertionPoints(self, baseRequestResponse):
        self.do_fuzzing(baseRequestResponse)

    def do_fuzzing(self, baseRequestResponse):
        req = FloydsHelpers.jb2ps(baseRequestResponse.getRequest())
        fuzz_strings = self._custom_fuzz_strings or self._known_fuzz_strings
        for _ in xrange(0, self._known_fuzz_string_mutations):
            index = random.choice(xrange(0, len(req)))
            print "Inserted known fuzz string at byte index", index
            new_req = req[:index]+random.choice(fuzz_strings)+req[index+1:]
            try:
                self._send(baseRequestResponse, new_req)
            except Exception, e:
                print "Error occured. Ignoring and simply going on."
                print e
        for _ in xrange(0, self._random_mutations):
            index = random.randint(0, len(req)-1)
            new_req = req
            if random.choice((True, False)):
                #byte change
                print "At byte index", index, "changed to new byte"
                new_req = req[:index]+chr(random.randint(0, 255))+req[index+1:]
            else:
                #bit change
                bit_index = random.randint(0, 7)
                print "At byte index", index, "changed bit", bit_index
                new_byte = chr(ord(req[index]) ^ (2**bit_index))
                new_req = req[:index]+new_byte+req[index+1:]
            try:
                self._send(baseRequestResponse, new_req)
            except Exception, e:
                print "Error occured. Ignoring and simply going on."
                print e
Esempio n. 12
0
    def _initializeGui(self, callbacks):
        tab = JPanel()

        jLabel1 = JLabel("Original Hash:")
        jLabel2 = JLabel("Original message:")
        jLabel3 = JLabel("Message to append:")
        jLabel5 = JLabel("Max key length:")
        jTextField1 = JTextField("")
        jTextField2 = JTextField("")
        jTextField3 = JTextField("")
        jTextField4 = JTextField("128")
        jLabel4 = JLabel("Hashing functions")
        jCheckBox1 = JCheckBox("MD4")
        jCheckBox2 = JCheckBox("MD5")
        jCheckBox3 = JCheckBox("SHA1")
        jCheckBox4 = JCheckBox("SHA256")
        jCheckBox5 = JCheckBox("SHA512")
        jCheckBox1.setEnabled(False)
        jCheckBox2.setEnabled(False)
        jCheckBox3.setEnabled(False)
        jCheckBox4.setEnabled(False)
        jCheckBox5.setEnabled(False)
        jScrollPane1 = JScrollPane()
        jTable1 = JTable()
        jButton1 = JButton("Generate", actionPerformed=self.generate_attack)
        jButton1.setEnabled(False)
        jButton2 = JButton("Copy messages", actionPerformed=self.copy_messages)
        jButton3 = JButton("Copy hashes", actionPerformed=self.copy_hashes)

        self._tab = tab
        self._textfields = {
            "original_hash": jTextField1,
            "original_msg": jTextField2,
            "append_msg": jTextField3,
            "max_key_len": jTextField4,
        }
        self._checkboxes = {
            md4: jCheckBox1,
            md5: jCheckBox2,
            sha1: jCheckBox3,
            sha256: jCheckBox4,
            sha512: jCheckBox5,
        }

        self._table = jTable1
        self._extensions = {}
        self._hashes, self._messages = [], []

        # Hash field change event
        jTextField1.getDocument().addDocumentListener(
            HashChangeListener(self._checkboxes,
                               self._textfields['original_hash'], jButton1))

        # Table columns
        jTable1.setModel(
            DefaultTableModel([], ["#", "Type", "New Message", "Hash"]))
        jScrollPane1.setViewportView(jTable1)
        # Table column width
        jTable1.getColumnModel().getColumn(0).setMaxWidth(50)
        jTable1.getColumnModel().getColumn(1).setMaxWidth(60)

        layout = GroupLayout(tab)
        tab.setLayout(layout)

        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addGap(24, 24, 24).addGroup(
                    layout.createParallelGroup(
                        GroupLayout.Alignment.TRAILING).addComponent(jLabel5).
                    addComponent(jLabel1).addComponent(jLabel2).
                    addComponent(jLabel3)).addPreferredGap(
                        LayoutStyle.ComponentPlacement.RELATED).addGroup(
                            layout.createParallelGroup(
                                GroupLayout.Alignment.LEADING).addComponent(
                                    jTextField3, GroupLayout.DEFAULT_SIZE, 425,
                                    32767).addComponent(jTextField2).
                            addComponent(jTextField1).addGroup(
                                layout.createSequentialGroup().addComponent(
                                    jTextField4, GroupLayout.PREFERRED_SIZE,
                                    88, GroupLayout.PREFERRED_SIZE).addGap(
                                        0, 0, 32767))).addGap(30, 30, 30).
                addGroup(
                    layout.createParallelGroup(GroupLayout.Alignment.LEADING).
                    addGroup(layout.createSequentialGroup(
                    ).addComponent(jCheckBox1).addPreferredGap(
                        LayoutStyle.ComponentPlacement.RELATED
                    ).addComponent(jCheckBox2).addPreferredGap(
                        LayoutStyle.ComponentPlacement.RELATED
                    ).addComponent(jCheckBox3).addPreferredGap(
                        LayoutStyle.ComponentPlacement.RELATED
                    ).addComponent(jCheckBox4).addPreferredGap(
                        LayoutStyle.ComponentPlacement.RELATED).addComponent(
                            jCheckBox5)).addComponent(jLabel4).addGroup(
                                layout.createSequentialGroup().addComponent(
                                    jButton1).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.RELATED
                                    ).addComponent(jButton3).addPreferredGap(
                                        LayoutStyle.ComponentPlacement.RELATED
                                    ).addComponent(jButton2))).addGap(
                                        167, 167,
                                        167)).addComponent(jScrollPane1))
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addGap(26, 26, 26).addGroup(
                    layout.createParallelGroup(GroupLayout.Alignment.BASELINE).
                    addComponent(jLabel1).addComponent(
                        jTextField1, GroupLayout.PREFERRED_SIZE,
                        GroupLayout.DEFAULT_SIZE,
                        GroupLayout.PREFERRED_SIZE).addComponent(jLabel4)).
                addPreferredGap(
                    LayoutStyle.ComponentPlacement.RELATED).addGroup(
                        layout.createParallelGroup(
                            GroupLayout.Alignment.BASELINE).addComponent(
                                jTextField2, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.DEFAULT_SIZE,
                                GroupLayout.PREFERRED_SIZE).
                        addComponent(jLabel2).addGroup(
                            layout.createParallelGroup(
                                GroupLayout.Alignment.BASELINE).addComponent(
                                    jCheckBox2).addComponent(jCheckBox3).
                            addComponent(jCheckBox1).addComponent(jCheckBox4).
                            addComponent(jCheckBox5))).addPreferredGap(
                                LayoutStyle.ComponentPlacement.RELATED).
                addGroup(
                    layout.createParallelGroup(
                        GroupLayout.Alignment.BASELINE).addComponent(
                            jTextField3, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addComponent(jLabel3)
                ).addPreferredGap(
                    LayoutStyle.ComponentPlacement.RELATED).addGroup(
                        layout.createParallelGroup(
                            GroupLayout.Alignment.BASELINE).
                        addComponent(jLabel5).addComponent(
                            jTextField4, GroupLayout.PREFERRED_SIZE,
                            GroupLayout.DEFAULT_SIZE,
                            GroupLayout.PREFERRED_SIZE).addComponent(jButton2).
                        addComponent(jButton3).addComponent(jButton1)).addGap(
                            13, 13, 13).addComponent(jScrollPane1,
                                                     GroupLayout.DEFAULT_SIZE,
                                                     971, 32767)))

        callbacks.customizeUiComponent(tab)
        callbacks.addSuiteTab(self)
Esempio n. 13
0
class BurpExtender(IBurpExtender, ITab, IMessageEditorController, AbstractTableModel, IContextMenuFactory):

    def registerExtenderCallbacks(self, callbacks):
        # keep a reference to our callbacks object
        self._callbacks = callbacks
        # obtain an extension helpers object
        self._helpers = callbacks.getHelpers()
        
        # set our extension name
        callbacks.setExtensionName("PT Vulnerabilities Manager")
        
        self.config = SafeConfigParser()
        self.createSection('projects')
        self.createSection('general')
        self.config.read('config.ini')
        self.chooser = JFileChooser()
        # create the log and a lock on which to synchronize when adding log entries
        self._log = ArrayList()
        self._lock = Lock()
        
        self.logTable = Table(self)
        self.logTable.getColumnModel().getColumn(0).setMaxWidth(35)
        self.logTable.getColumnModel().getColumn(1).setMinWidth(100)

        self._requestViewer = self._callbacks.createMessageEditor(self, False)
        self._responseViewer = self._callbacks.createMessageEditor(self, False)

        self.initVulnerabilityTab()
        self.initProjSettingsTab()
        self.initTabs()
        self.initCallbacks()

        if self.projPath.getText() != None:
            self.loadVulnerabilities(self.projPath.getText())

        print "Thank you for installing PT Vulnerabilities Manager v1.0 extension"
        print "by Barak Tawily\n\n\n"
        print "Disclaimer:\nThis extension might create folders and files in your hardisk which might be declared as sensitive information, make sure you are creating projects under encrypted partition"
        return

    def initVulnerabilityTab(self):
        #
        ##  init vulnerability tab
        #

        nameLabel = JLabel("Vulnerability Name:")
        nameLabel.setBounds(10, 10, 140, 30)

        self.addButton = JButton("Add",actionPerformed=self.addVuln)
        self.addButton.setBounds(10, 500, 100, 30) 

        rmVulnButton = JButton("Remove",actionPerformed=self.rmVuln)
        rmVulnButton.setBounds(465, 500, 100, 30)

        mitigationLabel = JLabel("Mitigation:")
        mitigationLabel.setBounds(10, 290, 150, 30)
        
        addSSBtn = JButton("Add SS",actionPerformed=self.addSS)
        addSSBtn.setBounds(750, 40, 110, 30) 

        deleteSSBtn = JButton("Remove SS",actionPerformed=self.removeSS)
        deleteSSBtn.setBounds(750, 75, 110, 30) 

        piclistLabel = JLabel("Images list:")
        piclistLabel.setBounds(580, 10, 140, 30)

        self.screenshotsList = DefaultListModel()
        self.ssList = JList(self.screenshotsList)
        self.ssList.setBounds(580, 40, 150, 250)
        self.ssList.addListSelectionListener(ssChangedHandler(self))
        self.ssList.setBorder(BorderFactory.createLineBorder(Color.GRAY))

        previewPicLabel = JLabel("Selected image preview: (click to open in image viewer)")
        previewPicLabel.setBounds(580, 290, 500, 30)


        copyImgMenu = JMenuItem("Copy")
        copyImgMenu.addActionListener(copyImg(self))

        self.imgMenu = JPopupMenu("Popup")
        self.imgMenu.add(copyImgMenu)

        self.firstPic = JLabel()
        self.firstPic.setBorder(BorderFactory.createLineBorder(Color.GRAY))
        self.firstPic.setBounds(580, 320, 550, 400)
        self.firstPic.addMouseListener(imageClicked(self))

        self.vulnName = JTextField("")
        self.vulnName.getDocument().addDocumentListener(vulnTextChanged(self))
        self.vulnName.setBounds(140, 10, 422, 30)

        sevirities = ["Unclassified", "Critical","High","Medium","Low"]
        self.threatLevel = JComboBox(sevirities);
        self.threatLevel.setBounds(140, 45, 140, 30)

        colors = ["Color:", "Green", "Red"]
        self.colorCombo = JComboBox(colors);
        self.colorCombo.setBounds(465, 45, 100, 30)
        self.colorCombo

        severityLabel = JLabel("Threat Level:")
        severityLabel.setBounds(10, 45, 100, 30)

        descriptionLabel = JLabel("Description:")
        descriptionLabel.setBounds(10, 80, 100, 30)

        self.descriptionString = JTextArea("", 5, 30)
        self.descriptionString.setWrapStyleWord(True);
        self.descriptionString.setLineWrap(True)
        self.descriptionString.setBounds(10, 110, 555, 175)
        descriptionStringScroll = JScrollPane(self.descriptionString)
        descriptionStringScroll.setBounds(10, 110, 555, 175)
        descriptionStringScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)


        self.mitigationStr = JTextArea("", 5, 30)
        self.mitigationStr.setWrapStyleWord(True);
        self.mitigationStr.setLineWrap(True)
        self.mitigationStr.setBounds(10, 320, 555, 175)

        mitigationStrScroll = JScrollPane(self.mitigationStr)
        mitigationStrScroll.setBounds(10, 320, 555, 175)
        mitigationStrScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)

        self.pnl = JPanel()
        self.pnl.setBounds(0, 0, 1000, 1000);
        self.pnl.setLayout(None);
        self.pnl.add(addSSBtn)
        self.pnl.add(piclistLabel)
        self.pnl.add(nameLabel)
        self.pnl.add(deleteSSBtn)
        self.pnl.add(rmVulnButton)
        self.pnl.add(severityLabel)
        self.pnl.add(mitigationLabel)
        self.pnl.add(descriptionLabel)
        self.pnl.add(previewPicLabel)
        self.pnl.add(mitigationStrScroll)
        self.pnl.add(descriptionStringScroll)
        self.pnl.add(self.ssList)
        self.pnl.add(self.firstPic)
        self.pnl.add(self.addButton)
        self.pnl.add(self.vulnName)
        self.pnl.add(self.threatLevel)
        self.pnl.add(self.colorCombo)
        
    def initProjSettingsTab(self):
        # init project settings 
        
        projNameLabel = JLabel("Name:")
        projNameLabel.setBounds(10, 50, 140, 30)

        self.projName = JTextField("")
        self.projName.setBounds(140, 50, 320, 30)
        self.projName.getDocument().addDocumentListener(projTextChanged(self))

        detailsLabel = JLabel("Details:")
        detailsLabel.setBounds(10, 120, 140, 30)

        reportLabel = JLabel("Generate Report:")
        reportLabel.setBounds(10, 375, 140, 30)

        types = ["DOCX","HTML","XLSX"]
        self.reportType = JComboBox(types)
        self.reportType.setBounds(10, 400, 140, 30)

        generateReportButton = JButton("Generate", actionPerformed=self.generateReport)
        generateReportButton.setBounds(160, 400, 90, 30)


        self.projDetails = JTextArea("", 5, 30)
        self.projDetails.setWrapStyleWord(True);
        self.projDetails.setLineWrap(True)

        projDetailsScroll = JScrollPane(self.projDetails)
        projDetailsScroll.setBounds(10, 150, 450, 175)
        projDetailsScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED)

        projPathLabel = JLabel("Path:")
        projPathLabel.setBounds(10, 90, 140, 30)

        self.projPath = JTextField("")
        self.projPath.setBounds(140, 90, 320, 30)

        chooseProjPathButton = JButton("Browse...",actionPerformed=self.chooseProjPath)
        chooseProjPathButton.setBounds(470, 90, 100, 30)
        
        importProjButton = JButton("Import",actionPerformed=self.importProj)
        importProjButton.setBounds(470, 10, 100, 30)

        exportProjButton = JButton("Export",actionPerformed=self.exportProj)
        exportProjButton.setBounds(575, 10, 100, 30)

        openProjButton = JButton("Open Directory",actionPerformed=self.openProj)
        openProjButton.setBounds(680, 10, 130, 30)

        currentProjectLabel = JLabel("Current:")
        currentProjectLabel.setBounds(10, 10, 140, 30)

        projects = self.config.options('projects')
        self.currentProject = JComboBox(projects)
        self.currentProject.addActionListener(projectChangeHandler(self))
        self.currentProject.setBounds(140, 10, 140, 30)

        self.autoSave = JCheckBox("Auto Save Mode")
        self.autoSave.setEnabled(False)  # implement this feature
        self.autoSave.setBounds(300, 10, 140, 30)
        self.autoSave.setToolTipText("Will save any changed value while focus is out")

        addProjButton = JButton("Add / Update",actionPerformed=self.addProj)
        addProjButton.setBounds(10, 330, 150, 30)

        removeProjButton = JButton("Remove Current",actionPerformed=self.rmProj)
        removeProjButton.setBounds(315, 330, 146, 30)

        generalOptions = self.config.options('general')
        if 'default project' in generalOptions:
            defaultProj = self.config.get('general','default project')
            self.currentProject.getModel().setSelectedItem(defaultProj)
            self.projPath.setText(self.config.get('projects',self.currentProject.getSelectedItem()))

        self.clearProjTab = True
        self.projectSettings = JPanel()
        self.projectSettings.setBounds(0, 0, 1000, 1000)
        self.projectSettings.setLayout(None)
        self.projectSettings.add(reportLabel)
        self.projectSettings.add(detailsLabel)
        self.projectSettings.add(projPathLabel)
        self.projectSettings.add(addProjButton)
        self.projectSettings.add(openProjButton)
        self.projectSettings.add(projNameLabel)
        self.projectSettings.add(projDetailsScroll)
        self.projectSettings.add(importProjButton)
        self.projectSettings.add(exportProjButton)
        self.projectSettings.add(removeProjButton)
        self.projectSettings.add(generateReportButton)
        self.projectSettings.add(chooseProjPathButton)
        self.projectSettings.add(currentProjectLabel)
        self.projectSettings.add(self.projPath)
        self.projectSettings.add(self.autoSave)
        self.projectSettings.add(self.projName)
        self.projectSettings.add(self.reportType)
        self.projectSettings.add(self.currentProject)

    def initTabs(self):
        #
        ##  init autorize tabs
        #
        
        self._splitpane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT)
        self.scrollPane = JScrollPane(self.logTable)
        self._splitpane.setLeftComponent(self.scrollPane)
        colorsMenu = JMenu("Paint")
        redMenu = JMenuItem("Red")
        noneMenu = JMenuItem("None")
        greenMenu = JMenuItem("Green")
        redMenu.addActionListener(paintChange(self, "Red"))
        noneMenu.addActionListener(paintChange(self, None))
        greenMenu.addActionListener(paintChange(self, "Green"))
        colorsMenu.add(redMenu)
        colorsMenu.add(noneMenu)
        colorsMenu.add(greenMenu)
        
        
        self.menu = JPopupMenu("Popup")
        self.menu.add(colorsMenu)

        self.tabs = JTabbedPane()
        
        self.tabs.addTab("Request", self._requestViewer.getComponent())
        self.tabs.addTab("Response", self._responseViewer.getComponent())

        self.tabs.addTab("Vulnerability", self.pnl)

        self.tabs.addTab("Project Settings", self.projectSettings)
        
        self.tabs.setSelectedIndex(2)
        self._splitpane.setRightComponent(self.tabs)

    def initCallbacks(self):
        #
        ##  init callbacks
        #

        # customize our UI components
        self._callbacks.customizeUiComponent(self._splitpane)
        self._callbacks.customizeUiComponent(self.logTable)
        self._callbacks.customizeUiComponent(self.scrollPane)
        self._callbacks.customizeUiComponent(self.tabs)
        self._callbacks.registerContextMenuFactory(self)
        # add the custom tab to Burp's UI
        self._callbacks.addSuiteTab(self)


    def loadVulnerabilities(self, projPath):
        self.clearList(None)
        selected = False
        for root, dirs, files in os.walk(projPath): # make it go only for dirs
            for dirName in dirs:
                xmlPath = projPath+"/"+dirName+"/vulnerability.xml"
                # xmlPath = xmlPath.replace("/","//")
                document = self.getXMLDoc(xmlPath)
                nodeList = document.getDocumentElement().getChildNodes()
                vulnName = nodeList.item(0).getTextContent()
                severity = nodeList.item(1).getTextContent()
                description = nodeList.item(2).getTextContent()
                mitigation = nodeList.item(3).getTextContent()
                color = nodeList.item(4).getTextContent()
                test = vulnerability(vulnName,severity,description,mitigation,color)
                self._lock.acquire()
                row = self._log.size()
                self._log.add(test)
                self.fireTableRowsInserted(row, row)
                self._lock.release()
                if vulnName == self.vulnName.getText():
                    self.logTable.setRowSelectionInterval(row,row)
                    selected = True
        if selected == False and self._log.size() > 0:
            self.logTable.setRowSelectionInterval(0, 0)
            self.loadVulnerability(self._log.get(0))
        
    def createSection(self, sectioName):
        self.config.read('config.ini')
        if not (sectioName in self.config.sections()):
            self.config.add_section(sectioName)
            cfgfile = open("config.ini",'w')
            self.config.write(cfgfile)
            cfgfile.close()

    def saveCfg(self):
        f = open('config.ini', 'w')
        self.config.write(f)
        f.close()

    def getXMLDoc(self, xmlPath):
        try:
            document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlPath)
            return document
        except:
            self._extender.popup("XML file not found")
            return

    def saveXMLDoc(self, doc, xmlPath):
        transformerFactory = TransformerFactory.newInstance()
        transformer = transformerFactory.newTransformer()
        source = DOMSource(doc)
        result = StreamResult(File(xmlPath))
        transformer.transform(source, result)

    def generateReport(self,event):
        if self.reportType.getSelectedItem() == "HTML":
            path = self.reportToHTML()
        if self.reportType.getSelectedItem() == "XLSX":
            path = self.reportToXLS()
        if self.reportType.getSelectedItem() == "DOCX":
            path = self.generateReportFromDocxTemplate('template.docx',"newfile.docx", 'word/document.xml')
        n = JOptionPane.showConfirmDialog(None, "Report generated successfuly:\n%s\nWould you like to open it?" % (path), "PT Manager", JOptionPane.YES_NO_OPTION)
        if n == JOptionPane.YES_OPTION:
            os.system('"' + path + '"') # Bug! stucking burp until the file get closed

    def exportProj(self,event):
        self.chooser.setDialogTitle("Save project")
        Ffilter = FileNameExtensionFilter("Zip files", ["zip"])
        self.chooser.setFileFilter(Ffilter)
        returnVal = self.chooser.showSaveDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            dst = str(self.chooser.getSelectedFile())
            shutil.make_archive(dst,"zip",self.getCurrentProjPath())
            self.popup("Project export successfuly")

    def importProj(self,event):
        self.chooser.setDialogTitle("Select project zip to directory")
        Ffilter = FileNameExtensionFilter("Zip files", ["zip"])
        self.chooser.setFileFilter(Ffilter)
        returnVal = self.chooser.showOpenDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            zipPath = str(self.chooser.getSelectedFile())
            self.chooser.setDialogTitle("Select project directory")
            self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
            returnVal = self.chooser.showOpenDialog(None)
            if returnVal == JFileChooser.APPROVE_OPTION:
                projPath = str(self.chooser.getSelectedFile()) + "/PTManager"
                with zipfile.ZipFile(zipPath, "r") as z:
                    z.extractall(projPath)

                xmlPath = projPath + "/project.xml"
                document = self.getXMLDoc(xmlPath)
                nodeList = document.getDocumentElement().getChildNodes()
                projName = nodeList.item(0).getTextContent()
                nodeList.item(1).setTextContent(projPath)
                self.saveXMLDoc(document, xmlPath)
                self.config.set('projects', projName, projPath)
                self.saveCfg()
                self.reloadProjects()
                self.currentProject.getModel().setSelectedItem(projName)
                self.clearVulnerabilityTab() 

    def reportToXLS(self):
        if not xlsxwriterImported:
            self.popup("xlsxwriter library is not imported")
            return
        workbook = xlsxwriter.Workbook(self.getCurrentProjPath() + '/PT Manager Report.xlsx')
        worksheet = workbook.add_worksheet()
        bold = workbook.add_format({'bold': True})
        worksheet.write(0, 0, "Vulnerability Name", bold)
        worksheet.write(0, 1, "Threat Level", bold)
        worksheet.write(0, 2, "Description", bold)
        worksheet.write(0, 3, "Mitigation", bold)
        row = 1
        for i in range(0,self._log.size()):
            worksheet.write(row, 0, self._log.get(i).getName())
            worksheet.write(row, 1, self._log.get(i).getSeverity())
            worksheet.write(row, 2, self._log.get(i).getDescription())
            worksheet.write(row, 3, self._log.get(i).getMitigation())
            row = row + 1
            # add requests and images as well
        workbook.close()
        return self.getCurrentProjPath() + '/PT Manager Report.xlsx'
        
    def reportToHTML(self):
        htmlContent = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="he" dir="ltr">
    <head>
        <title>PT Manager Report</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <style>
        body {
        background-repeat: no-repeat;
        background-attachment: fixed;
        font-family: Arial,Tahoma,sens-serif;
        font-size: 13px;
        margin: auto;
        }

        #warpcenter {
            width: 900px;
            margin: 0px auto;
        }

        table {
            border: 2px dashed #000000;
        }

        td {
            border-top: 2px dashed #000000;
            padding: 10px;
        }

        img {
                border: 0px;
        }
</style>
<script language="javascript">
    function divHideShow(divToHideOrShow) 
    {
        var div = document.getElementById(divToHideOrShow);

        if (div.style.display == "block") 
        {
            div.style.display = "none";
        }
        else 
        {
            div.style.display = "block";
        }

        
    }         
</script>
    </head>

    <body>
        <div id="warpcenter">

<h1> PT Manager Report </h1>
<h2> Project: %s</h1>
    """ % (self.projName.getText())

        for i in range(0,self._log.size()):
            name = self._log.get(i).getName()
            request = "None"
            response = "None"
            path = self.getVulnReqResPath("request",name)
            if os.path.exists(path):
                request = self.newlineToBR(self.getFileContent(path))
                
            path = self.getVulnReqResPath("response",name)
            if os.path.exists(path):
                response = self.newlineToBR(self.getFileContent(path))
            images = ""
            for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(name)):
                if fileName.endswith(".jpg"):
                    images += "%s<br><img src=\"%s\"><br><br>" % (fileName, self.projPath.getText()+"/"+self.clearStr(name) + "/" + fileName)
            description = self.newlineToBR(self._log.get(i).getDescription())
            mitigation = self.newlineToBR(self._log.get(i).getMitigation())
            htmlContent +=  self.convertVulntoTable(i,name,self._log.get(i).getSeverity(), description,mitigation, request, response, images)
        htmlContent += "</div></body></html>"
        f = open(self.getCurrentProjPath() + '/PT Manager Report.html', 'w')
        f.writelines(htmlContent)
        f.close()
        return self.getCurrentProjPath() + '/PT Manager Report.html'

    def newlineToBR(self,string):
        return "<br />".join(string.split("\n"))

    def getFileContent(self,path):
        f = open(path, "rb")
        content = f.read()
        f.close()
        return content

    def convertVulntoTable(self, number, name, severity, description, mitigation, request = "None", response = "None", images = "None"):
        return """<div style="width: 100%%;height: 30px;text-align: center;background-color:#E0E0E0;font-size: 17px;font-weight: bold;color: #000;padding-top: 10px;">%s <a href="javascript:divHideShow('Table_%s');" style="color:#191970">(OPEN / CLOSE)</a></div>
        <div id="Table_%s" style="display: none;">
            <table width="100%%" cellspacing="0" cellpadding="0" style="margin: 0px auto;text-align: left;border-top: 0px;">
                <tr>
                    <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Threat Level: </span> 
                        <span style="color:#8b8989">%s</span>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Description</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_03');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_03" style="display: none;margin-top: 25px;">
                        %s
                        </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Mitigration</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_04');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_04" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>

                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Request</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_05');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_05" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>


                                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Response</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_06');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_06" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                                            </td>
                                        </tr>

                                                        <tr>
                                            <td>
                        <div style="font-size: 16px;font-weight: bold;">
                        <span style="color:#000000">Images</span> 
                        <a href="javascript:divHideShow('Table_%s_Command_07');" style="color:#191970">OPEN / CLOSE >>></a>
                        </div>

                        <div id="Table_%s_Command_07" style="display: none;margin-top: 25px;">
                        %s
                        <b>
                    </td>
                </tr>
            </table>
        </div><br><br>""" % (name,number,number,severity,number,number,description,number,number,mitigation,number,number,request,number,number,response,number,number,images)

    def clearVulnerabilityTab(self, rmVuln=True):
        if rmVuln:
            self.vulnName.setText("")
        self.descriptionString.setText("")
        self.mitigationStr.setText("")
        self.colorCombo.setSelectedIndex(0)
        self.threatLevel.setSelectedIndex(0)
        self.screenshotsList.clear()
        self.addButton.setText("Add")
        self.firstPic.setIcon(None)

    def saveRequestResponse(self, type, requestResponse, vulnName):
        path = self.getVulnReqResPath(type,vulnName)
        f = open(path, 'wb')
        f.write(requestResponse)
        f.close()

    def openProj(self, event):
        os.system('explorer ' + self.projPath.getText())

    def getVulnReqResPath(self, requestOrResponse, vulnName):
        return self.getCurrentProjPath() + "/" + self.clearStr(vulnName) + "/"+requestOrResponse+"_" + self.clearStr(vulnName)

    def htmlEscape(self,data):
        return data.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;').replace("'", '&#39;')

    def generateReportFromDocxTemplate(self, zipname, newZipName, filename):      
        newZipName = self.getCurrentProjPath() + "/" + newZipName
        with zipfile.ZipFile(zipname, 'r') as zin:
            with zipfile.ZipFile(newZipName, 'w') as zout:
                zout.comment = zin.comment
                for item in zin.infolist():
                    if item.filename != filename:
                        zout.writestr(item, zin.read(item.filename))
                    else:
                        xml_content = zin.read(item.filename)
                        result = re.findall("(.*)<w:body>(?:.*)<\/w:body>(.*)",xml_content)[0]
                        newXML = result[0]
                        templateBody = re.findall("<w:body>(.*)<\/w:body>", xml_content)[0]
                        newBody = ""

                        for i in range(0,self._log.size()):
                            tmp = templateBody
                            tmp = tmp.replace("$vulnerability", self.htmlEscape(self._log.get(i).getName()))
                            tmp = tmp.replace("$severity", self.htmlEscape(self._log.get(i).getSeverity()))
                            tmp = tmp.replace("$description", self.htmlEscape(self._log.get(i).getDescription()))
                            tmp = tmp.replace("$mitigation", self.htmlEscape(self._log.get(i).getMitigation()))
                            newBody = newBody + tmp
                         
                        newXML = newXML + newBody
                        newXML = newXML + result[1]

        with zipfile.ZipFile(newZipName, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
            zf.writestr(filename, newXML)
        return newZipName


    def chooseProjPath(self, event):
        self.chooser.setDialogTitle("Select target directory")
        self.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
        returnVal = self.chooser.showOpenDialog(None)
        if returnVal == JFileChooser.APPROVE_OPTION:
            projPath = str(self.chooser.getSelectedFile()) + "/PTManager"
            os.makedirs(projPath)
            self.projPath.setText(projPath)

    def reloadProjects(self):
        self.currentProject.setModel(DefaultComboBoxModel(self.config.options('projects')))

    def rmProj(self, event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            self._requestViewer.setMessage("None", False)
            self._responseViewer.setMessage("None", False)
            shutil.rmtree(self.projPath.getText())
            self.config.remove_option('projects',self.currentProject.getSelectedItem())
            self.reloadProjects()
            self.currentProject.setSelectedIndex(0)
            self.loadVulnerabilities(self.projPath.getText())

    def popup(self,msg):
        JOptionPane.showMessageDialog(None,msg)

    def addProj(self, event):
        projPath = self.projPath.getText()
        if projPath == None or projPath == "":
            self.popup("Please select path")
            return
        self.config.set('projects', self.projName.getText(), projPath)
        self.saveCfg()
        xml = ET.Element('project')
        name = ET.SubElement(xml, "name")
        path = ET.SubElement(xml, "path")
        details = ET.SubElement(xml, "details")
        autoSaveMode = ET.SubElement(xml, "autoSaveMode")

        name.text = self.projName.getText()
        path.text = projPath
        details.text = self.projDetails.getText()
        autoSaveMode.text = str(self.autoSave.isSelected())
        tree = ET.ElementTree(xml)
        try:
            tree.write(self.getCurrentProjPath()+'/project.xml')
        except:
            self.popup("Invalid path")
            return

        self.reloadProjects()
        self.clearVulnerabilityTab()
        self.clearList(None)
        self.currentProject.getModel().setSelectedItem(self.projName.getText())

    def resize(self, image, width, height):
        bi = BufferedImage(width, height, BufferedImage.TRANSLUCENT)
        g2d = bi.createGraphics()
        g2d.addRenderingHints(RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY))
        g2d.drawImage(image, 0, 0, width, height, None)
        g2d.dispose()
        return bi;

    def clearStr(self, var):
        return var.replace(" " , "_").replace("\\" , "").replace("/" , "").replace(":" , "").replace("*" , "").replace("?" , "").replace("\"" , "").replace("<" , "").replace(">" , "").replace("|" , "").replace("(" , "").replace(")" , "")

    def popUpAreYouSure(self):
        dialogResult = JOptionPane.showConfirmDialog(None,"Are you sure?","Warning",JOptionPane.YES_NO_OPTION)
        if dialogResult == 0:
            return 0
        return 1

    def removeSS(self,event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            os.remove(self.getCurrentVulnPath() + "/" + self.ssList.getSelectedValue())
            self.ssList.getModel().remove(self.ssList.getSelectedIndex())
            self.firstPic.setIcon(ImageIcon(None))
            # check if there is images and select the first one
            # bug in linux

    def addSS(self,event):
        clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
        try:
            image = clipboard.getData(DataFlavor.imageFlavor)
        except:
            self.popup("Clipboard not contains image")
            return
        vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())
        if not os.path.exists(vulnPath):
            os.makedirs(vulnPath)
        name = self.clearStr(self.vulnName.getText()) + str(random.randint(1, 99999))+".jpg"
        fileName = self.projPath.getText()+"/"+ self.clearStr(self.vulnName.getText()) + "/" + name
        file = File(fileName)
        bufferedImage = BufferedImage(image.getWidth(None), image.getHeight(None), BufferedImage.TYPE_INT_RGB);
        g = bufferedImage.createGraphics();
        g.drawImage(image, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), Color.WHITE, None);
        ImageIO.write(bufferedImage, "jpg", file)
        self.addVuln(self)
        self.ssList.setSelectedValue(name,True)

    def rmVuln(self, event):
        if self.popUpAreYouSure() == JOptionPane.YES_OPTION:
            self._requestViewer.setMessage("None", False)
            self._responseViewer.setMessage("None", False)
            shutil.rmtree(self.getCurrentVulnPath())
            self.clearVulnerabilityTab()
            self.loadVulnerabilities(self.getCurrentProjPath())

    def addVuln(self, event):
        if self.colorCombo.getSelectedItem() == "Color:":
            colorTxt = None
        else:
            colorTxt = self.colorCombo.getSelectedItem()
        self._lock.acquire()
        row = self._log.size()
        vulnObject = vulnerability(self.vulnName.getText(),self.threatLevel.getSelectedItem(),self.descriptionString.getText(),self.mitigationStr.getText() ,colorTxt)
        self._log.add(vulnObject) 
        self.fireTableRowsInserted(row, row)
        self._lock.release()

        vulnPath = self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())
        if not os.path.exists(vulnPath):
            os.makedirs(vulnPath)

        xml = ET.Element('vulnerability')
        name = ET.SubElement(xml, "name")
        severity = ET.SubElement(xml, "severity")
        description = ET.SubElement(xml, "description")
        mitigation = ET.SubElement(xml, "mitigation")
        color = ET.SubElement(xml, "color")
        name.text = self.vulnName.getText()
        severity.text = self.threatLevel.getSelectedItem()
        description.text = self.descriptionString.getText()
        mitigation.text = self.mitigationStr.getText()
        color.text = colorTxt
        tree = ET.ElementTree(xml)
        tree.write(vulnPath+'/vulnerability.xml')

        self.loadVulnerabilities(self.getCurrentProjPath())
        self.loadVulnerability(vulnObject)

    def vulnNameChanged(self):
            if os.path.exists(self.getCurrentVulnPath()) and self.vulnName.getText() != "":
                self.addButton.setText("Update")
            elif self.addButton.getText() != "Add":
                options = ["Create a new vulnerability", "Change current vulnerability name"]
                n = JOptionPane.showOptionDialog(None,
                    "Would you like to?",
                    "Vulnerability Name",
                    JOptionPane.YES_NO_CANCEL_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    None,
                    options,
                    options[0]);

                if n == 0:
                    self.clearVulnerabilityTab(False)
                    self.addButton.setText("Add")
                else:
                    newName = JOptionPane.showInputDialog(
                    None,
                    "Enter new name:",
                    "Vulnerability Name",
                    JOptionPane.PLAIN_MESSAGE,
                    None,
                    None,
                    self.vulnName.getText())
                    row = self.logTable.getSelectedRow()
                    old = self.logTable.getValueAt(row,1)                   
                    self.changeVulnName(newName,old)
                
    def changeVulnName(self,new,old):
        newpath = self.getCurrentProjPath() + "/" + new
        oldpath = self.getCurrentProjPath() + "/" + old
        os.rename(oldpath,newpath)
        self.changeCurrentVuln(new,0, newpath + "/vulnerability.xml")

    def getCurrentVulnPath(self):
        return self.projPath.getText() + "/" + self.clearStr(self.vulnName.getText())

    def getCurrentProjPath(self):
        return self.projPath.getText()

    def loadSS(self, imgPath):
        image = ImageIO.read(File(imgPath))
        if image.getWidth() <= 550 and image.getHeight() <= 400:
            self.firstPic.setIcon(ImageIcon(image))
            self.firstPic.setSize(image.getWidth(),image.getHeight())
        else:
            self.firstPic.setIcon(ImageIcon(self.resize(image,550, 400)))
            self.firstPic.setSize(550,400)

    def clearProjectTab(self):
        self.projPath.setText("")
        self.projDetails.setText("")

    def clearList(self, event):
        self._lock.acquire()
        self._log = ArrayList()
        row = self._log.size()
        self.fireTableRowsInserted(row, row)
        self._lock.release()

    #
    # implement IContextMenuFactory
    #
    def createMenuItems(self, invocation):
        responses = invocation.getSelectedMessages();
        if responses > 0:
            ret = LinkedList()
            requestMenuItem = JMenuItem("Send to PT Manager");
            requestMenuItem.addActionListener(handleMenuItems(self,responses[0], "request"))
            ret.add(requestMenuItem);
            return(ret);
        return null;
    #
    # implement ITab
    #
    def getTabCaption(self):
        return "PT Manager"
    
    def getUiComponent(self):
        return self._splitpane

        #
    # extend AbstractTableModel
    #
    
    def getRowCount(self):
        try:
            return self._log.size()
        except:
            return 0

    def getColumnCount(self):
        return 3

    def getColumnName(self, columnIndex):
        if columnIndex == 0:
            return "#"
        if columnIndex == 1:
            return "Vulnerability Name"
        if columnIndex == 2:
            return "Threat Level"
        return ""

    def getValueAt(self, rowIndex, columnIndex):
        vulnObject = self._log.get(rowIndex)
        if columnIndex == 0:
            return rowIndex+1
        if columnIndex == 1:
            return vulnObject.getName()
        if columnIndex == 2:
            return vulnObject.getSeverity()
        if columnIndex == 3:
            return vulnObject.getMitigation()
        if columnIndex == 4:
            return vulnObject.getColor()

        return ""

    def changeCurrentVuln(self,value,fieldNumber, xmlPath = "def"):
        if xmlPath == "def":
            xmlPath = self.getCurrentVulnPath() + "/vulnerability.xml"
        document = self.getXMLDoc(xmlPath)
        nodeList = document.getDocumentElement().getChildNodes()
        nodeList.item(fieldNumber).setTextContent(value)
        self.saveXMLDoc(document, xmlPath)
        self.loadVulnerabilities(self.getCurrentProjPath())

    def loadVulnerability(self, vulnObject):
        self.addButton.setText("Update")
        self.vulnName.setText(vulnObject.getName())
        self.threatLevel.setSelectedItem(vulnObject.getSeverity())
        self.descriptionString.setText(vulnObject.getDescription())
        self.mitigationStr.setText(vulnObject.getMitigation())

        if vulnObject.getColor() == "" or vulnObject.getColor() == None:
            self.colorCombo.setSelectedItem("Color:")
        else:
            self.colorCombo.setSelectedItem(vulnObject.getColor())
        self.screenshotsList.clear()

        for fileName in os.listdir(self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())):
            if fileName.endswith(".jpg"):
                self.screenshotsList.addElement(fileName)
                imgPath = self.projPath.getText()+"/"+self.clearStr(vulnObject.getName())+'/'+fileName
                # imgPath = imgPath.replace("/","//")
                self.loadSS(imgPath)

        if (self.screenshotsList.getSize() == 0):
            self.firstPic.setIcon(None)
        else:
            self.ssList.setSelectedIndex(0)

        path = self.getVulnReqResPath("request",vulnObject.getName())
        if os.path.exists(path):
            f = self.getFileContent(path)
            self._requestViewer.setMessage(f, False)
        else:
            self._requestViewer.setMessage("None", False)
        
        path = self.getVulnReqResPath("response",vulnObject.getName())
        if os.path.exists(path):
            f = self.getFileContent(path)
            self._responseViewer.setMessage(f, False)
        else:
            self._responseViewer.setMessage("None", False)