From 027440a212a60bc5ecd3c4330c238435d3d97d87 Mon Sep 17 00:00:00 2001 From: Dmitri Bogomolov <4glitch@gmail.com> Date: Sat, 3 Mar 2018 17:31:49 +0200 Subject: [PATCH] Sorted out configuration loading/updating a bit: - used BMConfigParser.safeGet.. methods instead of try .. except - moved all config checks from class_sqlThread into helper_startup - commented out initialization of settings which are then rewritten by updateConfig() --- src/bitmessageqt/account.py | 4 +- src/bitmessageqt/languagebox.py | 11 +- src/bitmessageqt/support.py | 16 +- src/bitmessageqt/utils.py | 26 +-- src/class_sqlThread.py | 220 +++++++----------------- src/helper_startup.py | 293 ++++++++++++++++++++++++++------ 6 files changed, 333 insertions(+), 237 deletions(-) diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py index ad745f41..7f4222be 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -117,9 +117,7 @@ class BMAccount(object): def getLabel(self, address=None): if address is None: address = self.address - label = address - if BMConfigParser().has_section(address): - label = BMConfigParser().get(address, 'label') + label = BMConfigParser().safeGet(address, 'label', address) queryreturn = sqlQuery( '''select label from addressbook where address=?''', address) if queryreturn != []: diff --git a/src/bitmessageqt/languagebox.py b/src/bitmessageqt/languagebox.py index 1b8d4942..4226fad7 100644 --- a/src/bitmessageqt/languagebox.py +++ b/src/bitmessageqt/languagebox.py @@ -19,20 +19,15 @@ class LanguageBox(QtWidgets.QComboBox): self.populate() def populate(self): - self.languages = [] self.clear() - localesPath = os.path.join(paths.codePath(), 'translations') - try: - configuredLocale = BMConfigParser().get( - 'bitmessagesettings', 'userlocale', "system") - except: - configuredLocale = "system" self.addItem( _translate("settingsDialog", "System Settings", "system"), "system" ) self.setCurrentIndex(0) self.setInsertPolicy(QtWidgets.QComboBox.InsertAlphabetically) + + localesPath = os.path.join(paths.codePath(), 'translations') for translationFile in sorted( glob.glob(os.path.join(localesPath, "bitmessage_*.qm")) ): @@ -45,6 +40,8 @@ class LanguageBox(QtWidgets.QComboBox): locale = QtCore.QLocale(localeShort) self.addItem( locale.nativeLanguageName() or localeShort, localeShort) + configuredLocale = BMConfigParser().safeGet( + 'bitmessagesettings', 'userlocale', "system") for i in range(self.count()): if self.itemData(i) == configuredLocale: self.setCurrentIndex(i) diff --git a/src/bitmessageqt/support.py b/src/bitmessageqt/support.py index c4ab0c55..d97d03b5 100644 --- a/src/bitmessageqt/support.py +++ b/src/bitmessageqt/support.py @@ -5,7 +5,6 @@ import os import time import account -from qtpy import QtCore from tr import _translate from bmconfigparser import BMConfigParser import defaults @@ -135,16 +134,13 @@ def createSupportMessage(myapp): portablemode = "True" \ if state.appdata == paths.lookupExeFolder() else "False" cpow = "True" if proofofwork.bmpow else "False" - openclpow = str(BMConfigParser().safeGet('bitmessagesettings', 'opencl')) if openclEnabled() else "None" + openclpow = str( + BMConfigParser().safeGet('bitmessagesettings', 'opencl') + ) if openclEnabled() else "None" locale = getTranslationLanguage() - try: - socks = BMConfigParser().get('bitmessagesettings', 'socksproxytype') - except: - socks = "N/A" - try: - upnp = BMConfigParser().get('bitmessagesettings', 'upnp') - except: - upnp = "N/A" + socks = BMConfigParser().safeGet( + 'bitmessagesettings', 'socksproxytype', "N/A") + upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', "N/A") connectedhosts = len(network.stats.connectedHostsList()) myapp.ui.textEditMessage.setText( diff --git a/src/bitmessageqt/utils.py b/src/bitmessageqt/utils.py index f29ec8b5..67962c60 100644 --- a/src/bitmessageqt/utils.py +++ b/src/bitmessageqt/utils.py @@ -12,26 +12,26 @@ str_chan = '[chan]' def identiconize(address): size = 48 + if not BMConfigParser().getboolean('bitmessagesettings', 'useidenticons'): + return QtGui.QIcon() + # else: + # print("useidenticons = True") + # If you include another identicon library, please generate an # example identicon with the following md5 hash: # 3fd4bf901b9d4ea1394f0fb358725b28 - try: - identicon_lib = BMConfigParser().get( - 'bitmessagesettings', 'identiconlib') - except: - # default to qidenticon_two_x - identicon_lib = 'qidenticon_two_x' + identicon_lib = BMConfigParser().safeGet( + 'bitmessagesettings', 'identiconlib', 'qidenticon_two_x') - # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" to make it compatible with other identicon generators. (Note however, that E-Mail programs might convert the BM-address to lowercase first.) - # It can be used as a pseudo-password to salt the generation of the identicons to decrease the risk - # of attacks where someone creates an address to mimic someone else's identicon. + # As an 'identiconsuffix' you could put "@bitmessge.ch" or "@bm.addr" + # to make it compatible with other identicon generators. (Note however, + # that E-Mail programs might convert the BM-address to lowercase first.) + # It can be used as a pseudo-password to salt the generation of + # the identicons to decrease the risk of attacks where someone creates + # an address to mimic someone else's identicon. identiconsuffix = BMConfigParser().get('bitmessagesettings', 'identiconsuffix') - if not BMConfigParser().getboolean('bitmessagesettings', 'useidenticons'): - idcon = QtGui.QIcon() - return idcon - if (identicon_lib[:len('qidenticon')] == 'qidenticon'): # print identicon_lib # originally by: diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index a774a24b..d1e9465f 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -6,16 +6,13 @@ import shutil # used for moving the messages.dat file import sys import os from debug import logger -import defaults import helper_sql -from namecoin import ensureNamecoinOptions +import helper_startup import paths import queues -import random import state -import string -import tr#anslate -import helper_random +import tr + # This thread exists because SQLITE3 is so un-threadsafe that we must # submit queries to it and it puts results back in a different queue. They # won't let us just use locks. @@ -26,11 +23,11 @@ class sqlThread(threading.Thread): def __init__(self): threading.Thread.__init__(self, name="SQL") - def run(self): + def run(self): self.conn = sqlite3.connect(state.appdata + 'messages.dat') self.conn.text_factory = str self.cur = self.conn.cursor() - + self.cur.execute('PRAGMA secure_delete = true') try: @@ -70,35 +67,26 @@ class sqlThread(threading.Thread): 'ERROR trying to create database file (message.dat). Error message: %s\n' % str(err)) os._exit(0) - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 1: - BMConfigParser().set('bitmessagesettings', 'settingsversion', '2') - # If the settings version is equal to 2 or 3 then the - # sqlThread will modify the pubkeys table and change - # the settings version to 4. - BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none') - BMConfigParser().set('bitmessagesettings', 'sockshostname', 'localhost') - BMConfigParser().set('bitmessagesettings', 'socksport', '9050') - BMConfigParser().set('bitmessagesettings', 'socksauthentication', 'false') - BMConfigParser().set('bitmessagesettings', 'socksusername', '') - BMConfigParser().set('bitmessagesettings', 'sockspassword', '') - BMConfigParser().set('bitmessagesettings', 'sockslisten', 'false') - BMConfigParser().set('bitmessagesettings', 'keysencrypted', 'false') - BMConfigParser().set('bitmessagesettings', 'messagesencrypted', 'false') + # If the settings version is equal to 2 or 3 then the + # sqlThread will modify the pubkeys table and change + # the settings version to 4. + settingsversion = BMConfigParser().getint( + 'bitmessagesettings', 'settingsversion') # People running earlier versions of PyBitmessage do not have the # usedpersonally field in their pubkeys table. Let's add it. - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 2: + if settingsversion == 2: item = '''ALTER TABLE pubkeys ADD usedpersonally text DEFAULT 'no' ''' parameters = '' self.cur.execute(item, parameters) self.conn.commit() - BMConfigParser().set('bitmessagesettings', 'settingsversion', '3') + settingsversion = 3 # People running earlier versions of PyBitmessage do not have the # encodingtype field in their inbox and sent tables or the read field # in the inbox table. Let's add them. - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 3: + if settingsversion == 3: item = '''ALTER TABLE inbox ADD encodingtype int DEFAULT '2' ''' parameters = '' self.cur.execute(item, parameters) @@ -112,21 +100,13 @@ class sqlThread(threading.Thread): self.cur.execute(item, parameters) self.conn.commit() - BMConfigParser().set('bitmessagesettings', 'settingsversion', '4') + settingsversion = 4 - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 4: - BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str( - defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) - BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str( - defaults.networkDefaultPayloadLengthExtraBytes)) - BMConfigParser().set('bitmessagesettings', 'settingsversion', '5') + BMConfigParser().set( + 'bitmessagesettings', 'settingsversion', str(settingsversion)) + BMConfigParser().save() - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 5: - BMConfigParser().set( - 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') - BMConfigParser().set( - 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') - BMConfigParser().set('bitmessagesettings', 'settingsversion', '6') + helper_startup.updateConfig() # From now on, let us keep a 'version' embedded in the messages.dat # file so that when we make changes to the database, the database @@ -137,7 +117,8 @@ class sqlThread(threading.Thread): self.cur.execute(item, parameters) if self.cur.fetchall() == []: # The settings table doesn't exist. We need to make it. - logger.debug('In messages.dat database, creating new \'settings\' table.') + logger.debug( + "In messages.dat database, creating new 'settings' table.") self.cur.execute( '''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)''' ) self.cur.execute( '''INSERT INTO settings VALUES('version','1')''') @@ -178,12 +159,7 @@ class sqlThread(threading.Thread): self.cur.execute( '''update sent set status='broadcastqueued' where status='broadcastpending' ''') self.conn.commit() - - if not BMConfigParser().has_option('bitmessagesettings', 'sockslisten'): - BMConfigParser().set('bitmessagesettings', 'sockslisten', 'false') - - ensureNamecoinOptions() - + """# Add a new column to the inventory table to store the first 20 bytes of encrypted messages to support Android app item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' @@ -197,12 +173,15 @@ class sqlThread(threading.Thread): parameters = (2,) self.cur.execute(item, parameters)""" - # Let's get rid of the first20bytesofencryptedmessage field in the inventory table. + # Let's get rid of the first20bytesofencryptedmessage field in + # the inventory table. item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' self.cur.execute(item, parameters) if int(self.cur.fetchall()[0][0]) == 2: - logger.debug('In messages.dat database, removing an obsolete field from the inventory table.') + logger.debug( + 'In messages.dat database, removing an obsolete field from' + ' the inventory table.') self.cur.execute( '''CREATE TEMPORARY TABLE inventory_backup(hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE);''') self.cur.execute( @@ -223,7 +202,9 @@ class sqlThread(threading.Thread): self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 1 or currentVersion == 3: - logger.debug('In messages.dat database, adding tag field to the inventory table.') + logger.debug( + 'In messages.dat database, adding tag field to' + ' the inventory table.') item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' ''' parameters = '' self.cur.execute(item, parameters) @@ -231,19 +212,6 @@ class sqlThread(threading.Thread): parameters = (4,) self.cur.execute(item, parameters) - if not BMConfigParser().has_option('bitmessagesettings', 'userlocale'): - BMConfigParser().set('bitmessagesettings', 'userlocale', 'system') - if not BMConfigParser().has_option('bitmessagesettings', 'sendoutgoingconnections'): - BMConfigParser().set('bitmessagesettings', 'sendoutgoingconnections', 'True') - - # Raise the default required difficulty from 1 to 2 - # With the change to protocol v3, this is obsolete. - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 6: - """if int(shared.config.get('bitmessagesettings','defaultnoncetrialsperbyte')) == defaults.networkDefaultProofOfWorkNonceTrialsPerByte: - shared.config.set('bitmessagesettings','defaultnoncetrialsperbyte', str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte * 2)) - """ - BMConfigParser().set('bitmessagesettings', 'settingsversion', '7') - # Add a new column to the pubkeys table to store the address version. # We're going to trash all of our pubkeys and let them be redownloaded. item = '''SELECT value FROM settings WHERE key='version';''' @@ -251,27 +219,14 @@ class sqlThread(threading.Thread): self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 4: - self.cur.execute( '''DROP TABLE pubkeys''') + self.cur.execute('''DROP TABLE pubkeys''') self.cur.execute( - '''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''' ) + '''CREATE TABLE pubkeys (hash blob, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(hash, addressversion) ON CONFLICT REPLACE)''') self.cur.execute( '''delete from inventory where objecttype = 'pubkey';''') item = '''update settings set value=? WHERE key='version';''' parameters = (5,) self.cur.execute(item, parameters) - - if not BMConfigParser().has_option('bitmessagesettings', 'useidenticons'): - BMConfigParser().set('bitmessagesettings', 'useidenticons', 'True') - if not BMConfigParser().has_option('bitmessagesettings', 'identiconsuffix'): # acts as a salt - BMConfigParser().set('bitmessagesettings', 'identiconsuffix', ''.join(helper_random.randomchoice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") for x in range(12)))# a twelve character pseudo-password to salt the identicons - - #Add settings to support no longer resending messages after a certain period of time even if we never get an ack - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 7: - BMConfigParser().set( - 'bitmessagesettings', 'stopresendingafterxdays', '') - BMConfigParser().set( - 'bitmessagesettings', 'stopresendingafterxmonths', '') - BMConfigParser().set('bitmessagesettings', 'settingsversion', '8') # Add a new table: objectprocessorqueue with which to hold objects # that have yet to be processed if the user shuts down Bitmessage. @@ -280,21 +235,24 @@ class sqlThread(threading.Thread): self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 5: - self.cur.execute( '''DROP TABLE knownnodes''') + self.cur.execute('''DROP TABLE knownnodes''') self.cur.execute( - '''CREATE TABLE objectprocessorqueue (objecttype text, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''' ) + '''CREATE TABLE objectprocessorqueue (objecttype text, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)''') item = '''update settings set value=? WHERE key='version';''' parameters = (6,) self.cur.execute(item, parameters) - + # changes related to protocol v3 - # In table inventory and objectprocessorqueue, objecttype is now an integer (it was a human-friendly string previously) + # In table inventory and objectprocessorqueue, objecttype is now + # an integer (it was a human-friendly string previously) item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 6: - logger.debug('In messages.dat database, dropping and recreating the inventory table.') + logger.debug( + 'In messages.dat database, dropping and recreating' + ' the inventory table.') self.cur.execute( '''DROP TABLE inventory''') self.cur.execute( '''CREATE TABLE inventory (hash blob, objecttype int, streamnumber int, payload blob, expirestime integer, tag blob, UNIQUE(hash) ON CONFLICT REPLACE)''' ) self.cur.execute( '''DROP TABLE objectprocessorqueue''') @@ -302,57 +260,26 @@ class sqlThread(threading.Thread): item = '''update settings set value=? WHERE key='version';''' parameters = (7,) self.cur.execute(item, parameters) - logger.debug('Finished dropping and recreating the inventory table.') - - # With the change to protocol version 3, reset the user-settable difficulties to 1 - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 8: - BMConfigParser().set('bitmessagesettings','defaultnoncetrialsperbyte', str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) - BMConfigParser().set('bitmessagesettings','defaultpayloadlengthextrabytes', str(defaults.networkDefaultPayloadLengthExtraBytes)) - previousTotalDifficulty = int(BMConfigParser().getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte')) / 320 - previousSmallMessageDifficulty = int(BMConfigParser().getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / 14000 - BMConfigParser().set('bitmessagesettings','maxacceptablenoncetrialsperbyte', str(previousTotalDifficulty * 1000)) - BMConfigParser().set('bitmessagesettings','maxacceptablepayloadlengthextrabytes', str(previousSmallMessageDifficulty * 1000)) - BMConfigParser().set('bitmessagesettings', 'settingsversion', '9') - - # Adjust the required POW values for each of this user's addresses to conform to protocol v3 norms. - if BMConfigParser().getint('bitmessagesettings', 'settingsversion') == 9: - for addressInKeysFile in BMConfigParser().addressses(): - try: - previousTotalDifficulty = float(BMConfigParser().getint(addressInKeysFile, 'noncetrialsperbyte')) / 320 - previousSmallMessageDifficulty = float(BMConfigParser().getint(addressInKeysFile, 'payloadlengthextrabytes')) / 14000 - if previousTotalDifficulty <= 2: - previousTotalDifficulty = 1 - if previousSmallMessageDifficulty < 1: - previousSmallMessageDifficulty = 1 - BMConfigParser().set(addressInKeysFile,'noncetrialsperbyte', str(int(previousTotalDifficulty * 1000))) - BMConfigParser().set(addressInKeysFile,'payloadlengthextrabytes', str(int(previousSmallMessageDifficulty * 1000))) - except: - continue - BMConfigParser().set('bitmessagesettings', 'maxdownloadrate', '0') - BMConfigParser().set('bitmessagesettings', 'maxuploadrate', '0') - BMConfigParser().set('bitmessagesettings', 'settingsversion', '10') - BMConfigParser().save() - - # sanity check - if BMConfigParser().getint('bitmessagesettings', 'maxacceptablenoncetrialsperbyte') == 0: - BMConfigParser().set('bitmessagesettings','maxacceptablenoncetrialsperbyte', str(defaults.ridiculousDifficulty * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) - if BMConfigParser().getint('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') == 0: - BMConfigParser().set('bitmessagesettings','maxacceptablepayloadlengthextrabytes', str(defaults.ridiculousDifficulty * defaults.networkDefaultPayloadLengthExtraBytes)) + logger.debug( + 'Finished dropping and recreating the inventory table.') # The format of data stored in the pubkeys table has changed. Let's - # clear it, and the pubkeys from inventory, so that they'll be re-downloaded. + # clear it, and the pubkeys from inventory, so that they'll + # be re-downloaded. item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 7: - logger.debug('In messages.dat database, clearing pubkeys table because the data format has been updated.') + logger.debug( + 'In messages.dat database, clearing pubkeys table' + ' because the data format has been updated.') self.cur.execute( '''delete from inventory where objecttype = 1;''') self.cur.execute( '''delete from pubkeys;''') - # Any sending messages for which we *thought* that we had the pubkey must - # be rechecked. + # Any sending messages for which we *thought* that we had + # the pubkey must be rechecked. self.cur.execute( '''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';''') query = '''update settings set value=? WHERE key='version';''' @@ -360,32 +287,36 @@ class sqlThread(threading.Thread): self.cur.execute(query, parameters) logger.debug('Finished clearing currently held pubkeys.') - # Add a new column to the inbox table to store the hash of the message signature. - # We'll use this as temporary message UUID in order to detect duplicates. + # Add a new column to the inbox table to store the hash of + # the message signature. We'll use this as temporary message UUID + # in order to detect duplicates. item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 8: - logger.debug('In messages.dat database, adding sighash field to the inbox table.') + logger.debug( + 'In messages.dat database, adding sighash field to' + ' the inbox table.') item = '''ALTER TABLE inbox ADD sighash blob DEFAULT '' ''' parameters = '' self.cur.execute(item, parameters) item = '''update settings set value=? WHERE key='version';''' parameters = (9,) self.cur.execute(item, parameters) - - # TTL is now user-specifiable. Let's add an option to save whatever the user selects. - if not BMConfigParser().has_option('bitmessagesettings', 'ttl'): - BMConfigParser().set('bitmessagesettings', 'ttl', '367200') - # We'll also need a `sleeptill` field and a `ttl` field. Also we can combine - # the pubkeyretrynumber and msgretrynumber into one. + + # We'll also need a `sleeptill` field and a `ttl` field. Also we + # can combine the pubkeyretrynumber and msgretrynumber into one. item = '''SELECT value FROM settings WHERE key='version';''' parameters = '' self.cur.execute(item, parameters) currentVersion = int(self.cur.fetchall()[0][0]) if currentVersion == 9: - logger.info('In messages.dat database, making TTL-related changes: combining the pubkeyretrynumber and msgretrynumber fields into the retrynumber field and adding the sleeptill and ttl fields...') + logger.info( + 'In messages.dat database, making TTL-related changes:' + ' combining the pubkeyretrynumber and msgretrynumber' + ' fields into the retrynumber field and adding the' + ' sleeptill and ttl fields...') self.cur.execute( '''CREATE TEMPORARY TABLE sent_backup (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, lastactiontime integer, status text, retrynumber integer, folder text, encodingtype int)''' ) self.cur.execute( @@ -423,32 +354,11 @@ class sqlThread(threading.Thread): self.cur.execute( '''DROP TABLE pubkeys_backup''') logger.debug('In messages.dat database, done adding address field to the pubkeys table and removing the hash field.') self.cur.execute('''update settings set value=10 WHERE key='version';''') - - if not BMConfigParser().has_option('bitmessagesettings', 'onionhostname'): - BMConfigParser().set('bitmessagesettings', 'onionhostname', '') - if not BMConfigParser().has_option('bitmessagesettings', 'onionport'): - BMConfigParser().set('bitmessagesettings', 'onionport', '8444') - if not BMConfigParser().has_option('bitmessagesettings', 'onionbindip'): - BMConfigParser().set('bitmessagesettings', 'onionbindip', '127.0.0.1') - if not BMConfigParser().has_option('bitmessagesettings', 'smtpdeliver'): - BMConfigParser().set('bitmessagesettings', 'smtpdeliver', '') - if not BMConfigParser().has_option('bitmessagesettings', 'hidetrayconnectionnotifications'): - BMConfigParser().set('bitmessagesettings', 'hidetrayconnectionnotifications', 'false') - if BMConfigParser().has_option('bitmessagesettings', 'maxoutboundconnections'): - try: - if BMConfigParser().getint('bitmessagesettings', 'maxoutboundconnections') < 1: raise ValueError - except ValueError as err: - BMConfigParser().remove_option('bitmessagesettings', 'maxoutboundconnections') - logger.error('Your maximum outbound connections must be a number.') - if not BMConfigParser().has_option('bitmessagesettings', 'maxoutboundconnections'): - logger.info('Setting maximum outbound connections to 8.') - BMConfigParser().set('bitmessagesettings', 'maxoutboundconnections', '8') - BMConfigParser().save() - # 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! - + # Bitmessage users or modify the SQLite database? Add it right + # above this line! + try: testpayload = '\x00\x00' t = ('1234', 1, testpayload, '12345678', 'no') diff --git a/src/helper_startup.py b/src/helper_startup.py index c18c1a88..0f0e42b5 100644 --- a/src/helper_startup.py +++ b/src/helper_startup.py @@ -3,9 +3,6 @@ from bmconfigparser import BMConfigParser import defaults import sys import os -import locale -import random -import string import platform from distutils.version import StrictVersion @@ -14,7 +11,10 @@ import paths import state import helper_random -storeConfigFilesInSameDirectoryAsProgramByDefault = False # The user may de-select Portable Mode in the settings if they want the config files to stay in the application data folder. +# The user may de-select Portable Mode in the settings if they want +# the config files to stay in the application data folder. +storeConfigFilesInSameDirectoryAsProgramByDefault = False + def _loadTrustedPeer(): try: @@ -27,17 +27,17 @@ def _loadTrustedPeer(): host, port = trustedPeer.split(':') state.trustedPeer = state.Peer(host, int(port)) + def loadConfig(): if state.appdata: BMConfigParser().read(state.appdata + 'keys.dat') - #state.appdata must have been specified as a startup option. - try: - BMConfigParser().get('bitmessagesettings', 'settingsversion') - print 'Loading config files from directory specified on startup: ' + state.appdata - needToCreateKeysFile = False - except: - needToCreateKeysFile = True - + # state.appdata must have been specified as a startup option. + needToCreateKeysFile = BMConfigParser().safeGet( + 'bitmessagesettings', 'settingsversion') is None + if not needToCreateKeysFile: + print( + 'Loading config files from directory specified' + ' on startup: %s' % state.appdata) else: BMConfigParser().read(paths.lookupExeFolder() + 'keys.dat') try: @@ -46,18 +46,17 @@ def loadConfig(): needToCreateKeysFile = False state.appdata = paths.lookupExeFolder() except: - # Could not load the keys.dat file in the program directory. Perhaps it - # is in the appdata directory. + # Could not load the keys.dat file in the program directory. + # Perhaps it is in the appdata directory. state.appdata = paths.lookupAppdataFolder() BMConfigParser().read(state.appdata + 'keys.dat') - try: - BMConfigParser().get('bitmessagesettings', 'settingsversion') + needToCreateKeysFile = BMConfigParser().safeGet( + 'bitmessagesettings', 'settingsversion') is None + if not needToCreateKeysFile: print 'Loading existing config files from', state.appdata - needToCreateKeysFile = False - except: - needToCreateKeysFile = True if needToCreateKeysFile: + # This appears to be the first time running the program; there is # no config file (or it cannot be accessed). Create config file. BMConfigParser().add_section('bitmessagesettings') @@ -70,9 +69,9 @@ def loadConfig(): if 'linux' in sys.platform: BMConfigParser().set( 'bitmessagesettings', 'minimizetotray', 'false') - # This isn't implimented yet and when True on - # Ubuntu causes Bitmessage to disappear while - # running when minimized. + # This isn't implimented yet and when True on + # Ubuntu causes Bitmessage to disappear while + # running when minimized. else: BMConfigParser().set( 'bitmessagesettings', 'minimizetotray', 'true') @@ -85,48 +84,56 @@ def loadConfig(): BMConfigParser().set('bitmessagesettings', 'socksport', '9050') BMConfigParser().set( 'bitmessagesettings', 'socksauthentication', 'false') - BMConfigParser().set( - 'bitmessagesettings', 'sockslisten', 'false') + # BMConfigParser().set( + # 'bitmessagesettings', 'sockslisten', 'false') BMConfigParser().set('bitmessagesettings', 'socksusername', '') BMConfigParser().set('bitmessagesettings', 'sockspassword', '') BMConfigParser().set('bitmessagesettings', 'keysencrypted', 'false') BMConfigParser().set( 'bitmessagesettings', 'messagesencrypted', 'false') - BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str( - defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) - BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str( - defaults.networkDefaultPayloadLengthExtraBytes)) + BMConfigParser().set( + 'bitmessagesettings', 'defaultnoncetrialsperbyte', + str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) + BMConfigParser().set( + 'bitmessagesettings', 'defaultpayloadlengthextrabytes', + str(defaults.networkDefaultPayloadLengthExtraBytes)) BMConfigParser().set('bitmessagesettings', 'minimizeonclose', 'false') - BMConfigParser().set( - 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') - BMConfigParser().set( - 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') + # BMConfigParser().set( + # 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') + # BMConfigParser().set( + # 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', + # '0') BMConfigParser().set('bitmessagesettings', 'dontconnect', 'true') - BMConfigParser().set('bitmessagesettings', 'userlocale', 'system') - BMConfigParser().set('bitmessagesettings', 'useidenticons', 'True') - BMConfigParser().set('bitmessagesettings', 'identiconsuffix', ''.join(helper_random.randomchoice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") for x in range(12)))# a twelve character pseudo-password to salt the identicons + # BMConfigParser().set('bitmessagesettings', 'userlocale', 'system') + # BMConfigParser().set('bitmessagesettings', 'useidenticons', 'True') + # BMConfigParser().set( + # 'bitmessagesettings', 'identiconsuffix', + # ''.join(helper_random.randomchoice( + # "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + # ) for x in range(12) + # )) # a twelve character pseudo-password to salt the identicons BMConfigParser().set('bitmessagesettings', 'replybelow', 'False') BMConfigParser().set('bitmessagesettings', 'maxdownloadrate', '0') BMConfigParser().set('bitmessagesettings', 'maxuploadrate', '0') - BMConfigParser().set('bitmessagesettings', 'maxoutboundconnections', '8') - BMConfigParser().set('bitmessagesettings', 'ttl', '367200') - - #start:UI setting to stop trying to send messages after X days/months + # BMConfigParser().set( + # 'bitmessagesettings', 'maxoutboundconnections', '8') + # BMConfigParser().set('bitmessagesettings', 'ttl', '367200') + + # UI setting to stop trying to send messages after X days/months BMConfigParser().set( 'bitmessagesettings', 'stopresendingafterxdays', '') BMConfigParser().set( 'bitmessagesettings', 'stopresendingafterxmonths', '') - #BMConfigParser().set( + # BMConfigParser().set( # 'bitmessagesettings', 'timeperiod', '-1') - #end # Are you hoping to add a new option to the keys.dat file? You're in # the right place for adding it to users who install the software for # the first time. But you must also add it to the keys.dat file of - # existing users. To do that, search the class_sqlThread.py file for the - # text: "right above this line!" + # existing users. To do that, search the class_sqlThread.py file + # for the text: "right above this line!" - ensureNamecoinOptions() + # ensureNamecoinOptions() if storeConfigFilesInSameDirectoryAsProgramByDefault: # Just use the same directory as the program and forget about @@ -140,14 +147,202 @@ def loadConfig(): if not sys.platform.startswith('win'): os.umask(0o077) BMConfigParser().save() + else: + updateConfig() _loadTrustedPeer() + +def updateConfig(): + settingsversion = BMConfigParser().getint( + 'bitmessagesettings', 'settingsversion') + if settingsversion == 1: + BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none') + BMConfigParser().set( + 'bitmessagesettings', 'sockshostname', 'localhost') + BMConfigParser().set('bitmessagesettings', 'socksport', '9050') + BMConfigParser().set( + 'bitmessagesettings', 'socksauthentication', 'false') + BMConfigParser().set('bitmessagesettings', 'socksusername', '') + BMConfigParser().set('bitmessagesettings', 'sockspassword', '') + BMConfigParser().set('bitmessagesettings', 'sockslisten', 'false') + BMConfigParser().set('bitmessagesettings', 'keysencrypted', 'false') + BMConfigParser().set( + 'bitmessagesettings', 'messagesencrypted', 'false') + settingsversion = 2 + # let class_sqlThread update SQL and continue + elif settingsversion == 4: + BMConfigParser().set( + 'bitmessagesettings', 'defaultnoncetrialsperbyte', + str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) + BMConfigParser().set( + 'bitmessagesettings', 'defaultpayloadlengthextrabytes', + str(defaults.networkDefaultPayloadLengthExtraBytes)) + settingsversion = 5 + + if settingsversion == 5: + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', '0') + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', '0') + settingsversion = 7 + + # Raise the default required difficulty from 1 to 2 + # With the change to protocol v3, this is obsolete. + # if settingsversion == 6: + # if int(shared.config.get( + # 'bitmessagesettings', 'defaultnoncetrialsperbyte' + # )) == defaults.networkDefaultProofOfWorkNonceTrialsPerByte: + # shared.config.set( + # 'bitmessagesettings', 'defaultnoncetrialsperbyte', + # str( + # defaults.networkDefaultProofOfWorkNonceTrialsPerByte + # * 2) + # ) + # settingsversion = 7 + + if not BMConfigParser().has_option('bitmessagesettings', 'sockslisten'): + BMConfigParser().set('bitmessagesettings', 'sockslisten', 'false') + + ensureNamecoinOptions() + + if not BMConfigParser().has_option('bitmessagesettings', 'userlocale'): + BMConfigParser().set('bitmessagesettings', 'userlocale', 'system') + + if not BMConfigParser().has_option( + 'bitmessagesettings', 'sendoutgoingconnections'): + BMConfigParser().set( + 'bitmessagesettings', 'sendoutgoingconnections', 'True') + + if not BMConfigParser().has_option( + 'bitmessagesettings', 'useidenticons'): + BMConfigParser().set('bitmessagesettings', 'useidenticons', 'True') + if not BMConfigParser().has_option( + 'bitmessagesettings', 'identiconsuffix'): + # acts as a salt + BMConfigParser().set( + 'bitmessagesettings', 'identiconsuffix', + ''.join(helper_random.randomchoice( + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + ) for x in range(12) + )) # a twelve character pseudo-password to salt the identicons + + # Add settings to support no longer resending messages after + # a certain period of time even if we never get an ack + if settingsversion == 7: + BMConfigParser().set( + 'bitmessagesettings', 'stopresendingafterxdays', '') + BMConfigParser().set( + 'bitmessagesettings', 'stopresendingafterxmonths', '') + settingsversion = 8 + + # With the change to protocol version 3, reset the user-settable + # difficulties to 1 + if settingsversion == 8: + BMConfigParser().set( + 'bitmessagesettings', 'defaultnoncetrialsperbyte', + str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte)) + BMConfigParser().set( + 'bitmessagesettings', 'defaultpayloadlengthextrabytes', + str(defaults.networkDefaultPayloadLengthExtraBytes)) + previousTotalDifficulty = int( + BMConfigParser().getint( + 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte') + ) / 320 + previousSmallMessageDifficulty = int( + BMConfigParser().getint( + 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') + ) / 14000 + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', + str(previousTotalDifficulty * 1000)) + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', + str(previousSmallMessageDifficulty * 1000)) + settingsversion = 9 + + # Adjust the required POW values for each of this user's addresses + # to conform to protocol v3 norms. + if settingsversion == 9: + for addressInKeysFile in BMConfigParser().addresses(): + try: + previousTotalDifficulty = float( + BMConfigParser().getint( + addressInKeysFile, 'noncetrialsperbyte')) / 320 + previousSmallMessageDifficulty = float( + BMConfigParser().getint( + addressInKeysFile, 'payloadlengthextrabytes')) / 14000 + if previousTotalDifficulty <= 2: + previousTotalDifficulty = 1 + if previousSmallMessageDifficulty < 1: + previousSmallMessageDifficulty = 1 + BMConfigParser().set( + addressInKeysFile, 'noncetrialsperbyte', + str(int(previousTotalDifficulty * 1000))) + BMConfigParser().set( + addressInKeysFile, 'payloadlengthextrabytes', + str(int(previousSmallMessageDifficulty * 1000))) + except Exception: + continue + BMConfigParser().set('bitmessagesettings', 'maxdownloadrate', '0') + BMConfigParser().set('bitmessagesettings', 'maxuploadrate', '0') + settingsversion = 10 + + # sanity check + if BMConfigParser().safeGetInt( + 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte') == 0: + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', + str( + defaults.ridiculousDifficulty + * defaults.networkDefaultProofOfWorkNonceTrialsPerByte) + ) + if BMConfigParser().safeGetInt( + 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes' + ) == 0: + BMConfigParser().set( + 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', + str( + defaults.ridiculousDifficulty + * defaults.networkDefaultPayloadLengthExtraBytes) + ) + + if not BMConfigParser().has_option('bitmessagesettings', 'onionhostname'): + BMConfigParser().set('bitmessagesettings', 'onionhostname', '') + if not BMConfigParser().has_option('bitmessagesettings', 'onionport'): + BMConfigParser().set('bitmessagesettings', 'onionport', '8444') + if not BMConfigParser().has_option('bitmessagesettings', 'onionbindip'): + BMConfigParser().set('bitmessagesettings', 'onionbindip', '127.0.0.1') + if not BMConfigParser().has_option('bitmessagesettings', 'smtpdeliver'): + BMConfigParser().set('bitmessagesettings', 'smtpdeliver', '') + if not BMConfigParser().has_option( + 'bitmessagesettings', 'hidetrayconnectionnotifications'): + BMConfigParser().set( + 'bitmessagesettings', 'hidetrayconnectionnotifications', 'false') + if BMConfigParser().safeGetInt( + 'bitmessagesettings', 'maxoutboundconnections') < 1: + BMConfigParser().set( + 'bitmessagesettings', 'maxoutboundconnections', '8') + print('WARNING: your maximum outbound connections must be a number.') + + # TTL is now user-specifiable. Let's add an option to save + # whatever the user selects. + if not BMConfigParser().has_option('bitmessagesettings', 'ttl'): + BMConfigParser().set('bitmessagesettings', 'ttl', '367200') + + BMConfigParser().set( + 'bitmessagesettings', 'settingsversion', str(settingsversion)) + BMConfigParser().save() + + def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections(): try: - if sys.platform[0:3]=="win": - VER_THIS=StrictVersion(platform.version()) - return StrictVersion("5.1.2600")<=VER_THIS and StrictVersion("6.0.6000")>=VER_THIS - return False - except Exception as err: + if sys.platform[0:3] == "win": + VER_THIS = StrictVersion(platform.version()) + return ( + StrictVersion("5.1.2600") <= VER_THIS + and StrictVersion("6.0.6000") >= VER_THIS + ) return False + except Exception: + pass