derive plugins from BasePlugin class
[electrum-nvc.git] / plugins / aliases.py
index f8a3a5b..c44df3f 100644 (file)
@@ -15,217 +15,185 @@ from electrum_gui.i18n import _
 ALIAS_REGEXP = '^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$'    
 
 
-config = {}
-
-def get_info():
-    return 'Aliases', _('Retrieve aliases using http.')
-
-def init(self):
-    global config
-    config = self.config
-    self.aliases               = config.get('aliases', {})            # aliases for addresses
-    self.authorities           = config.get('authorities', {})        # trusted addresses
-    self.receipts              = config.get('receipts',{})            # signed URIs
-    do_enable(self, is_enabled())
-
-def is_enabled():
-    return config.get('use_aliases') is True
-
-def is_available():
-    return True
-
-
-def toggle(gui):
-    enabled = not is_enabled()
-    config.set_key('use_aliases', enabled, True)
-    do_enable(gui, enabled)
-    return enabled
-
-
-def do_enable(gui, enabled):
-    if enabled:
-        gui.set_hook('timer_actions', timer_actions)
-        gui.set_hook('set_url', set_url_hook)
-        gui.set_hook('update_contacts_tab', update_contacts_tab_hook)
-        gui.set_hook('update_completions', update_completions_hook)
-        gui.set_hook('create_contact_menu', create_contact_menu_hook)
-    else:
-        gui.unset_hook('timer_actions', timer_actions)
-        gui.unset_hook('set_url', set_url_hook)
-        gui.unset_hook('update_contacts_tab', update_contacts_tab_hook)
-        gui.unset_hook('update_completions', update_completions_hook)
-        gui.unset_hook('create_contact_menu', create_contact_menu_hook)
-
-
-def timer_actions(self):
-    if self.payto_e.hasFocus():
-        return
-    r = unicode( self.payto_e.text() )
-    if r != self.previous_payto_e:
-        self.previous_payto_e = r
-        r = r.strip()
-        if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
-            try:
-                to_address = get_alias(self, r, True, self.show_message, self.question)
-            except:
-                return
-            if to_address:
-                s = r + '  <' + to_address + '>'
-                self.payto_e.setText(s)
-
-
-def get_alias(self, alias, interactive = False, show_message=None, question = None):
-    try:
-        target, signing_address, auth_name = read_alias(self, alias)
-    except BaseException, e:
-        # raise exception if verify fails (verify the chain)
-        if interactive:
-            show_message("Alias error: " + str(e))
-        return
-
-    print target, signing_address, auth_name
-
-    if auth_name is None:
-        a = self.aliases.get(alias)
-        if not a:
-            msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
-            if interactive and question( msg ):
-                self.aliases[alias] = (signing_address, target)
-            else:
-                target = None
-        else:
-            if signing_address != a[0]:
-                msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
+
+from electrum_gui import BasePlugin
+class Plugin(BasePlugin):
+
+    def __init__(self, gui):
+        BasePlugin.__init__(self, gui, 'aliases', 'Aliases', _('Retrieve aliases using http.'))
+        self.aliases      = self.config.get('aliases', {})            # aliases for addresses
+        self.authorities  = self.config.get('authorities', {})        # trusted addresses
+        self.receipts     = self.config.get('receipts',{})            # signed URIs
+
+
+    def timer_actions(self):
+        if self.gui.payto_e.hasFocus():
+            return
+        r = unicode( self.gui.payto_e.text() )
+        if r != self.gui.previous_payto_e:
+            self.gui.previous_payto_e = r
+            r = r.strip()
+            if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', r):
+                try:
+                    to_address = self.get_alias(r, True, self.gui.show_message, self.gui.question)
+                except:
+                    return
+                if to_address:
+                    s = r + '  <' + to_address + '>'
+                    self.gui.payto_e.setText(s)
+
+
+    def get_alias(self, alias, interactive = False, show_message=None, question = None):
+        try:
+            target, signing_address, auth_name = read_alias(self, alias)
+        except BaseException, e:
+            # raise exception if verify fails (verify the chain)
+            if interactive:
+                show_message("Alias error: " + str(e))
+            return
+
+        print target, signing_address, auth_name
+
+        if auth_name is None:
+            a = self.aliases.get(alias)
+            if not a:
+                msg = "Warning: the alias '%s' is self-signed.\nThe signing address is %s.\n\nDo you want to add this alias to your list of contacts?"%(alias,signing_address)
                 if interactive and question( msg ):
                     self.aliases[alias] = (signing_address, target)
                 else:
                     target = None
-    else:
-        if signing_address not in self.authorities.keys():
-            msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
-            if interactive and question( msg ):
-                self.authorities[signing_address] = auth_name
             else:
-                target = None
+                if signing_address != a[0]:
+                    msg = "Warning: the key of alias '%s' has changed since your last visit! It is possible that someone is trying to do something nasty!!!\nDo you accept to change your trusted key?"%alias
+                    if interactive and question( msg ):
+                        self.aliases[alias] = (signing_address, target)
+                    else:
+                        target = None
+        else:
+            if signing_address not in self.authorities.keys():
+                msg = "The alias: '%s' links to %s\n\nWarning: this alias was signed by an unknown key.\nSigning authority: %s\nSigning address: %s\n\nDo you want to add this key to your list of trusted keys?"%(alias,target,auth_name,signing_address)
+                if interactive and question( msg ):
+                    self.authorities[signing_address] = auth_name
+                else:
+                    target = None
 
-    if target:
-        self.aliases[alias] = (signing_address, target)
+        if target:
+            self.aliases[alias] = (signing_address, target)
             
-    return target
-
-
-
-def read_alias(self, alias):
-    import urllib
-
-    m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', alias)
-    m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', alias)
-    if m1:
-        url = 'https://' + m1.group(2) + '/bitcoin.id/' + m1.group(1) 
-    elif m2:
-        url = 'https://' + alias + '/bitcoin.id'
-    else:
-        return ''
-    try:
-        lines = urllib.urlopen(url).readlines()
-    except:
-        return ''
-
-    # line 0
-    line = lines[0].strip().split(':')
-    if len(line) == 1:
-        auth_name = None
-        target = signing_addr = line[0]
-    else:
-        target, auth_name, signing_addr, signature = line
-        msg = "alias:%s:%s:%s"%(alias,target,auth_name)
-        print msg, signature
-        EC_KEY.verify_message(signing_addr, signature, msg)
-        
-    # other lines are signed updates
-    for line in lines[1:]:
-        line = line.strip()
-        if not line: continue
-        line = line.split(':')
-        previous = target
-        print repr(line)
-        target, signature = line
-        EC_KEY.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
-
-    if not is_valid(target):
-        raise ValueError("Invalid bitcoin address")
-
-    return target, signing_addr, auth_name
-
-
-def set_url_hook(self, url, show_message, question):
-    payto, amount, label, message, signature, identity, url = util.parse_url(url)
-    if signature:
-        if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
-            signing_address = get_alias(identity, True, show_message, question)
-        elif is_valid(identity):
-            signing_address = identity
+        return target
+
+
+
+    def read_alias(self, alias):
+        import urllib
+
+        m1 = re.match('([\w\-\.]+)@((\w[\w\-]+\.)+[\w\-]+)', alias)
+        m2 = re.match('((\w[\w\-]+\.)+[\w\-]+)', alias)
+        if m1:
+            url = 'https://' + m1.group(2) + '/bitcoin.id/' + m1.group(1) 
+        elif m2:
+            url = 'https://' + alias + '/bitcoin.id'
         else:
-            signing_address = None
-        if not signing_address:
-            return
+            return ''
         try:
-            EC_KEY.verify_message(signing_address, signature, url )
-            self.receipt = (signing_address, signature, url)
+            lines = urllib.urlopen(url).readlines()
         except:
-            show_message('Warning: the URI contains a bad signature.\nThe identity of the recipient cannot be verified.')
-            address = amount = label = identity = message = ''
+            return ''
 
-    if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', address):
-        payto_address = get_alias(address, True, show_message, question)
-        if payto_address:
-            address = address + ' <' + payto_address + '>'
+        # line 0
+        line = lines[0].strip().split(':')
+        if len(line) == 1:
+            auth_name = None
+            target = signing_addr = line[0]
+        else:
+            target, auth_name, signing_addr, signature = line
+            msg = "alias:%s:%s:%s"%(alias,target,auth_name)
+            print msg, signature
+            EC_KEY.verify_message(signing_addr, signature, msg)
+        
+        # other lines are signed updates
+        for line in lines[1:]:
+            line = line.strip()
+            if not line: continue
+            line = line.split(':')
+            previous = target
+            print repr(line)
+            target, signature = line
+            EC_KEY.verify_message(previous, signature, "alias:%s:%s"%(alias,target))
+
+        if not is_valid(target):
+            raise ValueError("Invalid bitcoin address")
+
+        return target, signing_addr, auth_name
+
+
+    def set_url(self, url, show_message, question):
+        payto, amount, label, message, signature, identity, url = util.parse_url(url)
+        if signature:
+            if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', identity):
+                signing_address = get_alias(identity, True, show_message, question)
+            elif is_valid(identity):
+                signing_address = identity
+            else:
+                signing_address = None
+            if not signing_address:
+                return
+            try:
+                EC_KEY.verify_message(signing_address, signature, url )
+                self.receipt = (signing_address, signature, url)
+            except:
+                show_message('Warning: the URI contains a bad signature.\nThe identity of the recipient cannot be verified.')
+                address = amount = label = identity = message = ''
 
-    return address, amount, label, message, signature, identity, url
+        if re.match('^(|([\w\-\.]+)@)((\w[\w\-]+\.)+[\w\-]+)$', address):
+            payto_address = get_alias(address, True, show_message, question)
+            if payto_address:
+                address = address + ' <' + payto_address + '>'
 
+        return address, amount, label, message, signature, identity, url
 
 
-def update_contacts_tab_hook(self, l):
-    alias_targets = []
-    for alias, v in self.aliases.items():
-        s, target = v
-        alias_targets.append(target)
-        item = QTreeWidgetItem( [ target, alias, '-'] )
-        item.setBackgroundColor(0, QColor('lightgray'))
-        l.insertTopLevelItem(0,item)
-        item.setData(0,32,False)
-        item.setData(0,33,alias + ' <' + target + '>')
 
+    def update_contacts_tab(self, l):
+        alias_targets = []
+        for alias, v in self.aliases.items():
+            s, target = v
+            alias_targets.append(target)
+            item = QTreeWidgetItem( [ target, alias, '-'] )
+            item.setBackgroundColor(0, QColor('lightgray'))
+            item.setData(0,32,False)
+            item.setData(0,33,alias + ' <' + target + '>')
+            l.insertTopLevelItem(0,item)
 
 
-def update_completions_hook(self, l):
-    l[:] = l + self.aliases.keys()
+    def update_completions(self, l):
+        l[:] = l + self.aliases.keys()
 
 
-def create_contact_menu_hook(self, menu, item):
-    label = unicode(item.text(1))
-    if label in self.aliases.keys():
-        addr = unicode(item.text(0))
+    def create_contact_menu(self, menu, item):
         label = unicode(item.text(1))
-        menu.addAction(_("View alias details"), lambda: show_contact_details(self, label))
-        menu.addAction(_("Delete alias"), lambda: delete_alias(self, label))
-
-
-def show_contact_details(self, m):
-    a = self.aliases.get(m)
-    if a:
-        if a[0] in self.authorities.keys():
-            s = self.authorities.get(a[0])
-        else:
-            s = "self-signed"
-        msg = _('Alias:')+' '+ m + '\n'+_('Target address:')+' '+ a[1] + '\n\n'+_('Signed by:')+' ' + s + '\n'+_('Signing address:')+' ' + a[0]
-        QMessageBox.information(self, 'Alias', msg, 'OK')
-
-
-def delete_alias(self, x):
-    if self.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")):
-        if x in self.aliases:
-            self.aliases.pop(x)
-            self.update_history_tab()
-            self.update_contacts_tab()
-            self.update_completions()
+        if label in self.aliases.keys():
+            addr = unicode(item.text(0))
+            label = unicode(item.text(1))
+            menu.addAction(_("View alias details"), lambda: self.show_contact_details(label))
+            menu.addAction(_("Delete alias"), lambda: delete_alias(self, label))
+
+
+    def show_contact_details(self, m):
+        a = self.aliases.get(m)
+        if a:
+            if a[0] in self.authorities.keys():
+                s = self.authorities.get(a[0])
+            else:
+                s = "self-signed"
+            msg = _('Alias:')+' '+ m + '\n'+_('Target address:')+' '+ a[1] + '\n\n'+_('Signed by:')+' ' + s + '\n'+_('Signing address:')+' ' + a[0]
+            QMessageBox.information(self.gui, 'Alias', msg, 'OK')
+
+
+    def delete_alias(self, x):
+        if self.gui.question(_("Do you want to remove")+" %s "%x +_("from your list of contacts?")):
+            if x in self.aliases:
+                self.aliases.pop(x)
+                self.update_history_tab()
+                self.update_contacts_tab()
+                self.update_completions()