flake8: api, debug
This commit is contained in:
parent
4610e1a0d7
commit
cb0996c6c8
624
src/api.py
624
src/api.py
|
@ -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
|
||||
|
|
64
src/debug.py
64
src/debug.py
|
@ -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')
|
||||
|