From 44e2954b208731109c5d7300f30a628a28d5b0a3 Mon Sep 17 00:00:00 2001 From: ligi Date: Mon, 29 May 2017 13:56:19 +0200 Subject: [PATCH] Add support for ethereum (ERC-67) URIs see https://github.com/ethereum/EIPs/issues/67 --- .../k9/message/html/EthereumUriParser.java | 32 +++++++ .../fsck/k9/message/html/UriLinkifier.java | 1 + .../message/html/EthereumUriParserTest.java | 83 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 k9mail/src/main/java/com/fsck/k9/message/html/EthereumUriParser.java create mode 100644 k9mail/src/test/java/com/fsck/k9/message/html/EthereumUriParserTest.java diff --git a/k9mail/src/main/java/com/fsck/k9/message/html/EthereumUriParser.java b/k9mail/src/main/java/com/fsck/k9/message/html/EthereumUriParser.java new file mode 100644 index 000000000..04c390ea7 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/message/html/EthereumUriParser.java @@ -0,0 +1,32 @@ +package com.fsck.k9.message.html; + + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Parses ERC-67 URIs + * https://github.com/ethereum/EIPs/issues/67 + */ +class EthereumUriParser implements UriParser { + private static final Pattern ETHEREUM_URI_PATTERN = + Pattern.compile("ethereum:0x[0-9a-fA-F]*(\\?[a-zA-Z0-9$\\-_.+!*'(),%:@&=]*)?"); + + @Override + public int linkifyUri(String text, int startPos, StringBuffer outputBuffer) { + Matcher matcher = ETHEREUM_URI_PATTERN.matcher(text); + + if (!matcher.find(startPos) || matcher.start() != startPos) { + return startPos; + } + + String ethereumURI = matcher.group(); + outputBuffer.append("") + .append(ethereumURI) + .append(""); + + return matcher.end(); + } +} diff --git a/k9mail/src/main/java/com/fsck/k9/message/html/UriLinkifier.java b/k9mail/src/main/java/com/fsck/k9/message/html/UriLinkifier.java index 01ee239e6..815acc5ce 100644 --- a/k9mail/src/main/java/com/fsck/k9/message/html/UriLinkifier.java +++ b/k9mail/src/main/java/com/fsck/k9/message/html/UriLinkifier.java @@ -18,6 +18,7 @@ public class UriLinkifier { static { SUPPORTED_URIS = new HashMap<>(); + SUPPORTED_URIS.put("ethereum:", new EthereumUriParser()); SUPPORTED_URIS.put("bitcoin:", new BitcoinUriParser()); UriParser httpParser = new HttpUriParser(); SUPPORTED_URIS.put("http:", httpParser); diff --git a/k9mail/src/test/java/com/fsck/k9/message/html/EthereumUriParserTest.java b/k9mail/src/test/java/com/fsck/k9/message/html/EthereumUriParserTest.java new file mode 100644 index 000000000..71460ea6c --- /dev/null +++ b/k9mail/src/test/java/com/fsck/k9/message/html/EthereumUriParserTest.java @@ -0,0 +1,83 @@ +package com.fsck.k9.message.html; + + +import org.junit.Test; +import static com.fsck.k9.message.html.UriParserTestHelper.assertLinkOnly; +import static org.junit.Assert.assertEquals; + + +public class EthereumUriParserTest { + EthereumUriParser parser = new EthereumUriParser(); + StringBuffer outputBuffer = new StringBuffer(); + + + @Test + public void basicEthereumUri() throws Exception { + assertLinkify("ethereum:0xfdf1210fc262c73d0436236a0e07be419babbbc4"); + } + + @Test + public void ethereumUriWithValue() throws Exception { + assertLinkify("ethereum:0xfdf1210fc262c73d0436236a0e07be419babbbc4?value=42"); + } + + @Test + public void ethereumUriWithQueryParameters() throws Exception { + assertLinkify("ethereum:0xfdf1210fc262c73d0436236a0e07be419babbbc4?value=42" + + "&gas=100000&bytecode=0xa9059cbb0000000000000000000000000000000dead"); + } + + @Test + public void uriInMiddleOfInput() throws Exception { + String prefix = "prefix "; + String uri = "ethereum:0xfdf1210fc262c73d0436236a0e07be419babbbc4?value=42"; + String text = prefix + uri; + + parser.linkifyUri(text, prefix.length(), outputBuffer); + + assertLinkOnly(uri, outputBuffer); + } + + @Test + public void invalidScheme() throws Exception { + assertNotLinkify("ethereMU:0xfdf1210fc262c73d0436236a0e07be419babbbc4"); + } + + @Test + public void invalidAddress() throws Exception { + assertNotLinkify("ethereum:[invalid]"); + } + + @Test + public void invalidEthereumUri_shouldReturnStartingPosition() throws Exception { + String uri = "ethereum:[invalid]"; + + int newPos = linkify(uri); + + assertEquals(0, newPos); + } + + @Test + public void invalidEthereumUri_shouldNotWriteToOutputBuffer() throws Exception { + String uri = "ethereum:[invalid]"; + + linkify(uri); + + assertEquals(0, outputBuffer.length()); + } + + + int linkify(String uri) { + return parser.linkifyUri(uri, 0, outputBuffer); + } + + void assertLinkify(String uri) { + linkify(uri); + assertLinkOnly(uri, outputBuffer); + } + + void assertNotLinkify(String text) { + int newPos = linkify(text); + assertEquals(0, newPos); + } +}