From 9f4a1fa0a4792d3e50c5915fdd3079207ba158a0 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Mon, 15 May 2017 12:18:07 +0200 Subject: [PATCH] Config file defaults and address unification - bmconfigpaser.py now allows to put default values for a specific option in the file - addresses as sections are now detected by "BM-" rather than just ignoring bitmessagesettings. There can now be other sections with a cleaner config file --- src/api.py | 30 ++++++++++----------- src/bitmessagecurses/__init__.py | 25 +++++++++-------- src/bitmessageqt/account.py | 2 +- src/bmconfigparser.py | 46 +++++++++++++++++++++----------- src/class_singleWorker.py | 2 +- src/class_smtpDeliver.py | 2 +- src/class_smtpServer.py | 4 +-- src/class_sqlThread.py | 2 +- src/shared.py | 38 +++++++++++++------------- 9 files changed, 81 insertions(+), 70 deletions(-) diff --git a/src/api.py b/src/api.py index c8612d60..82a56d40 100644 --- a/src/api.py +++ b/src/api.py @@ -169,22 +169,20 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): def HandleListAddresses(self, method): data = '{"addresses":[' - configSections = BMConfigParser().sections() - for addressInKeysFile in configSections: - if addressInKeysFile != 'bitmessagesettings': - status, addressVersionNumber, streamNumber, hash01 = decodeAddress( - addressInKeysFile) - if len(data) > 20: - data += ',' - if BMConfigParser().has_option(addressInKeysFile, 'chan'): - chan = BMConfigParser().getboolean(addressInKeysFile, 'chan') - else: - chan = False - label = BMConfigParser().get(addressInKeysFile, 'label') - if method == 'listAddresses2': - label = label.encode('base64') - data += json.dumps({'label': label, 'address': addressInKeysFile, 'stream': - streamNumber, 'enabled': BMConfigParser().getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': ')) + for addressInKeysFile in BMConfigParser().addresses(): + status, addressVersionNumber, streamNumber, hash01 = decodeAddress( + addressInKeysFile) + if len(data) > 20: + data += ',' + if BMConfigParser().has_option(addressInKeysFile, 'chan'): + chan = BMConfigParser().getboolean(addressInKeysFile, 'chan') + else: + chan = False + label = BMConfigParser().get(addressInKeysFile, 'label') + if method == 'listAddresses2': + label = label.encode('base64') + data += json.dumps({'label': label, 'address': addressInKeysFile, 'stream': + streamNumber, 'enabled': BMConfigParser().getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': ')) data += ']}' return data diff --git a/src/bitmessagecurses/__init__.py b/src/bitmessagecurses/__init__.py index d710720f..903b7e68 100644 --- a/src/bitmessagecurses/__init__.py +++ b/src/bitmessagecurses/__init__.py @@ -1024,20 +1024,19 @@ def run(stdscr): curses.init_pair(9, curses.COLOR_YELLOW, curses.COLOR_BLACK) # orangish # Init list of address in 'Your Identities' tab - configSections = BMConfigParser().sections() + configSections = BMConfigParser().addressses() for addressInKeysFile in configSections: - if addressInKeysFile != "bitmessagesettings": - isEnabled = BMConfigParser().getboolean(addressInKeysFile, "enabled") - addresses.append([BMConfigParser().get(addressInKeysFile, "label"), isEnabled, addressInKeysFile]) - # Set address color - if not isEnabled: - addresses[len(addresses)-1].append(8) # gray - elif BMConfigParser().safeGetBoolean(addressInKeysFile, 'chan'): - addresses[len(addresses)-1].append(9) # orange - elif BMConfigParser().safeGetBoolean(addressInKeysFile, 'mailinglist'): - addresses[len(addresses)-1].append(5) # magenta - else: - addresses[len(addresses)-1].append(0) # black + isEnabled = BMConfigParser().getboolean(addressInKeysFile, "enabled") + addresses.append([BMConfigParser().get(addressInKeysFile, "label"), isEnabled, addressInKeysFile]) + # Set address color + if not isEnabled: + addresses[len(addresses)-1].append(8) # gray + elif BMConfigParser().safeGetBoolean(addressInKeysFile, 'chan'): + addresses[len(addresses)-1].append(9) # orange + elif BMConfigParser().safeGetBoolean(addressInKeysFile, 'mailinglist'): + addresses[len(addresses)-1].append(5) # magenta + else: + addresses[len(addresses)-1].append(0) # black addresses.reverse() stdscr.clear() diff --git a/src/bitmessageqt/account.py b/src/bitmessageqt/account.py index 611f5039..eee6c7b4 100644 --- a/src/bitmessageqt/account.py +++ b/src/bitmessageqt/account.py @@ -13,7 +13,7 @@ from utils import str_broadcast_subscribers import time def getSortedAccounts(): - configSections = filter(lambda x: x != 'bitmessagesettings', BMConfigParser().sections()) + configSections = BMConfigParser().addresses() configSections.sort(cmp = lambda x,y: cmp(unicode(BMConfigParser().get(x, 'label'), 'utf-8').lower(), unicode(BMConfigParser().get(y, 'label'), 'utf-8').lower()) ) diff --git a/src/bmconfigparser.py b/src/bmconfigparser.py index 412d2fa5..448a9ffc 100644 --- a/src/bmconfigparser.py +++ b/src/bmconfigparser.py @@ -6,6 +6,17 @@ import os from singleton import Singleton import state +BMConfigDefaults = { + "bitmessagesettings": { + "maxaddrperstreamsend": 500, + "maxbootstrapconnections": 20, + "maxoutboundconnections": 8, + "maxtotalconnections": 200, + }, + "zlib": { + 'maxsize': 1048576 + } +} @Singleton class BMConfigParser(ConfigParser.SafeConfigParser): @@ -21,33 +32,38 @@ class BMConfigParser(ConfigParser.SafeConfigParser): return ConfigParser.ConfigParser.get(self, section, option, raw, vars) except ConfigParser.InterpolationError: return ConfigParser.ConfigParser.get(self, section, option, True, vars) - return ConfigParser.ConfigParser.get(self, section, option, True, vars) + try: + return ConfigParser.ConfigParser.get(self, section, option, True, vars) + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e: + try: + return BMConfigDefaults[section][option] + except KeyError: + raise e def safeGetBoolean(self, section, field): - if self.has_option(section, field): - try: - return self.getboolean(section, field) - except ValueError: - return False - return False + try: + return self.getboolean(section, field) + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError): + return False def safeGetInt(self, section, field, default=0): - if self.has_option(section, field): - try: - return self.getint(section, field) - except ValueError: - return default - return default + try: + return self.getint(section, field) + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError): + return default def safeGet(self, section, option, default = None): - if self.has_option(section, option): + try: return self.get(section, option) - else: + except (ConfigParser.NoSectionError, ConfigParser.NoOptionError, ValueError): return default def items(self, section, raw=False, vars=None): return ConfigParser.ConfigParser.items(self, section, True, vars) + def addresses(self): + return filter(lambda x: x.startswith('BM-'), BMConfigParser().sections()) + def save(self): fileName = os.path.join(state.appdata, 'keys.dat') fileNameBak = fileName + "." + datetime.datetime.now().strftime("%Y%j%H%M%S%f") + '.bak' diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py index b45c4aca..c2d16de4 100644 --- a/src/class_singleWorker.py +++ b/src/class_singleWorker.py @@ -136,7 +136,7 @@ class singleWorker(threading.Thread, StoppableThread): def doPOWForMyV2Pubkey(self, hash): # This function also broadcasts out the pubkey message once it is done with the POW # Look up my stream number based on my address hash - """configSections = shared.config.sections() + """configSections = shared.config.addresses() for addressInKeysFile in configSections: if addressInKeysFile <> 'bitmessagesettings': status,addressVersionNumber,streamNumber,hashFromThisParticularAddress = decodeAddress(addressInKeysFile) diff --git a/src/class_smtpDeliver.py b/src/class_smtpDeliver.py index 9492f123..bb659ebe 100644 --- a/src/class_smtpDeliver.py +++ b/src/class_smtpDeliver.py @@ -59,7 +59,7 @@ class smtpDeliver(threading.Thread, StoppableThread): msg = MIMEText(body, 'plain', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = fromAddress + '@' + SMTPDOMAIN - toLabel = map (lambda y: BMConfigParser().safeGet(y, "label"), filter(lambda x: x == toAddress, BMConfigParser().sections())) + toLabel = map (lambda y: BMConfigParser().safeGet(y, "label"), filter(lambda x: x == toAddress, BMConfigParser().addresses())) if len(toLabel) > 0: msg['To'] = "\"%s\" <%s>" % (Header(toLabel[0], 'utf-8'), toAddress + '@' + SMTPDOMAIN) else: diff --git a/src/class_smtpServer.py b/src/class_smtpServer.py index 13882a94..3bc81a61 100644 --- a/src/class_smtpServer.py +++ b/src/class_smtpServer.py @@ -115,7 +115,7 @@ class smtpServerPyBitmessage(smtpd.SMTPServer): sender, domain = p.sub(r'\1', mailfrom).split("@") if domain != SMTPDOMAIN: raise Exception("Bad domain %s", domain) - if sender not in BMConfigParser().sections(): + if sender not in BMConfigParser().addresses(): raise Exception("Nonexisting user %s", sender) except Exception as err: logger.debug("Bad envelope from %s: %s", mailfrom, repr(err)) @@ -125,7 +125,7 @@ class smtpServerPyBitmessage(smtpd.SMTPServer): sender, domain = msg_from.split("@") if domain != SMTPDOMAIN: raise Exception("Bad domain %s", domain) - if sender not in BMConfigParser().sections(): + if sender not in BMConfigParser().addresses(): raise Exception("Nonexisting user %s", sender) except Exception as err: logger.error("Bad headers from %s: %s", msg_from, repr(err)) diff --git a/src/class_sqlThread.py b/src/class_sqlThread.py index 9bd7e8e7..18606e74 100644 --- a/src/class_sqlThread.py +++ b/src/class_sqlThread.py @@ -316,7 +316,7 @@ class sqlThread(threading.Thread): # 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().sections(): + for addressInKeysFile in BMConfigParser().addressses(): try: previousTotalDifficulty = float(BMConfigParser().getint(addressInKeysFile, 'noncetrialsperbyte')) / 320 previousSmallMessageDifficulty = float(BMConfigParser().getint(addressInKeysFile, 'payloadlengthextrabytes')) / 14000 diff --git a/src/shared.py b/src/shared.py index 4fd66610..34597c78 100644 --- a/src/shared.py +++ b/src/shared.py @@ -110,29 +110,27 @@ def reloadMyAddressHashes(): #myPrivateKeys.clear() keyfileSecure = checkSensitiveFilePermissions(state.appdata + 'keys.dat') - configSections = BMConfigParser().sections() hasEnabledKeys = False - for addressInKeysFile in configSections: - if addressInKeysFile <> 'bitmessagesettings': - isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled') - if isEnabled: - hasEnabledKeys = True - status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile) - if addressVersionNumber == 2 or addressVersionNumber == 3 or addressVersionNumber == 4: - # Returns a simple 32 bytes of information encoded in 64 Hex characters, - # or null if there was an error. - privEncryptionKey = hexlify(decodeWalletImportFormat( - BMConfigParser().get(addressInKeysFile, 'privencryptionkey'))) + for addressInKeysFile in BMConfigParser().addresses(): + isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled') + if isEnabled: + hasEnabledKeys = True + status,addressVersionNumber,streamNumber,hash = decodeAddress(addressInKeysFile) + if addressVersionNumber == 2 or addressVersionNumber == 3 or addressVersionNumber == 4: + # Returns a simple 32 bytes of information encoded in 64 Hex characters, + # or null if there was an error. + privEncryptionKey = hexlify(decodeWalletImportFormat( + BMConfigParser().get(addressInKeysFile, 'privencryptionkey'))) - if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters - myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey) - myAddressesByHash[hash] = addressInKeysFile - tag = hashlib.sha512(hashlib.sha512(encodeVarint( - addressVersionNumber) + encodeVarint(streamNumber) + hash).digest()).digest()[32:] - myAddressesByTag[tag] = addressInKeysFile + if len(privEncryptionKey) == 64:#It is 32 bytes encoded as 64 hex characters + myECCryptorObjects[hash] = highlevelcrypto.makeCryptor(privEncryptionKey) + myAddressesByHash[hash] = addressInKeysFile + tag = hashlib.sha512(hashlib.sha512(encodeVarint( + addressVersionNumber) + encodeVarint(streamNumber) + hash).digest()).digest()[32:] + myAddressesByTag[tag] = addressInKeysFile - else: - logger.error('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2, 3, or 4.\n') + else: + logger.error('Error in reloadMyAddressHashes: Can\'t handle address versions other than 2, 3, or 4.\n') if not keyfileSecure: fixSensitiveFilePermissions(state.appdata + 'keys.dat', hasEnabledKeys)