From 80bc5f86b0c5f30782630d0f0d5e189353aee033 Mon Sep 17 00:00:00 2001 From: gdgd009xcd Date: Wed, 24 Jan 2024 11:07:54 +0900 Subject: [PATCH] 24012401 MARCIANUS240118 - bugfix: fixed bug in related to misuse of Style in StyledDocument --- addOns/automacrobuilder/CHANGELOG.md | 6 +- .../automacrobuilder.gradle.kts | 2 +- .../extension/automacrobuilder/PRequest.java | 3 +- .../extension/automacrobuilder/PResponse.java | 23 ++- .../generated/MacroBuilderUI.java | 10 +- .../generated/ParmGenRegex.java | 19 ++- .../view/StyledDocumentWithChunk.java | 144 ++++++++++++------ .../src/main/resources/burp/Bundle.properties | 3 + 8 files changed, 144 insertions(+), 66 deletions(-) diff --git a/addOns/automacrobuilder/CHANGELOG.md b/addOns/automacrobuilder/CHANGELOG.md index f815c33..31c0614 100644 --- a/addOns/automacrobuilder/CHANGELOG.md +++ b/addOns/automacrobuilder/CHANGELOG.md @@ -2,7 +2,11 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## [v1.1.14] - 2023-12-14 +## [v1.1.15] - 2024-01-24 +### Changed +- bugfix: fixed bug in related to misuse of displaying icons in StyledDocument + +## [v1.1.14] - 2024-01-15 ### Added - improve: Added javahelp [?] button on the right-top corner of the MacroBuilder tab ### Changed diff --git a/addOns/automacrobuilder/automacrobuilder.gradle.kts b/addOns/automacrobuilder/automacrobuilder.gradle.kts index f0fb662..5b2da3b 100644 --- a/addOns/automacrobuilder/automacrobuilder.gradle.kts +++ b/addOns/automacrobuilder/automacrobuilder.gradle.kts @@ -1,6 +1,6 @@ import org.zaproxy.gradle.addon.AddOnStatus -version = "1.1.14" +version = "1.1.15" description = "AutoMacroBuilder for ZAP" tasks.withType { diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PRequest.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PRequest.java index 48c8abd..0910d37 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PRequest.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PRequest.java @@ -45,7 +45,8 @@ public PRequest(String h, int p, boolean ssl, byte[] _binmessage, Encode _pageen } /** - * handover chunks, doctext from chunkdoc to this instance + * create instance + * pass argument chunkdoc, extract doctext from chunkdoc * * @param h * @param p diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PResponse.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PResponse.java index 97c7095..363ad59 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PResponse.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/PResponse.java @@ -32,6 +32,7 @@ public class PResponse extends ParseHTTPHeaders { private ParmGenGSONDecoder jsonparser = null; public static final int MAX_SIZE_RESPONSE_CONTENTS = 25000; + private static final int MAX_SIZE_DISPLAYABLE_TEXTS = 100000; public PResponse(byte[] bin, Encode _pageenc) { super(bin, _pageenc); @@ -40,7 +41,7 @@ public PResponse(byte[] bin, Encode _pageenc) { jsonparser = null; } - // Location headerのパラメータ取得 + // get Location header value public InterfaceCollection getLocationTokens(InterfaceCollection tklist) { String locheader = getHeader("Location"); @@ -179,13 +180,14 @@ public List getResponseChunks() { return getResponseChunks(theaders, tbodies, tcontent_type); } - public List getResponseChunks( + private List getResponseChunks( String theaders, byte[] tbodies, String tcontent_type) { List reschunks = new ArrayList<>(); String mediaType = getContentMimeType(); String displayableImageContents = ""; String application_json_contents = ""; + String text_contents = ""; if (tcontent_type != null && !tcontent_type.isEmpty()) { LOGGER4J.debug("content-type[" + tcontent_type + "]"); List matches = @@ -194,17 +196,24 @@ public List getResponseChunks( displayableImageContents = matches.get(0); } List jsonmatches = - ParmGenUtil.getRegexMatchGroups("application/(json)", tcontent_type); + ParmGenUtil.getRegexMatchGroups("application/(json|javascript)", tcontent_type); + if (jsonmatches.size() > 0) { + application_json_contents = jsonmatches.get(0); + } + List textmatches = + ParmGenUtil.getRegexMatchGroups("application/(\\w)", tcontent_type); if (jsonmatches.size() > 0) { application_json_contents = jsonmatches.get(0); } } boolean displayableTextContents = false; - if (mediaType.equalsIgnoreCase("text/html")) { - displayableTextContents = true; - } else if (!application_json_contents.isEmpty()) { - displayableTextContents = true; + if (tbodies.length < MAX_SIZE_DISPLAYABLE_TEXTS) { + if (mediaType.equalsIgnoreCase("text/html")) { + displayableTextContents = true; + } else if (!application_json_contents.isEmpty()) { + displayableTextContents = true; + } } int partno = 0; diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/MacroBuilderUI.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/MacroBuilderUI.java index e9793f1..53849bd 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/MacroBuilderUI.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/MacroBuilderUI.java @@ -75,7 +75,7 @@ public class MacroBuilderUI extends javax.swing.JPanel implements InterfacePar int EditTarget = -1; Encode EditPageEnc = Encode.ISO_8859_1; - static final int REQUEST_DISPMAXSIZ = 500000;//1MB + static final int REQUEST_DISPMAXSIZ = 500000;//0.5MB static final int RESPONSE_DISPMAXSIZ = 1000000;//1MB JPanel plusBtnPanel = null; @@ -240,6 +240,7 @@ public void clear() { messageRequest.setText(""); messageResponse.setText(""); + MacroComments.setText(""); this.pmtProvider.clear(); this.maxTabIndex = 0; @@ -473,7 +474,7 @@ private void initComponents() { RequestList = new javax.swing.JList<>(); generalHelpBtn = new JButton(QUESTION_BUTTON_ICON); - + messageResponse.setEditable(false); generalHelpBtn.addActionListener(new ActionListener() { @Override @@ -1801,7 +1802,10 @@ private void showActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:ev String orig = messageResponse.getText(); if (pos != -1) { StyledDocument doc = messageResponse.getStyledDocument(); - new ParmGenRegex(this,reg,doc).setVisible(true); + if (doc instanceof StyledDocumentWithChunk) { + StyledDocumentWithChunk newchunkdoc = new StyledDocumentWithChunk((StyledDocumentWithChunk) doc); + new ParmGenRegex(this, reg, newchunkdoc).setVisible(true); + } } } diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/ParmGenRegex.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/ParmGenRegex.java index e6cb30d..cdd9bf8 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/ParmGenRegex.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/generated/ParmGenRegex.java @@ -36,7 +36,7 @@ /** * - * @author tms783 + * @author gdgd009xcd */ @SuppressWarnings("serial") public class ParmGenRegex extends javax.swing.JDialog { @@ -212,12 +212,17 @@ public ParmGenRegex(InterfaceParmGenRegexSaveCancelAction _actionwin, String _re SwingStyle.clearAllCharacterAttributes(doc); OriginalText.setCaretPosition(0); - + + boolean hasBinaryContents = false; isLabelSaveBtn = false; if (doc instanceof StyledDocumentWithChunk) { this.docwithchunk = CastUtils.castToType(doc); + hasBinaryContents = this.docwithchunk.hasBinaryContents(); isLabelSaveBtn = this.docwithchunk.isRequest(); } + if(hasBinaryContents) { + RegexTest.setEnabled(false); + } addHexView(isLabelSaveBtn); @@ -284,7 +289,7 @@ public static String getParsedRegexRaw(String orig, String quant){ for(int i = 0;i < patterns.length; i++){ for(int j = 0 ; j< 2; j++){ String strpattern = patterns[i] + grpclose[j]; - Pattern pattern = ParmGenUtil.Pattern_compile(strpattern);//数値 + Pattern pattern = ParmGenUtil.Pattern_compile(strpattern);// number Matcher matcher = pattern.matcher(orig); if (matcher.find()){ regex = matcher.group(); @@ -310,7 +315,7 @@ public static String getParsedRegexRaw(String orig, String quant){ int hasGroupRegex(String r){ // (?:^|[^\\])(\([^?].*?\)|\(\)) - String greg = "(?:^|[^\\\\])(\\([^?].*?\\)|\\(\\))";//後方参照グループ + String greg = "(?:^|[^\\\\])(\\([^?].*?\\)|\\(\\))";//back-reference group Pattern pattern = ParmGenUtil.Pattern_compile(greg); Matcher matcher = pattern.matcher(r); int gtotal = 0; @@ -873,7 +878,7 @@ private void AddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:eve regprefix = "(?:\\r|\\n|.)"; }else{ - regprefix = "\\s";//ホワイトスペース(改行含む) + regprefix = "\\s";//white space(which contains \t \r \n \f) } String minmatch = ""; @@ -1013,13 +1018,13 @@ private void RegexTextKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event // TODO add your handling code here: switch (evt.getKeyCode()) { - case KeyEvent.VK_Z: //CTRL+Zのとき、UNDO実行 + case KeyEvent.VK_Z: //Undo when Ctrl+Z key is pressed. if (evt.isControlDown() && um.canUndo()) { um.undo(); evt.consume(); } break; - case KeyEvent.VK_Y: //CTRL+Yのとき、REDO実行 + case KeyEvent.VK_Y: //Undo when CTRL+Y key is pressed. if (evt.isControlDown() && um.canRedo()) { um.redo(); } diff --git a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/view/StyledDocumentWithChunk.java b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/view/StyledDocumentWithChunk.java index fe9d7a3..6a42345 100644 --- a/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/view/StyledDocumentWithChunk.java +++ b/addOns/automacrobuilder/src/main/java/org/zaproxy/zap/extension/automacrobuilder/view/StyledDocumentWithChunk.java @@ -14,8 +14,7 @@ import java.awt.Insets; import java.net.URL; import java.nio.charset.Charset; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; @@ -35,11 +34,15 @@ public class StyledDocumentWithChunk extends DefaultStyledDocument { private static final String CHUNK_STYLENAME = "StyledDocumentWithChunk.STYLE"; private static final String CRIMAGE_STYLENAME = "StyledDocumentWithChunk.CRSTYLE_IMAGE"; + private static final ResourceBundle bundle = ResourceBundle.getBundle("burp/Bundle"); + private final String[] styleNames = { CHUNK_STYLENAME, CRIMAGE_STYLENAME }; + Map styleMap = null; + public static int PARTNO_MAXLEN = 4; public static final String RESOURCES = @@ -102,8 +105,7 @@ public StyledDocumentWithChunk(StyledDocumentWithChunk chunkdoc) { try { generateStyledDocFromRequestText(chunkdoc.getText(0, chunkdoc.getLength())); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()) - .log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } } else { LOGGER4J.debug("chunkdoc is RESPONSE"); @@ -116,15 +118,37 @@ public StyledDocumentWithChunk(StyledDocumentWithChunk chunkdoc) { } private void createStyles() { + styleMap = new HashMap<>(); for(String name: styleNames) { - Style style = this.getStyle(name); - if (style == null) { - Style defaultStyle = SwingStyle.getDefaultStyle(this); - this.addStyle(name, defaultStyle); - } + addOrGetStyle(name); + } + } + private void deleteStyles() { + for (Map.Entry ent : this.styleMap.entrySet()) { + this.removeStyle(ent.getKey()); + } + } + + /** + * add Style if it does not exist + * otherwise return existing one. + * + * @param newStyleName + * @return Style + */ + private Style addOrGetStyle(String newStyleName) { + Style style = this.getStyle(newStyleName); + if (style == null) { + Style defaultStyle = SwingStyle.getDefaultStyle(this); + Style s = this.addStyle(newStyleName, defaultStyle); + this.styleMap.put(newStyleName, s); + return s; } + return style; } + + /** * this document for Prequest or not. * @@ -142,6 +166,37 @@ List getResponseChunks() { return responseChunks; } + /** + * return boolean value is there exist binary contents or not + * + * @return true - has binary contents + * + */ + public boolean hasBinaryContents() { + if (isRequest()) { + Optional reqBinChunk = + requestChunks.stream() + .filter( + c -> + (c.getChunkType() + == RequestChunk + .CHUNKTYPE + .CONTENTS + || c.getChunkType() + == RequestChunk + .CHUNKTYPE + .CONTENTSIMG) + ) + .findFirst(); + return reqBinChunk.isPresent(); + } + Optional resBinChunk = + responseChunks.stream() + .filter(c -> (c.getChunkType() == PResponse.ResponseChunk.CHUNKTYPE.CONTENTSIMG + || c.getChunkType() == PResponse.ResponseChunk.CHUNKTYPE.CONTENTSBINARY)).findFirst(); + return resBinChunk.isPresent(); + } + /** * Rebuild PRequest from intenal text and chunks. This method no affects contents of this. * @@ -214,7 +269,7 @@ private byte[] reBuildPRequestFromDocTextAndChunks(String text) { // requestChunks = newrequest.getRequestChunks(); return resultarray.getBytes(); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()).log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } return null; } @@ -234,7 +289,7 @@ public void updateStyleDocAndChunkFromHex(byte[] hexbytes) { try { doctext = this.getText(0, this.getLength()); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()).log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); return; } @@ -348,24 +403,27 @@ private void updateRequest(PRequest newrequest) { } } + private void destroyDocumentAndRecreateStyles() { + try { + this.remove(0, this.getLength()); + this.deleteStyles(); + this.createStyles(); + } catch (BadLocationException ex) { + LOGGER4J.error(ex.getMessage(), ex); + } + } /** update StyledDocument with requestChunk */ private void updateRequest() { Encode pageenc = this.enc; responseChunks = null; - try { - this.remove(0, this.getLength()); - } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()).log(Level.SEVERE, null, ex); - } + destroyDocumentAndRecreateStyles(); // if you change or newly create Document in JEditorPane's Document, JEditorPane cannot // display contents. this problem occur only ZAP. // Thus you must get original Document from JEditorPane for Setting Text. - Style defaultStyle = SwingStyle.getDefaultStyle(this); - List chunks = requestChunks; int pos = 0; @@ -421,7 +479,7 @@ private void updateRequest() { icon = new ImageIcon(BRKICONURL, partno); } // doc.addStyle(partno, def); - s = makeStyleImageButton(defaultStyle, icon, partno); + s = makeStyleImageButton(icon, bundle.getString("ParmGenRegex.UndisplayableLargerData.text"), partno); LOGGER4J.debug("@CONTENTS length:" + chunk.getBytes().length); element = partno; } else { @@ -451,7 +509,7 @@ private void updateRequest() { + CONTENTS_PLACEHOLDER_SUFFIX; ImageIcon icon = new ImageIcon(BINICONURL, partno); // doc.addStyle(partno, def); - s = makeStyleImageButton(defaultStyle, icon, partno); + s = makeStyleImageButton(icon,bundle.getString("ParmGenRegex.UndisplayableLargerData.text"),partno); LOGGER4J.debug("BINICONED @CONTENTS length:" + chunk.getBytes().length); element = partno; } else { @@ -491,7 +549,7 @@ private void updateRequest() { pos = this.getLength(); } } catch (BadLocationException ex) { - Logger.getLogger(JTextPaneContents.class.getName()).log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } LOGGER4J.debug("doc.length:" + this.getLength()); } @@ -511,11 +569,7 @@ public void updateResponse(PResponse presponse) { responseChunks = presponse.getResponseChunks(); requestChunks = null; - try { - this.remove(0, this.getLength()); - } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()).log(Level.SEVERE, null, ex); - } + destroyDocumentAndRecreateStyles(); Style defaultStyle = SwingStyle.getDefaultStyle(this); @@ -536,7 +590,7 @@ public void updateResponse(PResponse presponse) { switch (chunk.getChunkType()) { case CONTENTSBINARY: icon = new ImageIcon(BINICONURL, partno); - s = makeStyleImageButton(defaultStyle, icon, partno); + s = makeStyleImageButton(icon,bundle.getString("ParmGenRegex.UndisplayableLargerData.text"), partno); elem = partno; LOGGER4J.debug("CONTENTSBINARY[" + elem + "]pos:" + pos); break; @@ -547,7 +601,7 @@ public void updateResponse(PResponse presponse) { } catch (Exception e) { icon = new ImageIcon(BRKICONURL, partno); } - s = makeStyleImageButton(defaultStyle, icon, partno); + s = makeStyleImageButton(icon, bundle.getString("ParmGenRegex.BrokenData.text"),partno); elem = partno; LOGGER4J.debug("CONTENTSIMG[" + elem + "]pos:" + pos); break; @@ -571,23 +625,25 @@ public void updateResponse(PResponse presponse) { /** * create button with ImageIcon and add eventhandler. * - * @param s * @param icon * @param actioncommand * @return */ - public Style makeStyleImageButton(Style s, ImageIcon icon, String actioncommand) { - StyleConstants.setAlignment(s, StyleConstants.ALIGN_CENTER); + public Style makeStyleImageButton(ImageIcon icon, String toolTip, String actioncommand) { + String styleName = "Image" + actioncommand; + Style imageStyle = addOrGetStyle(styleName); + StyleConstants.setAlignment(imageStyle, StyleConstants.ALIGN_CENTER); JButton button = new JButton(); button.setIcon(icon); + button.setToolTipText(toolTip); button.setMargin(new Insets(0, 0, 0, 0)); button.setActionCommand(actioncommand); button.addActionListener( e -> { LOGGER4J.debug("button pressed:" + e.getActionCommand()); }); - StyleConstants.setComponent(s, button); - return s; + StyleConstants.setComponent(imageStyle, button); + return imageStyle; } public Style getCRstyle() { @@ -628,16 +684,14 @@ private void insertStringCR(int pos, String text) { cpos++; pos = this.getLength(); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()) - .log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } } if (cpos < totallen) { try { this.insertString(pos, text.substring(cpos, totallen), null); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()) - .log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } } } @@ -651,11 +705,7 @@ private void generateStyledDocFromRequestText(String requesttext) { if (requesttext == null || requesttext.isEmpty() || requestChunks == null) return; - try { - this.remove(0, this.getLength()); - } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()).log(Level.SEVERE, null, ex); - } + destroyDocumentAndRecreateStyles(); int npos = -1; int cpos = 0; @@ -704,18 +754,21 @@ private void generateStyledDocFromRequestText(String requesttext) { RequestChunk content_chunk = ochunks.orElse(null); if (content_chunk != null && content_chunk.getBytes().length > 0) { ImageIcon icon = null; + String toolTip ; if (content_chunk.getChunkType() == RequestChunk.CHUNKTYPE.CONTENTS) { icon = new ImageIcon(BINICONURL, partnostr); + toolTip = bundle.getString("ParmGenRegex.BinaryData.text"); } else { // diplayable image try { icon = new ImageIcon(content_chunk.getBytes(), partnostr); + toolTip = "Image"; LOGGER4J.debug("icon status:" + ImageIconLoadStatus(icon)); } catch (Exception e) { + toolTip = bundle.getString("ParmGenRegex.BrokenData.text"); icon = new ImageIcon(BRKICONURL, partnostr); } } - Style defstyle = SwingStyle.getDefaultStyle(this); - s = makeStyleImageButton(defstyle, icon, partnostr); + s = makeStyleImageButton(icon, toolTip,partnostr); } } } @@ -724,8 +777,7 @@ private void generateStyledDocFromRequestText(String requesttext) { try { this.insertString(this.getLength(), element, s); } catch (BadLocationException ex) { - Logger.getLogger(StyledDocumentWithChunk.class.getName()) - .log(Level.SEVERE, null, ex); + LOGGER4J.error(ex.getMessage(), ex); } } else { insertStringCR(this.getLength(), element); diff --git a/addOns/automacrobuilder/src/main/resources/burp/Bundle.properties b/addOns/automacrobuilder/src/main/resources/burp/Bundle.properties index 5edb89d..cfba3c0 100644 --- a/addOns/automacrobuilder/src/main/resources/burp/Bundle.properties +++ b/addOns/automacrobuilder/src/main/resources/burp/Bundle.properties @@ -195,6 +195,9 @@ ParmGenRegex.comboModel_columnpolicy_0orMore(lazy).text=0 or more(lazy) ParmGenRegex.comboModel_columnpolicy_0orMore(greedy).text=0 or more(greedy) ParmGenRegex.insCR.text =Insert CR ParmGenRegex.SelectPattern.text=Update Regex with selected text. +ParmGenRegex.UndisplayableLargerData.text=sorry, data isn't displayable for it's larger size. +ParmGenRegex.BinaryData.text=sorry, this binary data is can't displayable as text. +ParmGenRegex.BrokenData.text=sorry. this binary data is can't displayable such as format errors or something. ParmGenTokenJDialog.DialogTitle.text=Tracking parameters list ParmGenTokenJDialog.SelectParamLabel1.text=Select Parameters you want to track. ParmGenTokenJDialog.trackTkTable.columnName0.text=track