def getGUI(sym_dict): global frame, outCheckbox, fillCheckbox, slider, colorTF, widthTF frame = JFrame("Border Symbology", defaultCloseOperation=JFrame.DISPOSE_ON_CLOSE, bounds=(100, 100, 450, 200), layout=FlowLayout(), resizable=0) colorL = JLabel('Color: ') colorTF = JTextField(20) color = sym_dict["color"] color = Color(color.getRed(), color.getGreen(), color.getBlue(), sym_dict["alpha"]) colorTF.setBackground(color) colorTF.setText(color.toString()) colorB = JButton('...', actionPerformed=colorChooser) frame.add(colorL) frame.add(colorTF) frame.add(colorB) widthL = JLabel('Width: ') widthTF = JTextField(3) widthTF.setText(str(sym_dict["width"])) frame.add(widthL) frame.add(widthTF) alphaL = JLabel('Transparency: ') frame.add(alphaL) # Create a horizontal slider with min=0, max=100, value=50 slider = JSlider() slider.setPreferredSize(Dimension(200, 50)) slider.setValue(sym_dict["alpha"]*100/255) slider.setMajorTickSpacing(25) slider.setMinorTickSpacing(5) slider.setPaintTicks(1) slider.setPaintLabels(1) applyButton = JButton("Apply", actionPerformed=action) acceptButton = JButton("Accept", actionPerformed=accept) frame.add(slider) frame.add(applyButton) frame.add(acceptButton) frame.show()
class MainPanel(): """Represents the converted frame from NetBeans.""" # default issue to populate the panel with defaultIssue = Issue(name="Name", severity="Critical", host="Host", path="Path", description="Description", remediation="", reqResp=RequestResponse(request="default request", response="default response")) def loadPanel(self, issue): # type: (Issue) -> () """Populates the panel with issue.""" if issue is None: return # check if the input is the correct object assert isinstance(issue, Issue) # add selected issue to the panel to enable right-click stuff. self.selectedIssue = issue # set textfields and textareas self.textName.text = issue.name self.textHost.text = issue.host self.textPath.text = issue.path self.textAreaDescription.text = issue.description self.textAreaRemediation.text = issue.remediation self.textSeverity.text = issue.severity # request and response tabs self.panelRequest.setMessage(issue.getRequest(), True) self.panelResponse.setMessage(issue.getResponse(), False) # button actions def newIssueAction(self, event): """Pops up a frame to add a new issue.""" frm = NewIssueDialog(callbacks=self.callbacks, title="New Issue") frm.display(self) def gotNewIssue(self, issue): """got a new issue.""" self.tableIssue.addRow(issue) def editIssue(self, index, issue): """Issue has been edited.""" self.tableIssue.editRow(index, issue) def deleteIssueAction(self, event): """Delete the currently selected issue.""" # this is the button # btn = event.getSource() row = self.tableIssue.getTableSelectedRow() # YOLO self.tableIssue.deleteRow(row) # it works! def exportAction(self, event): """Export everything in the table to a file.""" lastDir = "" try: # load the last used directory # this will probably change as we will use a base64 encoded json as the complete config? lastDir = self.callbacks.loadExtensionSetting("lastDir") except: # if there is not a last used directory in the settings, continue pass from Utils import saveFileDialog, writeFile selectedFile, usedDirectory = saveFileDialog(parent=self.panel, startingDir=lastDir, title="Export Issues", extension="json") if selectedFile is not None: # write to the file writeFile(selectedFile.getAbsolutePath(), self.tableIssue.exportIssues()) if usedDirectory is not None: # overwrite the last used directory self.callbacks.saveExtensionSetting("lastDir", usedDirectory) def importAction(self, event): """Import a file to the table.""" lastDir = "" try: # load the last used directory # this will probably change as we will use a base64 encoded json as the complete config? lastDir = self.callbacks.loadExtensionSetting("lastDir") except: # if there is not a last used directory in the settings, continue pass from Utils import openFileDialog selectedFile, usedDirectory = openFileDialog(parent=self.panel, startingDir=lastDir, title="Import Issues", extension="json") # save the last directory self.callbacks.saveExtensionSetting("lastDir", usedDirectory) fi = open(selectedFile.getAbsolutePath(), "r") # read the file and create a list of Issues import json # newIssues = json.load(fi, object_hook=dictToIssue) # problem here is object_hook runs for every single object so newIssues # will have internal objects, even if we tag them from RequestResponse import RequestResponse, HttpService from base64 import b64decode issuesArray = json.load(fi) # now issuesArray is an array of dicts. # manual JSON deserialization - move this to a method/function? # also think about what happens if dictionaries are missing items newIssues = list() for eachissue in issuesArray: # now we have each issue # what if dictionaries are missing items? ht = HttpService( host=eachissue["reqResp"]["httpService"]["host"], port=eachissue["reqResp"]["httpService"]["port"], protocol=eachissue["reqResp"]["httpService"]["protocol"]) rr = RequestResponse( request=b64decode(eachissue["reqResp"]["request"]), response=b64decode(eachissue["reqResp"]["response"]), comment=eachissue["reqResp"]["comment"], highlight=eachissue["reqResp"]["highlight"], httpService=ht) iss = Issue(name=eachissue["name"], severity=eachissue["severity"], host=eachissue["host"], path=eachissue["path"], description=eachissue["description"], remediation=eachissue["remediation"], reqResp=rr) # iss = Issue() # rr = RequestResponse() # ht = HttpService() newIssues.append(iss) # clear the table self.tableIssue.clear() # add the issues to the table # for iss in newIssues: # self.tableIssue.addRow(iss) self.tableIssue.populate(newIssues) def newIssueFromBurp(self, invocation): """Create a New Issue from the context menu.""" from Utils import getPath, bytesToString, burpToolName reqResp = invocation.getSelectedMessages()[0] host = str(reqResp.getHttpService()) path = getPath(self.callbacks, reqResp) convertedReqResp = RequestResponse() convertedReqResp.fromIHttpRequestResponse(reqResp) tmpIssue = Issue(host=host, path=path, reqResp=convertedReqResp) # change the title to "New Issue from [TOOL]"? frameTitle = "New Issue from %s" % (burpToolName( invocation.getToolFlag())) frm = NewIssueDialog(callbacks=self.callbacks, issue=tmpIssue, title=frameTitle # , modality="application" ) frm.display(self) # FOCUS! frm.requestFocus() # print self.callbacks.getHelpers().bytesToString(reqResp[0].getRequest()) # mostly converted generated code def __init__(self, callbacks, table=None): self.callbacks = callbacks self.jScrollPane1 = JScrollPane() self.jPanel1 = JPanel() self.labelName = JLabel("Name") self.textName = JTextField() self.labelSeverity = JLabel("Severity") self.textSeverity = JTextField() self.labelHost = JLabel("Host") self.labelPath = JLabel("Path") self.textHost = JTextField() self.textPath = JTextField() self.tabIssue = JTabbedPane() self.textAreaDescription = JTextArea() self.textAreaRemediation = JTextArea() # JScrollPanes to hold the two jTextAreas # put the textareas in JScrollPanes self.jsPaneDescription = JScrollPane(self.textAreaDescription) self.jsPaneRemediation = JScrollPane(self.textAreaRemediation) self.panelRequest = self.callbacks.createMessageEditor(None, False) self.panelResponse = self.callbacks.createMessageEditor(None, False) self.loadPanel(self.defaultIssue) # buttons self.buttonNewIssue = JButton("New Issue", actionPerformed=self.newIssueAction) self.buttonDeleteIssue = JButton( "Delete Issue", actionPerformed=self.deleteIssueAction) self.buttonImport = JButton("Import", actionPerformed=self.importAction) self.buttonExport = JButton("Export", actionPerformed=self.exportAction) if table is not None: self.tableIssue = table else: from IssueTable import IssueTable self.tableIssue = IssueTable() # wrap the table in a scrollpane self.jScrollPane1.setViewportView(self.tableIssue) # top panel containing the table from java.awt import Color self.jPanel1.setBorder(BorderFactory.createLineBorder(Color(0, 0, 0))) # create the labels and textfields self.textName.editable = False self.textName.setBackground(Color.LIGHT_GRAY) self.textSeverity.editable = False self.textSeverity.setBackground(Color.LIGHT_GRAY) self.textHost.editable = False self.textHost.setBackground(Color.LIGHT_GRAY) self.textPath.editable = False self.textPath.setBackground(Color.LIGHT_GRAY) # description textarea self.textAreaDescription.editable = False self.textAreaDescription.setLineWrap(True) self.textAreaDescription.setWrapStyleWord(True) self.tabIssue.addTab("Description", self.jsPaneDescription) # remediation textarea self.textAreaRemediation.editable = False self.textAreaRemediation.setLineWrap(True) self.textAreaRemediation.setWrapStyleWord(True) self.tabIssue.addTab("Remediation", self.jsPaneRemediation) # request tab self.panelRequest.setMessage("", True) self.tabIssue.addTab("Request", self.panelRequest.getComponent()) # response tab self.panelResponse.setMessage("", False) self.tabIssue.addTab("Response", self.panelResponse.getComponent()) # from java.lang import Short # jpanel1 is the bottom panel jPanel1Layout = GroupLayout(self.jPanel1) self.jPanel1.setLayout(jPanel1Layout) jPanel1Layout.setHorizontalGroup( # GroupLayout.Alignment.CENTER centers the group, in this case it # centers the buttons jPanel1Layout.createParallelGroup( GroupLayout.Alignment.CENTER ).addGroup(jPanel1Layout.createSequentialGroup().addContainerGap( ).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.LEADING). addGroup(jPanel1Layout.createSequentialGroup().addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.TRAILING).addComponent( self.labelHost).addComponent(self.labelName) ).addPreferredGap( LayoutStyle.ComponentPlacement.UNRELATED).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.LEADING).addGroup( jPanel1Layout.createSequentialGroup( ).addComponent(self.textName).addPreferredGap( LayoutStyle.ComponentPlacement.UNRELATED). addComponent( self.labelSeverity).addPreferredGap( LayoutStyle.ComponentPlacement. RELATED).addComponent( self.textSeverity, GroupLayout.PREFERRED_SIZE, 186, GroupLayout.PREFERRED_SIZE)). addGroup( jPanel1Layout.createSequentialGroup().addComponent( self.textHost, GroupLayout.PREFERRED_SIZE, 330, GroupLayout.PREFERRED_SIZE).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED ).addComponent(self.labelPath).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED). addComponent(self.textPath)))).addComponent( self.tabIssue)).addContainerGap() ).addGroup( jPanel1Layout.createSequentialGroup().addComponent( self.buttonNewIssue).addComponent( self.buttonDeleteIssue).addComponent( self.buttonImport).addComponent( self.buttonExport))) # link size of buttons from javax.swing import SwingConstants jPanel1Layout.linkSize(SwingConstants.HORIZONTAL, [ self.buttonDeleteIssue, self.buttonExport, self.buttonImport, self.buttonNewIssue ]) jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup( ).addGroup( jPanel1Layout.createSequentialGroup().addContainerGap().addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.labelName).addComponent( self.textName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent( self.labelSeverity).addComponent( self.textSeverity, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) ).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.textHost, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent( self.labelPath).addComponent( self.textPath, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent( self.labelHost)).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED) .addComponent(self.tabIssue).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED).addGroup( jPanel1Layout.createParallelGroup().addComponent( self.buttonNewIssue).addComponent( self.buttonDeleteIssue).addComponent( self.buttonImport).addComponent( self.buttonExport)).addContainerGap())) # create the main panel self.panel = JSplitPane(JSplitPane.VERTICAL_SPLIT) # set the top component self.panel.leftComponent = self.jScrollPane1 self.panel.rightComponent = self.jPanel1 self.panel.setDividerLocation(150)
class ConsolePanel(Panel): def __init__(self): self.console = None self.outText = None self.inText = None self.outTextScroller = None self.nestedInputPanel = None self.directoryText = None Panel.__init__(self, "insets 0 0 0 0") def sendCommand(self, command): print str(self) oldText = self.inText.getText() self.inText.setText(command) self.inText.getActionListeners()[0].actionPerformed(None) self.inText.setText(oldText) def setDirectoryText(self, dirText): self.directoryText.setText(dirText) self.nestedInputPanel.revalidate() def write_out(self, text): if not self.outText: return self.outText.setText(self.outText.getText() + text) def initUI(self): font = Font("Courier New", Font.BOLD, 14) #create the output text panel self.outText = JTextArea() self.outText.setEditable(False) self.outText.setFont(font) self.outText.setWrapStyleWord(True) self.outText.setLineWrap(True) #self.outText.setLineWrap(True) #self.outText.setWrapStyleWord(True) class NoGhostScroller(JScrollPane): def paintComponent(self, g): g.setColor(self.getBackground()) g.fillRect(0, 0, self.getWidth(), self.getHeight()) #super(NoGhostScroller, self).paintComponent(g) self.outTextScroller = JScrollPane(self.outText) self.outTextScroller.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) self.outTextScroller.getVerticalScrollBar().setForeground( Color(255, 0, 0)) #self.outText.setOpaque(False) self.outText.setBackground(Color(0, 20, 0)) self.outText.setForeground(Color.WHITE) #self.outTextScroller.setOpaque(False) self.outTextScroller.setBackground(Color(0, 20, 0)) #self.outText.repaint() #self.layered = JLayeredPane() #self.layered.setLayer(self.outTextScroller, 0) #create the input text box self.inText = JTextField() self.inText.setFocusTraversalKeysEnabled(False) self.inText.setFont(font) self.inText.setBackground(Color(0, 20, 0)) self.inText.setForeground(Color.WHITE) self.inText.getCaret().setVisible(True) self.inText.getCaret().setBlinkRate(500) self.inText.setCaretColor(Color(200, 255, 200)) class InFocusAdapter(FocusAdapter): def focusLost(adap, e): self.inText.setVisible(True) self.inText.addFocusListener(InFocusAdapter()) self.nestedInputPanel = Panel("Insets 0 0 0 0") #create the directory text box self.directoryText = JTextField() self.directoryText.setEditable(False) self.directoryText.setFont(font) self.directoryText.setBackground(Color(0, 20, 0)) self.directoryText.setForeground(Color.WHITE) #set up the console sys.stdout = FakeOut(self.outText) self.console = BashED_Console(stdout=sys.stdout) self.directoryText.setText(self.console.get_prompt()) self.revalidate() dirTex = self.directoryText #create the listener that fires when the 'return' key is pressed class InputTextActionListener(ActionListener): def __init__(self, parent, inp, out, console): self.parent = parent self.inp = inp self.out = out self.console = console def actionPerformed(self, e): #print self.getCommandText() # print(self.console.get_prompt()) # self.console.onecmd(self.inp.getText()) # self.parent.write_out("\n" + self.inp.getText()) # dirTex.setText(self.console.get_prompt()) # self.inp.setText("") self.parent.write_out(self.console.get_prompt() + self.inp.getText() + '\n') if 'clear' in self.inp.getText().split(' ')[0]: self.out.setText("") #clear the screen else: self.console.onecmd(self.inp.getText()) dirTex.setText(self.console.get_prompt()) self.inp.setText("") #create the listener that fires whenever a user hits a key class InputKeyActionListener(KeyAdapter): def __init__(self, parent, inp, out, console): self.parent = parent self.inp = inp self.out = out self.console = console def keyReleased(self, k): inp = self.inp.getText() if k.getKeyCode() == 9: #tab character autos = self.console.tabcomplete(self.inp.getText()) if len(autos) == 1: self.inp.setText(autos[0]) else: i = 0 for option in autos: self.parent.write_out(option) if i % 3 == 0: print('\n') else: print('\t') hist = None if k.getKeyCode() == 38: hist = self.console.next_hist() if k.getKeyCode() == 40: hist = self.console.last_hist() if hist: self.inp.setText(hist.rstrip('\n')) #prevent from firing self.inText.addActionListener( InputTextActionListener(self, self.inText, self.outText, self.console)) self.inText.addKeyListener( InputKeyActionListener(self, self.inText, self.outText, self.console)) def addUI(self): self.add(self.outTextScroller, "cell 0 0, push, grow") self.add(self.nestedInputPanel, "cell 0 1, pushx, growx") self.nestedInputPanel.add(self.directoryText, "cell 0 0") self.nestedInputPanel.add(self.inText, "cell 1 0, spanx, pushx, growx")
class MainPanel(): """Represents the converted frame from NetBeans.""" # mostly converted generated code def __init__(self, table=None): self.jScrollPane1 = JScrollPane() self.jTable1 = JTable() self.jPanel1 = JPanel() self.labelName = JLabel() self.textName = JTextField() self.labelSeverity = JLabel() self.textSeverity = JTextField() self.labelHost = JLabel() self.labelPath = JLabel() self.textHost = JTextField() self.textPath = JTextField() self.tabIssue = JTabbedPane() self.panelDescription = JPanel() self.panelRequest = JPanel() self.panelResponse = JPanel() self.panelRemediation = JPanel() # setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE) self.jTable1 = table # wrap the table in a scrollpane self.jScrollPane1.setViewportView(self.jTable1) # top panel containing the table from java.awt import Color self.jPanel1.setBorder(BorderFactory.createLineBorder(Color(0, 0, 0))) # create the labels and textfields self.labelName.text = "Issue Type/Name" self.textName.text = "Issue Name/Type" self.textName.editable = False self.textName.setBackground(Color.LIGHT_GRAY) self.labelSeverity.text = "Severity" self.textSeverity.text = "" self.textSeverity.editable = False self.textSeverity.setBackground(Color.LIGHT_GRAY) self.labelHost.text = "Host" self.textHost.text = "Issue Host" self.textHost.editable = False self.textHost.setBackground(Color.LIGHT_GRAY) self.labelPath.text = "Path" self.textPath.text = "Issue Path" self.textPath.editable = False self.textPath.setBackground(Color.LIGHT_GRAY) from java.lang import Short # description panel panelDescriptionLayout = GroupLayout(self.panelDescription) self.panelDescription.setLayout(panelDescriptionLayout) panelDescriptionLayout.setHorizontalGroup( panelDescriptionLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 948, Short.MAX_VALUE)) panelDescriptionLayout.setVerticalGroup( panelDescriptionLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 287, Short.MAX_VALUE)) self.tabIssue.addTab("Description", self.panelDescription) # request tab panelRequestLayout = GroupLayout(self.panelRequest) self.panelRequest.setLayout(panelRequestLayout) panelRequestLayout.setHorizontalGroup( panelRequestLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 948, Short.MAX_VALUE)) panelRequestLayout.setVerticalGroup( panelRequestLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 287, Short.MAX_VALUE)) self.tabIssue.addTab("Request", self.panelRequest) # response tab panelResponseLayout = GroupLayout(self.panelResponse) self.panelResponse.setLayout(panelResponseLayout) panelResponseLayout.setHorizontalGroup( panelResponseLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 948, Short.MAX_VALUE)) panelResponseLayout.setVerticalGroup( panelResponseLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 287, Short.MAX_VALUE)) self.tabIssue.addTab("Response", self.panelResponse) # remediation tab panelRemediationLayout = GroupLayout(self.panelRemediation) self.panelRemediation.setLayout(panelRemediationLayout) panelRemediationLayout.setHorizontalGroup( panelRemediationLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 948, Short.MAX_VALUE)) panelRemediationLayout.setVerticalGroup( panelRemediationLayout.createParallelGroup( GroupLayout.Alignment.LEADING).addGap(0, 287, Short.MAX_VALUE)) self.tabIssue.addTab("Remediation", self.panelRemediation) # jpanel1? jPanel1Layout = GroupLayout(self.jPanel1) self.jPanel1.setLayout(jPanel1Layout) jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING). addGroup(jPanel1Layout.createSequentialGroup().addContainerGap( ).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.LEADING). addGroup(jPanel1Layout.createSequentialGroup().addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.TRAILING).addComponent( self.labelHost).addComponent( self.labelSeverity).addComponent( self.labelName) ).addPreferredGap( LayoutStyle.ComponentPlacement.UNRELATED).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.LEADING). addComponent(self.textName).addGroup( jPanel1Layout.createSequentialGroup().addComponent( self.textSeverity, GroupLayout.PREFERRED_SIZE, 98, GroupLayout.PREFERRED_SIZE).addGap( 0, 0, Short.MAX_VALUE)). addGroup( jPanel1Layout.createSequentialGroup().addComponent( self.textHost, GroupLayout.PREFERRED_SIZE, 330, GroupLayout.PREFERRED_SIZE).addGap(18, 18, 18). addComponent(self.labelPath).addPreferredGap( LayoutStyle.ComponentPlacement.RELATED ).addComponent(self.textPath)))).addComponent( self.tabIssue)).addContainerGap())) jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(GroupLayout.Alignment.LEADING). addGroup(jPanel1Layout.createSequentialGroup().addContainerGap( ).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.labelName).addComponent( self.textName, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) ).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.labelSeverity).addComponent( self.textSeverity, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) ).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addGroup( jPanel1Layout.createParallelGroup( GroupLayout.Alignment.BASELINE).addComponent( self.labelHost).addComponent( self.labelPath).addComponent( self.textHost, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addComponent( self.textPath, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)). addPreferredGap( LayoutStyle.ComponentPlacement.RELATED).addComponent( self.tabIssue).addContainerGap())) # create the main panel self.panel = JPanel() layout = GroupLayout(self.panel) self.panel.setLayout(layout) layout.setAutoCreateGaps(True) layout.setHorizontalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup( layout.createSequentialGroup().addContainerGap().addGroup( layout.createParallelGroup( GroupLayout.Alignment.LEADING).addComponent( self.jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent( self.jScrollPane1)).addContainerGap())) layout.setVerticalGroup( layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup( layout.createSequentialGroup().addContainerGap().addComponent( self.jScrollPane1, GroupLayout.PREFERRED_SIZE, 119, GroupLayout.PREFERRED_SIZE).addGap( 18, 18, 18).addComponent(self.jPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addContainerGap()))
class ChatApp(JFrame): ## Constructor function, initiate the base classes and call the GUI def __init__(self): '''Calls the base class and main UI ''' # Call to the super class, initiates associated base classes super(ChatApp, self).__init__() # Call the Initial UI self.initUI() ## Build the GUI for login, uses GroupLayout Manager for component positioning def initUI(self): '''Initial UI and Widget creation takes place here! ''' self.setContentPane = JPanel() #self.setDefaultLookAndFeelDecorated(True) # Borders foreground_colour = Color(30,57,68) background_colour = Color(247,246,242) window_background = Color(145,190,210) self.border = BorderFactory.createLoweredBevelBorder() self.border2 = BorderFactory.createLineBorder(foreground_colour, 1, True) # Fonts self.entry_font= Font("Ubuntu Light", Font.BOLD, 20) self.label_font= Font("Ubuntu Light", Font.BOLD, 17) self.btn_font=Font("Ubuntu Light", Font.BOLD, 15) # Layout start layout=GroupLayout(self.getContentPane()) self.getContentPane().setLayout(layout) layout.setAutoCreateGaps(True) layout.setAutoCreateContainerGaps(True) self.setPreferredSize(Dimension(300, 150)) # Create the labels user_label= JLabel(" Username : "******" Server : ", JLabel.LEFT, font=self.label_font) # Colours user_label.setForeground(foreground_colour) server_label.setForeground(foreground_colour) # Create the text entries self.username=JTextField(actionPerformed=self.continueEvent, border=self.border2, font = self.entry_font) self.server=JTextField(actionPerformed=self.continueEvent, border=self.border2, font = self.entry_font) # Colours self.username.setBackground(background_colour) self.server.setBackground(background_colour) self.username.setForeground(foreground_colour) self.server.setForeground(foreground_colour) # Allow editable self.username.setEditable(True) self.server.setEditable(True) # Create the buttons quit_btn=JButton(" Quit! ", actionPerformed=self.closeEvent, border=self.border2, font=self.btn_font) go_btn=JButton(" Go! ", actionPerformed=self.continueEvent, border=self.border2, font=self.btn_font) # Colours quit_btn.setBackground(background_colour) go_btn.setBackground(background_colour) quit_btn.setForeground(foreground_colour) go_btn.setForeground(foreground_colour) # Setting up the horizontal groups parameters layout.setHorizontalGroup(layout.createSequentialGroup() # Left side .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addComponent(user_label) .addComponent(server_label)) # Right side .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(self.username) .addComponent(self.server) .addGroup(layout.createSequentialGroup() .addComponent(quit_btn) .addComponent(go_btn))) ) # Setting up Vertical Groups layout.setVerticalGroup(layout.createSequentialGroup() # Top group .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(user_label) .addComponent(self.username)) # Middle group .addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER) .addComponent(server_label) .addComponent(self.server)) # Bottom group .addGroup(layout.createParallelGroup() .addComponent(quit_btn) .addComponent(go_btn)) ) # Finalise the GUI layout.linkSize(SwingConstants.HORIZONTAL, [quit_btn,go_btn]) self.getContentPane().setBackground(window_background) self.pack() self.setTitle('Chat Login') self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) self.setLocationRelativeTo(None) self.setVisible(True) ## Event driven funtion to respond to quit button click def closeEvent(self,event): '''Function to close the login window ''' print("Goodbye!") exit() ## Event driven function to respond to send button click, grabs text and sends it down the wire def continueEvent(self,event): '''Function that retreives the login details for sending to the server ''' # Grab the text that has been entered user = self.username.getText() Host = self.server.getText() # Default port Port=60001 connected=False while not connected: # Try make a connection except when there isn't one available, then quit program' try: tn=telnetlib.Telnet(Host, Port) connected=True continue except: JOptionPane.showMessageDialog(self,'Connection Error, No Server Available!') self.username.setText('') self.server.setText('') self.username.requestFocusInWindow() return # Listen for a response response = tn.read_until('<<<') print(response) # Acknowledge with the username tn.write(user+'\r\n') # Receive validation of name, present dialog if not valid valid_name = tn.read_until('<') valid_name.strip() v_name, delim = valid_name.split('<') if v_name.strip() != 'OK': JOptionPane.showMessageDialog(self,'Bad Username, please choose another') self.username.setText('') self.username.requestFocusInWindow() return # Set the login GUI to hidden self.setVisible(False) ## <<<<<< I have no idea why this doesn't work but I suspect it's something to do with either inheritance or having 2 class instances # Call the main program, pass the connection as a parameter ChatClient(user,response , tn)
class BurpExtender(IBurpExtender, IScannerListener, IContextMenuFactory, ActionListener, ITab, IHttpService, IScanIssue, IBurpExtenderCallbacks): def __init__(self): self.msgrel = False self.project = False self.projectId = None print("[+] Carregando GAT CORE Extension...") def registerExtenderCallbacks(self, callbacks): """ registrar classes """ self._callbacks = callbacks self._helpers = self._callbacks.getHelpers() self._callbacks.setExtensionName("GAT CORE Integration") self.gui_elements = self.build_gui() callbacks.customizeUiComponent(self.gui_elements) callbacks.addSuiteTab(self) self._callbacks.registerContextMenuFactory(self) self._callbacks.registerScannerListener(self) save_setting = self._callbacks.saveExtensionSetting save_setting('project_id', None) self.reload_config() print("[+] GAT CORE Extension carregado!") def newScanIssue(self, issue): print("[+] Issue encontrada (%s)" % issue.getIssueName()) return def actionTarget(self, event): print("*" * 80) self.fileId = [] requestResponses = self.invocation.getSelectedMessages() chosts, ihosts = self.countHostIssues(requestResponses) if self.project <= 1: panelinput = JPanel() panelinput.add(JLabel("Projeto ID: ")) projectq = JTextField(20) panelinput.add(projectq) result = JOptionPane.showOptionDialog( None, panelinput, "Qual projeto enviar Issues?", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, None, ["OK", "Sem projeto"], "OK") if result == -1: print("[-] Cancelado envio!") return if result == JOptionPane.OK_OPTION: self.project_id.setText(projectq.getText()) self.projectId = str(projectq.getText()) if not re.match('([0-9a-f]{24})', self.projectId): self.projectId = None mess = "Projeto Id formato inválido".decode("utf8") JOptionPane.showMessageDialog(None, mess, "Error", JOptionPane.ERROR_MESSAGE) return mess = "Sessão atual".decode("utf8") ever = JOptionPane.showOptionDialog( None, "Solicitar Id de Projeto novamente?", mess, JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, None, ["Nunca", "Sim"], "Sim") # let user select parameters for new session if ever == JOptionPane.OK_OPTION: self.project = 2 else: self.project = 1 for reqResp in requestResponses: url = reqResp.getHttpService() requestIssues = self._callbacks.getScanIssues(str(url)) listIssues = [] if requestIssues: if len(requestIssues) > 0: for i in requestIssues: scanissue = i if scanissue.getIssueName() not in ['']: sep = "<br><hr><br>" issue = {} issue['Tool_Type'] = "BURP" IssueType = scanissue.getIssueType() IssueName = scanissue.getIssueName() IssueCrit = scanissue.getSeverity() IssueConf = scanissue.getConfidence() protocol = scanissue.getHttpService().getProtocol() host = scanissue.getHttpService().getHost() IssuePath = i.getUrl().getPath() IssueDesc = scanissue.getIssueDetail() IssueDescBk = scanissue.getIssueBackground() IssueRecom = scanissue.getRemediationDetail() IssueRecomBk = scanissue.getRemediationBackground() if IssueType: issue['IssueType'] = scanissue.getIssueType() else: issue['IssueType'] = 0000 if IssueName: issue['DetailsFinding_Title'] = IssueName issue['Recomenation_Title'] = IssueName else: issue['DetailsFinding_Title'] = "No Issue name" issue['Recomenation_Title'] = "No Issue name" if "False positive" in IssueCrit: sTag = "False positive" IssueCrit = "" elif "Information" in IssueCrit: IssueCrit = "Informative" sTag = "" else: sTag = "" if IssueCrit: issue['Severity'] = IssueCrit else: issue['Severity'] = "Informative" issue['Web_Application_URI'] = "{}://{}".format( protocol, host) if IssuePath: issue['Web_Application_Path'] = IssuePath else: issue['Web_Application_Path'] = "/" if IssueConf: issue['fTag'] = IssueConf else: issue['fTag'] = " " issue['sTag'] = sTag if IssueDescBk is not None: issue['Description'] = IssueDescBk.replace( "\n", "") else: issue['Description'] = "" if IssueDesc is not None: issue['Description'] += "{}{}".format( sep, IssueDesc.replace("\n", "")) if IssueRecomBk is not None: issue['Recommendation'] = IssueRecomBk.replace( "\n", "") else: issue['Recommendation'] = IssueName if IssueRecom is not None: issue['Recommendation'] += "{}{}".format( sep, IssueRecom.replace("\n", "")) listIssues.append(issue) self.generateReportGat(listIssues) # iniciar threads print("[+] Thread(s) Iniciada(s)...") if self.project: print("[+] Enviando Issues para o Project Id: {}".format( self.projectId)) print("[+] Enviando {} host(s), total de {} Issue(s),\n".format( chosts, ihosts)) self.launchThread(self.sendIssues) def actionScanner(self): pass def createMenuItems(self, invocation): self.invocation = invocation context = invocation.getInvocationContext() if context in [invocation.CONTEXT_TARGET_SITE_MAP_TREE]: sendToGAT = JMenuItem("Enviar Issues para GAT CORE") # sendToGAT.setForeground(Color.ORANGE) FONT = sendToGAT.getFont() sendToGAT.setFont( Font(FONT.getFontName(), Font.BOLD, FONT.getSize())) sendToGAT.addActionListener(self.actionTarget) menuItems = ArrayList() menuItems.add(sendToGAT) return menuItems else: # TODO: add support for other tools pass def build_gui(self): """Construct GUI elements.""" Mpanel = JPanel() # Mpanel.setLayout(GridLayout(0, 3)) Mpanel.setLayout(BoxLayout(Mpanel, BoxLayout.X_AXIS)) panel = JPanel() panel.setLayout(None) Mpanel.add(Box.createVerticalGlue()) Mpanel.add(panel) Mpanel.add(Box.createVerticalGlue()) img = os.path.abspath("gat_logo_sticky.png") logo = JLabel(ImageIcon(img)) logo.setBounds(150, 40, 165, 49) save_btn = JButton('Salvar', actionPerformed=self.save_config) save_btn.setBounds(100, 240, 75, 30) save_btn.setPreferredSize(Dimension(75, 30)) limpar_btn = JButton('Limpar ID Projeto', actionPerformed=self.clsProjectId) limpar_btn.setBounds(250, 240, 150, 30) limpar_btn.setPreferredSize(Dimension(150, 30)) label_h = JLabel('API Url:') label_h.setHorizontalAlignment(SwingConstants.RIGHT) label_h.setBounds(0, 120, 95, 30) label_h.setPreferredSize(Dimension(100, 30)) self.host_api = JTextField(50) self.host_api.setBounds(100, 120, 300, 30) self.host_api.setPreferredSize(Dimension(250, 30)) label_a = JLabel('API Token:') label_a.setHorizontalAlignment(SwingConstants.RIGHT) label_a.setBounds(0, 160, 95, 30) label_a.setPreferredSize(Dimension(100, 30)) self.api_token = JTextField(50) self.api_token.setBounds(100, 160, 300, 30) self.api_token.setPreferredSize(Dimension(250, 30)) label_p = JLabel('Project ID:') label_p.setHorizontalAlignment(SwingConstants.RIGHT) label_p.setBounds(0, 200, 95, 30) label_p.setPreferredSize(Dimension(100, 30)) self.project_id = JTextField(50) self.project_id.setForeground(Color.orange) self.project_id.setBackground(Color.gray) self.project_id.setBounds(100, 200, 300, 30) self.project_id.setPreferredSize(Dimension(250, 30)) self.project_id.editable = False panel.add(logo) panel.add(label_h) panel.add(self.host_api) panel.add(label_a) panel.add(self.api_token) panel.add(label_p) panel.add(self.project_id) panel.add(limpar_btn) panel.add(save_btn) return Mpanel def save_config(self, _): """Save settings.""" url = self.host_api.getText() token = self.api_token.getText() if re.match('https?://', url): url = re.sub('https?://', '', url) if url[-1:] == "/": url = url[:-1] if re.match('^(?i)Bearer ', token): token = re.sub('^(?i)Bearer ', '', token) if not re.match( '([a-f\d]{8})-([a-f\d]{4})-([a-f\d]{4})-([a-f\d]{4})-([a-f\d]{12})', token): JOptionPane.showMessageDialog(None, "Formato de TOKEN invalido!", "Error", JOptionPane.ERROR_MESSAGE) return save_setting = self._callbacks.saveExtensionSetting save_setting('host_api', url) save_setting('api_token', token) self.msgrel = True self.reload_config() return def reload_config(self): """Reload settings.""" load_setting = self._callbacks.loadExtensionSetting host_api_url = load_setting('host_api') or '' host_api_token = load_setting('api_token') or '' # project_id = '' self.host_api.setText(host_api_url) self.api_token.setText(host_api_token) # self.project_id.setText(project_id) if self.msgrel: if self.host_api and self.api_token: JOptionPane.showMessageDialog( None, "API token, API url dados salvo\n ", "Informativo", JOptionPane.INFORMATION_MESSAGE) print("[+] API token, API url dados salvo") print("[+] Recarregue: GAT CORE Extension") return try: vapi = self.checkAuth() if vapi.status_code == 200: data = json.loads(vapi.text) print("[ ] Conectado: {}, {}".format(data['name'], data['email'])) # if self.msgrel: JOptionPane.showMessageDialog( None, "Conectado: {}, {}".format(data['name'], data['email']), "Informativo", JOptionPane.INFORMATION_MESSAGE) else: raise Exception("Status_Code({})".format(vapi.status_code)) except Exception as e: print("[-] GAT CORE Settings, erro ao conectar na API.") print("[-] Exception: {}".format(e)) return def getTabCaption(self): """Return the text to be displayed on the tab""" return "GAT CORE Settings" def getUiComponent(self): """Passes the UI to burp""" return self.gui_elements def generateReportGat(self, rows): quote = '"' Id = uuid.uuid4().hex self.fileId.append(Id) path = os.getcwd() folder = "\\exports\\" file_name = "{}{}{}.csv".format(path, folder, Id) with open(file_name, mode='w') as csv_file: fields = [ 'Tool_Type', 'IssueType', 'DetailsFinding_Title', 'Severity', 'Web_Application_URI', 'Web_Application_Path', 'fTag', 'sTag', 'Description', 'Recomenation_Title', 'Recommendation' ] writer = csv.DictWriter(csv_file, fieldnames=fields, quotechar=quote, quoting=csv.QUOTE_NONNUMERIC, lineterminator='\n') writer.writeheader() writer.writerows(rows) csv_file.close() return Id def sendIssues(self): for Id in self.fileId: print("[+] Processando ID: {}".format(Id)) path = os.getcwd() folder = "\\exports\\" file_name = "{}{}{}.csv".format(path, folder, Id) self.launchThread(self.requestAPI, arguments=file_name) def launchThread(self, targetFunction, arguments=None, retur=False): """Launches a thread against a specified target function""" if arguments: t = Thread(name='args', target=targetFunction, args=(arguments, )) else: t = Thread(name='no-args', target=targetFunction) t.setDaemon(True) t.start() if retur: r = t.join() return r def countHostIssues(self, requestResponses): count = 0 icount = 0 for reqResp in requestResponses: url = reqResp.getHttpService() requestIssues = self._callbacks.getScanIssues(str(url)) if requestIssues: if len(requestIssues) > 0: count += 1 for issue in requestIssues: icount += 1 return count, icount def requestAPI(self, filename): load_setting = self._callbacks.loadExtensionSetting api_uri = load_setting('host_api') or '' api_token = load_setting('api_token') or '' projectid = self.projectId name_csv = os.path.basename(filename) if projectid: resource = "/app/vulnerability/upload/api/Burp/{}".format( projectid) else: resource = "/app/vulnerability/upload/api/Burp" # print(resource) protocol = "http" if api_uri == "localhost" else "https" gatPoint = "{}://{}{}".format(protocol, api_uri, resource) try: dataList = [] api_url = URL(gatPoint) boundary = name_csv.replace(".csv", "") headers = ArrayList() headers.add('POST %s HTTP/1.1' % resource) headers.add('Host: %s' % api_uri) headers.add('Authorization: Bearer %s' % api_token) headers.add('Accept: application/json') headers.add( 'Content-type: multipart/form-data; boundary={}'.format( boundary)) dataList.append('--' + boundary) dataList.append( 'Content-Disposition: form-data; name=file; filename={}'. format(name_csv)) dataList.append('Content-Type: text/csv') dataList.append('') with open(filename) as f: dataList.append(f.read()) dataList.append('--' + boundary + '--') dataList.append('') body = '\r\n'.join(dataList) newBody = self._helpers.bytesToString(body) newRequest = self._helpers.buildHttpMessage(headers, newBody) requestInfo = self._helpers.analyzeRequest(newRequest) headers = requestInfo.getHeaders() response = self._callbacks.makeHttpRequest(api_url.getHost(), 443, True, newRequest) response_info = self._helpers.analyzeResponse(response) response_value = self._helpers.bytesToString( response)[response_info.getBodyOffset():].encode("utf-8") except Exception as e: print("[-] Falha arquivo/envio de Issues ID:{} - Error: {}".format( name_csv, e)) if response_info.getStatusCode() == 200: self.removeCSV(filename) print("[+] Success ID: {}".format(name_csv.replace(".csv", ""))) else: print("[-] Falhou o envio do ID: {} - code :{}".format( name_csv.replace(".csv", ""), response_info.getStatusCode())) if response_value: print("Error: {}".format(response_value)) JOptionPane.showMessageDialog(None, "Falhou o envio das Issues", "Error", JOptionPane.ERROR_MESSAGE) self.removeCSV(filename) def checkAuth(self): """ Validar api + token GAT """ load_setting = self._callbacks.loadExtensionSetting api_uri = load_setting('host_api') or '' api_token = load_setting('api_token') or '' resource = "/api/v1/me" protocol = "http" if api_uri == "localhost" else "https" gatPoint = "{}://{}{}".format(protocol, api_uri, resource) api_url = URL(gatPoint) headers = ArrayList() headers.add('GET %s HTTP/1.1' % resource) headers.add('Host: %s' % api_uri) headers.add('Authorization: Bearer %s' % api_token) headers.add('Content-Type: application/json') newRequest = self._helpers.buildHttpMessage(headers, None) requestInfo = self._helpers.analyzeRequest(newRequest) headers = requestInfo.getHeaders() response = self._callbacks.makeHttpRequest(api_url.getHost(), 443, True, newRequest) response_info = self._helpers.analyzeResponse(response) response_value = self._helpers.bytesToString( response)[response_info.getBodyOffset():].encode("utf-8") response = {} response['status_code'] = response_info.getStatusCode() response['text'] = response_value r = DotDict(response) return r def removeCSV(self, path): """ param <path> could either be relative or absolute. """ if os.path.isfile(path) or os.path.islink(path): os.remove(path) else: raise ValueError("file {} is not a file".format(path)) def clsProjectId(self, _): self.project_id.setText(None) self.project = False self.projectId = None JOptionPane.showMessageDialog( None, "Redefinido envio de Issues sem Projeto.", "Informativo", JOptionPane.INFORMATION_MESSAGE)
class ConsolePanel(Panel): def __init__(self): self.console = None self.outText = None self.inText = None self.outTextScroller = None self.nestedInputPanel = None self.directoryText = None Panel.__init__(self, "insets 0 0 0 0") def sendCommand(self, command): print str(self) oldText = self.inText.getText() self.inText.setText(command) self.inText.getActionListeners()[0].actionPerformed(None) self.inText.setText(oldText) def setDirectoryText(self, dirText): self.directoryText.setText(dirText) self.nestedInputPanel.revalidate() def write_out(self,text): if not self.outText: return self.outText.setText(self.outText.getText() + text) def initUI(self): font = Font("Courier New", Font.BOLD, 14) #create the output text panel self.outText = JTextArea() self.outText.setEditable(False) self.outText.setFont(font) self.outText.setWrapStyleWord(True) self.outText.setLineWrap(True) #self.outText.setLineWrap(True) #self.outText.setWrapStyleWord(True) class NoGhostScroller(JScrollPane): def paintComponent(self, g): g.setColor(self.getBackground()) g.fillRect(0, 0, self.getWidth(), self.getHeight()) #super(NoGhostScroller, self).paintComponent(g) self.outTextScroller = JScrollPane(self.outText) self.outTextScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) self.outTextScroller.getVerticalScrollBar().setForeground(Color(255, 0, 0)) #self.outText.setOpaque(False) self.outText.setBackground(Color(0, 20, 0)) self.outText.setForeground(Color.WHITE) #self.outTextScroller.setOpaque(False) self.outTextScroller.setBackground(Color(0, 20, 0)) #self.outText.repaint() #self.layered = JLayeredPane() #self.layered.setLayer(self.outTextScroller, 0) #create the input text box self.inText = JTextField() self.inText.setFocusTraversalKeysEnabled(False) self.inText.setFont(font) self.inText.setBackground(Color(0, 20, 0)) self.inText.setForeground(Color.WHITE) self.inText.getCaret().setVisible(True) self.inText.getCaret().setBlinkRate(500) self.inText.setCaretColor(Color(200,255,200)) class InFocusAdapter(FocusAdapter): def focusLost(adap, e): self.inText.setVisible(True) self.inText.addFocusListener(InFocusAdapter()) self.nestedInputPanel = Panel("Insets 0 0 0 0") #create the directory text box self.directoryText = JTextField() self.directoryText.setEditable(False) self.directoryText.setFont(font) self.directoryText.setBackground(Color(0, 20, 0)) self.directoryText.setForeground(Color.WHITE) #set up the console sys.stdout = FakeOut(self.outText) self.console = BashED_Console(stdout=sys.stdout) self.directoryText.setText(self.console.get_prompt()) self.revalidate(); dirTex = self.directoryText; #create the listener that fires when the 'return' key is pressed class InputTextActionListener(ActionListener): def __init__(self,parent,inp,out,console): self.parent = parent self.inp = inp self.out = out self.console = console def actionPerformed(self, e): #print self.getCommandText() # print(self.console.get_prompt()) # self.console.onecmd(self.inp.getText()) # self.parent.write_out("\n" + self.inp.getText()) # dirTex.setText(self.console.get_prompt()) # self.inp.setText("") self.parent.write_out(self.console.get_prompt() + self.inp.getText() + '\n') if 'clear' in self.inp.getText().split(' ')[0]: self.out.setText("") #clear the screen else: self.console.onecmd(self.inp.getText()) dirTex.setText(self.console.get_prompt()) self.inp.setText("") #create the listener that fires whenever a user hits a key class InputKeyActionListener(KeyAdapter): def __init__(self,parent,inp,out,console): self.parent = parent self.inp = inp self.out = out self.console = console def keyReleased(self, k): inp = self.inp.getText() if k.getKeyCode() == 9: #tab character autos = self.console.tabcomplete(self.inp.getText()) if len(autos) == 1: self.inp.setText(autos[0]) else: i = 0 for option in autos: self.parent.write_out(option) if i % 3 == 0: print('\n') else: print('\t') hist = None if k.getKeyCode() == 38: hist = self.console.next_hist() if k.getKeyCode() == 40: hist = self.console.last_hist() if hist: self.inp.setText(hist.rstrip('\n'))#prevent from firing self.inText.addActionListener(InputTextActionListener(self,self.inText,self.outText,self.console)) self.inText.addKeyListener(InputKeyActionListener(self,self.inText,self.outText,self.console)) def addUI(self): self.add(self.outTextScroller, "cell 0 0, push, grow") self.add(self.nestedInputPanel, "cell 0 1, pushx, growx") self.nestedInputPanel.add(self.directoryText, "cell 0 0") self.nestedInputPanel.add(self.inText, "cell 1 0, spanx, pushx, growx")