flake8: api, debug

This commit is contained in:
Dmitri Bogomolov 2018-04-08 18:28:08 +03:00
parent 4610e1a0d7
commit cb0996c6c8
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13
2 changed files with 466 additions and 222 deletions

View File

@ -1,37 +1,32 @@
# 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
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
"""
if __name__ == "__main__":
print comment
import sys
sys.exit(0)
import base64
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
import hashlib
import json
import time
from binascii import hexlify, unhexlify
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from struct import pack
import shared
import time
from addresses import (decodeAddress, addBMIfNotPresent, decodeVarint,
from addresses import (
decodeAddress, addBMIfNotPresent, decodeVarint,
calculateInventoryHash, varintDecodeError)
from bmconfigparser import BMConfigParser
import defaults
import helper_inbox
import helper_sent
import hashlib
import state
import queues
import shutdown
from struct import pack
import network.stats
# Classes
@ -52,6 +47,7 @@ class APIError(Exception):
super(APIError, self).__init__()
self.error_number = error_number
self.error_message = error_message
def __str__(self):
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 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/
class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
@ -130,14 +127,18 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def APIAuthenticateClient(self):
if 'Authorization' in self.headers:
# handle Basic authentication
(enctype, encstr) = self.headers.get('Authorization').split()
(emailid, password) = encstr.decode('base64').split(':')
if emailid == BMConfigParser().get('bitmessagesettings', 'apiusername') and password == BMConfigParser().get('bitmessagesettings', 'apipassword'):
return True
else:
return False
enctype, encstr = self.headers.get('Authorization').split()
emailid, password = encstr.decode('base64').split(':')
return (
emailid ==
BMConfigParser().get('bitmessagesettings', 'apiusername')
and password ==
BMConfigParser().get('bitmessagesettings', 'apipassword')
)
else:
logger.warn('Authentication failed because header lacks Authentication field')
logger.warning(
'Authentication failed because header lacks'
' Authentication field')
time.sleep(2)
return False
@ -150,31 +151,48 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
elif decode_type == 'base64':
return base64.b64decode(text)
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):
status, addressVersionNumber, streamNumber, ripe = decodeAddress(address)
status, addressVersionNumber, streamNumber, ripe = \
decodeAddress(address)
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':
raise APIError(8, 'Checksum failed for address: ' + address)
if status == 'invalidcharacters':
raise APIError(9, 'Invalid characters in address: ' + address)
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':
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:
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:
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)
#Request Handlers
# Request Handlers
def HandleListAddresses(self, method):
data = '{"addresses":['
@ -190,8 +208,14 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = BMConfigParser().get(addressInKeysFile, 'label')
if method == 'listAddresses2':
label = base64.b64encode(label)
data += json.dumps({'label': label, 'address': addressInKeysFile, 'stream':
streamNumber, 'enabled': BMConfigParser().getboolean(addressInKeysFile, 'enabled'), 'chan': chan}, indent=4, separators=(',', ': '))
data += json.dumps({
'label': label,
'address': addressInKeysFile,
'stream': streamNumber,
'enabled':
BMConfigParser().getboolean(addressInKeysFile, 'enabled'),
'chan': chan
}, indent=4, separators=(',', ': '))
data += ']}'
return data
@ -199,18 +223,22 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if len(params) == 1:
label, = params
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:
raise APIError(0, "Too many paremeters, max 1")
else:
queryreturn = sqlQuery('''SELECT label, address from addressbook''')
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 += json.dumps({
'label': base64.b64encode(label),
'address': address}, indent=4, separators=(',', ': '))
data += ']}'
return data
@ -221,14 +249,16 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
label = self._decode(label, "base64")
address = addBMIfNotPresent(address)
self._verifyAddress(address)
queryreturn = sqlQuery("SELECT address FROM addressbook WHERE address=?", address)
queryreturn = sqlQuery(
"SELECT address FROM addressbook WHERE address=?", address)
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)
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
queues.UISignalQueue.put(('rerenderAddressBook',''))
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
queues.UISignalQueue.put(('rerenderAddressBook', ''))
return "Added address %s to address book" % address
def HandleDeleteAddressBookEntry(self, params):
@ -238,9 +268,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
address = addBMIfNotPresent(address)
self._verifyAddress(address)
sqlExecute('DELETE FROM addressbook WHERE address=?', address)
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
queues.UISignalQueue.put(('rerenderAddressBook',''))
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
queues.UISignalQueue.put(('rerenderAddressBook', ''))
return "Deleted address book entry for %s if it existed" % address
def HandleCreateRandomAddress(self, params):
@ -262,15 +292,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
elif len(params) == 3:
label, eighteenByteRipe, totalDifficulty = params
nonceTrialsPerByte = int(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
* totalDifficulty)
payloadLengthExtraBytes = BMConfigParser().get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 4:
label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
label, eighteenByteRipe, totalDifficulty, \
smallMessageDifficulty = params
nonceTrialsPerByte = int(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
* totalDifficulty)
payloadLengthExtraBytes = int(
defaults.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
defaults.networkDefaultPayloadLengthExtraBytes
* smallMessageDifficulty)
else:
raise APIError(0, 'Too many parameters!')
label = self._decode(label, "base64")
@ -281,7 +315,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
queues.apiAddressGeneratorReturnQueue.queue.clear()
streamNumberForAddress = 1
queues.addressGeneratorQueue.put((
'createRandomAddress', 4, streamNumberForAddress, label, 1, "", eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
'createRandomAddress', 4, streamNumberForAddress, label, 1, "",
eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes
))
return queues.apiAddressGeneratorReturnQueue.get()
def HandleCreateDeterministicAddresses(self, params):
@ -315,54 +351,81 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
payloadLengthExtraBytes = BMConfigParser().get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 4:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params
passphrase, numberOfAddresses, addressVersionNumber, \
streamNumber = params
eighteenByteRipe = False
nonceTrialsPerByte = BMConfigParser().get(
'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = BMConfigParser().get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 5:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params
passphrase, numberOfAddresses, addressVersionNumber, \
streamNumber, eighteenByteRipe = params
nonceTrialsPerByte = BMConfigParser().get(
'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = BMConfigParser().get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 6:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params
passphrase, numberOfAddresses, addressVersionNumber, \
streamNumber, eighteenByteRipe, totalDifficulty = params
nonceTrialsPerByte = int(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
* totalDifficulty)
payloadLengthExtraBytes = BMConfigParser().get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 7:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
passphrase, numberOfAddresses, addressVersionNumber, \
streamNumber, eighteenByteRipe, totalDifficulty, \
smallMessageDifficulty = params
nonceTrialsPerByte = int(
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
* totalDifficulty)
payloadLengthExtraBytes = int(
defaults.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
defaults.networkDefaultPayloadLengthExtraBytes
* smallMessageDifficulty)
else:
raise APIError(0, 'Too many parameters!')
if len(passphrase) == 0:
raise APIError(1, 'The specified passphrase is blank.')
if not isinstance(eighteenByteRipe, bool):
raise APIError(23, 'Bool expected in eighteenByteRipe, saw %s instead' % type(eighteenByteRipe))
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"
# 0 means "just use the proper addressVersionNumber"
if addressVersionNumber == 0:
addressVersionNumber = 4
if addressVersionNumber != 3 and addressVersionNumber != 4:
raise APIError(2,'The address version number currently must be 3, 4, or 0 (which means auto-select). ' + 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"
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:
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:
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()
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
queues.addressGeneratorQueue.put(
('createDeterministicAddresses', addressVersionNumber, streamNumber,
'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes))
logger.debug(
'Requesting that the addressGenerator create %s addresses.',
numberOfAddresses)
queues.addressGeneratorQueue.put((
'createDeterministicAddresses', addressVersionNumber, streamNumber,
'unused API address', numberOfAddresses, passphrase,
eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes
))
data = '{"addresses":['
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
for item in queueReturn:
@ -382,14 +445,21 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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.')
raise APIError(
2, 'The address version number currently must be 3 or 4. %i'
' isn\'t supported.' % addressVersionNumber)
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()
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
queues.addressGeneratorQueue.put(
('getDeterministicAddress', addressVersionNumber,
streamNumber, 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe))
logger.debug(
'Requesting that the addressGenerator create %s addresses.',
numberOfAddresses)
queues.addressGeneratorQueue.put((
'getDeterministicAddress', addressVersionNumber, streamNumber,
'unused API address', numberOfAddresses, passphrase,
eighteenByteRipe
))
return queues.apiAddressGeneratorReturnQueue.get()
def HandleCreateChan(self, params):
@ -411,8 +481,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
addressVersionNumber = 4
streamNumber = 1
queues.apiAddressGeneratorReturnQueue.queue.clear()
logger.debug('Requesting that the addressGenerator create chan %s.', passphrase)
queues.addressGeneratorQueue.put(('createChan', addressVersionNumber, streamNumber, label, passphrase, True))
logger.debug(
'Requesting that the addressGenerator create chan %s.', passphrase)
queues.addressGeneratorQueue.put((
'createChan', addressVersionNumber, streamNumber, label,
passphrase, True
))
queueReturn = queues.apiAddressGeneratorReturnQueue.get()
if len(queueReturn) == 0:
raise APIError(24, 'Chan address is already present.')
@ -423,7 +497,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
if len(params) < 2:
raise APIError(0, 'I need two parameters.')
elif len(params) == 2:
passphrase, suppliedAddress= params
passphrase, suppliedAddress = params
passphrase = self._decode(passphrase, "base64")
if len(passphrase) == 0:
raise APIError(1, 'The specified passphrase is blank.')
@ -435,18 +509,24 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
except:
label = str_chan + ' ' + repr(passphrase)
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(suppliedAddress)
status, addressVersionNumber, streamNumber, toRipe = \
self._verifyAddress(suppliedAddress)
suppliedAddress = addBMIfNotPresent(suppliedAddress)
queues.apiAddressGeneratorReturnQueue.queue.clear()
queues.addressGeneratorQueue.put(('joinChan', suppliedAddress, label, passphrase, True))
addressGeneratorReturnValue = queues.apiAddressGeneratorReturnQueue.get()
queues.addressGeneratorQueue.put((
'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.')
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.
# TODO: this variable is not used to anything
# in case we ever want it for anything.
# createdAddress = addressGeneratorReturnValue[0]
return "success"
def HandleLeaveChan(self, params):
@ -454,12 +534,16 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
raise APIError(0, 'I need parameters.')
elif len(params) == 1:
address, = params
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
status, addressVersionNumber, streamNumber, toRipe = \
self._verifyAddress(address)
address = addBMIfNotPresent(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'):
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)
with open(state.appdata + 'keys.dat', 'wb') as configfile:
BMConfigParser().write(configfile)
@ -470,44 +554,56 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
raise APIError(0, 'I need parameters.')
elif len(params) == 1:
address, = params
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(address)
status, addressVersionNumber, streamNumber, toRipe = \
self._verifyAddress(address)
address = addBMIfNotPresent(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)
with open(state.appdata + 'keys.dat', 'wb') as configfile:
BMConfigParser().write(configfile)
queues.UISignalQueue.put(('rerenderMessagelistFromLabels',''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels',''))
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
queues.UISignalQueue.put(('rerenderMessagelistToLabels', ''))
shared.reloadMyAddressHashes()
return 'success'
def HandleGetAllInboxMessages(self, params):
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":['
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)
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 += 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 HandleGetAllInboxMessageIds(self, params):
queryreturn = sqlQuery(
'''SELECT msgid FROM inbox where folder='inbox' ORDER BY received''')
"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': hexlify(msgid)}, indent=4, separators=(',', ': '))
data += json.dumps(
{'msgid': hexlify(msgid)}, indent=4, separators=(',', ': '))
data += ']}'
return data
@ -520,43 +616,78 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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)
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)
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
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 += 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 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":['
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)
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 += 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
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":['
for row in queryreturn:
msgid = row[0]
if len(data) > 25:
data += ','
data += json.dumps({'msgid':hexlify(msgid)}, indent=4, separators=(',', ': '))
data += json.dumps(
{'msgid': hexlify(msgid)}, indent=4, separators=(',', ': '))
data += ']}'
return data
@ -564,15 +695,26 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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
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 += 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
@ -580,13 +722,27 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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
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 += 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
@ -594,16 +750,30 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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
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 += 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
@ -611,14 +781,27 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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
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 += 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
@ -658,7 +841,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
toAddress, fromAddress, subject, message, encodingType = params
TTL = 4 * 24 * 60 * 60
elif len(params) == 6:
toAddress, fromAddress, subject, message, encodingType, TTL = params
toAddress, fromAddress, subject, message, encodingType, TTL = \
params
if encodingType not in [2, 3]:
raise APIError(6, 'The encoding type must be 2 or 3.')
subject = self._decode(subject, "base64")
@ -671,38 +855,42 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
TTL = 28 * 24 * 60 * 60
toAddress = addBMIfNotPresent(toAddress)
fromAddress = addBMIfNotPresent(fromAddress)
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
status, addressVersionNumber, streamNumber, toRipe = \
self._verifyAddress(toAddress)
self._verifyAddress(fromAddress)
try:
fromAddressEnabled = BMConfigParser().getboolean(
fromAddress, 'enabled')
except:
raise APIError(13, 'Could not find your fromAddress in the keys.dat file.')
raise APIError(
13, 'Could not find your fromAddress in the keys.dat file.')
if not fromAddressEnabled:
raise APIError(14, 'Your fromAddress is disabled. Cannot send.')
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
stealthLevel = BMConfigParser().safeGetInt(
'bitmessagesettings', 'ackstealthlevel')
ackdata = genAckPayload(streamNumber, stealthLevel)
t = ('',
toAddress,
toRipe,
fromAddress,
subject,
message,
ackdata,
t = ('',
toAddress,
toRipe,
fromAddress,
subject,
message,
ackdata,
int(time.time()), # sentTime (this won't change)
int(time.time()), # lastActionTime
0,
'msgqueued',
0,
'sent',
2,
0,
'msgqueued',
0,
'sent',
2,
TTL)
helper_sent.insert(t)
toLabel = ''
queryreturn = sqlQuery('''select label from addressbook where address=?''', toAddress)
queryreturn = sqlQuery(
"SELECT label FROM addressbook WHERE address=?", toAddress)
if queryreturn != []:
for row in queryreturn:
toLabel, = row
@ -739,10 +927,10 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
fromAddress = addBMIfNotPresent(fromAddress)
self._verifyAddress(fromAddress)
try:
fromAddressEnabled = BMConfigParser().getboolean(
fromAddress, 'enabled')
BMConfigParser().getboolean(fromAddress, 'enabled')
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]
ackdata = genAckPayload(streamNumber, 0)
toAddress = '[Broadcast subscribers]'
@ -781,8 +969,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
raise APIError(15, 'Invalid ackData object size.')
ackdata = self._decode(ackdata, "hex")
queryreturn = sqlQuery(
'''SELECT status FROM sent where ackdata=?''',
ackdata)
"SELECT status FROM sent where ackdata=?", ackdata)
if queryreturn == []:
return 'notfound'
for row in queryreturn:
@ -808,10 +995,12 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
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)
sqlExecute(
"INSERT INTO subscriptions VALUES (?,?,?)", label, address, True)
shared.reloadBroadcastSendersForWhichImWatching()
queues.UISignalQueue.put(('rerenderMessagelistFromLabels', ''))
queues.UISignalQueue.put(('rerenderSubscriptions', ''))
@ -829,26 +1018,34 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return 'Deleted subscription if it existed.'
def ListSubscriptions(self, params):
queryreturn = sqlQuery('''SELECT label, address, enabled FROM subscriptions''')
queryreturn = sqlQuery(
"SELECT label, address, enabled FROM subscriptions")
data = {'subscriptions': []}
for row in queryreturn:
label, address, enabled = row
label = shared.fixPotentiallyInvalidUTF8Data(label)
data['subscriptions'].append({'label':base64.b64encode(label), 'address': address, 'enabled': enabled == 1})
return json.dumps(data, indent=4, separators=(',',': '))
data['subscriptions'].append({
'label': base64.b64encode(label),
'address': address,
'enabled': enabled == 1
})
return json.dumps(data, indent=4, separators=(',', ': '))
def HandleDisseminatePreEncryptedMsg(self, params):
# 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.
# 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, 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)
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) / defaults.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / defaults.networkDefaultPayloadLengthExtraBytes
powStartTime = time.time()
@ -866,7 +1063,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
objectType = 2
TTL = 2.5 * 24 * 60 * 60
Inventory()[inventoryHash] = (
objectType, toStreamNumber, encryptedPayload, int(time.time()) + TTL,'')
objectType, toStreamNumber, encryptedPayload,
int(time.time()) + TTL, ''
)
with shared.printLock:
print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash)
queues.invQueue.put((toStreamNumber, inventoryHash))
@ -876,43 +1075,47 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
sqlExecute("UPDATE sent SET folder='trash' WHERE ackdata=?", ackdata)
return 'Trashed sent message (assuming message existed).'
def HandleDissimatePubKey(self, params):
# 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.
# 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) + defaults.networkDefaultPayloadLengthExtraBytes +
8) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
target = 2 ** 64 / (
(len(payload) + defaults.networkDefaultPayloadLengthExtraBytes
+ 8) * defaults.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 # 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])
addressVersion, addressVersionLength = decodeVarint(
payload[pubkeyReadPosition:pubkeyReadPosition+10])
pubkeyReadPosition += addressVersionLength
pubkeyStreamNumber = decodeVarint(payload[pubkeyReadPosition:pubkeyReadPosition+10])[0]
pubkeyStreamNumber = decodeVarint(
payload[pubkeyReadPosition:pubkeyReadPosition+10])[0]
inventoryHash = calculateInventoryHash(payload)
objectType = 1
#todo: support v4 pubkeys
objectType = 1 # TODO: support v4 pubkeys
TTL = 28 * 24 * 60 * 60
Inventory()[inventoryHash] = (
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL,'')
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL, ''
)
with shared.printLock:
print 'broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash)
queues.invQueue.put((pubkeyStreamNumber, inventoryHash))
@ -925,41 +1128,56 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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).')
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 = 2 ; ''')
"SELECT hash, payload FROM inventory WHERE tag = ''"
" and objecttype = 2")
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)
readPosition = 16 # Nonce length + time length
# Stream Number length
readPosition += decodeVarint(
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 = ?''',
requestedHash)
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':hexlify(payload)}, indent=4, separators=(',', ': '))
data += json.dumps(
{'data': hexlify(payload)}, indent=4, separators=(',', ': '))
data += ']}'
return data
def HandleClientStatus(self, params):
if len(network.stats.connectedHostsList()) == 0:
networkStatus = 'notConnected'
elif len(network.stats.connectedHostsList()) > 0 and not shared.clientHasReceivedIncomingConnections:
elif len(network.stats.connectedHostsList()) > 0 \
and not shared.clientHasReceivedIncomingConnections:
networkStatus = 'connectedButHaveNotReceivedIncomingConnections'
else:
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):
# Return a meaningful decoding of an address.
@ -967,16 +1185,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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':base64.b64encode(ripe)}, indent=4,
separators=(',', ': '))
return json.dumps({
'status': status,
'addressVersion': addressVersion,
'streamNumber': streamNumber,
'ripe': base64.b64encode(ripe)
}, indent=4, separators=(',', ': '))
def HandleHelloWorld(self, params):
(a, b) = params
a, b = params
return a + '-' + b
def HandleAdd(self, params):
(a, b) = params
a, b = params
return a + b
def HandleStatusBar(self, params):
@ -998,14 +1219,18 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
handlers['add'] = HandleAdd
handlers['statusBar'] = HandleStatusBar
handlers['listAddresses'] = HandleListAddresses
handlers['listAddressBookEntries'] = HandleListAddressBookEntries;
handlers['listAddressbook'] = HandleListAddressBookEntries # the listAddressbook alias should be removed eventually.
handlers['listAddressBookEntries'] = HandleListAddressBookEntries
# the listAddressbook alias should be removed eventually.
handlers['listAddressbook'] = HandleListAddressBookEntries
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['deleteAddressbook'] = HandleDeleteAddressBookEntry # The deleteAddressbook alias should be deleted eventually.
# The deleteAddressbook alias should be deleted eventually.
handlers['deleteAddressbook'] = HandleDeleteAddressBookEntry
handlers['createRandomAddress'] = HandleCreateRandomAddress
handlers['createDeterministicAddresses'] = HandleCreateDeterministicAddresses
handlers['createDeterministicAddresses'] = \
HandleCreateDeterministicAddresses
handlers['getDeterministicAddress'] = HandleGetDeterministicAddress
handlers['createChan'] = HandleCreateChan
handlers['joinChan'] = HandleJoinChan
@ -1020,7 +1245,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
handlers['getAllSentMessageIds'] = HandleGetAllSentMessageIds
handlers['getAllSentMessageIDs'] = HandleGetAllSentMessageIds
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['getSentMessagesByAddress'] = HandleGetSentMessagesByAddress
@ -1038,18 +1264,19 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
handlers['listSubscriptions'] = ListSubscriptions
handlers['disseminatePreEncryptedMsg'] = HandleDisseminatePreEncryptedMsg
handlers['disseminatePubkey'] = HandleDissimatePubKey
handlers['getMessageDataByDestinationHash'] = HandleGetMessageDataByDestinationHash
handlers['getMessageDataByDestinationTag'] = HandleGetMessageDataByDestinationHash
handlers['getMessageDataByDestinationHash'] = \
HandleGetMessageDataByDestinationHash
handlers['getMessageDataByDestinationTag'] = \
HandleGetMessageDataByDestinationHash
handlers['clientStatus'] = HandleClientStatus
handlers['decodeAddress'] = HandleDecodeAddress
handlers['deleteAndVacuum'] = HandleDeleteAndVacuum
handlers['shutdown'] = HandleShutdown
def _handle_request(self, method, params):
if (self.handlers.has_key(method)):
return self.handlers[method](self, params)
else:
if method not in self.handlers:
raise APIError(20, 'Invalid method: %s' % method)
return self.handlers[method](self, params)
def _dispatch(self, method, params):
self.cookies = []
@ -1068,4 +1295,5 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
return "API Error 0026: Data contains a malformed varint. Some details: %s" % e
except Exception as e:
logger.exception(e)
return "API Error 0021: Unexpected API Failure - %s" % str(e)
return "API Error 0021: Unexpected API Failure - %s" % e

View File

@ -1,50 +1,65 @@
# -*- coding: utf-8 -*-
'''
"""
Logging and debuging facility
=============================
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.
WARNING An indication that something unexpected happened, or indicative of some problem in the
near future (e.g. disk space low). The software is still working as expected.
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.
WARNING An indication that something unexpected happened, or indicative
of some problem in the near future (e.g. disk space low).
The software is still working as expected.
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`.
Use: `from debug import logger` to import this facility into whatever module you wish to log messages from.
Logging is thread-safe so you don't have to worry about locks, just import and log.
'''
Use: `from debug import logger` to import this facility into whatever module
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.config
import os
import sys
import helper_startup
import state
helper_startup.loadConfig()
# Now can be overriden from a config file, which uses standard python logging.config.fileConfig interface
# examples are here: https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163
# Now can be overriden from a config file, which uses standard python
# logging.config.fileConfig interface
# examples are here:
# https://bitmessage.org/forum/index.php/topic,4820.msg11163.html#msg11163
log_level = 'WARNING'
def log_uncaught_exceptions(ex_cls, ex, tb):
logging.critical('Unhandled exception', exc_info=(ex_cls, ex, tb))
def configureLogging():
have_logging = False
try:
logging.config.fileConfig(os.path.join (state.appdata, 'logging.dat'))
logging.config.fileConfig(os.path.join(state.appdata, 'logging.dat'))
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:
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 sys.exc_info()
print(
'Failed to load logger configuration from %s, using default'
' logging config\n%s' %
(os.path.join(state.appdata, 'logging.dat'), sys.exc_info()))
else:
# no need to confuse the user if the logger config is missing entirely
print "Using default logger configuration"
# no need to confuse the user if the logger config
# is missing entirely
print('Using default logger configuration')
sys.excepthook = log_uncaught_exceptions
if have_logging:
@ -69,7 +84,7 @@ def configureLogging():
'formatter': 'default',
'level': log_level,
'filename': state.appdata + 'debug.log',
'maxBytes': 2097152, # 2 MiB
'maxBytes': 2097152, # 2 MiB
'backupCount': 1,
'encoding': 'UTF-8',
}
@ -77,15 +92,15 @@ def configureLogging():
'loggers': {
'console_only': {
'handlers': ['console'],
'propagate' : 0
'propagate': 0
},
'file_only': {
'handlers': ['file'],
'propagate' : 0
'propagate': 0
},
'both': {
'handlers': ['console', 'file'],
'propagate' : 0
'propagate': 0
},
},
'root': {
@ -95,8 +110,9 @@ def configureLogging():
})
return True
# TODO (xj9): Get from a config file.
#logger = logging.getLogger('console_only')
# logger = logging.getLogger('console_only')
if configureLogging():
if '-c' in sys.argv:
logger = logging.getLogger('file_only')
@ -105,6 +121,7 @@ if configureLogging():
else:
logger = logging.getLogger('default')
def restartLoggingInUpdatedAppdataLocation():
global logger
for i in list(logger.handlers):
@ -118,4 +135,3 @@ def restartLoggingInUpdatedAppdataLocation():
logger = logging.getLogger('both')
else:
logger = logging.getLogger('default')