diff options
author | Danny van Heumen <danny@dannyvanheumen.nl> | 2014-08-26 00:28:31 +0200 |
---|---|---|
committer | Danny van Heumen <danny@dannyvanheumen.nl> | 2014-09-16 21:26:40 +0200 |
commit | ff00a1076502943921390c3ad762182ca2b9d139 (patch) | |
tree | 68fc2d60bdb8959ca52f6a7217f193911ac2419e | |
parent | 61a9ae412db91a866176ec50939faa0e88829590 (diff) | |
download | jitsi-ff00a1076502943921390c3ad762182ca2b9d139.zip jitsi-ff00a1076502943921390c3ad762182ca2b9d139.tar.gz jitsi-ff00a1076502943921390c3ad762182ca2b9d139.tar.bz2 |
More advanced Text pattern that will take quotes into account.
A more advanced pattern that tries to take quotes into account. In case
this pattern does not work, this commit can be reverted and instead a
simpler pattern is used that relies on html tags being opened and closed
with < and > brackets. It assumes that < and > are always part of HTML
tags so any textual (content) occurrence should be replaced with html
entities (escaping).
-rw-r--r-- | src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java | 39 | ||||
-rw-r--r-- | test/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanelTest.java | 111 |
2 files changed, 145 insertions, 5 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java index fd95a61..78904db 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java @@ -106,10 +106,39 @@ public class ChatConversationPanel * correctly escaped, such that there is no occurrence of the symbols < * and >.</i> * - * <p>The first group matches any piece of text outside of HTML tags.</p> + * <pre> + * In essence this regexp pattern works as follows: + * 1. Find all the text that isn't the start of a tag. (so all chars != '<') + * -> This is your actual result: textual content that is not part of a + * tag. + * 2. Then, if you find a '<', find as much chars as you can until you find + * '>' (if it is possible at all to find a closing '>') + * + * In depth explanation of 2.: + * The text between tags consists mainly of 2 parts: + * + * A) a piece of text + * B) some value "between quotes" + * + * So everything up to the "quote" is part of a piece of text (A). Then + * if we encounter a "quote" we consider the rest of the text part of the + * value (B) until the value section is closed with a closing "quote". + * (We tend to be rather greedy, so we even swallow '>' along the way + * looking for the closing "quote".) + * + * This subpattern is allowed any number of times, until eventually the + * closing '>' is encountered. (Or not if the pattern is incomplete.) + * + * 3. And consider that 2. is optional, since it could also be that we only + * find plain text, which would all be captured by 1. + * </pre> + * + * <p>The first group matches any piece of text outside of the < and > + * brackets that define the start and end of HTML tags.</p> */ - public static final Pattern TEXT_TO_REPLACE_PATTERN = Pattern.compile( - "([^<]*+)(?:<[^>]*+>)?", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); + static final Pattern TEXT_TO_REPLACE_PATTERN = Pattern.compile( + "([^<]*+)(?:<(?:[^>\"]*(?:\"[^\"]*+\"?)*)*+>?)?", + Pattern.CASE_INSENSITIVE | Pattern.DOTALL); /** * List for observing text messages. @@ -206,8 +235,8 @@ public class ChatConversationPanel = new ShowPreviewDialog(ChatConversationPanel.this); /** - * The implementation of the routine which scrolls {@link #chatTextPane} to its - * bottom. + * The implementation of the routine which scrolls {@link #chatTextPane} to + * its bottom. */ private final Runnable scrollToBottomRunnable = new Runnable() { diff --git a/test/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanelTest.java b/test/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanelTest.java new file mode 100644 index 0000000..54d8922 --- /dev/null +++ b/test/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanelTest.java @@ -0,0 +1,111 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.gui.main.chat; + +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.*; + +import junit.framework.*; + +/** + * Tests for functionality of the ChatConversationPanel. + * + * @author Danny van Heumen + */ +public class ChatConversationPanelTest + extends TestCase +{ + + /** + * Test for various better and worse pieces of HTML to test the resilience + * of the pattern. + */ + public void testHtmlSnippetsOnTextToReplacePattern() + { + final HashMap<String, String[]> tests = new HashMap<String, String[]>(); + tests.put("just a piece of text", + new String[] {"just a piece of text", ""}); + tests.put(">another piece of text", + new String[] {">another piece of text", ""}); + tests.put("<another piece of text", + new String[] {"", ""}); + tests.put("<another piece> of text", + new String[] {"", " of text", ""}); + tests.put("<another attribute=\"piece\"> of text", + new String[] {"", " of text", ""}); + tests.put("<another attribute=\"<\"> of text", + new String[] {"", " of text", ""}); + tests.put("piece of text<tag>'nother piece</tag>stuff at the end", + new String[] + {"piece of text", "'nother piece", "stuff at the end", "" }); + tests.put("<br />", new String[] {"", ""}); + tests.put("<br />text", new String[] {"", "text", ""}); + tests.put("some<br />text", new String[] {"some", "text", ""}); + tests.put("<img src=\"blablabla.jpg\" />", + new String[] {"", ""}); + tests.put("some<img src=\"blablabla.jpg\" />", + new String[] {"some", ""}); + tests.put("some<img src=\"blablabla.jpg\" />foobar", + new String[] {"some", "foobar", ""}); + tests.put(">some text between cut-off tags<", + new String[] {">some text between cut-off tags", ""}); + tests.put("<some text between pointy brackets>", + new String[] {"", ""}); + tests.put("fake <br/> tag", + new String[] {"fake <br/> tag", ""}); + tests.put("fake <br/> tag", + new String[] {"fake <br/> tag", ""}); + tests.put("fake <br/> tag", + new String[] {"fake ", ""}); + tests.put("a piece <b>of <u>formatted</u> text for </b>testing...", + new String[] {"a piece ", "of ", "formatted", " text for ", + "testing...", ""}); + tests.put("a piece <a href=\"www.google.com?query=blabla#blabla\">" + + "www.google.com</a> hyperlinked text", + new String[] {"a piece ", "www.google.com", " hyperlinked text", + ""}); + tests.put("<another attribute=\">\"> of text", + new String[] {"", " of text", ""}); + tests.put("<a name=\"Click here ><\" href=\"www.google.com\">" + + "For a treat</a> or something ...", + new String[] {"", "For a treat", " or something ...", ""}); + tests.put("and here is <a \"some weird syntax\"> to test", + new String[] {"and here is ", " to test", ""}); + tests.put("and here <option name=\"opt\" checked> checked option", + new String[] {"and here ", " checked option", ""}); + tests.put("incomplete <img href=\"www.goo", + new String[] {"incomplete ", ""}); + tests.put("incomplete <img href=\"www.goo > <a href=\">test", + new String[] {"incomplete ", "test", ""}); + tests.put("\"blablabla\">See if this text is ignored ...", + new String[] {"\"blablabla\">See if this text is ignored ...", ""}); + tests.put("bla\">See if this<img src=\"test1\">test2</img>", + new String[] {"bla\">See if this", "test2", ""}); + tests.put("<the-end", new String[] {"", ""}); + tests.put("<this-is-not-a-tag>", + new String[] {"<this-is-not-a-tag>", ""}); + tests.put("<this-is-a-tag>", new String[] {"", ""}); + + for (final Entry<String, String[]> entry : tests.entrySet()) + { + final String input = entry.getKey(); + int index = 0; + final Matcher matcher = + ChatConversationPanel.TEXT_TO_REPLACE_PATTERN.matcher(input); + while (matcher.find()) + { + final String piece = matcher.group(1); + Assert.assertEquals("INPUT [[" + input + "]]:", + entry.getValue()[index], piece); + index++; + } + // ensure that we have checked all predicted pieces + Assert.assertEquals(entry.getValue().length, index); + } + } +} |