This commit is contained in:
william 2015-01-31 22:31:50 -05:00
commit 6bf1eb74cd
2 changed files with 520 additions and 415 deletions

View File

@ -14,6 +14,7 @@ if __name__ == "__main__":
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import json import json
import re
import shared import shared
import time import time
@ -21,7 +22,7 @@ import time
import hashlib import hashlib
from helper_api import _handle_request from helper_api import _handle_request
from addresses import decodeAddress,addBMIfNotPresent,decodeVarint,calculateInventoryHash,varintDecodeError
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
from struct import pack from struct import pack
@ -74,6 +75,9 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
# SimpleXMLRPCDispatcher. To maintain backwards compatibility, # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
# check to see if a subclass implements _dispatch and dispatch # check to see if a subclass implements _dispatch and dispatch
# using that method if present. # using that method if present.
from pprint import pprint
print self.headers['Content-type']
response = self.server._marshaled_dispatch( response = self.server._marshaled_dispatch(
data, getattr(self, '_dispatch', None) data, getattr(self, '_dispatch', None)
) )
@ -151,13 +155,18 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
time.sleep(2) time.sleep(2)
return "RPC Username or password incorrect or HTTP header lacks authentication at all." return "RPC Username or password incorrect or HTTP header lacks authentication at all."
if method in dir( _handle_request ): if method in dir( _handle_request ):
logger.warn( 'Found "{}" in API'.format( method ) ) logger.warn( 'Found "{}" in API'.format( method ) )
try: try:
statusCode, data = object.__getattribute__( _handle_request, method )( self, *params ) statusCode, data = object.__getattribute__( _handle_request, method )( self, *params )
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
else:
statusCode = 404
data = "Method not found"
if statusCode != 200:
data = { 'error': data }
response = { response = {
'data': data, 'data': data,
@ -165,14 +174,3 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
'method': method 'method': method
} }
return json.dumps( response ) return json.dumps( response )
# try:
# return self._handle_request(method, params)
# except APIError as e:
# return str(e)
# except varintDecodeError as e:
# logger.error(e)
# 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)

View File

@ -15,14 +15,50 @@ from pyelliptic.openssl import OpenSSL
str_chan = '[chan]' str_chan = '[chan]'
def sentMessage( query ):
data = []
for row in query:
data.append( {
'msgid': row[0].encode( 'hex' ),
'toAddress': row[1],
'fromAddress': row[2],
'subject': shared.fixPotentiallyInvalidUTF8Data( row[3].encode( 'base64' ) ),
'message': shared.fixPotentiallyInvalidUTF8Data( row[4].encode( 'base64' ) ),
'encodingType': row[5],
'lastactiontime': row[6],
'status': row[7],
'ackdata': row[8].endcode( 'hex' ),
} )
return data
def recievedMessage( query ):
data = []
for row in query:
data.append( {
'msgid': row[0].encode( 'hex' ),
'toAddress': row[1],
'fromAddress': row[2],
'subject': shared.fixPotentiallyInvalidUTF8Data( row[3].encode( 'base64' ) ),
'message': shared.fixPotentiallyInvalidUTF8Data( row[4].encode( 'base64' ) ),
'encodingType': row[5],
'receivedTime': row[6],
'read': row[7],
} )
return data
class _handle_request( object ): class _handle_request( object ):
def ping( self, *args ): def ping( self, *args ):
data = { 'pong': args } data = { 'pong': args }
return 200, data return 200, data
def statusBar( self, *args ): def statusBar( self, *args ):
if not args:
return 0, 'Need status message!'
message, = args message, = args
shared.UISignalQueue.put( ('updateStatusBar', message) ) shared.UISignalQueue.put( ('updateStatusBar', message) ) # does this need to be encoded before transmission?
return 200, True return 200, True
def listAddresses( self, *args ): def listAddresses( self, *args ):
@ -36,8 +72,8 @@ class _handle_request( object ):
chan = shared.config.getboolean( addressInKeysFile, 'chan' ) chan = shared.config.getboolean( addressInKeysFile, 'chan' )
else: else:
chan = False chan = False
label = shared.config.get( addressInKeysFile, 'label' ).encode( 'base64' )
label = shared.config.get( addressInKeysFile, 'label' ).encode( 'base64' )
data.append( { data.append( {
'label': label, 'label': label,
'address': addressInKeysFile, 'address': addressInKeysFile,
@ -53,7 +89,7 @@ class _handle_request( object ):
# if address book is empty, return nothing and stop for loop from firing. # if address book is empty, return nothing and stop for loop from firing.
if not queryreturn: if not queryreturn:
return data return 200, data
for row in queryreturn: for row in queryreturn:
label, address = row label, address = row
@ -65,8 +101,6 @@ class _handle_request( object ):
return 200, data return 200, data
''' test below this line '''
def addAddressBookEntry( self, *args ): ## fix verifyAddress! def addAddressBookEntry( self, *args ): ## fix verifyAddress!
if len( args ) != 2: if len( args ) != 2:
return 0, "I need label and address" return 0, "I need label and address"
@ -99,9 +133,8 @@ class _handle_request( object ):
shared.UISignalQueue.put( ( 'rerenderAddressBook','' ) ) shared.UISignalQueue.put( ( 'rerenderAddressBook','' ) )
return 200, "Deleted address book entry for %s if it existed" % address return 200, "Deleted address book entry for %s if it existed" % address
''' not tested above this line '''
def createRandomAddress( self, *args ): def createRandomAddress( self, *args ):
if not args: if len( args ) not in [1,2,3,4]:
return 0, 'I need parameters!' return 0, 'I need parameters!'
if len( args ) == 1: if len( args ) == 1:
@ -129,7 +162,8 @@ class _handle_request( object ):
elif len( args ) == 3: elif len( args ) == 3:
label, eighteenByteRipe, totalDifficulty = args label, eighteenByteRipe, totalDifficulty = args
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty
)
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'bitmessagesettings',
'defaultpayloadlengthextrabytes' 'defaultpayloadlengthextrabytes'
@ -137,9 +171,11 @@ class _handle_request( object ):
elif len( args ) == 4: elif len( args ) == 4:
label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = args label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = args
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty
)
payloadLengthExtraBytes = int( payloadLengthExtraBytes = int(
shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty) shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty
)
else: else:
return 0, 'Too many parameters!' return 0, 'Too many parameters!'
@ -162,7 +198,6 @@ class _handle_request( object ):
nonceTrialsPerByte, nonceTrialsPerByte,
payloadLengthExtraBytes payloadLengthExtraBytes
) ) ) )
data = { data = {
'address': shared.apiAddressGeneratorReturnQueue.get(), 'address': shared.apiAddressGeneratorReturnQueue.get(),
'label': label 'label': label
@ -170,7 +205,7 @@ class _handle_request( object ):
return 200, data return 200, data
def createDeterministicAddresses( self, *args ): # needs to be tested def createDeterministicAddresses( self, *args ): # needs to be tested
if not args: if len( args ) not in range( 1,7 ):
return 0, 'I need parameters!' return 0, 'I need parameters!'
if len( args ) == 1: if len( args ) == 1:
@ -236,7 +271,8 @@ class _handle_request( object ):
elif len( args ) == 6: elif len( args ) == 6:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = args passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = args
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty
)
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'bitmessagesettings',
'defaultpayloadlengthextrabytes' 'defaultpayloadlengthextrabytes'
@ -244,9 +280,11 @@ class _handle_request( object ):
elif len( args ) == 7: elif len( args ) == 7:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = args passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = args
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty
)
payloadLengthExtraBytes = int( payloadLengthExtraBytes = int(
shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty) shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty
)
else: else:
return 0, 'Too many parameters!' return 0, 'Too many parameters!'
@ -276,7 +314,10 @@ class _handle_request( object ):
return 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.' return 5, 'You have (accidentally?) specified too many addresses to make. Maximum 999. This check only exists to prevent mischief; if you really want to create more addresses than this, contact the Bitmessage developers and we can modify the check or you can do it yourself by searching the source code for this message.'
shared.apiAddressGeneratorReturnQueue.queue.clear() shared.apiAddressGeneratorReturnQueue.queue.clear()
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses) logger.debug(
'Requesting that the addressGenerator create %s addresses.',
numberOfAddresses
)
shared.addressGeneratorQueue.put( ( shared.addressGeneratorQueue.put( (
'createDeterministicAddresses', 'createDeterministicAddresses',
addressVersionNumber, addressVersionNumber,
@ -290,6 +331,7 @@ class _handle_request( object ):
) ) ) )
data = [] data = []
queueReturn = shared.apiAddressGeneratorReturnQueue.get() queueReturn = shared.apiAddressGeneratorReturnQueue.get()
for item in queueReturn: for item in queueReturn:
data.append( item ) data.append( item )
@ -314,7 +356,10 @@ class _handle_request( object ):
return 3, ' The stream number must be 1. Others aren\'t supported.' return 3, ' The stream number must be 1. Others aren\'t supported.'
shared.apiAddressGeneratorReturnQueue.queue.clear() shared.apiAddressGeneratorReturnQueue.queue.clear()
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses) logger.debug(
'Requesting that the addressGenerator create %s addresses.',
numberOfAddresses
)
shared.addressGeneratorQueue.put( ( shared.addressGeneratorQueue.put( (
'getDeterministicAddress', 'getDeterministicAddress',
addressVersionNumber, addressVersionNumber,
@ -324,11 +369,12 @@ class _handle_request( object ):
passphrase, passphrase,
eighteenByteRipe eighteenByteRipe
) ) ) )
return 200, shared.apiAddressGeneratorReturnQueue.get() return 200, shared.apiAddressGeneratorReturnQueue.get()
def createChan( self, *args ): def createChan( self, *args ):
if not args: if len( args ) != 1:
return 0, 'I need parameters.' return 0, 'Passphrase needed!'
if len( args ) == 1: if len( args ) == 1:
passphrase, = args passphrase, = args
@ -336,6 +382,7 @@ class _handle_request( object ):
passphrase = self._decode( passphrase, "base64" ) passphrase = self._decode( passphrase, "base64" )
if len( passphrase ) == 0: if len( passphrase ) == 0:
return 1, 'The specified passphrase is blank.' return 1, 'The specified passphrase is blank.'
# It would be nice to make the label the passphrase but it is # It would be nice to make the label the passphrase but it is
# possible that the passphrase contains non-utf-8 characters. -wtf! # possible that the passphrase contains non-utf-8 characters. -wtf!
try: try:
@ -347,7 +394,10 @@ class _handle_request( object ):
addressVersionNumber = 4 addressVersionNumber = 4
streamNumber = 1 streamNumber = 1
shared.apiAddressGeneratorReturnQueue.queue.clear() shared.apiAddressGeneratorReturnQueue.queue.clear()
logger.debug('Requesting that the addressGenerator create chan %s.', passphrase) logger.debug(
'Requesting that the addressGenerator create chan %s.',
passphrase
)
shared.addressGeneratorQueue.put( ( shared.addressGeneratorQueue.put( (
'createChan', 'createChan',
addressVersionNumber, addressVersionNumber,
@ -358,11 +408,13 @@ class _handle_request( object ):
queueReturn = shared.apiAddressGeneratorReturnQueue.get() queueReturn = shared.apiAddressGeneratorReturnQueue.get()
if len( queueReturn ) == 0: if len( queueReturn ) == 0:
return 24, 'Chan address is already present.' return 24, 'Chan address is already present.'
address = queueReturn[0] address = queueReturn[0]
data = { data = {
'address': address, 'address': address,
'label': label 'label': label
} }
return 200, data return 200, data
def joinChan( self, *args ): def joinChan( self, *args ):
@ -421,7 +473,7 @@ class _handle_request( object ):
return 200, {} return 200, {}
def deleteAddress( self, *args ): def deleteAddress( self, *args ):
if len( args ) != 0: if len( args ) != 1:
return 0, 'I need parameters.' return 0, 'I need parameters.'
address, = args address, = args
@ -439,384 +491,425 @@ class _handle_request( object ):
return 200, {} return 200, {}
def getAllInboxMessages( self, *args ): def getAllInboxMessages( self, *args ):
queryreturn = sqlQuery('''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, received, read FROM inbox where folder='inbox' ORDER BY received''') queryreturn = sqlQuery(
# data = rowMessage( queryreturn ) '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, received, read FROM inbox where folder='inbox' ORDER BY received'''
print queryreturn )
return 200, queryreturn data = recievedMessage( queryreturn )
return 200, data
# def getAllInboxMessageIDs( self, *args ): def getAllInboxMessageIDs( self, *args ):
# 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 = [] )
# for row in queryreturn: data = []
# msgid = row[0] for row in queryreturn:
# data.append({ msgid = row[0]
# 'msgid': msgid.encode('hex') data.append( {
# }) 'msgid': msgid.encode( 'hex' )
} )
# return 200, data return 200, data
# def getInboxMessageByID( self, *args ): def getInboxMessageByID( self, *args ):
# if len( args ) not in range(1,2): if len( args ) not in [1,2]:
# return 0, 'I need parameters!' return 0, 'Missing message id'
# if len(args) == 1: if len( args ) == 1:
# msgid = self._decode(args[0], "hex") msgid = self._decode( args[0], "hex" )
# elif len(args) >= 2:
# msgid = self._decode(args[0], "hex")
# readStatus = args[1]
# if not isinstance(readStatus, bool):
# return 23, 'Bool expected in readStatus, saw %s instead.' % type(readStatus)
# queryreturn = sqlQuery('''SELECT read FROM inbox WHERE msgid=?''', msgid) elif len( args ) >= 2:
# # UPDATE is slow, only update if status is different msgid = self._decode( args[0], "hex" )
# if queryreturn != [] and (queryreturn[0][0] == 1) != readStatus: readStatus = args[1]
# sqlExecute('''UPDATE inbox set read = ? WHERE msgid=?''', readStatus, msgid) if not isinstance( readStatus, bool ):
# shared.UISignalQueue.put(('changedInboxUnread', None)) return 23, 'Bool expected in readStatus, saw %s instead.' % type( readStatus )
# queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox WHERE msgid=?''', msgid) queryreturn = sqlQuery( '''SELECT read FROM inbox WHERE msgid=?''', msgid )
# data = rowMessage( queryreturn ) # UPDATE is slow, only update if status is different
if queryreturn != [] and ( queryreturn[0][0] == 1 ) != readStatus:
sqlExecute( '''UPDATE inbox set read = ? WHERE msgid=?''', readStatus, msgid )
shared.UISignalQueue.put( ( 'changedInboxUnread', None ) )
# return 200, data queryreturn = sqlQuery(
'''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, received, read FROM inbox WHERE msgid=?''',
msgid
)
data = recievedMessage( queryreturn )
return 200, data
def getAllSentMessages( self, *args ): def getAllSentMessages( self, *args ):
queryreturn = sqlQuery('''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, lastactiontime, status, ackdata FROM sent where folder='sent' ORDER BY lastactiontime''') queryreturn = sqlQuery(
print queryreturn '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, lastactiontime, status, ackdata FROM sent where folder='sent' ORDER BY lastactiontime'''
data = [] )
# for row in queryreturn: data = sentMessage( queryreturn )
# msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
# subject = shared.fixPotentiallyInvalidUTF8Data(subject)
# message = shared.fixPotentiallyInvalidUTF8Data(message)
# data.append({
# 'msgid':msgid.encode('hex'),
# 'toAddress':toAddress,
# 'fromAddress':fromAddress,
# 'subject':subject.encode('base64'),
# 'message':message.encode('base64'),
# 'encodingType':encodingtype,
# 'lastActionTime':lastactiontime,
# 'status':status,
# 'ackData':ackdata.encode('hex')
# })
return 200, queryreturn return 200, queryreturn
# def getAllSentMessageIDs( self, *args ): # undocumented def getAllSentMessageIDs( self, *args ): # undocumented
# 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 = [] data = []
# for row in queryreturn: for row in queryreturn:
# msgid = row[0] msgid = row[0]
# data.append({ 'msgid':msgid.encode('hex') }) data.append( { 'msgid':msgid.encode( 'hex' ) } )
# return 200, data return 200, data
# def getInboxMessagesByToAddress( self, *args ): # renamed from getInboxMessagesByReceiver / undocumented def getInboxMessagesByToAddress( self, *args ): # renamed from getInboxMessagesByReceiver / undocumented
# if len( args ) == 0: if len( args ) != 1:
# return 0, 'I need parameters!' return 0, 'I need parameters!'
# toAddress = args[0] toAddress, = args
# queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, received, message, encodingtype, read FROM inbox WHERE folder='inbox' AND toAddress=?''', toAddress) queryreturn = sqlQuery(
# data = rowMessage( queryreturn ) '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, received, read FROM inbox WHERE folder='inbox' AND toAddress=?''',
# return 200, data toAddress
)
data = recievedMessage( queryreturn )
# def getSentMessagesBySender( self, *args ): return 200, data
# if len( args ) == 0:
# return 0, 'I need parameters!'
# fromAddress = args[0]
# queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE folder='sent' AND fromAddress=? ORDER BY lastactiontime''',
# fromAddress)
# data = []
# for row in queryreturn:
# msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row
# subject = shared.fixPotentiallyInvalidUTF8Data(subject)
# message = shared.fixPotentiallyInvalidUTF8Data(message)
# data.append({'msgid':msgid.encode('hex'), 'toAddress':toAddress, 'fromAddress':fromAddress, 'subject':subject.encode('base64'), 'message':message.encode('base64'), 'encodingType':encodingtype, 'lastActionTime':lastactiontime, 'status':status, 'ackData':ackdata.encode('hex')}, indent=4, separators=(',', ': '))
# return data
# def getSentMessageByID( self, *args ): def getSentMessagesBySender( self, *args ):
# if len( args ) == 0: if len( args ) != 1:
# return 0, 'I need parameters!' return 0, 'I need parameters!'
# msgid = self._decode( args[0], "hex") fromAddress, = args
# queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE msgid=?''', msgid) queryreturn = sqlQuery(
# data = [] '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, lastactiontime, status, ackdata FROM sent WHERE folder='sent' AND fromAddress=? ORDER BY lastactiontime''',
# for row in queryreturn: fromAddress
# msgid, toAddress, fromAddress, subject, lastactiontime, message, encodingtype, status, ackdata = row )
# subject = shared.fixPotentiallyInvalidUTF8Data(subject) data = sentMessage( queryreturn )
# message = shared.fixPotentiallyInvalidUTF8Data(message)
# data.append({
# 'msgid':msgid.encode('hex'),
# 'toAddress':toAddress,
# 'fromAddress':fromAddress,
# 'subject':subject.encode('base64'),
# 'message':message.encode('base64'),
# 'encodingType':encodingtype,
# 'lastActionTime':lastactiontime,
# 'status':status,
# 'ackData':ackdata.encode('hex')
# })
# return 200, data return 200, data
# def getSentMessageByAckData( self, *args ): def getSentMessageByID( self, *args ):
# if len( args ) == 0: if len( args ) != 1:
# return 0, 'I need parameters!' return 0, 'I need parameters!'
# ackData = self._decode( args[0], "hex" )
# queryreturn = sqlQuery('''SELECT msgid, toaddress, fromaddress, subject, lastactiontime, message, encodingtype, status, ackdata FROM sent WHERE ackdata=?''',
# ackData)
# data = sentMessageRow( queryreturn )
# return data
# def trashMessage( self, *args ): msgid = self._decode( args[0], "hex" )
# if len( args ) == 0: queryreturn = sqlQuery(
# return 0, 'I need parameters!' '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, lastactiontime, status, ackdata FROM sent WHERE msgid=?''',
# msgid = self._decode(args[0], "hex") msgid
)
data = sentMessage( queryreturn )
# # Trash if in inbox table return 200, data
# helper_inbox.trash(msgid)
# # Trash if in sent table
# sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid)
# return 200, 'Trashed message (assuming message existed).'
# def trashInboxMessage( self, *args ): def getSentMessageByAckData( self, *args ):
# if len( args ) == 0: if len( args ) != 1:
# return 0, 'I need parameters!' return 0, 'I need parameters!'
# msgid = self._decode(args[0], "hex")
# helper_inbox.trash(msgid)
# return 200, 'Trashed inbox message (assuming message existed).'
# def trashInboxMessage( self, *args ): ackData = self._decode( args[0], "hex" )
# if len( args ) == 0: queryreturn = sqlQuery(
# return 0, 'I need parameters!' '''SELECT msgid, toAddress, fromAddress, subject, message, encodingtype, lastactiontime, status, ackdata FROM sent WHERE ackdata=?''',
# msgid = self._decode(args[0], "hex") ackData
# helper_inbox.trash(msgid) )
# return 200, 'Trashed inbox message (assuming message existed).' data = sentMessage( queryreturn )
# def trashSentMessage( self, *args ): return 200, data
# if len( args ) == 0:
# return 0, 'I need parameters!'
# msgid = self._decode(args[0], "hex")
# sqlExecute('''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid)
# return 200, 'Trashed sent message (assuming message existed).'
# def trashSentMessageByAckData( self, *args ): def trashMessage( self, *args ):
# # This API method should only be used when msgid is not available if len( args ) != 1:
# if len( args ) == 0: return 0, 'I need parameters!'
# return 0, 'I need parameters!'
# ackdata = self._decode(args[0], "hex")
# sqlExecute('''UPDATE sent SET folder='trash' WHERE ackdata=?''',
# ackdata)
# return 200, 'Trashed sent message (assuming message existed).'
# def sendMessage( self, *args ): msgid = self._decode( args[0], "hex" )
# if len( args ) not in [4,5]:
# return 0, 'I need parameters!'
# elif len( args ) == 4: # Trash if in inbox table
# toAddress, fromAddress, subject, message = args helper_inbox.trash(msgid)
# encodingType = 2 # Trash if in sent table
# elif len( args ) == 5: sqlExecute( '''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid )
# toAddress, fromAddress, subject, message, encodingType = args return 200, 'Trashed message (assuming message existed).'
# if encodingType != 2: def trashInboxMessage( self, *args ):
# return 6, 'The encoding type must be 2 because that is the only one this program currently supports.' if len( args ) != 1:
return 0, 'I need parameters!'
# subject = self._decode(subject, "base64") msgid = self._decode( args[0], "hex" )
# message = self._decode(message, "base64") helper_inbox.trash( msgid )
# if len(subject + message) > (2 ** 18 - 500):
# return 27, 'Message is too long.'
# toAddress = addBMIfNotPresent(toAddress) return 200, 'Trashed inbox message (assuming message existed).'
# fromAddress = addBMIfNotPresent(fromAddress)
# status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(toAddress)
# self._verifyAddress(fromAddress)
# try:
# fromAddressEnabled = shared.config.getboolean(
# fromAddress, 'enabled')
# except:
# return 13, 'Could not find your fromAddress in the keys.dat file.'
# if not fromAddressEnabled: def trashInboxMessage( self, *args ):
# return 14, 'Your fromAddress is disabled. Cannot send.' if len( args ) != 1:
return 0, 'I need parameters!'
# ackdata = OpenSSL.rand(32) msgid = self._decode( args[0], "hex" )
helper_inbox.trash( msgid )
# t = ('', toAddress, toRipe, fromAddress, subject, message, ackdata, int( return 200, 'Trashed inbox message (assuming message existed).'
# time.time()), 'msgqueued', 1, 1, 'sent', 2)
# helper_sent.insert(t)
# toLabel = '' def trashSentMessage( self, *args ):
# queryreturn = sqlQuery('''select label from addressbook where address=?''', toAddress) if len( args ) != 1:
# if queryreturn != []: return 0, 'I need parameters!'
# for row in queryreturn:
# toLabel, = row
# # apiSignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata)))
# shared.UISignalQueue.put(('displayNewSentMessage', (
# toAddress, toLabel, fromAddress, subject, message, ackdata)))
# shared.workerQueue.put(('sendmessage', toAddress)) msgid = self._decode( args[0], "hex" )
sqlExecute( '''UPDATE sent SET folder='trash' WHERE msgid=?''', msgid )
# return 200, ackdata.encode('hex') return 200, 'Trashed sent message (assuming message existed).'
# def sendBroadcast( self, *args ): def trashSentMessageByAckData( self, *args ):
# if len(params) not in [3,4]: # This API method should only be used when msgid is not available
# return 0, 'I need parameters!' if len( args ) != 1:
return 0, 'I need parameters!'
# if len( args ) == 3: ackdata = self._decode (args[0], "hex" )
# fromAddress, subject, message = args sqlExecute( '''UPDATE sent SET folder='trash' WHERE ackdata=?''', ackdata )
# encodingType = 2
# elif len(params) == 4:
# fromAddress, subject, message, encodingType = args
# if encodingType != 2: return 200, 'Trashed sent message (assuming message existed).'
# return 6, 'The encoding type must be 2 because that is the only one this program currently supports.'
# subject = self._decode(subject, "base64") def sendMessage( self, *args ):
# message = self._decode(message, "base64") if len( args ) not in [4,5]:
# if len(subject + message) > (2 ** 18 - 500): return 0, 'I need parameters!'
# return 27, 'Message is too long.'
# fromAddress = addBMIfNotPresent(fromAddress) elif len( args ) == 4:
# self._verifyAddress(fromAddress) toAddress, fromAddress, subject, message = args
# try: encodingType = 2
# fromAddressEnabled = shared.config.getboolean( elif len( args ) == 5:
# fromAddress, 'enabled') toAddress, fromAddress, subject, message, encodingType = args
# except:
# return 13, 'could not find your fromAddress in the keys.dat file.'
# ackdata = OpenSSL.rand(32) if encodingType != 2:
# toAddress = '[Broadcast subscribers]' return 6, 'The encoding type must be 2 because that is the only one this program currently supports.'
# ripe = ''
# t = ('', toAddress, ripe, fromAddress, subject, message, ackdata, int( subject = self._decode( subject, "base64" )
# time.time()), 'broadcastqueued', 1, 1, 'sent', 2) message = self._decode( message, "base64" )
# helper_sent.insert(t) if len( subject + message ) > ( 2 ** 18 - 500 ):
return 27, 'Message is too long.'
# toLabel = '[Broadcast subscribers]' toAddress = addBMIfNotPresent( toAddress )
# shared.UISignalQueue.put(('displayNewSentMessage', ( fromAddress = addBMIfNotPresent( fromAddress )
# toAddress, toLabel, fromAddress, subject, message, ackdata))) status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress( toAddress )
# shared.workerQueue.put(('sendbroadcast', '')) self._verifyAddress( fromAddress )
try:
fromAddressEnabled = shared.config.getboolean( fromAddress, 'enabled' )
except:
return 13, 'Could not find your fromAddress in the keys.dat file.'
# return 200, ackdata.encode('hex') if not fromAddressEnabled:
return 14, 'Your fromAddress is disabled. Cannot send.'
# def getStatus( self, *args ): ackdata = OpenSSL.rand( 32 )
# if len( args ) != 1:
# return 0, 'I need one parameter!'
# ackdata, = args sendData = (
# if len(ackdata) != 64: '',
# return 15, 'The length of ackData should be 32 bytes (encoded in hex thus 64 characters).' toAddress,
toRipe,
fromAddress,
subject,
message,
ackdata, int( time.time() ),
'msgqueued',
1,
1,
'sent',
2
)
helper_sent.insert( sendData )
# ackdata = self._decode(ackdata, "hex") toLabel = ''
# queryreturn = sqlQuery( queryreturn = sqlQuery( '''select label from addressbook where address=?''', toAddress )
# '''SELECT status FROM sent where ackdata=?''', if queryreturn != []:
# ackdata) for row in queryreturn:
# if queryreturn == []: toLabel, = row
# return 404, 'notfound'
# for row in queryreturn:
# status, = row
# return 200, status
# def addSubscription( self, *args ): # apiSignalQueue.put(('displayNewSentMessage',(toAddress,toLabel,fromAddress,subject,message,ackdata)))
# if len( args ) not in [1,2]: shared.UISignalQueue.put( (
# return 0, 'I need parameters!' 'displayNewSentMessage',
(
toAddress,
toLabel,
fromAddress,
subject,
message,
ackdata
)
) )
shared.workerQueue.put( ( 'sendmessage', toAddress ) )
# if len( args ) == 1: return 200, ackdata.encode( 'hex' )
# address, = args
# label = ''
# if len( args ) == 2:
# address, label = args
# label = self._decode(label, "base64")
# try:
# unicode(label, 'utf-8')
# except:
# return 17, 'Label is not valid UTF-8 data.'
# address = addBMIfNotPresent(address) def sendBroadcast( self, *args ):
# self._verifyAddress(address) if len( args ) not in [3,4]:
# # First we must check to see if the address is already in the return 0, 'I need parameters!'
# # subscriptions list.
# queryreturn = sqlQuery('''select * from subscriptions where address=?''', address)
# if queryreturn != []:
# return 16, 'You are already subscribed to that address.'
# sqlExecute('''INSERT INTO subscriptions VALUES (?,?,?)''',label, address, True)
# shared.reloadBroadcastSendersForWhichImWatching()
# shared.UISignalQueue.put(('rerenderInboxFromLabels', ''))
# shared.UISignalQueue.put(('rerenderSubscriptions', ''))
# return 200, 'Added subscription.'
# def addAddressToBlackWhiteList( self, *args ): if len( args ) == 3:
# if len(params) not in [1,2]: fromAddress, subject, message = args
# return 0, 'I need parameters!' encodingType = 2
elif len( args ) == 4:
fromAddress, subject, message, encodingType = args
# if len( args ) == 1: if encodingType != 2:
# address, = args return 6, 'The encoding type must be 2 because that is the only one this program currently supports.'
# label = ''
# if len( args ) == 2: subject = self._decode( subject, "base64" )
# address, label = args message = self._decode( message, "base64" )
# label = self._decode(label, "base64") if len( subject + message ) > ( 2 ** 18 - 500 ):
# try: return 27, 'Message is too long.'
# unicode(label, 'utf-8')
# except:
# return 17, 'Label is not valid UTF-8 data.'
# if len( args ) > 2: fromAddress = addBMIfNotPresent( fromAddress )
# return 0, 'I need either 1 or 2 parameters!' self._verifyAddress( fromAddress )
try:
fromAddressEnabled = shared.config.getboolean( fromAddress, 'enabled' )
except:
return 13, 'could not find your fromAddress in the keys.dat file.'
# address = addBMIfNotPresent(address) ackdata = OpenSSL.rand( 32 )
# self._verifyAddress(address) toAddress = '[Broadcast subscribers]'
ripe = ''
# table = '' sendData = (
# if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': '',
# table = 'blacklist' toAddress,
# else: ripe,
# table = 'whitelist' fromAddress,
subject,
message,
ackdata, int( time.time() ),
'broadcastqueued',
1,
1,
'sent',
2
)
helper_sent.insert( sendData )
# # First we must check to see if the address is already in the toLabel = '[Broadcast subscribers]'
# # black-/white-list. shared.UISignalQueue.put( (
# queryreturn = sqlQuery('''select * from '''+table+''' where address=?''', address) 'displayNewSentMessage',
# if queryreturn != []: (
# return 28, 'You have already black-/white-listed that address.' toAddress,
toLabel,
fromAddress,
subject,
message,
ackdata
)
) )
shared.workerQueue.put( ( 'sendbroadcast', '' ) )
# sqlExecute('''INSERT INTO '''+table+''' VALUES (?,?,?)''',label, address, True) return 200, ackdata.encode( 'hex' )
# shared.UISignalQueue.put(('rerenderBlackWhiteList', ''))
# return 200, 'Added black-/white-list entry.' def getStatus( self, *args ):
if len( args ) != 1:
return 0, 'I need one parameter!'
# def removeAddressFromBlackWhiteList': ackdata, = args
# if len( args ) != 1: if len(ackdata) != 64:
# return 0, 'I need 1 parameter!' return 15, 'The length of ackData should be 32 bytes (encoded in hex thus 64 characters).'
# address, = args ackdata = self._decode( ackdata, "hex" )
# address = addBMIfNotPresent(address) queryreturn = sqlQuery(
'''SELECT status FROM sent where ackdata=?''',
ackdata)
if queryreturn == []:
return 404, 'notfound'
# table = '' for row in queryreturn:
# if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': status, = row
# table = 'blacklist'
# else:
# table = 'whitelist'
# # First we must check to see if the address is already in the return 200, status
# # black-/white-list.
# queryreturn = sqlQuery('''select * from '''+table+''' where address=?''', address)
# if queryreturn == []:
# return 29, 'That entry does not exist in the black-/white-list.'
# sqlExecute('''DELETE FROM '''+table+''' WHERE address=?''', address) def addSubscription( self, *args ):
# shared.UISignalQueue.put(('rerenderBlackWhiteList', '')) if len( args ) not in [1,2]:
# return 200, 'Deleted black-/white-list entry if it existed.' return 0, 'I need parameters!'
# def deleteSubscription( self, *args): if len( args ) == 1:
# if len( args ) != 1: address, = args
# return 0, 'I need 1 parameter!' label = ''
if len( args ) == 2:
address, label = args
label = self._decode( label, "base64" )
try:
unicode( label, 'utf-8' )
except:
return 17, 'Label is not valid UTF-8 data.'
# address, = args address = addBMIfNotPresent( address )
# address = addBMIfNotPresent(address) self._verifyAddress( address )
# sqlExecute('''DELETE FROM subscriptions WHERE address=?''', address) # First we must check to see if the address is already in the
# shared.reloadBroadcastSendersForWhichImWatching() # subscriptions list.
# shared.UISignalQueue.put(('rerenderInboxFromLabels', '')) queryreturn = sqlQuery( '''select * from subscriptions where address=?''', address )
# shared.UISignalQueue.put(('rerenderSubscriptions', '')) if queryreturn != []:
# return 200, 'Deleted subscription if it existed.' return 16, 'You are already subscribed to that address.'
sqlExecute( '''INSERT INTO subscriptions VALUES (?,?,?)''', label, address, True )
shared.reloadBroadcastSendersForWhichImWatching()
shared.UISignalQueue.put( ( 'rerenderInboxFromLabels', '' ) )
shared.UISignalQueue.put( ( 'rerenderSubscriptions', '' ) )
return 200, 'Added subscription.'
def addAddressToBlackWhiteList( self, *args ):
if len( args ) not in [1,2]:
return 0, 'I need parameters!'
if len( args ) == 1:
address, = args
label = ''
if len( args ) == 2:
address, label = args
label = self._decode( label, "base64" )
try:
unicode( label, 'utf-8' )
except:
return 17, 'Label is not valid UTF-8 data.'
if len( args ) > 2:
return 0, 'I need either 1 or 2 parameters!'
address = addBMIfNotPresent( address )
self._verifyAddress( address )
table = ''
if shared.config.get( 'bitmessagesettings', 'blackwhitelist' ) == 'black':
table = 'blacklist'
else:
table = 'whitelist'
# First we must check to see if the address is already in the
# black-/white-list.
queryreturn = sqlQuery( '''select * from '''+table+''' where address=?''', address )
if queryreturn != []:
return 28, 'You have already black-/white-listed that address.'
sqlExecute( '''INSERT INTO '''+table+''' VALUES (?,?,?)''',label, address, True )
shared.UISignalQueue.put( ( 'rerenderBlackWhiteList', '' ) )
return 200, 'Added black-/white-list entry.'
def removeAddressFromBlackWhiteList( self, *args ):
if len( args ) != 1:
return 0, 'I need 1 parameter!'
address, = args
address = addBMIfNotPresent( address )
table = ''
if shared.config.get( 'bitmessagesettings', 'blackwhitelist' ) == 'black':
table = 'blacklist'
else:
table = 'whitelist'
# First we must check to see if the address is already in the
# black-/white-list.
queryreturn = sqlQuery( '''select * from '''+table+''' where address=?''', address )
if queryreturn == []:
return 29, 'That entry does not exist in the black-/white-list.'
sqlExecute( '''DELETE FROM '''+table+''' WHERE address=?''', address )
shared.UISignalQueue.put( ( 'rerenderBlackWhiteList', '' ) )
return 200, 'Deleted black-/white-list entry if it existed.'
def deleteSubscription( self, *args):
if len( args ) != 1:
return 0, 'I need 1 parameter!'
address, = args
address = addBMIfNotPresent( address )
sqlExecute( '''DELETE FROM subscriptions WHERE address=?''', address )
shared.reloadBroadcastSendersForWhichImWatching()
shared.UISignalQueue.put( ( 'rerenderInboxFromLabels', '' ) )
shared.UISignalQueue.put( ( 'rerenderSubscriptions', '' ) )
return 200, 'Deleted subscription if it existed.'
def listSubscriptions( self, *args ): def listSubscriptions( self, *args ):
queryreturn = sqlQuery( '''SELECT label, address, enabled FROM subscriptions''' ) queryreturn = sqlQuery( '''SELECT label, address, enabled FROM subscriptions''' )
@ -829,6 +922,7 @@ class _handle_request( object ):
'address': address, 'address': address,
'enabled': enabled == 1 'enabled': enabled == 1
} ) } )
return 200, data return 200, data
def disseminatePreEncryptedMsg( self, *args ): def disseminatePreEncryptedMsg( self, *args ):
@ -867,7 +961,7 @@ class _handle_request( object ):
shared.broadcastToSendDataQueues(( shared.broadcastToSendDataQueues((
toStreamNumber, 'advertiseobject', inventoryHash)) toStreamNumber, 'advertiseobject', inventoryHash))
def disseminatePubkey': def disseminatePubkey( self, *args ):
# The device issuing this command to PyBitmessage supplies a pubkey object to be # The device issuing this command to PyBitmessage supplies a pubkey object to be
# disseminated to the rest of the Bitmessage network. PyBitmessage accepts this # 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 # pubkey object and sends it out to the rest of the Bitmessage network as if it
@ -915,15 +1009,18 @@ class _handle_request( object ):
if len( args ) != 1: if len( args ) != 1:
0, 'I need 1 parameter!' 0, 'I need 1 parameter!'
requestedHash, = args requestedHash, = args
if len(requestedHash) != 32: if len(requestedHash) != 32:
return 19, 'The length of hash should be 32 bytes (encoded in hex thus 64 characters).' return 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
@ -932,8 +1029,10 @@ class _handle_request( object ):
t = ( payload[readPosition:readPosition+32], hash01 ) t = ( payload[readPosition:readPosition+32], hash01 )
sql.execute('''UPDATE inventory SET tag=? WHERE hash=?; ''', *t) 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 = [] data = []
for row in queryreturn: for row in queryreturn:
payload, = row payload, = row
@ -950,11 +1049,15 @@ class _handle_request( object ):
if len(requestedHash) != 40: if len(requestedHash) != 40:
return 19, 'The length of hash should be 20 bytes (encoded in hex thus 40 characters).' return 19, 'The length of hash should be 20 bytes (encoded in hex thus 40 characters).'
requestedHash = self._decode( requestedHash, "hex" ) requestedHash = self._decode( requestedHash, "hex" )
queryreturn = sqlQuery('''SELECT transmitdata FROM pubkeys WHERE hash = ? ; ''', requestedHash) queryreturn = sqlQuery(
'''SELECT transmitdata FROM pubkeys WHERE hash = ? ; ''',
requestedHash
)
data = [] data = []
for row in queryreturn: for row in queryreturn:
transmitdata, = row transmitdata, = row
data.append( { 'data': transmitdata.encode('hex') } ) data.append( { 'data': transmitdata.encode('hex') } )
return 200, data return 200, data
def clientStatus( self, *args ): def clientStatus( self, *args ):
@ -964,6 +1067,7 @@ class _handle_request( object ):
networkStatus = 'connectedButHaveNotReceivedIncomingConnections' networkStatus = 'connectedButHaveNotReceivedIncomingConnections'
else: else:
networkStatus = 'connectedAndReceivingIncomingConnections' networkStatus = 'connectedAndReceivingIncomingConnections'
data = { data = {
'networkConnections': len( shared.connectedHostsList ), 'networkConnections': len( shared.connectedHostsList ),
'numberOfMessagesProcessed': shared.numberOfMessagesProcessed, 'numberOfMessagesProcessed': shared.numberOfMessagesProcessed,
@ -973,13 +1077,15 @@ class _handle_request( object ):
'softwareName': 'PyBitmessage', 'softwareName': 'PyBitmessage',
'softwareVersion': shared.softwareVersion 'softwareVersion': shared.softwareVersion
} }
return 200, data return 200, data
def decodeAddress( self, *args ): def decodeAddress( self, *args ):
# Return a meaningful decoding of an address. # Return a meaningful decoding of an address.
if len( args ) != 1: if len( args ) != 1:
return 0, 'I need 1 parameter!' return 0, 'I need 1 parameter!'
address, = params
address, = args
status, addressVersion, streamNumber, ripe = decodeAddress( address ) status, addressVersion, streamNumber, ripe = decodeAddress( address )
data = { data = {
'status': status, 'status': status,
@ -987,4 +1093,5 @@ class _handle_request( object ):
'streamNumber': streamNumber, 'streamNumber': streamNumber,
'ripe': ripe.encode( 'base64' ) 'ripe': ripe.encode( 'base64' )
} }
return 200, data return 200, data