flake8: api, debug
This commit is contained in:
parent
4610e1a0d7
commit
cb0996c6c8
600
src/api.py
600
src/api.py
|
@ -1,37 +1,32 @@
|
||||||
# Copyright (c) 2012-2016 Jonathan Warren
|
# Copyright (c) 2012-2016 Jonathan Warren
|
||||||
# Copyright (c) 2012-2016 The Bitmessage developers
|
# Copyright (c) 2012-2018 The Bitmessage developers
|
||||||
|
|
||||||
comment = """
|
"""
|
||||||
This is not what you run to run the Bitmessage API. Instead, enable the API
|
This is not what you run to run the Bitmessage API. Instead, enable the API
|
||||||
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
|
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
|
||||||
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
|
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print comment
|
|
||||||
import sys
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
|
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
|
||||||
|
from struct import pack
|
||||||
|
|
||||||
import shared
|
import shared
|
||||||
import time
|
from addresses import (
|
||||||
from addresses import (decodeAddress, addBMIfNotPresent, decodeVarint,
|
decodeAddress, addBMIfNotPresent, decodeVarint,
|
||||||
calculateInventoryHash, varintDecodeError)
|
calculateInventoryHash, varintDecodeError)
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
import defaults
|
import defaults
|
||||||
import helper_inbox
|
import helper_inbox
|
||||||
import helper_sent
|
import helper_sent
|
||||||
import hashlib
|
|
||||||
|
|
||||||
import state
|
import state
|
||||||
import queues
|
import queues
|
||||||
import shutdown
|
import shutdown
|
||||||
from struct import pack
|
|
||||||
import network.stats
|
import network.stats
|
||||||
|
|
||||||
# Classes
|
# Classes
|
||||||
|
@ -52,6 +47,7 @@ class APIError(Exception):
|
||||||
super(APIError, self).__init__()
|
super(APIError, self).__init__()
|
||||||
self.error_number = error_number
|
self.error_number = error_number
|
||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "API Error %04i: %s" % (self.error_number, self.error_message)
|
return "API Error %04i: %s" % (self.error_number, self.error_message)
|
||||||
|
|
||||||
|
@ -65,7 +61,8 @@ class StoppableXMLRPCServer(SimpleXMLRPCServer):
|
||||||
|
|
||||||
|
|
||||||
# This is one of several classes that constitute the API
|
# This is one of several classes that constitute the API
|
||||||
# This class was written by Vaibhav Bhatia. Modified by Jonathan Warren (Atheros).
|
# This class was written by Vaibhav Bhatia.
|
||||||
|
# Modified by Jonathan Warren (Atheros).
|
||||||
# http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/
|
# http://code.activestate.com/recipes/501148-xmlrpc-serverclient-which-does-cookie-handling-and/
|
||||||
class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
|
|
||||||
|
@ -130,14 +127,18 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
def APIAuthenticateClient(self):
|
def APIAuthenticateClient(self):
|
||||||
if 'Authorization' in self.headers:
|
if 'Authorization' in self.headers:
|
||||||
# handle Basic authentication
|
# handle Basic authentication
|
||||||
(enctype, encstr) = self.headers.get('Authorization').split()
|
enctype, encstr = self.headers.get('Authorization').split()
|
||||||
(emailid, password) = encstr.decode('base64').split(':')
|
emailid, password = encstr.decode('base64').split(':')
|
||||||
if emailid == BMConfigParser().get('bitmessagesettings', 'apiusername') and password == BMConfigParser().get('bitmessagesettings', 'apipassword'):
|
return (
|
||||||
return True
|
emailid ==
|
||||||
else:
|
BMConfigParser().get('bitmessagesettings', 'apiusername')
|
||||||
return False
|
and password ==
|
||||||
|
BMConfigParser().get('bitmessagesettings', 'apipassword')
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.warn('Authentication failed because header lacks Authentication field')
|
logger.warning(
|
||||||
|
'Authentication failed because header lacks'
|
||||||
|
' Authentication field')
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -150,31 +151,48 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
elif decode_type == 'base64':
|
elif decode_type == 'base64':
|
||||||
return base64.b64decode(text)
|
return base64.b64decode(text)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise APIError(22, "Decode error - " + str(e) + ". Had trouble while decoding string: " + repr(text))
|
raise APIError(
|
||||||
|
22, "Decode error - %s. Had trouble while decoding string: %r"
|
||||||
|
% (e, text)
|
||||||
|
)
|
||||||
|
|
||||||
def _verifyAddress(self, address):
|
def _verifyAddress(self, address):
|
||||||
status, addressVersionNumber, streamNumber, ripe = decodeAddress(address)
|
status, addressVersionNumber, streamNumber, ripe = \
|
||||||
|
decodeAddress(address)
|
||||||
if status != 'success':
|
if status != 'success':
|
||||||
logger.warn('API Error 0007: Could not decode address %s. Status: %s.', address, status)
|
logger.warning(
|
||||||
|
'API Error 0007: Could not decode address %s. Status: %s.',
|
||||||
|
address, status
|
||||||
|
)
|
||||||
|
|
||||||
if status == 'checksumfailed':
|
if status == 'checksumfailed':
|
||||||
raise APIError(8, 'Checksum failed for address: ' + address)
|
raise APIError(8, 'Checksum failed for address: ' + address)
|
||||||
if status == 'invalidcharacters':
|
if status == 'invalidcharacters':
|
||||||
raise APIError(9, 'Invalid characters in address: ' + address)
|
raise APIError(9, 'Invalid characters in address: ' + address)
|
||||||
if status == 'versiontoohigh':
|
if status == 'versiontoohigh':
|
||||||
raise APIError(10, 'Address version number too high (or zero) in address: ' + address)
|
raise APIError(
|
||||||
|
10,
|
||||||
|
'Address version number too high (or zero) in address: '
|
||||||
|
+ address
|
||||||
|
)
|
||||||
if status == 'varintmalformed':
|
if status == 'varintmalformed':
|
||||||
raise APIError(26, 'Malformed varint in address: ' + address)
|
raise APIError(26, 'Malformed varint in address: ' + address)
|
||||||
raise APIError(7, 'Could not decode address: ' + address + ' : ' + status)
|
raise APIError(
|
||||||
|
7, 'Could not decode address: %s : %s' % (address, status))
|
||||||
if addressVersionNumber < 2 or addressVersionNumber > 4:
|
if addressVersionNumber < 2 or addressVersionNumber > 4:
|
||||||
raise APIError(11, 'The address version number currently must be 2, 3 or 4. Others aren\'t supported. Check the address.')
|
raise APIError(
|
||||||
|
11, 'The address version number currently must be 2, 3 or 4.'
|
||||||
|
' Others aren\'t supported. Check the address.'
|
||||||
|
)
|
||||||
if streamNumber != 1:
|
if streamNumber != 1:
|
||||||
raise APIError(12, 'The stream number must be 1. Others aren\'t supported. Check the address.')
|
raise APIError(
|
||||||
|
12, 'The stream number must be 1. Others aren\'t supported.'
|
||||||
|
' Check the address.'
|
||||||
|
)
|
||||||
|
|
||||||
return (status, addressVersionNumber, streamNumber, ripe)
|
return (status, addressVersionNumber, streamNumber, ripe)
|
||||||
|
|
||||||
|
# Request Handlers
|
||||||
#Request Handlers
|
|
||||||
|
|
||||||
def HandleListAddresses(self, method):
|
def HandleListAddresses(self, method):
|
||||||
data = '{"addresses":['
|
data = '{"addresses":['
|
||||||
|
@ -190,8 +208,14 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
label = BMConfigParser().get(addressInKeysFile, 'label')
|
label = BMConfigParser().get(addressInKeysFile, 'label')
|
||||||
if method == 'listAddresses2':
|
if method == 'listAddresses2':
|
||||||
label = base64.b64encode(label)
|
label = base64.b64encode(label)
|
||||||
data += json.dumps({'label': label, 'address': addressInKeysFile, 'stream':
|
data += json.dumps({
|
||||||
streamNumber, 'enabled': BMConfigParser().getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': '))
|
'label': label,
|
||||||
|
'address': addressInKeysFile,
|
||||||
|
'stream': streamNumber,
|
||||||
|
'enabled':
|
||||||
|
BMConfigParser().getboolean(addressInKeysFile, 'enabled'),
|
||||||
|
'chan': chan
|
||||||
|
}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -199,18 +223,22 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 1:
|
if len(params) == 1:
|
||||||
label, = params
|
label, = params
|
||||||
label = self._decode(label, "base64")
|
label = self._decode(label, "base64")
|
||||||
queryreturn = sqlQuery('''SELECT label, address from addressbook WHERE label = ?''', label)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT label, address from addressbook WHERE label = ?",
|
||||||
|
label)
|
||||||
elif len(params) > 1:
|
elif len(params) > 1:
|
||||||
raise APIError(0, "Too many paremeters, max 1")
|
raise APIError(0, "Too many paremeters, max 1")
|
||||||
else:
|
else:
|
||||||
queryreturn = sqlQuery('''SELECT label, address from addressbook''')
|
queryreturn = sqlQuery("SELECT label, address from addressbook")
|
||||||
data = '{"addresses":['
|
data = '{"addresses":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
label, address = row
|
label, address = row
|
||||||
label = shared.fixPotentiallyInvalidUTF8Data(label)
|
label = shared.fixPotentiallyInvalidUTF8Data(label)
|
||||||
if len(data) > 20:
|
if len(data) > 20:
|
||||||
data += ','
|
data += ','
|
||||||
data += json.dumps({'label':base64.b64encode(label), 'address': address}, indent=4, separators=(',', ': '))
|
data += json.dumps({
|
||||||
|
'label': base64.b64encode(label),
|
||||||
|
'address': address}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -221,14 +249,16 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
label = self._decode(label, "base64")
|
label = self._decode(label, "base64")
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
self._verifyAddress(address)
|
self._verifyAddress(address)
|
||||||
queryreturn = sqlQuery("SELECT address FROM addressbook WHERE address=?", address)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT address FROM addressbook WHERE address=?", address)
|
||||||
if queryreturn != []:
|
if queryreturn != []:
|
||||||
raise APIError(16, 'You already have this address in your address book.')
|
raise APIError(
|
||||||
|
16, 'You already have this address in your address book.')
|
||||||
|
|
||||||
sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address)
|
sqlExecute("INSERT INTO addressbook VALUES(?,?)", label, address)
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderAddressBook',''))
|
queues.UISignalQueue.put(('rerenderAddressBook', ''))
|
||||||
return "Added address %s to address book" % address
|
return "Added address %s to address book" % address
|
||||||
|
|
||||||
def HandleDeleteAddressBookEntry(self, params):
|
def HandleDeleteAddressBookEntry(self, params):
|
||||||
|
@ -238,9 +268,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
self._verifyAddress(address)
|
self._verifyAddress(address)
|
||||||
sqlExecute('DELETE FROM addressbook WHERE address=?', address)
|
sqlExecute('DELETE FROM addressbook WHERE address=?', address)
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderAddressBook',''))
|
queues.UISignalQueue.put(('rerenderAddressBook', ''))
|
||||||
return "Deleted address book entry for %s if it existed" % address
|
return "Deleted address book entry for %s if it existed" % address
|
||||||
|
|
||||||
def HandleCreateRandomAddress(self, params):
|
def HandleCreateRandomAddress(self, params):
|
||||||
|
@ -262,15 +292,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
elif len(params) == 3:
|
elif len(params) == 3:
|
||||||
label, eighteenByteRipe, totalDifficulty = params
|
label, eighteenByteRipe, totalDifficulty = params
|
||||||
nonceTrialsPerByte = int(
|
nonceTrialsPerByte = int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||||
|
* totalDifficulty)
|
||||||
payloadLengthExtraBytes = BMConfigParser().get(
|
payloadLengthExtraBytes = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
||||||
elif len(params) == 4:
|
elif len(params) == 4:
|
||||||
label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
|
label, eighteenByteRipe, totalDifficulty, \
|
||||||
|
smallMessageDifficulty = params
|
||||||
nonceTrialsPerByte = int(
|
nonceTrialsPerByte = int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||||
|
* totalDifficulty)
|
||||||
payloadLengthExtraBytes = int(
|
payloadLengthExtraBytes = int(
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
|
defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
* smallMessageDifficulty)
|
||||||
else:
|
else:
|
||||||
raise APIError(0, 'Too many parameters!')
|
raise APIError(0, 'Too many parameters!')
|
||||||
label = self._decode(label, "base64")
|
label = self._decode(label, "base64")
|
||||||
|
@ -281,7 +315,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
streamNumberForAddress = 1
|
streamNumberForAddress = 1
|
||||||
queues.addressGeneratorQueue.put((
|
queues.addressGeneratorQueue.put((
|
||||||
'createRandomAddress', 4, streamNumberForAddress, label, 1, "", eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
|
'createRandomAddress', 4, streamNumberForAddress, label, 1, "",
|
||||||
|
eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes
|
||||||
|
))
|
||||||
return queues.apiAddressGeneratorReturnQueue.get()
|
return queues.apiAddressGeneratorReturnQueue.get()
|
||||||
|
|
||||||
def HandleCreateDeterministicAddresses(self, params):
|
def HandleCreateDeterministicAddresses(self, params):
|
||||||
|
@ -315,54 +351,81 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
payloadLengthExtraBytes = BMConfigParser().get(
|
payloadLengthExtraBytes = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
||||||
elif len(params) == 4:
|
elif len(params) == 4:
|
||||||
passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params
|
passphrase, numberOfAddresses, addressVersionNumber, \
|
||||||
|
streamNumber = params
|
||||||
eighteenByteRipe = False
|
eighteenByteRipe = False
|
||||||
nonceTrialsPerByte = BMConfigParser().get(
|
nonceTrialsPerByte = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultnoncetrialsperbyte')
|
'bitmessagesettings', 'defaultnoncetrialsperbyte')
|
||||||
payloadLengthExtraBytes = BMConfigParser().get(
|
payloadLengthExtraBytes = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
||||||
elif len(params) == 5:
|
elif len(params) == 5:
|
||||||
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params
|
passphrase, numberOfAddresses, addressVersionNumber, \
|
||||||
|
streamNumber, eighteenByteRipe = params
|
||||||
nonceTrialsPerByte = BMConfigParser().get(
|
nonceTrialsPerByte = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultnoncetrialsperbyte')
|
'bitmessagesettings', 'defaultnoncetrialsperbyte')
|
||||||
payloadLengthExtraBytes = BMConfigParser().get(
|
payloadLengthExtraBytes = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
||||||
elif len(params) == 6:
|
elif len(params) == 6:
|
||||||
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params
|
passphrase, numberOfAddresses, addressVersionNumber, \
|
||||||
|
streamNumber, eighteenByteRipe, totalDifficulty = params
|
||||||
nonceTrialsPerByte = int(
|
nonceTrialsPerByte = int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||||
|
* totalDifficulty)
|
||||||
payloadLengthExtraBytes = BMConfigParser().get(
|
payloadLengthExtraBytes = BMConfigParser().get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
|
||||||
elif len(params) == 7:
|
elif len(params) == 7:
|
||||||
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
|
passphrase, numberOfAddresses, addressVersionNumber, \
|
||||||
|
streamNumber, eighteenByteRipe, totalDifficulty, \
|
||||||
|
smallMessageDifficulty = params
|
||||||
nonceTrialsPerByte = int(
|
nonceTrialsPerByte = int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||||
|
* totalDifficulty)
|
||||||
payloadLengthExtraBytes = int(
|
payloadLengthExtraBytes = int(
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
|
defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
* smallMessageDifficulty)
|
||||||
else:
|
else:
|
||||||
raise APIError(0, 'Too many parameters!')
|
raise APIError(0, 'Too many parameters!')
|
||||||
if len(passphrase) == 0:
|
if len(passphrase) == 0:
|
||||||
raise APIError(1, 'The specified passphrase is blank.')
|
raise APIError(1, 'The specified passphrase is blank.')
|
||||||
if not isinstance(eighteenByteRipe, bool):
|
if not isinstance(eighteenByteRipe, bool):
|
||||||
raise APIError(23, 'Bool expected in eighteenByteRipe, saw %s instead' % type(eighteenByteRipe))
|
raise APIError(
|
||||||
|
23, 'Bool expected in eighteenByteRipe, saw %s instead' %
|
||||||
|
type(eighteenByteRipe))
|
||||||
passphrase = self._decode(passphrase, "base64")
|
passphrase = self._decode(passphrase, "base64")
|
||||||
if addressVersionNumber == 0: # 0 means "just use the proper addressVersionNumber"
|
# 0 means "just use the proper addressVersionNumber"
|
||||||
|
if addressVersionNumber == 0:
|
||||||
addressVersionNumber = 4
|
addressVersionNumber = 4
|
||||||
if addressVersionNumber != 3 and 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.')
|
raise APIError(
|
||||||
|
2, 'The address version number currently must be 3, 4, or 0'
|
||||||
|
' (which means auto-select). %i isn\'t supported.' %
|
||||||
|
addressVersionNumber)
|
||||||
if streamNumber == 0: # 0 means "just use the most available stream"
|
if streamNumber == 0: # 0 means "just use the most available stream"
|
||||||
streamNumber = 1
|
streamNumber = 1
|
||||||
if streamNumber != 1:
|
if streamNumber != 1:
|
||||||
raise APIError(3,'The stream number must be 1 (or 0 which means auto-select). Others aren\'t supported.')
|
raise APIError(
|
||||||
|
3, 'The stream number must be 1 (or 0 which means'
|
||||||
|
' auto-select). Others aren\'t supported.')
|
||||||
if numberOfAddresses == 0:
|
if numberOfAddresses == 0:
|
||||||
raise APIError(4, 'Why would you ask me to generate 0 addresses for you?')
|
raise APIError(
|
||||||
|
4, 'Why would you ask me to generate 0 addresses for you?')
|
||||||
if numberOfAddresses > 999:
|
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.')
|
raise APIError(
|
||||||
|
5, 'You have (accidentally?) specified too many addresses to'
|
||||||
|
' make. Maximum 999. This check only exists to prevent'
|
||||||
|
' mischief; if you really want to create more addresses than'
|
||||||
|
' this, contact the Bitmessage developers and we can modify'
|
||||||
|
' the check or you can do it yourself by searching the source'
|
||||||
|
' code for this message.')
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
|
logger.debug(
|
||||||
queues.addressGeneratorQueue.put(
|
'Requesting that the addressGenerator create %s addresses.',
|
||||||
('createDeterministicAddresses', addressVersionNumber, streamNumber,
|
numberOfAddresses)
|
||||||
'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
|
queues.addressGeneratorQueue.put((
|
||||||
|
'createDeterministicAddresses', addressVersionNumber, streamNumber,
|
||||||
|
'unused API address', numberOfAddresses, passphrase,
|
||||||
|
eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes
|
||||||
|
))
|
||||||
data = '{"addresses":['
|
data = '{"addresses":['
|
||||||
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
|
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
|
||||||
for item in queueReturn:
|
for item in queueReturn:
|
||||||
|
@ -382,14 +445,21 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(1, 'The specified passphrase is blank.')
|
raise APIError(1, 'The specified passphrase is blank.')
|
||||||
passphrase = self._decode(passphrase, "base64")
|
passphrase = self._decode(passphrase, "base64")
|
||||||
if addressVersionNumber != 3 and addressVersionNumber != 4:
|
if addressVersionNumber != 3 and addressVersionNumber != 4:
|
||||||
raise APIError(2, 'The address version number currently must be 3 or 4. ' + addressVersionNumber + ' isn\'t supported.')
|
raise APIError(
|
||||||
|
2, 'The address version number currently must be 3 or 4. %i'
|
||||||
|
' isn\'t supported.' % addressVersionNumber)
|
||||||
if streamNumber != 1:
|
if streamNumber != 1:
|
||||||
raise APIError(3, ' The stream number must be 1. Others aren\'t supported.')
|
raise APIError(
|
||||||
|
3, ' The stream number must be 1. Others aren\'t supported.')
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
|
logger.debug(
|
||||||
queues.addressGeneratorQueue.put(
|
'Requesting that the addressGenerator create %s addresses.',
|
||||||
('getDeterministicAddress', addressVersionNumber,
|
numberOfAddresses)
|
||||||
streamNumber, 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe))
|
queues.addressGeneratorQueue.put((
|
||||||
|
'getDeterministicAddress', addressVersionNumber, streamNumber,
|
||||||
|
'unused API address', numberOfAddresses, passphrase,
|
||||||
|
eighteenByteRipe
|
||||||
|
))
|
||||||
return queues.apiAddressGeneratorReturnQueue.get()
|
return queues.apiAddressGeneratorReturnQueue.get()
|
||||||
|
|
||||||
def HandleCreateChan(self, params):
|
def HandleCreateChan(self, params):
|
||||||
|
@ -411,8 +481,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
addressVersionNumber = 4
|
addressVersionNumber = 4
|
||||||
streamNumber = 1
|
streamNumber = 1
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
logger.debug('Requesting that the addressGenerator create chan %s.', passphrase)
|
logger.debug(
|
||||||
queues.addressGeneratorQueue.put(('createChan', addressVersionNumber, streamNumber, label, passphrase, True))
|
'Requesting that the addressGenerator create chan %s.', passphrase)
|
||||||
|
queues.addressGeneratorQueue.put((
|
||||||
|
'createChan', addressVersionNumber, streamNumber, label,
|
||||||
|
passphrase, True
|
||||||
|
))
|
||||||
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
|
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
|
||||||
if len(queueReturn) == 0:
|
if len(queueReturn) == 0:
|
||||||
raise APIError(24, 'Chan address is already present.')
|
raise APIError(24, 'Chan address is already present.')
|
||||||
|
@ -423,7 +497,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) < 2:
|
if len(params) < 2:
|
||||||
raise APIError(0, 'I need two parameters.')
|
raise APIError(0, 'I need two parameters.')
|
||||||
elif len(params) == 2:
|
elif len(params) == 2:
|
||||||
passphrase, suppliedAddress= params
|
passphrase, suppliedAddress = params
|
||||||
passphrase = self._decode(passphrase, "base64")
|
passphrase = self._decode(passphrase, "base64")
|
||||||
if len(passphrase) == 0:
|
if len(passphrase) == 0:
|
||||||
raise APIError(1, 'The specified passphrase is blank.')
|
raise APIError(1, 'The specified passphrase is blank.')
|
||||||
|
@ -435,18 +509,24 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
except:
|
except:
|
||||||
label = str_chan + ' ' + repr(passphrase)
|
label = str_chan + ' ' + repr(passphrase)
|
||||||
|
|
||||||
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(suppliedAddress)
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(suppliedAddress)
|
||||||
suppliedAddress = addBMIfNotPresent(suppliedAddress)
|
suppliedAddress = addBMIfNotPresent(suppliedAddress)
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
queues.addressGeneratorQueue.put(('joinChan', suppliedAddress, label, passphrase, True))
|
queues.addressGeneratorQueue.put((
|
||||||
addressGeneratorReturnValue = queues.apiAddressGeneratorReturnQueue.get()
|
'joinChan', suppliedAddress, label, passphrase, True
|
||||||
|
))
|
||||||
|
addressGeneratorReturnValue = \
|
||||||
|
queues.apiAddressGeneratorReturnQueue.get()
|
||||||
|
|
||||||
if addressGeneratorReturnValue[0] == 'chan name does not match address':
|
if addressGeneratorReturnValue[0] == \
|
||||||
|
'chan name does not match address':
|
||||||
raise APIError(18, 'Chan name does not match address.')
|
raise APIError(18, 'Chan name does not match address.')
|
||||||
if len(addressGeneratorReturnValue) == 0:
|
if len(addressGeneratorReturnValue) == 0:
|
||||||
raise APIError(24, 'Chan address is already present.')
|
raise APIError(24, 'Chan address is already present.')
|
||||||
#TODO: this variable is not used to anything
|
# TODO: this variable is not used to anything
|
||||||
createdAddress = addressGeneratorReturnValue[0] # in case we ever want it for anything.
|
# in case we ever want it for anything.
|
||||||
|
# createdAddress = addressGeneratorReturnValue[0]
|
||||||
return "success"
|
return "success"
|
||||||
|
|
||||||
def HandleLeaveChan(self, params):
|
def HandleLeaveChan(self, params):
|
||||||
|
@ -454,12 +534,16 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need parameters.')
|
raise APIError(0, 'I need parameters.')
|
||||||
elif len(params) == 1:
|
elif len(params) == 1:
|
||||||
address, = params
|
address, = params
|
||||||
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(address)
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
if not BMConfigParser().has_section(address):
|
if not BMConfigParser().has_section(address):
|
||||||
raise APIError(13, 'Could not find this address in your keys.dat file.')
|
raise APIError(
|
||||||
|
13, 'Could not find this address in your keys.dat file.')
|
||||||
if not BMConfigParser().safeGetBoolean(address, 'chan'):
|
if not BMConfigParser().safeGetBoolean(address, 'chan'):
|
||||||
raise APIError(25, 'Specified address is not a chan address. Use deleteAddress API call instead.')
|
raise APIError(
|
||||||
|
25, 'Specified address is not a chan address.'
|
||||||
|
' Use deleteAddress API call instead.')
|
||||||
BMConfigParser().remove_section(address)
|
BMConfigParser().remove_section(address)
|
||||||
with open(state.appdata + 'keys.dat', 'wb') as configfile:
|
with open(state.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
|
@ -470,44 +554,56 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need parameters.')
|
raise APIError(0, 'I need parameters.')
|
||||||
elif len(params) == 1:
|
elif len(params) == 1:
|
||||||
address, = params
|
address, = params
|
||||||
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(address)
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
if not BMConfigParser().has_section(address):
|
if not BMConfigParser().has_section(address):
|
||||||
raise APIError(13, 'Could not find this address in your keys.dat file.')
|
raise APIError(
|
||||||
|
13, 'Could not find this address in your keys.dat file.')
|
||||||
BMConfigParser().remove_section(address)
|
BMConfigParser().remove_section(address)
|
||||||
with open(state.appdata + 'keys.dat', 'wb') as configfile:
|
with open(state.appdata + 'keys.dat', 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
|
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
|
||||||
shared.reloadMyAddressHashes()
|
shared.reloadMyAddressHashes()
|
||||||
return 'success'
|
return 'success'
|
||||||
|
|
||||||
def HandleGetAllInboxMessages(self, params):
|
def HandleGetAllInboxMessages(self, params):
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox where folder='inbox' ORDER BY received''')
|
"SELECT msgid, toaddress, fromaddress, subject, received, message,"
|
||||||
|
" encodingtype, read FROM inbox where folder='inbox'"
|
||||||
|
" ORDER BY received"
|
||||||
|
)
|
||||||
data = '{"inboxMessages":['
|
data = '{"inboxMessages":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, received, message, encodingtype, read = row
|
msgid, toAddress, fromAddress, subject, received, message, \
|
||||||
|
encodingtype, read = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
data += ','
|
||||||
data += json.dumps({'msgid': hexlify(msgid), 'toAddress': toAddress,
|
data += json.dumps({
|
||||||
'fromAddress': fromAddress, 'subject': base64.b64encode(subject),
|
'msgid': hexlify(msgid),
|
||||||
'message': base64.b64encode(message), 'encodingType': encodingtype,
|
'toAddress': toAddress,
|
||||||
'receivedTime': received, 'read': read}, indent=4, separators=(',', ': '))
|
'fromAddress': fromAddress,
|
||||||
|
'subject': base64.b64encode(subject),
|
||||||
|
'message': base64.b64encode(message),
|
||||||
|
'encodingType': encodingtype,
|
||||||
|
'receivedTime': received,
|
||||||
|
'read': read}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def HandleGetAllInboxMessageIds(self, params):
|
def HandleGetAllInboxMessageIds(self, params):
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT msgid FROM inbox where folder='inbox' ORDER BY received''')
|
"SELECT msgid FROM inbox where folder='inbox' ORDER BY received")
|
||||||
data = '{"inboxMessageIds":['
|
data = '{"inboxMessageIds":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid = row[0]
|
msgid = row[0]
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
data += ','
|
||||||
data += json.dumps({'msgid': hexlify(msgid)}, indent=4, separators=(',', ': '))
|
data += json.dumps(
|
||||||
|
{'msgid': hexlify(msgid)}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -520,43 +616,78 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
msgid = self._decode(params[0], "hex")
|
msgid = self._decode(params[0], "hex")
|
||||||
readStatus = params[1]
|
readStatus = params[1]
|
||||||
if not isinstance(readStatus, bool):
|
if not isinstance(readStatus, bool):
|
||||||
raise APIError(23, 'Bool expected in readStatus, saw %s instead.' % type(readStatus))
|
raise APIError(
|
||||||
queryreturn = sqlQuery('''SELECT read FROM inbox WHERE msgid=?''', msgid)
|
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
|
# UPDATE is slow, only update if status is different
|
||||||
if queryreturn != [] and (queryreturn[0][0] == 1) != readStatus:
|
if queryreturn != [] and (queryreturn[0][0] == 1) != readStatus:
|
||||||
sqlExecute('''UPDATE inbox set read = ? WHERE msgid=?''', readStatus, msgid)
|
sqlExecute(
|
||||||
|
"UPDATE inbox set read = ? WHERE msgid=?",
|
||||||
|
readStatus, msgid)
|
||||||
queues.UISignalQueue.put(('changedInboxUnread', None))
|
queues.UISignalQueue.put(('changedInboxUnread', None))
|
||||||
queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox WHERE msgid=?''', msgid)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT msgid, toaddress, fromaddress, subject, received, message,"
|
||||||
|
" encodingtype, read FROM inbox WHERE msgid=?", msgid
|
||||||
|
)
|
||||||
data = '{"inboxMessage":['
|
data = '{"inboxMessage":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, received, message, encodingtype, read = row
|
msgid, toAddress, fromAddress, subject, received, message, \
|
||||||
|
encodingtype, read = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def HandleGetAllSentMessages(self, params):
|
def HandleGetAllSentMessages(self, params):
|
||||||
queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent where folder='sent' ORDER BY lastactiontime''')
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
|
||||||
|
" message, encodingtype, status, ackdata FROM sent"
|
||||||
|
" WHERE folder='sent' ORDER BY lastactiontime"
|
||||||
|
)
|
||||||
data = '{"sentMessages":['
|
data = '{"sentMessages":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
|
msgid, toAddress, fromAddress, subject, lastactiontime, message, \
|
||||||
|
encodingtype, status, ackdata = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def HandleGetAllSentMessageIds(self, params):
|
def HandleGetAllSentMessageIds(self, params):
|
||||||
queryreturn = sqlQuery('''SELECT msgid FROM sent where folder='sent' ORDER BY lastactiontime''')
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT msgid FROM sent where folder='sent'"
|
||||||
|
" ORDER BY lastactiontime"
|
||||||
|
)
|
||||||
data = '{"sentMessageIds":['
|
data = '{"sentMessageIds":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid = row[0]
|
msgid = row[0]
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
data += ','
|
||||||
data += json.dumps({'msgid':hexlify(msgid)}, indent=4, separators=(',', ': '))
|
data += json.dumps(
|
||||||
|
{'msgid': hexlify(msgid)}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -564,15 +695,26 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 0:
|
if len(params) == 0:
|
||||||
raise APIError(0, 'I need parameters!')
|
raise APIError(0, 'I need parameters!')
|
||||||
toAddress = params[0]
|
toAddress = params[0]
|
||||||
queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype FROM inbox WHERE folder='inbox' AND toAddress=?''', toAddress)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT msgid, toaddress, fromaddress, subject, received, message,"
|
||||||
|
" encodingtype FROM inbox WHERE folder='inbox' AND toAddress=?",
|
||||||
|
toAddress)
|
||||||
data = '{"inboxMessages":['
|
data = '{"inboxMessages":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, received, message, encodingtype = row
|
msgid, toAddress, fromAddress, subject, received, message, \
|
||||||
|
encodingtype = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -580,13 +722,27 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 0:
|
if len(params) == 0:
|
||||||
raise APIError(0, 'I need parameters!')
|
raise APIError(0, 'I need parameters!')
|
||||||
msgid = self._decode(params[0], "hex")
|
msgid = self._decode(params[0], "hex")
|
||||||
queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE msgid=?''', msgid)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
|
||||||
|
" message, encodingtype, status, ackdata FROM sent WHERE msgid=?",
|
||||||
|
msgid
|
||||||
|
)
|
||||||
data = '{"sentMessage":['
|
data = '{"sentMessage":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
|
msgid, toAddress, fromAddress, subject, lastactiontime, message, \
|
||||||
|
encodingtype, status, ackdata = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -594,16 +750,30 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 0:
|
if len(params) == 0:
|
||||||
raise APIError(0, 'I need parameters!')
|
raise APIError(0, 'I need parameters!')
|
||||||
fromAddress = params[0]
|
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''',
|
queryreturn = sqlQuery(
|
||||||
fromAddress)
|
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
|
||||||
|
" message, encodingtype, status, ackdata FROM sent"
|
||||||
|
" WHERE folder='sent' AND fromAddress=? ORDER BY lastactiontime",
|
||||||
|
fromAddress
|
||||||
|
)
|
||||||
data = '{"sentMessages":['
|
data = '{"sentMessages":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
|
msgid, toAddress, fromAddress, subject, lastactiontime, message, \
|
||||||
|
encodingtype, status, ackdata = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -611,14 +781,27 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 0:
|
if len(params) == 0:
|
||||||
raise APIError(0, 'I need parameters!')
|
raise APIError(0, 'I need parameters!')
|
||||||
ackData = self._decode(params[0], "hex")
|
ackData = self._decode(params[0], "hex")
|
||||||
queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE ackdata=?''',
|
queryreturn = sqlQuery(
|
||||||
ackData)
|
"SELECT msgid, toaddress, fromaddress, subject, lastactiontime,"
|
||||||
|
" message, encodingtype, status, ackdata FROM sent"
|
||||||
|
" WHERE ackdata=?", ackData
|
||||||
|
)
|
||||||
data = '{"sentMessage":['
|
data = '{"sentMessage":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
|
msgid, toAddress, fromAddress, subject, lastactiontime, message, \
|
||||||
|
encodingtype, status, ackdata = row
|
||||||
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
subject = shared.fixPotentiallyInvalidUTF8Data(subject)
|
||||||
message = shared.fixPotentiallyInvalidUTF8Data(message)
|
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 += 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 += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -658,7 +841,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
toAddress, fromAddress, subject, message, encodingType = params
|
toAddress, fromAddress, subject, message, encodingType = params
|
||||||
TTL = 4 * 24 * 60 * 60
|
TTL = 4 * 24 * 60 * 60
|
||||||
elif len(params) == 6:
|
elif len(params) == 6:
|
||||||
toAddress, fromAddress, subject, message, encodingType, TTL = params
|
toAddress, fromAddress, subject, message, encodingType, TTL = \
|
||||||
|
params
|
||||||
if encodingType not in [2, 3]:
|
if encodingType not in [2, 3]:
|
||||||
raise APIError(6, 'The encoding type must be 2 or 3.')
|
raise APIError(6, 'The encoding type must be 2 or 3.')
|
||||||
subject = self._decode(subject, "base64")
|
subject = self._decode(subject, "base64")
|
||||||
|
@ -671,17 +855,20 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
TTL = 28 * 24 * 60 * 60
|
TTL = 28 * 24 * 60 * 60
|
||||||
toAddress = addBMIfNotPresent(toAddress)
|
toAddress = addBMIfNotPresent(toAddress)
|
||||||
fromAddress = addBMIfNotPresent(fromAddress)
|
fromAddress = addBMIfNotPresent(fromAddress)
|
||||||
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(toAddress)
|
||||||
self._verifyAddress(fromAddress)
|
self._verifyAddress(fromAddress)
|
||||||
try:
|
try:
|
||||||
fromAddressEnabled = BMConfigParser().getboolean(
|
fromAddressEnabled = BMConfigParser().getboolean(
|
||||||
fromAddress, 'enabled')
|
fromAddress, 'enabled')
|
||||||
except:
|
except:
|
||||||
raise APIError(13, 'Could not find your fromAddress in the keys.dat file.')
|
raise APIError(
|
||||||
|
13, 'Could not find your fromAddress in the keys.dat file.')
|
||||||
if not fromAddressEnabled:
|
if not fromAddressEnabled:
|
||||||
raise APIError(14, 'Your fromAddress is disabled. Cannot send.')
|
raise APIError(14, 'Your fromAddress is disabled. Cannot send.')
|
||||||
|
|
||||||
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
|
stealthLevel = BMConfigParser().safeGetInt(
|
||||||
|
'bitmessagesettings', 'ackstealthlevel')
|
||||||
ackdata = genAckPayload(streamNumber, stealthLevel)
|
ackdata = genAckPayload(streamNumber, stealthLevel)
|
||||||
|
|
||||||
t = ('',
|
t = ('',
|
||||||
|
@ -702,7 +889,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
helper_sent.insert(t)
|
helper_sent.insert(t)
|
||||||
|
|
||||||
toLabel = ''
|
toLabel = ''
|
||||||
queryreturn = sqlQuery('''select label from addressbook where address=?''', toAddress)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT label FROM addressbook WHERE address=?", toAddress)
|
||||||
if queryreturn != []:
|
if queryreturn != []:
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
toLabel, = row
|
toLabel, = row
|
||||||
|
@ -739,10 +927,10 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
fromAddress = addBMIfNotPresent(fromAddress)
|
fromAddress = addBMIfNotPresent(fromAddress)
|
||||||
self._verifyAddress(fromAddress)
|
self._verifyAddress(fromAddress)
|
||||||
try:
|
try:
|
||||||
fromAddressEnabled = BMConfigParser().getboolean(
|
BMConfigParser().getboolean(fromAddress, 'enabled')
|
||||||
fromAddress, 'enabled')
|
|
||||||
except:
|
except:
|
||||||
raise APIError(13, 'could not find your fromAddress in the keys.dat file.')
|
raise APIError(
|
||||||
|
13, 'could not find your fromAddress in the keys.dat file.')
|
||||||
streamNumber = decodeAddress(fromAddress)[2]
|
streamNumber = decodeAddress(fromAddress)[2]
|
||||||
ackdata = genAckPayload(streamNumber, 0)
|
ackdata = genAckPayload(streamNumber, 0)
|
||||||
toAddress = '[Broadcast subscribers]'
|
toAddress = '[Broadcast subscribers]'
|
||||||
|
@ -781,8 +969,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(15, 'Invalid ackData object size.')
|
raise APIError(15, 'Invalid ackData object size.')
|
||||||
ackdata = self._decode(ackdata, "hex")
|
ackdata = self._decode(ackdata, "hex")
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT status FROM sent where ackdata=?''',
|
"SELECT status FROM sent where ackdata=?", ackdata)
|
||||||
ackdata)
|
|
||||||
if queryreturn == []:
|
if queryreturn == []:
|
||||||
return 'notfound'
|
return 'notfound'
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
|
@ -808,10 +995,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
self._verifyAddress(address)
|
self._verifyAddress(address)
|
||||||
# First we must check to see if the address is already in the
|
# First we must check to see if the address is already in the
|
||||||
# subscriptions list.
|
# subscriptions list.
|
||||||
queryreturn = sqlQuery('''select * from subscriptions where address=?''', address)
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT * FROM subscriptions WHERE address=?", address)
|
||||||
if queryreturn != []:
|
if queryreturn != []:
|
||||||
raise APIError(16, 'You are already subscribed to that address.')
|
raise APIError(16, 'You are already subscribed to that address.')
|
||||||
sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',label, address, True)
|
sqlExecute(
|
||||||
|
"INSERT INTO subscriptions VALUES (?,?,?)", label, address, True)
|
||||||
shared.reloadBroadcastSendersForWhichImWatching()
|
shared.reloadBroadcastSendersForWhichImWatching()
|
||||||
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
|
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
|
||||||
queues.UISignalQueue.put(('rerenderSubscriptions', ''))
|
queues.UISignalQueue.put(('rerenderSubscriptions', ''))
|
||||||
|
@ -829,26 +1018,34 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
return 'Deleted subscription if it existed.'
|
return 'Deleted subscription if it existed.'
|
||||||
|
|
||||||
def ListSubscriptions(self, params):
|
def ListSubscriptions(self, params):
|
||||||
queryreturn = sqlQuery('''SELECT label, address, enabled FROM subscriptions''')
|
queryreturn = sqlQuery(
|
||||||
|
"SELECT label, address, enabled FROM subscriptions")
|
||||||
data = {'subscriptions': []}
|
data = {'subscriptions': []}
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
label, address, enabled = row
|
label, address, enabled = row
|
||||||
label = shared.fixPotentiallyInvalidUTF8Data(label)
|
label = shared.fixPotentiallyInvalidUTF8Data(label)
|
||||||
data['subscriptions'].append({'label':base64.b64encode(label), 'address': address, 'enabled': enabled == 1})
|
data['subscriptions'].append({
|
||||||
return json.dumps(data, indent=4, separators=(',',': '))
|
'label': base64.b64encode(label),
|
||||||
|
'address': address,
|
||||||
|
'enabled': enabled == 1
|
||||||
|
})
|
||||||
|
return json.dumps(data, indent=4, separators=(',', ': '))
|
||||||
|
|
||||||
def HandleDisseminatePreEncryptedMsg(self, params):
|
def HandleDisseminatePreEncryptedMsg(self, params):
|
||||||
# The device issuing this command to PyBitmessage supplies a msg object that has
|
# The device issuing this command to PyBitmessage supplies a msg
|
||||||
# already been encrypted but which still needs the POW to be done. PyBitmessage
|
# object that has already been encrypted but which still needs the POW
|
||||||
# accepts this msg object and sends it out to the rest of the Bitmessage network
|
# to be done. PyBitmessage accepts this msg object and sends it out
|
||||||
# as if it had generated the message itself. Please do not yet add this to the
|
# to the rest of the Bitmessage network as if it had generated
|
||||||
# api doc.
|
# the message itself. Please do not yet add this to the api doc.
|
||||||
if len(params) != 3:
|
if len(params) != 3:
|
||||||
raise APIError(0, 'I need 3 parameter!')
|
raise APIError(0, 'I need 3 parameter!')
|
||||||
encryptedPayload, requiredAverageProofOfWorkNonceTrialsPerByte, requiredPayloadLengthExtraBytes = params
|
encryptedPayload, requiredAverageProofOfWorkNonceTrialsPerByte, \
|
||||||
|
requiredPayloadLengthExtraBytes = params
|
||||||
encryptedPayload = self._decode(encryptedPayload, "hex")
|
encryptedPayload = self._decode(encryptedPayload, "hex")
|
||||||
# Let us do the POW and attach it to the front
|
# Let us do the POW and attach it to the front
|
||||||
target = 2**64 / ((len(encryptedPayload)+requiredPayloadLengthExtraBytes+8) * requiredAverageProofOfWorkNonceTrialsPerByte)
|
target = 2**64 / (
|
||||||
|
(len(encryptedPayload) + requiredPayloadLengthExtraBytes + 8)
|
||||||
|
* requiredAverageProofOfWorkNonceTrialsPerByte)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print '(For msg message via API) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / defaults.networkDefaultPayloadLengthExtraBytes
|
print '(For msg message via API) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
powStartTime = time.time()
|
powStartTime = time.time()
|
||||||
|
@ -866,7 +1063,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
objectType = 2
|
objectType = 2
|
||||||
TTL = 2.5 * 24 * 60 * 60
|
TTL = 2.5 * 24 * 60 * 60
|
||||||
Inventory()[inventoryHash] = (
|
Inventory()[inventoryHash] = (
|
||||||
objectType, toStreamNumber, encryptedPayload, int(time.time()) + TTL,'')
|
objectType, toStreamNumber, encryptedPayload,
|
||||||
|
int(time.time()) + TTL, ''
|
||||||
|
)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash)
|
print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash)
|
||||||
queues.invQueue.put((toStreamNumber, inventoryHash))
|
queues.invQueue.put((toStreamNumber, inventoryHash))
|
||||||
|
@ -876,43 +1075,47 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if len(params) == 0:
|
if len(params) == 0:
|
||||||
raise APIError(0, 'I need parameters!')
|
raise APIError(0, 'I need parameters!')
|
||||||
ackdata = self._decode(params[0], "hex")
|
ackdata = self._decode(params[0], "hex")
|
||||||
sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdata)
|
sqlExecute("UPDATE sent SET folder='trash' WHERE ackdata=?", ackdata)
|
||||||
return 'Trashed sent message (assuming message existed).'
|
return 'Trashed sent message (assuming message existed).'
|
||||||
|
|
||||||
def HandleDissimatePubKey(self, params):
|
def HandleDissimatePubKey(self, params):
|
||||||
# The device issuing this command to PyBitmessage supplies a pubkey object to be
|
# The device issuing this command to PyBitmessage supplies a pubkey
|
||||||
# disseminated to the rest of the Bitmessage network. PyBitmessage accepts this
|
# object to be disseminated to the rest of the Bitmessage network.
|
||||||
# pubkey object and sends it out to the rest of the Bitmessage network as if it
|
# PyBitmessage accepts this pubkey object and sends it out to the rest
|
||||||
# had generated the pubkey object itself. Please do not yet add this to the api
|
# of the Bitmessage network as if it had generated the pubkey object
|
||||||
# doc.
|
# itself. Please do not yet add this to the api doc.
|
||||||
if len(params) != 1:
|
if len(params) != 1:
|
||||||
raise APIError(0, 'I need 1 parameter!')
|
raise APIError(0, 'I need 1 parameter!')
|
||||||
payload, = params
|
payload, = params
|
||||||
payload = self._decode(payload, "hex")
|
payload = self._decode(payload, "hex")
|
||||||
|
|
||||||
# Let us do the POW
|
# Let us do the POW
|
||||||
target = 2 ** 64 / ((len(payload) + defaults.networkDefaultPayloadLengthExtraBytes +
|
target = 2 ** 64 / (
|
||||||
8) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
|
(len(payload) + defaults.networkDefaultPayloadLengthExtraBytes
|
||||||
|
+ 8) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
|
||||||
print '(For pubkey message via API) Doing proof of work...'
|
print '(For pubkey message via API) Doing proof of work...'
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
print '(For pubkey message via API) Found proof of work', trialValue, 'Nonce:', nonce
|
print '(For pubkey message via API) Found proof of work', trialValue, 'Nonce:', nonce
|
||||||
payload = pack('>Q', nonce) + payload
|
payload = pack('>Q', nonce) + payload
|
||||||
|
|
||||||
pubkeyReadPosition = 8 # bypass the nonce
|
pubkeyReadPosition = 8 # bypass the nonce
|
||||||
if payload[pubkeyReadPosition:pubkeyReadPosition+4] == '\x00\x00\x00\x00': # if this pubkey uses 8 byte time
|
if payload[pubkeyReadPosition:pubkeyReadPosition+4] == \
|
||||||
|
'\x00\x00\x00\x00': # if this pubkey uses 8 byte time
|
||||||
pubkeyReadPosition += 8
|
pubkeyReadPosition += 8
|
||||||
else:
|
else:
|
||||||
pubkeyReadPosition += 4
|
pubkeyReadPosition += 4
|
||||||
addressVersion, addressVersionLength = decodeVarint(payload[pubkeyReadPosition:pubkeyReadPosition+10])
|
addressVersion, addressVersionLength = decodeVarint(
|
||||||
|
payload[pubkeyReadPosition:pubkeyReadPosition+10])
|
||||||
pubkeyReadPosition += addressVersionLength
|
pubkeyReadPosition += addressVersionLength
|
||||||
pubkeyStreamNumber = decodeVarint(payload[pubkeyReadPosition:pubkeyReadPosition+10])[0]
|
pubkeyStreamNumber = decodeVarint(
|
||||||
|
payload[pubkeyReadPosition:pubkeyReadPosition+10])[0]
|
||||||
inventoryHash = calculateInventoryHash(payload)
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
objectType = 1
|
objectType = 1 # TODO: support v4 pubkeys
|
||||||
#todo: support v4 pubkeys
|
|
||||||
TTL = 28 * 24 * 60 * 60
|
TTL = 28 * 24 * 60 * 60
|
||||||
Inventory()[inventoryHash] = (
|
Inventory()[inventoryHash] = (
|
||||||
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL,'')
|
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL, ''
|
||||||
|
)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash)
|
print 'broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash)
|
||||||
queues.invQueue.put((pubkeyStreamNumber, inventoryHash))
|
queues.invQueue.put((pubkeyStreamNumber, inventoryHash))
|
||||||
|
@ -925,41 +1128,56 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need 1 parameter!')
|
raise APIError(0, 'I need 1 parameter!')
|
||||||
requestedHash, = params
|
requestedHash, = params
|
||||||
if len(requestedHash) != 32:
|
if len(requestedHash) != 32:
|
||||||
raise APIError(19, 'The length of hash should be 32 bytes (encoded in hex thus 64 characters).')
|
raise APIError(
|
||||||
|
19, 'The length of hash should be 32 bytes (encoded in hex'
|
||||||
|
' thus 64 characters).')
|
||||||
requestedHash = self._decode(requestedHash, "hex")
|
requestedHash = self._decode(requestedHash, "hex")
|
||||||
|
|
||||||
# This is not a particularly commonly used API function. Before we
|
# 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
|
# use it we'll need to fill out a field in our inventory database
|
||||||
# which is blank by default (first20bytesofencryptedmessage).
|
# which is blank by default (first20bytesofencryptedmessage).
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'''SELECT hash, payload FROM inventory WHERE tag = '' and objecttype = 2 ; ''')
|
"SELECT hash, payload FROM inventory WHERE tag = ''"
|
||||||
|
" and objecttype = 2")
|
||||||
with SqlBulkExecute() as sql:
|
with SqlBulkExecute() as sql:
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
hash01, payload = row
|
hash01, payload = row
|
||||||
readPosition = 16 # Nonce length + time length
|
readPosition = 16 # Nonce length + time length
|
||||||
readPosition += decodeVarint(payload[readPosition:readPosition+10])[1] # Stream Number length
|
# Stream Number length
|
||||||
t = (payload[readPosition:readPosition+32],hash01)
|
readPosition += decodeVarint(
|
||||||
sql.execute('''UPDATE inventory SET tag=? WHERE hash=?; ''', *t)
|
payload[readPosition:readPosition+10])[1]
|
||||||
|
t = (payload[readPosition:readPosition+32], hash01)
|
||||||
|
sql.execute("UPDATE inventory SET tag=? WHERE hash=?", *t)
|
||||||
|
|
||||||
queryreturn = sqlQuery('''SELECT payload FROM inventory WHERE tag = ?''',
|
queryreturn = sqlQuery(
|
||||||
requestedHash)
|
"SELECT payload FROM inventory WHERE tag = ?", requestedHash)
|
||||||
data = '{"receivedMessageDatas":['
|
data = '{"receivedMessageDatas":['
|
||||||
for row in queryreturn:
|
for row in queryreturn:
|
||||||
payload, = row
|
payload, = row
|
||||||
if len(data) > 25:
|
if len(data) > 25:
|
||||||
data += ','
|
data += ','
|
||||||
data += json.dumps({'data':hexlify(payload)}, indent=4, separators=(',', ': '))
|
data += json.dumps(
|
||||||
|
{'data': hexlify(payload)}, indent=4, separators=(',', ': '))
|
||||||
data += ']}'
|
data += ']}'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def HandleClientStatus(self, params):
|
def HandleClientStatus(self, params):
|
||||||
if len(network.stats.connectedHostsList()) == 0:
|
if len(network.stats.connectedHostsList()) == 0:
|
||||||
networkStatus = 'notConnected'
|
networkStatus = 'notConnected'
|
||||||
elif len(network.stats.connectedHostsList()) > 0 and not shared.clientHasReceivedIncomingConnections:
|
elif len(network.stats.connectedHostsList()) > 0 \
|
||||||
|
and not shared.clientHasReceivedIncomingConnections:
|
||||||
networkStatus = 'connectedButHaveNotReceivedIncomingConnections'
|
networkStatus = 'connectedButHaveNotReceivedIncomingConnections'
|
||||||
else:
|
else:
|
||||||
networkStatus = 'connectedAndReceivingIncomingConnections'
|
networkStatus = 'connectedAndReceivingIncomingConnections'
|
||||||
return json.dumps({'networkConnections':len(network.stats.connectedHostsList()),'numberOfMessagesProcessed':shared.numberOfMessagesProcessed, 'numberOfBroadcastsProcessed':shared.numberOfBroadcastsProcessed, 'numberOfPubkeysProcessed':shared.numberOfPubkeysProcessed, 'networkStatus':networkStatus, 'softwareName':'PyBitmessage','softwareVersion':softwareVersion}, indent=4, separators=(',', ': '))
|
return json.dumps({
|
||||||
|
'networkConnections': len(network.stats.connectedHostsList()),
|
||||||
|
'numberOfMessagesProcessed': shared.numberOfMessagesProcessed,
|
||||||
|
'numberOfBroadcastsProcessed': shared.numberOfBroadcastsProcessed,
|
||||||
|
'numberOfPubkeysProcessed': shared.numberOfPubkeysProcessed,
|
||||||
|
'networkStatus': networkStatus,
|
||||||
|
'softwareName': 'PyBitmessage',
|
||||||
|
'softwareVersion': softwareVersion
|
||||||
|
}, indent=4, separators=(',', ': '))
|
||||||
|
|
||||||
def HandleDecodeAddress(self, params):
|
def HandleDecodeAddress(self, params):
|
||||||
# Return a meaningful decoding of an address.
|
# Return a meaningful decoding of an address.
|
||||||
|
@ -967,16 +1185,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need 1 parameter!')
|
raise APIError(0, 'I need 1 parameter!')
|
||||||
address, = params
|
address, = params
|
||||||
status, addressVersion, streamNumber, ripe = decodeAddress(address)
|
status, addressVersion, streamNumber, ripe = decodeAddress(address)
|
||||||
return json.dumps({'status':status, 'addressVersion':addressVersion,
|
return json.dumps({
|
||||||
'streamNumber':streamNumber, 'ripe':base64.b64encode(ripe)}, indent=4,
|
'status': status,
|
||||||
separators=(',', ': '))
|
'addressVersion': addressVersion,
|
||||||
|
'streamNumber': streamNumber,
|
||||||
|
'ripe': base64.b64encode(ripe)
|
||||||
|
}, indent=4, separators=(',', ': '))
|
||||||
|
|
||||||
def HandleHelloWorld(self, params):
|
def HandleHelloWorld(self, params):
|
||||||
(a, b) = params
|
a, b = params
|
||||||
return a + '-' + b
|
return a + '-' + b
|
||||||
|
|
||||||
def HandleAdd(self, params):
|
def HandleAdd(self, params):
|
||||||
(a, b) = params
|
a, b = params
|
||||||
return a + b
|
return a + b
|
||||||
|
|
||||||
def HandleStatusBar(self, params):
|
def HandleStatusBar(self, params):
|
||||||
|
@ -998,14 +1219,18 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
handlers['add'] = HandleAdd
|
handlers['add'] = HandleAdd
|
||||||
handlers['statusBar'] = HandleStatusBar
|
handlers['statusBar'] = HandleStatusBar
|
||||||
handlers['listAddresses'] = HandleListAddresses
|
handlers['listAddresses'] = HandleListAddresses
|
||||||
handlers['listAddressBookEntries'] = HandleListAddressBookEntries;
|
handlers['listAddressBookEntries'] = HandleListAddressBookEntries
|
||||||
handlers['listAddressbook'] = HandleListAddressBookEntries # the listAddressbook alias should be removed eventually.
|
# the listAddressbook alias should be removed eventually.
|
||||||
|
handlers['listAddressbook'] = HandleListAddressBookEntries
|
||||||
handlers['addAddressBookEntry'] = HandleAddAddressBookEntry
|
handlers['addAddressBookEntry'] = HandleAddAddressBookEntry
|
||||||
handlers['addAddressbook'] = HandleAddAddressBookEntry # the addAddressbook alias should be deleted eventually.
|
# the addAddressbook alias should be deleted eventually.
|
||||||
|
handlers['addAddressbook'] = HandleAddAddressBookEntry
|
||||||
handlers['deleteAddressBookEntry'] = HandleDeleteAddressBookEntry
|
handlers['deleteAddressBookEntry'] = HandleDeleteAddressBookEntry
|
||||||
handlers['deleteAddressbook'] = HandleDeleteAddressBookEntry # The deleteAddressbook alias should be deleted eventually.
|
# The deleteAddressbook alias should be deleted eventually.
|
||||||
|
handlers['deleteAddressbook'] = HandleDeleteAddressBookEntry
|
||||||
handlers['createRandomAddress'] = HandleCreateRandomAddress
|
handlers['createRandomAddress'] = HandleCreateRandomAddress
|
||||||
handlers['createDeterministicAddresses'] = HandleCreateDeterministicAddresses
|
handlers['createDeterministicAddresses'] = \
|
||||||
|
HandleCreateDeterministicAddresses
|
||||||
handlers['getDeterministicAddress'] = HandleGetDeterministicAddress
|
handlers['getDeterministicAddress'] = HandleGetDeterministicAddress
|
||||||
handlers['createChan'] = HandleCreateChan
|
handlers['createChan'] = HandleCreateChan
|
||||||
handlers['joinChan'] = HandleJoinChan
|
handlers['joinChan'] = HandleJoinChan
|
||||||
|
@ -1020,7 +1245,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
handlers['getAllSentMessageIds'] = HandleGetAllSentMessageIds
|
handlers['getAllSentMessageIds'] = HandleGetAllSentMessageIds
|
||||||
handlers['getAllSentMessageIDs'] = HandleGetAllSentMessageIds
|
handlers['getAllSentMessageIDs'] = HandleGetAllSentMessageIds
|
||||||
handlers['getInboxMessagesByReceiver'] = HandleInboxMessagesByReceiver
|
handlers['getInboxMessagesByReceiver'] = HandleInboxMessagesByReceiver
|
||||||
handlers['getInboxMessagesByAddress'] = HandleInboxMessagesByReceiver #after some time getInboxMessagesByAddress should be removed
|
# after some time getInboxMessagesByAddress should be removed
|
||||||
|
handlers['getInboxMessagesByAddress'] = HandleInboxMessagesByReceiver
|
||||||
handlers['getSentMessageById'] = HandleGetSentMessageById
|
handlers['getSentMessageById'] = HandleGetSentMessageById
|
||||||
handlers['getSentMessageByID'] = HandleGetSentMessageById
|
handlers['getSentMessageByID'] = HandleGetSentMessageById
|
||||||
handlers['getSentMessagesByAddress'] = HandleGetSentMessagesByAddress
|
handlers['getSentMessagesByAddress'] = HandleGetSentMessagesByAddress
|
||||||
|
@ -1038,18 +1264,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
handlers['listSubscriptions'] = ListSubscriptions
|
handlers['listSubscriptions'] = ListSubscriptions
|
||||||
handlers['disseminatePreEncryptedMsg'] = HandleDisseminatePreEncryptedMsg
|
handlers['disseminatePreEncryptedMsg'] = HandleDisseminatePreEncryptedMsg
|
||||||
handlers['disseminatePubkey'] = HandleDissimatePubKey
|
handlers['disseminatePubkey'] = HandleDissimatePubKey
|
||||||
handlers['getMessageDataByDestinationHash'] = HandleGetMessageDataByDestinationHash
|
handlers['getMessageDataByDestinationHash'] = \
|
||||||
handlers['getMessageDataByDestinationTag'] = HandleGetMessageDataByDestinationHash
|
HandleGetMessageDataByDestinationHash
|
||||||
|
handlers['getMessageDataByDestinationTag'] = \
|
||||||
|
HandleGetMessageDataByDestinationHash
|
||||||
handlers['clientStatus'] = HandleClientStatus
|
handlers['clientStatus'] = HandleClientStatus
|
||||||
handlers['decodeAddress'] = HandleDecodeAddress
|
handlers['decodeAddress'] = HandleDecodeAddress
|
||||||
handlers['deleteAndVacuum'] = HandleDeleteAndVacuum
|
handlers['deleteAndVacuum'] = HandleDeleteAndVacuum
|
||||||
handlers['shutdown'] = HandleShutdown
|
handlers['shutdown'] = HandleShutdown
|
||||||
|
|
||||||
def _handle_request(self, method, params):
|
def _handle_request(self, method, params):
|
||||||
if (self.handlers.has_key(method)):
|
if method not in self.handlers:
|
||||||
return self.handlers[method](self, params)
|
|
||||||
else:
|
|
||||||
raise APIError(20, 'Invalid method: %s' % method)
|
raise APIError(20, 'Invalid method: %s' % method)
|
||||||
|
return self.handlers[method](self, params)
|
||||||
|
|
||||||
def _dispatch(self, method, params):
|
def _dispatch(self, method, params):
|
||||||
self.cookies = []
|
self.cookies = []
|
||||||
|
@ -1068,4 +1295,5 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
return "API Error 0026: Data contains a malformed varint. Some details: %s" % e
|
return "API Error 0026: Data contains a malformed varint. Some details: %s" % e
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
return "API Error 0021: Unexpected API Failure - %s" % str(e)
|
|
||||||
|
return "API Error 0021: Unexpected API Failure - %s" % e
|
||||||
|
|
62
src/debug.py
62
src/debug.py
|
@ -1,49 +1,64 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
"""
|
||||||
Logging and debuging facility
|
Logging and debuging facility
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
Levels:
|
Levels:
|
||||||
DEBUG Detailed information, typically of interest only when diagnosing problems.
|
DEBUG Detailed information, typically of interest only when
|
||||||
|
diagnosing problems.
|
||||||
INFO Confirmation that things are working as expected.
|
INFO Confirmation that things are working as expected.
|
||||||
WARNING An indication that something unexpected happened, or indicative of some problem in the
|
WARNING An indication that something unexpected happened, or indicative
|
||||||
near future (e.g. ‘disk space low’). The software is still working as expected.
|
of some problem in the near future (e.g. ‘disk space low’).
|
||||||
ERROR Due to a more serious problem, the software has not been able to perform some function.
|
The software is still working as expected.
|
||||||
CRITICAL A serious error, indicating that the program itself may be unable to continue running.
|
ERROR Due to a more serious problem, the software has not been able
|
||||||
|
to perform some function.
|
||||||
|
CRITICAL A serious error, indicating that the program itself may be
|
||||||
|
unable to continue running.
|
||||||
|
|
||||||
There are three loggers: `console_only`, `file_only` and `both`.
|
There are three loggers: `console_only`, `file_only` and `both`.
|
||||||
|
|
||||||
Use: `from debug import logger` to import this facility into whatever module you wish to log messages from.
|
Use: `from debug import logger` to import this facility into whatever module
|
||||||
Logging is thread-safe so you don't have to worry about locks, just import and log.
|
you wish to log messages from. Logging is thread-safe so you don't have
|
||||||
'''
|
to worry about locks, just import and log.
|
||||||
|
"""
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import helper_startup
|
import helper_startup
|
||||||
import state
|
import state
|
||||||
|
|
||||||
helper_startup.loadConfig()
|
helper_startup.loadConfig()
|
||||||
|
|
||||||
# Now can be overriden from a config file, which uses standard python logging.config.fileConfig interface
|
# Now can be overriden from a config file, which uses standard python
|
||||||
# examples are here: https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163
|
# logging.config.fileConfig interface
|
||||||
|
# examples are here:
|
||||||
|
# https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163
|
||||||
log_level = 'WARNING'
|
log_level = 'WARNING'
|
||||||
|
|
||||||
|
|
||||||
def log_uncaught_exceptions(ex_cls, ex, tb):
|
def log_uncaught_exceptions(ex_cls, ex, tb):
|
||||||
logging.critical('Unhandled exception', exc_info=(ex_cls, ex, tb))
|
logging.critical('Unhandled exception', exc_info=(ex_cls, ex, tb))
|
||||||
|
|
||||||
|
|
||||||
def configureLogging():
|
def configureLogging():
|
||||||
have_logging = False
|
have_logging = False
|
||||||
try:
|
try:
|
||||||
logging.config.fileConfig(os.path.join (state.appdata, 'logging.dat'))
|
logging.config.fileConfig(os.path.join(state.appdata, 'logging.dat'))
|
||||||
have_logging = True
|
have_logging = True
|
||||||
print "Loaded logger configuration from %s" % (os.path.join(state.appdata, 'logging.dat'))
|
print(
|
||||||
|
'Loaded logger configuration from %s' %
|
||||||
|
os.path.join(state.appdata, 'logging.dat'))
|
||||||
except:
|
except:
|
||||||
if os.path.isfile(os.path.join(state.appdata, 'logging.dat')):
|
if os.path.isfile(os.path.join(state.appdata, 'logging.dat')):
|
||||||
print "Failed to load logger configuration from %s, using default logging config" % (os.path.join(state.appdata, 'logging.dat'))
|
print(
|
||||||
print sys.exc_info()
|
'Failed to load logger configuration from %s, using default'
|
||||||
|
' logging config\n%s' %
|
||||||
|
(os.path.join(state.appdata, 'logging.dat'), sys.exc_info()))
|
||||||
else:
|
else:
|
||||||
# no need to confuse the user if the logger config is missing entirely
|
# no need to confuse the user if the logger config
|
||||||
print "Using default logger configuration"
|
# is missing entirely
|
||||||
|
print('Using default logger configuration')
|
||||||
|
|
||||||
sys.excepthook = log_uncaught_exceptions
|
sys.excepthook = log_uncaught_exceptions
|
||||||
|
|
||||||
|
@ -69,7 +84,7 @@ def configureLogging():
|
||||||
'formatter': 'default',
|
'formatter': 'default',
|
||||||
'level': log_level,
|
'level': log_level,
|
||||||
'filename': state.appdata + 'debug.log',
|
'filename': state.appdata + 'debug.log',
|
||||||
'maxBytes': 2097152, # 2 MiB
|
'maxBytes': 2097152, # 2 MiB
|
||||||
'backupCount': 1,
|
'backupCount': 1,
|
||||||
'encoding': 'UTF-8',
|
'encoding': 'UTF-8',
|
||||||
}
|
}
|
||||||
|
@ -77,15 +92,15 @@ def configureLogging():
|
||||||
'loggers': {
|
'loggers': {
|
||||||
'console_only': {
|
'console_only': {
|
||||||
'handlers': ['console'],
|
'handlers': ['console'],
|
||||||
'propagate' : 0
|
'propagate': 0
|
||||||
},
|
},
|
||||||
'file_only': {
|
'file_only': {
|
||||||
'handlers': ['file'],
|
'handlers': ['file'],
|
||||||
'propagate' : 0
|
'propagate': 0
|
||||||
},
|
},
|
||||||
'both': {
|
'both': {
|
||||||
'handlers': ['console', 'file'],
|
'handlers': ['console', 'file'],
|
||||||
'propagate' : 0
|
'propagate': 0
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -95,8 +110,9 @@ def configureLogging():
|
||||||
})
|
})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# TODO (xj9): Get from a config file.
|
# TODO (xj9): Get from a config file.
|
||||||
#logger = logging.getLogger('console_only')
|
# logger = logging.getLogger('console_only')
|
||||||
if configureLogging():
|
if configureLogging():
|
||||||
if '-c' in sys.argv:
|
if '-c' in sys.argv:
|
||||||
logger = logging.getLogger('file_only')
|
logger = logging.getLogger('file_only')
|
||||||
|
@ -105,6 +121,7 @@ if configureLogging():
|
||||||
else:
|
else:
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
|
||||||
def restartLoggingInUpdatedAppdataLocation():
|
def restartLoggingInUpdatedAppdataLocation():
|
||||||
global logger
|
global logger
|
||||||
for i in list(logger.handlers):
|
for i in list(logger.handlers):
|
||||||
|
@ -118,4 +135,3 @@ def restartLoggingInUpdatedAppdataLocation():
|
||||||
logger = logging.getLogger('both')
|
logger = logging.getLogger('both')
|
||||||
else:
|
else:
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user