Exemplo n.º 1
0
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

    else:
        BMConfigParser().read(paths.lookupExeFolder() + 'keys.dat')
        try:
            BMConfigParser().get('bitmessagesettings', 'settingsversion')
            print 'Loading config files from same directory as program.'
            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.
            state.appdata = paths.lookupAppdataFolder()
            BMConfigParser().read(state.appdata + 'keys.dat')
            try:
                BMConfigParser().get('bitmessagesettings', 'settingsversion')
                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')
        BMConfigParser().set('bitmessagesettings', 'settingsversion', '10')
        BMConfigParser().set('bitmessagesettings', 'port', '8444')
        BMConfigParser().set('bitmessagesettings', 'timeformat', '%%c')
        BMConfigParser().set('bitmessagesettings', 'blackwhitelist', 'black')
        BMConfigParser().set('bitmessagesettings', 'startonlogon', 'false')
        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.
        else:
            BMConfigParser().set('bitmessagesettings', 'minimizetotray',
                                 'true')
        BMConfigParser().set('bitmessagesettings', 'showtraynotifications',
                             'true')
        BMConfigParser().set('bitmessagesettings', 'startintray', 'false')
        BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none')
        BMConfigParser().set('bitmessagesettings', 'sockshostname',
                             'localhost')
        BMConfigParser().set('bitmessagesettings', 'socksport', '9050')
        BMConfigParser().set('bitmessagesettings', 'socksauthentication',
                             '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', 'minimizeonclose', 'false')
        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(
            random.choice(
                "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', 'stopresendingafterxdays',
                             '')
        BMConfigParser().set('bitmessagesettings', 'stopresendingafterxmonths',
                             '')
        #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!"

        ensureNamecoinOptions()

        if storeConfigFilesInSameDirectoryAsProgramByDefault:
            # Just use the same directory as the program and forget about
            # the appdata folder
            state.appdata = ''
            print 'Creating new config files in same directory as program.'
        else:
            print 'Creating new config files in', state.appdata
            if not os.path.exists(state.appdata):
                os.makedirs(state.appdata)
        if not sys.platform.startswith('win'):
            os.umask(0o077)
        BMConfigParser().save()

    _loadTrustedPeer()
    def processbroadcast(self, data):
        messageProcessingStartTime = time.time()
        shared.numberOfBroadcastsProcessed += 1
        queues.UISignalQueue.put(
            ('updateNumberOfBroadcastsProcessed', 'no data'))
        inventoryHash = calculateInventoryHash(data)
        readPosition = 20  # bypass the nonce, time, and object type
        broadcastVersion, broadcastVersionLength = decodeVarint(
            data[readPosition:readPosition + 9])
        readPosition += broadcastVersionLength
        if broadcastVersion < 4 or broadcastVersion > 5:
            logger.info(
                'Cannot decode incoming broadcast versions less than 4 or higher than 5. Assuming the sender isn\'t being silly, you should upgrade Bitmessage because this message shall be ignored.'
            )
            return
        cleartextStreamNumber, cleartextStreamNumberLength = decodeVarint(
            data[readPosition:readPosition + 10])
        readPosition += cleartextStreamNumberLength
        if broadcastVersion == 4:
            """
            v4 broadcasts are encrypted the same way the msgs are encrypted. To see if we are interested in a
            v4 broadcast, we try to decrypt it. This was replaced with v5 broadcasts which include a tag which 
            we check instead, just like we do with v4 pubkeys. 
            """
            signedData = data[8:readPosition]
            initialDecryptionSuccessful = False
            for key, cryptorObject in shared.MyECSubscriptionCryptorObjects.items(
            ):
                try:
                    if initialDecryptionSuccessful:  # continue decryption attempts to avoid timing attacks
                        cryptorObject.decrypt(data[readPosition:])
                    else:
                        decryptedData = cryptorObject.decrypt(
                            data[readPosition:])
                        toRipe = key  # This is the RIPE hash of the sender's pubkey. We need this below to compare to the RIPE hash of the sender's address to verify that it was encrypted by with their key rather than some other key.
                        initialDecryptionSuccessful = True
                        logger.info(
                            'EC decryption successful using key associated with ripe hash: %s'
                            % hexlify(key))
                except Exception as err:
                    pass
                    # print 'cryptorObject.decrypt Exception:', err
            if not initialDecryptionSuccessful:
                # This is not a broadcast I am interested in.
                logger.debug(
                    'Length of time program spent failing to decrypt this v4 broadcast: %s seconds.'
                    % (time.time() - messageProcessingStartTime, ))
                return
        elif broadcastVersion == 5:
            embeddedTag = data[readPosition:readPosition + 32]
            readPosition += 32
            if embeddedTag not in shared.MyECSubscriptionCryptorObjects:
                logger.debug('We\'re not interested in this broadcast.')
                return
            # We are interested in this broadcast because of its tag.
            signedData = data[
                8:
                readPosition]  # We're going to add some more data which is signed further down.
            cryptorObject = shared.MyECSubscriptionCryptorObjects[embeddedTag]
            try:
                decryptedData = cryptorObject.decrypt(data[readPosition:])
                logger.debug('EC decryption successful')
            except Exception as err:
                logger.debug('Broadcast version %s decryption Unsuccessful.' %
                             broadcastVersion)
                return
        # At this point this is a broadcast I have decrypted and am
        # interested in.
        readPosition = 0
        sendersAddressVersion, sendersAddressVersionLength = decodeVarint(
            decryptedData[readPosition:readPosition + 9])
        if broadcastVersion == 4:
            if sendersAddressVersion < 2 or sendersAddressVersion > 3:
                logger.warning(
                    'Cannot decode senderAddressVersion other than 2 or 3. Assuming the sender isn\'t being silly, you should upgrade Bitmessage because this message shall be ignored.'
                )
                return
        elif broadcastVersion == 5:
            if sendersAddressVersion < 4:
                logger.info(
                    'Cannot decode senderAddressVersion less than 4 for broadcast version number 5. Assuming the sender isn\'t being silly, you should upgrade Bitmessage because this message shall be ignored.'
                )
                return
        readPosition += sendersAddressVersionLength
        sendersStream, sendersStreamLength = decodeVarint(
            decryptedData[readPosition:readPosition + 9])
        if sendersStream != cleartextStreamNumber:
            logger.info(
                'The stream number outside of the encryption on which the POW was completed doesn\'t match the stream number inside the encryption. Ignoring broadcast.'
            )
            return
        readPosition += sendersStreamLength
        behaviorBitfield = decryptedData[readPosition:readPosition + 4]
        readPosition += 4
        sendersPubSigningKey = '\x04' + \
            decryptedData[readPosition:readPosition + 64]
        readPosition += 64
        sendersPubEncryptionKey = '\x04' + \
            decryptedData[readPosition:readPosition + 64]
        readPosition += 64
        if sendersAddressVersion >= 3:
            requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = decodeVarint(
                decryptedData[readPosition:readPosition + 10])
            readPosition += varintLength
            logger.debug(
                'sender\'s requiredAverageProofOfWorkNonceTrialsPerByte is %s'
                % requiredAverageProofOfWorkNonceTrialsPerByte)
            requiredPayloadLengthExtraBytes, varintLength = decodeVarint(
                decryptedData[readPosition:readPosition + 10])
            readPosition += varintLength
            logger.debug('sender\'s requiredPayloadLengthExtraBytes is %s' %
                         requiredPayloadLengthExtraBytes)
        endOfPubkeyPosition = readPosition

        sha = hashlib.new('sha512')
        sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
        ripeHasher = hashlib.new('ripemd160')
        ripeHasher.update(sha.digest())
        calculatedRipe = ripeHasher.digest()

        if broadcastVersion == 4:
            if toRipe != calculatedRipe:
                logger.info(
                    'The encryption key used to encrypt this message doesn\'t match the keys inbedded in the message itself. Ignoring message.'
                )
                return
        elif broadcastVersion == 5:
            calculatedTag = hashlib.sha512(
                hashlib.sha512(
                    encodeVarint(sendersAddressVersion) +
                    encodeVarint(sendersStream) +
                    calculatedRipe).digest()).digest()[32:]
            if calculatedTag != embeddedTag:
                logger.debug(
                    'The tag and encryption key used to encrypt this message doesn\'t match the keys inbedded in the message itself. Ignoring message.'
                )
                return
        messageEncodingType, messageEncodingTypeLength = decodeVarint(
            decryptedData[readPosition:readPosition + 9])
        if messageEncodingType == 0:
            return
        readPosition += messageEncodingTypeLength
        messageLength, messageLengthLength = decodeVarint(
            decryptedData[readPosition:readPosition + 9])
        readPosition += messageLengthLength
        message = decryptedData[readPosition:readPosition + messageLength]
        readPosition += messageLength
        readPositionAtBottomOfMessage = readPosition
        signatureLength, signatureLengthLength = decodeVarint(
            decryptedData[readPosition:readPosition + 9])
        readPosition += signatureLengthLength
        signature = decryptedData[readPosition:readPosition + signatureLength]
        signedData += decryptedData[:readPositionAtBottomOfMessage]
        if not highlevelcrypto.verify(signedData, signature,
                                      hexlify(sendersPubSigningKey)):
            logger.debug('ECDSA verify failed')
            return
        logger.debug('ECDSA verify passed')
        sigHash = hashlib.sha512(hashlib.sha512(signature).digest()).digest()[
            32:]  # Used to detect and ignore duplicate messages in our inbox

        fromAddress = encodeAddress(sendersAddressVersion, sendersStream,
                                    calculatedRipe)
        logger.info('fromAddress: %s' % fromAddress)

        # Let's store the public key in case we want to reply to this person.
        sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', fromAddress,
                   sendersAddressVersion, decryptedData[:endOfPubkeyPosition],
                   int(time.time()), 'yes')

        # Check to see whether we happen to be awaiting this
        # pubkey in order to send a message. If we are, it will do the POW
        # and send it.
        self.possibleNewPubkey(fromAddress)

        fromAddress = encodeAddress(sendersAddressVersion, sendersStream,
                                    calculatedRipe)
        logger.debug('fromAddress: ' + fromAddress)

        decodedMessage = helper_msgcoding.MsgDecode(messageEncodingType,
                                                    message)
        subject = decodedMessage.subject
        body = decodedMessage.body

        toAddress = '[Broadcast subscribers]'
        if helper_inbox.isMessageAlreadyInInbox(sigHash):
            logger.info('This broadcast is already in our inbox. Ignoring it.')
            return
        t = (inventoryHash, toAddress, fromAddress, subject, int(time.time()),
             body, 'inbox', messageEncodingType, 0, sigHash)
        helper_inbox.insert(t)

        queues.UISignalQueue.put(
            ('displayNewInboxMessage', (inventoryHash, toAddress, fromAddress,
                                        subject, body)))

        # If we are behaving as an API then we might need to run an
        # outside command to let some program know that a new message
        # has arrived.
        if BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'):
            try:
                apiNotifyPath = BMConfigParser().get('bitmessagesettings',
                                                     'apinotifypath')
            except:
                apiNotifyPath = ''
            if apiNotifyPath != '':
                call([apiNotifyPath, "newBroadcast"])

        # Display timing data
        logger.info('Time spent processing this interesting broadcast: %s' %
                    (time.time() - messageProcessingStartTime, ))
Exemplo n.º 3
0
 def HandleCreateDeterministicAddresses(self, params):
     if len(params) == 0:
         raise APIError(0, 'I need parameters!')
     elif len(params) == 1:
         passphrase, = params
         numberOfAddresses = 1
         addressVersionNumber = 0
         streamNumber = 0
         eighteenByteRipe = False
         nonceTrialsPerByte = BMConfigParser().get(
             'bitmessagesettings', 'defaultnoncetrialsperbyte')
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 2:
         passphrase, numberOfAddresses = params
         addressVersionNumber = 0
         streamNumber = 0
         eighteenByteRipe = False
         nonceTrialsPerByte = BMConfigParser().get(
             'bitmessagesettings', 'defaultnoncetrialsperbyte')
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 3:
         passphrase, numberOfAddresses, addressVersionNumber = params
         streamNumber = 0
         eighteenByteRipe = False
         nonceTrialsPerByte = BMConfigParser().get(
             'bitmessagesettings', 'defaultnoncetrialsperbyte')
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 4:
         passphrase, numberOfAddresses, addressVersionNumber, \
             streamNumber = params
         eighteenByteRipe = False
         nonceTrialsPerByte = BMConfigParser().get(
             'bitmessagesettings', 'defaultnoncetrialsperbyte')
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 5:
         passphrase, numberOfAddresses, addressVersionNumber, \
             streamNumber, eighteenByteRipe = params
         nonceTrialsPerByte = BMConfigParser().get(
             'bitmessagesettings', 'defaultnoncetrialsperbyte')
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 6:
         passphrase, numberOfAddresses, addressVersionNumber, \
             streamNumber, eighteenByteRipe, totalDifficulty = params
         nonceTrialsPerByte = int(
             defaults.networkDefaultPayloadLengthExtraBytes *
             totalDifficulty)
         payloadLengthExtraBytes = BMConfigParser().get(
             'bitmessagesettings', 'defaultpayloadlengthextrabytes')
     elif len(params) == 7:
         passphrase, numberOfAddresses, addressVersionNumber, \
             streamNumber, eighteenByteRipe, totalDifficulty, \
             smallMessageDifficulty = params
         nonceTrialsPerByte = int(
             defaults.networkDefaultPayloadLengthExtraBytes *
             totalDifficulty)
         payloadLengthExtraBytes = int(
             defaults.networkDefaultPayloadLengthExtraBytes *
             smallMessageDifficulty)
     else:
         raise APIError(0, 'Too many parameters!')
     if len(passphrase) == 0:
         raise APIError(1, 'The specified passphrase is blank.')
     if not isinstance(eighteenByteRipe, bool):
         raise APIError(
             23, 'Bool expected in eighteenByteRipe, saw %s instead' %
             type(eighteenByteRipe))
     passphrase = self._decode(passphrase, "base64")
     # 0 means "just use the proper addressVersionNumber"
     if addressVersionNumber == 0:
         addressVersionNumber = 4
     if addressVersionNumber != 3 and addressVersionNumber != 4:
         raise APIError(
             2, 'The address version number currently must be 3, 4, or 0'
             ' (which means auto-select). %i isn\'t supported.' %
             addressVersionNumber)
     if streamNumber == 0:  # 0 means "just use the most available stream"
         streamNumber = 1
     if streamNumber != 1:
         raise APIError(
             3, 'The stream number must be 1 (or 0 which means'
             ' auto-select). Others aren\'t supported.')
     if numberOfAddresses == 0:
         raise APIError(
             4, 'Why would you ask me to generate 0 addresses for you?')
     if numberOfAddresses > 999:
         raise APIError(
             5, 'You have (accidentally?) specified too many addresses to'
             ' make. Maximum 999. This check only exists to prevent'
             ' mischief; if you really want to create more addresses than'
             ' this, contact the Bitmessage developers and we can modify'
             ' the check or you can do it yourself by searching the source'
             ' code for this message.')
     queues.apiAddressGeneratorReturnQueue.queue.clear()
     logger.debug(
         'Requesting that the addressGenerator create %s addresses.',
         numberOfAddresses)
     queues.addressGeneratorQueue.put(
         ('createDeterministicAddresses', addressVersionNumber,
          streamNumber, 'unused API address', numberOfAddresses, passphrase,
          eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
     data = '{"addresses":['
     queueReturn = queues.apiAddressGeneratorReturnQueue.get()
     for item in queueReturn:
         if len(data) > 20:
             data += ','
         data += "\"" + item + "\""
     data += ']}'
     return data
Exemplo n.º 4
0
def main():
    mainprogram = Main()
    mainprogram.start(BMConfigParser().safeGetBoolean('bitmessagesettings',
                                                      'daemon'))
    def processgetpubkey(self, data):
        if len(data) > 200:
            logger.info(
                'getpubkey is abnormally long. Sanity check failed. Ignoring object.'
            )
            return
        readPosition = 20  # bypass the nonce, time, and object type
        requestedAddressVersionNumber, addressVersionLength = decodeVarint(
            data[readPosition:readPosition + 10])
        readPosition += addressVersionLength
        streamNumber, streamNumberLength = decodeVarint(
            data[readPosition:readPosition + 10])
        readPosition += streamNumberLength

        if requestedAddressVersionNumber == 0:
            logger.debug(
                'The requestedAddressVersionNumber of the pubkey request is zero. That doesn\'t make any sense. Ignoring it.'
            )
            return
        elif requestedAddressVersionNumber == 1:
            logger.debug(
                'The requestedAddressVersionNumber of the pubkey request is 1 which isn\'t supported anymore. Ignoring it.'
            )
            return
        elif requestedAddressVersionNumber > 4:
            logger.debug(
                'The requestedAddressVersionNumber of the pubkey request is too high. Can\'t understand. Ignoring it.'
            )
            return

        myAddress = ''
        if requestedAddressVersionNumber <= 3:
            requestedHash = data[readPosition:readPosition + 20]
            if len(requestedHash) != 20:
                logger.debug(
                    'The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.'
                )
                return
            logger.info('the hash requested in this getpubkey request is: %s' %
                        hexlify(requestedHash))
            if requestedHash in shared.myAddressesByHash:  # if this address hash is one of mine
                myAddress = shared.myAddressesByHash[requestedHash]
        elif requestedAddressVersionNumber >= 4:
            requestedTag = data[readPosition:readPosition + 32]
            if len(requestedTag) != 32:
                logger.debug(
                    'The length of the requested tag is not 32 bytes. Something is wrong. Ignoring.'
                )
                return
            logger.debug('the tag requested in this getpubkey request is: %s' %
                         hexlify(requestedTag))
            if requestedTag in shared.myAddressesByTag:
                myAddress = shared.myAddressesByTag[requestedTag]

        if myAddress == '':
            logger.info('This getpubkey request is not for any of my keys.')
            return

        if decodeAddress(myAddress)[1] != requestedAddressVersionNumber:
            logger.warning(
                '(Within the processgetpubkey function) Someone requested one of my pubkeys but the requestedAddressVersionNumber doesn\'t match my actual address version number. Ignoring.'
            )
            return
        if decodeAddress(myAddress)[2] != streamNumber:
            logger.warning(
                '(Within the processgetpubkey function) Someone requested one of my pubkeys but the stream number on which we heard this getpubkey object doesn\'t match this address\' stream number. Ignoring.'
            )
            return
        if BMConfigParser().safeGetBoolean(myAddress, 'chan'):
            logger.info(
                'Ignoring getpubkey request because it is for one of my chan addresses. The other party should already have the pubkey.'
            )
            return
        try:
            lastPubkeySendTime = int(BMConfigParser().get(
                myAddress, 'lastpubkeysendtime'))
        except:
            lastPubkeySendTime = 0
        if lastPubkeySendTime > time.time(
        ) - 2419200:  # If the last time we sent our pubkey was more recent than 28 days ago...
            logger.info(
                'Found getpubkey-requested-item in my list of EC hashes BUT we already sent it recently. Ignoring request. The lastPubkeySendTime is: %s'
                % lastPubkeySendTime)
            return
        logger.info(
            'Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.'
        )
        if requestedAddressVersionNumber == 2:
            queues.workerQueue.put(('doPOWForMyV2Pubkey', requestedHash))
        elif requestedAddressVersionNumber == 3:
            queues.workerQueue.put(('sendOutOrStoreMyV3Pubkey', requestedHash))
        elif requestedAddressVersionNumber == 4:
            queues.workerQueue.put(('sendOutOrStoreMyV4Pubkey', myAddress))
Exemplo n.º 6
0
    def run(self):
        from debug import logger

        logger.debug("Starting UPnP thread")
        logger.debug("Local IP: %s", self.localIP)
        lastSent = 0

        # wait until asyncore binds so that we know the listening port
        bound = False
        while state.shutdown == 0 and not self._stopped and not bound:
            for s in BMConnectionPool().listeningSockets.values():
                if s.is_bound():
                    bound = True
            if not bound:
                time.sleep(1)

        self.localPort = BMConfigParser().getint('bitmessagesettings', 'port')
        while state.shutdown == 0 and BMConfigParser().safeGetBoolean(
                'bitmessagesettings', 'upnp'):
            if time.time() - lastSent > self.sendSleep and len(
                    self.routers) == 0:
                try:
                    self.sendSearchRouter()
                except:
                    pass
                lastSent = time.time()
            try:
                while state.shutdown == 0 and BMConfigParser().safeGetBoolean(
                        'bitmessagesettings', 'upnp'):
                    resp, (ip, port) = self.sock.recvfrom(1000)
                    if resp is None:
                        continue
                    newRouter = Router(resp, ip)
                    for router in self.routers:
                        if router.location == newRouter.location:
                            break
                    else:
                        logger.debug("Found UPnP router at %s", ip)
                        self.routers.append(newRouter)
                        self.createPortMapping(newRouter)
                        queues.UISignalQueue.put(
                            ('updateStatusBar',
                             tr._translate(
                                 "MainWindow",
                                 'UPnP port mapping established on port %1').
                             arg(str(self.extPort))))
                        # retry connections so that the submitted port is refreshed
                        with shared.alreadyAttemptedConnectionsListLock:
                            shared.alreadyAttemptedConnectionsList.clear()
                            shared.alreadyAttemptedConnectionsListResetTime = int(
                                time.time())
                        break
            except socket.timeout as e:
                pass
            except:
                logger.error("Failure running UPnP router search.",
                             exc_info=True)
            for router in self.routers:
                if router.extPort is None:
                    self.createPortMapping(router)
        try:
            self.sock.shutdown(socket.SHUT_RDWR)
        except:
            pass
        try:
            self.sock.close()
        except:
            pass
        deleted = False
        for router in self.routers:
            if router.extPort is not None:
                deleted = True
                self.deletePortMapping(router)
        shared.extPort = None
        if deleted:
            queues.UISignalQueue.put(
                ('updateStatusBar',
                 tr._translate("MainWindow", 'UPnP port mapping removed')))
        logger.debug("UPnP thread done")
Exemplo n.º 7
0
def loadConfig():
    """Load the config"""
    config = BMConfigParser()
    if state.appdata:
        config.read(state.appdata + 'keys.dat')
        # state.appdata must have been specified as a startup option.
        needToCreateKeysFile = config.safeGet('bitmessagesettings',
                                              'settingsversion') is None
        if not needToCreateKeysFile:
            print('Loading config files from directory specified'
                  ' on startup: %s' % state.appdata)
    else:
        config.read(paths.lookupExeFolder() + 'keys.dat')
        try:
            config.get('bitmessagesettings', 'settingsversion')
            print('Loading config files from same directory as program.')
            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.
            state.appdata = paths.lookupAppdataFolder()
            config.read(state.appdata + 'keys.dat')
            needToCreateKeysFile = config.safeGet('bitmessagesettings',
                                                  'settingsversion') is None
            if not needToCreateKeysFile:
                print('Loading existing config files from', state.appdata)

    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.
        config.add_section('bitmessagesettings')
        config.set('bitmessagesettings', 'settingsversion', '10')
        config.set('bitmessagesettings', 'port', '8444')
        config.set('bitmessagesettings', 'timeformat', '%%c')
        config.set('bitmessagesettings', 'blackwhitelist', 'black')
        config.set('bitmessagesettings', 'startonlogon', 'false')
        if 'linux' in sys.platform:
            config.set('bitmessagesettings', 'minimizetotray', 'false')
        # This isn't implimented yet and when True on
        # Ubuntu causes Bitmessage to disappear while
        # running when minimized.
        else:
            config.set('bitmessagesettings', 'minimizetotray', 'true')
        config.set('bitmessagesettings', 'showtraynotifications', 'true')
        config.set('bitmessagesettings', 'startintray', 'false')
        config.set('bitmessagesettings', 'socksproxytype', 'none')
        config.set('bitmessagesettings', 'sockshostname', 'localhost')
        config.set('bitmessagesettings', 'socksport', '9050')
        config.set('bitmessagesettings', 'socksauthentication', 'false')
        config.set('bitmessagesettings', 'socksusername', '')
        config.set('bitmessagesettings', 'sockspassword', '')
        config.set('bitmessagesettings', 'keysencrypted', 'false')
        config.set('bitmessagesettings', 'messagesencrypted', 'false')
        config.set('bitmessagesettings', 'defaultnoncetrialsperbyte',
                   str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
        config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes',
                   str(defaults.networkDefaultPayloadLengthExtraBytes))
        config.set('bitmessagesettings', 'minimizeonclose', 'false')
        config.set('bitmessagesettings', 'dontconnect', 'true')
        config.set('bitmessagesettings', 'replybelow', 'False')
        config.set('bitmessagesettings', 'maxdownloadrate', '0')
        config.set('bitmessagesettings', 'maxuploadrate', '0')

        # UI setting to stop trying to send messages after X days/months
        config.set('bitmessagesettings', 'stopresendingafterxdays', '')
        config.set('bitmessagesettings', 'stopresendingafterxmonths', '')

        # 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!"

        if StoreConfigFilesInSameDirectoryAsProgramByDefault:
            # Just use the same directory as the program and forget about
            # the appdata folder
            state.appdata = ''
            print('Creating new config files in same directory as program.')
        else:
            print('Creating new config files in', state.appdata)
            if not os.path.exists(state.appdata):
                os.makedirs(state.appdata)
        if not sys.platform.startswith('win'):
            os.umask(0o077)
        config.save()
    else:
        updateConfig()

    _loadTrustedPeer()
Exemplo n.º 8
0
    def run(self):
        while state.shutdown == 0:
            queueValue = queues.addressGeneratorQueue.get()
            nonceTrialsPerByte = 0
            payloadLengthExtraBytes = 0
            live = True
            if queueValue[0] == 'createChan':
                command, addressVersionNumber, streamNumber, label, \
                    deterministicPassphrase, live = queueValue
                eighteenByteRipe = False
                numberOfAddressesToMake = 1
                numberOfNullBytesDemandedOnFrontOfRipeHash = 1
            elif queueValue[0] == 'joinChan':
                command, chanAddress, label, deterministicPassphrase, \
                    live = queueValue
                eighteenByteRipe = False
                addressVersionNumber = decodeAddress(chanAddress)[1]
                streamNumber = decodeAddress(chanAddress)[2]
                numberOfAddressesToMake = 1
                numberOfNullBytesDemandedOnFrontOfRipeHash = 1
            elif len(queueValue) == 7:
                command, addressVersionNumber, streamNumber, label, \
                    numberOfAddressesToMake, deterministicPassphrase, \
                    eighteenByteRipe = queueValue
                try:
                    numberOfNullBytesDemandedOnFrontOfRipeHash = \
                        BMConfigParser().getint(
                            'bitmessagesettings',
                            'numberofnullbytesonaddress'
                        )
                except:
                    if eighteenByteRipe:
                        numberOfNullBytesDemandedOnFrontOfRipeHash = 2
                    else:
                        # the default
                        numberOfNullBytesDemandedOnFrontOfRipeHash = 1
            elif len(queueValue) == 9:
                command, addressVersionNumber, streamNumber, label, \
                    numberOfAddressesToMake, deterministicPassphrase, \
                    eighteenByteRipe, nonceTrialsPerByte, \
                    payloadLengthExtraBytes = queueValue
                try:
                    numberOfNullBytesDemandedOnFrontOfRipeHash = \
                        BMConfigParser().getint(
                            'bitmessagesettings',
                            'numberofnullbytesonaddress'
                        )
                except:
                    if eighteenByteRipe:
                        numberOfNullBytesDemandedOnFrontOfRipeHash = 2
                    else:
                        # the default
                        numberOfNullBytesDemandedOnFrontOfRipeHash = 1
            elif queueValue[0] == 'stopThread':
                break
            else:
                logger.error(
                    'Programming error: A structure with the wrong number'
                    ' of values was passed into the addressGeneratorQueue.'
                    ' Here is the queueValue: %r\n', queueValue)
            if addressVersionNumber < 3 or addressVersionNumber > 4:
                logger.error(
                    'Program error: For some reason the address generator'
                    ' queue has been given a request to create at least'
                    ' one version %s address which it cannot do.\n',
                    addressVersionNumber)
            if nonceTrialsPerByte == 0:
                nonceTrialsPerByte = BMConfigParser().getint(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
            if nonceTrialsPerByte < \
                    defaults.networkDefaultProofOfWorkNonceTrialsPerByte:
                nonceTrialsPerByte = \
                    defaults.networkDefaultProofOfWorkNonceTrialsPerByte
            if payloadLengthExtraBytes == 0:
                payloadLengthExtraBytes = BMConfigParser().getint(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            if payloadLengthExtraBytes < \
                    defaults.networkDefaultPayloadLengthExtraBytes:
                payloadLengthExtraBytes = \
                    defaults.networkDefaultPayloadLengthExtraBytes
            if command == 'createRandomAddress':
                queues.UISignalQueue.put((
                    'updateStatusBar',
                    tr._translate(
                        "MainWindow", "Generating one new address")
                ))
                # This next section is a little bit strange. We're going
                # to generate keys over and over until we find one
                # that starts with either \x00 or \x00\x00. Then when
                # we pack them into a Bitmessage address, we won't store
                # the \x00 or \x00\x00 bytes thus making the address shorter.
                startTime = time.time()
                numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
                potentialPrivSigningKey = OpenSSL.rand(32)
                potentialPubSigningKey = highlevelcrypto.pointMult(
                    potentialPrivSigningKey)
                while True:
                    numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
                    potentialPrivEncryptionKey = OpenSSL.rand(32)
                    potentialPubEncryptionKey = highlevelcrypto.pointMult(
                        potentialPrivEncryptionKey)
                    ripe = hashlib.new('ripemd160')
                    sha = hashlib.new('sha512')
                    sha.update(
                        potentialPubSigningKey + potentialPubEncryptionKey)
                    ripe.update(sha.digest())
                    if ripe.digest()[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash:
                        break
                logger.info(
                    'Generated address with ripe digest: %s',
                    hexlify(ripe.digest()))
                try:
                    logger.info(
                        'Address generator calculated %s addresses at %s'
                        ' addresses per second before finding one with'
                        ' the correct ripe-prefix.',
                        numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix,
                        numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix
                        / (time.time() - startTime))
                except ZeroDivisionError:
                    # The user must have a pretty fast computer.
                    # time.time() - startTime equaled zero.
                    pass
                address = encodeAddress(
                    addressVersionNumber, streamNumber, ripe.digest())

                # An excellent way for us to store our keys
                # is in Wallet Import Format. Let us convert now.
                # https://en.bitcoin.it/wiki/Wallet_import_format
                privSigningKey = '\x80' + potentialPrivSigningKey
                checksum = hashlib.sha256(hashlib.sha256(
                    privSigningKey).digest()).digest()[0:4]
                privSigningKeyWIF = arithmetic.changebase(
                    privSigningKey + checksum, 256, 58)

                privEncryptionKey = '\x80' + potentialPrivEncryptionKey
                checksum = hashlib.sha256(hashlib.sha256(
                    privEncryptionKey).digest()).digest()[0:4]
                privEncryptionKeyWIF = arithmetic.changebase(
                    privEncryptionKey + checksum, 256, 58)

                BMConfigParser().add_section(address)
                BMConfigParser().set(address, 'label', label)
                BMConfigParser().set(address, 'enabled', 'true')
                BMConfigParser().set(address, 'decoy', 'false')
                BMConfigParser().set(address, 'noncetrialsperbyte', str(
                    nonceTrialsPerByte))
                BMConfigParser().set(address, 'payloadlengthextrabytes', str(
                    payloadLengthExtraBytes))
                BMConfigParser().set(
                    address, 'privsigningkey', privSigningKeyWIF)
                BMConfigParser().set(
                    address, 'privencryptionkey', privEncryptionKeyWIF)
                BMConfigParser().save()

                # The API and the join and create Chan functionality
                # both need information back from the address generator.
                queues.apiAddressGeneratorReturnQueue.put(address)

                queues.UISignalQueue.put((
                    'updateStatusBar',
                    tr._translate(
                        "MainWindow",
                        "Done generating address. Doing work necessary"
                        " to broadcast it...")
                ))
                queues.UISignalQueue.put(('writeNewAddressToTable', (
                    label, address, streamNumber)))
                shared.reloadMyAddressHashes()
                if addressVersionNumber == 3:
                    queues.workerQueue.put((
                        'sendOutOrStoreMyV3Pubkey', ripe.digest()))
                elif addressVersionNumber == 4:
                    queues.workerQueue.put((
                        'sendOutOrStoreMyV4Pubkey', address))

            elif command == 'createDeterministicAddresses' \
                    or command == 'getDeterministicAddress' \
                    or command == 'createChan' or command == 'joinChan':
                if len(deterministicPassphrase) == 0:
                    logger.warning(
                        'You are creating deterministic'
                        ' address(es) using a blank passphrase.'
                        ' Bitmessage will do it but it is rather stupid.')
                if command == 'createDeterministicAddresses':
                    queues.UISignalQueue.put((
                        'updateStatusBar',
                        tr._translate(
                            "MainWindow",
                            "Generating %1 new addresses."
                        ).arg(str(numberOfAddressesToMake))
                    ))
                signingKeyNonce = 0
                encryptionKeyNonce = 1
                # We fill out this list no matter what although we only
                # need it if we end up passing the info to the API.
                listOfNewAddressesToSendOutThroughTheAPI = []

                for _ in range(numberOfAddressesToMake):
                    # This next section is a little bit strange. We're
                    # going to generate keys over and over until we find
                    # one that has a RIPEMD hash that starts with either
                    # \x00 or \x00\x00. Then when we pack them into a
                    # Bitmessage address, we won't store the \x00 or
                    # \x00\x00 bytes thus making the address shorter.
                    startTime = time.time()
                    numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
                    while True:
                        numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
                        potentialPrivSigningKey = hashlib.sha512(
                            deterministicPassphrase +
                            encodeVarint(signingKeyNonce)
                        ).digest()[:32]
                        potentialPrivEncryptionKey = hashlib.sha512(
                            deterministicPassphrase +
                            encodeVarint(encryptionKeyNonce)
                        ).digest()[:32]
                        potentialPubSigningKey = highlevelcrypto.pointMult(
                            potentialPrivSigningKey)
                        potentialPubEncryptionKey = highlevelcrypto.pointMult(
                            potentialPrivEncryptionKey)
                        signingKeyNonce += 2
                        encryptionKeyNonce += 2
                        ripe = hashlib.new('ripemd160')
                        sha = hashlib.new('sha512')
                        sha.update(
                            potentialPubSigningKey + potentialPubEncryptionKey)
                        ripe.update(sha.digest())
                        if ripe.digest()[:numberOfNullBytesDemandedOnFrontOfRipeHash] == '\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash:
                            break

                    logger.info(
                        'Generated address with ripe digest: %s',
                        hexlify(ripe.digest()))
                    try:
                        logger.info(
                            'Address generator calculated %s addresses'
                            ' at %s addresses per second before finding'
                            ' one with the correct ripe-prefix.',
                            numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix,
                            numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix /
                            (time.time() - startTime)
                        )
                    except ZeroDivisionError:
                        # The user must have a pretty fast computer.
                        # time.time() - startTime equaled zero.
                        pass
                    address = encodeAddress(
                        addressVersionNumber, streamNumber, ripe.digest())

                    saveAddressToDisk = True
                    # If we are joining an existing chan, let us check
                    # to make sure it matches the provided Bitmessage address
                    if command == 'joinChan':
                        if address != chanAddress:
                            listOfNewAddressesToSendOutThroughTheAPI.append(
                                'chan name does not match address')
                            saveAddressToDisk = False
                    if command == 'getDeterministicAddress':
                        saveAddressToDisk = False

                    if saveAddressToDisk and live:
                        # An excellent way for us to store our keys is
                        # in Wallet Import Format. Let us convert now.
                        # https://en.bitcoin.it/wiki/Wallet_import_format
                        privSigningKey = '\x80' + potentialPrivSigningKey
                        checksum = hashlib.sha256(hashlib.sha256(
                            privSigningKey).digest()).digest()[0:4]
                        privSigningKeyWIF = arithmetic.changebase(
                            privSigningKey + checksum, 256, 58)

                        privEncryptionKey = '\x80' + \
                            potentialPrivEncryptionKey
                        checksum = hashlib.sha256(hashlib.sha256(
                            privEncryptionKey).digest()).digest()[0:4]
                        privEncryptionKeyWIF = arithmetic.changebase(
                            privEncryptionKey + checksum, 256, 58)

                        try:
                            BMConfigParser().add_section(address)
                            addressAlreadyExists = False
                        except:
                            addressAlreadyExists = True

                        if addressAlreadyExists:
                            logger.info(
                                '%s already exists. Not adding it again.',
                                address
                            )
                            queues.UISignalQueue.put((
                                'updateStatusBar',
                                tr._translate(
                                    "MainWindow",
                                    "%1 is already in 'Your Identities'."
                                    " Not adding it again."
                                ).arg(address)
                            ))
                        else:
                            logger.debug('label: %s', label)
                            BMConfigParser().set(address, 'label', label)
                            BMConfigParser().set(address, 'enabled', 'true')
                            BMConfigParser().set(address, 'decoy', 'false')
                            if command == 'joinChan' \
                                    or command == 'createChan':
                                BMConfigParser().set(address, 'chan', 'true')
                            BMConfigParser().set(
                                address, 'noncetrialsperbyte',
                                str(nonceTrialsPerByte))
                            BMConfigParser().set(
                                address, 'payloadlengthextrabytes',
                                str(payloadLengthExtraBytes))
                            BMConfigParser().set(
                                address, 'privSigningKey',
                                privSigningKeyWIF)
                            BMConfigParser().set(
                                address, 'privEncryptionKey',
                                privEncryptionKeyWIF)
                            BMConfigParser().save()

                            queues.UISignalQueue.put((
                                'writeNewAddressToTable',
                                (label, address, str(streamNumber))
                            ))
                            listOfNewAddressesToSendOutThroughTheAPI.append(
                                address)
                            shared.myECCryptorObjects[ripe.digest()] = \
                                highlevelcrypto.makeCryptor(
                                hexlify(potentialPrivEncryptionKey))
                            shared.myAddressesByHash[ripe.digest()] = address
                            tag = hashlib.sha512(hashlib.sha512(
                                encodeVarint(addressVersionNumber) +
                                encodeVarint(streamNumber) + ripe.digest()
                            ).digest()).digest()[32:]
                            shared.myAddressesByTag[tag] = address
                            if addressVersionNumber == 3:
                                # If this is a chan address,
                                # the worker thread won't send out
                                # the pubkey over the network.
                                queues.workerQueue.put((
                                    'sendOutOrStoreMyV3Pubkey', ripe.digest()))
                            elif addressVersionNumber == 4:
                                queues.workerQueue.put((
                                    'sendOutOrStoreMyV4Pubkey', address))
                            queues.UISignalQueue.put((
                                'updateStatusBar',
                                tr._translate(
                                    "MainWindow", "Done generating address")
                            ))
                    elif saveAddressToDisk and not live \
                            and not BMConfigParser().has_section(address):
                        listOfNewAddressesToSendOutThroughTheAPI.append(
                            address)

                # Done generating addresses.
                if command == 'createDeterministicAddresses' \
                        or command == 'joinChan' or command == 'createChan':
                    queues.apiAddressGeneratorReturnQueue.put(
                        listOfNewAddressesToSendOutThroughTheAPI)
                elif command == 'getDeterministicAddress':
                    queues.apiAddressGeneratorReturnQueue.put(address)
            else:
                raise Exception(
                    "Error in the addressGenerator thread. Thread was" +
                    " given a command it could not understand: " + command)
            queues.addressGeneratorQueue.task_done()
Exemplo n.º 9
0
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(885, 580)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-24px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        MainWindow.setTabShape(QtGui.QTabWidget.Rounded)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.gridLayout_10 = QtGui.QGridLayout(self.centralwidget)
        self.gridLayout_10.setObjectName(_fromUtf8("gridLayout_10"))
        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth())
        self.tabWidget.setSizePolicy(sizePolicy)
        self.tabWidget.setMinimumSize(QtCore.QSize(0, 0))
        self.tabWidget.setBaseSize(QtCore.QSize(0, 0))
        font = QtGui.QFont()
        font.setPointSize(9)
        self.tabWidget.setFont(font)
        self.tabWidget.setTabPosition(QtGui.QTabWidget.North)
        self.tabWidget.setTabShape(QtGui.QTabWidget.Rounded)
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.inbox = QtGui.QWidget()
        self.inbox.setObjectName(_fromUtf8("inbox"))
        self.gridLayout = QtGui.QGridLayout(self.inbox)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.horizontalSplitter_3 = settingsmixin.SSplitter()
        self.horizontalSplitter_3.setObjectName(_fromUtf8("horizontalSplitter_3"))
        self.verticalSplitter_12 = settingsmixin.SSplitter()
        self.verticalSplitter_12.setObjectName(_fromUtf8("verticalSplitter_12"))
        self.verticalSplitter_12.setOrientation(QtCore.Qt.Vertical)
        self.treeWidgetYourIdentities = settingsmixin.STreeWidget(self.inbox)
        self.treeWidgetYourIdentities.setObjectName(_fromUtf8("treeWidgetYourIdentities"))
        self.treeWidgetYourIdentities.resize(200, self.treeWidgetYourIdentities.height())
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/identities.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
        self.treeWidgetYourIdentities.headerItem().setIcon(0, icon1)
        self.verticalSplitter_12.addWidget(self.treeWidgetYourIdentities)
        self.pushButtonNewAddress = QtGui.QPushButton(self.inbox)
        self.pushButtonNewAddress.setObjectName(_fromUtf8("pushButtonNewAddress"))
        self.pushButtonNewAddress.resize(200, self.pushButtonNewAddress.height())
        self.verticalSplitter_12.addWidget(self.pushButtonNewAddress)
        self.verticalSplitter_12.setStretchFactor(0, 1)
        self.verticalSplitter_12.setStretchFactor(1, 0)
        self.verticalSplitter_12.setCollapsible(0, False)
        self.verticalSplitter_12.setCollapsible(1, False)
        self.verticalSplitter_12.handle(1).setEnabled(False)
        self.horizontalSplitter_3.addWidget(self.verticalSplitter_12)
        self.verticalSplitter_7 = settingsmixin.SSplitter()
        self.verticalSplitter_7.setObjectName(_fromUtf8("verticalSplitter_7"))
        self.verticalSplitter_7.setOrientation(QtCore.Qt.Vertical)
        self.horizontalSplitterSearch = QtGui.QSplitter()
        self.horizontalSplitterSearch.setObjectName(_fromUtf8("horizontalSplitterSearch"))
        self.inboxSearchLineEdit = QtGui.QLineEdit(self.inbox)
        self.inboxSearchLineEdit.setObjectName(_fromUtf8("inboxSearchLineEdit"))
        self.horizontalSplitterSearch.addWidget(self.inboxSearchLineEdit)
        self.inboxSearchOption = QtGui.QComboBox(self.inbox)
        self.inboxSearchOption.setObjectName(_fromUtf8("inboxSearchOption"))
        self.inboxSearchOption.addItem(_fromUtf8(""))
        self.inboxSearchOption.addItem(_fromUtf8(""))
        self.inboxSearchOption.addItem(_fromUtf8(""))
        self.inboxSearchOption.addItem(_fromUtf8(""))
        self.inboxSearchOption.addItem(_fromUtf8(""))
        self.inboxSearchOption.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
        self.horizontalSplitterSearch.addWidget(self.inboxSearchOption)
        self.horizontalSplitterSearch.handle(1).setEnabled(False)
        self.horizontalSplitterSearch.setStretchFactor(0, 1)
        self.horizontalSplitterSearch.setStretchFactor(1, 0)
        self.verticalSplitter_7.addWidget(self.horizontalSplitterSearch)
        self.tableWidgetInbox = settingsmixin.STableWidget(self.inbox)
        self.tableWidgetInbox.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.tableWidgetInbox.setAlternatingRowColors(True)
        self.tableWidgetInbox.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableWidgetInbox.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableWidgetInbox.setWordWrap(False)
        self.tableWidgetInbox.setObjectName(_fromUtf8("tableWidgetInbox"))
        self.tableWidgetInbox.setColumnCount(4)
        self.tableWidgetInbox.setRowCount(0)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInbox.setHorizontalHeaderItem(0, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInbox.setHorizontalHeaderItem(1, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInbox.setHorizontalHeaderItem(2, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInbox.setHorizontalHeaderItem(3, item)
        self.tableWidgetInbox.horizontalHeader().setCascadingSectionResizes(True)
        self.tableWidgetInbox.horizontalHeader().setDefaultSectionSize(200)
        self.tableWidgetInbox.horizontalHeader().setHighlightSections(False)
        self.tableWidgetInbox.horizontalHeader().setMinimumSectionSize(27)
        self.tableWidgetInbox.horizontalHeader().setSortIndicatorShown(False)
        self.tableWidgetInbox.horizontalHeader().setStretchLastSection(True)
        self.tableWidgetInbox.verticalHeader().setVisible(False)
        self.tableWidgetInbox.verticalHeader().setDefaultSectionSize(26)
        self.verticalSplitter_7.addWidget(self.tableWidgetInbox)
        self.textEditInboxMessage = MessageView(self.inbox)
        self.textEditInboxMessage.setBaseSize(QtCore.QSize(0, 500))
        self.textEditInboxMessage.setReadOnly(True)
        self.textEditInboxMessage.setObjectName(_fromUtf8("textEditInboxMessage"))
        self.verticalSplitter_7.addWidget(self.textEditInboxMessage)
        self.verticalSplitter_7.setStretchFactor(0, 0)
        self.verticalSplitter_7.setStretchFactor(1, 1)
        self.verticalSplitter_7.setStretchFactor(2, 2)
        self.verticalSplitter_7.setCollapsible(0, False)
        self.verticalSplitter_7.setCollapsible(1, False)
        self.verticalSplitter_7.setCollapsible(2, False)
        self.verticalSplitter_7.handle(1).setEnabled(False)
        self.horizontalSplitter_3.addWidget(self.verticalSplitter_7)
        self.horizontalSplitter_3.setStretchFactor(0, 0)
        self.horizontalSplitter_3.setStretchFactor(1, 1)
        self.horizontalSplitter_3.setCollapsible(0, False)
        self.horizontalSplitter_3.setCollapsible(1, False)
        self.gridLayout.addWidget(self.horizontalSplitter_3)
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/inbox.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.tabWidget.addTab(self.inbox, icon2, _fromUtf8(""))
        self.send = QtGui.QWidget()
        self.send.setObjectName(_fromUtf8("send"))
        self.gridLayout_7 = QtGui.QGridLayout(self.send)
        self.gridLayout_7.setObjectName(_fromUtf8("gridLayout_7"))
        self.horizontalSplitter = settingsmixin.SSplitter()
        self.horizontalSplitter.setObjectName(_fromUtf8("horizontalSplitter"))
        self.verticalSplitter_2 = settingsmixin.SSplitter()
        self.verticalSplitter_2.setObjectName(_fromUtf8("verticalSplitter_2"))
        self.verticalSplitter_2.setOrientation(QtCore.Qt.Vertical)
        self.tableWidgetAddressBook = settingsmixin.STableWidget(self.send)
        self.tableWidgetAddressBook.setAlternatingRowColors(True)
        self.tableWidgetAddressBook.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableWidgetAddressBook.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableWidgetAddressBook.setObjectName(_fromUtf8("tableWidgetAddressBook"))
        self.tableWidgetAddressBook.setColumnCount(2)
        self.tableWidgetAddressBook.setRowCount(0)
        self.tableWidgetAddressBook.resize(200, self.tableWidgetAddressBook.height())
        item = QtGui.QTableWidgetItem()
        icon3 = QtGui.QIcon()
        icon3.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/addressbook.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
        item.setIcon(icon3)
        self.tableWidgetAddressBook.setHorizontalHeaderItem(0, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetAddressBook.setHorizontalHeaderItem(1, item)
        self.tableWidgetAddressBook.horizontalHeader().setCascadingSectionResizes(True)
        self.tableWidgetAddressBook.horizontalHeader().setDefaultSectionSize(200)
        self.tableWidgetAddressBook.horizontalHeader().setHighlightSections(False)
        self.tableWidgetAddressBook.horizontalHeader().setStretchLastSection(True)
        self.tableWidgetAddressBook.verticalHeader().setVisible(False)
        self.verticalSplitter_2.addWidget(self.tableWidgetAddressBook)
        self.addressBookCompleter = AddressBookCompleter()
        self.addressBookCompleter.setCompletionMode(QtGui.QCompleter.PopupCompletion)
        self.addressBookCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.addressBookCompleterModel = QtGui.QStringListModel()
        self.addressBookCompleter.setModel(self.addressBookCompleterModel)
        self.pushButtonAddAddressBook = QtGui.QPushButton(self.send)
        self.pushButtonAddAddressBook.setObjectName(_fromUtf8("pushButtonAddAddressBook"))
        self.pushButtonAddAddressBook.resize(200, self.pushButtonAddAddressBook.height())
        self.verticalSplitter_2.addWidget(self.pushButtonAddAddressBook)
        self.verticalSplitter_2.setStretchFactor(0, 1)
        self.verticalSplitter_2.setStretchFactor(1, 0)
        self.verticalSplitter_2.setCollapsible(0, False)
        self.verticalSplitter_2.setCollapsible(1, False)
        self.verticalSplitter_2.handle(1).setEnabled(False)
        self.horizontalSplitter.addWidget(self.verticalSplitter_2)
        self.verticalSplitter = settingsmixin.SSplitter()
        self.verticalSplitter.setObjectName(_fromUtf8("verticalSplitter"))
        self.verticalSplitter.setOrientation(QtCore.Qt.Vertical)
        self.tabWidgetSend = QtGui.QTabWidget(self.send)
        self.tabWidgetSend.setObjectName(_fromUtf8("tabWidgetSend"))
        self.sendDirect = QtGui.QWidget()
        self.sendDirect.setObjectName(_fromUtf8("sendDirect"))
        self.gridLayout_8 = QtGui.QGridLayout(self.sendDirect)
        self.gridLayout_8.setObjectName(_fromUtf8("gridLayout_8"))
        self.verticalSplitter_5 = settingsmixin.SSplitter()
        self.verticalSplitter_5.setObjectName(_fromUtf8("verticalSplitter_5"))
        self.verticalSplitter_5.setOrientation(QtCore.Qt.Vertical)
        self.gridLayout_2 = QtGui.QGridLayout()
        self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
        self.label_3 = QtGui.QLabel(self.sendDirect)
        self.label_3.setObjectName(_fromUtf8("label_3"))
        self.gridLayout_2.addWidget(self.label_3, 2, 0, 1, 1)
        self.label_2 = QtGui.QLabel(self.sendDirect)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
        self.lineEditSubject = QtGui.QLineEdit(self.sendDirect)
        self.lineEditSubject.setText(_fromUtf8(""))
        self.lineEditSubject.setObjectName(_fromUtf8("lineEditSubject"))
        self.gridLayout_2.addWidget(self.lineEditSubject, 2, 1, 1, 1)
        self.label = QtGui.QLabel(self.sendDirect)
        self.label.setObjectName(_fromUtf8("label"))
        self.gridLayout_2.addWidget(self.label, 1, 0, 1, 1)
        self.comboBoxSendFrom = QtGui.QComboBox(self.sendDirect)
        self.comboBoxSendFrom.setMinimumSize(QtCore.QSize(300, 0))
        self.comboBoxSendFrom.setObjectName(_fromUtf8("comboBoxSendFrom"))
        self.gridLayout_2.addWidget(self.comboBoxSendFrom, 0, 1, 1, 1)
        self.lineEditTo = QtGui.QLineEdit(self.sendDirect)
        self.lineEditTo.setObjectName(_fromUtf8("lineEditTo"))
        self.gridLayout_2.addWidget(self.lineEditTo, 1, 1, 1, 1)
        self.lineEditTo.setCompleter(self.addressBookCompleter)
        self.gridLayout_2_Widget = QtGui.QWidget()
        self.gridLayout_2_Widget.setLayout(self.gridLayout_2)
        self.verticalSplitter_5.addWidget(self.gridLayout_2_Widget)
        self.textEditMessage = MessageCompose(self.sendDirect)
        self.textEditMessage.setObjectName(_fromUtf8("textEditMessage"))
        self.verticalSplitter_5.addWidget(self.textEditMessage)
        self.verticalSplitter_5.setStretchFactor(0, 0)
        self.verticalSplitter_5.setStretchFactor(1, 1)
        self.verticalSplitter_5.setCollapsible(0, False)
        self.verticalSplitter_5.setCollapsible(1, False)
        self.verticalSplitter_5.handle(1).setEnabled(False)
        self.gridLayout_8.addWidget(self.verticalSplitter_5, 0, 0, 1, 1)
        self.tabWidgetSend.addTab(self.sendDirect, _fromUtf8(""))
        self.sendBroadcast = QtGui.QWidget()
        self.sendBroadcast.setObjectName(_fromUtf8("sendBroadcast"))
        self.gridLayout_9 = QtGui.QGridLayout(self.sendBroadcast)
        self.gridLayout_9.setObjectName(_fromUtf8("gridLayout_9"))
        self.verticalSplitter_6 = settingsmixin.SSplitter()
        self.verticalSplitter_6.setObjectName(_fromUtf8("verticalSplitter_6"))
        self.verticalSplitter_6.setOrientation(QtCore.Qt.Vertical)
        self.gridLayout_5 = QtGui.QGridLayout()
        self.gridLayout_5.setObjectName(_fromUtf8("gridLayout_5"))
        self.label_8 = QtGui.QLabel(self.sendBroadcast)
        self.label_8.setObjectName(_fromUtf8("label_8"))
        self.gridLayout_5.addWidget(self.label_8, 0, 0, 1, 1)
        self.lineEditSubjectBroadcast = QtGui.QLineEdit(self.sendBroadcast)
        self.lineEditSubjectBroadcast.setText(_fromUtf8(""))
        self.lineEditSubjectBroadcast.setObjectName(_fromUtf8("lineEditSubjectBroadcast"))
        self.gridLayout_5.addWidget(self.lineEditSubjectBroadcast, 1, 1, 1, 1)
        self.label_7 = QtGui.QLabel(self.sendBroadcast)
        self.label_7.setObjectName(_fromUtf8("label_7"))
        self.gridLayout_5.addWidget(self.label_7, 1, 0, 1, 1)
        self.comboBoxSendFromBroadcast = QtGui.QComboBox(self.sendBroadcast)
        self.comboBoxSendFromBroadcast.setMinimumSize(QtCore.QSize(300, 0))
        self.comboBoxSendFromBroadcast.setObjectName(_fromUtf8("comboBoxSendFromBroadcast"))
        self.gridLayout_5.addWidget(self.comboBoxSendFromBroadcast, 0, 1, 1, 1)
        self.gridLayout_5_Widget = QtGui.QWidget()
        self.gridLayout_5_Widget.setLayout(self.gridLayout_5)
        self.verticalSplitter_6.addWidget(self.gridLayout_5_Widget)
        self.textEditMessageBroadcast = MessageCompose(self.sendBroadcast)
        self.textEditMessageBroadcast.setObjectName(_fromUtf8("textEditMessageBroadcast"))
        self.verticalSplitter_6.addWidget(self.textEditMessageBroadcast)
        self.verticalSplitter_6.setStretchFactor(0, 0)
        self.verticalSplitter_6.setStretchFactor(1, 1)
        self.verticalSplitter_6.setCollapsible(0, False)
        self.verticalSplitter_6.setCollapsible(1, False)
        self.verticalSplitter_6.handle(1).setEnabled(False)
        self.gridLayout_9.addWidget(self.verticalSplitter_6, 0, 0, 1, 1)
        self.tabWidgetSend.addTab(self.sendBroadcast, _fromUtf8(""))
        self.verticalSplitter.addWidget(self.tabWidgetSend)
        self.tTLContainer = QtGui.QWidget()
        self.tTLContainer.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        self.horizontalLayout_5 = QtGui.QHBoxLayout()
        self.tTLContainer.setLayout(self.horizontalLayout_5)
        self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
        self.pushButtonTTL = QtGui.QPushButton(self.send)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButtonTTL.sizePolicy().hasHeightForWidth())
        self.pushButtonTTL.setSizePolicy(sizePolicy)
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
        brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
        self.pushButtonTTL.setPalette(palette)
        font = QtGui.QFont()
        font.setUnderline(True)
        self.pushButtonTTL.setFont(font)
        self.pushButtonTTL.setFlat(True)
        self.pushButtonTTL.setObjectName(_fromUtf8("pushButtonTTL"))
        self.horizontalLayout_5.addWidget(self.pushButtonTTL, 0, QtCore.Qt.AlignRight)
        self.horizontalSliderTTL = QtGui.QSlider(self.send)
        self.horizontalSliderTTL.setMinimumSize(QtCore.QSize(70, 0))
        self.horizontalSliderTTL.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSliderTTL.setInvertedAppearance(False)
        self.horizontalSliderTTL.setInvertedControls(False)
        self.horizontalSliderTTL.setObjectName(_fromUtf8("horizontalSliderTTL"))
        self.horizontalLayout_5.addWidget(self.horizontalSliderTTL, 0, QtCore.Qt.AlignLeft)
        self.labelHumanFriendlyTTLDescription = QtGui.QLabel(self.send)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.labelHumanFriendlyTTLDescription.sizePolicy().hasHeightForWidth())
        self.labelHumanFriendlyTTLDescription.setSizePolicy(sizePolicy)
        self.labelHumanFriendlyTTLDescription.setMinimumSize(QtCore.QSize(45, 0))
        self.labelHumanFriendlyTTLDescription.setObjectName(_fromUtf8("labelHumanFriendlyTTLDescription"))
        self.horizontalLayout_5.addWidget(self.labelHumanFriendlyTTLDescription, 1, QtCore.Qt.AlignLeft)
        self.pushButtonSend = QtGui.QPushButton(self.send)
        self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
        self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight)
        self.horizontalSliderTTL.setMaximumSize(QtCore.QSize(105, self.pushButtonSend.height()))
        self.verticalSplitter.addWidget(self.tTLContainer)
        self.tTLContainer.adjustSize()
        self.verticalSplitter.setStretchFactor(1, 0)
        self.verticalSplitter.setStretchFactor(0, 1)
        self.verticalSplitter.setCollapsible(0, False)
        self.verticalSplitter.setCollapsible(1, False)
        self.verticalSplitter.handle(1).setEnabled(False)
        self.horizontalSplitter.addWidget(self.verticalSplitter)
        self.horizontalSplitter.setStretchFactor(0, 0)
        self.horizontalSplitter.setStretchFactor(1, 1)
        self.horizontalSplitter.setCollapsible(0, False)
        self.horizontalSplitter.setCollapsible(1, False)
        self.gridLayout_7.addWidget(self.horizontalSplitter, 0, 0, 1, 1)
        icon4 = QtGui.QIcon()
        icon4.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/send.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.tabWidget.addTab(self.send, icon4, _fromUtf8(""))
        self.subscriptions = QtGui.QWidget()
        self.subscriptions.setObjectName(_fromUtf8("subscriptions"))
        self.gridLayout_3 = QtGui.QGridLayout(self.subscriptions)
        self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
        self.horizontalSplitter_4 = settingsmixin.SSplitter()
        self.horizontalSplitter_4.setObjectName(_fromUtf8("horizontalSplitter_4"))
        self.verticalSplitter_3 = settingsmixin.SSplitter()
        self.verticalSplitter_3.setObjectName(_fromUtf8("verticalSplitter_3"))
        self.verticalSplitter_3.setOrientation(QtCore.Qt.Vertical)
        self.treeWidgetSubscriptions = settingsmixin.STreeWidget(self.subscriptions)
        self.treeWidgetSubscriptions.setAlternatingRowColors(True)
        self.treeWidgetSubscriptions.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self.treeWidgetSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.treeWidgetSubscriptions.setObjectName(_fromUtf8("treeWidgetSubscriptions"))
        self.treeWidgetSubscriptions.resize(200, self.treeWidgetSubscriptions.height())
        icon5 = QtGui.QIcon()
        icon5.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
        self.treeWidgetSubscriptions.headerItem().setIcon(0, icon5)
        self.verticalSplitter_3.addWidget(self.treeWidgetSubscriptions)
        self.pushButtonAddSubscription = QtGui.QPushButton(self.subscriptions)
        self.pushButtonAddSubscription.setObjectName(_fromUtf8("pushButtonAddSubscription"))
        self.pushButtonAddSubscription.resize(200, self.pushButtonAddSubscription.height())
        self.verticalSplitter_3.addWidget(self.pushButtonAddSubscription)
        self.verticalSplitter_3.setStretchFactor(0, 1)
        self.verticalSplitter_3.setStretchFactor(1, 0)
        self.verticalSplitter_3.setCollapsible(0, False)
        self.verticalSplitter_3.setCollapsible(1, False)
        self.verticalSplitter_3.handle(1).setEnabled(False)
        self.horizontalSplitter_4.addWidget(self.verticalSplitter_3)
        self.verticalSplitter_4 = settingsmixin.SSplitter()
        self.verticalSplitter_4.setObjectName(_fromUtf8("verticalSplitter_4"))
        self.verticalSplitter_4.setOrientation(QtCore.Qt.Vertical)
        self.horizontalSplitter_2 = QtGui.QSplitter()
        self.horizontalSplitter_2.setObjectName(_fromUtf8("horizontalSplitter_2"))
        self.inboxSearchLineEditSubscriptions = QtGui.QLineEdit(self.subscriptions)
        self.inboxSearchLineEditSubscriptions.setObjectName(_fromUtf8("inboxSearchLineEditSubscriptions"))
        self.horizontalSplitter_2.addWidget(self.inboxSearchLineEditSubscriptions)
        self.inboxSearchOptionSubscriptions = QtGui.QComboBox(self.subscriptions)
        self.inboxSearchOptionSubscriptions.setObjectName(_fromUtf8("inboxSearchOptionSubscriptions"))
        self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
        self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
        self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
        self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
        self.inboxSearchOptionSubscriptions.addItem(_fromUtf8(""))
        self.inboxSearchOptionSubscriptions.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
        self.horizontalSplitter_2.addWidget(self.inboxSearchOptionSubscriptions)
        self.horizontalSplitter_2.handle(1).setEnabled(False)
        self.horizontalSplitter_2.setStretchFactor(0, 1)
        self.horizontalSplitter_2.setStretchFactor(1, 0)
        self.verticalSplitter_4.addWidget(self.horizontalSplitter_2)
        self.tableWidgetInboxSubscriptions = settingsmixin.STableWidget(self.subscriptions)
        self.tableWidgetInboxSubscriptions.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.tableWidgetInboxSubscriptions.setAlternatingRowColors(True)
        self.tableWidgetInboxSubscriptions.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableWidgetInboxSubscriptions.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableWidgetInboxSubscriptions.setWordWrap(False)
        self.tableWidgetInboxSubscriptions.setObjectName(_fromUtf8("tableWidgetInboxSubscriptions"))
        self.tableWidgetInboxSubscriptions.setColumnCount(4)
        self.tableWidgetInboxSubscriptions.setRowCount(0)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(0, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(1, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(2, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxSubscriptions.setHorizontalHeaderItem(3, item)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setCascadingSectionResizes(True)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setDefaultSectionSize(200)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setHighlightSections(False)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setMinimumSectionSize(27)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setSortIndicatorShown(False)
        self.tableWidgetInboxSubscriptions.horizontalHeader().setStretchLastSection(True)
        self.tableWidgetInboxSubscriptions.verticalHeader().setVisible(False)
        self.tableWidgetInboxSubscriptions.verticalHeader().setDefaultSectionSize(26)
        self.verticalSplitter_4.addWidget(self.tableWidgetInboxSubscriptions)
        self.textEditInboxMessageSubscriptions = MessageView(self.subscriptions)
        self.textEditInboxMessageSubscriptions.setBaseSize(QtCore.QSize(0, 500))
        self.textEditInboxMessageSubscriptions.setReadOnly(True)
        self.textEditInboxMessageSubscriptions.setObjectName(_fromUtf8("textEditInboxMessageSubscriptions"))
        self.verticalSplitter_4.addWidget(self.textEditInboxMessageSubscriptions)
        self.verticalSplitter_4.setStretchFactor(0, 0)
        self.verticalSplitter_4.setStretchFactor(1, 1)
        self.verticalSplitter_4.setStretchFactor(2, 2)
        self.verticalSplitter_4.setCollapsible(0, False)
        self.verticalSplitter_4.setCollapsible(1, False)
        self.verticalSplitter_4.setCollapsible(2, False)
        self.verticalSplitter_4.handle(1).setEnabled(False)
        self.horizontalSplitter_4.addWidget(self.verticalSplitter_4)
        self.horizontalSplitter_4.setStretchFactor(0, 0)
        self.horizontalSplitter_4.setStretchFactor(1, 1)
        self.horizontalSplitter_4.setCollapsible(0, False)
        self.horizontalSplitter_4.setCollapsible(1, False)
        self.gridLayout_3.addWidget(self.horizontalSplitter_4, 0, 0, 1, 1)
        icon6 = QtGui.QIcon()
        icon6.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/subscriptions.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.tabWidget.addTab(self.subscriptions, icon6, _fromUtf8(""))
        self.chans = QtGui.QWidget()
        self.chans.setObjectName(_fromUtf8("chans"))
        self.gridLayout_4 = QtGui.QGridLayout(self.chans)
        self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
        self.horizontalSplitter_7 = settingsmixin.SSplitter()
        self.horizontalSplitter_7.setObjectName(_fromUtf8("horizontalSplitter_7"))
        self.verticalSplitter_17 = settingsmixin.SSplitter()
        self.verticalSplitter_17.setObjectName(_fromUtf8("verticalSplitter_17"))
        self.verticalSplitter_17.setOrientation(QtCore.Qt.Vertical)
        self.treeWidgetChans = settingsmixin.STreeWidget(self.chans)
        self.treeWidgetChans.setFrameShadow(QtGui.QFrame.Sunken)
        self.treeWidgetChans.setLineWidth(1)
        self.treeWidgetChans.setAlternatingRowColors(True)
        self.treeWidgetChans.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self.treeWidgetChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.treeWidgetChans.setObjectName(_fromUtf8("treeWidgetChans"))
        self.treeWidgetChans.resize(200, self.treeWidgetChans.height())
        icon7 = QtGui.QIcon()
        icon7.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Selected, QtGui.QIcon.Off)
        self.treeWidgetChans.headerItem().setIcon(0, icon7)
        self.verticalSplitter_17.addWidget(self.treeWidgetChans)
        self.pushButtonAddChan = QtGui.QPushButton(self.chans)
        self.pushButtonAddChan.setObjectName(_fromUtf8("pushButtonAddChan"))
        self.pushButtonAddChan.resize(200, self.pushButtonAddChan.height())
        self.verticalSplitter_17.addWidget(self.pushButtonAddChan)
        self.verticalSplitter_17.setStretchFactor(0, 1)
        self.verticalSplitter_17.setStretchFactor(1, 0)
        self.verticalSplitter_17.setCollapsible(0, False)
        self.verticalSplitter_17.setCollapsible(1, False)
        self.verticalSplitter_17.handle(1).setEnabled(False)
        self.horizontalSplitter_7.addWidget(self.verticalSplitter_17)
        self.verticalSplitter_8 = settingsmixin.SSplitter()
        self.verticalSplitter_8.setObjectName(_fromUtf8("verticalSplitter_8"))
        self.verticalSplitter_8.setOrientation(QtCore.Qt.Vertical)
        self.horizontalSplitter_6 = QtGui.QSplitter()
        self.horizontalSplitter_6.setObjectName(_fromUtf8("horizontalSplitter_6"))
        self.inboxSearchLineEditChans = QtGui.QLineEdit(self.chans)
        self.inboxSearchLineEditChans.setObjectName(_fromUtf8("inboxSearchLineEditChans"))
        self.horizontalSplitter_6.addWidget(self.inboxSearchLineEditChans)
        self.inboxSearchOptionChans = QtGui.QComboBox(self.chans)
        self.inboxSearchOptionChans.setObjectName(_fromUtf8("inboxSearchOptionChans"))
        self.inboxSearchOptionChans.addItem(_fromUtf8(""))
        self.inboxSearchOptionChans.addItem(_fromUtf8(""))
        self.inboxSearchOptionChans.addItem(_fromUtf8(""))
        self.inboxSearchOptionChans.addItem(_fromUtf8(""))
        self.inboxSearchOptionChans.addItem(_fromUtf8(""))
        self.inboxSearchOptionChans.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
        self.horizontalSplitter_6.addWidget(self.inboxSearchOptionChans)
        self.horizontalSplitter_6.handle(1).setEnabled(False)
        self.horizontalSplitter_6.setStretchFactor(0, 1)
        self.horizontalSplitter_6.setStretchFactor(1, 0)
        self.verticalSplitter_8.addWidget(self.horizontalSplitter_6)
        self.tableWidgetInboxChans = settingsmixin.STableWidget(self.chans)
        self.tableWidgetInboxChans.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.tableWidgetInboxChans.setAlternatingRowColors(True)
        self.tableWidgetInboxChans.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.tableWidgetInboxChans.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.tableWidgetInboxChans.setWordWrap(False)
        self.tableWidgetInboxChans.setObjectName(_fromUtf8("tableWidgetInboxChans"))
        self.tableWidgetInboxChans.setColumnCount(4)
        self.tableWidgetInboxChans.setRowCount(0)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxChans.setHorizontalHeaderItem(0, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxChans.setHorizontalHeaderItem(1, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxChans.setHorizontalHeaderItem(2, item)
        item = QtGui.QTableWidgetItem()
        self.tableWidgetInboxChans.setHorizontalHeaderItem(3, item)
        self.tableWidgetInboxChans.horizontalHeader().setCascadingSectionResizes(True)
        self.tableWidgetInboxChans.horizontalHeader().setDefaultSectionSize(200)
        self.tableWidgetInboxChans.horizontalHeader().setHighlightSections(False)
        self.tableWidgetInboxChans.horizontalHeader().setMinimumSectionSize(27)
        self.tableWidgetInboxChans.horizontalHeader().setSortIndicatorShown(False)
        self.tableWidgetInboxChans.horizontalHeader().setStretchLastSection(True)
        self.tableWidgetInboxChans.verticalHeader().setVisible(False)
        self.tableWidgetInboxChans.verticalHeader().setDefaultSectionSize(26)
        self.verticalSplitter_8.addWidget(self.tableWidgetInboxChans)
        self.textEditInboxMessageChans = MessageView(self.chans)
        self.textEditInboxMessageChans.setBaseSize(QtCore.QSize(0, 500))
        self.textEditInboxMessageChans.setReadOnly(True)
        self.textEditInboxMessageChans.setObjectName(_fromUtf8("textEditInboxMessageChans"))
        self.verticalSplitter_8.addWidget(self.textEditInboxMessageChans)
        self.verticalSplitter_8.setStretchFactor(0, 0)
        self.verticalSplitter_8.setStretchFactor(1, 1)
        self.verticalSplitter_8.setStretchFactor(2, 2)
        self.verticalSplitter_8.setCollapsible(0, False)
        self.verticalSplitter_8.setCollapsible(1, False)
        self.verticalSplitter_8.setCollapsible(2, False)
        self.verticalSplitter_8.handle(1).setEnabled(False)
        self.horizontalSplitter_7.addWidget(self.verticalSplitter_8)
        self.horizontalSplitter_7.setStretchFactor(0, 0)
        self.horizontalSplitter_7.setStretchFactor(1, 1)
        self.horizontalSplitter_7.setCollapsible(0, False)
        self.horizontalSplitter_7.setCollapsible(1, False)
        self.gridLayout_4.addWidget(self.horizontalSplitter_7, 0, 0, 1, 1)
        icon8 = QtGui.QIcon()
        icon8.addPixmap(QtGui.QPixmap(_fromUtf8(":/newPrefix/images/can-icon-16px.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.tabWidget.addTab(self.chans, icon8, _fromUtf8(""))
        self.blackwhitelist = Blacklist()
        self.tabWidget.addTab(self.blackwhitelist, QtGui.QIcon(":/newPrefix/images/blacklist.png"), "")
        # Initialize the Blacklist or Whitelist
        if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'white':
            self.blackwhitelist.radioButtonWhitelist.click()
        self.blackwhitelist.rerenderBlackWhiteList()

        self.networkstatus = NetworkStatus()
        self.tabWidget.addTab(self.networkstatus, QtGui.QIcon(":/newPrefix/images/networkstatus.png"), "")
        self.gridLayout_10.addWidget(self.tabWidget, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 885, 27))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuFile = QtGui.QMenu(self.menubar)
        self.menuFile.setObjectName(_fromUtf8("menuFile"))
        self.menuSettings = QtGui.QMenu(self.menubar)
        self.menuSettings.setObjectName(_fromUtf8("menuSettings"))
        self.menuHelp = QtGui.QMenu(self.menubar)
        self.menuHelp.setObjectName(_fromUtf8("menuHelp"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setMaximumSize(QtCore.QSize(16777215, 22))
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.actionImport_keys = QtGui.QAction(MainWindow)
        self.actionImport_keys.setObjectName(_fromUtf8("actionImport_keys"))
        self.actionManageKeys = QtGui.QAction(MainWindow)
        self.actionManageKeys.setCheckable(False)
        self.actionManageKeys.setEnabled(True)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("dialog-password"))
        self.actionManageKeys.setIcon(icon)
        self.actionManageKeys.setObjectName(_fromUtf8("actionManageKeys"))
        self.actionExit = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("application-exit"))
        self.actionExit.setIcon(icon)
        self.actionExit.setObjectName(_fromUtf8("actionExit"))
        self.actionHelp = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("help-contents"))
        self.actionHelp.setIcon(icon)
        self.actionHelp.setObjectName(_fromUtf8("actionHelp"))
        self.actionAbout = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("help-about"))
        self.actionAbout.setIcon(icon)
        self.actionAbout.setObjectName(_fromUtf8("actionAbout"))
        self.actionSettings = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("document-properties"))
        self.actionSettings.setIcon(icon)
        self.actionSettings.setObjectName(_fromUtf8("actionSettings"))
        self.actionRegenerateDeterministicAddresses = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("view-refresh"))
        self.actionRegenerateDeterministicAddresses.setIcon(icon)
        self.actionRegenerateDeterministicAddresses.setObjectName(_fromUtf8("actionRegenerateDeterministicAddresses"))
        self.actionDeleteAllTrashedMessages = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("user-trash"))
        self.actionDeleteAllTrashedMessages.setIcon(icon)
        self.actionDeleteAllTrashedMessages.setObjectName(_fromUtf8("actionDeleteAllTrashedMessages"))
        self.actionJoinChan = QtGui.QAction(MainWindow)
        icon = QtGui.QIcon.fromTheme(_fromUtf8("contact-new"))
        self.actionJoinChan.setIcon(icon)
        self.actionJoinChan.setObjectName(_fromUtf8("actionJoinChan"))
        self.menuFile.addAction(self.actionManageKeys)
        self.menuFile.addAction(self.actionDeleteAllTrashedMessages)
        self.menuFile.addAction(self.actionRegenerateDeterministicAddresses)
        self.menuFile.addAction(self.actionExit)
        self.menuSettings.addAction(self.actionSettings)
        self.menuHelp.addAction(self.actionHelp)
        self.menuHelp.addAction(self.actionAbout)
        self.menubar.addAction(self.menuFile.menuAction())
        self.menubar.addAction(self.menuSettings.menuAction())
        self.menubar.addAction(self.menuHelp.menuAction())

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        self.tabWidgetSend.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        MainWindow.setTabOrder(self.tableWidgetInbox, self.textEditInboxMessage)
        MainWindow.setTabOrder(self.textEditInboxMessage, self.comboBoxSendFrom)
        MainWindow.setTabOrder(self.comboBoxSendFrom, self.lineEditTo)
        MainWindow.setTabOrder(self.lineEditTo, self.lineEditSubject)
        MainWindow.setTabOrder(self.lineEditSubject, self.textEditMessage)
        MainWindow.setTabOrder(self.textEditMessage, self.pushButtonAddSubscription)
Exemplo n.º 10
0
def getSortedAccounts():
    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()))
    return configSections
Exemplo n.º 11
0
    def start(self):
        _fixSocket()

        daemon = BMConfigParser().safeGetBoolean('bitmessagesettings',
                                                 'daemon')

        try:
            opts, args = getopt.getopt(sys.argv[1:], "hcd",
                                       ["help", "curses", "daemon"])

        except getopt.GetoptError:
            self.usage()
            sys.exit(2)

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                self.usage()
                sys.exit()
            elif opt in ("-d", "--daemon"):
                daemon = True
            elif opt in ("-c", "--curses"):
                state.curses = True

        shared.daemon = daemon

        # is the application already running?  If yes then exit.
        shared.thisapp = singleinstance("", daemon)

        if daemon:
            with shared.printLock:
                print('Running as a daemon. Send TERM signal to end.')
            self.daemonize()

        self.setSignalHandler()

        helper_threading.set_thread_name("PyBitmessage")

        helper_bootstrap.knownNodes()
        # Start the address generation thread
        addressGeneratorThread = addressGenerator()
        addressGeneratorThread.daemon = True  # close the main program even if there are threads left
        addressGeneratorThread.start()

        # Start the thread that calculates POWs
        singleWorkerThread = singleWorker()
        singleWorkerThread.daemon = True  # close the main program even if there are threads left
        singleWorkerThread.start()

        # Start the SQL thread
        sqlLookup = sqlThread()
        sqlLookup.daemon = False  # DON'T close the main program even if there are threads left. The closeEvent should command this thread to exit gracefully.
        sqlLookup.start()

        Inventory()  # init
        Dandelion(
        )  # init, needs to be early because other thread may access it early

        # SMTP delivery thread
        if daemon and BMConfigParser().safeGet("bitmessagesettings",
                                               "smtpdeliver", '') != '':
            smtpDeliveryThread = smtpDeliver()
            smtpDeliveryThread.start()

        # SMTP daemon thread
        if daemon and BMConfigParser().safeGetBoolean("bitmessagesettings",
                                                      "smtpd"):
            smtpServerThread = smtpServer()
            smtpServerThread.start()

        # Start the thread that calculates POWs
        objectProcessorThread = objectProcessor()
        objectProcessorThread.daemon = False  # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object.
        objectProcessorThread.start()

        # Start the cleanerThread
        singleCleanerThread = singleCleaner()
        singleCleanerThread.daemon = True  # close the main program even if there are threads left
        singleCleanerThread.start()

        shared.reloadMyAddressHashes()
        shared.reloadBroadcastSendersForWhichImWatching()

        if BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'):
            try:
                apiNotifyPath = BMConfigParser().get('bitmessagesettings',
                                                     'apinotifypath')
            except:
                apiNotifyPath = ''
            if apiNotifyPath != '':
                with shared.printLock:
                    print('Trying to call', apiNotifyPath)

                call([apiNotifyPath, "startingUp"])
            singleAPIThread = singleAPI()
            singleAPIThread.daemon = True  # close the main program even if there are threads left
            singleAPIThread.start()

        BMConnectionPool()
        asyncoreThread = BMNetworkThread()
        asyncoreThread.daemon = True
        asyncoreThread.start()
        for i in range(BMConfigParser().getint("threads", "receive")):
            receiveQueueThread = ReceiveQueueThread(i)
            receiveQueueThread.daemon = True
            receiveQueueThread.start()
        announceThread = AnnounceThread()
        announceThread.daemon = True
        announceThread.start()
        state.invThread = InvThread()
        state.invThread.daemon = True
        state.invThread.start()
        state.addrThread = AddrThread()
        state.addrThread.daemon = True
        state.addrThread.start()
        state.downloadThread = DownloadThread()
        state.downloadThread.daemon = True
        state.downloadThread.start()

        connectToStream(1)

        if BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'):
            import upnp
            upnpThread = upnp.uPnPThread()
            upnpThread.start()

        if daemon == False and BMConfigParser().safeGetBoolean(
                'bitmessagesettings', 'daemon') == False:
            if state.curses == False:
                if not depends.check_pyqt():
                    print(
                        'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download   or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
                    )
                    print(
                        'You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.'
                    )
                    sys.exit()

                import bitmessageqt
                bitmessageqt.run()
            else:
                if True:
                    #                if depends.check_curses():
                    print('Running with curses')
                    import bitmessagecurses
                    bitmessagecurses.runwrapper()
        else:
            BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')

        if daemon:
            while state.shutdown == 0:
                sleep(1)
Exemplo n.º 12
0
 def startListening(self):
     host = self.getListeningIP()
     port = BMConfigParser().safeGetInt("bitmessagesettings", "port")
     self.listeningSockets[state.Peer(host, port)] = network.tcp.TCPServer(
         host=host, port=port)
Exemplo n.º 13
0
    def sendAddr(self):
        # We are going to share a maximum number of 1000 addrs (per overlapping
        # stream) with our peer. 500 from overlapping streams, 250 from the
        # left child stream, and 250 from the right child stream.
        maxAddrCount = BMConfigParser().safeGetInt("bitmessagesettings",
                                                   "maxaddrperstreamsend", 500)

        # init
        addressCount = 0
        payload = b''

        templist = []
        addrs = {}
        for stream in self.streams:
            with knownnodes.knownNodesLock:
                if len(knownnodes.knownNodes[stream]) > 0:
                    filtered = {
                        k: v
                        for k, v in knownnodes.knownNodes[stream].items()
                        if v["lastseen"] > (
                            int(time.time()) -
                            shared.maximumAgeOfNodesThatIAdvertiseToOthers)
                    }
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount:
                        elemCount = maxAddrCount
                    # only if more recent than 3 hours
                    addrs[stream] = random.sample(filtered.items(), elemCount)
                # sent 250 only if the remote isn't interested in it
                if len(knownnodes.knownNodes[
                        stream * 2]) > 0 and stream not in self.streams:
                    filtered = {
                        k: v
                        for k, v in knownnodes.knownNodes[stream * 2].items()
                        if v["lastseen"] > (
                            int(time.time()) -
                            shared.maximumAgeOfNodesThatIAdvertiseToOthers)
                    }
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount / 2:
                        elemCount = int(maxAddrCount / 2)
                    addrs[stream * 2] = random.sample(filtered.items(),
                                                      elemCount)
                if len(knownnodes.knownNodes[
                    (stream * 2) + 1]) > 0 and stream not in self.streams:
                    filtered = {
                        k: v
                        for k, v in knownnodes.knownNodes[stream * 2 +
                                                          1].items()
                        if v["lastseen"] > (
                            int(time.time()) -
                            shared.maximumAgeOfNodesThatIAdvertiseToOthers)
                    }
                    elemCount = len(filtered)
                    if elemCount > maxAddrCount / 2:
                        elemCount = int(maxAddrCount / 2)
                    addrs[stream * 2 + 1] = random.sample(
                        filtered.items(), elemCount)
        for substream in addrs.keys():
            for peer, params in addrs[substream]:
                templist.append((substream, peer, params["lastseen"]))
        if len(templist) > 0:
            self.append_write_buf(BMProto.assembleAddr(templist))
Exemplo n.º 14
0
    def start(self):
        _fixSocket()

        daemon = BMConfigParser().safeGetBoolean(
            'bitmessagesettings', 'daemon')

        try:
            opts, args = getopt.getopt(
                sys.argv[1:], "hcdtsa",
                ["help", "curses", "daemon", "test", "apitest"])

        except getopt.GetoptError:
            self.usage()
            sys.exit(2)

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                self.usage()
                sys.exit()
            elif opt in ("-d", "--daemon"):
                daemon = True
                state.enableGUI = False  # run without a UI
            elif opt in ("-c", "--curses"):
                state.curses = True
            elif opt in ("-t", "--test"):
                state.testmode = daemon = True
                state.enableGUI = False  # run without a UI
            elif opt in ("-a", "--apitest"):
                from bmsxmlrpc.server import TestAPIThread
                server = TestAPIThread()
                server.start()

        # is the application already running?  If yes then exit.
        if state.enableGUI and not state.curses and not depends.check_pyqt():
            sys.exit(
                'PyBitmessage requires PyQt unless you want'
                ' to run it as a daemon and interact with it'
                ' using the API. You can download PyQt from '
                'http://www.riverbankcomputing.com/software/pyqt/download'
                ' or by searching Google for \'PyQt Download\'.'
                ' If you want to run in daemon mode, see '
                'https://bitmessage.org/wiki/Daemon\n'
                'You can also run PyBitmessage with'
                ' the new curses interface by providing'
                ' \'-c\' as a commandline argument.'
            )
        shared.thisapp = singleinstance("", daemon)

        if daemon and not state.testmode:
            with shared.printLock:
                logger.warn('Running as a daemon. Send TERM signal to end.')
            self.daemonize()

        self.setSignalHandler()

        helper_threading.set_thread_name("PyBitmessage")

        state.dandelion = BMConfigParser().safeGetInt('network', 'dandelion')
        # dandelion requires outbound connections, without them,
        # stem objects will get stuck forever
        if state.dandelion and not BMConfigParser().safeGetBoolean(
                'bitmessagesettings', 'sendoutgoingconnections'):
            state.dandelion = 0

        knownnodes.readKnownNodes()

        # Not needed if objproc is disabled
        if state.enableObjProc:

            # Start the address generation thread
            addressGeneratorThread = addressGenerator()
            # close the main program even if there are threads left
            addressGeneratorThread.daemon = True
            addressGeneratorThread.start()

            # Start the thread that calculates POWs
            singleWorkerThread = singleWorker()
            # close the main program even if there are threads left
            singleWorkerThread.daemon = True
            singleWorkerThread.start()

        # Start the SQL thread
        sqlLookup = sqlThread()
        # DON'T close the main program even if there are threads left.
        # The closeEvent should command this thread to exit gracefully.
        sqlLookup.daemon = False
        sqlLookup.start()

        Inventory()  # init
        # init, needs to be early because other thread may access it early
        Dandelion()

        # Enable object processor and SMTP only if objproc enabled
        if state.enableObjProc:

            # SMTP delivery thread
            if daemon and BMConfigParser().safeGet(
                    "bitmessagesettings", "smtpdeliver", '') != '':
                from class_smtpDeliver import smtpDeliver
                smtpDeliveryThread = smtpDeliver()
                smtpDeliveryThread.start()

            # SMTP daemon thread
            if daemon and BMConfigParser().safeGetBoolean(
                    "bitmessagesettings", "smtpd"):
                from class_smtpServer import smtpServer
                smtpServerThread = smtpServer()
                smtpServerThread.start()

            # Start the thread that calculates POWs
            objectProcessorThread = objectProcessor()
            # DON'T close the main program even the thread remains.
            # This thread checks the shutdown variable after processing
            # each object.
            objectProcessorThread.daemon = False
            objectProcessorThread.start()

        # Start the cleanerThread
        singleCleanerThread = singleCleaner()
        # close the main program even if there are threads left
        singleCleanerThread.daemon = True
        singleCleanerThread.start()

        # Not needed if objproc disabled
        if state.enableObjProc:
            shared.reloadMyAddressHashes()
            shared.reloadBroadcastSendersForWhichImWatching()

            # API is also objproc dependent
            if BMConfigParser().safeGetBoolean(
                    'bitmessagesettings', 'apienabled'):
                try:
                    apiNotifyPath = BMConfigParser().get(
                        'bitmessagesettings', 'apinotifypath')
                except:
                    apiNotifyPath = ''
                if apiNotifyPath != '':
                    with shared.printLock:
                        print('Trying to call', apiNotifyPath)

                    call([apiNotifyPath, "startingUp"])
                from bmsxmlrpc.server import singleAPI
                singleAPIThread = singleAPI()
                # close the main program even if there are threads left
                singleAPIThread.daemon = True
                singleAPIThread.start()

        # start network components if networking is enabled
        if state.enableNetwork:
            BMConnectionPool()
            asyncoreThread = BMNetworkThread()
            asyncoreThread.daemon = True
            asyncoreThread.start()
            for i in range(BMConfigParser().getint("threads", "receive")):
                receiveQueueThread = ReceiveQueueThread(i)
                receiveQueueThread.daemon = True
                receiveQueueThread.start()
            announceThread = AnnounceThread()
            announceThread.daemon = True
            announceThread.start()
            state.invThread = InvThread()
            state.invThread.daemon = True
            state.invThread.start()
            state.addrThread = AddrThread()
            state.addrThread.daemon = True
            state.addrThread.start()
            state.downloadThread = DownloadThread()
            state.downloadThread.daemon = True
            state.downloadThread.start()

            connectToStream(1)

            if BMConfigParser().safeGetBoolean(
                    'bitmessagesettings', 'upnp'):
                import upnp
                upnpThread = upnp.uPnPThread()
                upnpThread.start()
        else:
            # Populate with hardcoded value (same as connectToStream above)
            state.streamsInWhichIAmParticipating.append(1)

        if not daemon and state.enableGUI:
            if state.curses:
                if not depends.check_curses():
                    sys.exit()
                logger.info('Running with curses')
                import bitmessagecurses
                bitmessagecurses.runwrapper()
            elif state.kivy:
                BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')
                from bitmessagekivy.mpybit import NavigateApp
                NavigateApp().run()
            else:
                import bitmessageqt
                bitmessageqt.run()
        else:
            BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')

        if daemon:
            if state.testmode:
                sleep(30)
                # make testing
                self.stop()
            while state.shutdown == 0:
                sleep(1)
Exemplo n.º 15
0
    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:
            self.cur.execute(
                '''CREATE TABLE inbox (msgid blob, toaddress text, fromaddress text, subject text, received text, message text, folder text, encodingtype int, read bool, sighash blob, UNIQUE(msgid) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill integer, status text, retrynumber integer, folder text, encodingtype int, ttl int)'''
            )
            self.cur.execute(
                '''CREATE TABLE subscriptions (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE addressbook (label text, address text)''')
            self.cur.execute(
                '''CREATE TABLE blacklist (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE whitelist (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            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(
                '''INSERT INTO subscriptions VALUES('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('lastvacuumtime',?)''',
                (int(time.time()), ))
            self.cur.execute(
                '''CREATE TABLE objectprocessorqueue (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)'''
            )
            self.conn.commit()
            logger.info('Created messages database file')
        except Exception as err:
            if str(err) == 'table inbox already exists':
                logger.debug('Database file already exists.')

            else:
                sys.stderr.write(
                    'ERROR trying to create database file (message.dat). Error message: %s\n'
                    % str(err))
                os._exit(0)

        # 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().safeGetInt('bitmessagesettings',
                                                      'settingsversion')

        # People running earlier versions of PyBitmessage do not have the
        # usedpersonally field in their pubkeys table. Let's add it.
        if settingsversion == 2:
            item = '''ALTER TABLE pubkeys ADD usedpersonally text DEFAULT 'no' '''
            parameters = ''
            self.cur.execute(item, parameters)
            self.conn.commit()

            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 settingsversion == 3:
            item = '''ALTER TABLE inbox ADD encodingtype int DEFAULT '2' '''
            parameters = ''
            self.cur.execute(item, parameters)

            item = '''ALTER TABLE inbox ADD read bool DEFAULT '1' '''
            parameters = ''
            self.cur.execute(item, parameters)

            item = '''ALTER TABLE sent ADD encodingtype int DEFAULT '2' '''
            parameters = ''
            self.cur.execute(item, parameters)
            self.conn.commit()

            settingsversion = 4

        BMConfigParser().set('bitmessagesettings', 'settingsversion',
                             str(settingsversion))
        BMConfigParser().save()

        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
        # version we are on can stay embedded in the messages.dat file. Let us
        # check to see if the settings table exists yet.
        item = '''SELECT name FROM sqlite_master WHERE type='table' AND name='settings';'''
        parameters = ''
        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.")
            self.cur.execute(
                '''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)'''
            )
            self.cur.execute('''INSERT INTO settings VALUES('version','1')''')
            self.cur.execute(
                '''INSERT INTO settings VALUES('lastvacuumtime',?)''',
                (int(time.time()), ))
            logger.debug(
                'In messages.dat database, removing an obsolete field from the pubkeys table.'
            )
            self.cur.execute(
                '''CREATE TEMPORARY TABLE pubkeys_backup(hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE);'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys_backup SELECT hash, transmitdata, time, usedpersonally FROM pubkeys;'''
            )
            self.cur.execute('''DROP TABLE pubkeys''')
            self.cur.execute(
                '''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys SELECT hash, transmitdata, time, usedpersonally FROM pubkeys_backup;'''
            )
            self.cur.execute('''DROP TABLE pubkeys_backup;''')
            logger.debug(
                'Deleting all pubkeys from inventory. They will be redownloaded and then saved with the correct times.'
            )
            self.cur.execute(
                '''delete from inventory where objecttype = 'pubkey';''')
            logger.debug(
                'replacing Bitmessage announcements mailing list with a new one.'
            )
            self.cur.execute(
                '''delete from subscriptions where address='BM-BbkPSZbzPwpVcYZpU4yHwf9ZPEapN5Zx' '''
            )
            self.cur.execute(
                '''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)'''
            )
            logger.debug('Commiting.')
            self.conn.commit()
            logger.debug(
                'Vacuuming message.dat. You might notice that the file size gets much smaller.'
            )
            self.cur.execute(''' VACUUM ''')

        # After code refactoring, the possible status values for sent messages
        # have changed.
        self.cur.execute(
            '''update sent set status='doingmsgpow' where status='doingpow'  '''
        )
        self.cur.execute(
            '''update sent set status='msgsent' where status='sentmessage'  '''
        )
        self.cur.execute(
            '''update sent set status='doingpubkeypow' where status='findingpubkey'  '''
        )
        self.cur.execute(
            '''update sent set status='broadcastqueued' where status='broadcastpending'  '''
        )
        self.conn.commit()

        # 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.')
            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(
                '''INSERT INTO inventory_backup SELECT hash, objecttype, streamnumber, payload, receivedtime FROM inventory;'''
            )
            self.cur.execute('''DROP TABLE inventory''')
            self.cur.execute(
                '''CREATE TABLE inventory (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO inventory SELECT hash, objecttype, streamnumber, payload, receivedtime FROM inventory_backup;'''
            )
            self.cur.execute('''DROP TABLE inventory_backup;''')
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (3, )
            self.cur.execute(item, parameters)

        # Add a new column to the inventory table to store tags.
        item = '''SELECT value FROM settings WHERE key='version';'''
        parameters = ''
        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.')
            item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' '''
            parameters = ''
            self.cur.execute(item, parameters)
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (4, )
            self.cur.execute(item, parameters)

        # 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';'''
        parameters = ''
        self.cur.execute(item, parameters)
        currentVersion = int(self.cur.fetchall()[0][0])
        if currentVersion == 4:
            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)'''
            )
            self.cur.execute(
                '''delete from inventory where objecttype = 'pubkey';''')
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (5, )
            self.cur.execute(item, parameters)

        # Add a new table: objectprocessorqueue with which to hold objects
        # that have yet to be processed if the user shuts down Bitmessage.
        item = '''SELECT value FROM settings WHERE key='version';'''
        parameters = ''
        self.cur.execute(item, parameters)
        currentVersion = int(self.cur.fetchall()[0][0])
        if currentVersion == 5:
            self.cur.execute('''DROP TABLE knownnodes''')
            self.cur.execute(
                '''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)
        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.')
            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''')
            self.cur.execute(
                '''CREATE TABLE objectprocessorqueue (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)'''
            )
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (7, )
            self.cur.execute(item, parameters)
            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.
        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.')
            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.
            self.cur.execute(
                '''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';'''
            )
            query = '''update settings set value=? WHERE key='version';'''
            parameters = (8, )
            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.
        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.')
            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)

        # 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...')
            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(
                '''INSERT INTO sent_backup SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, 0, folder, encodingtype FROM sent;'''
            )
            self.cur.execute('''DROP TABLE sent''')
            self.cur.execute(
                '''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill int, status text, retrynumber integer, folder text, encodingtype int, ttl int)'''
            )
            self.cur.execute(
                '''INSERT INTO sent SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, lastactiontime, 0, status, 0, folder, encodingtype, 216000 FROM sent_backup;'''
            )
            self.cur.execute('''DROP TABLE sent_backup''')
            logger.info(
                'In messages.dat database, finished making TTL-related changes.'
            )
            logger.debug(
                'In messages.dat database, adding address field to the pubkeys table.'
            )
            # We're going to have to calculate the address for each row in the pubkeys
            # table. Then we can take out the hash field.
            self.cur.execute(
                '''ALTER TABLE pubkeys ADD address text DEFAULT '' ''')
            self.cur.execute('''SELECT hash, addressversion FROM pubkeys''')
            queryResult = self.cur.fetchall()
            from addresses import encodeAddress
            for row in queryResult:
                addressHash, addressVersion = row
                address = encodeAddress(addressVersion, 1, hash)
                item = '''UPDATE pubkeys SET address=? WHERE hash=?;'''
                parameters = (address, addressHash)
                self.cur.execute(item, parameters)
            # Now we can remove the hash field from the pubkeys table.
            self.cur.execute(
                '''CREATE TEMPORARY TABLE pubkeys_backup (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys_backup SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys;'''
            )
            self.cur.execute('''DROP TABLE pubkeys''')
            self.cur.execute(
                '''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys_backup;'''
            )
            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';''')

        # 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!

        try:
            testpayload = '\x00\x00'
            t = ('1234', 1, testpayload, '12345678', 'no')
            self.cur.execute('''INSERT INTO pubkeys VALUES(?,?,?,?,?)''', t)
            self.conn.commit()
            self.cur.execute(
                '''SELECT transmitdata FROM pubkeys WHERE address='1234' ''')
            queryreturn = self.cur.fetchall()
            for row in queryreturn:
                transmitdata, = row
            self.cur.execute('''DELETE FROM pubkeys WHERE address='1234' ''')
            self.conn.commit()
            if transmitdata == '':
                logger.fatal(
                    'Problem: The version of SQLite you have cannot store Null values. Please download and install the latest revision of your version of Python (for example, the latest Python 2.7 revision) and try again.\n'
                )
                logger.fatal(
                    'PyBitmessage will now exit very abruptly. You may now see threading errors related to this abrupt exit but the problem you need to solve is related to SQLite.\n\n'
                )
                os._exit(0)
        except Exception as err:
            if str(err) == 'database or disk is full':
                logger.fatal(
                    '(While null value test) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                )
                queues.UISignalQueue.put(('alert', (
                    tr._translate("MainWindow", "Disk full"),
                    tr._translate(
                        "MainWindow",
                        'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                    ), True)))
                os._exit(0)
            else:
                logger.error(err)

        # Let us check to see the last time we vaccumed the messages.dat file.
        # If it has been more than a month let's do it now.
        item = '''SELECT value FROM settings WHERE key='lastvacuumtime';'''
        parameters = ''
        self.cur.execute(item, parameters)
        queryreturn = self.cur.fetchall()
        for row in queryreturn:
            value, = row
            if int(value) < int(time.time()) - 86400:
                logger.info(
                    'It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...'
                )
                try:
                    self.cur.execute(''' VACUUM ''')
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(While VACUUM) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                item = '''update settings set value=? WHERE key='lastvacuumtime';'''
                parameters = (int(time.time()), )
                self.cur.execute(item, parameters)

        state.sqlReady = True

        while True:
            item = helper_sql.sqlSubmitQueue.get()
            if item == 'commit':
                try:
                    self.conn.commit()
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(While committing) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
            elif item == 'exit':
                self.conn.close()
                logger.info('sqlThread exiting gracefully.')

                return
            elif item == 'movemessagstoprog':
                logger.debug(
                    'the sqlThread is moving the messages.dat file to the local program directory.'
                )

                try:
                    self.conn.commit()
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while movemessagstoprog) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                self.conn.close()
                shutil.move(paths.lookupAppdataFolder() + 'messages.dat',
                            paths.lookupExeFolder() + 'messages.dat')
                self.conn = sqlite3.connect(paths.lookupExeFolder() +
                                            'messages.dat')
                self.conn.text_factory = str
                self.cur = self.conn.cursor()
            elif item == 'movemessagstoappdata':
                logger.debug(
                    'the sqlThread is moving the messages.dat file to the Appdata folder.'
                )

                try:
                    self.conn.commit()
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while movemessagstoappdata) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                self.conn.close()
                shutil.move(paths.lookupExeFolder() + 'messages.dat',
                            paths.lookupAppdataFolder() + 'messages.dat')
                self.conn = sqlite3.connect(paths.lookupAppdataFolder() +
                                            'messages.dat')
                self.conn.text_factory = str
                self.cur = self.conn.cursor()
            elif item == 'deleteandvacuume':
                self.cur.execute('''delete from inbox where folder='trash' ''')
                self.cur.execute('''delete from sent where folder='trash' ''')
                self.conn.commit()
                try:
                    self.cur.execute(''' VACUUM ''')
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while deleteandvacuume) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
            else:
                parameters = helper_sql.sqlSubmitQueue.get()
                rowcount = 0
                # print 'item', item
                # print 'parameters', parameters
                try:
                    self.cur.execute(item, parameters)
                    rowcount = self.cur.rowcount
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while cur.execute) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                    else:
                        logger.fatal(
                            'Major error occurred when trying to execute a SQL statement within the sqlThread. Please tell Atheros about this error message or post it in the forum! Error occurred while trying to execute statement: "%s"  Here are the parameters; you might want to censor this data with asterisks (***) as it can contain private information: %s. Here is the actual error message thrown by the sqlThread: %s',
                            str(item), str(repr(parameters)), str(err))
                        logger.fatal('This program shall now abruptly exit!')

                    os._exit(0)

                helper_sql.sqlReturnQueue.put((self.cur.fetchall(), rowcount))
Exemplo n.º 16
0
 def retranslateUi(self, MainWindow):
     MainWindow.setWindowTitle(_translate("MainWindow", "Bitmessage", None))
     self.treeWidgetYourIdentities.headerItem().setText(0, _translate("MainWindow", "Identities", None))
     self.pushButtonNewAddress.setText(_translate("MainWindow", "New Identity", None))
     self.inboxSearchLineEdit.setPlaceholderText(_translate("MainWindow", "Search", None))
     self.inboxSearchOption.setItemText(0, _translate("MainWindow", "All", None))
     self.inboxSearchOption.setItemText(1, _translate("MainWindow", "To", None))
     self.inboxSearchOption.setItemText(2, _translate("MainWindow", "From", None))
     self.inboxSearchOption.setItemText(3, _translate("MainWindow", "Subject", None))
     self.inboxSearchOption.setItemText(4, _translate("MainWindow", "Message", None))
     self.tableWidgetInbox.setSortingEnabled(True)
     item = self.tableWidgetInbox.horizontalHeaderItem(0)
     item.setText(_translate("MainWindow", "To", None))
     item = self.tableWidgetInbox.horizontalHeaderItem(1)
     item.setText(_translate("MainWindow", "From", None))
     item = self.tableWidgetInbox.horizontalHeaderItem(2)
     item.setText(_translate("MainWindow", "Subject", None))
     item = self.tableWidgetInbox.horizontalHeaderItem(3)
     item.setText(_translate("MainWindow", "Received", None))
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.inbox), _translate("MainWindow", "Messages", None))
     self.tableWidgetAddressBook.setSortingEnabled(True)
     item = self.tableWidgetAddressBook.horizontalHeaderItem(0)
     item.setText(_translate("MainWindow", "Address book", None))
     item = self.tableWidgetAddressBook.horizontalHeaderItem(1)
     item.setText(_translate("MainWindow", "Address", None))
     self.pushButtonAddAddressBook.setText(_translate("MainWindow", "Add Contact", None))
     self.label_3.setText(_translate("MainWindow", "Subject:", None))
     self.label_2.setText(_translate("MainWindow", "From:", None))
     self.label.setText(_translate("MainWindow", "To:", None))
     #self.textEditMessage.setHtml("")
     self.tabWidgetSend.setTabText(self.tabWidgetSend.indexOf(self.sendDirect), _translate("MainWindow", "Send ordinary Message", None))
     self.label_8.setText(_translate("MainWindow", "From:", None))
     self.label_7.setText(_translate("MainWindow", "Subject:", None))
     #self.textEditMessageBroadcast.setHtml("")
     self.tabWidgetSend.setTabText(self.tabWidgetSend.indexOf(self.sendBroadcast), _translate("MainWindow", "Send Message to your Subscribers", None))
     self.pushButtonTTL.setText(_translate("MainWindow", "TTL:", None))
     hours = 48
     try:
         hours = int(BMConfigParser().getint('bitmessagesettings', 'ttl')/60/60)
     except:
         pass
     self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, hours))
     self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
     self.treeWidgetSubscriptions.headerItem().setText(0, _translate("MainWindow", "Subscriptions", None))
     self.pushButtonAddSubscription.setText(_translate("MainWindow", "Add new Subscription", None))
     self.inboxSearchLineEditSubscriptions.setPlaceholderText(_translate("MainWindow", "Search", None))
     self.inboxSearchOptionSubscriptions.setItemText(0, _translate("MainWindow", "All", None))
     self.inboxSearchOptionSubscriptions.setItemText(1, _translate("MainWindow", "To", None))
     self.inboxSearchOptionSubscriptions.setItemText(2, _translate("MainWindow", "From", None))
     self.inboxSearchOptionSubscriptions.setItemText(3, _translate("MainWindow", "Subject", None))
     self.inboxSearchOptionSubscriptions.setItemText(4, _translate("MainWindow", "Message", None))
     self.tableWidgetInboxSubscriptions.setSortingEnabled(True)
     item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(0)
     item.setText(_translate("MainWindow", "To", None))
     item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(1)
     item.setText(_translate("MainWindow", "From", None))
     item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(2)
     item.setText(_translate("MainWindow", "Subject", None))
     item = self.tableWidgetInboxSubscriptions.horizontalHeaderItem(3)
     item.setText(_translate("MainWindow", "Received", None))
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.subscriptions), _translate("MainWindow", "Subscriptions", None))
     self.treeWidgetChans.headerItem().setText(0, _translate("MainWindow", "Chans", None))
     self.pushButtonAddChan.setText(_translate("MainWindow", "Add Chan", None))
     self.inboxSearchLineEditChans.setPlaceholderText(_translate("MainWindow", "Search", None))
     self.inboxSearchOptionChans.setItemText(0, _translate("MainWindow", "All", None))
     self.inboxSearchOptionChans.setItemText(1, _translate("MainWindow", "To", None))
     self.inboxSearchOptionChans.setItemText(2, _translate("MainWindow", "From", None))
     self.inboxSearchOptionChans.setItemText(3, _translate("MainWindow", "Subject", None))
     self.inboxSearchOptionChans.setItemText(4, _translate("MainWindow", "Message", None))
     self.tableWidgetInboxChans.setSortingEnabled(True)
     item = self.tableWidgetInboxChans.horizontalHeaderItem(0)
     item.setText(_translate("MainWindow", "To", None))
     item = self.tableWidgetInboxChans.horizontalHeaderItem(1)
     item.setText(_translate("MainWindow", "From", None))
     item = self.tableWidgetInboxChans.horizontalHeaderItem(2)
     item.setText(_translate("MainWindow", "Subject", None))
     item = self.tableWidgetInboxChans.horizontalHeaderItem(3)
     item.setText(_translate("MainWindow", "Received", None))
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.chans), _translate("MainWindow", "Chans", None))
     self.blackwhitelist.retranslateUi()
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.blackwhitelist), _translate("blacklist", "Blacklist", None))
     self.networkstatus.retranslateUi()
     self.tabWidget.setTabText(self.tabWidget.indexOf(self.networkstatus), _translate("networkstatus", "Network Status", None))
     self.menuFile.setTitle(_translate("MainWindow", "File", None))
     self.menuSettings.setTitle(_translate("MainWindow", "Settings", None))
     self.menuHelp.setTitle(_translate("MainWindow", "Help", None))
     self.actionImport_keys.setText(_translate("MainWindow", "Import keys", None))
     self.actionManageKeys.setText(_translate("MainWindow", "Manage keys", None))
     self.actionExit.setText(_translate("MainWindow", "Quit", None))
     self.actionExit.setShortcut(_translate("MainWindow", "Ctrl+Q", None))
     self.actionHelp.setText(_translate("MainWindow", "Help", None))
     self.actionHelp.setShortcut(_translate("MainWindow", "F1", None))
     self.actionAbout.setText(_translate("MainWindow", "About", None))
     self.actionSettings.setText(_translate("MainWindow", "Settings", None))
     self.actionRegenerateDeterministicAddresses.setText(_translate("MainWindow", "Regenerate deterministic addresses", None))
     self.actionDeleteAllTrashedMessages.setText(_translate("MainWindow", "Delete all trashed messages", None))
     self.actionJoinChan.setText(_translate("MainWindow", "Join / Create chan", None))
Exemplo n.º 17
0
    def peerValidityChecks(self):
        if self.remoteProtocolVersion < 3:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    fatal=2,
                    errorText=
                    "Your is using an old protocol. Closing connection."))
            logger.debug(
                'Closing connection to old protocol version %s, node: %s',
                str(self.remoteProtocolVersion), str(self.destination))
            return False
        if self.timeOffset > BMProto.maxTimeOffset:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    fatal=2,
                    errorText=
                    "Your time is too far in the future compared to mine. Closing connection."
                ))
            logger.info(
                "%s's time is too far in the future (%s seconds). Closing connection to it.",
                self.destination, self.timeOffset)
            shared.timeOffsetWrongCount += 1
            return False
        elif self.timeOffset < -BMProto.maxTimeOffset:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    fatal=2,
                    errorText=
                    "Your time is too far in the past compared to mine. Closing connection."
                ))
            logger.info(
                "%s's time is too far in the past (timeOffset %s seconds). Closing connection to it.",
                self.destination, self.timeOffset)
            shared.timeOffsetWrongCount += 1
            return False
        else:
            shared.timeOffsetWrongCount = 0
        if not self.streams:
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    fatal=2,
                    errorText=
                    "We don't have shared stream interests. Closing connection."
                ))
            logger.debug(
                'Closed connection to %s because there is no overlapping interest in streams.',
                str(self.destination))
            return False
        if self.destination in network.connectionpool.BMConnectionPool(
        ).inboundConnections:
            try:
                if not protocol.checkSocksIP(self.destination.host):
                    self.append_write_buf(
                        protocol.assembleErrorMessage(
                            fatal=2,
                            errorText=
                            "Too many connections from your IP. Closing connection."
                        ))
                    logger.debug(
                        'Closed connection to %s because we are already connected to that IP.',
                        str(self.destination))
                    return False
            except:
                pass
        if not self.isOutbound:
            # incoming from a peer we're connected to as outbound, or server full
            # report the same error to counter deanonymisation
            if state.Peer(self.destination.host, self.peerNode.port) in \
                network.connectionpool.BMConnectionPool().inboundConnections or \
                len(network.connectionpool.BMConnectionPool().inboundConnections) + \
                len(network.connectionpool.BMConnectionPool().outboundConnections) > \
                BMConfigParser().safeGetInt("lmessagesettings", "maxtotalconnections") + \
                BMConfigParser().safeGetInt("lmessagesettings", "maxbootstrapconnections"):
                self.append_write_buf(
                    protocol.assembleErrorMessage(
                        fatal=2,
                        errorText="Server full, please try again later."))
                logger.debug(
                    "Closed connection to %s due to server full or duplicate inbound/outbound.",
                    str(self.destination))
                return False
        if network.connectionpool.BMConnectionPool().isAlreadyConnected(
                self.nonce):
            self.append_write_buf(
                protocol.assembleErrorMessage(
                    fatal=2,
                    errorText="I'm connected to myself. Closing connection."))
            logger.debug(
                "Closed connection to %s because I'm connected to myself.",
                str(self.destination))
            return False

        return True
Exemplo n.º 18
0
def checkHasNormalAddress():
    for address in account.getSortedAccounts():
        acct = account.accountClass(address)
        if acct.type == AccountMixin.NORMAL and BMConfigParser().safeGetBoolean(address, 'enabled'):
            return address
    return False
Exemplo n.º 19
0
def updateConfig():
    """Save the config"""
    config = BMConfigParser()
    settingsversion = config.getint('bitmessagesettings', 'settingsversion')
    if settingsversion == 1:
        config.set('bitmessagesettings', 'socksproxytype', 'none')
        config.set('bitmessagesettings', 'sockshostname', 'localhost')
        config.set('bitmessagesettings', 'socksport', '9050')
        config.set('bitmessagesettings', 'socksauthentication', 'false')
        config.set('bitmessagesettings', 'socksusername', '')
        config.set('bitmessagesettings', 'sockspassword', '')
        config.set('bitmessagesettings', 'sockslisten', 'false')
        config.set('bitmessagesettings', 'keysencrypted', 'false')
        config.set('bitmessagesettings', 'messagesencrypted', 'false')
        settingsversion = 2
    # let class_sqlThread update SQL and continue
    elif settingsversion == 4:
        config.set('bitmessagesettings', 'defaultnoncetrialsperbyte',
                   str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
        config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes',
                   str(defaults.networkDefaultPayloadLengthExtraBytes))
        settingsversion = 5

    if settingsversion == 5:
        config.set('bitmessagesettings', 'maxacceptablenoncetrialsperbyte',
                   '0')
        config.set('bitmessagesettings',
                   'maxacceptablepayloadlengthextrabytes', '0')
        settingsversion = 7

    if not config.has_option('bitmessagesettings', 'sockslisten'):
        config.set('bitmessagesettings', 'sockslisten', 'false')

    if not config.has_option('bitmessagesettings', 'userlocale'):
        config.set('bitmessagesettings', 'userlocale', 'system')

    if not config.has_option('bitmessagesettings', 'sendoutgoingconnections'):
        config.set('bitmessagesettings', 'sendoutgoingconnections', 'True')

    if not config.has_option('bitmessagesettings', 'useidenticons'):
        config.set('bitmessagesettings', 'useidenticons', 'True')
    if not config.has_option('bitmessagesettings', 'identiconsuffix'):
        # acts as a salt
        config.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:
        config.set('bitmessagesettings', 'stopresendingafterxdays', '')
        config.set('bitmessagesettings', 'stopresendingafterxmonths', '')
        settingsversion = 8

    # With the change to protocol version 3, reset the user-settable
    # difficulties to 1
    if settingsversion == 8:
        config.set('bitmessagesettings', 'defaultnoncetrialsperbyte',
                   str(defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
        config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes',
                   str(defaults.networkDefaultPayloadLengthExtraBytes))
        previousTotalDifficulty = int(
            config.getint('bitmessagesettings',
                          'maxacceptablenoncetrialsperbyte')) / 320
        previousSmallMessageDifficulty = int(
            config.getint('bitmessagesettings',
                          'maxacceptablepayloadlengthextrabytes')) / 14000
        config.set('bitmessagesettings', 'maxacceptablenoncetrialsperbyte',
                   str(previousTotalDifficulty * 1000))
        config.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 config.addresses():
            try:
                previousTotalDifficulty = float(
                    config.getint(addressInKeysFile,
                                  'noncetrialsperbyte')) / 320
                previousSmallMessageDifficulty = float(
                    config.getint(addressInKeysFile,
                                  'payloadlengthextrabytes')) / 14000
                if previousTotalDifficulty <= 2:
                    previousTotalDifficulty = 1
                if previousSmallMessageDifficulty < 1:
                    previousSmallMessageDifficulty = 1
                config.set(addressInKeysFile, 'noncetrialsperbyte',
                           str(int(previousTotalDifficulty * 1000)))
                config.set(addressInKeysFile, 'payloadlengthextrabytes',
                           str(int(previousSmallMessageDifficulty * 1000)))
            except Exception:
                continue
        config.set('bitmessagesettings', 'maxdownloadrate', '0')
        config.set('bitmessagesettings', 'maxuploadrate', '0')
        settingsversion = 10

    # sanity check
    if config.safeGetInt('bitmessagesettings',
                         'maxacceptablenoncetrialsperbyte') == 0:
        config.set(
            'bitmessagesettings', 'maxacceptablenoncetrialsperbyte',
            str(defaults.ridiculousDifficulty *
                defaults.networkDefaultProofOfWorkNonceTrialsPerByte))
    if config.safeGetInt('bitmessagesettings',
                         'maxacceptablepayloadlengthextrabytes') == 0:
        config.set(
            'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes',
            str(defaults.ridiculousDifficulty *
                defaults.networkDefaultPayloadLengthExtraBytes))

    if not config.has_option('bitmessagesettings', 'onionhostname'):
        config.set('bitmessagesettings', 'onionhostname', '')
    if not config.has_option('bitmessagesettings', 'onionport'):
        config.set('bitmessagesettings', 'onionport', '8444')
    if not config.has_option('bitmessagesettings', 'onionbindip'):
        config.set('bitmessagesettings', 'onionbindip', '127.0.0.1')
    if not config.has_option('bitmessagesettings', 'smtpdeliver'):
        config.set('bitmessagesettings', 'smtpdeliver', '')
    if not config.has_option('bitmessagesettings',
                             'hidetrayconnectionnotifications'):
        config.set('bitmessagesettings', 'hidetrayconnectionnotifications',
                   'false')
    if config.safeGetInt('bitmessagesettings', 'maxoutboundconnections') < 1:
        config.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 config.has_option('bitmessagesettings', 'ttl'):
        config.set('bitmessagesettings', 'ttl', '367200')

    config.set('bitmessagesettings', 'settingsversion', str(settingsversion))
    config.save()
Exemplo n.º 20
0
 def getApiAddress(self):
     if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'):
         return None
     address = BMConfigParser().get('bitmessagesettings', 'apiinterface')
     port = BMConfigParser().getint('bitmessagesettings', 'apiport')
     return {'address':address,'port':port}
Exemplo n.º 21
0
    def start(self, daemon=False):
        _fixWinsock()

        shared.daemon = daemon

        # get curses flag
        if '-c' in sys.argv:
            state.curses = True

        # is the application already running?  If yes then exit.
        shared.thisapp = singleinstance("", daemon)

        if daemon:
            with shared.printLock:
                print('Running as a daemon. Send TERM signal to end.')
            self.daemonize()

        self.setSignalHandler()

        helper_bootstrap.knownNodes()
        # Start the address generation thread
        addressGeneratorThread = addressGenerator()
        addressGeneratorThread.daemon = True  # close the main program even if there are threads left
        addressGeneratorThread.start()

        # Start the thread that calculates POWs
        singleWorkerThread = singleWorker()
        singleWorkerThread.daemon = True  # close the main program even if there are threads left
        singleWorkerThread.start()

        # Start the SQL thread
        sqlLookup = sqlThread()
        sqlLookup.daemon = False  # DON'T close the main program even if there are threads left. The closeEvent should command this thread to exit gracefully.
        sqlLookup.start()

        # SMTP delivery thread
        if daemon and BMConfigParser().safeGet("bitmessagesettings",
                                               "smtpdeliver", '') != '':
            smtpDeliveryThread = smtpDeliver()
            smtpDeliveryThread.start()

        # SMTP daemon thread
        if daemon and BMConfigParser().safeGetBoolean("bitmessagesettings",
                                                      "smtpd"):
            smtpServerThread = smtpServer()
            smtpServerThread.start()

        # Start the thread that calculates POWs
        objectProcessorThread = objectProcessor()
        objectProcessorThread.daemon = False  # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object.
        objectProcessorThread.start()

        # Start the cleanerThread
        singleCleanerThread = singleCleaner()
        singleCleanerThread.daemon = True  # close the main program even if there are threads left
        singleCleanerThread.start()

        shared.reloadMyAddressHashes()
        shared.reloadBroadcastSendersForWhichImWatching()

        if BMConfigParser().safeGetBoolean('bitmessagesettings', 'apienabled'):
            try:
                apiNotifyPath = BMConfigParser().get('bitmessagesettings',
                                                     'apinotifypath')
            except:
                apiNotifyPath = ''
            if apiNotifyPath != '':
                with shared.printLock:
                    print('Trying to call', apiNotifyPath)

                call([apiNotifyPath, "startingUp"])
            singleAPIThread = singleAPI()
            singleAPIThread.daemon = True  # close the main program even if there are threads left
            singleAPIThread.start()

        connectToStream(1)

        singleListenerThread = singleListener()
        singleListenerThread.setup(selfInitiatedConnections)
        singleListenerThread.daemon = True  # close the main program even if there are threads left
        singleListenerThread.start()

        if BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'):
            import upnp
            upnpThread = upnp.uPnPThread()
            upnpThread.start()

        if daemon == False and BMConfigParser().safeGetBoolean(
                'bitmessagesettings', 'daemon') == False:
            if state.curses == False:
                if not depends.check_pyqt():
                    print(
                        'PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API. You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download   or by searching Google for \'PyQt Download\'. If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
                    )
                    print(
                        'You can also run PyBitmessage with the new curses interface by providing \'-c\' as a commandline argument.'
                    )
                    sys.exit()

                import bitmessageqt
                bitmessageqt.run()
            else:
                if True:
                    #                if depends.check_curses():
                    print('Running with curses')
                    import bitmessagecurses
                    bitmessagecurses.runwrapper()
        else:
            BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')

            while True:
                time.sleep(20)
Exemplo n.º 22
0
def dns():
    # DNS bootstrap. This could be programmed to use the SOCKS proxy to do the
    # DNS lookup some day but for now we will just rely on the entries in
    # defaultKnownNodes.py. Hopefully either they are up to date or the user
    # has run Bitmessage recently without SOCKS turned on and received good
    # bootstrap nodes using that method.
    def try_add_known_node(stream, addr, port, method=''):
        try:
            socket.inet_aton(addr)
        except (TypeError, socket.error):
            return
        logger.info('Adding %s to knownNodes based on %s DNS bootstrap method',
                    addr, method)
        addKnownNode(stream, state.Peer(addr, port))

    proxy_type = BMConfigParser().get('bitmessagesettings', 'socksproxytype')

    if proxy_type == 'none':
        for port in [8080, 8444]:
            try:
                for item in socket.getaddrinfo(
                        'bootstrap%s.bitmessage.org' % port, 80):
                    try_add_known_node(1, item[4][0], port)
            except:
                logger.error(
                    'bootstrap%s.bitmessage.org DNS bootstrapping failed.',
                    port,
                    exc_info=True)
    elif proxy_type == 'SOCKS5':
        addKnownNode(1, state.Peer('quzwelsuziwqgpt2.onion', 8444))
        logger.debug("Adding quzwelsuziwqgpt2.onion:8444 to knownNodes.")
        for port in [8080, 8444]:
            logger.debug("Resolving %i through SOCKS...", port)
            address_family = socket.AF_INET
            sock = socks.socksocket(address_family, socket.SOCK_STREAM)
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            sock.settimeout(20)
            proxytype = socks.PROXY_TYPE_SOCKS5
            sockshostname = BMConfigParser().get('bitmessagesettings',
                                                 'sockshostname')
            socksport = BMConfigParser().getint('bitmessagesettings',
                                                'socksport')
            rdns = True  # Do domain name lookups through the proxy; though this setting doesn't really matter since we won't be doing any domain name lookups anyway.
            if BMConfigParser().getboolean('bitmessagesettings',
                                           'socksauthentication'):
                socksusername = BMConfigParser().get('bitmessagesettings',
                                                     'socksusername')
                sockspassword = BMConfigParser().get('bitmessagesettings',
                                                     'sockspassword')
                sock.setproxy(proxytype, sockshostname, socksport, rdns,
                              socksusername, sockspassword)
            else:
                sock.setproxy(proxytype, sockshostname, socksport, rdns)
            try:
                ip = sock.resolve("bootstrap" + str(port) + ".bitmessage.org")
                sock.shutdown(socket.SHUT_RDWR)
                sock.close()
            except:
                logger.error("SOCKS DNS resolving failed", exc_info=True)
            else:
                try_add_known_node(1, ip, port, 'SOCKS')
    else:
        logger.info(
            'DNS bootstrap skipped because the proxy type does not support'
            ' DNS resolution.')
Exemplo n.º 23
0
    def start(self):
        _fixSocket()

        daemon = BMConfigParser().safeGetBoolean('bitmessagesettings',
                                                 'daemon')

        try:
            opts, args = getopt.getopt(sys.argv[1:], "hcdt",
                                       ["help", "curses", "daemon", "test"])

        except getopt.GetoptError:
            self.usage()
            sys.exit(2)

        for opt, arg in opts:
            if opt in ("-h", "--help"):
                self.usage()
                sys.exit()
            elif opt in ("-d", "--daemon"):
                daemon = True
                state.enableGUI = False  # run without a UI
            elif opt in ("-c", "--curses"):
                state.curses = True
            elif opt in ("-t", "--test"):
                state.testmode = True
                if os.path.isfile(os.path.join(state.appdata,
                                               'unittest.lock')):
                    daemon = True
                state.enableGUI = False  # run without a UI
                # Fallback: in case when no api command was issued
                state.last_api_response = datetime.now()
                # Apply special settings
                config = BMConfigParser()
                config.set('bitmessagesettings', 'apienabled', 'true')
                config.set('bitmessagesettings', 'apiusername', 'username')
                config.set('bitmessagesettings', 'apipassword', 'password')
                config.set(
                    'bitmessagesettings', 'apinotifypath',
                    os.path.join(app_dir, 'tests', 'apinotify_handler.py'))

        # is the application already running?  If yes then exit.
        shared.thisapp = singleinstance("", daemon)

        if daemon:
            with shared.printLock:
                print('Running as a daemon. Send TERM signal to end.')
            self.daemonize()

        self.setSignalHandler()

        helper_threading.set_thread_name("PyBitmessage")

        state.dandelion = BMConfigParser().safeGetInt('network', 'dandelion')
        # dandelion requires outbound connections, without them, stem objects will get stuck forever
        if state.dandelion and not BMConfigParser().safeGetBoolean(
                'bitmessagesettings', 'sendoutgoingconnections'):
            state.dandelion = 0

        helper_bootstrap.knownNodes()

        # Not needed if objproc is disabled
        if state.enableObjProc:

            # Start the address generation thread
            addressGeneratorThread = addressGenerator()
            addressGeneratorThread.daemon = True  # close the main program even if there are threads left
            addressGeneratorThread.start()

            # Start the thread that calculates POWs
            singleWorkerThread = singleWorker()
            singleWorkerThread.daemon = True  # close the main program even if there are threads left
            singleWorkerThread.start()

        # Start the SQL thread
        sqlLookup = sqlThread()
        sqlLookup.daemon = False  # DON'T close the main program even if there are threads left. The closeEvent should command this thread to exit gracefully.
        sqlLookup.start()

        Inventory()  # init
        Dandelion(
        )  # init, needs to be early because other thread may access it early

        # Enable object processor and SMTP only if objproc enabled
        if state.enableObjProc:

            # SMTP delivery thread
            if daemon and BMConfigParser().safeGet("bitmessagesettings",
                                                   "smtpdeliver", '') != '':
                smtpDeliveryThread = smtpDeliver()
                smtpDeliveryThread.start()

            # SMTP daemon thread
            if daemon and BMConfigParser().safeGetBoolean(
                    "bitmessagesettings", "smtpd"):
                smtpServerThread = smtpServer()
                smtpServerThread.start()

            # Start the thread that calculates POWs
            objectProcessorThread = objectProcessor()
            objectProcessorThread.daemon = False  # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object.
            objectProcessorThread.start()

        # Start the cleanerThread
        singleCleanerThread = singleCleaner()
        singleCleanerThread.daemon = True  # close the main program even if there are threads left
        singleCleanerThread.start()

        # Not needed if objproc disabled
        if state.enableObjProc:
            shared.reloadMyAddressHashes()
            shared.reloadBroadcastSendersForWhichImWatching()

            # API is also objproc dependent
            if BMConfigParser().safeGetBoolean('bitmessagesettings',
                                               'apienabled'):
                singleAPIThread = singleAPI()
                singleAPIThread.daemon = True  # close the main program even if there are threads left
                singleAPIThread.start()

        # start network components if networking is enabled
        if state.enableNetwork:
            BMConnectionPool()
            asyncoreThread = BMNetworkThread()
            asyncoreThread.daemon = True
            asyncoreThread.start()
            for i in range(BMConfigParser().getint("threads", "receive")):
                receiveQueueThread = ReceiveQueueThread(i)
                receiveQueueThread.daemon = True
                receiveQueueThread.start()
            announceThread = AnnounceThread()
            announceThread.daemon = True
            announceThread.start()
            state.invThread = InvThread()
            state.invThread.daemon = True
            state.invThread.start()
            state.addrThread = AddrThread()
            state.addrThread.daemon = True
            state.addrThread.start()
            state.downloadThread = DownloadThread()
            state.downloadThread.daemon = True
            state.downloadThread.start()

            connectToStream(1)

            if BMConfigParser().safeGetBoolean('bitmessagesettings', 'upnp'):
                import upnp
                upnpThread = upnp.uPnPThread()
                upnpThread.start()
        else:
            # Populate with hardcoded value (same as connectToStream above)
            state.streamsInWhichIAmParticipating.append(1)

        if daemon is False and state.enableGUI:  # FIXME redundant?
            if state.curses is False:
                if not depends.check_pyqt():
                    sys.exit(
                        'PyBitmessage requires PyQt unless you want'
                        ' to run it as a daemon and interact with it'
                        ' using the API. You can download PyQt from '
                        'http://www.riverbankcomputing.com/software/pyqt/download'
                        ' or by searching Google for \'PyQt Download\'.'
                        ' If you want to run in daemon mode, see '
                        'https://bitmessage.org/wiki/Daemon\n'
                        'You can also run PyBitmessage with'
                        ' the new curses interface by providing'
                        ' \'-c\' as a commandline argument.')

                import bitmessageqt
                bitmessageqt.run()
            else:
                if True:
                    #                if depends.check_curses():
                    print('Running with curses')
                    import bitmessagecurses
                    bitmessagecurses.runwrapper()
        else:
            BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')

        if daemon:
            while state.shutdown == 0:
                sleep(1)
                if state.testmode and 30 <= \
                        (datetime.now() - state.last_api_response).seconds:
                    self.stop()
        elif not state.enableGUI:
            from tests import core
            test_core_result = core.run()
            state.enableGUI = True
            self.stop()
            sys.exit('Core tests failed!' if test_core_result.errors
                     or test_core_result.failures else 0)
Exemplo n.º 24
0
    def loop(self):
        # defaults to empty loop if outbound connections are maxed
        spawnConnections = False
        acceptConnections = True
        if BMConfigParser().safeGetBoolean('bitmessagesettings',
                                           'dontconnect'):
            acceptConnections = False
        elif BMConfigParser().safeGetBoolean('bitmessagesettings',
                                             'sendoutgoingconnections'):
            spawnConnections = True
        if BMConfigParser().get('bitmessagesettings', 'socksproxytype')[0:5] == 'SOCKS' and \
            (not BMConfigParser().getboolean('bitmessagesettings', 'sockslisten') and \
            ".onion" not in BMConfigParser().get('bitmessagesettings', 'onionhostname')):
            acceptConnections = False

        if spawnConnections:
            if not self.bootstrapped:
                helper_bootstrap.dns()
                self.bootstrapped = True
                Proxy.proxy = (BMConfigParser().safeGet(
                    "bitmessagesettings",
                    "sockshostname"), BMConfigParser().safeGetInt(
                        "bitmessagesettings", "socksport"))
            established = sum(1 for c in self.outboundConnections.values()
                              if (c.connected and c.fullyEstablished))
            pending = len(self.outboundConnections) - established
            if established < BMConfigParser().safeGetInt(
                    "bitmessagesettings", "maxoutboundconnections"):
                for i in range(state.maximumNumberOfHalfOpenConnections -
                               pending):
                    try:
                        chosen = chooseConnection(random.choice(self.streams))
                    except ValueError:
                        continue
                    if chosen in self.outboundConnections:
                        continue
                    if chosen.host in self.inboundConnections:
                        continue
                    # don't connect to self
                    if chosen in state.ownAddresses:
                        continue

                    #for c in self.outboundConnections:
                    #    if chosen == c.destination:
                    #        continue
                    #for c in self.inboundConnections:
                    #    if chosen.host == c.destination.host:
                    #        continue
                    try:
                        if (BMConfigParser().safeGet(
                                "bitmessagesettings",
                                "socksproxytype") == "SOCKS5"):
                            self.addConnection(
                                network.tcp.Socks5BMConnection(chosen))
                        elif (BMConfigParser().safeGet(
                                "bitmessagesettings",
                                "socksproxytype") == "SOCKS4a"):
                            self.addConnection(
                                network.tcp.Socks4aBMConnection(chosen))
                        elif not chosen.host.endswith(".onion"):
                            self.addConnection(
                                network.tcp.TCPConnection(chosen))
                    except socket.error as e:
                        if e.errno == errno.ENETUNREACH:
                            continue

                    self.lastSpawned = time.time()

        if acceptConnections:
            if not self.listeningSockets:
                if BMConfigParser().safeGet("network", "bind") == '':
                    self.startListening()
                else:
                    for bind in re.sub(
                            "[^\w.]+", " ",
                            BMConfigParser().safeGet("network",
                                                     "bind")).split():
                        self.startListening(bind)
                logger.info('Listening for incoming connections.')
            if not self.udpSockets:
                if BMConfigParser().safeGet("network", "bind") == '':
                    self.startUDPSocket()
                else:
                    for bind in re.sub(
                            "[^\w.]+", " ",
                            BMConfigParser().safeGet("network",
                                                     "bind")).split():
                        self.startUDPSocket(bind)
                    self.startUDPSocket(False)
                logger.info('Starting UDP socket(s).')
        else:
            if self.listeningSockets:
                for i in self.listeningSockets.values():
                    i.close_reason = "Stopping listening"
                    i.accepting = i.connecting = i.connected = False
                logger.info('Stopped listening for incoming connections.')
            if self.udpSockets:
                for i in self.udpSockets.values():
                    i.close_reason = "Stopping UDP socket"
                    i.accepting = i.connecting = i.connected = False
                logger.info('Stopped udp sockets.')

        loopTime = float(self.spawnWait)
        if self.lastSpawned < time.time() - self.spawnWait:
            loopTime = 2.0
        asyncore.loop(timeout=loopTime, count=1000)

        reaper = []
        for i in self.inboundConnections.values(
        ) + self.outboundConnections.values():
            minTx = time.time() - 20
            if i.fullyEstablished:
                minTx -= 300 - 20
            if i.lastTx < minTx:
                if i.fullyEstablished:
                    i.append_write_buf(protocol.CreatePacket('ping'))
                else:
                    i.close_reason = "Timeout (%is)" % (time.time() - i.lastTx)
                    i.set_state("close")
        for i in self.inboundConnections.values(
        ) + self.outboundConnections.values() + self.listeningSockets.values(
        ) + self.udpSockets.values():
            if not (i.accepting or i.connecting or i.connected):
                reaper.append(i)
            else:
                try:
                    if i.state == "close":
                        reaper.append(i)
                except AttributeError:
                    pass
        for i in reaper:
            self.removeConnection(i)
Exemplo n.º 25
0
    def processmsg(self, data):
        messageProcessingStartTime = time.time()
        shared.numberOfMessagesProcessed += 1
        queues.UISignalQueue.put(
            ('updateNumberOfMessagesProcessed', 'no data'))
        readPosition = 20  # bypass the nonce, time, and object type
        msgVersion, msgVersionLength = decodeVarint(
            data[readPosition:readPosition + 9])
        if msgVersion != 1:
            logger.info(
                'Cannot understand message versions other than one. Ignoring message.'
            )
            return
        readPosition += msgVersionLength

        streamNumberAsClaimedByMsg, streamNumberAsClaimedByMsgLength = decodeVarint(
            data[readPosition:readPosition + 9])
        readPosition += streamNumberAsClaimedByMsgLength
        inventoryHash = calculateInventoryHash(data)
        initialDecryptionSuccessful = False

        # This is not an acknowledgement bound for me. See if it is a message
        # bound for me by trying to decrypt it with my private keys.

        for key, cryptorObject in shared.myECCryptorObjects.items():
            try:
                if initialDecryptionSuccessful:  # continue decryption attempts to avoid timing attacks
                    cryptorObject.decrypt(data[readPosition:])
                else:
                    decryptedData = cryptorObject.decrypt(data[readPosition:])
                    toRipe = key  # This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data.
                    initialDecryptionSuccessful = True
                    logger.info(
                        'EC decryption successful using key associated with ripe hash: %s.'
                        % hexlify(key))
            except Exception as err:
                pass
        if not initialDecryptionSuccessful:
            # This is not a message bound for me.
            logger.info(
                'Length of time program spent failing to decrypt this message: %s seconds.'
                % (time.time() - messageProcessingStartTime, ))
            return

        # This is a message bound for me.
        toAddress = shared.myAddressesByHash[
            toRipe]  # Look up my address based on the RIPE hash.
        readPosition = 0
        sendersAddressVersionNumber, sendersAddressVersionNumberLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        readPosition += sendersAddressVersionNumberLength
        if sendersAddressVersionNumber == 0:
            logger.info(
                'Cannot understand sendersAddressVersionNumber = 0. Ignoring message.'
            )
            return
        if sendersAddressVersionNumber > 4:
            logger.info(
                'Sender\'s address version number %s not yet supported. Ignoring message.'
                % sendersAddressVersionNumber)
            return
        if len(decryptedData) < 170:
            logger.info(
                'Length of the unencrypted data is unreasonably short. Sanity check failed. Ignoring message.'
            )
            return
        sendersStreamNumber, sendersStreamNumberLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        if sendersStreamNumber == 0:
            logger.info('sender\'s stream number is 0. Ignoring message.')
            return
        readPosition += sendersStreamNumberLength
        behaviorBitfield = decryptedData[readPosition:readPosition + 4]
        readPosition += 4
        pubSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
        readPosition += 64
        pubEncryptionKey = '\x04' + decryptedData[readPosition:readPosition +
                                                  64]
        readPosition += 64
        if sendersAddressVersionNumber >= 3:
            requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = decodeVarint(
                decryptedData[readPosition:readPosition + 10])
            readPosition += varintLength
            logger.info(
                'sender\'s requiredAverageProofOfWorkNonceTrialsPerByte is %s'
                % requiredAverageProofOfWorkNonceTrialsPerByte)
            requiredPayloadLengthExtraBytes, varintLength = decodeVarint(
                decryptedData[readPosition:readPosition + 10])
            readPosition += varintLength
            logger.info('sender\'s requiredPayloadLengthExtraBytes is %s' %
                        requiredPayloadLengthExtraBytes)
        endOfThePublicKeyPosition = readPosition  # needed for when we store the pubkey in our database of pubkeys for later use.
        if toRipe != decryptedData[readPosition:readPosition + 20]:
            logger.info(
                'The original sender of this message did not send it to you. Someone is attempting a Surreptitious Forwarding Attack.\n\
                See: http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html \n\
                your toRipe: %s\n\
                embedded destination toRipe: %s' %
                (hexlify(toRipe),
                 hexlify(decryptedData[readPosition:readPosition + 20])))
            return
        readPosition += 20
        messageEncodingType, messageEncodingTypeLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        readPosition += messageEncodingTypeLength
        messageLength, messageLengthLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        readPosition += messageLengthLength
        message = decryptedData[readPosition:readPosition + messageLength]
        # print 'First 150 characters of message:', repr(message[:150])
        readPosition += messageLength
        ackLength, ackLengthLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        readPosition += ackLengthLength
        ackData = decryptedData[readPosition:readPosition + ackLength]
        readPosition += ackLength
        positionOfBottomOfAckData = readPosition  # needed to mark the end of what is covered by the signature
        signatureLength, signatureLengthLength = decodeVarint(
            decryptedData[readPosition:readPosition + 10])
        readPosition += signatureLengthLength
        signature = decryptedData[readPosition:readPosition + signatureLength]
        signedData = data[8:20] + encodeVarint(
            1) + encodeVarint(streamNumberAsClaimedByMsg
                              ) + decryptedData[:positionOfBottomOfAckData]

        if not highlevelcrypto.verify(signedData, signature,
                                      hexlify(pubSigningKey)):
            logger.debug('ECDSA verify failed')
            return
        logger.debug('ECDSA verify passed')
        logger.debug(
            'As a matter of intellectual curiosity, here is the Bitcoin address associated with the keys owned by the other person: %s  ..and here is the testnet address: %s. The other person must take their private signing key from Bitmessage and import it into Bitcoin (or a service like Blockchain.info) for it to be of any use. Do not use this unless you know what you are doing.'
            %
            (helper_bitcoin.calculateBitcoinAddressFromPubkey(pubSigningKey),
             helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey)))
        sigHash = hashlib.sha512(hashlib.sha512(signature).digest()).digest()[
            32:]  # Used to detect and ignore duplicate messages in our inbox

        # calculate the fromRipe.
        sha = hashlib.new('sha512')
        sha.update(pubSigningKey + pubEncryptionKey)
        ripe = hashlib.new('ripemd160')
        ripe.update(sha.digest())
        fromAddress = encodeAddress(sendersAddressVersionNumber,
                                    sendersStreamNumber, ripe.digest())

        # Let's store the public key in case we want to reply to this
        # person.
        sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', fromAddress,
                   sendersAddressVersionNumber,
                   decryptedData[:endOfThePublicKeyPosition], int(time.time()),
                   'yes')

        # Check to see whether we happen to be awaiting this
        # pubkey in order to send a message. If we are, it will do the POW
        # and send it.
        self.possibleNewPubkey(fromAddress)

        # If this message is bound for one of my version 3 addresses (or
        # higher), then we must check to make sure it meets our demanded
        # proof of work requirement. If this is bound for one of my chan
        # addresses then we skip this check; the minimum network POW is
        # fine.
        if decodeAddress(toAddress)[1] >= 3 and not BMConfigParser(
        ).safeGetBoolean(
                toAddress, 'chan'
        ):  # If the toAddress version number is 3 or higher and not one of my chan addresses:
            if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(
                    fromAddress):  # If I'm not friendly with this person:
                requiredNonceTrialsPerByte = BMConfigParser().getint(
                    toAddress, 'noncetrialsperbyte')
                requiredPayloadLengthExtraBytes = BMConfigParser().getint(
                    toAddress, 'payloadlengthextrabytes')
                if not protocol.isProofOfWorkSufficient(
                        data, requiredNonceTrialsPerByte,
                        requiredPayloadLengthExtraBytes):
                    logger.info(
                        'Proof of work in msg is insufficient only because it does not meet our higher requirement.'
                    )
                    return
        blockMessage = False  # Gets set to True if the user shouldn't see the message according to black or white lists.
        if BMConfigParser().get(
                'bitmessagesettings',
                'blackwhitelist') == 'black':  # If we are using a blacklist
            queryreturn = sqlQuery(
                '''SELECT label FROM blacklist where address=? and enabled='1' ''',
                fromAddress)
            if queryreturn != []:
                logger.info('Message ignored because address is in blacklist.')

                blockMessage = True
        else:  # We're using a whitelist
            queryreturn = sqlQuery(
                '''SELECT label FROM whitelist where address=? and enabled='1' ''',
                fromAddress)
            if queryreturn == []:
                logger.info(
                    'Message ignored because address not in whitelist.')
                blockMessage = True

        toLabel = BMConfigParser().get(toAddress, 'label')
        if toLabel == '':
            toLabel = toAddress

        decodedMessage = helper_msgcoding.MsgDecode(messageEncodingType,
                                                    message)
        subject = decodedMessage.subject
        body = decodedMessage.body

        # Let us make sure that we haven't already received this message
        if helper_inbox.isMessageAlreadyInInbox(sigHash):
            logger.info('This msg is already in our inbox. Ignoring it.')
            blockMessage = True
        if not blockMessage:
            if messageEncodingType != 0:
                t = (inventoryHash, toAddress, fromAddress, subject,
                     int(time.time()), body, 'inbox', messageEncodingType, 0,
                     sigHash)
                helper_inbox.insert(t)

                queues.UISignalQueue.put(
                    ('displayNewInboxMessage', (inventoryHash, toAddress,
                                                fromAddress, subject, body)))

            # If we are behaving as an API then we might need to run an
            # outside command to let some program know that a new message
            # has arrived.
            if BMConfigParser().safeGetBoolean('bitmessagesettings',
                                               'apienabled'):
                try:
                    apiNotifyPath = BMConfigParser().get(
                        'bitmessagesettings', 'apinotifypath')
                except:
                    apiNotifyPath = ''
                if apiNotifyPath != '':
                    call([apiNotifyPath, "newMessage"])

            # Let us now check and see whether our receiving address is
            # behaving as a mailing list
            if BMConfigParser().safeGetBoolean(
                    toAddress, 'mailinglist') and messageEncodingType != 0:
                try:
                    mailingListName = BMConfigParser().get(
                        toAddress, 'mailinglistname')
                except:
                    mailingListName = ''
                # Let us send out this message as a broadcast
                subject = self.addMailingListNameToSubject(
                    subject, mailingListName)
                # Let us now send this message out as a broadcast
                message = time.strftime(
                    "%a, %Y-%m-%d %H:%M:%S UTC", time.gmtime()
                ) + '   Message ostensibly from ' + fromAddress + ':\n\n' + body
                fromAddress = toAddress  # The fromAddress for the broadcast that we are about to send is the toAddress (my address) for the msg message we are currently processing.
                ackdataForBroadcast = OpenSSL.rand(
                    32
                )  # We don't actually need the ackdataForBroadcast for acknowledgement since this is a broadcast message but we can use it to update the user interface when the POW is done generating.
                toAddress = '[Broadcast subscribers]'
                ripe = ''

                # We really should have a discussion about how to
                # set the TTL for mailing list broadcasts. This is obviously
                # hard-coded.
                TTL = 2 * 7 * 24 * 60 * 60  # 2 weeks
                t = (
                    '',
                    toAddress,
                    ripe,
                    fromAddress,
                    subject,
                    message,
                    ackdataForBroadcast,
                    int(time.time()),  # sentTime (this doesn't change)
                    int(time.time()),  # lastActionTime
                    0,
                    'broadcastqueued',
                    0,
                    'sent',
                    messageEncodingType,
                    TTL)
                helper_sent.insert(t)

                queues.UISignalQueue.put(
                    ('displayNewSentMessage',
                     (toAddress, '[Broadcast subscribers]', fromAddress,
                      subject, message, ackdataForBroadcast)))
                queues.workerQueue.put(('sendbroadcast', ''))

        # Don't send ACK if invalid, blacklisted senders, invisible messages, disabled or chan
        if self.ackDataHasAValidHeader(ackData) and \
            not blockMessage and \
            messageEncodingType != 0 and \
            not BMConfigParser().safeGetBoolean(toAddress, 'dontsendack') and \
            not BMConfigParser().safeGetBoolean(toAddress, 'chan'):
            shared.checkAndShareObjectWithPeers(ackData[24:])

        # Display timing data
        timeRequiredToAttemptToDecryptMessage = time.time(
        ) - messageProcessingStartTime
        shared.successfullyDecryptMessageTimings.append(
            timeRequiredToAttemptToDecryptMessage)
        sum = 0
        for item in shared.successfullyDecryptMessageTimings:
            sum += item
        logger.debug('Time to decrypt this message successfully: %s\n\
                     Average time for all message decryption successes since startup: %s.'
                     % (timeRequiredToAttemptToDecryptMessage,
                        sum / len(shared.successfullyDecryptMessageTimings)))
Exemplo n.º 26
0
def identiconize(address):
    size = 48

    # 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'

    # 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:
        # :Author:Shin Adachi <*****@*****.**>
        # Licesensed under FreeBSD License.
        # stripped from PIL and uses QT instead (by sendiulo, same license)
        import qidenticon
        hash = hashlib.md5(addBMIfNotPresent(address) +
                           identiconsuffix).hexdigest()
        use_two_colors = (
            identicon_lib[:len('qidenticon_two')] == 'qidenticon_two')
        opacity = int(not ((identicon_lib == 'qidenticon_x') |
                           (identicon_lib == 'qidenticon_two_x') |
                           (identicon_lib == 'qidenticon_b') |
                           (identicon_lib == 'qidenticon_two_b'))) * 255
        penwidth = 0
        image = qidenticon.render_identicon(int(hash, 16), size,
                                            use_two_colors, opacity, penwidth)
        # filename = './images/identicons/'+hash+'.png'
        # image.save(filename)
        idcon = QtGui.QIcon()
        idcon.addPixmap(image, QtGui.QIcon.Normal, QtGui.QIcon.Off)
        return idcon
    elif identicon_lib == 'pydenticon':
        # print identicon_lib
        # Here you could load pydenticon.py (just put it in the "src" folder of your Bitmessage source)
        from pydenticon import Pydenticon
        # It is not included in the source, because it is licensed under GPLv3
        # GPLv3 is a copyleft license that would influence our licensing
        # Find the source here: http://boottunes.googlecode.com/svn-history/r302/trunk/src/pydenticon.py
        # note that it requires PIL to be installed: http://www.pythonware.com/products/pil/
        idcon_render = Pydenticon(
            addBMIfNotPresent(address) + identiconsuffix, size * 3)
        rendering = idcon_render._render()
        data = rendering.convert("RGBA").tostring("raw", "RGBA")
        qim = QImage(data, size, size, QImage.Format_ARGB32)
        pix = QPixmap.fromImage(qim)
        idcon = QtGui.QIcon()
        idcon.addPixmap(pix, QtGui.QIcon.Normal, QtGui.QIcon.Off)
        return idcon
Exemplo n.º 27
0
    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:
            self.cur.execute(
                '''CREATE TABLE inbox (msgid blob, toaddress text, fromaddress text, subject text, received text, message text, folder text, encodingtype int, read bool, sighash blob, UNIQUE(msgid) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill integer, status text, retrynumber integer, folder text, encodingtype int, ttl int)'''
            )
            self.cur.execute(
                '''CREATE TABLE subscriptions (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE addressbook (label text, address text)''')
            self.cur.execute(
                '''CREATE TABLE blacklist (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE whitelist (label text, address text, enabled bool)'''
            )
            self.cur.execute(
                '''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            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(
                '''INSERT INTO subscriptions VALUES('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('lastvacuumtime',?)''',
                (int(time.time()), ))
            self.cur.execute(
                '''CREATE TABLE objectprocessorqueue (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)'''
            )
            self.conn.commit()
            logger.info('Created messages database file')
        except Exception as err:
            if str(err) == 'table inbox already exists':
                logger.debug('Database file already exists.')

            else:
                sys.stderr.write(
                    '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')

        # 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:
            item = '''ALTER TABLE pubkeys ADD usedpersonally text DEFAULT 'no' '''
            parameters = ''
            self.cur.execute(item, parameters)
            self.conn.commit()

            BMConfigParser().set('bitmessagesettings', '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:
            item = '''ALTER TABLE inbox ADD encodingtype int DEFAULT '2' '''
            parameters = ''
            self.cur.execute(item, parameters)

            item = '''ALTER TABLE inbox ADD read bool DEFAULT '1' '''
            parameters = ''
            self.cur.execute(item, parameters)

            item = '''ALTER TABLE sent ADD encodingtype int DEFAULT '2' '''
            parameters = ''
            self.cur.execute(item, parameters)
            self.conn.commit()

            BMConfigParser().set('bitmessagesettings', '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')

        if BMConfigParser().getint('bitmessagesettings',
                                   'settingsversion') == 5:
            BMConfigParser().set('bitmessagesettings',
                                 'maxacceptablenoncetrialsperbyte', '0')
            BMConfigParser().set('bitmessagesettings',
                                 'maxacceptablepayloadlengthextrabytes', '0')
            BMConfigParser().set('bitmessagesettings', 'settingsversion', '6')

        # 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
        # version we are on can stay embedded in the messages.dat file. Let us
        # check to see if the settings table exists yet.
        item = '''SELECT name FROM sqlite_master WHERE type='table' AND name='settings';'''
        parameters = ''
        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.')
            self.cur.execute(
                '''CREATE TABLE settings (key text, value blob, UNIQUE(key) ON CONFLICT REPLACE)'''
            )
            self.cur.execute('''INSERT INTO settings VALUES('version','1')''')
            self.cur.execute(
                '''INSERT INTO settings VALUES('lastvacuumtime',?)''',
                (int(time.time()), ))
            logger.debug(
                'In messages.dat database, removing an obsolete field from the pubkeys table.'
            )
            self.cur.execute(
                '''CREATE TEMPORARY TABLE pubkeys_backup(hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE);'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys_backup SELECT hash, transmitdata, time, usedpersonally FROM pubkeys;'''
            )
            self.cur.execute('''DROP TABLE pubkeys''')
            self.cur.execute(
                '''CREATE TABLE pubkeys (hash blob, transmitdata blob, time int, usedpersonally text, UNIQUE(hash) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys SELECT hash, transmitdata, time, usedpersonally FROM pubkeys_backup;'''
            )
            self.cur.execute('''DROP TABLE pubkeys_backup;''')
            logger.debug(
                'Deleting all pubkeys from inventory. They will be redownloaded and then saved with the correct times.'
            )
            self.cur.execute(
                '''delete from inventory where objecttype = 'pubkey';''')
            logger.debug(
                'replacing Bitmessage announcements mailing list with a new one.'
            )
            self.cur.execute(
                '''delete from subscriptions where address='BM-BbkPSZbzPwpVcYZpU4yHwf9ZPEapN5Zx' '''
            )
            self.cur.execute(
                '''INSERT INTO subscriptions VALUES('Bitmessage new releases/announcements','BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw',1)'''
            )
            logger.debug('Commiting.')
            self.conn.commit()
            logger.debug(
                'Vacuuming message.dat. You might notice that the file size gets much smaller.'
            )
            self.cur.execute(''' VACUUM ''')

        # After code refactoring, the possible status values for sent messages
        # have changed.
        self.cur.execute(
            '''update sent set status='doingmsgpow' where status='doingpow'  '''
        )
        self.cur.execute(
            '''update sent set status='msgsent' where status='sentmessage'  '''
        )
        self.cur.execute(
            '''update sent set status='doingpubkeypow' where status='findingpubkey'  '''
        )
        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')
        """# 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 = ''
        self.cur.execute(item, parameters)
        if int(self.cur.fetchall()[0][0]) == 1:
            print 'upgrading database'
            item = '''ALTER TABLE inventory ADD first20bytesofencryptedmessage blob DEFAULT '' '''
            parameters = ''
            self.cur.execute(item, parameters)
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (2,)
            self.cur.execute(item, parameters)"""

        # 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.'
            )
            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(
                '''INSERT INTO inventory_backup SELECT hash, objecttype, streamnumber, payload, receivedtime FROM inventory;'''
            )
            self.cur.execute('''DROP TABLE inventory''')
            self.cur.execute(
                '''CREATE TABLE inventory (hash blob, objecttype text, streamnumber int, payload blob, receivedtime integer, UNIQUE(hash) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO inventory SELECT hash, objecttype, streamnumber, payload, receivedtime FROM inventory_backup;'''
            )
            self.cur.execute('''DROP TABLE inventory_backup;''')
            item = '''update settings set value=? WHERE key='version';'''
            parameters = (3, )
            self.cur.execute(item, parameters)

        # Add a new column to the inventory table to store tags.
        item = '''SELECT value FROM settings WHERE key='version';'''
        parameters = ''
        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.'
            )
            item = '''ALTER TABLE inventory ADD tag blob DEFAULT '' '''
            parameters = ''
            self.cur.execute(item, parameters)
            item = '''update settings set value=? WHERE key='version';'''
            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';'''
        parameters = ''
        self.cur.execute(item, parameters)
        currentVersion = int(self.cur.fetchall()[0][0])
        if currentVersion == 4:
            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)'''
            )
            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(
                random.choice(
                    "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
                ) for x in xrange(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.
        item = '''SELECT value FROM settings WHERE key='version';'''
        parameters = ''
        self.cur.execute(item, parameters)
        currentVersion = int(self.cur.fetchall()[0][0])
        if currentVersion == 5:
            self.cur.execute('''DROP TABLE knownnodes''')
            self.cur.execute(
                '''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)
        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.'
            )
            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''')
            self.cur.execute(
                '''CREATE TABLE objectprocessorqueue (objecttype int, data blob, UNIQUE(objecttype, data) ON CONFLICT REPLACE)'''
            )
            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))

        # 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.
        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.'
            )
            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.
            self.cur.execute(
                '''UPDATE sent SET status='msgqueued' WHERE status='doingmsgpow' or status='badkey';'''
            )
            query = '''update settings set value=? WHERE key='version';'''
            parameters = (8, )
            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.
        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.'
            )
            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.
        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...'
            )
            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(
                '''INSERT INTO sent_backup SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, status, 0, folder, encodingtype FROM sent;'''
            )
            self.cur.execute('''DROP TABLE sent''')
            self.cur.execute(
                '''CREATE TABLE sent (msgid blob, toaddress text, toripe blob, fromaddress text, subject text, message text, ackdata blob, senttime integer, lastactiontime integer, sleeptill int, status text, retrynumber integer, folder text, encodingtype int, ttl int)'''
            )
            self.cur.execute(
                '''INSERT INTO sent SELECT msgid, toaddress, toripe, fromaddress, subject, message, ackdata, lastactiontime, lastactiontime, 0, status, 0, folder, encodingtype, 216000 FROM sent_backup;'''
            )
            self.cur.execute('''DROP TABLE sent_backup''')
            logger.info(
                'In messages.dat database, finished making TTL-related changes.'
            )
            logger.debug(
                'In messages.dat database, adding address field to the pubkeys table.'
            )
            # We're going to have to calculate the address for each row in the pubkeys
            # table. Then we can take out the hash field.
            self.cur.execute(
                '''ALTER TABLE pubkeys ADD address text DEFAULT '' ''')
            self.cur.execute('''SELECT hash, addressversion FROM pubkeys''')
            queryResult = self.cur.fetchall()
            from addresses import encodeAddress
            for row in queryResult:
                hash, addressVersion = row
                address = encodeAddress(addressVersion, 1, hash)
                item = '''UPDATE pubkeys SET address=? WHERE hash=?;'''
                parameters = (address, hash)
                self.cur.execute(item, parameters)
            # Now we can remove the hash field from the pubkeys table.
            self.cur.execute(
                '''CREATE TEMPORARY TABLE pubkeys_backup (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys_backup SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys;'''
            )
            self.cur.execute('''DROP TABLE pubkeys''')
            self.cur.execute(
                '''CREATE TABLE pubkeys (address text, addressversion int, transmitdata blob, time int, usedpersonally text, UNIQUE(address) ON CONFLICT REPLACE)'''
            )
            self.cur.execute(
                '''INSERT INTO pubkeys SELECT address, addressversion, transmitdata, time, usedpersonally FROM pubkeys_backup;'''
            )
            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',
                                           '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!

        try:
            testpayload = '\x00\x00'
            t = ('1234', 1, testpayload, '12345678', 'no')
            self.cur.execute('''INSERT INTO pubkeys VALUES(?,?,?,?,?)''', t)
            self.conn.commit()
            self.cur.execute(
                '''SELECT transmitdata FROM pubkeys WHERE address='1234' ''')
            queryreturn = self.cur.fetchall()
            for row in queryreturn:
                transmitdata, = row
            self.cur.execute('''DELETE FROM pubkeys WHERE address='1234' ''')
            self.conn.commit()
            if transmitdata == '':
                logger.fatal(
                    'Problem: The version of SQLite you have cannot store Null values. Please download and install the latest revision of your version of Python (for example, the latest Python 2.7 revision) and try again.\n'
                )
                logger.fatal(
                    'PyBitmessage will now exit very abruptly. You may now see threading errors related to this abrupt exit but the problem you need to solve is related to SQLite.\n\n'
                )
                os._exit(0)
        except Exception as err:
            if str(err) == 'database or disk is full':
                logger.fatal(
                    '(While null value test) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                )
                queues.UISignalQueue.put(('alert', (
                    tr._translate("MainWindow", "Disk full"),
                    tr._translate(
                        "MainWindow",
                        'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                    ), True)))
                os._exit(0)
            else:
                logger.error(err)

        # Let us check to see the last time we vaccumed the messages.dat file.
        # If it has been more than a month let's do it now.
        item = '''SELECT value FROM settings WHERE key='lastvacuumtime';'''
        parameters = ''
        self.cur.execute(item, parameters)
        queryreturn = self.cur.fetchall()
        for row in queryreturn:
            value, = row
            if int(value) < int(time.time()) - 86400:
                logger.info(
                    'It has been a long time since the messages.dat file has been vacuumed. Vacuuming now...'
                )
                try:
                    self.cur.execute(''' VACUUM ''')
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(While VACUUM) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                item = '''update settings set value=? WHERE key='lastvacuumtime';'''
                parameters = (int(time.time()), )
                self.cur.execute(item, parameters)

        state.sqlReady = True

        while True:
            item = helper_sql.sqlSubmitQueue.get()
            if item == 'commit':
                try:
                    self.conn.commit()
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(While committing) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
            elif item == 'exit':
                self.conn.close()
                logger.info('sqlThread exiting gracefully.')

                return
            elif item == 'deleteandvacuume':
                self.cur.execute('''delete from inbox where folder='trash' ''')
                self.cur.execute('''delete from sent where folder='trash' ''')
                self.conn.commit()
                try:
                    self.cur.execute(''' VACUUM ''')
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while deleteandvacuume) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
            else:
                parameters = helper_sql.sqlSubmitQueue.get()
                rowcount = 0
                # print 'item', item
                # print 'parameters', parameters
                try:
                    self.cur.execute(item, parameters)
                    rowcount = self.cur.rowcount
                except Exception as err:
                    if str(err) == 'database or disk is full':
                        logger.fatal(
                            '(while cur.execute) Alert: Your disk or data storage volume is full. sqlThread will now exit.'
                        )
                        queues.UISignalQueue.put(('alert', (
                            tr._translate("MainWindow", "Disk full"),
                            tr._translate(
                                "MainWindow",
                                'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'
                            ), True)))
                        os._exit(0)
                    else:
                        logger.fatal(
                            'Major error occurred when trying to execute a SQL statement within the sqlThread. Please tell Atheros about this error message or post it in the forum! Error occurred while trying to execute statement: "%s"  Here are the parameters; you might want to censor this data with asterisks (***) as it can contain private information: %s. Here is the actual error message thrown by the sqlThread: %s',
                            str(item), str(repr(parameters)), str(err))
                        logger.fatal('This program shall now abruptly exit!')

                    os._exit(0)

                helper_sql.sqlReturnQueue.put((self.cur.fetchall(), rowcount))
Exemplo n.º 28
0
def assembleVersionMessage(remoteHost,
                           remotePort,
                           participatingStreams,
                           server=False,
                           nodeid=None):
    """Construct the payload of a version message, return the resultng bytes of running CreatePacket() on it"""
    payload = ''
    payload += pack('>L', 3)  # protocol version.
    # bitflags of the services I offer.
    payload += pack(
        '>q', NODE_NETWORK | (NODE_SSL if haveSSL(server) else 0) |
        (NODE_DANDELION if state.dandelion else 0))
    payload += pack('>q', int(time.time()))

    payload += pack(
        '>q',
        1)  # boolservices of remote connection; ignored by the remote host.
    if checkSocksIP(
            remoteHost) and server:  # prevent leaking of tor outbound IP
        payload += encodeHost('127.0.0.1')
        payload += pack('>H', 8444)
    else:
        payload += encodeHost(remoteHost)
        payload += pack('>H', remotePort)  # remote IPv6 and port

    # bitflags of the services I offer.
    payload += pack(
        '>q', NODE_NETWORK | (NODE_SSL if haveSSL(server) else 0) |
        (NODE_DANDELION if state.dandelion else 0))
    # = 127.0.0.1. This will be ignored by the remote host. The actual remote connected IP will be used.
    payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack(
        '>L', 2130706433)
    # we have a separate extPort and incoming over clearnet or outgoing through clearnet
    if BMConfigParser().safeGetBoolean('lmessagesettings', 'upnp') and state.extPort \
        and ((server and not checkSocksIP(remoteHost)) or
             (BMConfigParser().get("lmessagesettings", "socksproxytype") == "none" and not server)):
        payload += pack('>H', state.extPort)
    elif checkSocksIP(remoteHost) and server:  # incoming connection over Tor
        payload += pack(
            '>H',
            BMConfigParser().getint('lmessagesettings', 'onionport'))
    else:  # no extPort and not incoming over Tor
        payload += pack('>H',
                        BMConfigParser().getint('lmessagesettings', 'port'))

    random.seed()
    if nodeid is not None:
        payload += nodeid[0:8]
    else:
        payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf
    userAgent = '/PyLMessage:' + softwareVersion + '/'
    payload += encodeVarint(len(userAgent))
    payload += userAgent

    # Streams
    payload += encodeVarint(len(participatingStreams))
    count = 0
    for stream in sorted(participatingStreams):
        payload += encodeVarint(stream)
        count += 1
        # protocol limit, see specification
        if count >= 160000:
            break

    return CreatePacket('version', payload)
Exemplo n.º 29
0
    def HandleSendMessage(self, params):
        if len(params) == 0:
            raise APIError(0, 'I need parameters!')
        elif len(params) == 4:
            toAddress, fromAddress, subject, message = params
            encodingType = 2
            TTL = 4 * 24 * 60 * 60
        elif len(params) == 5:
            toAddress, fromAddress, subject, message, encodingType = params
            TTL = 4 * 24 * 60 * 60
        elif len(params) == 6:
            toAddress, fromAddress, subject, message, encodingType, TTL = \
                params
        if encodingType not in [2, 3]:
            raise APIError(6, 'The encoding type must be 2 or 3.')
        subject = self._decode(subject, "base64")
        message = self._decode(message, "base64")
        if len(subject + message) > (2**18 - 500):
            raise APIError(27, 'Message is too long.')
        if TTL < 60 * 60:
            TTL = 60 * 60
        if TTL > 28 * 24 * 60 * 60:
            TTL = 28 * 24 * 60 * 60
        toAddress = addBMIfNotPresent(toAddress)
        fromAddress = addBMIfNotPresent(fromAddress)
        status, addressVersionNumber, streamNumber, toRipe = \
            self._verifyAddress(toAddress)
        self._verifyAddress(fromAddress)
        try:
            fromAddressEnabled = BMConfigParser().getboolean(
                fromAddress, 'enabled')
        except:
            raise APIError(
                13, 'Could not find your fromAddress in the keys.dat file.')
        if not fromAddressEnabled:
            raise APIError(14, 'Your fromAddress is disabled. Cannot send.')

        stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings',
                                                   'ackstealthlevel')
        ackdata = genAckPayload(streamNumber, stealthLevel)

        t = (
            '',
            toAddress,
            toRipe,
            fromAddress,
            subject,
            message,
            ackdata,
            int(time.time()),  # sentTime (this won't change)
            int(time.time()),  # lastActionTime
            0,
            'msgqueued',
            0,
            'sent',
            2,
            TTL)
        helper_sent.insert(t)

        toLabel = ''
        queryreturn = sqlQuery("SELECT label FROM addressbook WHERE address=?",
                               toAddress)
        if queryreturn != []:
            for row in queryreturn:
                toLabel, = row
        # apiSignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata)))
        queues.UISignalQueue.put(
            ('displayNewSentMessage', (toAddress, toLabel, fromAddress,
                                       subject, message, ackdata)))

        queues.workerQueue.put(('sendmessage', toAddress))

        return hexlify(ackdata)
Exemplo n.º 30
0
    def run(self):
        while True:
            objectType, data = queues.objectProcessorQueue.get()

            self.checkackdata(data)

            try:
                if objectType == 0: # getpubkey
                    self.processgetpubkey(data)
                elif objectType == 1: #pubkey
                    self.processpubkey(data)
                elif objectType == 2: #msg
                    self.processmsg(data)
                elif objectType == 3: #broadcast
                    self.processbroadcast(data)
                elif objectType == 'checkShutdownVariable': # is more of a command, not an object type. Is used to get this thread past the queue.get() so that it will check the shutdown variable.
                    pass
                else:
                    logger.critical('Error! Bug! The class_objectProcessor was passed an object type it doesn\'t recognize: %s' % str(objectType))
            except helper_msgcoding.DecompressionSizeException as e:
                logger.error("The object is too big after decompression (stopped decompressing at %ib, your configured limit %ib). Ignoring", e.size, BMConfigParser().safeGetInt("zlib", "maxsize"))
            except varintDecodeError as e:
                logger.debug("There was a problem with a varint while processing an object. Some details: %s" % e)
            except Exception as e:
                logger.critical("Critical error within objectProcessorThread: \n%s" % traceback.format_exc())

            if state.shutdown:
                time.sleep(.5) # Wait just a moment for most of the connections to close
                numberOfObjectsThatWereInTheObjectProcessorQueue = 0
                with SqlBulkExecute() as sql:
                    while queues.objectProcessorQueue.curSize > 0:
                        objectType, data = queues.objectProcessorQueue.get()
                        sql.execute('''INSERT INTO objectprocessorqueue VALUES (?,?)''',
                                   objectType,data)
                        numberOfObjectsThatWereInTheObjectProcessorQueue += 1
                logger.debug('Saved %s objects from the objectProcessorQueue to disk. objectProcessorThread exiting.' % str(numberOfObjectsThatWereInTheObjectProcessorQueue))
                state.shutdown = 2
                break