Repository: Bitmessage/PyBitmessage

Issue:
own addresses cannot be added to addressbook
here when I tried adding my own address to address book,it adds that without any error and I think it should not be like that.


Discussion:
here when I am trying to save my own address to the address book then it is saving it but it should not happen so have tried to
put one more validation method in shared.py module for checking that the entered address is the user own address or not 
![image](https://user-images.githubusercontent.com/33522186/92461633-2218a000-f1e7-11ea-8eb1-31194f1d51b2.png)

and I have put the check-in bitmessageqt/init.py module now it is fixed and the user can not able to save his own address in the address book
![image](https://user-images.githubusercontent.com/33522186/92461771-45dbe600-f1e7-11ea-8679-21e33fe0c1df.png)


Resolving patch:
diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py
--- a/src/bitmessageqt/__init__.py
+++ b/src/bitmessageqt/__init__.py
@@ -36,6 +36,7 @@
 import settingsmixin
 import support
 from helper_sql import sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure
+import helper_addressbook
 import helper_search
 import l10n
 from utils import str_broadcast_subscribers, avatarize
@@ -2435,15 +2436,15 @@ def click_pushButtonAddAddressBook(self, dialog=None):
             ))
             return
 
-        self.addEntryToAddressBook(address, label)
-
-    def addEntryToAddressBook(self, address, label):
-        if shared.isAddressInMyAddressBook(address):
-            return
-        sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', label, address)
-        self.rerenderMessagelistFromLabels()
-        self.rerenderMessagelistToLabels()
-        self.rerenderAddressBook()
+        if helper_addressbook.insert(label=label, address=address):
+            self.rerenderMessagelistFromLabels()
+            self.rerenderMessagelistToLabels()
+            self.rerenderAddressBook()
+        else:
+            self.updateStatusBar(_translate(
+                "MainWindow",
+                "Error: You cannot add your own address in the address book."
+            ))
 
     def addSubscription(self, address, label):
         # This should be handled outside of this function, for error displaying
diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py
--- a/src/class_sqlThread.py
+++ b/src/class_sqlThread.py
@@ -47,7 +47,7 @@ def run(self):  # pylint: disable=too-many-locals, too-many-branches, too-many-s
             self.cur.execute(
                 '''CREATE TABLE subscriptions (label text, address text, enabled bool)''')
             self.cur.execute(
-                '''CREATE TABLE addressbook (label text, address text)''')
+                '''CREATE TABLE addressbook (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''')
             self.cur.execute(
                 '''CREATE TABLE blacklist (label text, address text, enabled bool)''')
             self.cur.execute(
@@ -63,7 +63,7 @@ def run(self):  # pylint: disable=too-many-locals, too-many-branches, too-many-s
                 '''('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)''')
             self.cur.execute(
                 '''CREATE TABLE settings (key blob, value blob, UNIQUE(key) ON CONFLICT REPLACE)''')
-            self.cur.execute('''INSERT INTO settings VALUES('version','10')''')
+            self.cur.execute('''INSERT INTO settings VALUES('version','11')''')
             self.cur.execute('''INSERT INTO settings VALUES('lastvacuumtime',?)''', (
                 int(time.time()),))
             self.cur.execute(
@@ -390,6 +390,25 @@ def run(self):  # pylint: disable=too-many-locals, too-many-branches, too-many-s
                 ' and removing the hash field.')
             self.cur.execute('''update settings set value=10 WHERE key='version';''')
 
+        # Update the address colunm to unique in addressbook table
+        item = '''SELECT value FROM settings WHERE key='version';'''
+        parameters = ''
+        self.cur.execute(item, parameters)
+        currentVersion = int(self.cur.fetchall()[0][0])
+        if currentVersion == 10:
+            logger.debug(
+                'In messages.dat database, updating address column to UNIQUE'
+                ' in the addressbook table.')
+            self.cur.execute(
+                '''ALTER TABLE addressbook RENAME TO old_addressbook''')
+            self.cur.execute(
+                '''CREATE TABLE addressbook'''
+                ''' (label text, address text, UNIQUE(address) ON CONFLICT IGNORE)''')
+            self.cur.execute(
+                '''INSERT INTO addressbook SELECT label, address FROM old_addressbook;''')
+            self.cur.execute('''DROP TABLE old_addressbook''')
+            self.cur.execute('''update settings set value=11 WHERE key='version';''')
+
         # Are you hoping to add a new option to the keys.dat file of existing
         # Bitmessage users or modify the SQLite database? Add it right
         # above this line!
diff --git a/src/helper_addressbook.py b/src/helper_addressbook.py
new file mode 100644
--- /dev/null
+++ b/src/helper_addressbook.py
@@ -0,0 +1,14 @@
+"""
+Insert value into addressbook
+"""
+
+from bmconfigparser import BMConfigParser
+from helper_sql import sqlExecute
+
+
+def insert(address, label):
+    """perform insert into addressbook"""
+
+    if address not in BMConfigParser().addresses():
+        return sqlExecute('''INSERT INTO addressbook VALUES (?,?)''', label, address) == 1
+    return False


Test patch:
diff --git a/src/tests/core.py b/src/tests/core.py
--- a/src/tests/core.py
+++ b/src/tests/core.py
@@ -16,6 +16,7 @@
 import protocol
 import state
 import helper_sent
+import helper_addressbook
 
 from bmconfigparser import BMConfigParser
 from helper_msgcoding import MsgEncode, MsgDecode
@@ -57,6 +58,7 @@ def pickle_knownnodes():
 
 class TestCore(unittest.TestCase):
     """Test case, which runs in main pybitmessage thread"""
+    addr = 'BM-2cVvkzJuQDsQHLqxRXc6HZGPLZnkBLzEZY'
 
     def test_msgcoding(self):
         """test encoding and decoding (originally from helper_msgcoding)"""
@@ -251,7 +253,7 @@ def test_insert_method_msgid(self):
         subject = 'test subject'
         result = helper_sent.insert(
             toAddress=toAddress, fromAddress=fromAddress,
-            subject=subject, message=message,
+            subject=subject, message=message
         )
         queryreturn = sqlQuery(
             '''select msgid from sent where ackdata=?''', result)
@@ -274,6 +276,42 @@ def test_old_knownnodes_pickle(self):
         finally:
             cleanup(files=('knownnodes.dat',))
 
+    @staticmethod
+    def delete_address_from_addressbook(address):
+        """Clean up addressbook"""
+        sqlQuery('''delete from addressbook where address=?''', address)
+
+    def test_add_same_address_twice_in_addressbook(self):
+        """checking same address is added twice in addressbook"""
+        self.assertTrue(helper_addressbook.insert(label='test1', address=self.addr))
+        self.assertFalse(helper_addressbook.insert(label='test1', address=self.addr))
+        self.delete_address_from_addressbook(self.addr)
+
+    def test_is_address_present_in_addressbook(self):
+        """checking is address added in addressbook or not"""
+        helper_addressbook.insert(label='test1', address=self.addr)
+        queryreturn = sqlQuery('''select count(*) from addressbook where address=?''', self.addr)
+        self.assertEqual(queryreturn[0][0], 1)
+        self.delete_address_from_addressbook(self.addr)
+
+    def test_is_own_address_add_to_addressbook(self):
+        """Checking own address adding in addressbook"""
+        from helper_addressGenerator import createAddressIfNeeded
+        try:
+            address = createAddressIfNeeded('test1')
+            self.assertFalse(helper_addressbook.insert(label='test', address=address))
+        except IndexError:
+            self.fail("Can't generate addresses")
+
+    def test_adding_two_same_case_sensitive_addresses(self):
+        """Testing same case sensitive address store in addressbook"""
+        address1 = 'BM-2cVWtdUzPwF7UNGDrZftWuHWiJ6xxBpiSP'
+        address2 = 'BM-2CvwTDuZpWf7ungdRzFTwUhwIj6XXbPIsp'
+        self.assertTrue(helper_addressbook.insert(label='test1', address=address1))
+        self.assertTrue(helper_addressbook.insert(label='test2', address=address2))
+        self.delete_address_from_addressbook(address1)
+        self.delete_address_from_addressbook(address2)
+
 
 def run():
     """Starts all tests defined in this module"""