From 918451f3da348d07a41b8659f81d694eabaf851e Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Thu, 30 Aug 2018 19:56:18 +1200 Subject: [PATCH 1/2] Scanning or pasting ordinary URL gives the option to open it in a browser. --- i18n/po/template.pot | 8 +++++ src/js/services/bitcoin-uri.service.js | 9 ++++++ src/js/services/bitcoin-uri.service.spec.js | 15 ++++++++-- src/js/services/incomingData.js | 33 +++++++++++---------- www/views/includes/incomingDataMenu.html | 24 +++++++++++++++ 5 files changed, 71 insertions(+), 18 deletions(-) diff --git a/i18n/po/template.pot b/i18n/po/template.pot index 5483ce40b..f61012914 100644 --- a/i18n/po/template.pot +++ b/i18n/po/template.pot @@ -3865,4 +3865,12 @@ msgstr "" #: src/js/controllers/tab-scan.js:121 msgid "Testnet is not supported." +msgstr "" + +#: www/views/includes/incomingDataMenu.html:81 +msgid "URL" +msgstr "" + +#: www/views/includes/incomingDataMenu.html:90 +msgid "Open in web browser" msgstr "" \ No newline at end of file diff --git a/src/js/services/bitcoin-uri.service.js b/src/js/services/bitcoin-uri.service.js index 0dd57dbf2..25d6cbfb0 100644 --- a/src/js/services/bitcoin-uri.service.js +++ b/src/js/services/bitcoin-uri.service.js @@ -93,6 +93,7 @@ returns: { amount: '', + bareUrl: '', coin: '', copayInvitation: '', isValid: false, @@ -163,6 +164,9 @@ addressAndParams = colonSplit[1]; console.log('No prefix.'); + } else if (/^https?$/.test(colonSplit[1])) { + addressAndParams = trimmed; + } else { // Something with a colon in the middle that we don't recognise return parsed; @@ -253,6 +257,7 @@ var privateKeyForUncompressedPublicKeyTestnetRe = /^9[1-9A-HJ-NP-Za-km-z]{50}$/; var privateKeyForCompressedPublicKeyRe = /^[KL][1-9A-HJ-NP-Za-km-z]{51}$/; var privateKeyForCompressedPublicKeyTestnetRe = /^[c][1-9A-HJ-NP-Za-km-z]{51}$/; + var urlRe = /^https?:\/\/.+/; var bitpayAddrMainnet = bitpayAddrOnMainnet(address); var cashAddrTestnet = cashAddrOnTestnet(addressLowerCase); @@ -322,6 +327,10 @@ } else if (privateKeyEncryptedRe.test(address)) { parsed.privateKey = { encrypted: address }; parsed.isValid = true; + + } else if (urlRe.test(address)) { + parsed.bareUrl = trimmed; + parsed.isValid = true; } } else { diff --git a/src/js/services/bitcoin-uri.service.spec.js b/src/js/services/bitcoin-uri.service.spec.js index 0e4a2ba31..85554df0e 100644 --- a/src/js/services/bitcoin-uri.service.spec.js +++ b/src/js/services/bitcoin-uri.service.spec.js @@ -343,11 +343,20 @@ fdescribe('bitcoinUriService', function() { expect(parsed.isValid).toBe(false); }); - it('URL only', function() { + it('URL only, http', function() { - var parsed = bitcoinUriService.parse('https://www.google.com'); + var parsed = bitcoinUriService.parse('http://paperwallet.bitcoin.com'); - expect(parsed.isValid).toBe(false); + expect(parsed.isValid).toBe(true); + expect(parsed.bareUrl).toBe('http://paperwallet.bitcoin.com'); + }); + + it('URL only, https with query', function() { + + var parsed = bitcoinUriService.parse('https://purse.io/?one=two&three=four'); + + expect(parsed.isValid).toBe(true); + expect(parsed.bareUrl).toBe('https://purse.io/?one=two&three=four'); }); }); \ No newline at end of file diff --git a/src/js/services/incomingData.js b/src/js/services/incomingData.js index b2e125e48..e9b6f6dfa 100644 --- a/src/js/services/incomingData.js +++ b/src/js/services/incomingData.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('incomingData', function(bitcoinUriService, $log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, sendFlowService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) { +angular.module('copayApp.services').factory('incomingData', function(externalLinkService, bitcoinUriService, $log, $state, $timeout, $ionicHistory, bitcore, bitcoreCash, $rootScope, payproService, scannerService, sendFlowService, appConfigService, popupService, gettextCatalog, bitcoinCashJsService) { var root = {}; @@ -251,20 +251,23 @@ angular.module('copayApp.services').factory('incomingData', function(bitcoinUriS ); return true; // Plain URL - } else if (/^https?:\/\//.test(data)) { - payproService.getPayProDetails(data, coin, function(err, details) { - if (err) { - if ($state.includes('tabs.scan')) { - root.showMenu({ - data: data, - type: 'url' - }); - } - return; - } - handlePayPro(details); - return true; - }); + } else if (allParsed.bareUrl) { + + if ($state.includes('tabs.scan')) { + root.showMenu({ + data: allParsed.bareUrl, + type: 'url' + }); + } else { + externalLinkService.open( + allParsed.bareUrl, + true, + gettextCatalog.getString('Open in web browser'), + allParsed.bareUrl + ); + } + return true; + // Plain Address } else if (bitcore.Address.isValid(data, 'livenet') || bitcore.Address.isValid(data, 'testnet')) { if ($state.includes('tabs.scan')) { diff --git a/www/views/includes/incomingDataMenu.html b/www/views/includes/incomingDataMenu.html index ca4b78dfc..1d66b616a 100644 --- a/www/views/includes/incomingDataMenu.html +++ b/www/views/includes/incomingDataMenu.html @@ -76,4 +76,28 @@ +
+
+
URL
+
+
+ {{data}} +
+
+
+ + +
Open in web browser
+ +
+ + +
Copy to clipboard
+ +
+ + Cancel + +
+ From 6a68d73e3ab1ce0c18ae6102fa1eb5c9b85eadd5 Mon Sep 17 00:00:00 2001 From: Brendon Duncan Date: Thu, 30 Aug 2018 20:20:51 +1200 Subject: [PATCH 2/2] Now handles spaces after address prefix. --- src/js/services/bitcoin-uri.service.js | 8 +++--- src/js/services/bitcoin-uri.service.spec.js | 31 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/js/services/bitcoin-uri.service.js b/src/js/services/bitcoin-uri.service.js index 25d6cbfb0..f2f17fd9d 100644 --- a/src/js/services/bitcoin-uri.service.js +++ b/src/js/services/bitcoin-uri.service.js @@ -144,24 +144,24 @@ var preColonLower = colonSplit[1].toLowerCase(); if (preColonLower === 'bitcoin') { parsed.coin = 'btc'; - addressAndParams = colonSplit[2]; + addressAndParams = colonSplit[2].trim(); console.log('Is btc'); } else if (/^(?:bitcoincash)|(?:bitcoin-cash)$/.test(preColonLower)) { parsed.coin = 'bch'; parsed.test = false; - addressAndParams = colonSplit[2]; + addressAndParams = colonSplit[2].trim(); console.log('Is bch'); } else if (/^(?:bchtest)$/.test(preColonLower)) { parsed.coin = 'bch'; parsed.testnet = true; - addressAndParams = colonSplit[2]; + addressAndParams = colonSplit[2].trim(); console.log('Is bch'); } else if (colonSplit[2] === '') { // No colon and no coin specifier. - addressAndParams = colonSplit[1]; + addressAndParams = colonSplit[1].trim(); console.log('No prefix.'); } else if (/^https?$/.test(colonSplit[1])) { diff --git a/src/js/services/bitcoin-uri.service.spec.js b/src/js/services/bitcoin-uri.service.spec.js index 85554df0e..61c6f6fa3 100644 --- a/src/js/services/bitcoin-uri.service.spec.js +++ b/src/js/services/bitcoin-uri.service.spec.js @@ -140,6 +140,16 @@ fdescribe('bitcoinUriService', function() { expect(parsed.testnet).toBe(false); }); + it('Bitcoin uri with space', function() { + + var parsed = bitcoinUriService.parse('bitcoin: 19cPoKU5ZazY8NkLEsxK7drBqJnpGkax3d'); + + expect(parsed.isValid).toBe(true); + expect(parsed.coin).toBe('btc'); + expect(parsed.publicAddress.legacy).toBe('19cPoKU5ZazY8NkLEsxK7drBqJnpGkax3d'); + expect(parsed.testnet).toBe(false); + }); + it('Bitpay without prefix', function() { var parsed = bitcoinUriService.parse('CJoRov8TirekvajiimQpb5Hk95evA7H2Yz'); @@ -220,6 +230,27 @@ fdescribe('bitcoinUriService', function() { expect(parsed.testnet).toBe(false); }); + it('cashAddr with space', function() { + + var parsed = bitcoinUriService.parse('bitcoincash: qpar9ldle8z6alcwgclejdhc24ha2xrg0szs5802ce'); + + expect(parsed.isValid).toBe(true); + expect(parsed.coin).toBe('bch'); + expect(parsed.publicAddress.cashAddr).toBe('qpar9ldle8z6alcwgclejdhc24ha2xrg0szs5802ce'); + expect(parsed.testnet).toBe(false); + }); + + + it('cashAddr with space on testnet', function() { + + var parsed = bitcoinUriService.parse('bchtest: qqjxkmtaxk4nv6w9h5ht2fjcj9c7ruh0fu7cnxsx5j'); + + expect(parsed.isValid).toBe(true); + expect(parsed.coin).toBe('bch'); + expect(parsed.publicAddress.cashAddr).toBe('qqjxkmtaxk4nv6w9h5ht2fjcj9c7ruh0fu7cnxsx5j'); + expect(parsed.testnet).toBe(true); + }); + it('cashAddr without prefix', function() { var parsed = bitcoinUriService.parse('qqen2y3l28dpk0dzsag8w027ds96u7z4pc0uxtl0nq');