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()) ))
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)
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
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())
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()
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)
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)"
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()
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()
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()
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
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)
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('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", ''') 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)