Support the invalid QRcodes generated by blockchain.info (Ben Reeves software). They put bitcoin:// at the front instead of bitcoin:, apparently because otherwise some social networks won't recognize them.

This commit is contained in:
Mike Hearn 2012-07-14 13:23:00 +02:00
parent ad2c339d85
commit 831f2d582f
2 changed files with 20 additions and 13 deletions

View file

@ -93,7 +93,6 @@ public class BitcoinURI {
private static final String ENCODED_SPACE_CHARACTER = "%20"; private static final String ENCODED_SPACE_CHARACTER = "%20";
private static final String AMPERSAND_SEPARATOR = "&"; private static final String AMPERSAND_SEPARATOR = "&";
private static final String QUESTION_MARK_SEPARATOR = "?"; private static final String QUESTION_MARK_SEPARATOR = "?";
private static final String COLON_SEPARATOR = ":";
/** /**
* Contains all the parameters in the order in which they were processed * Contains all the parameters in the order in which they were processed
@ -121,12 +120,7 @@ public class BitcoinURI {
Preconditions.checkNotNull(input); Preconditions.checkNotNull(input);
log.debug("Attempting to parse '{}' for {}", input, params == null ? "any" : params.getId()); log.debug("Attempting to parse '{}' for {}", input, params == null ? "any" : params.getId());
// URI validation // Attempt to form the URI (fail fast syntax checking to official standards).
if (!input.startsWith(BITCOIN_SCHEME)) {
throw new BitcoinURIParseException("Bad scheme - expecting '" + BITCOIN_SCHEME + "'");
}
// Attempt to form the URI (fail fast syntax checking to official standards)
URI uri; URI uri;
try { try {
uri = new URI(input); uri = new URI(input);
@ -135,15 +129,21 @@ public class BitcoinURI {
} }
// URI is formed as bitcoin:<address>?<query parameters> // URI is formed as bitcoin:<address>?<query parameters>
// blockchain.info generates URIs of non-BIP compliant form bitcoin://address?....
// We support both until Ben fixes his code.
// Remove the bitcoin scheme. // Remove the bitcoin scheme.
// (Note: getSchemeSpecificPart() is not used as it unescapes the label and parse then fails. // (Note: getSchemeSpecificPart() is not used as it unescapes the label and parse then fails.
// For instance with : bitcoin:129mVqKUmJ9uwPxKJBnNdABbuaaNfho4Ha?amount=0.06&label=Tom%20%26%20Jerry // For instance with : bitcoin:129mVqKUmJ9uwPxKJBnNdABbuaaNfho4Ha?amount=0.06&label=Tom%20%26%20Jerry
// the & (%26) in Tom and Jerry gets interpreted as a separator and the label then gets parsed // the & (%26) in Tom and Jerry gets interpreted as a separator and the label then gets parsed
// as 'Tom ' instead of 'Tom & Jerry') // as 'Tom ' instead of 'Tom & Jerry')
String schemeSpecificPart = ""; String schemeSpecificPart;
if (uri.toString().startsWith(BITCOIN_SCHEME + COLON_SEPARATOR)) { if (input.startsWith("bitcoin://")) {
schemeSpecificPart = uri.toString().substring(BITCOIN_SCHEME.length() + 1); schemeSpecificPart = input.substring("bitcoin://".length());
} else if (input.startsWith("bitcoin:")) {
schemeSpecificPart = input.substring("bitcoin:".length());
} else {
throw new BitcoinURIParseException("Unsupported URI scheme: " + uri.getScheme());
} }
// Split off the address from the rest of the query parameters. // Split off the address from the rest of the query parameters.
@ -311,7 +311,7 @@ public class BitcoinURI {
} }
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(BITCOIN_SCHEME).append(COLON_SEPARATOR).append(address); builder.append(BITCOIN_SCHEME).append(":").append(address);
boolean questionMarkHasBeenOutput = false; boolean questionMarkHasBeenOutput = false;

View file

@ -111,7 +111,6 @@ public class BitcoinURITest {
testObject = new BitcoinURI(NetworkParameters.prodNet(), "blimpcoin:" + PRODNET_GOOD_ADDRESS); testObject = new BitcoinURI(NetworkParameters.prodNet(), "blimpcoin:" + PRODNET_GOOD_ADDRESS);
fail("Expecting BitcoinURIParseException"); fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) { } catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("Bad scheme"));
} }
} }
@ -153,7 +152,6 @@ public class BitcoinURITest {
testObject = new BitcoinURI(NetworkParameters.prodNet(), BitcoinURI.BITCOIN_SCHEME); testObject = new BitcoinURI(NetworkParameters.prodNet(), BitcoinURI.BITCOIN_SCHEME);
fail("Expecting BitcoinURIParseException"); fail("Expecting BitcoinURIParseException");
} catch (BitcoinURIParseException e) { } catch (BitcoinURIParseException e) {
assertTrue(e.getMessage().contains("Missing address"));
} }
} }
@ -413,4 +411,13 @@ public class BitcoinURITest {
assertTrue(e.getMessage().contains("req-aardvark")); assertTrue(e.getMessage().contains("req-aardvark"));
} }
} }
@Test
public void brokenURIs() throws BitcoinURIParseException {
// Check we can parse the incorrectly formatted URIs produced by blockchain.info and its iPhone app.
String str = "bitcoin://1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH?amount=0.01000000";
BitcoinURI uri = new BitcoinURI(str);
assertEquals("1KzTSfqjF2iKCduwz59nv2uqh1W2JsTxZH", uri.getAddress().toString());
assertEquals(Utils.toNanoCoins(0, 1), uri.getAmount());
}
} }