class JTabTitle(JPanel, ActionListener): def __init__(self, ui, tabName): self._ui = ui self.jStatusBtn = JButton() #self.jStatusBtn.setMargin(Insets(2,0,2,0)) self.jStatusBtn = JCheckBox() self.jStatusBtn.setToolTipText(Strings.jStatusBtn_tooltip) self.jStatusBtn.setMargin(Insets(1, 5, 1, 5)) #enlarged clickable zone self.jStatusBtn.setBackground(Color.RED) #transparent background self.add(self.jStatusBtn) self.jStatusBtn.addActionListener(self) self.jLabel = JDoubleClickTextField(self, tabName) self.add(self.jLabel) self.setOpaque(False) def actionPerformed(self, event): #Check box was clicked if self.jStatusBtn == event.getSource(): if self.jStatusBtn.isSelected(): self._ui.initVars(self) pass #do nothing for now def setTabName(self, tabName): self.jLabel.setText(tabName) def getTabName(self): return self.jLabel.getText()
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 BurpExtender(IBurpExtender, ITab, IHttpListener, IMessageEditorController, AbstractTableModel, IContextMenuFactory, IExtensionStateListener): # # 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("Burp Scope Monitor Experimental") self.GLOBAL_HANDLER_ANALYZED = False self.GLOBAL_HANDLER = False self.STATUS = False self.AUTOSAVE_REQUESTS = 10 self.AUTOSAVE_TIMEOUT = 600 # 10 minutes should be fine self.CONFIG_INSCOPE = True self.BAD_EXTENSIONS_DEFAULT = [ '.gif', '.png', '.js', '.woff', '.woff2', '.jpeg', '.jpg', '.css', '.ico', '.m3u8', '.ts', '.svg' ] self.BAD_MIMES_DEFAULT = [ 'gif', 'script', 'jpeg', 'jpg', 'png', 'video', 'mp2t' ] self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT self.BAD_MIMES = self.BAD_MIMES_DEFAULT # create the log and a lock on which to synchronize when adding log entries self._currentlyDisplayedItem = None self.SELECTED_MODEL_ROW = 0 self.SELECTED_VIEW_ROW = 0 self._log = ArrayList() self._fullLog = ArrayList() self._lock = Lock() self._lockFile = Lock() # main split pane self._parentPane = JTabbedPane() self._splitpane = JSplitPane(JSplitPane.VERTICAL_SPLIT) ##### config pane self._config = JTabbedPane() config = JPanel() iexport = JPanel() #config.setLayout(BorderLayout()) config.setLayout(None) iexport.setLayout(None) # config radio button X_BASE = 40 Y_OFFSET = 5 Y_OPTION = 200 Y_OPTION_SPACING = 20 Y_CHECKMARK_SPACING = 20 self.showAllButton = JRadioButton(SHOW_ALL_BUTTON_LABEL, True) self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False) self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False) self.showAllButton.setBounds(40, 60 + Y_OFFSET, 400, 30) self.showNewButton.setBounds(40, 80 + Y_OFFSET, 400, 30) self.showTestedButton.setBounds(40, 100 + Y_OFFSET, 400, 30) #self.showNewButton = JRadioButton(SHOW_NEW_BUTTON_LABEL, False) #self.showTestedButton = JRadioButton(SHOW_TEST_BUTTON_LABEL, False) self.showAllButton.addActionListener(self.handleRadioConfig) self.showNewButton.addActionListener(self.handleRadioConfig) self.showTestedButton.addActionListener(self.handleRadioConfig) self.clearButton = JButton("Clear") self.clearButton.addActionListener(self.handleClearButton) self.clearButton.setBounds(40, 20, 100, 30) self.startButton = JButton(MONITOR_ON_LABEL) self.startButton.addActionListener(self.handleStartButton) self.startButton.setBounds(150, 20, 200, 30) self.badExtensionsLabel = JLabel("Ignore extensions:") self.badExtensionsLabel.setBounds(X_BASE, 150, 200, 30) self.badExtensionsText = JTextArea("") self.loadBadExtensions() self.badExtensionsText.setBounds(X_BASE, 175, 310, 30) self.badExtensionsButton = JButton("Save") self.badExtensionsButton.addActionListener( self.handleBadExtensionsButton) self.badExtensionsButton.setBounds(355, 175, 70, 30) self.badExtensionsDefaultButton = JButton("Load Defaults") self.badExtensionsDefaultButton.addActionListener( self.handleBadExtensionsDefaultButton) self.badExtensionsDefaultButton.setBounds(430, 175, 120, 30) self.badMimesLabel = JLabel("Ignore mime types:") self.badMimesLabel.setBounds(X_BASE, 220, 200, 30) self.badMimesText = JTextArea("") self.loadBadMimes() self.badMimesText.setBounds(X_BASE, 245, 310, 30) self.badMimesButton = JButton("Save") self.badMimesButton.addActionListener(self.handleBadMimesButton) self.badMimesButton.setBounds(355, 245, 70, 30) self.badMimesDefaultButton = JButton("Load Defaults") self.badMimesDefaultButton.addActionListener( self.handleBadMimesDefaultButton) self.badMimesDefaultButton.setBounds(430, 245, 120, 30) self.otherLabel = JLabel("Other:") self.otherLabel.setBounds(40, 300, 120, 30) self.otherLabel2 = JLabel("Other:") self.otherLabel2.setBounds(X_BASE, Y_OPTION, 120, 30) self.autoSaveOption = JCheckBox("Auto save periodically") self.autoSaveOption.setSelected(True) self.autoSaveOption.addActionListener(self.handleAutoSaveOption) self.autoSaveOption.setBounds(X_BASE, Y_OPTION + Y_CHECKMARK_SPACING, 420, 30) self.repeaterOptionButton = JCheckBox( "Repeater request automatically marks as analyzed") self.repeaterOptionButton.setSelected(True) self.repeaterOptionButton.addActionListener( self.handleRepeaterOptionButton) self.repeaterOptionButton.setBounds(50, 330, 420, 30) self.scopeOptionButton = JCheckBox("Follow Burp Target In Scope rules") self.scopeOptionButton.setSelected(True) self.scopeOptionButton.addActionListener(self.handleScopeOptionButton) self.scopeOptionButton.setBounds(50, 350, 420, 30) self.startOptionButton = JCheckBox("Autostart Scope Monitor") self.startOptionButton.setSelected(True) self.startOptionButton.addActionListener(self.handleStartOption) self.startOptionButton.setBounds(50, 350 + Y_OPTION_SPACING, 420, 30) self.markTestedRequestsProxy = JCheckBox( "Color request in Proxy tab if analyzed") self.markTestedRequestsProxy.setSelected(True) self.markTestedRequestsProxy.addActionListener( self.handleTestedRequestsProxy) self.markTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 2, 420, 30) self.markNotTestedRequestsProxy = JCheckBox( "Color request in Proxy tab if NOT analyzed") self.markNotTestedRequestsProxy.setSelected(True) self.markNotTestedRequestsProxy.addActionListener( self.handleNotTestedRequestsProxy) self.markNotTestedRequestsProxy.setBounds(50, 350 + Y_OPTION_SPACING * 3, 420, 30) self.saveButton = JButton("Save now") self.saveButton.addActionListener(self.handleSaveButton) self.saveButton.setBounds(X_BASE + 320, 95, 90, 30) self.loadButton = JButton("Load now") self.loadButton.addActionListener(self.handleLoadButton) self.loadButton.setBounds(X_BASE + 420, 95, 90, 30) self.selectPath = JButton("Select path") self.selectPath.addActionListener(self.selectExportFile) self.selectPath.setBounds(X_BASE + 530, 60, 120, 30) self.selectPathText = JTextArea("") self.selectPathText.setBounds(X_BASE, 60, 510, 30) self.selectPathLabel = JLabel("State file:") self.selectPathLabel.setBounds(X_BASE, 30, 200, 30) bGroup = ButtonGroup() bGroup.add(self.showAllButton) bGroup.add(self.showNewButton) bGroup.add(self.showTestedButton) config.add(self.clearButton) config.add(self.startButton) config.add(self.startOptionButton) config.add(self.showAllButton) config.add(self.showNewButton) config.add(self.showTestedButton) config.add(self.badExtensionsButton) config.add(self.badExtensionsText) config.add(self.badExtensionsLabel) config.add(self.badMimesButton) config.add(self.badMimesText) config.add(self.badMimesLabel) config.add(self.badExtensionsDefaultButton) config.add(self.badMimesDefaultButton) config.add(self.otherLabel) config.add(self.repeaterOptionButton) config.add(self.scopeOptionButton) config.add(self.markTestedRequestsProxy) config.add(self.markNotTestedRequestsProxy) iexport.add(self.saveButton) iexport.add(self.loadButton) iexport.add(self.selectPath) iexport.add(self.selectPathText) iexport.add(self.selectPathLabel) iexport.add(self.otherLabel2) iexport.add(self.autoSaveOption) self._config.addTab("General", config) self._config.addTab("Import/Export", iexport) ##### end config pane self._parentPane.addTab("Monitor", self._splitpane) self._parentPane.addTab("Config", self._config) # table of log entries self.logTable = Table(self) #self.logTable.setDefaultRenderer(self.logTable.getColumnClass(0), ColoredTableCellRenderer(self)) self.logTable.setAutoCreateRowSorter(True) self.logTable.setRowSelectionAllowed(True) renderer = ColoredTableCellRenderer(self) #column = TableColumn(0, 190, renderer, None) print 'Initiating... ' # this could be improved by fetching initial dimensions self.logTable.getColumn("URL").setPreferredWidth(720) # noscope self.logTable.getColumn("URL").setResizable(True) self.logTable.getColumn("Checked").setCellRenderer(renderer) self.logTable.getColumn("Checked").setPreferredWidth(80) self.logTable.getColumn("Checked").setMaxWidth(80) self.logTable.getColumn("Method").setPreferredWidth(120) #self.logTable.getColumn("Method").setMaxWidth(120) self.logTable.getColumn("Method").setResizable(True) self.logTable.getColumn("Time").setPreferredWidth(120) # noscope self.logTable.getColumn("Time").setResizable(True) scrollPane = JScrollPane(self.logTable) self._splitpane.setLeftComponent(scrollPane) # 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) ## Row sorter shit #self._tableRowSorterAutoProxyAutoAction = CustomTableRowSorter(self.logTable.getModel()) #self.logTable.setRowSorter(self._tableRowSorterAutoProxyAutoAction) markAnalyzedButton = JMenuItem("Mark Requests as Analyzed") markAnalyzedButton.addActionListener(markRequestsHandler(self, True)) markNotAnalyzedButton = JMenuItem("Mark Requests as NOT Analyzed") markNotAnalyzedButton.addActionListener( markRequestsHandler(self, False)) sendRequestMenu = JMenuItem("Send Request to Repeater") sendRequestMenu.addActionListener(sendRequestRepeater(self)) deleteRequestMenu = JMenuItem("Delete request") deleteRequestMenu.addActionListener(deleteRequestHandler(self)) self.menu = JPopupMenu("Popup") self.menu.add(markAnalyzedButton) self.menu.add(markNotAnalyzedButton) self.menu.add(sendRequestMenu) self.menu.add(deleteRequestMenu) # customize our UI components callbacks.customizeUiComponent(self._parentPane) callbacks.customizeUiComponent(self._splitpane) callbacks.customizeUiComponent(self._config) callbacks.customizeUiComponent(config) callbacks.customizeUiComponent(self.logTable) callbacks.customizeUiComponent(scrollPane) callbacks.customizeUiComponent(tabs) callbacks.registerContextMenuFactory(self) callbacks.registerExtensionStateListener(self) callbacks.registerScannerCheck(passiveScanner(self)) # add the custom tab to Burp's UI callbacks.addSuiteTab(self) # register ourselves as an HTTP listener callbacks.registerHttpListener(self) self.loadConfigs() print "Loaded!" print "Experimental import state.. " self.importState("") self.SC = sched.scheduler(time.time, time.sleep) self.SCC = self.SC.enter(10, 1, self.autoSave, (self.SC, )) self.SC.run() return ##### CUSTOM CODE ##### def loadConfigs(self): if self._callbacks.loadExtensionSetting("CONFIG_AUTOSTART") == "False": self.startOptionButton.setSelected(False) self.startOrStop(None, False) else: self.startOptionButton.setSelected(True) self.startOrStop(None, True) if self._callbacks.loadExtensionSetting("exportFile") != "": self.selectPathText.setText( self._callbacks.loadExtensionSetting("exportFile")) if self._callbacks.loadExtensionSetting("CONFIG_REPEATER") == "True": self.repeaterOptionButton.setSelected(True) else: self.repeaterOptionButton.setSelected(False) if self._callbacks.loadExtensionSetting("CONFIG_INSCOPE") == "True": self.scopeOptionButton.setSelected(True) else: self.scopeOptionButton.setSelected(False) if self._callbacks.loadExtensionSetting("CONFIG_AUTOSAVE") == "True": self.autoSaveOption.setSelected(True) else: self.autoSaveOption.setSelected(False) if self._callbacks.loadExtensionSetting( "CONFIG_HIGHLIGHT_TESTED") == "True": self.markTestedRequestsProxy.setSelected(True) else: self.markTestedRequestsProxy.setSelected(False) if self._callbacks.loadExtensionSetting( "CONFIG_HIGHLIGHT_NOT_TESTED") == "True": self.markNotTestedRequestsProxy.setSelected(True) else: self.markNotTestedRequestsProxy.setSelected(False) return def selectExportFile(self, event): parentFrame = JFrame() fileChooser = JFileChooser() fileChooser.setDialogTitle("Specify file to save state") fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY) userSelection = fileChooser.showOpenDialog(parentFrame) if (userSelection == JFileChooser.APPROVE_OPTION): fileLoad = fileChooser.getSelectedFile() filename = fileLoad.getAbsolutePath() self.selectPathText.setText(filename) print 'Filename selected:' + filename self._callbacks.saveExtensionSetting("exportFile", filename) return def extensionUnloaded(self): print 'extension unloading.. ' print 'canceling scheduler.. ' map(self.SC.cancel, self.SC.queue) return def loadBadExtensions(self): bad = self._callbacks.loadExtensionSetting("badExtensions") if bad: self.badExtensionsText.setText(bad) # transform text to array bad = bad.replace(" ", "") self.BAD_EXTENSIONS = bad.split(",") else: print 'no bad extension saved, reverting' self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS)) def loadBadMimes(self): bad = self._callbacks.loadExtensionSetting("badMimes") if bad: self.badMimesText.setText(bad) bad = bad.replace(" ", "") self.BAD_MIMES = bad.split(",") else: print 'no bad mimes saved, reverting' self.badMimesText.setText(", ".join(self.BAD_MIMES)) ## GLOBAL CONTEXT CODE ## def createMenuItems(self, invocation): responses = invocation.getSelectedMessages() if responses > 0: ret = LinkedList() analyzedMenuItem = JMenuItem("Mark as analyzed") notAnalyzedMenuItem = JMenuItem("Mark as NOT analyzed") for response in responses: analyzedMenuItem.addActionListener( handleMenuItems(self, response, "analyzed")) notAnalyzedMenuItem.addActionListener( handleMenuItems(self, response, "not")) ret.add(analyzedMenuItem) ret.add(notAnalyzedMenuItem) return ret def getEndpoint(self, requestResponse): url_ = str(self._helpers.analyzeRequest(requestResponse).getUrl()) o = urlparse(url_) url = o.scheme + "://" + o.netloc + o.path #print "Url3: " + url return url def getMethod(self, requestResponse): return self._helpers.analyzeRequest(requestResponse).getMethod() ##### CUSTOM CODE ##### def handleTestedRequestsProxy(self, event): self._callbacks.saveExtensionSetting( "CONFIG_HIGHLIGHT_TESTED", str(self.markTestedRequestsProxy.isSelected())) return def handleNotTestedRequestsProxy(self, event): self._callbacks.saveExtensionSetting( "CONFIG_HIGHLIGHT_NOT_TESTED", str(self.markNotTestedRequestsProxy.isSelected())) return def handleStartOption(self, event): self._callbacks.saveExtensionSetting( "CONFIG_AUTOSTART", str(self.startOptionButton.isSelected())) #print 'saving autostart: ' + str(self.startOptionButton.isSelected()) return def startOrStop(self, event, autoStart): if (self.startButton.getText() == MONITOR_OFF_LABEL) or autoStart: self.startButton.setText(MONITOR_ON_LABEL) self.startButton.setBackground(GREEN_COLOR) self.STATUS = True else: self.startButton.setText(MONITOR_OFF_LABEL) self.startButton.setBackground(RED_COLOR) self.STATUS = False def handleStartButton(self, event): self.startOrStop(event, False) def handleAutoSaveOption(self, event): self._callbacks.saveExtensionSetting( "CONFIG_AUTOSAVE", str(self.autoSaveOption.isSelected())) return def handleSaveButton(self, event): self.exportState("") def handleLoadButton(self, event): self.importState("") def handleRepeaterOptionButton(self, event): self._callbacks.saveExtensionSetting( "CONFIG_REPEATER", str(self.repeaterOptionButton.isSelected())) return def handleScopeOptionButton(self, event): self.CONFIG_INSCOPE = self.scopeOptionButton.isSelected() self._callbacks.saveExtensionSetting("CONFIG_INSCOPE", str(self.CONFIG_INSCOPE)) return def handleBadExtensionsButton(self, event): #print "before BAD array: " print self.BAD_EXTENSIONS extensions = self.badExtensionsText.getText() self._callbacks.saveExtensionSetting("badExtensions", extensions) print 'New extensions blocked: ' + extensions bad = extensions.replace(" ", "") self.BAD_EXTENSIONS = bad.split(",") #print "BAD array: " #print self.BAD_EXTENSIONS def handleBadExtensionsDefaultButton(self, event): self.BAD_EXTENSIONS = self.BAD_EXTENSIONS_DEFAULT self.badExtensionsText.setText(", ".join(self.BAD_EXTENSIONS)) self._callbacks.saveExtensionSetting("badExtensions", ", ".join(self.BAD_EXTENSIONS)) return def handleBadMimesDefaultButton(self, event): self.BAD_MIMES = self.BAD_MIMES_DEFAULT self.badMimesText.setText(", ".join(self.BAD_MIMES)) self._callbacks.saveExtensionSetting("badExtensions", ", ".join(self.BAD_MIMES)) return def handleBadMimesButton(self, event): mimes = self.badMimesText.getText() self._callbacks.saveExtensionSetting("badMimes", mimes) print 'New mimes blocked: ' + mimes bad = mimes.replace(" ", "") self.BAD_MIMES = bad.split(",") def handleClearButton(self, event): print 'Clearing table' self._lock.acquire() self._log = ArrayList() self._fullLog = ArrayList() self._lock.release() return def handleRadioConfig(self, event): #print ' radio button clicked ' #print event.getActionCommand() self._lock.acquire() if event.getActionCommand() == SHOW_ALL_BUTTON_LABEL: print "Showing all" self._log = self._fullLog elif event.getActionCommand() == SHOW_NEW_BUTTON_LABEL: print "Showing new scope only" tmpLog = ArrayList() for item in self._fullLog: if not (item._analyzed): tmpLog.add(item) self._log = tmpLog elif event.getActionCommand() == SHOW_TEST_BUTTON_LABEL: print "Showing tested scope only" tmpLog = ArrayList() for item in self._fullLog: if item._analyzed: tmpLog.add(item) self._log = tmpLog else: print "unrecognized radio label" self.fireTableDataChanged() #self._tableRowSorterAutoProxyAutoAction.toggleSortOrder(1) #self.toggleSortOrder(2) #self.logTable.toggleSortOrder(2) # refresh table? self._lock.release() # # implement ITab # def getTabCaption(self): return "Scope Monitor" def getUiComponent(self): return self._parentPane # # implement IHttpListener # def markAnalyzed(self, messageIsRequest, state): #print "markAnalyzed..." self._lock.acquire() url = self.getEndpoint(messageIsRequest) for item in self._log: if url == item._url: item._analyzed = state self._lock.release() return self._lock.release() return def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): # only process requests #print "processing httpMessage.." #print messageIsRequest print "processHttpMessage toolFlag: " + str(toolFlag) #print " -- " + str(self._callbacks.getToolName(toolFlag)) + " -- " if not (self.STATUS): return #print "global handler status: (true): " + str(self.GLOBAL_HANDLER) #print "(processHTTP) messageIsRequest" #print messageIsRequest isFromPassiveScan = False if toolFlag == 1234: print "1 processHttpMessage: processing passiveScan item" isFromPassiveScan = True if toolFlag != 1234: if messageIsRequest and not (self.GLOBAL_HANDLER): print "1.5 processHttpMessage droping message" return if self.scopeOptionButton.isSelected(): url = self._helpers.analyzeRequest(messageInfo).getUrl() if not self._callbacks.isInScope(url): #print 'Url not in scope, skipping.. ' return #print "still processing httpMessage.., request came from: " + self._callbacks.getToolName(toolFlag) if toolFlag == 1234: print "2 processHttpMessage: processing passiveScan item; setting toolFlag to proxy (4)" toolFlag = 4 #toolFlag = 4 if ((self._callbacks.getToolName(toolFlag) != "Repeater") and (self._callbacks.getToolName(toolFlag) != "Proxy") and (self._callbacks.getToolName(toolFlag) != "Target")): #print 'Aborting processHTTP, request came from: ' + str(self._callbacks.getToolName(toolFlag)) print "Droping request from " + str( self._callbacks.getToolName(toolFlag)) return #print "---> still processing from tool: " + str(self._callbacks.getToolName(toolFlag)) url = self.getEndpoint(messageInfo) method = self.getMethod(messageInfo) #print "(processHTTP) before extensions check: " + url for extension in self.BAD_EXTENSIONS: if url.endswith(extension): return if messageInfo.getResponse(): mime = self._helpers.analyzeResponse( messageInfo.getResponse()).getStatedMimeType() #print 'Declared mime:' + mime mime = mime.lower() if mime in self.BAD_MIMES: #print 'Bad mime:' + mime return #print "[httpMessage] before lock" # create a new log entry with the message details self._lock.acquire() row = self._log.size() for item in self._log: if url == item._url: if method == self._helpers.analyzeRequest( item._requestResponse).getMethod(): #print 'duplicate URL+method, skipping.. ' self._lock.release() # has it been analyzed? analyzed = False if self._callbacks.getToolName(toolFlag) == "Repeater": if self.repeaterOptionButton.isSelected(): analyzed = True #print "[httpMessage] setting analyzed as true" if self.GLOBAL_HANDLER_ANALYZED: analyzed = True item._analyzed = analyzed self.paintItems(messageInfo, item) return #print "[httpMessage] before setComment" if not (isFromPassiveScan): messageInfo.setComment(SCOPE_MONITOR_COMMENT) # reached here, must be new entry analyzed = False if self._callbacks.getToolName(toolFlag) == "Repeater": if self.repeaterOptionButton.isSelected(): analyzed = True #print "[httpMessage] setting analyzed as true" if self.GLOBAL_HANDLER_ANALYZED: analyzed = True #print "[httpMessage] after comment" #print 'in httpmessage, response:' #print self._helpers.analyzeResponse(messageInfo.getResponse()) date = datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S %d %b %Y') entry = LogEntry(toolFlag, self._callbacks.saveBuffersToTempFiles(messageInfo), url, analyzed, date, method) #print "toolFlag: " + str(toolFlag) #print "(processHTTP) Adding URL: " + url self._log.add(entry) self._fullLog.add(entry) self.fireTableRowsInserted(row, row) self.paintItems(messageInfo, entry) self._lock.release() #print "columnCoun:" + str(self.logTable.getColumnCount()) # # extend AbstractTableModel # def paintItems(self, messageInfo, item): ''' print "in paint Items" print "mark color is: (true)" + str(self.markTestedRequestsProxy.isSelected()) print "global handler analyzed: :" + str(self.GLOBAL_HANDLER_ANALYZED) print "item analyzed should be the same ^^:" + str(item._analyzed) ''' if (self.markTestedRequestsProxy.isSelected()) and ( item._analyzed and self.GLOBAL_HANDLER_ANALYZED): messageInfo.setHighlight("green") return if self.markNotTestedRequestsProxy.isSelected() and not ( item._analyzed): messageInfo.setHighlight("red") def getRowCount(self): try: return self._log.size() except: return 0 def getColumnCount(self): return 4 def getColumnName(self, columnIndex): if columnIndex == 0: return "Checked" if columnIndex == 1: return "URL" if columnIndex == 2: return "Method" if columnIndex == 3: return "Time" def getValueAt(self, rowIndex, columnIndex): logEntry = self._log.get(rowIndex) #self.setBackground(Color.GREEN) return self.returnEntry(rowIndex, columnIndex, logEntry) if self.showNewButton.isSelected() and not (logEntry._analyzed): return self.returnEntry(rowIndex, columnIndex, logEntry) elif self.showTestedButton.isSelected() and logEntry._analyzed: return self.returnEntry(rowIndex, columnIndex, logEntry) elif self.showAllButton.isSelected(): return self.returnEntry(rowIndex, columnIndex, logEntry) def returnEntry(self, rowIndex, columnIndex, entry): logEntry = self._log.get(rowIndex) if columnIndex == 0: if logEntry._analyzed: return "True" else: return "False" if columnIndex == 1: return self._helpers.urlDecode(logEntry._url) if columnIndex == 2: return logEntry._method if columnIndex == 3: return logEntry._date # return date 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): #print 'getRequest called' return self._currentlyDisplayedItem.getRequest() def getResponse(self): #print 'getResponse called: ' print self._currentlyDisplayedItem.getResponse() return self._currentlyDisplayedItem.getResponse() def exportRequest(self, entity, filename): line = str(entity._analyzed) + "," line = line + self._helpers.urlEncode(entity._url).replace( ",", "%2c") + "," # URL is encoded so we should be good line = line + entity._method + "," line = line + entity._date line = line + '\n' #print 'Exporting: "' + line + '"' return line def exportUrlEncode(self, url): return self._helpers.urlEncode(url).replace(",", "%2c") def exportState(self, filename): filename = self.selectPathText.getText() if filename == "": filename = self._callbacks.loadExtensionSetting("exportFile") print 'Empty filename, skipping export' return else: self._callbacks.saveExtensionSetting("exportFile", filename) print 'saving state to: ' + filename savedUrls = [] self._lockFile.acquire() try: with open(filename, 'r') as fr: savedEntries = fr.read().splitlines() savedUrls = [] for savedEntry in savedEntries: savedUrls.append(savedEntry.split(",")[1]) #print "savedUrls len: " + str(len(savedUrls)) #print "savedUrls:" #print savedUrls fr.close() except IOError: print "Autosaving skipped as file doesn't exist yet" with open(filename, 'a+') as f: for item in self._log: if self.exportUrlEncode(item._url) not in savedUrls: line = self.exportRequest(item, "xx") f.write(line) f.close() self._lockFile.release() return def importState(self, filename): filename = self.selectPathText.getText() if filename == "": filename = self._callbacks.loadExtensionSetting("exportFile") print 'Empty filename, skipping import' return else: self._callbacks.saveExtensionSetting("exportFile", filename) print 'loading state from: ' + filename self.STATUS = False self._lockFile.acquire() with open(filename, 'r') as f: proxy = self._callbacks.getProxyHistory() proxyItems = [] for item in proxy: if item.getComment(): if SCOPE_MONITOR_COMMENT in item.getComment(): proxyItems.append(item) print 'proxyItems has: ' + str(len(proxyItems)) # TODO - if no proxy items, sraight to import lines = f.read().splitlines() for line in lines: data = line.split(",") url = data[1] url = self._helpers.urlDecode(url) #print 'Saving: ' + url if not self._callbacks.isInScope(URL(url)): print '-- imported url not in scope, skipping.. ' continue analyzed = False if data[0] == "True": analyzed = True #print '.. simulating url search.. ' requestResponse = None for request in proxyItems: if url == self.getEndpoint(request): #print 'Match found when importing for url: ' + url requestResponse = request break self._log.add( LogEntry("", requestResponse, url, analyzed, data[3], data[2])) self._lockFile.release() print 'finished loading.. ' #print 'size: ' + str(self._log.size()) self.fireTableDataChanged() if self.startButton.getText() == MONITOR_ON_LABEL: self.STATUS = True return def autoSave(self, sc): #print 'autosaving.. lol what' if self.autoSaveOption.isSelected(): print "[" + self.getTime( ) + "] autosaving to " + self._callbacks.loadExtensionSetting( "exportFile") self.exportState("") self.SC.enter(self.AUTOSAVE_TIMEOUT, 1, self.autoSave, (self.SC, )) return def getTime(self): date = datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S') return date
class SystemPanel(JPanel, ActionListener, ItemListener, PropertyChangeListener): def propertyChange(self, evt): if evt.getSource() == self.fdr and evt.getPropertyName() == 'value': new = float(evt.getNewValue()) old = float(evt.getOldValue()) if new > 0.99: evt.getSource().setValue(old) if new < 0.005: evt.getSource().setValue(old) def itemStateChanged(self, e): if self.enableChartFun: self.chartFun() def actionPerformed(self, e): if e.getID() <> ActionEvent.ACTION_PERFORMED: return if e.getSource() == self.neutral: if self.isTemporal: warn(self, """ Using a "neutral" mean Ne means doing a first simulation run to remove potential selected loci for computing the initial mean Ne. This effectively doubles the computation time, but it is the recommended option. If you are not sure of what you want, please check this option. """) else: warn(self, """ Using a "neutral" mean Fst means doing a first simulation run to remove potential selected loci for computing the initial mean Fst. This effectively doubles the computation time, but it is the recommended option. If you are not sure of what you want, please check this option. """) elif e.getSource() == self.force: warn(self, """ Simulating a PRECISE mean Fst is not possible outside ideal theoretical conditions (infinite populations, infinite allele model). SELWB can try to approximate a desired Fst, by running a bisection algorithm over repeated simulations. Checking this option will increase the computation time by a certain amount of time (in most cases it will double the computation time), this is still, the recommended option. If you are not sure of what you want, please check this option. """) def getForce(self): if self.force.getSelectedObjects() == None: return False else: return True def getNeutral(self): if self.neutral.getSelectedObjects() == None: return False else: return True def getCI(self): return float(self.ci.getSelectedItem()) def getFDR(self): return self.fdr.getValue() def getNumCores(self): return int(self.cores.getSelectedItem()) def getNumSims(self): return 1000*int(self.numSims.getSelectedItem()) def __init__(self, chartFun, isTemporal = False): self.isTemporal = isTemporal JPanel() #self.setBackground(Color.LIGHT_GRAY) self.chartFun = chartFun self.enableChartFun = False self.setLayout(GridLayout(6,2)) self.add(JLabel('CPU Cores')) nprocs = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors() procvals = sorted(set([nprocs, 1, 2, 4, 8, 16, 32, 64, 128])) cores = JComboBox(procvals) cores.setSelectedIndex(procvals.index(nprocs)) cores.setMaximumSize(cores.getPreferredSize()) self.cores = cores self.add(self.cores) self.add(JLabel('# of sims (x1000) ')) numSims = JComboBox( map(lambda x: str((10+x)*5), range(10)) + map(lambda x: str(x*100), range(1,11)) ) numSims.setMaximumSize(numSims.getPreferredSize()) self.numSims = numSims self.add(self.numSims) if isTemporal: self.add(JLabel('"Neutral" Ne')) self.neutral = JCheckBox() self.neutral.addActionListener(self) self.add(self.neutral) else: self.add(JLabel('"Neutral" mean Fst')) self.neutral = JCheckBox() self.neutral.addActionListener(self) self.add(self.neutral) self.add(JLabel('Force mean Fst')) self.force = JCheckBox() self.force.addActionListener(self) self.add(self.force) self.add(JLabel('Confidence interval ')) ci = JComboBox(['0.95', '0.99', '0.995']) ci.addItemListener(self) ci.setMaximumSize(cores.getPreferredSize()) self.ci = ci self.add(self.ci) self.add(JLabel('False Disc. Rate')) fdr = JFormattedTextField( NumberFormat.getNumberInstance(Locale.US)) fdr.setValue(0.1) fdr.addPropertyChangeListener(self) self.add(fdr) self.fdr = fdr
class BurpExtender(IBurpExtender, IExtensionStateListener, IHttpListener, ITab, FocusListener, ActionListener, MouseAdapter): _version = "0.2" _name = "PyRules" _varsStorage = _name + "_vars" _scriptStorage = _name + "_script" _enabled = 0 _vars = {} def registerExtenderCallbacks(self, callbacks): print "Load:" + self._name + " " + self._version self.callbacks = callbacks self.helpers = callbacks.helpers #Create Tab layout self.jVarsPane = JTextPane() self.jVarsPane.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jVarsPane.addFocusListener(self) self.jMenuPanel = JPanel() self.jLeftUpPanel = JPanel() self.jEnable = JCheckBox() self.jEnable.setFont(Font('Monospaced', Font.BOLD, 11)) self.jEnable.setForeground(Color(0, 0, 204)) self.jEnable.setText(self._name) self.jEnable.addActionListener(self) self.jDocs = JLabel() self.jDocs.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jDocs.setForeground(Color(51, 102, 255)) self.jDocs.setText(Strings.docs_titel) self.jDocs.setToolTipText(Strings.docs_tooltip) self.jDocs.addMouseListener(self) self.jConsoleText = JTextArea() self.jConsoleText.setFont(Font('Monospaced', Font.PLAIN, 10)) self.jConsoleText.setBackground(Color(244, 246, 247)) self.jConsoleText.setEditable(0) self.jConsoleText.setWrapStyleWord(1) self.jConsoleText.setRows(10) self.jScrollConsolePane = JScrollPane() self.jScrollConsolePane.setViewportView(self.jConsoleText) #set initial text self.jConsoleText.setText(Strings.console_disable) self.jMenuPanelLayout = GroupLayout(self.jMenuPanel) self.jMenuPanel.setLayout(self.jMenuPanelLayout) self.jMenuPanelLayout.setHorizontalGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( self.jMenuPanelLayout.createSequentialGroup().addComponent( self.jEnable).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED, 205, 32767).addComponent(self.jDocs))) self.jMenuPanelLayout.setVerticalGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( self.jMenuPanelLayout.createSequentialGroup().addGroup( self.jMenuPanelLayout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.jEnable).addComponent(self.jDocs)).addGap( 0, 7, 32767))) self.jConsolePane = JPanel() self.jConsoleLayout = GroupLayout(self.jConsolePane) self.jConsolePane.setLayout(self.jConsoleLayout) self.jConsoleLayout.setHorizontalGroup( self.jConsoleLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addComponent( self.jScrollConsolePane)) self.jConsoleLayout.setVerticalGroup( self.jConsoleLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( GroupLayout.Alignment.TRAILING, self.jConsoleLayout.createSequentialGroup().addComponent( self.jScrollConsolePane, GroupLayout.DEFAULT_SIZE, 154, 32767).addContainerGap())) self.jLeftUpPanelLayout = GroupLayout(self.jLeftUpPanel) self.jLeftUpPanel.setLayout(self.jLeftUpPanelLayout) self.jLeftUpPanelLayout.setHorizontalGroup( self.jLeftUpPanelLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addComponent( self.jConsolePane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, 32767).addComponent(self.jMenuPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) self.jLeftUpPanelLayout.setVerticalGroup( self.jLeftUpPanelLayout. createParallelGroup(GroupLayout.Alignment.LEADING).addGroup( GroupLayout.Alignment.TRAILING, self.jLeftUpPanelLayout.createSequentialGroup().addComponent( self.jMenuPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED).addComponent( self.jConsolePane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, 32767))) self.jScrollpaneLeftDown = JScrollPane() self.jScrollpaneLeftDown.setViewportView(self.jVarsPane) self.jSplitPaneLeft = JSplitPane(JSplitPane.VERTICAL_SPLIT, self.jLeftUpPanel, self.jScrollpaneLeftDown) self.jSplitPaneLeft.setDividerLocation(300) self.jScriptPane = JTextPane() self.jScriptPane.setFont(Font('Monospaced', Font.PLAIN, 11)) self.jScriptPane.addMouseListener(self) self.JScrollPaneRight = JScrollPane() self.JScrollPaneRight.setViewportView(self.jScriptPane) self.jSplitPane = JSplitPane(JSplitPane.HORIZONTAL_SPLIT, self.jSplitPaneLeft, self.JScrollPaneRight) self.jSplitPane.setDividerLocation(400) #Load saved saved settings ##Load vars vars = callbacks.loadExtensionSetting(self._varsStorage) if vars: vars = base64.b64decode(vars) else: # try to load the example try: with open("examples/Simple-CSRF-vars.py") as fvars: vars = fvars.read() # load the default text except: vars = Strings.vars ## initiate the persistant variables locals_ = {} try: exec(vars, {}, locals_) except Exception as e: print e self._vars = locals_ ## update the vars screen self.jVarsPane.document.insertString(self.jVarsPane.document.length, vars, SimpleAttributeSet()) ##Load script script = callbacks.loadExtensionSetting(self._scriptStorage) if script: script = base64.b64decode(script) else: # try to load the example try: with open("examples/Simple-CSRF-script.py") as fscript: script = fscript.read() # load the default text except: script = Strings.script ## compile the rules self._script = script self._code = '' try: self._code = compile(script, '<string>', 'exec') except Exception as e: print( '{}\nReload extension after you correct the error.'.format(e)) ## update the rules screen self.jScriptPane.document.insertString( self.jScriptPane.document.length, script, SimpleAttributeSet()) #Register Extension callbacks.customizeUiComponent(self.getUiComponent()) callbacks.addSuiteTab(self) callbacks.registerExtensionStateListener(self) callbacks.registerHttpListener(self) self.jScriptPane.requestFocus() def getUiComponent(self): return self.jSplitPane def getTabCaption(self): return self._name def actionPerformed(self, event): #Check box was clicked if self.jEnable == event.getSource(): if self._enabled == 1: self._enabled = 0 # console content shows help self.jConsoleText.setText(Strings.console_disable) else: self._enabled = 1 # console content displays the current persistent variable state self.jConsoleText.setText(Strings.console_state) self.jConsoleText.append(pformat(self._vars)) self.jConsoleText.append(Strings.extra_line) self.jConsoleText.append(Strings.console_log) return def mouseClicked(self, event): if event.source == self.jDocs: uri = URI.create("https://github.com/DanNegrea/PyRules") if uri and Desktop.isDesktopSupported() and Desktop.getDesktop( ).isSupported(Desktop.Action.BROWSE): Desktop.getDesktop().browse(uri) return def focusGained(self, event): if self.jConsolePane == event.getSource(): pass #print "Status pane gained focus" #debug return def focusLost(self, event): #Reinitialize the persistent values if self.jVarsPane == event.getSource(): # get the text from the pane end = self.jVarsPane.document.length vars = self.jVarsPane.document.getText(0, end) # compute the new values locals_ = {} exec(vars, {}, locals_) self._vars = locals_ # display the new result in console self.jConsoleText.append(Strings.console_state) self.jConsoleText.append(pformat(self._vars)) self.jConsoleText.append(Strings.extra_line) self.jConsoleText.append(Strings.console_log) # scroll to bottom verticalScrollBar = self.jScrollConsolePane.getVerticalScrollBar() verticalScrollBar.setValue(verticalScrollBar.getMaximum()) return def extensionUnloaded(self): try: #Save the latestest vars and script text ## save vars end = self.jVarsPane.document.length vars = self.jVarsPane.document.getText(0, end) vars = base64.b64encode(vars) self.callbacks.saveExtensionSetting(self._varsStorage, vars) ## save script/rules end = self.jScriptPane.document.length script = self.jScriptPane.document.getText(0, end) script = base64.b64encode(script) self.callbacks.saveExtensionSetting(self._scriptStorage, script) except Exception: traceback.print_exc(file=self.callbacks.getStderr()) print "Unloaded" #debug return def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): if self._enabled == 0: return try: locals_ = { 'extender': self, 'callbacks': self.callbacks, 'helpers': self.helpers, 'toolFlag': toolFlag, 'messageIsRequest': messageIsRequest, 'messageInfo': messageInfo, 'log': self.log } # add the _vars as gloval variables locals_ = dict(locals_, **self._vars) # execute the script/rules try: exec(self.getCode, {}, locals_) # catch exit() call inside the rule except SystemExit: pass # update the persistant variables by searching the local variables with the same name for key in self._vars: # assumption self._vars dictionary is smaller than locals_ if key in locals_: self._vars[key] = locals_[key] except Exception: traceback.print_exc(file=self.callbacks.getStderr()) return #Returns the compiled script @property def getCode(self): end = self.jScriptPane.document.length script = self.jScriptPane.document.getText(0, end) # if the script hasn't changed return the already compile text if script == self._script: return self._code self._script = script # compile, store and return the result self._code = compile(script, '<string>', 'exec') return self._code #Log the information into the console screen def log(self, obj): # if string just append. else use pformat from pprint if isinstance(obj, str): self.jConsoleText.append(obj + "\n") else: self.jConsoleText.append(pformat(obj) + "\n") # scroll to bottom verticalScrollBar = self.jScrollConsolePane.getVerticalScrollBar() verticalScrollBar.setValue(verticalScrollBar.getMaximum()) return
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 SystemPanel(JPanel, ActionListener, ItemListener, PropertyChangeListener): def propertyChange(self, evt): if evt.getSource() == self.fdr and evt.getPropertyName() == 'value': new = float(evt.getNewValue()) old = float(evt.getOldValue()) if new > 0.99: evt.getSource().setValue(old) if new < 0.005: evt.getSource().setValue(old) def itemStateChanged(self, e): if self.enableChartFun: self.chartFun() def actionPerformed(self, e): if e.getID() <> ActionEvent.ACTION_PERFORMED: return if e.getSource() == self.neutral: if self.isTemporal: warn(self, """ Using a "neutral" mean Ne means doing a first simulation run to remove potential selected loci for computing the initial mean Ne. This effectively doubles the computation time, but it is the recommended option. If you are not sure of what you want, please check this option. """) else: warn(self, """ Using a "neutral" mean Fst means doing a first simulation run to remove potential selected loci for computing the initial mean Fst. This effectively doubles the computation time, but it is the recommended option. If you are not sure of what you want, please check this option. """) elif e.getSource() == self.force: warn(self, """ Simulating a PRECISE mean Fst is not possible outside ideal theoretical conditions (infinite populations, infinite allele model). SELWB can try to approximate a desired Fst, by running a bisection algorithm over repeated simulations. Checking this option will increase the computation time by a certain amount of time (in most cases it will double the computation time), this is still, the recommended option. If you are not sure of what you want, please check this option. """) def getForce(self): if self.force.getSelectedObjects() == None: return False else: return True def getNeutral(self): if self.neutral.getSelectedObjects() == None: return False else: return True def getCI(self): return float(self.ci.getSelectedItem()) def getFDR(self): return self.fdr.getValue() def getNumCores(self): return int(self.cores.getSelectedItem()) def getNumSims(self): return 1000*int(self.numSims.getSelectedItem()) def __init__(self, chartFun, isTemporal = False): self.isTemporal = isTemporal JPanel() #self.setBackground(Color.LIGHT_GRAY) self.chartFun = chartFun self.enableChartFun = False self.setLayout(GridLayout(6,2)) self.add(JLabel('CPU Cores')) cores = JComboBox(['1', '2', '4', '8', '16', '32', '64', '128']) nprocs = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors() pos = min([7, log(ceil(nprocs)) / log(2)]) cores.setSelectedIndex(int(pos)) cores.setMaximumSize(cores.getPreferredSize()) self.cores = cores self.add(self.cores) self.add(JLabel('# of sims (x1000) ')) numSims = JComboBox( map(lambda x: str((10+x)*5), range(10)) + map(lambda x: str(x*100), range(1,11)) ) numSims.setMaximumSize(numSims.getPreferredSize()) self.numSims = numSims self.add(self.numSims) if isTemporal: self.add(JLabel('"Neutral" Ne')) self.neutral = JCheckBox() self.neutral.addActionListener(self) self.add(self.neutral) else: self.add(JLabel('"Neutral" mean Fst')) self.neutral = JCheckBox() self.neutral.addActionListener(self) self.add(self.neutral) self.add(JLabel('Force mean Fst')) self.force = JCheckBox() self.force.addActionListener(self) self.add(self.force) self.add(JLabel('Confidence interval ')) ci = JComboBox(['0.95', '0.99', '0.995']) ci.addItemListener(self) ci.setMaximumSize(cores.getPreferredSize()) self.ci = ci self.add(self.ci) self.add(JLabel('False Disc. Rate')) fdr = JFormattedTextField( NumberFormat.getNumberInstance(Locale.US)) fdr.setValue(0.1) fdr.addPropertyChangeListener(self) self.add(fdr) self.fdr = fdr