tunify util.parse_URI - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 6f3c9e6a447ef76b3a63d7eeac167a392ed71940 DIR parent ca4e9261e0a5d05c0a9d10d6221e4ec840291a52 HTML Author: ThomasV <thomasv@gitorious> Date: Fri, 13 Jun 2014 16:02:30 +0200 unify util.parse_URI Diffstat: M gui/android.py | 4 ++-- M gui/gtk.py | 4 ++-- M gui/qt/__init__.py | 42 +++---------------------------- M gui/qt/lite_window.py | 8 ++++++-- M gui/qt/main_window.py | 69 +++++++++++++++++++++----------- M lib/util.py | 13 +++++++++---- M plugins/qrscanner.py | 69 +------------------------------ 7 files changed, 69 insertions(+), 140 deletions(-) --- DIR diff --git a/gui/android.py b/gui/android.py t@@ -488,7 +488,7 @@ def make_new_contact(): data = r['extras']['SCAN_RESULT'] if data: if re.match('^bitcoin:', data): - address, _, _, _, _, _, _ = util.parse_url(data) + address, _, _, _, _ = util.parse_URI(data) elif is_valid(data): address = data else: t@@ -619,7 +619,7 @@ def payto_loop(): data = r['extras']['SCAN_RESULT'] if data: if re.match('^bitcoin:', data): - payto, amount, label, _, _, _, _ = util.parse_url(data) + payto, amount, label, _, _ = util.parse_URI(data) droid.fullSetProperty("recipient", "text",payto) droid.fullSetProperty("amount", "text", amount) droid.fullSetProperty("label", "text", label) DIR diff --git a/gui/gtk.py b/gui/gtk.py t@@ -33,7 +33,7 @@ APP_NAME = "Electrum" import platform MONOSPACE_FONT = 'Lucida Console' if platform.system() == 'Windows' else 'monospace' -from electrum.util import format_satoshis, parse_url +from electrum.util import format_satoshis, parse_URI from electrum.network import DEFAULT_SERVERS from electrum.bitcoin import MIN_RELAY_TX_FEE t@@ -730,7 +730,7 @@ class ElectrumWindow: entry.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse("#ffffff")) def set_url(self, url): - payto, amount, label, message, payment_request, url = parse_url(url) + payto, amount, label, message, payment_request = parse_URI(url) self.notebook.set_current_page(1) self.payto_entry.set_text(payto) self.message_entry.set_text(message) DIR diff --git a/gui/qt/__init__.py b/gui/qt/__init__.py t@@ -18,7 +18,7 @@ import sys, time, datetime, re, threading from electrum.i18n import _, set_language -from electrum.util import print_error, print_msg, parse_url +from electrum.util import print_error, print_msg from electrum.plugins import run_hook import os.path, json, ast, traceback import shutil t@@ -142,44 +142,8 @@ class ElectrumGui: return int(qtVersion[0]) >= 4 and int(qtVersion[2]) >= 7 - def set_url(self, url): - from electrum import util - from decimal import Decimal - - try: - address, amount, label, message, request_url, url = util.parse_url(url) - except Exception: - QMessageBox.warning(self.main_window, _('Error'), _('Invalid bitcoin URL'), _('OK')) - return - - if amount: - try: - if self.main_window.base_unit() == 'mBTC': - amount = str( 1000* Decimal(amount)) - else: - amount = str(Decimal(amount)) - except Exception: - amount = "0.0" - QMessageBox.warning(self.main_window, _('Error'), _('Invalid Amount'), _('OK')) - - if request_url: - from electrum import paymentrequest - - if not request_url: - self.main_window.set_send(address, amount, label, message) - self.lite_window.set_payment_fields(address, amount) - return - - def payment_request(): - self.payment_request = paymentrequest.PaymentRequest(self.config) - self.payment_request.read(request_url) - if self.payment_request.verify(): - self.main_window.emit(SIGNAL('payment_request_ok')) - else: - self.main_window.emit(SIGNAL('payment_request_error')) - - threading.Thread(target=payment_request).start() - self.main_window.prepare_for_payment_request() + def set_url(self, uri): + self.current_window.pay_from_URI(uri) def main(self, url): DIR diff --git a/gui/qt/lite_window.py b/gui/qt/lite_window.py t@@ -308,10 +308,14 @@ class MiniWindow(QDialog): self.actuator.g.closeEvent(event) qApp.quit() - def set_payment_fields(self, dest_address, amount): + def pay_from_URI(self, URI): + try: + dest_address, amount, label, message, request_url = util.parse_URI(URI) + except: + return self.address_input.setText(dest_address) self.address_field_changed(dest_address) - self.amount_input.setText(amount) + self.amount_input.setText(str(amount)) def activate(self): pass DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py t@@ -803,8 +803,8 @@ class ElectrumWindow(QMainWindow): def read_send_tab(self): label = unicode( self.message_e.text() ) - if self.gui_object.payment_request: - outputs = self.gui_object.payment_request.get_outputs() + if self.payment_request: + outputs = self.payment_request.get_outputs() else: outputs = self.payto_e.get_outputs() t@@ -903,12 +903,12 @@ class ElectrumWindow(QMainWindow): def broadcast_transaction(self, tx): def broadcast_thread(): - pr = self.gui_object.payment_request + pr = self.payment_request if pr is None: return self.wallet.sendtx(tx) if pr.has_expired(): - self.gui_object.payment_request = None + self.payment_request = None return False, _("Payment request has expired") status, msg = self.wallet.sendtx(tx) t@@ -918,7 +918,7 @@ class ElectrumWindow(QMainWindow): self.invoices[pr.get_id()] = (pr.get_domain(), pr.get_memo(), pr.get_amount(), PR_PAID, tx.hash()) self.wallet.storage.put('invoices', self.invoices) self.update_invoices_tab() - self.gui_object.payment_request = None + self.payment_request = None refund_address = self.wallet.addresses()[0] ack_status, ack_msg = pr.send_ack(str(tx), refund_address) if ack_status: t@@ -950,7 +950,7 @@ class ElectrumWindow(QMainWindow): return True def payment_request_ok(self): - pr = self.gui_object.payment_request + pr = self.payment_request pr_id = pr.get_id() if pr_id not in self.invoices: self.invoices[pr_id] = (pr.get_domain(), pr.get_memo(), pr.get_amount(), PR_UNPAID, None) t@@ -963,7 +963,7 @@ class ElectrumWindow(QMainWindow): if status == PR_PAID: self.do_clear() self.show_message("invoice already paid") - self.gui_object.payment_request = None + self.payment_request = None return self.payto_help.show() t@@ -976,25 +976,48 @@ class ElectrumWindow(QMainWindow): def payment_request_error(self): self.do_clear() - self.show_message(self.gui_object.payment_request.error) - self.gui_object.payment_request = None + self.show_message(self.payment_request.error) + self.payment_request = None - def set_send(self, address, amount, label, message): - - if label and self.wallet.labels.get(address) != label: - if self.question('Give label "%s" to address %s ?'%(label,address)): - if address not in self.wallet.addressbook and not self.wallet.is_mine(address): - self.wallet.addressbook.append(address) - self.wallet.set_label(address, label) + def pay_from_URI(self,URI): + address, amount, label, message, request_url = util.parse_URI(URI) + try: + address, amount, label, message, request_url = util.parse_URI(URI) + except Exception as e: + QMessageBox.warning(self, _('Error'), _('Invalid bitcoin URI:') + '\n' + str(e), _('OK')) + return self.tabs.setCurrentIndex(1) - label = self.wallet.labels.get(address) - m_addr = label + ' <'+ address +'>' if label else address - self.payto_e.setText(m_addr) - self.message_e.setText(message) - if amount: - self.amount_e.setText(amount) + if not request_url: + if label: + if self.wallet.labels.get(address) != label: + if self.question(_('Save label "%s" for address %s ?'%(label,address))): + if address not in self.wallet.addressbook and not self.wallet.is_mine(address): + self.wallet.addressbook.append(address) + self.wallet.set_label(address, label) + else: + label = self.wallet.labels.get(address) + if address: + self.payto_e.setText(label + ' <'+ address +'>' if label else address) + if message: + self.message_e.setText(message) + if amount: + self.amount_e.setAmount(amount) + return + + from electrum import paymentrequest + def payment_request(): + self.payment_request = paymentrequest.PaymentRequest(self.config) + self.payment_request.read(request_url) + if self.payment_request.verify(): + self.emit(SIGNAL('payment_request_ok')) + else: + self.emit(SIGNAL('payment_request_error')) + + self.pr_thread = threading.Thread(target=payment_request).start() + self.prepare_for_payment_request() + def do_clear(self): t@@ -1279,7 +1302,7 @@ class ElectrumWindow(QMainWindow): pr = PaymentRequest(self.config) pr.read_file(key) pr.domain = domain - self.gui_object.payment_request = pr + self.payment_request = pr self.prepare_for_payment_request() if pr.verify(): self.payment_request_ok() DIR diff --git a/lib/util.py b/lib/util.py t@@ -157,15 +157,20 @@ def age(from_date, since_date = None, target_tz=None, include_seconds=False): #_ud = re.compile('%([0-9a-hA-H]{2})', re.MULTILINE) #urldecode = lambda x: _ud.sub(lambda m: chr(int(m.group(1), 16)), x) -def parse_url(url): +def parse_URI(uri): import urlparse + import bitcoin from decimal import Decimal - u = urlparse.urlparse(url) + if ':' not in uri: + assert bitcoin.is_address(url) + return uri, None, None, None, None + + u = urlparse.urlparse(uri) assert u.scheme == 'bitcoin' address = u.path - #assert bitcoin.is_address(address) + assert bitcoin.is_address(address) pq = urlparse.parse_qs(u.query) t@@ -189,7 +194,7 @@ def parse_url(url): if 'r' in pq: request_url = pq['r'][0] - return address, amount, label, message, request_url, url + return address, amount, label, message, request_url # Python bug (http://bugs.python.org/issue1927) causes raw_input DIR diff --git a/plugins/qrscanner.py b/plugins/qrscanner.py t@@ -46,7 +46,7 @@ class Plugin(BasePlugin): self.win = self.gui.main_window self.win.raw_transaction_menu.addAction(_("&From QR code"), self.read_raw_qr) b = QPushButton(_("Scan QR code")) - b.clicked.connect(self.fill_from_qr) + b.clicked.connect(lambda: self.win.pay_from_URI(self.scan_qr())) self.win.send_grid.addWidget(b, 1, 5) self.win.send_grid.setColumnStretch(5, 0) self.win.send_grid.setColumnStretch(6, 1) t@@ -98,21 +98,6 @@ class Plugin(BasePlugin): return self.win.show_transaction(tx) - - def fill_from_qr(self): - qrcode = parse_uri(self.scan_qr()) - if not qrcode: - return - - if 'address' in qrcode: - self.win.payto_e.setText(qrcode['address']) - if 'amount' in qrcode: - self.win.amount_e.setText(str(qrcode['amount'])) - if 'label' in qrcode: - self.win.message_e.setText(qrcode['label']) - if 'message' in qrcode: - self.win.message_e.setText("%s (%s)" % (self.win.message_e.text(), qrcode['message'])) - def video_device(self): device = self.config.get("video_device", "default") if device == 'default': t@@ -195,55 +180,3 @@ class Plugin(BasePlugin): return True else: return False - - - -def parse_uri(uri): - if not uri: - return {} - - if ':' not in uri: - # It's just an address (not BIP21) - return {'address': uri} - - if '//' not in uri: - # Workaround for urlparse, it don't handle bitcoin: URI properly - uri = uri.replace(':', '://') - - uri = urlparse(uri) - result = {'address': uri.netloc} - - if uri.query.startswith('?'): - params = parse_qs(uri.query[1:]) - else: - params = parse_qs(uri.query) - - for k,v in params.items(): - if k in ('amount', 'label', 'message'): - result[k] = v[0] - - return result - - - - - -if __name__ == '__main__': - # Run some tests - - assert(parse_uri('1Marek48fwU7mugmSe186do2QpUkBnpzSN') == - {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'}) - - assert(parse_uri('bitcoin://1Marek48fwU7mugmSe186do2QpUkBnpzSN') == - {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'}) - - assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN') == - {'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'}) - - assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN?amount=10') == - {'amount': '10', 'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'}) - - assert(parse_uri('bitcoin:1Marek48fwU7mugmSe186do2QpUkBnpzSN?amount=10&label=slush&message=Small%20tip%20to%20slush') == - {'amount': '10', 'label': 'slush', 'message': 'Small tip to slush', 'address': '1Marek48fwU7mugmSe186do2QpUkBnpzSN'}) - -