Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 32 additions & 26 deletions bminterface.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import ConfigParser
import xmlrpclib
import json
from six.moves import configparser
from six.moves import xmlrpc_client
import datetime
import time
import email.utils
import os
import logging
from codecs import encode, decode

try:
SafeConfigParser = configparser.SafeConfigParser
except AttributeError:
SafeConfigParser = configparser.ConfigParser

purgeList = []
allMessages = []
Expand All @@ -17,7 +22,7 @@ def _getKeyLocation(): #make this not suck later
def _getConfig(keys):
return apiData()
#TODO make this work, so the above can be removed
config = ConfigParser.SafeConfigParser()
config = SafeConfigParser()
config.read(keys)
try:
api_port = config.getint('bitmessagesettings', 'apiport')
Expand All @@ -30,7 +35,7 @@ def _getConfig(keys):
return "http://"+api_uname+":"+api_passwd+"@"+api_iface+":"+str(api_port)+"/"

def _makeApi(keys):
return xmlrpclib.ServerProxy(_getConfig(keys))
return xmlrpc_client.ServerProxy(_getConfig(keys))

def _sendMessage(toAddress, fromAddress, subject, body):
api = _makeApi(_getKeyLocation())
Expand Down Expand Up @@ -73,8 +78,8 @@ def registerAddress(address):
def send(toAddress, fromAddress, subject, body):
toAddress = _stripAddress(toAddress)
fromAddress = _stripAddress(fromAddress)
subject = subject.encode('base64')
body = body.encode('base64')
subject = encode(subject.encode("utf-8", "replace"), 'base64').decode("utf-8", "replace")
body = encode(body.encode("utf-8", "replace"), 'base64').decode("utf-8", "replace")
if toAddress == 'broadcast':
return _sendBroadcast(fromAddress, subject, body)
else:
Expand All @@ -85,12 +90,13 @@ def _getAll():
global currentAddress
if not allMessages:
api = _makeApi(_getKeyLocation())
allMessages = json.loads(api.getAllInboxMessages())
allMessages = api.getAllInboxMessages()
logging.debug("current address is %s" % currentAddress)
if currentAddress is not None:
ret = []
cur_addr = currentAddress.decode("utf-8", "replace")
for msg in allMessages['inboxMessages']:
if msg['toAddress'] == currentAddress:
if msg['toAddress'] == cur_addr:
ret.append(msg)
return dict(inboxMessages=ret)
return allMessages
Expand All @@ -105,8 +111,8 @@ def get(msgID):
#if 'Broadcast' in toAddress:
# toAddress = fromAddress

subject = inboxMessages['inboxMessages'][msgID]['subject'].decode('base64')
body = inboxMessages['inboxMessages'][msgID]['message'].decode('base64')
subject = decode(inboxMessages['inboxMessages'][msgID]['subject'].encode("utf-8", "replace"), 'base64')
body = decode(inboxMessages['inboxMessages'][msgID]['message'].encode("utf-8", "replace"), 'base64')
return dateTime, toAddress, fromAddress, subject, body

def listMsgs():
Expand Down Expand Up @@ -135,7 +141,7 @@ def _deleteMessage(msgRef):

def getUIDLforAll():
api = _makeApi(_getKeyLocation())
inboxMessages = json.loads(api.getAllInboxMessages())
inboxMessages = _getAll()
refdata = []
for msgID in range(len(inboxMessages['inboxMessages'])):
msgRef = inboxMessages['inboxMessages'][msgID]['msgid'] #gets the message Ref via the message index number
Expand All @@ -144,7 +150,7 @@ def getUIDLforAll():

def getUIDLforSingle(msgID):
api = _makeApi(_getKeyLocation())
inboxMessages = json.loads(api.getAllInboxMessages())
inboxMessages = _getAll()
msgRef = inboxMessages['inboxMessages'][msgID]['msgid'] #gets the message Ref via the message index number
return [str(msgRef)]

Expand All @@ -170,7 +176,7 @@ def lookupAppdataFolder(): #gets the appropriate folders for the .dat files depe
def apiData():
global keysPath

config = ConfigParser.SafeConfigParser()
config = SafeConfigParser()
keysPath = 'keys.dat'
config.read(keysPath) #First try to load the config file (the keys.dat file) from the program directory

Expand All @@ -181,30 +187,30 @@ def apiData():
#Could not load the keys.dat file in the program directory. Perhaps it is in the appdata directory.
appDataFolder = lookupAppdataFolder()
keysPath = appDataFolder + 'keys.dat'
config = ConfigParser.SafeConfigParser()
config = SafeConfigParser()
config.read(keysPath)

try:
config.get('bitmessagesettings','settingsversion')
except:
#keys.dat was not there either, something is wrong.
print ' '
print '******************************************************************'
print 'There was a problem trying to access the Bitmessage keys.dat file.'
print 'Make sure that daemon is in the same directory as Bitmessage.'
print '******************************************************************'
print ' '
print config
print ' '
print(' ')
print('******************************************************************')
print('There was a problem trying to access the Bitmessage keys.dat file.')
print('Make sure that daemon is in the same directory as Bitmessage.')
print('******************************************************************')
print(' ')
print(config)
print(' ')

try:
apiConfigured = config.getboolean('bitmessagesettings','apienabled') #Look for 'apienabled'
apiEnabled = apiConfigured
except:
apiConfigured = False #If not found, set to false since it still needs to be configured
print "You need to edit your keys.dat file and enable bitmessage's API"
print "See for more details: https://bitmessage.org/wiki/API"
print "Will now crash..."
print("You need to edit your keys.dat file and enable bitmessage's API")
print("See for more details: https://bitmessage.org/wiki/API")
print("Will now crash...")
raise

#if (apiConfigured == False):#If the apienabled == false or is not present in the keys.dat file, notify the user and set it up
Expand Down
73 changes: 38 additions & 35 deletions incoming.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class ChatterboxConnection(object):
END = "\r\n"
END = b"\r\n"
def __init__(self, conn):
self.conn = conn
def __getattr__(self, name):
Expand All @@ -33,23 +33,23 @@ def recvall(self, END=END):
data[-2] = pair[:pair.index(END)]
data.pop()
break
return "".join(data)
return b"".join(data)


def handleUser(data):
d = data.split()
logging.debug("data:%s" % d)
username = d[-1]
if username[:3] == 'BM-':
if username[:3] == b'BM-':
logging.debug("Only showing messages for %s" % username)
bminterface.registerAddress(username)
else:
logging.debug("Showing all messages in the inbox")
bminterface.registerAddress(None)
return "+OK user accepted"
return b"+OK user accepted"

def handlePass(data):
return "+OK pass accepted"
return b"+OK pass accepted"

def _getMsgSizes():
msgCount = bminterface.listMsgs()
Expand All @@ -66,7 +66,7 @@ def handleStat(data):
msgSizeTotal = 0
for msgSize in msgSizes:
msgSizeTotal += msgSize
returnData = '+OK %i %i' % (msgCount, msgSizeTotal)
returnData = b'+OK %i %i' % (msgCount, msgSizeTotal)
logging.debug("Answering STAT: %i %i" % (msgCount, msgSizeTotal))
return returnData

Expand All @@ -79,26 +79,26 @@ def handleList(data):
# means the server wants a single message response
i = int(msgId) - 1
if i >= len(msgSizes):
return "-ERR no such message"
return b"-ERR no such message"
else:
msgSize = msgSizes[i]
return "+OK %s %s" % (msgId, msgSize)
return b"+OK %i %i" % (msgId, msgSize)
msgCount = 0
returnDataPart2 = ''
returnDataPart2 = b''
msgSizeTotal = 0
for msgSize in msgSizes:
msgSizeTotal += msgSize
msgCount += 1
returnDataPart2 += '%i %i\r\n' % (msgCount, msgSize)
returnDataPart2 += '.'
returnDataPart1 = '+OK %i messages (%i octets)\r\n' % (msgCount, msgSizeTotal)
returnDataPart2 += b'%i %i\r\n' % (msgCount, msgSize)
returnDataPart2 += b'.'
returnDataPart1 = b'+OK %i messages (%i octets)\r\n' % (msgCount, msgSizeTotal)
returnData = returnDataPart1 + returnDataPart2
logging.debug("Answering LIST: %i %i" % (msgCount, msgSizeTotal))
logging.debug(returnData)
return returnData

def handleTop(data):
msg = 'test'
msg = b'test'
logging.debug(data.split())
cmd, msgID, lines = data.split()
msgID = int(msgID)-1
Expand All @@ -107,34 +107,37 @@ def handleTop(data):
dateTime, toAddress, fromAddress, subject, body = bminterface.get(msgID)
logging.debug(subject)
msg = makeEmail(dateTime, toAddress, fromAddress, subject, body)
top, bot = msg.split("\n\n", 1)
#text = top + "\r\n\r\n" + "\r\n".join(bot[:lines])
return "+OK top of message follows\r\n%s\r\n." % top
top, bot = msg.split(b"\n\n", 1)
#text = top + b"\r\n\r\n" + b"\r\n".join(bot[:lines])
return b"+OK top of message follows\r\n%s\r\n." % top

def handleRetr(data):
logging.debug(data.split())
msgID = int(data.split()[1])-1
msgCount = bminterface.listMsgs()
if msgID >= msgCount:
return b"-ERR no such message"
dateTime, toAddress, fromAddress, subject, body = bminterface.get(msgID)
msg = makeEmail(dateTime, toAddress, fromAddress, subject, body)
return "+OK %i octets\r\n%s\r\n." % (len(msg), msg)
return b"+OK %i octets\r\n%b\r\n." % (len(msg), msg.encode("utf-8", "replace"))

def handleDele(data):
msgID = int(data.split()[1])-1
bminterface.markForDelete(msgID)
return "+OK I'll try..."
return b"+OK I'll try..."

def handleNoop(data):
return "+OK"
return b"+OK"

def handleQuit(data):
bminterface.cleanup()
return "+OK just pretend I'm gone"
return b"+OK just pretend I'm gone"

def handleCapa(data):
returnData = "+OK List of capabilities follows\r\n"
returnData = b"+OK List of capabilities follows\r\n"
for k in dispatch:
returnData += "%s\r\n" % k
returnData += "."
returnData += b"%b\r\n" % k.encode("utf-8", "replace")
returnData += b"."
return returnData

def handleUIDL(data):
Expand All @@ -143,14 +146,14 @@ def handleUIDL(data):
if len(data) == 1:
refdata = bminterface.getUIDLforAll()
logging.debug(refdata)
returnData = '+OK\r\n'
returnData = b'+OK\r\n'
for msgID, d in enumerate(refdata):
returnData += "%s %s\r\n" % (msgID+1, d)
returnData += '.'
returnData += b"%i %b\r\n" % (msgID+1, d.encode("utf-8", "replace"))
returnData += b'.'
else:
refdata = bminterface.getUIDLforSingle(int(data[1])-1)
logging.debug(refdata)
returnData = '+OK ' + data[0] + str(refdata[0])
returnData = b'+OK ' + data[0] + refdata[0]
return returnData

def makeEmail(dateTime, toAddress, fromAddress, subject, body):
Expand Down Expand Up @@ -198,16 +201,16 @@ def makeEmail(dateTime, toAddress, fromAddress, subject, body):

def parseBody(body):
returnData = []
text = ''
searchString = '<img[^>]*'
text = b''
searchString = b'<img[^>]*'
attachment = re.search(searchString, body)
while attachment:
imageCode = body[attachment.start():attachment.end()]
imageDataRange = re.search('src=[\"\'][^\"\']*[\"\']', imageCode)
imageDataRange = re.search(b'src=[\"\'][^\"\']*[\"\']', imageCode)
imageData=''
if imageDataRange:
try:
imageData = imageCode[imageDataRange.start()+5:imageDataRange.end()-1].lstrip('data:')
imageData = imageCode[imageDataRange.start()+5:imageDataRange.end()-1].lstrip(b'data:')
except:
pass
if imageData:
Expand Down Expand Up @@ -257,15 +260,15 @@ def incomingServer_main(host, port, run_event):
sock = None
try:
conn = ChatterboxConnection(conn)
conn.sendall("+OK server ready")
conn.sendall(b"+OK server ready")
while run_event.is_set():
data = conn.recvall()
logging.debug("Answering %s" % data)
command = data.split(None, 1)[0]
command = data.split(None, 1)[0].decode("utf-8", "replace")
try:
cmd = dispatch[command]
except KeyError:
conn.sendall("-ERR unknown command")
conn.sendall(b"-ERR unknown command")
else:
conn.sendall(cmd(data))
if cmd is handleQuit:
Expand All @@ -275,7 +278,7 @@ def incomingServer_main(host, port, run_event):

except (SystemExit, KeyboardInterrupt):
pass
except Exception, ex:
except Exception as ex:
raise
finally:
if sock is not None:
Expand Down
8 changes: 4 additions & 4 deletions outgoing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import logging

class outgoingServer(SMTPServer):
def process_message(self, peer, mailfrom, rcpttos, data):
def process_message(self, peer, mailfrom, rcpttos, data, mail_options=[], rcpt_options=[]):
parser = email.parser.FeedParser()
parser.feed(data)
parser.feed(data.decode("utf-8", "replace"))
msg = parser.close()

toAddress = msg['To']
fromAddress = msg['From']
subject = u' '.join(unicode(t[0], t[1] or 'UTF-8') for t in email.header.decode_header(msg['Subject'])).encode('UTF-8')
subject = ' '.join(t[0] for t in email.header.decode_header(msg['Subject']))
body = self._bmformat(msg)

#Make sure we don't send an actually blank subject or body--this can cause problems.
Expand Down Expand Up @@ -49,7 +49,7 @@ def _recurseParse(self, msg):
if 'text/plain' in item['Content-Type']:
text += item.get_payload()
elif 'image' in item['Content-Type']:
[filetype, name] = item['Content-Type'].rstrip().split('\n')
filetype, name = item['Content-Type'].rstrip().split(' ')
name = name.replace('name', 'alt')
imageraw = item.get_payload().rstrip().split('\n')
imagedata = ''
Expand Down