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 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,38 +855,42 @@ 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 = ('',
toAddress, toAddress,
toRipe, toRipe,
fromAddress, fromAddress,
subject, subject,
message, message,
ackdata, ackdata,
int(time.time()), # sentTime (this won't change) int(time.time()), # sentTime (this won't change)
int(time.time()), # lastActionTime int(time.time()), # lastActionTime
0, 0,
'msgqueued', 'msgqueued',
0, 0,
'sent', 'sent',
2, 2,
TTL) TTL)
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

View File

@ -1,50 +1,65 @@
# -*- 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
if have_logging: if have_logging:
@ -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')