示例#1
0
    def setLabel(self, label=None):
        """Set label"""
        super(MessageList_AddressWidget, self).setLabel(label)
        if label is not None:
            return
        newLabel = self.address
        queryreturn = None
        if self.type in (AccountMixin.NORMAL, AccountMixin.CHAN,
                         AccountMixin.MAILINGLIST):
            try:
                newLabel = unicode(BMConfigParser().get(self.address, 'label'),
                                   'utf-8', 'ignore')
            except:
                queryreturn = sqlQuery(
                    '''select label from addressbook where address=?''',
                    self.address)
        elif self.type == AccountMixin.SUBSCRIPTION:
            queryreturn = sqlQuery(
                '''select label from subscriptions where address=?''',
                self.address)
        if queryreturn:
            for row in queryreturn:
                newLabel = unicode(row[0], 'utf-8', 'ignore')

        self.label = newLabel
示例#2
0
 def HandleListAddressBookEntries(self, params):
     if len(params) == 1:
         label, = params
         label = self._decode(label, "base64")
         queryreturn = sqlQuery(
             "SELECT label, address from addressbook WHERE label = ?",
             label)
     elif len(params) > 1:
         raise APIError(0, "Too many paremeters, max 1")
     else:
         queryreturn = sqlQuery("SELECT label, address from addressbook")
     data = '{"addresses":['
     for row in queryreturn:
         label, address = row
         label = shared.fixPotentiallyInvalidUTF8Data(label)
         if len(data) > 20:
             data += ','
         data += json.dumps(
             {
                 'label': base64.b64encode(label),
                 'address': address
             },
             indent=4,
             separators=(',', ': '))
     data += ']}'
     return data
示例#3
0
def doCleanShutdown():
    state.shutdown = 1  #Used to tell proof of work worker threads and the objectProcessorThread to exit.
    objectProcessorQueue.put(('checkShutdownVariable', 'no data'))
    for thread in threading.enumerate():
        if thread.isAlive() and isinstance(thread, StoppableThread):
            thread.stopThread()

    UISignalQueue.put(
        ('updateStatusBar', 'Saving the knownNodes list of peers to disk...'))
    logger.info('Saving knownNodes list of peers to disk')
    saveKnownNodes()
    logger.info('Done saving knownNodes list of peers to disk')
    UISignalQueue.put(('updateStatusBar',
                       'Done saving the knownNodes list of peers to disk.'))
    logger.info('Flushing inventory in memory out to disk...')
    UISignalQueue.put((
        'updateStatusBar',
        'Flushing inventory in memory out to disk. This should normally only take a second...'
    ))
    Inventory().flush()

    # Verify that the objectProcessor has finished exiting. It should have incremented the
    # shutdown variable from 1 to 2. This must finish before we command the sqlThread to exit.
    while state.shutdown == 1:
        time.sleep(.1)

    # This one last useless query will guarantee that the previous flush committed and that the
    # objectProcessorThread committed before we close the program.
    sqlQuery('SELECT address FROM subscriptions')
    logger.info('Finished flushing inventory.')
    sqlStoredProcedure('exit')

    # Wait long enough to guarantee that any running proof of work worker threads will check the
    # shutdown variable and exit. If the main thread closes before they do then they won't stop.
    time.sleep(.25)

    for thread in threading.enumerate():
        if thread is not threading.currentThread() and isinstance(
                thread, StoppableThread):
            logger.debug("Waiting for thread %s", thread.name)
            thread.join()

    # flush queued
    for queue in (workerQueue, UISignalQueue, addressGeneratorQueue,
                  objectProcessorQueue):
        while True:
            try:
                queue.get(False)
                queue.task_done()
            except Queue.Empty:
                break

    if shared.thisapp.daemon:
        logger.info('Clean shutdown complete.')
        shared.thisapp.cleanup()
        os._exit(0)
    else:
        logger.info('Core shutdown complete.')
    for thread in threading.enumerate():
        logger.debug("Thread %s still running", thread.name)
示例#4
0
 def setLabel(self, label=None):
     newLabel = self.address
     if label is None:
         queryreturn = None
         if self.type in (AccountMixin.NORMAL, AccountMixin.CHAN,
                          AccountMixin.MAILINGLIST):
             try:
                 newLabel = unicode(
                     BMConfigParser().get(self.address, 'label'), 'utf-8',
                     'ignore')
             except:
                 queryreturn = sqlQuery(
                     '''select label from addressbook where address=?''',
                     self.address)
         elif self.type == AccountMixin.SUBSCRIPTION:
             queryreturn = sqlQuery(
                 '''select label from subscriptions where address=?''',
                 self.address)
         if queryreturn is not None:
             if queryreturn != []:
                 for row in queryreturn:
                     newLabel = unicode(row[0], 'utf-8', 'ignore')
     else:
         newLabel = label
     if hasattr(self, 'label') and newLabel == self.label:
         return
     self.label = newLabel
示例#5
0
 def defaultLabel(self):
     queryreturn = None
     retval = None
     if self.type in (AccountMixin.NORMAL, AccountMixin.CHAN,
                      AccountMixin.MAILINGLIST):
         try:
             retval = unicode(BMConfigParser().get(self.address, 'label'),
                              'utf-8')
         except Exception as e:
             queryreturn = sqlQuery(
                 '''select label from addressbook where address=?''',
                 self.address)
     elif self.type == AccountMixin.SUBSCRIPTION:
         queryreturn = sqlQuery(
             '''select label from subscriptions where address=?''',
             self.address)
     if queryreturn is not None:
         if queryreturn != []:
             for row in queryreturn:
                 retval, = row
                 retval = unicode(retval, 'utf-8')
     elif self.address is None or self.type == AccountMixin.ALL:
         return unicode(
             str(QtGui.QApplication.translate("MainWindow",
                                              "All accounts")), 'utf-8')
     if retval is None:
         return unicode(self.address, 'utf-8')
     else:
         return retval
示例#6
0
 def rerenderBlackWhiteList(self):
     tabs = self.parent().parent()
     if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black':
         tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Blacklist'))
     else:
         tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Whitelist'))
     self.tableWidgetBlacklist.setRowCount(0)
     listType = BMConfigParser().get('bitmessagesettings', 'blackwhitelist')
     if listType == 'black':
         queryreturn = sqlQuery('''SELECT label, address, enabled FROM blacklist''')
     else:
         queryreturn = sqlQuery('''SELECT label, address, enabled FROM whitelist''')
     self.tableWidgetBlacklist.setSortingEnabled(False)
     for row in queryreturn:
         label, address, enabled = row
         self.tableWidgetBlacklist.insertRow(0)
         newItem = QtGui.QTableWidgetItem(unicode(label, 'utf-8'))
         if not enabled:
             newItem.setTextColor(QtGui.QColor(128, 128, 128))
         newItem.setIcon(avatarize(address))
         self.tableWidgetBlacklist.setItem(0, 0, newItem)
         newItem = QtGui.QTableWidgetItem(address)
         newItem.setFlags(
             QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
         if not enabled:
             newItem.setTextColor(QtGui.QColor(128, 128, 128))
         self.tableWidgetBlacklist.setItem(0, 1, newItem)
     self.tableWidgetBlacklist.setSortingEnabled(True)
示例#7
0
def getSortedSubscriptions(count=False):
    queryreturn = sqlQuery(
        'SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC'
    )
    ret = {}
    for row in queryreturn:
        label, address, enabled = row
        ret[address] = {}
        ret[address]["inbox"] = {}
        ret[address]["inbox"]['label'] = label
        ret[address]["inbox"]['enabled'] = enabled
        ret[address]["inbox"]['count'] = 0
    if count:
        queryreturn = sqlQuery(
            '''SELECT fromaddress, folder, count(msgid) as cnt
            FROM inbox, subscriptions ON subscriptions.address = inbox.fromaddress
            WHERE read = 0 AND toaddress = ?
            GROUP BY inbox.fromaddress, folder''', str_broadcast_subscribers)
        for row in queryreturn:
            address, folder, cnt = row
            if not folder in ret[address]:
                ret[address][folder] = {
                    'label': ret[address]['inbox']['label'],
                    'enabled': ret[address]['inbox']['enabled']
                }
            ret[address][folder]['count'] = cnt
    return ret
def getSortedSubscriptions(count=False):
    """
    Actually return a grouped dictionary rather than a sorted list

    :param count: Whether to count messages for each fromaddress in the inbox
    :type count: bool, default False
    :retuns: dict keys are addresses, values are dicts containing settings
    :rtype: dict, default {}
    """
    queryreturn = sqlQuery(
        'SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC'
    )
    ret = {}
    for row in queryreturn:
        label, address, enabled = row
        ret[address] = {}
        ret[address]["inbox"] = {}
        ret[address]["inbox"]['label'] = label
        ret[address]["inbox"]['enabled'] = enabled
        ret[address]["inbox"]['count'] = 0
    if count:
        queryreturn = sqlQuery(
            '''SELECT fromaddress, folder, count(msgid) as cnt
            FROM inbox, subscriptions ON subscriptions.address = inbox.fromaddress
            WHERE read = 0 AND toaddress = ?
            GROUP BY inbox.fromaddress, folder''', str_broadcast_subscribers)
        for row in queryreturn:
            address, folder, cnt = row
            if folder not in ret[address]:
                ret[address][folder] = {
                    'label': ret[address]['inbox']['label'],
                    'enabled': ret[address]['inbox']['enabled']
                }
            ret[address][folder]['count'] = cnt
    return ret
    def recgetdata(self, data):
        numberOfRequestedInventoryItems, lengthOfVarint = decodeVarint(
            data[:10])
        if len(data) < lengthOfVarint + (32 * numberOfRequestedInventoryItems):
            return
        for i in xrange(numberOfRequestedInventoryItems):
            hash = data[lengthOfVarint + (
                i * 32):32 + lengthOfVarint + (i * 32)]

            shared.numberOfInventoryLookupsPerformed += 1
            shared.inventoryLock.acquire()
            if hash in shared.inventory:
                objectType, streamNumber, payload, expiresTime, tag = shared.inventory[hash]
                shared.inventoryLock.release()
                self.sendObject(payload)
            else:
                shared.inventoryLock.release()
                queryreturn = sqlQuery(
                    '''select payload from inventory where hash=? and expirestime>=?''',
                    hash,
                    int(time.time()))
                if queryreturn != []:
                    for row in queryreturn:
                        payload, = row
                    self.sendObject(payload)
                else:
                    pass
示例#10
0
def getStatusByAck(ackdata):
    query = sqlQuery("SELECT status FROM sent WHERE ackdata=? LIMIT 0,1",
                     ackdata)
    if not len(query) == 0:
        return query[0][0]
    else:
        return "not found"
 def sendBigInv(self):
     # Select all hashes for objects in this stream.
     queryreturn = sqlQuery(
         '''SELECT hash FROM inventory WHERE expirestime>? and streamnumber=?''',
         int(time.time()), self.streamNumber)
     bigInvList = {}
     for row in queryreturn:
         hash, = row
         if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
             bigInvList[hash] = 0
     # We also have messages in our inventory in memory (which is a python
     # dictionary). Let's fetch those too.
     with shared.inventoryLock:
         for hash, storedValue in shared.inventory.items():
             if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
                 objectType, streamNumber, payload, expiresTime, tag = storedValue
                 if streamNumber == self.streamNumber and expiresTime > int(
                         time.time()):
                     bigInvList[hash] = 0
     numberOfObjectsInInvMessage = 0
     payload = ''
     # Now let us start appending all of these hashes together. They will be
     # sent out in a big inv message to our new peer.
     for hash, storedValue in bigInvList.items():
         payload += hash
         numberOfObjectsInInvMessage += 1
         if numberOfObjectsInInvMessage == 50000:  # We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages.
             self.sendinvMessageToJustThisOnePeer(
                 numberOfObjectsInInvMessage, payload)
             payload = ''
             numberOfObjectsInInvMessage = 0
     if numberOfObjectsInInvMessage > 0:
         self.sendinvMessageToJustThisOnePeer(numberOfObjectsInInvMessage,
                                              payload)
示例#12
0
 def HandleAddSubscription(self, params):
     if len(params) == 0:
         raise APIError(0, 'I need parameters!')
     if len(params) == 1:
         address, = params
         label = ''
     if len(params) == 2:
         address, label = params
         label = self._decode(label, "base64")
         try:
             unicode(label, 'utf-8')
         except:
             raise APIError(17, 'Label is not valid UTF-8 data.')
     if len(params) > 2:
         raise APIError(0, 'I need either 1 or 2 parameters!')
     address = addBMIfNotPresent(address)
     self._verifyAddress(address)
     # First we must check to see if the address is already in the
     # subscriptions list.
     queryreturn = sqlQuery("SELECT * FROM subscriptions WHERE address=?",
                            address)
     if queryreturn != []:
         raise APIError(16, 'You are already subscribed to that address.')
     sqlExecute("INSERT INTO subscriptions VALUES (?,?,?)", label, address,
                True)
     shared.reloadBroadcastSendersForWhichImWatching()
     queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
     queues.UISignalQueue.put(('rerenderSubscriptions', ''))
     return 'Added subscription.'
示例#13
0
 def HandleGetAllInboxMessages(self, params):
     queryreturn = sqlQuery(
         "SELECT msgid, toaddress, fromaddress, subject, received, message,"
         " encodingtype, read FROM inbox where folder='inbox'"
         " ORDER BY received")
     data = '{"inboxMessages":['
     for row in queryreturn:
         msgid, toAddress, fromAddress, subject, received, message, \
             encodingtype, read = row
         subject = shared.fixPotentiallyInvalidUTF8Data(subject)
         message = shared.fixPotentiallyInvalidUTF8Data(message)
         if len(data) > 25:
             data += ','
         data += json.dumps(
             {
                 'msgid': hexlify(msgid),
                 'toAddress': toAddress,
                 'fromAddress': fromAddress,
                 'subject': base64.b64encode(subject),
                 'message': base64.b64encode(message),
                 'encodingType': encodingtype,
                 'receivedTime': received,
                 'read': read
             },
             indent=4,
             separators=(',', ': '))
     data += ']}'
     return data
    def recgetdata(self, data):
        numberOfRequestedInventoryItems, lengthOfVarint = decodeVarint(
            data[:10])
        if len(data) < lengthOfVarint + (32 * numberOfRequestedInventoryItems):
            print 'getdata message does not contain enough data. Ignoring.'
            return
        for i in xrange(numberOfRequestedInventoryItems):
            hash = data[lengthOfVarint + (
                i * 32):32 + lengthOfVarint + (i * 32)]
            with shared.printLock:
                print 'received getdata request for item:', hash.encode('hex')

            shared.numberOfInventoryLookupsPerformed += 1
            shared.inventoryLock.acquire()
            if hash in shared.inventory:
                objectType, streamNumber, payload, expiresTime, tag = shared.inventory[hash]
                shared.inventoryLock.release()
                self.sendObject(payload)
            else:
                shared.inventoryLock.release()
                queryreturn = sqlQuery(
                    '''select payload from inventory where hash=? and expirestime>=?''',
                    hash,
                    int(time.time()))
                if queryreturn != []:
                    for row in queryreturn:
                        payload, = row
                    self.sendObject(payload)
                else:
                    logger.warning('%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.' % (self.peer,))
示例#15
0
 def HandleGetAllSentMessages(self, params):
     queryreturn = sqlQuery(
         "SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
         " message, encodingtype, status, ackdata FROM sent"
         " WHERE folder='sent' ORDER BY lastactiontime")
     data = '{"sentMessages":['
     for row in queryreturn:
         msgid, toAddress, fromAddress, subject, lastactiontime, message, \
             encodingtype, status, ackdata = row
         subject = shared.fixPotentiallyInvalidUTF8Data(subject)
         message = shared.fixPotentiallyInvalidUTF8Data(message)
         if len(data) > 25:
             data += ','
         data += json.dumps(
             {
                 'msgid': hexlify(msgid),
                 'toAddress': toAddress,
                 'fromAddress': fromAddress,
                 'subject': base64.b64encode(subject),
                 'message': base64.b64encode(message),
                 'encodingType': encodingtype,
                 'lastActionTime': lastactiontime,
                 'status': status,
                 'ackData': hexlify(ackdata)
             },
             indent=4,
             separators=(',', ': '))
     data += ']}'
     return data
示例#16
0
def reloadBroadcastSendersForWhichImWatching():
    broadcastSendersForWhichImWatching.clear()
    MyECSubscriptionCryptorObjects.clear()
    queryreturn = sqlQuery('SELECT address FROM subscriptions where enabled=1')
    logger.debug('reloading subscriptions...')
    for row in queryreturn:
        address, = row
        # status
        _, addressVersionNumber, streamNumber, hash = decodeAddress(address)
        if addressVersionNumber == 2:
            broadcastSendersForWhichImWatching[hash] = 0
        # Now, for all addresses, even version 2 addresses,
        # we should create Cryptor objects in a dictionary which we will
        # use to attempt to decrypt encrypted broadcast messages.

        if addressVersionNumber <= 3:
            privEncryptionKey = hashlib.sha512(
                encodeVarint(addressVersionNumber) +
                encodeVarint(streamNumber) + hash).digest()[:32]
            MyECSubscriptionCryptorObjects[hash] = \
                highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
        else:
            doubleHashOfAddressData = hashlib.sha512(
                hashlib.sha512(
                    encodeVarint(addressVersionNumber) +
                    encodeVarint(streamNumber) + hash).digest()).digest()
            tag = doubleHashOfAddressData[32:]
            privEncryptionKey = doubleHashOfAddressData[:32]
            MyECSubscriptionCryptorObjects[tag] = \
                highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
    def recgetdata(self, data):
        numberOfRequestedInventoryItems, lengthOfVarint = decodeVarint(
            data[:10])
        if len(data) < lengthOfVarint + (32 * numberOfRequestedInventoryItems):
            logger.debug(
                'getdata message does not contain enough data. Ignoring.')
            return
        for i in xrange(numberOfRequestedInventoryItems):
            hash = data[lengthOfVarint + (i * 32):32 + lengthOfVarint +
                        (i * 32)]
            logger.debug('received getdata request for item:' +
                         hash.encode('hex'))

            shared.numberOfInventoryLookupsPerformed += 1
            shared.inventoryLock.acquire()
            if hash in shared.inventory:
                objectType, streamNumber, payload, expiresTime, tag = shared.inventory[
                    hash]
                shared.inventoryLock.release()
                self.sendObject(payload)
            else:
                shared.inventoryLock.release()
                queryreturn = sqlQuery(
                    '''select payload from inventory where hash=? and expirestime>=?''',
                    hash, int(time.time()))
                if queryreturn != []:
                    for row in queryreturn:
                        payload, = row
                    self.sendObject(payload)
                else:
                    logger.warning(
                        '%s asked for an object with a getdata which is not in either our memory inventory or our SQL inventory. We probably cleaned it out after advertising it but before they got around to asking for it.'
                        % (self.peer, ))
示例#18
0
 def HandleInboxMessagesByReceiver(self, params):
     if len(params) == 0:
         raise APIError(0, 'I need parameters!')
     toAddress = params[0]
     queryreturn = sqlQuery(
         "SELECT msgid, toaddress, fromaddress, subject, received, message,"
         " encodingtype FROM inbox WHERE folder='inbox' AND toAddress=?",
         toAddress)
     data = '{"inboxMessages":['
     for row in queryreturn:
         msgid, toAddress, fromAddress, subject, received, message, \
             encodingtype = row
         subject = shared.fixPotentiallyInvalidUTF8Data(subject)
         message = shared.fixPotentiallyInvalidUTF8Data(message)
         if len(data) > 25:
             data += ','
         data += json.dumps(
             {
                 'msgid': hexlify(msgid),
                 'toAddress': toAddress,
                 'fromAddress': fromAddress,
                 'subject': base64.b64encode(subject),
                 'message': base64.b64encode(message),
                 'encodingType': encodingtype,
                 'receivedTime': received
             },
             indent=4,
             separators=(',', ': '))
     data += ']}'
     return data
示例#19
0
 def HandleGetSentMessagesByAckData(self, params):
     if len(params) == 0:
         raise APIError(0, 'I need parameters!')
     ackData = self._decode(params[0], "hex")
     queryreturn = sqlQuery(
         "SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
         " message, encodingtype, status, ackdata FROM sent"
         " WHERE ackdata=?", ackData)
     data = '{"sentMessage":['
     for row in queryreturn:
         msgid, toAddress, fromAddress, subject, lastactiontime, message, \
             encodingtype, status, ackdata = row
         subject = shared.fixPotentiallyInvalidUTF8Data(subject)
         message = shared.fixPotentiallyInvalidUTF8Data(message)
         data += json.dumps(
             {
                 'msgid': hexlify(msgid),
                 'toAddress': toAddress,
                 'fromAddress': fromAddress,
                 'subject': base64.b64encode(subject),
                 'message': base64.b64encode(message),
                 'encodingType': encodingtype,
                 'lastActionTime': lastactiontime,
                 'status': status,
                 'ackData': hexlify(ackdata)
             },
             indent=4,
             separators=(',', ': '))
     data += ']}'
     return data
示例#20
0
def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
    if isAddressInMyAddressBook(address):
        return True

    queryreturn = sqlQuery(
        '''SELECT address FROM whitelist where address=?'''
        ''' and enabled = '1' ''', address)
    if queryreturn != []:
        return True

    queryreturn = sqlQuery(
        '''select address from subscriptions where address=?'''
        ''' and enabled = '1' ''', address)
    if queryreturn != []:
        return True
    return False
 def sendBigInv(self):
     # Select all hashes for objects in this stream.
     queryreturn = sqlQuery(
         '''SELECT hash FROM inventory WHERE expirestime>? and streamnumber=?''',
         int(time.time()),
         self.streamNumber)
     bigInvList = {}
     for row in queryreturn:
         hash, = row
         if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
             bigInvList[hash] = 0
     # We also have messages in our inventory in memory (which is a python
     # dictionary). Let's fetch those too.
     with shared.inventoryLock:
         for hash, storedValue in shared.inventory.items():
             if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
                 objectType, streamNumber, payload, expiresTime, tag = storedValue
                 if streamNumber == self.streamNumber and expiresTime > int(time.time()):
                     bigInvList[hash] = 0
     numberOfObjectsInInvMessage = 0
     payload = ''
     # Now let us start appending all of these hashes together. They will be
     # sent out in a big inv message to our new peer.
     for hash, storedValue in bigInvList.items():
         payload += hash
         numberOfObjectsInInvMessage += 1
         if numberOfObjectsInInvMessage == 50000:  # We can only send a max of 50000 items per inv message but we may have more objects to advertise. They must be split up into multiple inv messages.
             self.sendinvMessageToJustThisOnePeer(
                 numberOfObjectsInInvMessage, payload)
             payload = ''
             numberOfObjectsInInvMessage = 0
     if numberOfObjectsInInvMessage > 0:
         self.sendinvMessageToJustThisOnePeer(
             numberOfObjectsInInvMessage, payload)
示例#22
0
 def getLabel(self, address=None):
     """Get a label for this bitmessage account"""
     if address is None:
         address = self.address
     label = BMConfigParser().safeGet(address, 'label', address)
     queryreturn = sqlQuery(
         '''select label from addressbook where address=?''', address)
     if queryreturn != []:
         for row in queryreturn:
             label, = row
     else:
         queryreturn = sqlQuery(
             '''select label from subscriptions where address=?''', address)
         if queryreturn != []:
             for row in queryreturn:
                 label, = row
     return label
示例#23
0
def checkAddressBook(myapp):
    sqlExecute('DELETE from addressbook WHERE address=?', OLD_SUPPORT_ADDRESS)
    queryreturn = sqlQuery('SELECT * FROM addressbook WHERE address=?',
                           SUPPORT_ADDRESS)
    if queryreturn == []:
        sqlExecute('INSERT INTO addressbook VALUES (?,?)',
                   SUPPORT_LABEL.toUtf8(), SUPPORT_ADDRESS)
        myapp.rerenderAddressBook()
示例#24
0
 def __getitem__(self, hash):
     with self.lock:
         if hash in self._inventory:
             return self._inventory[hash]
         rows = sqlQuery('SELECT objecttype, streamnumber, payload, expirestime, tag FROM inventory WHERE hash=?', hash)
         if not rows:
             raise KeyError(hash)
         return self.InventoryItem(*rows[0])
示例#25
0
def search_sql(xAddress="toaddress",
               account=None,
               folder="inbox",
               where=None,
               what=None,
               unreadOnly=False):
    if what is not None and what != "":
        what = "%" + what + "%"
        if where == search_translate("MainWindow", "To"):
            where = "toaddress"
        elif where == search_translate("MainWindow", "From"):
            where = "fromaddress"
        elif where == search_translate("MainWindow", "Subject"):
            where = "subject"
        elif where == search_translate("MainWindow", "Message"):
            where = "message"
        else:
            where = "toaddress || fromaddress || subject || message"
    else:
        what = None

    if folder == "sent":
        sqlStatementBase = '''
            SELECT toaddress, fromaddress, subject, status, ackdata, lastactiontime 
            FROM sent '''
    else:
        sqlStatementBase = '''SELECT folder, msgid, toaddress, fromaddress, subject, received, read
            FROM inbox '''

    sqlStatementParts = []
    sqlArguments = []
    if account is not None:
        if xAddress == 'both':
            sqlStatementParts.append("(fromaddress = ? OR toaddress = ?)")
            sqlArguments.append(account)
            sqlArguments.append(account)
        else:
            sqlStatementParts.append(xAddress + " = ? ")
            sqlArguments.append(account)
    if folder is not None:
        if folder == "new":
            folder = "inbox"
            unreadOnly = True
        sqlStatementParts.append("folder = ? ")
        sqlArguments.append(folder)
    else:
        sqlStatementParts.append("folder != ?")
        sqlArguments.append("trash")
    if what is not None:
        sqlStatementParts.append("%s LIKE ?" % (where))
        sqlArguments.append(what)
    if unreadOnly:
        sqlStatementParts.append("read = 0")
    if len(sqlStatementParts) > 0:
        sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts)
    if folder == "sent":
        sqlStatementBase += " ORDER BY lastactiontime"
    return sqlQuery(sqlStatementBase, sqlArguments)
示例#26
0
 def getLabel(self, address=None):
     if address is None:
         address = self.address
     label = address
     if BMConfigParser().has_section(address):
         label = BMConfigParser().get(address, 'label')
     queryreturn = sqlQuery(
         '''select label from addressbook where address=?''', address)
     if queryreturn != []:
         for row in queryreturn:
             label, = row
     else:
         queryreturn = sqlQuery(
             '''select label from subscriptions where address=?''', address)
         if queryreturn != []:
             for row in queryreturn:
                 label, = row
     return label
示例#27
0
 def _getLabel(self):
     queryreturn = sqlQuery(
         '''select label from subscriptions where address=?''',
         self.address)
     if queryreturn != []:
         for row in queryreturn:
             retval, = row
         return unicode(retval, 'utf-8', 'ignore')
     return unicode(self.address, 'utf-8')
示例#28
0
 def HandleGetInboxMessageById(self, params):
     if len(params) == 0:
         raise APIError(0, 'I need parameters!')
     elif len(params) == 1:
         msgid = self._decode(params[0], "hex")
     elif len(params) >= 2:
         msgid = self._decode(params[0], "hex")
         readStatus = params[1]
         if not isinstance(readStatus, bool):
             raise APIError(
                 23, 'Bool expected in readStatus, saw %s instead.' %
                 type(readStatus))
         queryreturn = sqlQuery("SELECT read FROM inbox WHERE msgid=?",
                                msgid)
         # UPDATE is slow, only update if status is different
         if queryreturn != [] and (queryreturn[0][0] == 1) != readStatus:
             sqlExecute("UPDATE inbox set read = ? WHERE msgid=?",
                        readStatus, msgid)
             queues.UISignalQueue.put(('changedInboxUnread', None))
     queryreturn = sqlQuery(
         "SELECT msgid, toaddress, fromaddress, subject, received, message,"
         " encodingtype, read FROM inbox WHERE msgid=?", msgid)
     data = '{"inboxMessage":['
     for row in queryreturn:
         msgid, toAddress, fromAddress, subject, received, message, \
             encodingtype, read = row
         subject = shared.fixPotentiallyInvalidUTF8Data(subject)
         message = shared.fixPotentiallyInvalidUTF8Data(message)
         data += json.dumps(
             {
                 'msgid': hexlify(msgid),
                 'toAddress': toAddress,
                 'fromAddress': fromAddress,
                 'subject': base64.b64encode(subject),
                 'message': base64.b64encode(message),
                 'encodingType': encodingtype,
                 'receivedTime': received,
                 'read': read
             },
             indent=4,
             separators=(',', ': '))
         data += ']}'
         return data
示例#29
0
def has_pubkey_for(address, decodedAddress):
    # Can return True or False

    # If we need the public key for our own address or a chan,
    # we can compute it from the private key
    if shared.config.has_section(address):
        return True

    # This is not an address where we know the private key.
    # See if we already have the public key in our database:
    _, toAddressVersion, toStreamNumber, toRipe = decodedAddress
    queryReturn = sqlQuery(
        "SELECT hash FROM pubkeys WHERE hash=? AND addressversion=?", toRipe,
        toAddressVersion)
    if queryReturn != []:
        return True

    if toAddressVersion >= 4:  # If we are trying to send to address version >= 4 then the needed pubkey might be encrypted in the inventory.
        # If we have it we'll need to decrypt it and put it in the pubkeys table.
        _, toTag = compute_priv_encryption_key_and_tag(toAddressVersion,
                                                       toStreamNumber, toRipe)
        queryreturn = sqlQuery(
            '''SELECT payload FROM inventory WHERE objecttype='pubkey' and tag=? ''',
            toTag)
        if queryreturn != []:  # if there was a pubkey in our inventory with the correct tag, we need to try to decrypt it.
            for row in queryreturn:
                data, = row
                if shared.decryptAndCheckPubkeyPayload(
                        data, address) == 'successful':
                    return True

        with shared.inventoryLock:
            for hash, storedValue in shared.inventory.items():
                objectType, streamNumber, payload, receivedTime, tag = storedValue
                if objectType == 'pubkey' and tag == toTag:
                    result = shared.decryptAndCheckPubkeyPayload(
                        payload, address
                    )  #if valid, this function also puts it in the pubkeys table.
                    if result == 'successful':
                        return True

    # We don't have the public key in our database.
    return False
示例#30
0
 def __contains__(self, hash_):
     with self.lock:
         if hash_ in self._objects:
             return True
         rows = sqlQuery('SELECT streamnumber FROM inventory WHERE hash=?',
                         sqlite3.Binary(hash_))
         if not rows:
             return False
         self._objects[hash_] = rows[0][0]
         return True
示例#31
0
def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
    """
    Am I subscribed to this address, is it in my addressbook or whitelist?
    """
    if isAddressInMyAddressBook(address):
        return True

    queryreturn = sqlQuery(
        '''SELECT address FROM whitelist where address=?'''
        ''' and enabled = '1' ''', address)
    if queryreturn != []:
        return True

    queryreturn = sqlQuery(
        '''select address from subscriptions where address=?'''
        ''' and enabled = '1' ''', address)
    if queryreturn != []:
        return True
    return False
 def click_pushButtonAddBlacklist(self):
     self.NewBlacklistDialogInstance = AddAddressDialog(self)
     if self.NewBlacklistDialogInstance.exec_():
         if self.NewBlacklistDialogInstance.labelAddressCheck.text() == \
                 _translate("MainWindow", "Address is valid."):
             address = addBMIfNotPresent(
                 str(self.NewBlacklistDialogInstance.lineEditAddress.text())
             )
             # First we must check to see if the address is already in the
             # address book. The user cannot add it again or else it will
             # cause problems when updating and deleting the entry.
             t = (address, )
             if BMConfigParser().get('bitmessagesettings',
                                     'blackwhitelist') == 'black':
                 sql = '''select * from blacklist where address=?'''
             else:
                 sql = '''select * from whitelist where address=?'''
             queryreturn = sqlQuery(sql, *t)
             if queryreturn == []:
                 self.tableWidgetBlacklist.setSortingEnabled(False)
                 self.tableWidgetBlacklist.insertRow(0)
                 newItem = QtGui.QTableWidgetItem(
                     unicode(
                         self.NewBlacklistDialogInstance.lineEditLabel.text(
                         ).toUtf8(), 'utf-8'))
                 newItem.setIcon(avatarize(address))
                 self.tableWidgetBlacklist.setItem(0, 0, newItem)
                 newItem = QtGui.QTableWidgetItem(address)
                 newItem.setFlags(QtCore.Qt.ItemIsSelectable
                                  | QtCore.Qt.ItemIsEnabled)
                 self.tableWidgetBlacklist.setItem(0, 1, newItem)
                 self.tableWidgetBlacklist.setSortingEnabled(True)
                 t = (str(self.NewBlacklistDialogInstance.lineEditLabel.
                          text().toUtf8()), address, True)
                 if BMConfigParser().get('bitmessagesettings',
                                         'blackwhitelist') == 'black':
                     sql = '''INSERT INTO blacklist VALUES (?,?,?)'''
                 else:
                     sql = '''INSERT INTO whitelist VALUES (?,?,?)'''
                 sqlExecute(sql, *t)
             else:
                 UISignalQueue.put(
                     ('updateStatusBar',
                      _translate(
                          "MainWindow",
                          "Error: You cannot add the same address to your"
                          " list twice. Perhaps rename the existing one"
                          " if you want.")))
         else:
             UISignalQueue.put(
                 ('updateStatusBar',
                  _translate(
                      "MainWindow",
                      "The address you entered was invalid. Ignoring it.")))
def has_pubkey_for(address, decodedAddress):
    # Can return True or False
    
    # If we need the public key for our own address or a chan,
    # we can compute it from the private key
    if shared.config.has_section( address ):
        return True
    
    # This is not an address where we know the private key.
    # See if we already have the public key in our database:
    _, toAddressVersion, toStreamNumber, toRipe = decodedAddress
    queryReturn = sqlQuery( "SELECT hash FROM pubkeys WHERE hash=? AND addressversion=?", toRipe, toAddressVersion)
    if queryReturn != []:
        return True
    
    if toAddressVersion >= 4: # If we are trying to send to address version >= 4 then the needed pubkey might be encrypted in the inventory.
        # If we have it we'll need to decrypt it and put it in the pubkeys table.
        _, toTag = compute_priv_encryption_key_and_tag(toAddressVersion, toStreamNumber, toRipe)
        queryreturn = sqlQuery(
            '''SELECT payload FROM inventory WHERE objecttype='pubkey' and tag=? ''', toTag)
        if queryreturn != []: # if there was a pubkey in our inventory with the correct tag, we need to try to decrypt it.
            for row in queryreturn:
                data, = row
                if shared.decryptAndCheckPubkeyPayload(data, address) == 'successful':
                    return True
                
        with shared.inventoryLock:
            for hash, storedValue in shared.inventory.items():
                objectType, streamNumber, payload, receivedTime, tag = storedValue
                if objectType == 'pubkey' and tag == toTag:
                    result = shared.decryptAndCheckPubkeyPayload(payload, address) #if valid, this function also puts it in the pubkeys table.
                    if result == 'successful':
                        return True
                    
     # We don't have the public key in our database.
    return False
def connectToStream(streamNumber):
    shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
    selfInitiatedConnections[streamNumber] = {}
    shared.inventorySets[streamNumber] = set()
    queryData = sqlQuery('''SELECT hash FROM inventory WHERE streamnumber=?''', streamNumber)
    for row in queryData:
        shared.inventorySets[streamNumber].add(row[0])

    if sys.platform[0:3] == 'win':
        maximumNumberOfHalfOpenConnections = 9
    else:
        maximumNumberOfHalfOpenConnections = 32
    for i in range(maximumNumberOfHalfOpenConnections):
        a = outgoingSynSender()
        a.setup(streamNumber, selfInitiatedConnections)
        a.start()
示例#35
0
def connectToStream(streamNumber):
    shared.streamsInWhichIAmParticipating[streamNumber] = "no data"
    selfInitiatedConnections[streamNumber] = {}
    shared.inventorySets[streamNumber] = set()
    queryData = sqlQuery("""SELECT hash FROM inventory WHERE streamnumber=?""", streamNumber)
    for row in queryData:
        shared.inventorySets[streamNumber].add(row[0])

    if isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
        # Some XP and Vista systems can only have 10 outgoing connections at a time.
        maximumNumberOfHalfOpenConnections = 9
    else:
        maximumNumberOfHalfOpenConnections = 64
    for i in range(maximumNumberOfHalfOpenConnections):
        a = outgoingSynSender()
        a.setup(streamNumber, selfInitiatedConnections)
        a.start()
示例#36
0
def connect_to_stream(stream_number):
    shared.streamsInWhichIAmParticipating[stream_number] = 'no data'
    self_initiated_connections[stream_number] = {}
    shared.inventorySets[stream_number] = set()
    query_data = sqlQuery('''SELECT hash FROM inventory WHERE streamnumber=?''', stream_number)
    for row in query_data:
        shared.inventorySets[stream_number].add(row[0])

    if isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
        # Some XP and Vista systems can only have 10 outgoing connections at a time.
        maximum_number_of_half_open_connections = 9
    else:
        maximum_number_of_half_open_connections = 64
    for i in range(maximum_number_of_half_open_connections):
        a = outgoingSynSender()
        a.setup(stream_number, self_initiated_connections)
        a.start()
示例#37
0
 def click_pushButtonAddBlacklist(self):
     self.NewBlacklistDialogInstance = AddAddressDialog(self)
     if self.NewBlacklistDialogInstance.exec_():
         if self.NewBlacklistDialogInstance.ui.labelAddressCheck.text() == _translate("MainWindow", "Address is valid."):
             address = addBMIfNotPresent(str(
                 self.NewBlacklistDialogInstance.ui.lineEditAddress.text()))
             # First we must check to see if the address is already in the
             # address book. The user cannot add it again or else it will
             # cause problems when updating and deleting the entry.
             t = (address,)
             if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black':
                 sql = '''select * from blacklist where address=?'''
             else:
                 sql = '''select * from whitelist where address=?'''
             queryreturn = sqlQuery(sql,*t)
             if queryreturn == []:
                 self.tableWidgetBlacklist.setSortingEnabled(False)
                 self.tableWidgetBlacklist.insertRow(0)
                 newItem = QtGui.QTableWidgetItem(unicode(
                     self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8(), 'utf-8'))
                 newItem.setIcon(avatarize(address))
                 self.tableWidgetBlacklist.setItem(0, 0, newItem)
                 newItem = QtGui.QTableWidgetItem(address)
                 newItem.setFlags(
                     QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
                 self.tableWidgetBlacklist.setItem(0, 1, newItem)
                 self.tableWidgetBlacklist.setSortingEnabled(True)
                 t = (str(self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8()), address, True)
                 if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black':
                     sql = '''INSERT INTO blacklist VALUES (?,?,?)'''
                 else:
                     sql = '''INSERT INTO whitelist VALUES (?,?,?)'''
                 sqlExecute(sql, *t)
             else:
                 self.statusBar().showMessage(_translate(
                     "MainWindow", "Error: You cannot add the same address to your list twice. Perhaps rename the existing one if you want."))
         else:
             self.statusBar().showMessage(_translate(
                 "MainWindow", "The address you entered was invalid. Ignoring it."))
def get_pubkey_for(address, decodedAddress=None):
    """
    Retrieve public key for an address.
    Provide the decodedAddress if you already have it. No need to decode it more than once.
    Returns None if pubkey not found, otherwise the following tuple:
    ( pubEncryptionKey, pubSigningKey, requiredAvgPOWNonceTrialsPerByte,
      requiredPayloadLengthExtraBytes, behaviourBitfield )
      
    The keys returned are in binary format.
    """
    # Can return None, "mobile-user-disallowed", or
    #    ( pubEncryptionKeyBase256, pubsigningKeyBase256,
    #      requiredAverageProofOfWorkNonceTrialsPerByte,
    #      requiredPayloadLengthExtraBytes,
    #      behaviourBitfield )
    
    if decodedAddress is None:
        decodedAddress = shared.decodeAddress( address )
        
    requiredAverageProofOfWorkNonceTrialsPerByte = shared.networkDefaultProofOfWorkNonceTrialsPerByte
    requiredPayloadLengthExtraBytes = shared.networkDefaultPayloadLengthExtraBytes
    
    # If we need the public key for our own address or a chan,
    # we can compute it from the private key
    if shared.config.has_section( address ):
        try:
            privSigningKeyBase58 = shared.config.get(
                address, 'privsigningkey')
            privEncryptionKeyBase58 = shared.config.get(
                address, 'privencryptionkey')
        except:
            debug.logger.error( tr.translateText("MainWindow", "Error! Could not find sender address (your address) in the keys.dat file." ) )
            return None

        privSigningKeyHex = shared.decodeWalletImportFormat(
            privSigningKeyBase58).encode('hex')
        privEncryptionKeyHex = shared.decodeWalletImportFormat(
            privEncryptionKeyBase58).encode('hex')

        pubSigningKey = highlevelcrypto.privToPub(
            privSigningKeyHex).decode('hex')[1:]
        pubEncryptionKey = highlevelcrypto.privToPub(
            privEncryptionKeyHex).decode('hex')[1:]
            
        return ( pubEncryptionKey, pubSigningKey, 
                 requiredAverageProofOfWorkNonceTrialsPerByte,
                 requiredPayloadLengthExtraBytes,
                 "\x00\x00\x00\x01" )
    
    # This is not an address where we know the private key.
    # See if we already have the public key in our database:
    _, addressVersion, streamNumber, ripe = decodedAddress
    queryReturn = sqlQuery( "SELECT transmitdata FROM pubkeys WHERE hash=? AND addressversion=?", ripe, addressVersion)
    if queryReturn != []:
        pubkeyPayload = queryReturn[0][0]
        return decode_pubkey_payload( pubkeyPayload, addressVersion )

        # The pubkey message is stored the way we originally received it
        # which means that we need to read beyond things like the nonce and
        # time to get to the actual public keys.
    
                    
    # We don't have the public key in our database.
    return None
示例#39
0
def getStatusByAck(ackdata):
    query = sqlQuery("SELECT status FROM sent WHERE ackdata=? LIMIT 0,1", ackdata)
    if not len(query) == 0:
        return query[0][0]
    else:
        return "not found"
示例#40
0
    def _handle_request(self, method, params):
        if method == 'helloWorld':
            (a, b) = params
            return a + '-' + b
        elif method == 'add':
            (a, b) = params
            return a + b
        elif method == 'statusBar':
            message, = params
            shared.UISignalQueue.put(('updateStatusBar', message))
        elif method == 'listAddresses' or method == 'listAddresses2':
            data = '{"addresses":['
            configSections = shared.config.sections()
            for addressInKeysFile in configSections:
                if addressInKeysFile != 'bitmessagesettings':
                    status, addressVersionNumber, streamNumber, hash01 = decodeAddress(
                        addressInKeysFile)
                    if len(data) > 20:
                        data += ','
                    if shared.config.has_option(addressInKeysFile, 'chan'):
                        chan = shared.config.getboolean(addressInKeysFile, 'chan')
                    else:
                        chan = False
                    label = shared.config.get(addressInKeysFile, 'label')
                    if method == 'listAddresses2':
                        label = label.encode('base64')
                    data += json.dumps({'label': label, 'address': addressInKeysFile, 'stream':
                                        streamNumber, 'enabled': shared.config.getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'listAddressBookEntries' or method == 'listAddressbook': # the listAddressbook alias should be removed eventually.
            queryreturn = sqlQuery('''SELECT label, address from addressbook''')
            data = '{"addresses":['
            for row in queryreturn:
                label, address = row
                label = shared.fixPotentiallyInvalidUTF8Data(label)
                if len(data) > 20:
                    data += ','
                data += json.dumps({'label':label.encode('base64'), 'address': address}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'addAddressBookEntry' or method == 'addAddressbook': # the addAddressbook alias should be deleted eventually.
            if len(params) != 2:
                raise APIError(0, "I need label and address")
            address, label = params
            label = self._decode(label, "base64")
            address = addBMIfNotPresent(address)
            self._verifyAddress(address)
            queryreturn = sqlQuery("SELECT address FROM addressbook WHERE address=?", address)
            if queryreturn != []:
                raise APIError(16, 'You already have this address in your address book.')

            sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address)
            shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
            shared.UISignalQueue.put(('rerenderSentToLabels',''))
            shared.UISignalQueue.put(('rerenderAddressBook',''))
            return "Added address %s to address book" % address
        elif method == 'deleteAddressBookEntry' or method == 'deleteAddressbook': # The deleteAddressbook alias should be deleted eventually.
            if len(params) != 1:
                raise APIError(0, "I need an address")
            address, = params
            address = addBMIfNotPresent(address)
            self._verifyAddress(address)
            sqlExecute('DELETE FROM addressbook WHERE address=?', address)
            shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
            shared.UISignalQueue.put(('rerenderSentToLabels',''))
            shared.UISignalQueue.put(('rerenderAddressBook',''))
            return "Deleted address book entry for %s if it existed" % address
        elif method == 'createRandomAddress':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            elif len(params) == 1:
                label, = params
                eighteenByteRipe = False
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 2:
                label, eighteenByteRipe = params
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 3:
                label, eighteenByteRipe, totalDifficulty = params
                nonceTrialsPerByte = int(
                    shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 4:
                label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
                nonceTrialsPerByte = int(
                    shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
                payloadLengthExtraBytes = int(
                    shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
            else:
                raise APIError(0, 'Too many parameters!')
            label = self._decode(label, "base64")
            try:
                unicode(label, 'utf-8')
            except:
                raise APIError(17, 'Label is not valid UTF-8 data.')
            shared.apiAddressGeneratorReturnQueue.queue.clear()
            streamNumberForAddress = 1
            shared.addressGeneratorQueue.put((
                'createRandomAddress', 4, streamNumberForAddress, label, 1, "", eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
            return shared.apiAddressGeneratorReturnQueue.get()
        elif method == 'createDeterministicAddresses':
            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 = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 2:
                passphrase, numberOfAddresses = params
                addressVersionNumber = 0
                streamNumber = 0
                eighteenByteRipe = False
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 3:
                passphrase, numberOfAddresses, addressVersionNumber = params
                streamNumber = 0
                eighteenByteRipe = False
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 4:
                passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params
                eighteenByteRipe = False
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 5:
                passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params
                nonceTrialsPerByte = shared.config.get(
                    'bitmessagesettings', 'defaultnoncetrialsperbyte')
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 6:
                passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params
                nonceTrialsPerByte = int(
                    shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
                payloadLengthExtraBytes = shared.config.get(
                    'bitmessagesettings', 'defaultpayloadlengthextrabytes')
            elif len(params) == 7:
                passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
                nonceTrialsPerByte = int(
                    shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
                payloadLengthExtraBytes = int(
                    shared.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")
            if addressVersionNumber == 0:  # 0 means "just use the proper addressVersionNumber"
                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). ' + addressVersionNumber + ' isn\'t supported.')
            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.')
            shared.apiAddressGeneratorReturnQueue.queue.clear()
            logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
            shared.addressGeneratorQueue.put(
                ('createDeterministicAddresses', addressVersionNumber, streamNumber,
                 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
            data = '{"addresses":['
            queueReturn = shared.apiAddressGeneratorReturnQueue.get()
            for item in queueReturn:
                if len(data) > 20:
                    data += ','
                data += "\"" + item + "\""
            data += ']}'
            return data
        elif method == 'getDeterministicAddress':
            if len(params) != 3:
                raise APIError(0, 'I need exactly 3 parameters.')
            passphrase, addressVersionNumber, streamNumber = params
            numberOfAddresses = 1
            eighteenByteRipe = False
            if len(passphrase) == 0:
                raise APIError(1, 'The specified passphrase is blank.')
            passphrase = self._decode(passphrase, "base64")
            if addressVersionNumber != 3 and addressVersionNumber != 4:
                raise APIError(2, 'The address version number currently must be 3 or 4. ' + addressVersionNumber + ' isn\'t supported.')
            if streamNumber != 1:
                raise APIError(3, ' The stream number must be 1. Others aren\'t supported.')
            shared.apiAddressGeneratorReturnQueue.queue.clear()
            logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
            shared.addressGeneratorQueue.put(
                ('getDeterministicAddress', addressVersionNumber,
                 streamNumber, 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe))
            return shared.apiAddressGeneratorReturnQueue.get()

        elif method == 'createChan':
            if len(params) == 0:
                raise APIError(0, 'I need parameters.')
            elif len(params) == 1:
                passphrase, = params
            passphrase = self._decode(passphrase, "base64")
            if len(passphrase) == 0:
                raise APIError(1, 'The specified passphrase is blank.')
            # It would be nice to make the label the passphrase but it is
            # possible that the passphrase contains non-utf-8 characters.
            try:
                unicode(passphrase, 'utf-8')
                label = str_chan + ' ' + passphrase
            except:
                label = str_chan + ' ' + repr(passphrase)

            addressVersionNumber = 4
            streamNumber = 1
            shared.apiAddressGeneratorReturnQueue.queue.clear()
            logger.debug('Requesting that the addressGenerator create chan %s.', passphrase)
            shared.addressGeneratorQueue.put(('createChan', addressVersionNumber, streamNumber, label, passphrase))
            queueReturn = shared.apiAddressGeneratorReturnQueue.get()
            if len(queueReturn) == 0:
                raise APIError(24, 'Chan address is already present.')
            address = queueReturn[0]
            return address
        elif method == 'joinChan':
            if len(params) < 2:
                raise APIError(0, 'I need two parameters.')
            elif len(params) == 2:
                passphrase, suppliedAddress= params
            passphrase = self._decode(passphrase, "base64")
            if len(passphrase) == 0:
                raise APIError(1, 'The specified passphrase is blank.')
            # It would be nice to make the label the passphrase but it is
            # possible that the passphrase contains non-utf-8 characters.
            try:
                unicode(passphrase, 'utf-8')
                label = str_chan + ' ' + passphrase
            except:
                label = str_chan + ' ' + repr(passphrase)

            status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(suppliedAddress)
            suppliedAddress = addBMIfNotPresent(suppliedAddress)
            shared.apiAddressGeneratorReturnQueue.queue.clear()
            shared.addressGeneratorQueue.put(('joinChan', suppliedAddress, label, passphrase))
            addressGeneratorReturnValue = shared.apiAddressGeneratorReturnQueue.get()

            if addressGeneratorReturnValue == 'chan name does not match address':
                raise APIError(18, 'Chan name does not match address.')
            if len(addressGeneratorReturnValue) == 0:
                raise APIError(24, 'Chan address is already present.')
            #TODO: this variable is not used to anything
            createdAddress = addressGeneratorReturnValue[0] # in case we ever want it for anything.
            return "success"
        elif method == 'leaveChan':
            if len(params) == 0:
                raise APIError(0, 'I need parameters.')
            elif len(params) == 1:
                address, = params
            status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
            address = addBMIfNotPresent(address)
            if not shared.config.has_section(address):
                raise APIError(13, 'Could not find this address in your keys.dat file.')
            if not shared.safeConfigGetBoolean(address, 'chan'):
                raise APIError(25, 'Specified address is not a chan address. Use deleteAddress API call instead.')
            shared.config.remove_section(address)
            with open(shared.appdata + 'keys.dat', 'wb') as configfile:
                shared.config.write(configfile)
            return 'success'

        elif method == 'deleteAddress':
            if len(params) == 0:
                raise APIError(0, 'I need parameters.')
            elif len(params) == 1:
                address, = params
            status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
            address = addBMIfNotPresent(address)
            if not shared.config.has_section(address):
                raise APIError(13, 'Could not find this address in your keys.dat file.')
            shared.config.remove_section(address)
            with open(shared.appdata + 'keys.dat', 'wb') as configfile:
                shared.config.write(configfile)
            shared.UISignalQueue.put(('rerenderInboxFromLabels',''))
            shared.UISignalQueue.put(('rerenderSentToLabels',''))
            shared.reloadMyAddressHashes()
            return 'success'

        elif method == 'getAllInboxMessages':
            queryreturn = sqlQuery(
                '''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox where folder='inbox' ORDER BY received''')
            data = '{"inboxMessages":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, received, message, encodingtype, read = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid': msgid.encode('hex'), 'toAddress': toAddress, 'fromAddress': fromAddress, 'subject': subject.encode(
                    'base64'), 'message': message.encode('base64'), 'encodingType': encodingtype, 'receivedTime': received, 'read': read}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getAllInboxMessageIds' or method == 'getAllInboxMessageIDs':
            queryreturn = sqlQuery(
                '''SELECT msgid FROM inbox where folder='inbox' ORDER BY received''')
            data = '{"inboxMessageIds":['
            for row in queryreturn:
                msgid = row[0]
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid': msgid.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getInboxMessageById' or method == 'getInboxMessageByID':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            elif len(params) == 1:
                msgid = self._decode(params[0], "hex")
            elif len(params) >= 2:
                msgid = self._decode(params[0], "hex")
                readStatus = params[1]
                if not isinstance(readStatus, bool):
                    raise APIError(23, 'Bool expected in readStatus, saw %s instead.' % type(readStatus))
                queryreturn = sqlQuery('''SELECT read FROM inbox WHERE msgid=?''', msgid)
                # UPDATE is slow, only update if status is different
                if queryreturn != [] and (queryreturn[0][0] == 1) != readStatus:
                    sqlExecute('''UPDATE inbox set read = ? WHERE msgid=?''', readStatus, msgid)
                    shared.UISignalQueue.put(('changedInboxUnread', None))
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox WHERE msgid=?''', msgid)
            data = '{"inboxMessage":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, received, message, encodingtype, read = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received, 'read': read}, indent=4, separators=(',', ': '))
                data += ']}'
                return data
        elif method == 'getAllSentMessages':
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent where folder='sent' ORDER BY lastactiontime''')
            data = '{"sentMessages":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getAllSentMessageIds' or method == 'getAllSentMessageIDs':
            queryreturn = sqlQuery('''SELECT msgid FROM sent where folder='sent' ORDER BY lastactiontime''')
            data = '{"sentMessageIds":['
            for row in queryreturn:
                msgid = row[0]
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid':msgid.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getInboxMessagesByReceiver' or method == 'getInboxMessagesByAddress': #after some time getInboxMessagesByAddress should be removed
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            toAddress = params[0]
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype FROM inbox WHERE folder='inbox' AND toAddress=?''', toAddress)
            data = '{"inboxMessages":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, received, message, encodingtype = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'receivedTime':received}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getSentMessageById' or method == 'getSentMessageByID':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            msgid = self._decode(params[0], "hex")
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE msgid=?''', msgid)
            data = '{"sentMessage":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': '))
                data += ']}'
                return data
        elif method == 'getSentMessagesByAddress' or method == 'getSentMessagesBySender':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            fromAddress = params[0]
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE folder='sent' AND fromAddress=? ORDER BY lastactiontime''',
                                   fromAddress)
            data = '{"sentMessages":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                if len(data) > 25:
                    data += ','
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getSentMessageByAckData':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            ackData = self._decode(params[0], "hex")
            queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE ackdata=?''',
                                   ackData)
            data = '{"sentMessage":['
            for row in queryreturn:
                msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
                subject = shared.fixPotentiallyInvalidUTF8Data(subject)
                message = shared.fixPotentiallyInvalidUTF8Data(message)
                data += json.dumps({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'trashMessage':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            msgid = self._decode(params[0], "hex")

            # Trash if in inbox table
            helper_inbox.trash(msgid)
            # Trash if in sent table
            sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid)
            return 'Trashed message (assuming message existed).'
        elif method == 'trashInboxMessage':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            msgid = self._decode(params[0], "hex")
            helper_inbox.trash(msgid)
            return 'Trashed inbox message (assuming message existed).'
        elif method == 'trashSentMessage':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            msgid = self._decode(params[0], "hex")
            sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid)
            return 'Trashed sent message (assuming message existed).'
        elif method == 'trashSentMessageByAckData':
            # This API method should only be used when msgid is not available
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            ackdata = self._decode(params[0], "hex")
            sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''',
                       ackdata)
            return 'Trashed sent message (assuming message existed).'
        elif method == 'sendMessage':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            elif len(params) == 4:
                toAddress, fromAddress, subject, message = params
                encodingType = 2
            elif len(params) == 5:
                toAddress, fromAddress, subject, message, encodingType = params
            if encodingType != 2:
                raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
            subject = self._decode(subject, "base64")
            message = self._decode(message, "base64")
            toAddress = addBMIfNotPresent(toAddress)
            fromAddress = addBMIfNotPresent(fromAddress)
            status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
            self._verifyAddress(fromAddress)
            try:
                fromAddressEnabled = shared.config.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.')

            ackdata = OpenSSL.rand(32)

            t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int(
                time.time()), 'msgqueued', 1, 1, 'sent', 2)
            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)))
            shared.UISignalQueue.put(('displayNewSentMessage', (
                toAddress, toLabel, fromAddress, subject, message, ackdata)))

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

            return ackdata.encode('hex')

        elif method == 'sendBroadcast':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            if len(params) == 3:
                fromAddress, subject, message = params
                encodingType = 2
            elif len(params) == 4:
                fromAddress, subject, message, encodingType = params
            if encodingType != 2:
                raise APIError(6, 'The encoding type must be 2 because that is the only one this program currently supports.')
            subject = self._decode(subject, "base64")
            message = self._decode(message, "base64")

            fromAddress = addBMIfNotPresent(fromAddress)
            self._verifyAddress(fromAddress)
            try:
                fromAddressEnabled = shared.config.getboolean(
                    fromAddress, 'enabled')
            except:
                raise APIError(13, 'could not find your fromAddress in the keys.dat file.')
            ackdata = OpenSSL.rand(32)
            toAddress = '[Broadcast subscribers]'
            ripe = ''


            t = ('', toAddress, ripe, fromAddress, subject, message, ackdata, int(
                time.time()), 'broadcastqueued', 1, 1, 'sent', 2)
            helper_sent.insert(t)

            toLabel = '[Broadcast subscribers]'
            shared.UISignalQueue.put(('displayNewSentMessage', (
                toAddress, toLabel, fromAddress, subject, message, ackdata)))
            shared.workerQueue.put(('sendbroadcast', ''))

            return ackdata.encode('hex')
        elif method == 'getStatus':
            if len(params) != 1:
                raise APIError(0, 'I need one parameter!')
            ackdata, = params
            if len(ackdata) != 64:
                raise APIError(15, 'The length of ackData should be 32 bytes (encoded in hex thus 64 characters).')
            ackdata = self._decode(ackdata, "hex")
            queryreturn = sqlQuery(
                '''SELECT status FROM sent where ackdata=?''',
                ackdata)
            if queryreturn == []:
                return 'notfound'
            for row in queryreturn:
                status, = row
                return status
        elif method == 'addSubscription':
            if len(params) == 0:
                raise APIError(0, 'I need parameters!')
            if len(params) == 1:
                address, = params
                label = ''
            if len(params) == 2:
                address, label = params
                label = self._decode(label, "base64")
                try:
                    unicode(label, 'utf-8')
                except:
                    raise APIError(17, 'Label is not valid UTF-8 data.')
            if len(params) > 2:
                raise APIError(0, 'I need either 1 or 2 parameters!')
            address = addBMIfNotPresent(address)
            self._verifyAddress(address)
            # First we must check to see if the address is already in the
            # subscriptions list.
            queryreturn = sqlQuery('''select * from subscriptions where address=?''', address)
            if queryreturn != []:
                raise APIError(16, 'You are already subscribed to that address.')
            sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',label, address, True)
            shared.reloadBroadcastSendersForWhichImWatching()
            shared.UISignalQueue.put(('rerenderInboxFromLabels', ''))
            shared.UISignalQueue.put(('rerenderSubscriptions', ''))
            return 'Added subscription.'

        elif method == 'deleteSubscription':
            if len(params) != 1:
                raise APIError(0, 'I need 1 parameter!')
            address, = params
            address = addBMIfNotPresent(address)
            sqlExecute('''DELETE FROM subscriptions WHERE address=?''', address)
            shared.reloadBroadcastSendersForWhichImWatching()
            shared.UISignalQueue.put(('rerenderInboxFromLabels', ''))
            shared.UISignalQueue.put(('rerenderSubscriptions', ''))
            return 'Deleted subscription if it existed.'
        elif method == 'listSubscriptions':
            queryreturn = sqlQuery('''SELECT label, address, enabled FROM subscriptions''')
            data = '{"subscriptions":['
            for row in queryreturn:
                label, address, enabled = row
                label = shared.fixPotentiallyInvalidUTF8Data(label)
                if len(data) > 20:
                    data += ','
                data += json.dumps({'label':label.encode('base64'), 'address': address, 'enabled': enabled == 1}, indent=4, separators=(',',': '))
            data += ']}'
            return data
        elif method == 'disseminatePreEncryptedMsg':
            # The device issuing this command to PyBitmessage supplies a msg object that has
            # already been encrypted but which still needs the POW to be done. PyBitmessage
            # accepts this msg object and sends it out to the rest of the Bitmessage network
            # as if it had generated the message itself. Please do not yet add this to the
            # api doc.
            if len(params) != 3:
                raise APIError(0, 'I need 3 parameter!')
            encryptedPayload, requiredAverageProofOfWorkNonceTrialsPerByte, requiredPayloadLengthExtraBytes = params
            encryptedPayload = self._decode(encryptedPayload, "hex")
            # Let us do the POW and attach it to the front
            target = 2**64 / ((len(encryptedPayload)+requiredPayloadLengthExtraBytes+8) * requiredAverageProofOfWorkNonceTrialsPerByte)
            with shared.printLock:
                print '(For msg message via API) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes
            powStartTime = time.time()
            initialHash = hashlib.sha512(encryptedPayload).digest()
            trialValue, nonce = proofofwork.run(target, initialHash)
            with shared.printLock:
                print '(For msg message via API) Found proof of work', trialValue, 'Nonce:', nonce
                try:
                    print 'POW took', int(time.time() - powStartTime), 'seconds.', nonce / (time.time() - powStartTime), 'nonce trials per second.'
                except:
                    pass
            encryptedPayload = pack('>Q', nonce) + encryptedPayload
            toStreamNumber = decodeVarint(encryptedPayload[16:26])[0]
            inventoryHash = calculateInventoryHash(encryptedPayload)
            objectType = 'msg'
            shared.inventory[inventoryHash] = (
                objectType, toStreamNumber, encryptedPayload, int(time.time()),'')
            shared.inventorySets[toStreamNumber].add(inventoryHash)
            with shared.printLock:
                print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', inventoryHash.encode('hex')
            shared.broadcastToSendDataQueues((
                toStreamNumber, 'advertiseobject', inventoryHash))
        elif method == 'disseminatePubkey':
            # The device issuing this command to PyBitmessage supplies a pubkey object to be
            # disseminated to the rest of the Bitmessage network. PyBitmessage accepts this
            # pubkey object and sends it out to the rest of the Bitmessage network as if it
            # had generated the pubkey object itself. Please do not yet add this to the api
            # doc.
            if len(params) != 1:
                raise APIError(0, 'I need 1 parameter!')
            payload, = params
            payload = self._decode(payload, "hex")

            # Let us do the POW
            target = 2 ** 64 / ((len(payload) + shared.networkDefaultPayloadLengthExtraBytes +
                                 8) * shared.networkDefaultProofOfWorkNonceTrialsPerByte)
            print '(For pubkey message via API) Doing proof of work...'
            initialHash = hashlib.sha512(payload).digest()
            trialValue, nonce = proofofwork.run(target, initialHash)
            print '(For pubkey message via API) Found proof of work', trialValue, 'Nonce:', nonce
            payload = pack('>Q', nonce) + payload

            pubkeyReadPosition = 8 # bypass the nonce
            if payload[pubkeyReadPosition:pubkeyReadPosition+4] == '\x00\x00\x00\x00': # if this pubkey uses 8 byte time
                pubkeyReadPosition += 8
            else:
                pubkeyReadPosition += 4
            addressVersion, addressVersionLength = decodeVarint(payload[pubkeyReadPosition:pubkeyReadPosition+10])
            pubkeyReadPosition += addressVersionLength
            pubkeyStreamNumber = decodeVarint(payload[pubkeyReadPosition:pubkeyReadPosition+10])[0]
            inventoryHash = calculateInventoryHash(payload)
            objectType = 'pubkey'
                        #todo: support v4 pubkeys
            shared.inventory[inventoryHash] = (
                objectType, pubkeyStreamNumber, payload, int(time.time()),'')
            shared.inventorySets[pubkeyStreamNumber].add(inventoryHash)
            with shared.printLock:
                print 'broadcasting inv within API command disseminatePubkey with hash:', inventoryHash.encode('hex')
            shared.broadcastToSendDataQueues((
                streamNumber, 'advertiseobject', inventoryHash))
        elif method == 'getMessageDataByDestinationHash' or method == 'getMessageDataByDestinationTag':
            # Method will eventually be used by a particular Android app to
            # select relevant messages. Do not yet add this to the api
            # doc.

            if len(params) != 1:
                raise APIError(0, 'I need 1 parameter!')
            requestedHash, = params
            if len(requestedHash) != 32:
                raise APIError(19, 'The length of hash should be 32 bytes (encoded in hex thus 64 characters).')
            requestedHash = self._decode(requestedHash, "hex")

            # This is not a particularly commonly used API function. Before we
            # use it we'll need to fill out a field in our inventory database
            # which is blank by default (first20bytesofencryptedmessage).
            queryreturn = sqlQuery(
                '''SELECT hash, payload FROM inventory WHERE tag = '' and objecttype = 'msg' ; ''')
            with SqlBulkExecute() as sql:
                for row in queryreturn:
                    hash01, payload = row
                    readPosition = 16 # Nonce length + time length
                    readPosition += decodeVarint(payload[readPosition:readPosition+10])[1] # Stream Number length
                    t = (payload[readPosition:readPosition+32],hash01)
                    sql.execute('''UPDATE inventory SET tag=? WHERE hash=?; ''', *t)

            queryreturn = sqlQuery('''SELECT payload FROM inventory WHERE tag = ?''',
                                   requestedHash)
            data = '{"receivedMessageDatas":['
            for row in queryreturn:
                payload, = row
                if len(data) > 25:
                    data += ','
                data += json.dumps({'data':payload.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'getPubkeyByHash':
            # Method will eventually be used by a particular Android app to
            # retrieve pubkeys. Please do not yet add this to the api docs.
            if len(params) != 1:
                raise APIError(0, 'I need 1 parameter!')
            requestedHash, = params
            if len(requestedHash) != 40:
                raise APIError(19, 'The length of hash should be 20 bytes (encoded in hex thus 40 characters).')
            requestedHash = self._decode(requestedHash, "hex")
            queryreturn = sqlQuery('''SELECT transmitdata FROM pubkeys WHERE hash = ? ; ''', requestedHash)
            data = '{"pubkey":['
            for row in queryreturn:
                transmitdata, = row
                data += json.dumps({'data':transmitdata.encode('hex')}, indent=4, separators=(',', ': '))
            data += ']}'
            return data
        elif method == 'clientStatus':
            if len(shared.connectedHostsList) == 0:
                networkStatus = 'notConnected'
            elif len(shared.connectedHostsList) > 0 and not shared.clientHasReceivedIncomingConnections:
                networkStatus = 'connectedButHaveNotReceivedIncomingConnections'
            else:
                networkStatus = 'connectedAndReceivingIncomingConnections'
            return json.dumps({'networkConnections':len(shared.connectedHostsList),'numberOfMessagesProcessed':shared.numberOfMessagesProcessed, 'numberOfBroadcastsProcessed':shared.numberOfBroadcastsProcessed, 'numberOfPubkeysProcessed':shared.numberOfPubkeysProcessed, 'networkStatus':networkStatus, 'softwareName':'PyBitmessage','softwareVersion':shared.softwareVersion}, indent=4, separators=(',', ': '))
        elif method == 'decodeAddress':
            # Return a meaningful decoding of an address.
            if len(params) != 1:
                raise APIError(0, 'I need 1 parameter!')
            address, = params
            status, addressVersion, streamNumber, ripe = decodeAddress(address)
            return json.dumps({'status':status, 'addressVersion':addressVersion,
                               'streamNumber':streamNumber, 'ripe':ripe.encode('base64')}, indent=4,
                              separators=(',', ': '))
        else:
            raise APIError(20, 'Invalid method: %s' % method)
示例#41
0
    def _handle_request(self, method, params):
        
        if method == 'add':
            (a, b) = params
            return a + b

    #   Commands for disseminating msgs, getpubkeys, and pubkeys

        elif method == 'disseminateMsg': 
            self.checkParameters(params, 1)
            payload, = params 
            payloadBytes = payload.decode('hex') 
            if (shared.checkAndShareObjectWithPeers(payloadBytes) > 0):
                return 'Message disseminated successfully'
            else:
                return 'Message dissemination failed'

        elif method == 'disseminatePubkey': 
            self.checkParameters(params, 1)
            payload, = params 
            payloadBytes = payload.decode('hex') 
            if (shared.checkAndShareObjectWithPeers(payloadBytes) > 0):
                return 'Pubkey disseminated successfully'
            else:
                return 'Pubkey dissemination failed'

        elif method == 'disseminateGetpubkey': 
            self.checkParameters(params, 1)
            payload, = params 
            payloadBytes = payload.decode('hex') 
            if (shared.checkAndShareObjectWithPeers(payloadBytes) > 0):
                return 'Getpubkey disseminated successfully'
            else:
                return 'Getpubkey dissemination failed'


        #   Commands for requesting msgs and pubkeys

        elif method == 'requestPubkey':
            
            ''' Check the supplied parameters ''' 
            if len(params) != 2: 
                raise APIError(0, 'I need 2 parameters!') 
            identifierHex, addressVersion = params
            
            ''' Check that the address version and requested tag are valid '''
            if addressVersion < 1:
                raise APIError(2, 'The address version cannot be less than 1')
            elif addressVersion > 4:
                raise APIError(3, 'Address versions above 4 are currently not supported')
            elif addressVersion < 4: # For pubkeys of address versions 1-3
                if len(identifierHex) != 40: 
                    raise APIError(4, 'The length of identifier (the ripe hash of the pubkey) should be 20 bytes (encoded in hex and thus 40 characters).')
            else:  # For pubkeys of address version 4  
                if len(identifierHex) != 64: 
                    raise APIError(5, 'The length of identifier (the tag of the pubkey) should be 32 bytes (encoded in hex and thus 64 characters).') 
                
            ''' Now attempt to retrieve the pubkey using the given identifier '''
            requestedTag = self._decode(identifierHex, "hex")
            queryReturn = sqlQuery('''SELECT payload FROM inventory WHERE objecttype=1 and tag=? ''', requestedTag) 
            if queryReturn != []:
                payload = queryReturn[0]
                if len(payload) <= self.MAX_PAYLOAD_SIZE_TO_RETURN:
                    return self.outputQueryReturn("pubkeyPayload", queryReturn)
                else:
                    raise APIError(6, 'The requested object was found, but its payload is above the maximum size limit. The size of the object payload is ' + str(len(payload)))                   
            else:
                # We had no success looking in the sql inventory. Let's look through the memory inventory.
                with shared.inventoryLock:
                    for hash, storedValue in shared.inventory.items():
                        objectType, streamNumber, payload, expiresTime, tag, receivedTime = storedValue
                        if objectType == self.OBJECT_TYPE_PUBKEY and tag == requestedTag:
                            if len(payload) <= self.MAX_PAYLOAD_SIZE_TO_RETURN:
                                return self.outputPayload("pubkeyPayload", payload)
                            else:
                                raise APIError(6, 'The requested object was found, but its payload is above the maximum size limit. The size of the object payload is ' + str(len(payload)))
                        else:
                            return 'No pubkeys found'
                                
        elif method == 'checkForNewMsgs':
            self.checkParameters(params, 3)
            streamNumber, receivedSinceTime, receivedBeforeTime = params
            queryReturn = sqlQuery('''SELECT payload FROM inventory WHERE objecttype=2 and streamnumber=? and receivedTime>? and receivedTime<? ''', streamNumber, receivedSinceTime, receivedBeforeTime)
            output = []
            if queryReturn != []:
                output = self.addQueryReturnToOutput(output, queryReturn)
            # Now let us search through the objects stored in memory
            with shared.inventoryLock:
                for hash, storedValue in shared.inventory.items():
                    objectType, streamNumber, payload, expiresTime, tag, receivedTime = storedValue
                    if objectType == self.OBJECT_TYPE_MSG and receivedTime > receivedSinceTime and receivedTime < receivedBeforeTime:
                        if len(payload) <= self.MAX_PAYLOAD_SIZE_TO_RETURN:
                            output = self.addPayloadToOutput(output, payload)
            if output == []:
                return 'No msgs found'
            else:
                return self.outputAsJSON('msgPayloads', output)