fixes after new merging PR #23
This commit is contained in:
commit
ade796c700
|
@ -1 +0,0 @@
|
||||||
src
|
|
21
python3_requirements.txt
Normal file
21
python3_requirements.txt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
astroid==2.3.3
|
||||||
|
certifi==2019.9.11
|
||||||
|
chardet==3.0.4
|
||||||
|
docutils==0.15.2
|
||||||
|
idna==2.8
|
||||||
|
isort==4.3.21
|
||||||
|
Kivy==1.11.1
|
||||||
|
Kivy-Garden==0.1.4
|
||||||
|
git+https://github.com/HeaTTheatR/KivyMD.git
|
||||||
|
lazy-object-proxy==1.4.3
|
||||||
|
mccabe==0.6.1
|
||||||
|
Pillow==6.1.0
|
||||||
|
pkg-resources==0.0.0
|
||||||
|
pydenticon==0.3.1
|
||||||
|
Pygments==2.4.2
|
||||||
|
pylint==2.4.4
|
||||||
|
qrcode==6.1
|
||||||
|
requests==2.22.0
|
||||||
|
six==1.12.0
|
||||||
|
typed-ast==1.4.0
|
||||||
|
urllib3==1.25.6
|
|
@ -44,7 +44,8 @@ def decodeBase58(string, alphabet=ALPHABET):
|
||||||
for char in string:
|
for char in string:
|
||||||
num *= base
|
num *= base
|
||||||
num += alphabet.index(char)
|
num += alphabet.index(char)
|
||||||
except: # ValueError
|
# ValueError
|
||||||
|
except:
|
||||||
# character not found (like a space character or a 0)
|
# character not found (like a space character or a 0)
|
||||||
return 0
|
return 0
|
||||||
return num
|
return num
|
||||||
|
@ -83,13 +84,13 @@ def decodeVarint(data):
|
||||||
the minimum amount of data possible or else it is malformed.
|
the minimum amount of data possible or else it is malformed.
|
||||||
Returns a tuple: (theEncodedValue, theSizeOfTheVarintInBytes)
|
Returns a tuple: (theEncodedValue, theSizeOfTheVarintInBytes)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
return (0, 0)
|
return (0, 0)
|
||||||
firstByte, = unpack('>B', data[0:1])
|
firstByte, = unpack('>B', data[0:1])
|
||||||
if firstByte < 253:
|
if firstByte < 253:
|
||||||
# encodes 0 to 252
|
# encodes 0 to 252
|
||||||
return (firstByte, 1) # the 1 is the length of the varint
|
# the 1 is the length of the varint
|
||||||
|
return (firstByte, 1)
|
||||||
if firstByte == 253:
|
if firstByte == 253:
|
||||||
# encodes 253 to 65535
|
# encodes 253 to 65535
|
||||||
if len(data) < 3:
|
if len(data) < 3:
|
||||||
|
@ -157,7 +158,7 @@ def encodeAddress(version, stream, ripe):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Programming error in encodeAddress: The length of'
|
'Programming error in encodeAddress: The length of'
|
||||||
' a given ripe hash was not 20.')
|
' a given ripe hash was not 20.')
|
||||||
ripe = ripe.lstrip('\x00')
|
ripe = ripe.lstrip('\x00'.encode('utf-8'))
|
||||||
|
|
||||||
storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
|
storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
|
||||||
|
|
||||||
|
@ -180,7 +181,6 @@ def decodeAddress(address):
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-return-statements,too-many-statements
|
# pylint: disable=too-many-return-statements,too-many-statements
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
|
|
||||||
address = str(address).strip()
|
address = str(address).strip()
|
||||||
|
|
||||||
if address[:3] == 'BM-':
|
if address[:3] == 'BM-':
|
||||||
|
@ -192,7 +192,7 @@ def decodeAddress(address):
|
||||||
return status, 0, 0, ''
|
return status, 0, 0, ''
|
||||||
# after converting to hex, the string will be prepended
|
# after converting to hex, the string will be prepended
|
||||||
# with a 0x and appended with a L
|
# with a 0x and appended with a L
|
||||||
hexdata = hex(integer)[2:-1]
|
hexdata = hex(integer)[2:]
|
||||||
|
|
||||||
if len(hexdata) % 2 != 0:
|
if len(hexdata) % 2 != 0:
|
||||||
hexdata = '0' + hexdata
|
hexdata = '0' + hexdata
|
||||||
|
@ -237,7 +237,8 @@ def decodeAddress(address):
|
||||||
status = 'success'
|
status = 'success'
|
||||||
if addressVersionNumber == 1:
|
if addressVersionNumber == 1:
|
||||||
return status, addressVersionNumber, streamNumber, data[-24:-4]
|
return status, addressVersionNumber, streamNumber, data[-24:-4]
|
||||||
elif addressVersionNumber == 2 or addressVersionNumber == 3:
|
# elif addressVersionNumber == 2 or addressVersionNumber == 3:
|
||||||
|
elif addressVersionNumber in (2, 3):
|
||||||
embeddedRipeData = \
|
embeddedRipeData = \
|
||||||
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
data[bytesUsedByVersionNumber + bytesUsedByStreamNumber:-4]
|
||||||
if len(embeddedRipeData) == 19:
|
if len(embeddedRipeData) == 19:
|
||||||
|
@ -248,7 +249,7 @@ def decodeAddress(address):
|
||||||
embeddedRipeData
|
embeddedRipeData
|
||||||
elif len(embeddedRipeData) == 18:
|
elif len(embeddedRipeData) == 18:
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
'\x00\x00' + embeddedRipeData
|
'\x00\x00'.encode('utf-8') + embeddedRipeData
|
||||||
elif len(embeddedRipeData) < 18:
|
elif len(embeddedRipeData) < 18:
|
||||||
return 'ripetooshort', 0, 0, ''
|
return 'ripetooshort', 0, 0, ''
|
||||||
elif len(embeddedRipeData) > 20:
|
elif len(embeddedRipeData) > 20:
|
||||||
|
@ -265,7 +266,8 @@ def decodeAddress(address):
|
||||||
return 'ripetoolong', 0, 0, ''
|
return 'ripetoolong', 0, 0, ''
|
||||||
elif len(embeddedRipeData) < 4:
|
elif len(embeddedRipeData) < 4:
|
||||||
return 'ripetooshort', 0, 0, ''
|
return 'ripetooshort', 0, 0, ''
|
||||||
x00string = '\x00' * (20 - len(embeddedRipeData))
|
x00string = '\x00'.encode('utf-8') * (20 - len(embeddedRipeData))
|
||||||
|
|
||||||
return status, addressVersionNumber, streamNumber, \
|
return status, addressVersionNumber, streamNumber, \
|
||||||
x00string + embeddedRipeData
|
x00string + embeddedRipeData
|
||||||
|
|
||||||
|
|
56
src/api.py
56
src/api.py
|
@ -3,9 +3,16 @@ This is not what you run to run the Bitmessage API. Instead, enable the API
|
||||||
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
|
( https://bitmessage.org/wiki/API ) and optionally enable daemon mode
|
||||||
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
|
( https://bitmessage.org/wiki/Daemon ) then run bitmessagemain.py.
|
||||||
"""
|
"""
|
||||||
|
<<<<<<< HEAD
|
||||||
# Copyright (c) 2012-2016 Jonathan Warren
|
# Copyright (c) 2012-2016 Jonathan Warren
|
||||||
# Copyright (c) 2012-2020 The Bitmessage developers
|
# Copyright (c) 2012-2020 The Bitmessage developers
|
||||||
# pylint: disable=too-many-lines,no-self-use,unused-variable,unused-argument
|
# pylint: disable=too-many-lines,no-self-use,unused-variable,unused-argument
|
||||||
|
=======
|
||||||
|
# pylint: disable=too-many-locals,too-many-lines,no-self-use,unused-argument
|
||||||
|
# pylint: disable=too-many-statements,too-many-public-methods,too-many-branches
|
||||||
|
# Copyright (c) 2012-2016 Jonathan Warren
|
||||||
|
# Copyright (c) 2012-2019 The Bitmessage developers
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
import base64
|
import base64
|
||||||
import errno
|
import errno
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -27,6 +34,7 @@ import queues
|
||||||
import shared
|
import shared
|
||||||
import shutdown
|
import shutdown
|
||||||
import state
|
import state
|
||||||
|
<<<<<<< HEAD
|
||||||
from addresses import (
|
from addresses import (
|
||||||
addBMIfNotPresent,
|
addBMIfNotPresent,
|
||||||
calculateInventoryHash,
|
calculateInventoryHash,
|
||||||
|
@ -34,13 +42,21 @@ from addresses import (
|
||||||
decodeVarint,
|
decodeVarint,
|
||||||
varintDecodeError
|
varintDecodeError
|
||||||
)
|
)
|
||||||
|
=======
|
||||||
|
|
||||||
|
from addresses import addBMIfNotPresent, calculateInventoryHash, decodeAddress, decodeVarint, varintDecodeError
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from helper_ackPayload import genAckPayload
|
from helper_ackPayload import genAckPayload
|
||||||
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure
|
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network.threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
<<<<<<< HEAD
|
||||||
from version import softwareVersion
|
from version import softwareVersion
|
||||||
|
=======
|
||||||
|
# pylint: disable=unused-variable
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
|
|
||||||
str_chan = '[chan]'
|
str_chan = '[chan]'
|
||||||
|
|
||||||
|
@ -59,6 +75,7 @@ class APIError(Exception):
|
||||||
|
|
||||||
class StoppableXMLRPCServer(SimpleXMLRPCServer):
|
class StoppableXMLRPCServer(SimpleXMLRPCServer):
|
||||||
"""A SimpleXMLRPCServer that honours state.shutdown"""
|
"""A SimpleXMLRPCServer that honours state.shutdown"""
|
||||||
|
# pylint:disable=too-few-public-methods
|
||||||
allow_reuse_address = True
|
allow_reuse_address = True
|
||||||
|
|
||||||
def serve_forever(self):
|
def serve_forever(self):
|
||||||
|
@ -153,7 +170,6 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
Note: this method is the same as in SimpleXMLRPCRequestHandler,
|
Note: this method is the same as in SimpleXMLRPCRequestHandler,
|
||||||
just hacked to handle cookies
|
just hacked to handle cookies
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Check that the path is legal
|
# Check that the path is legal
|
||||||
if not self.is_rpc_path_valid():
|
if not self.is_rpc_path_valid():
|
||||||
self.report_404()
|
self.report_404()
|
||||||
|
@ -182,7 +198,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
response = self.server._marshaled_dispatch(
|
response = self.server._marshaled_dispatch(
|
||||||
data, getattr(self, '_dispatch', None)
|
data, getattr(self, '_dispatch', None)
|
||||||
)
|
)
|
||||||
except BaseException: # This should only happen if the module is buggy
|
# This should only happen if the module is buggy
|
||||||
|
except BaseException:
|
||||||
# internal error, report as HTTP server error
|
# internal error, report as HTTP server error
|
||||||
self.send_response(500)
|
self.send_response(500)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
@ -258,9 +275,13 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(9, 'Invalid characters in address: ' + address)
|
raise APIError(9, 'Invalid characters in address: ' + address)
|
||||||
if status == 'versiontoohigh':
|
if status == 'versiontoohigh':
|
||||||
raise APIError(
|
raise APIError(
|
||||||
|
<<<<<<< HEAD
|
||||||
10,
|
10,
|
||||||
'Address version number too high (or zero) in address: ' +
|
'Address version number too high (or zero) in address: ' +
|
||||||
address)
|
address)
|
||||||
|
=======
|
||||||
|
10, 'Address version number too high (or zero) in address: ' + address)
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
if status == 'varintmalformed':
|
if status == 'varintmalformed':
|
||||||
raise APIError(26, 'Malformed varint in address: ' + address)
|
raise APIError(26, 'Malformed varint in address: ' + address)
|
||||||
raise APIError(
|
raise APIError(
|
||||||
|
@ -501,7 +522,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
# 0 means "just use the proper addressVersionNumber"
|
# 0 means "just use the proper addressVersionNumber"
|
||||||
if addressVersionNumber == 0:
|
if addressVersionNumber == 0:
|
||||||
addressVersionNumber = 4
|
addressVersionNumber = 4
|
||||||
if addressVersionNumber != 3 and addressVersionNumber != 4:
|
# if addressVersionNumber != 3 and addressVersionNumber != 4:
|
||||||
|
if addressVersionNumber not in (3, 4):
|
||||||
raise APIError(
|
raise APIError(
|
||||||
2, 'The address version number currently must be 3, 4, or 0'
|
2, 'The address version number currently must be 3, 4, or 0'
|
||||||
' (which means auto-select). %i isn\'t supported.' %
|
' (which means auto-select). %i isn\'t supported.' %
|
||||||
|
@ -552,7 +574,8 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
if not passphrase:
|
if not passphrase:
|
||||||
raise APIError(1, 'The specified passphrase is blank.')
|
raise APIError(1, 'The specified passphrase is blank.')
|
||||||
passphrase = self._decode(passphrase, "base64")
|
passphrase = self._decode(passphrase, "base64")
|
||||||
if addressVersionNumber != 3 and addressVersionNumber != 4:
|
# if addressVersionNumber != 3 and addressVersionNumber != 4:
|
||||||
|
if addressVersionNumber not in (3, 4):
|
||||||
raise APIError(
|
raise APIError(
|
||||||
2, 'The address version number currently must be 3 or 4. %i'
|
2, 'The address version number currently must be 3 or 4. %i'
|
||||||
' isn\'t supported.' % addressVersionNumber)
|
' isn\'t supported.' % addressVersionNumber)
|
||||||
|
@ -622,8 +645,13 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
label = str_chan + ' ' + passphrase
|
label = str_chan + ' ' + passphrase
|
||||||
except BaseException:
|
except BaseException:
|
||||||
label = str_chan + ' ' + repr(passphrase)
|
label = str_chan + ' ' + repr(passphrase)
|
||||||
|
<<<<<<< HEAD
|
||||||
status, addressVersionNumber, streamNumber, toRipe = (
|
status, addressVersionNumber, streamNumber, toRipe = (
|
||||||
self._verifyAddress(suppliedAddress))
|
self._verifyAddress(suppliedAddress))
|
||||||
|
=======
|
||||||
|
status, addressVersionNumber, streamNumber, toRipe = self._verifyAddress(
|
||||||
|
suppliedAddress)
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
suppliedAddress = addBMIfNotPresent(suppliedAddress)
|
suppliedAddress = addBMIfNotPresent(suppliedAddress)
|
||||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||||
queues.addressGeneratorQueue.put((
|
queues.addressGeneratorQueue.put((
|
||||||
|
@ -646,8 +674,13 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need parameters.')
|
raise APIError(0, 'I need parameters.')
|
||||||
elif len(params) == 1:
|
elif len(params) == 1:
|
||||||
address, = params
|
address, = params
|
||||||
|
<<<<<<< HEAD
|
||||||
status, addressVersionNumber, streamNumber, toRipe = (
|
status, addressVersionNumber, streamNumber, toRipe = (
|
||||||
self._verifyAddress(address))
|
self._verifyAddress(address))
|
||||||
|
=======
|
||||||
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(address)
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
if not BMConfigParser().has_section(address):
|
if not BMConfigParser().has_section(address):
|
||||||
raise APIError(
|
raise APIError(
|
||||||
|
@ -668,8 +701,13 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
raise APIError(0, 'I need parameters.')
|
raise APIError(0, 'I need parameters.')
|
||||||
elif len(params) == 1:
|
elif len(params) == 1:
|
||||||
address, = params
|
address, = params
|
||||||
|
<<<<<<< HEAD
|
||||||
status, addressVersionNumber, streamNumber, toRipe = (
|
status, addressVersionNumber, streamNumber, toRipe = (
|
||||||
self._verifyAddress(address))
|
self._verifyAddress(address))
|
||||||
|
=======
|
||||||
|
status, addressVersionNumber, streamNumber, toRipe = \
|
||||||
|
self._verifyAddress(address)
|
||||||
|
>>>>>>> 86df28c260eb1dd4acae506c1366f3cf136c5840
|
||||||
address = addBMIfNotPresent(address)
|
address = addBMIfNotPresent(address)
|
||||||
if not BMConfigParser().has_section(address):
|
if not BMConfigParser().has_section(address):
|
||||||
raise APIError(
|
raise APIError(
|
||||||
|
@ -1222,7 +1260,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
initialHash = hashlib.sha512(encryptedPayload).digest()
|
initialHash = hashlib.sha512(encryptedPayload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print '(For msg message via API) Found proof of work', trialValue, 'Nonce:', nonce
|
print('(For msg message via API) Found proof of work', trialValue, 'Nonce:', nonce)
|
||||||
try:
|
try:
|
||||||
print(
|
print(
|
||||||
'POW took', int(time.time() - powStartTime),
|
'POW took', int(time.time() - powStartTime),
|
||||||
|
@ -1241,7 +1279,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
int(time.time()) + TTL, ''
|
int(time.time()) + TTL, ''
|
||||||
)
|
)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash)
|
print('Broadcasting inv for msg(API disseminatePreEncryptedMsg command):', hexlify(inventoryHash))
|
||||||
queues.invQueue.put((toStreamNumber, inventoryHash))
|
queues.invQueue.put((toStreamNumber, inventoryHash))
|
||||||
|
|
||||||
def HandleTrashSentMessageByAckDAta(self, params):
|
def HandleTrashSentMessageByAckDAta(self, params):
|
||||||
|
@ -1271,10 +1309,10 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
target = 2 ** 64 / ((
|
target = 2 ** 64 / ((
|
||||||
len(payload) + defaults.networkDefaultPayloadLengthExtraBytes + 8
|
len(payload) + defaults.networkDefaultPayloadLengthExtraBytes + 8
|
||||||
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
|
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
|
||||||
print '(For pubkey message via API) Doing proof of work...'
|
print('(For pubkey message via API) Doing proof of work...')
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
print '(For pubkey message via API) Found proof of work', trialValue, 'Nonce:', nonce
|
print('(For pubkey message via API) Found proof of work', trialValue, 'Nonce:', nonce)
|
||||||
payload = pack('>Q', nonce) + payload
|
payload = pack('>Q', nonce) + payload
|
||||||
|
|
||||||
pubkeyReadPosition = 8 # bypass the nonce
|
pubkeyReadPosition = 8 # bypass the nonce
|
||||||
|
@ -1295,7 +1333,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL, ''
|
objectType, pubkeyStreamNumber, payload, int(time.time()) + TTL, ''
|
||||||
)
|
)
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash)
|
print('broadcasting inv within API command disseminatePubkey with hash:', hexlify(inventoryHash))
|
||||||
queues.invQueue.put((pubkeyStreamNumber, inventoryHash))
|
queues.invQueue.put((pubkeyStreamNumber, inventoryHash))
|
||||||
|
|
||||||
def HandleGetMessageDataByDestinationHash(self, params):
|
def HandleGetMessageDataByDestinationHash(self, params):
|
||||||
|
|
|
@ -29,7 +29,8 @@ from bmconfigparser import BMConfigParser
|
||||||
api = ''
|
api = ''
|
||||||
keysName = 'keys.dat'
|
keysName = 'keys.dat'
|
||||||
keysPath = 'keys.dat'
|
keysPath = 'keys.dat'
|
||||||
usrPrompt = 0 # 0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up
|
# 0 = First Start, 1 = prompt, 2 = no prompt if the program is starting up
|
||||||
|
usrPrompt = 0
|
||||||
knownAddresses = dict()
|
knownAddresses = dict()
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ def userInput(message):
|
||||||
|
|
||||||
global usrPrompt
|
global usrPrompt
|
||||||
|
|
||||||
print '\n' + message
|
print('\n' + message)
|
||||||
uInput = raw_input('> ')
|
uInput = raw_input('> ')
|
||||||
|
|
||||||
if uInput.lower() == 'exit': # Returns the user to the main menu
|
if uInput.lower() == 'exit': # Returns the user to the main menu
|
||||||
|
@ -46,7 +47,7 @@ def userInput(message):
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif uInput.lower() == 'quit': # Quits the program
|
elif uInput.lower() == 'quit': # Quits the program
|
||||||
print '\n Bye\n'
|
print('\n Bye\n')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -55,9 +56,9 @@ def userInput(message):
|
||||||
|
|
||||||
def restartBmNotify():
|
def restartBmNotify():
|
||||||
"""Prompt the user to restart Bitmessage"""
|
"""Prompt the user to restart Bitmessage"""
|
||||||
print '\n *******************************************************************'
|
print('\n *******************************************************************')
|
||||||
print ' WARNING: If Bitmessage is running locally, you must restart it now.'
|
print(' WARNING: If Bitmessage is running locally, you must restart it now.')
|
||||||
print ' *******************************************************************\n'
|
print(' *******************************************************************\n')
|
||||||
|
|
||||||
|
|
||||||
# Begin keys.dat interactions
|
# Begin keys.dat interactions
|
||||||
|
@ -96,8 +97,8 @@ def configInit():
|
||||||
with open(keysName, 'wb') as configfile:
|
with open(keysName, 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
|
|
||||||
print '\n ' + str(keysName) + ' Initalized in the same directory as daemon.py'
|
print('\n ' + str(keysName) + ' Initalized in the same directory as daemon.py')
|
||||||
print ' You will now need to configure the ' + str(keysName) + ' file.\n'
|
print(' You will now need to configure the ' + str(keysName) + ' file.\n')
|
||||||
|
|
||||||
|
|
||||||
def apiInit(apiEnabled):
|
def apiInit(apiEnabled):
|
||||||
|
@ -114,20 +115,20 @@ def apiInit(apiEnabled):
|
||||||
with open(keysPath, 'wb') as configfile:
|
with open(keysPath, 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
|
|
||||||
print 'Done'
|
print('Done')
|
||||||
restartBmNotify()
|
restartBmNotify()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif uInput == "n":
|
elif uInput == "n":
|
||||||
print ' \n************************************************************'
|
print(' \n************************************************************')
|
||||||
print ' Daemon will not work when the API is disabled. '
|
print(' Daemon will not work when the API is disabled. ')
|
||||||
print ' Please refer to the Bitmessage Wiki on how to setup the API.'
|
print(' Please refer to the Bitmessage Wiki on how to setup the API.')
|
||||||
print ' ************************************************************\n'
|
print(' ************************************************************\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print '\n Invalid Entry\n'
|
print('\n Invalid Entry\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -136,11 +137,11 @@ def apiInit(apiEnabled):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else: # API information was not present.
|
else: # API information was not present.
|
||||||
print '\n ' + str(keysPath) + ' not properly configured!\n'
|
print('\n ' + str(keysPath) + ' not properly configured!\n')
|
||||||
uInput = userInput("Would you like to do this now, (Y)es or (N)o?").lower()
|
uInput = userInput("Would you like to do this now, (Y)es or (N)o?").lower()
|
||||||
|
|
||||||
if uInput == "y": # User said yes, initalize the api by writing these values to the keys.dat file
|
if uInput == "y": # User said yes, initalize the api by writing these values to the keys.dat file
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
apiUsr = userInput("API Username")
|
apiUsr = userInput("API Username")
|
||||||
apiPwd = userInput("API Password")
|
apiPwd = userInput("API Password")
|
||||||
|
@ -149,11 +150,11 @@ def apiInit(apiEnabled):
|
||||||
daemon = userInput("Daemon mode Enabled? (True) or (False)").lower()
|
daemon = userInput("Daemon mode Enabled? (True) or (False)").lower()
|
||||||
|
|
||||||
if (daemon != 'true' and daemon != 'false'):
|
if (daemon != 'true' and daemon != 'false'):
|
||||||
print '\n Invalid Entry for Daemon.\n'
|
print('\n Invalid Entry for Daemon.\n')
|
||||||
uInput = 1
|
uInput = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
print ' -----------------------------------\n'
|
print(' -----------------------------------\n')
|
||||||
|
|
||||||
# sets the bitmessage port to stop the warning about the api not properly
|
# sets the bitmessage port to stop the warning about the api not properly
|
||||||
# being setup. This is in the event that the keys.dat is in a different
|
# being setup. This is in the event that the keys.dat is in a different
|
||||||
|
@ -168,18 +169,18 @@ def apiInit(apiEnabled):
|
||||||
with open(keysPath, 'wb') as configfile:
|
with open(keysPath, 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
|
|
||||||
print '\n Finished configuring the keys.dat file with API information.\n'
|
print('\n Finished configuring the keys.dat file with API information.\n')
|
||||||
restartBmNotify()
|
restartBmNotify()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif uInput == "n":
|
elif uInput == "n":
|
||||||
print '\n ***********************************************************'
|
print('\n ***********************************************************')
|
||||||
print ' Please refer to the Bitmessage Wiki on how to setup the API.'
|
print(' Please refer to the Bitmessage Wiki on how to setup the API.')
|
||||||
print ' ***********************************************************\n'
|
print(' ***********************************************************\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
print ' \nInvalid entry\n'
|
print(' \nInvalid entry\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -206,11 +207,11 @@ def apiData():
|
||||||
BMConfigParser().get('bitmessagesettings', 'port')
|
BMConfigParser().get('bitmessagesettings', 'port')
|
||||||
except:
|
except:
|
||||||
# keys.dat was not there either, something is wrong.
|
# keys.dat was not there either, something is wrong.
|
||||||
print '\n ******************************************************************'
|
print('\n ******************************************************************')
|
||||||
print ' There was a problem trying to access the Bitmessage keys.dat file'
|
print(' There was a problem trying to access the Bitmessage keys.dat file')
|
||||||
print ' or keys.dat is not set up correctly'
|
print(' or keys.dat is not set up correctly')
|
||||||
print ' Make sure that daemon is in the same directory as Bitmessage. '
|
print(' Make sure that daemon is in the same directory as Bitmessage. ')
|
||||||
print ' ******************************************************************\n'
|
print(' ******************************************************************\n')
|
||||||
|
|
||||||
uInput = userInput("Would you like to create a keys.dat in the local directory, (Y)es or (N)o?").lower()
|
uInput = userInput("Would you like to create a keys.dat in the local directory, (Y)es or (N)o?").lower()
|
||||||
|
|
||||||
|
@ -220,11 +221,11 @@ def apiData():
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
elif (uInput == "n" or uInput == "no"):
|
elif (uInput == "n" or uInput == "no"):
|
||||||
print '\n Trying Again.\n'
|
print('\n Trying Again.\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
print '\n Invalid Input.\n'
|
print('\n Invalid Input.\n')
|
||||||
|
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
@ -249,7 +250,7 @@ def apiData():
|
||||||
apiUsername = BMConfigParser().get('bitmessagesettings', 'apiusername')
|
apiUsername = BMConfigParser().get('bitmessagesettings', 'apiusername')
|
||||||
apiPassword = BMConfigParser().get('bitmessagesettings', 'apipassword')
|
apiPassword = BMConfigParser().get('bitmessagesettings', 'apipassword')
|
||||||
|
|
||||||
print '\n API data successfully imported.\n'
|
print('\n API data successfully imported.\n')
|
||||||
|
|
||||||
# Build the api credentials
|
# Build the api credentials
|
||||||
return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface + ":" + str(apiPort) + "/"
|
return "http://" + apiUsername + ":" + apiPassword + "@" + apiInterface + ":" + str(apiPort) + "/"
|
||||||
|
@ -281,7 +282,7 @@ def bmSettings():
|
||||||
try:
|
try:
|
||||||
port = BMConfigParser().get('bitmessagesettings', 'port')
|
port = BMConfigParser().get('bitmessagesettings', 'port')
|
||||||
except:
|
except:
|
||||||
print '\n File not found.\n'
|
print('\n File not found.\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -300,27 +301,27 @@ def bmSettings():
|
||||||
socksusername = BMConfigParser().get('bitmessagesettings', 'socksusername')
|
socksusername = BMConfigParser().get('bitmessagesettings', 'socksusername')
|
||||||
sockspassword = BMConfigParser().get('bitmessagesettings', 'sockspassword')
|
sockspassword = BMConfigParser().get('bitmessagesettings', 'sockspassword')
|
||||||
|
|
||||||
print '\n -----------------------------------'
|
print('\n -----------------------------------')
|
||||||
print ' | Current Bitmessage Settings |'
|
print(' | Current Bitmessage Settings |')
|
||||||
print ' -----------------------------------'
|
print(' -----------------------------------')
|
||||||
print ' port = ' + port
|
print(' port = ' + port)
|
||||||
print ' startonlogon = ' + str(startonlogon)
|
print(' startonlogon = ' + str(startonlogon))
|
||||||
print ' minimizetotray = ' + str(minimizetotray)
|
print(' minimizetotray = ' + str(minimizetotray))
|
||||||
print ' showtraynotifications = ' + str(showtraynotifications)
|
print(' showtraynotifications = ' + str(showtraynotifications))
|
||||||
print ' startintray = ' + str(startintray)
|
print(' startintray = ' + str(startintray))
|
||||||
print ' defaultnoncetrialsperbyte = ' + defaultnoncetrialsperbyte
|
print(' defaultnoncetrialsperbyte = ' + defaultnoncetrialsperbyte)
|
||||||
print ' defaultpayloadlengthextrabytes = ' + defaultpayloadlengthextrabytes
|
print(' defaultpayloadlengthextrabytes = ' + defaultpayloadlengthextrabytes)
|
||||||
print ' daemon = ' + str(daemon)
|
print(' daemon = ' + str(daemon))
|
||||||
print '\n ------------------------------------'
|
print('\n ------------------------------------')
|
||||||
print ' | Current Connection Settings |'
|
print(' | Current Connection Settings |')
|
||||||
print ' -----------------------------------'
|
print(' -----------------------------------')
|
||||||
print ' socksproxytype = ' + socksproxytype
|
print(' socksproxytype = ' + socksproxytype)
|
||||||
print ' sockshostname = ' + sockshostname
|
print(' sockshostname = ' + sockshostname)
|
||||||
print ' socksport = ' + socksport
|
print(' socksport = ' + socksport)
|
||||||
print ' socksauthentication = ' + str(socksauthentication)
|
print(' socksauthentication = ' + str(socksauthentication))
|
||||||
print ' socksusername = ' + socksusername
|
print(' socksusername = ' + socksusername)
|
||||||
print ' sockspassword = ' + sockspassword
|
print(' sockspassword = ' + sockspassword)
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
uInput = userInput("Would you like to modify any of these settings, (Y)es or (N)o?").lower()
|
uInput = userInput("Would you like to modify any of these settings, (Y)es or (N)o?").lower()
|
||||||
|
|
||||||
|
@ -328,74 +329,74 @@ def bmSettings():
|
||||||
while True: # loops if they mistype the setting name, they can exit the loop with 'exit'
|
while True: # loops if they mistype the setting name, they can exit the loop with 'exit'
|
||||||
invalidInput = False
|
invalidInput = False
|
||||||
uInput = userInput("What setting would you like to modify?").lower()
|
uInput = userInput("What setting would you like to modify?").lower()
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
if uInput == "port":
|
if uInput == "port":
|
||||||
print ' Current port number: ' + port
|
print(' Current port number: ' + port)
|
||||||
uInput = userInput("Enter the new port number.")
|
uInput = userInput("Enter the new port number.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'port', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'port', str(uInput))
|
||||||
elif uInput == "startonlogon":
|
elif uInput == "startonlogon":
|
||||||
print ' Current status: ' + str(startonlogon)
|
print(' Current status: ' + str(startonlogon))
|
||||||
uInput = userInput("Enter the new status.")
|
uInput = userInput("Enter the new status.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'startonlogon', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'startonlogon', str(uInput))
|
||||||
elif uInput == "minimizetotray":
|
elif uInput == "minimizetotray":
|
||||||
print ' Current status: ' + str(minimizetotray)
|
print(' Current status: ' + str(minimizetotray))
|
||||||
uInput = userInput("Enter the new status.")
|
uInput = userInput("Enter the new status.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'minimizetotray', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'minimizetotray', str(uInput))
|
||||||
elif uInput == "showtraynotifications":
|
elif uInput == "showtraynotifications":
|
||||||
print ' Current status: ' + str(showtraynotifications)
|
print(' Current status: ' + str(showtraynotifications))
|
||||||
uInput = userInput("Enter the new status.")
|
uInput = userInput("Enter the new status.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'showtraynotifications', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'showtraynotifications', str(uInput))
|
||||||
elif uInput == "startintray":
|
elif uInput == "startintray":
|
||||||
print ' Current status: ' + str(startintray)
|
print(' Current status: ' + str(startintray))
|
||||||
uInput = userInput("Enter the new status.")
|
uInput = userInput("Enter the new status.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'startintray', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'startintray', str(uInput))
|
||||||
elif uInput == "defaultnoncetrialsperbyte":
|
elif uInput == "defaultnoncetrialsperbyte":
|
||||||
print ' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte
|
print(' Current default nonce trials per byte: ' + defaultnoncetrialsperbyte)
|
||||||
uInput = userInput("Enter the new defaultnoncetrialsperbyte.")
|
uInput = userInput("Enter the new defaultnoncetrialsperbyte.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'defaultnoncetrialsperbyte', str(uInput))
|
||||||
elif uInput == "defaultpayloadlengthextrabytes":
|
elif uInput == "defaultpayloadlengthextrabytes":
|
||||||
print ' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes
|
print(' Current default payload length extra bytes: ' + defaultpayloadlengthextrabytes)
|
||||||
uInput = userInput("Enter the new defaultpayloadlengthextrabytes.")
|
uInput = userInput("Enter the new defaultpayloadlengthextrabytes.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(uInput))
|
||||||
elif uInput == "daemon":
|
elif uInput == "daemon":
|
||||||
print ' Current status: ' + str(daemon)
|
print(' Current status: ' + str(daemon))
|
||||||
uInput = userInput("Enter the new status.").lower()
|
uInput = userInput("Enter the new status.").lower()
|
||||||
BMConfigParser().set('bitmessagesettings', 'daemon', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'daemon', str(uInput))
|
||||||
elif uInput == "socksproxytype":
|
elif uInput == "socksproxytype":
|
||||||
print ' Current socks proxy type: ' + socksproxytype
|
print(' Current socks proxy type: ' + socksproxytype)
|
||||||
print "Possibilities: 'none', 'SOCKS4a', 'SOCKS5'."
|
print("Possibilities: 'none', 'SOCKS4a', 'SOCKS5'.")
|
||||||
uInput = userInput("Enter the new socksproxytype.")
|
uInput = userInput("Enter the new socksproxytype.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'socksproxytype', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'socksproxytype', str(uInput))
|
||||||
elif uInput == "sockshostname":
|
elif uInput == "sockshostname":
|
||||||
print ' Current socks host name: ' + sockshostname
|
print(' Current socks host name: ' + sockshostname)
|
||||||
uInput = userInput("Enter the new sockshostname.")
|
uInput = userInput("Enter the new sockshostname.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'sockshostname', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'sockshostname', str(uInput))
|
||||||
elif uInput == "socksport":
|
elif uInput == "socksport":
|
||||||
print ' Current socks port number: ' + socksport
|
print(' Current socks port number: ' + socksport)
|
||||||
uInput = userInput("Enter the new socksport.")
|
uInput = userInput("Enter the new socksport.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'socksport', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'socksport', str(uInput))
|
||||||
elif uInput == "socksauthentication":
|
elif uInput == "socksauthentication":
|
||||||
print ' Current status: ' + str(socksauthentication)
|
print(' Current status: ' + str(socksauthentication))
|
||||||
uInput = userInput("Enter the new status.")
|
uInput = userInput("Enter the new status.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'socksauthentication', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'socksauthentication', str(uInput))
|
||||||
elif uInput == "socksusername":
|
elif uInput == "socksusername":
|
||||||
print ' Current socks username: ' + socksusername
|
print(' Current socks username: ' + socksusername)
|
||||||
uInput = userInput("Enter the new socksusername.")
|
uInput = userInput("Enter the new socksusername.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'socksusername', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'socksusername', str(uInput))
|
||||||
elif uInput == "sockspassword":
|
elif uInput == "sockspassword":
|
||||||
print ' Current socks password: ' + sockspassword
|
print(' Current socks password: ' + sockspassword)
|
||||||
uInput = userInput("Enter the new password.")
|
uInput = userInput("Enter the new password.")
|
||||||
BMConfigParser().set('bitmessagesettings', 'sockspassword', str(uInput))
|
BMConfigParser().set('bitmessagesettings', 'sockspassword', str(uInput))
|
||||||
else:
|
else:
|
||||||
print "\n Invalid input. Please try again.\n"
|
print("\n Invalid input. Please try again.\n")
|
||||||
invalidInput = True
|
invalidInput = True
|
||||||
|
|
||||||
if invalidInput is not True: # don't prompt if they made a mistake.
|
if invalidInput is not True: # don't prompt if they made a mistake.
|
||||||
uInput = userInput("Would you like to change another setting, (Y)es or (N)o?").lower()
|
uInput = userInput("Would you like to change another setting, (Y)es or (N)o?").lower()
|
||||||
|
|
||||||
if uInput != "y":
|
if uInput != "y":
|
||||||
print '\n Changes Made.\n'
|
print('\n Changes Made.\n')
|
||||||
with open(keysPath, 'wb') as configfile:
|
with open(keysPath, 'wb') as configfile:
|
||||||
BMConfigParser().write(configfile)
|
BMConfigParser().write(configfile)
|
||||||
restartBmNotify()
|
restartBmNotify()
|
||||||
|
@ -405,7 +406,7 @@ def bmSettings():
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
print "Invalid input."
|
print("Invalid input.")
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -433,10 +434,10 @@ def subscribe():
|
||||||
|
|
||||||
if address == "c":
|
if address == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(address) is False:
|
elif validAddress(address) is False:
|
||||||
print '\n Invalid. "c" to cancel. Please try again.\n'
|
print('\n Invalid. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -444,7 +445,7 @@ def subscribe():
|
||||||
label = label.encode('base64')
|
label = label.encode('base64')
|
||||||
|
|
||||||
api.addSubscription(address, label)
|
api.addSubscription(address, label)
|
||||||
print '\n You are now subscribed to: ' + address + '\n'
|
print('\n You are now subscribed to: ' + address + '\n')
|
||||||
|
|
||||||
|
|
||||||
def unsubscribe():
|
def unsubscribe():
|
||||||
|
@ -456,31 +457,31 @@ def unsubscribe():
|
||||||
|
|
||||||
if address == "c":
|
if address == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(address) is False:
|
elif validAddress(address) is False:
|
||||||
print '\n Invalid. "c" to cancel. Please try again.\n'
|
print('\n Invalid. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
userInput("Are you sure, (Y)es or (N)o?").lower() # uInput =
|
userInput("Are you sure, (Y)es or (N)o?").lower() # uInput =
|
||||||
|
|
||||||
api.deleteSubscription(address)
|
api.deleteSubscription(address)
|
||||||
print '\n You are now unsubscribed from: ' + address + '\n'
|
print('\n You are now unsubscribed from: ' + address + '\n')
|
||||||
|
|
||||||
|
|
||||||
def listSubscriptions():
|
def listSubscriptions():
|
||||||
"""List subscriptions"""
|
"""List subscriptions"""
|
||||||
|
|
||||||
global usrPrompt
|
global usrPrompt
|
||||||
print '\nLabel, Address, Enabled\n'
|
print('\nLabel, Address, Enabled\n')
|
||||||
try:
|
try:
|
||||||
print api.listSubscriptions()
|
print(api.listSubscriptions())
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
|
|
||||||
def createChan():
|
def createChan():
|
||||||
|
@ -490,9 +491,9 @@ def createChan():
|
||||||
password = userInput("Enter channel name")
|
password = userInput("Enter channel name")
|
||||||
password = password.encode('base64')
|
password = password.encode('base64')
|
||||||
try:
|
try:
|
||||||
print api.createChan(password)
|
print(api.createChan(password))
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -506,19 +507,19 @@ def joinChan():
|
||||||
|
|
||||||
if address == "c":
|
if address == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(address) is False:
|
elif validAddress(address) is False:
|
||||||
print '\n Invalid. "c" to cancel. Please try again.\n'
|
print('\n Invalid. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
password = userInput("Enter channel name")
|
password = userInput("Enter channel name")
|
||||||
password = password.encode('base64')
|
password = password.encode('base64')
|
||||||
try:
|
try:
|
||||||
print api.joinChan(password, address)
|
print(api.joinChan(password, address))
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -532,17 +533,17 @@ def leaveChan():
|
||||||
|
|
||||||
if address == "c":
|
if address == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(address) is False:
|
elif validAddress(address) is False:
|
||||||
print '\n Invalid. "c" to cancel. Please try again.\n'
|
print('\n Invalid. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print api.leaveChan(address)
|
print(api.leaveChan(address))
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -554,14 +555,14 @@ def listAdd():
|
||||||
jsonAddresses = json.loads(api.listAddresses())
|
jsonAddresses = json.loads(api.listAddresses())
|
||||||
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
# print '\nAddress Number,Label,Address,Stream,Enabled\n'
|
# print('\nAddress Number,Label,Address,Stream,Enabled\n')
|
||||||
print '\n --------------------------------------------------------------------------'
|
print('\n --------------------------------------------------------------------------')
|
||||||
print ' | # | Label | Address |S#|Enabled|'
|
print(' | # | Label | Address |S#|Enabled|')
|
||||||
print ' |---|-------------------|-------------------------------------|--|-------|'
|
print(' |---|-------------------|-------------------------------------|--|-------|')
|
||||||
for addNum in range(0, numAddresses): # processes all of the addresses and lists them out
|
for addNum in range(0, numAddresses): # processes all of the addresses and lists them out
|
||||||
label = (jsonAddresses['addresses'][addNum]['label']).encode(
|
label = (jsonAddresses['addresses'][addNum]['label']).encode(
|
||||||
'utf') # may still misdiplay in some consoles
|
'utf') # may still misdiplay in some consoles
|
||||||
|
@ -572,7 +573,7 @@ def listAdd():
|
||||||
if len(label) > 19:
|
if len(label) > 19:
|
||||||
label = label[:16] + '...'
|
label = label[:16] + '...'
|
||||||
|
|
||||||
print ''.join([
|
print(''.join([
|
||||||
' |',
|
' |',
|
||||||
str(addNum).ljust(3),
|
str(addNum).ljust(3),
|
||||||
'|',
|
'|',
|
||||||
|
@ -584,13 +585,13 @@ def listAdd():
|
||||||
'|',
|
'|',
|
||||||
enabled.ljust(7),
|
enabled.ljust(7),
|
||||||
'|',
|
'|',
|
||||||
])
|
]))
|
||||||
|
|
||||||
print ''.join([
|
print(''.join([
|
||||||
' ',
|
' ',
|
||||||
74 * '-',
|
74 * '-',
|
||||||
'\n',
|
'\n',
|
||||||
])
|
]))
|
||||||
|
|
||||||
|
|
||||||
def genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe):
|
def genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe):
|
||||||
|
@ -603,7 +604,7 @@ def genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe):
|
||||||
try:
|
try:
|
||||||
generatedAddress = api.createRandomAddress(addressLabel)
|
generatedAddress = api.createRandomAddress(addressLabel)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -614,7 +615,7 @@ def genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe):
|
||||||
try:
|
try:
|
||||||
generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe)
|
generatedAddress = api.createDeterministicAddresses(passphrase, numOfAdd, addVNum, streamNum, ripe)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
return generatedAddress
|
return generatedAddress
|
||||||
|
@ -646,7 +647,7 @@ def saveFile(fileName, fileData):
|
||||||
|
|
||||||
with open(filePath, 'wb+') as path_to_file:
|
with open(filePath, 'wb+') as path_to_file:
|
||||||
path_to_file.write(fileData.decode("base64"))
|
path_to_file.write(fileData.decode("base64"))
|
||||||
print '\n Successfully saved ' + filePath + '\n'
|
print('\n Successfully saved ' + filePath + '\n')
|
||||||
|
|
||||||
|
|
||||||
def attachment():
|
def attachment():
|
||||||
|
@ -667,26 +668,26 @@ def attachment():
|
||||||
with open(filePath):
|
with open(filePath):
|
||||||
break
|
break
|
||||||
except IOError:
|
except IOError:
|
||||||
print '\n %s was not found on your filesystem or can not be opened.\n' % filePath
|
print('\n %s was not found on your filesystem or can not be opened.\n' % filePath)
|
||||||
|
|
||||||
# print filesize, and encoding estimate with confirmation if file is over X size (1mb?)
|
# print(filesize, and encoding estimate with confirmation if file is over X size (1mb?))
|
||||||
invSize = os.path.getsize(filePath)
|
invSize = os.path.getsize(filePath)
|
||||||
invSize = (invSize / 1024) # Converts to kilobytes
|
invSize = (invSize / 1024) # Converts to kilobytes
|
||||||
round(invSize, 2) # Rounds to two decimal places
|
round(invSize, 2) # Rounds to two decimal places
|
||||||
|
|
||||||
if invSize > 500.0: # If over 500KB
|
if invSize > 500.0: # If over 500KB
|
||||||
print ''.join([
|
print(''.join([
|
||||||
'\n WARNING:The file that you are trying to attach is ',
|
'\n WARNING:The file that you are trying to attach is ',
|
||||||
invSize,
|
invSize,
|
||||||
'KB and will take considerable time to send.\n'
|
'KB and will take considerable time to send.\n'
|
||||||
])
|
]))
|
||||||
uInput = userInput('Are you sure you still want to attach it, (Y)es or (N)o?').lower()
|
uInput = userInput('Are you sure you still want to attach it, (Y)es or (N)o?').lower()
|
||||||
|
|
||||||
if uInput != "y":
|
if uInput != "y":
|
||||||
print '\n Attachment discarded.\n'
|
print('\n Attachment discarded.\n')
|
||||||
return ''
|
return ''
|
||||||
elif invSize > 184320.0: # If larger than 180MB, discard.
|
elif invSize > 184320.0: # If larger than 180MB, discard.
|
||||||
print '\n Attachment too big, maximum allowed size:180MB\n'
|
print('\n Attachment too big, maximum allowed size:180MB\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
pathLen = len(str(ntpath.basename(filePath))) # Gets the length of the filepath excluding the filename
|
pathLen = len(str(ntpath.basename(filePath))) # Gets the length of the filepath excluding the filename
|
||||||
|
@ -694,17 +695,17 @@ def attachment():
|
||||||
|
|
||||||
filetype = imghdr.what(filePath) # Tests if it is an image file
|
filetype = imghdr.what(filePath) # Tests if it is an image file
|
||||||
if filetype is not None:
|
if filetype is not None:
|
||||||
print '\n ---------------------------------------------------'
|
print('\n ---------------------------------------------------')
|
||||||
print ' Attachment detected as an Image.'
|
print(' Attachment detected as an Image.')
|
||||||
print ' <img> tags will automatically be included,'
|
print(' <img> tags will automatically be included,')
|
||||||
print ' allowing the recipient to view the image'
|
print(' allowing the recipient to view the image')
|
||||||
print ' using the "View HTML code..." option in Bitmessage.'
|
print(' using the "View HTML code..." option in Bitmessage.')
|
||||||
print ' ---------------------------------------------------\n'
|
print(' ---------------------------------------------------\n')
|
||||||
isImage = True
|
isImage = True
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
|
||||||
# Alert the user that the encoding process may take some time.
|
# Alert the user that the encoding process may take some time.
|
||||||
print '\n Encoding Attachment, Please Wait ...\n'
|
print('\n Encoding Attachment, Please Wait ...\n')
|
||||||
|
|
||||||
with open(filePath, 'rb') as f: # Begin the actual encoding
|
with open(filePath, 'rb') as f: # Begin the actual encoding
|
||||||
data = f.read(188743680) # Reads files up to 180MB, the maximum size for Bitmessage.
|
data = f.read(188743680) # Reads files up to 180MB, the maximum size for Bitmessage.
|
||||||
|
@ -759,10 +760,10 @@ def sendMsg(toAddress, fromAddress, subject, message):
|
||||||
|
|
||||||
if toAddress == "c":
|
if toAddress == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(toAddress) is False:
|
elif validAddress(toAddress) is False:
|
||||||
print '\n Invalid Address. "c" to cancel. Please try again.\n'
|
print('\n Invalid Address. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -771,14 +772,14 @@ def sendMsg(toAddress, fromAddress, subject, message):
|
||||||
jsonAddresses = json.loads(api.listAddresses())
|
jsonAddresses = json.loads(api.listAddresses())
|
||||||
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
if numAddresses > 1: # Ask what address to send from if multiple addresses
|
if numAddresses > 1: # Ask what address to send from if multiple addresses
|
||||||
found = False
|
found = False
|
||||||
while True:
|
while True:
|
||||||
print ' '
|
print(' ')
|
||||||
fromAddress = userInput("Enter an Address or Address Label to send from.")
|
fromAddress = userInput("Enter an Address or Address Label to send from.")
|
||||||
|
|
||||||
if fromAddress == "exit":
|
if fromAddress == "exit":
|
||||||
|
@ -795,7 +796,7 @@ def sendMsg(toAddress, fromAddress, subject, message):
|
||||||
|
|
||||||
if found is False:
|
if found is False:
|
||||||
if validAddress(fromAddress) is False:
|
if validAddress(fromAddress) is False:
|
||||||
print '\n Invalid Address. Please try again.\n'
|
print('\n Invalid Address. Please try again.\n')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for addNum in range(0, numAddresses): # processes all of the addresses
|
for addNum in range(0, numAddresses): # processes all of the addresses
|
||||||
|
@ -805,13 +806,13 @@ def sendMsg(toAddress, fromAddress, subject, message):
|
||||||
break
|
break
|
||||||
|
|
||||||
if found is False:
|
if found is False:
|
||||||
print '\n The address entered is not one of yours. Please try again.\n'
|
print('\n The address entered is not one of yours. Please try again.\n')
|
||||||
|
|
||||||
if found:
|
if found:
|
||||||
break # Address was found
|
break # Address was found
|
||||||
|
|
||||||
else: # Only one address in address book
|
else: # Only one address in address book
|
||||||
print '\n Using the only address in the addressbook to send from.\n'
|
print('\n Using the only address in the addressbook to send from.\n')
|
||||||
fromAddress = jsonAddresses['addresses'][0]['address']
|
fromAddress = jsonAddresses['addresses'][0]['address']
|
||||||
|
|
||||||
if subject == '':
|
if subject == '':
|
||||||
|
@ -828,9 +829,9 @@ def sendMsg(toAddress, fromAddress, subject, message):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ackData = api.sendMessage(toAddress, fromAddress, subject, message)
|
ackData = api.sendMessage(toAddress, fromAddress, subject, message)
|
||||||
print '\n Message Status:', api.getStatus(ackData), '\n'
|
print('\n Message Status:', api.getStatus(ackData), '\n')
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -845,7 +846,7 @@ def sendBrd(fromAddress, subject, message):
|
||||||
jsonAddresses = json.loads(api.listAddresses())
|
jsonAddresses = json.loads(api.listAddresses())
|
||||||
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
numAddresses = len(jsonAddresses['addresses']) # Number of addresses
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -868,7 +869,7 @@ def sendBrd(fromAddress, subject, message):
|
||||||
|
|
||||||
if found is False:
|
if found is False:
|
||||||
if validAddress(fromAddress) is False:
|
if validAddress(fromAddress) is False:
|
||||||
print '\n Invalid Address. Please try again.\n'
|
print('\n Invalid Address. Please try again.\n')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for addNum in range(0, numAddresses): # processes all of the addresses
|
for addNum in range(0, numAddresses): # processes all of the addresses
|
||||||
|
@ -878,13 +879,13 @@ def sendBrd(fromAddress, subject, message):
|
||||||
break
|
break
|
||||||
|
|
||||||
if found is False:
|
if found is False:
|
||||||
print '\n The address entered is not one of yours. Please try again.\n'
|
print('\n The address entered is not one of yours. Please try again.\n')
|
||||||
|
|
||||||
if found:
|
if found:
|
||||||
break # Address was found
|
break # Address was found
|
||||||
|
|
||||||
else: # Only one address in address book
|
else: # Only one address in address book
|
||||||
print '\n Using the only address in the addressbook to send from.\n'
|
print('\n Using the only address in the addressbook to send from.\n')
|
||||||
fromAddress = jsonAddresses['addresses'][0]['address']
|
fromAddress = jsonAddresses['addresses'][0]['address']
|
||||||
|
|
||||||
if subject == '':
|
if subject == '':
|
||||||
|
@ -901,9 +902,9 @@ def sendBrd(fromAddress, subject, message):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ackData = api.sendBroadcast(fromAddress, subject, message)
|
ackData = api.sendBroadcast(fromAddress, subject, message)
|
||||||
print '\n Message Status:', api.getStatus(ackData), '\n'
|
print('\n Message Status:', api.getStatus(ackData), '\n')
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -916,7 +917,7 @@ def inbox(unreadOnly=False):
|
||||||
inboxMessages = json.loads(api.getAllInboxMessages())
|
inboxMessages = json.loads(api.getAllInboxMessages())
|
||||||
numMessages = len(inboxMessages['inboxMessages'])
|
numMessages = len(inboxMessages['inboxMessages'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -926,16 +927,16 @@ def inbox(unreadOnly=False):
|
||||||
message = inboxMessages['inboxMessages'][msgNum]
|
message = inboxMessages['inboxMessages'][msgNum]
|
||||||
# if we are displaying all messages or if this message is unread then display it
|
# if we are displaying all messages or if this message is unread then display it
|
||||||
if not unreadOnly or not message['read']:
|
if not unreadOnly or not message['read']:
|
||||||
print ' -----------------------------------\n'
|
print(' -----------------------------------\n')
|
||||||
print ' Message Number:', msgNum # Message Number
|
print(' Message Number:', msgNum) # Message Number
|
||||||
print ' To:', getLabelForAddress(message['toAddress']) # Get the to address
|
print(' To:', getLabelForAddress(message['toAddress'])) # Get the to address
|
||||||
print ' From:', getLabelForAddress(message['fromAddress']) # Get the from address
|
print(' From:', getLabelForAddress(message['fromAddress'])) # Get the from address
|
||||||
print ' Subject:', message['subject'].decode('base64') # Get the subject
|
print(' Subject:', message['subject'].decode('base64')) # Get the subject
|
||||||
print ''.join([
|
print(''.join([
|
||||||
' Received:',
|
' Received:',
|
||||||
datetime.datetime.fromtimestamp(
|
datetime.datetime.fromtimestamp(
|
||||||
float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
float(message['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
])
|
]))
|
||||||
messagesPrinted += 1
|
messagesPrinted += 1
|
||||||
if not message['read']:
|
if not message['read']:
|
||||||
messagesUnread += 1
|
messagesUnread += 1
|
||||||
|
@ -943,9 +944,9 @@ def inbox(unreadOnly=False):
|
||||||
if messagesPrinted % 20 == 0 and messagesPrinted != 0:
|
if messagesPrinted % 20 == 0 and messagesPrinted != 0:
|
||||||
userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput =
|
userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput =
|
||||||
|
|
||||||
print '\n -----------------------------------'
|
print('\n -----------------------------------')
|
||||||
print ' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages)
|
print(' There are %d unread messages of %d messages in the inbox.' % (messagesUnread, numMessages))
|
||||||
print ' -----------------------------------\n'
|
print(' -----------------------------------\n')
|
||||||
|
|
||||||
|
|
||||||
def outbox():
|
def outbox():
|
||||||
|
@ -956,32 +957,32 @@ def outbox():
|
||||||
outboxMessages = json.loads(api.getAllSentMessages())
|
outboxMessages = json.loads(api.getAllSentMessages())
|
||||||
numMessages = len(outboxMessages['sentMessages'])
|
numMessages = len(outboxMessages['sentMessages'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
for msgNum in range(0, numMessages): # processes all of the messages in the outbox
|
for msgNum in range(0, numMessages): # processes all of the messages in the outbox
|
||||||
print '\n -----------------------------------\n'
|
print('\n -----------------------------------\n')
|
||||||
print ' Message Number:', msgNum # Message Number
|
print(' Message Number:', msgNum) # Message Number
|
||||||
# print ' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid']
|
# print(' Message ID:', outboxMessages['sentMessages'][msgNum]['msgid'])
|
||||||
print ' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) # Get the to address
|
# Get the to address
|
||||||
|
print(' To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']))
|
||||||
# Get the from address
|
# Get the from address
|
||||||
print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress'])
|
print(' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']))
|
||||||
print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') # Get the subject
|
print(' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64')) # Get the subject
|
||||||
print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] # Get the subject
|
print(' Status:', outboxMessages['sentMessages'][msgNum]['status']) # Get the subject
|
||||||
|
print(''.join([
|
||||||
print ''.join([
|
|
||||||
' Last Action Time:',
|
' Last Action Time:',
|
||||||
datetime.datetime.fromtimestamp(
|
datetime.datetime.fromtimestamp(
|
||||||
float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
])
|
]))
|
||||||
|
|
||||||
if msgNum % 20 == 0 and msgNum != 0:
|
if msgNum % 20 == 0 and msgNum != 0:
|
||||||
userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput =
|
userInput('(Press Enter to continue or type (Exit) to return to the main menu.)').lower() # uInput =
|
||||||
|
|
||||||
print '\n -----------------------------------'
|
print('\n -----------------------------------')
|
||||||
print ' There are ', numMessages, ' messages in the outbox.'
|
print(' There are ', numMessages, ' messages in the outbox.')
|
||||||
print ' -----------------------------------\n'
|
print(' -----------------------------------\n')
|
||||||
|
|
||||||
|
|
||||||
def readSentMsg(msgNum):
|
def readSentMsg(msgNum):
|
||||||
|
@ -992,14 +993,14 @@ def readSentMsg(msgNum):
|
||||||
outboxMessages = json.loads(api.getAllSentMessages())
|
outboxMessages = json.loads(api.getAllSentMessages())
|
||||||
numMessages = len(outboxMessages['sentMessages'])
|
numMessages = len(outboxMessages['sentMessages'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
if msgNum >= numMessages:
|
if msgNum >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
# Begin attachment detection
|
# Begin attachment detection
|
||||||
|
@ -1035,19 +1036,19 @@ def readSentMsg(msgNum):
|
||||||
|
|
||||||
# End attachment Detection
|
# End attachment Detection
|
||||||
|
|
||||||
print '\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress']) # Get the to address
|
print('\n To:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['toAddress'])) # Get the to address
|
||||||
# Get the from address
|
# Get the from address
|
||||||
print ' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress'])
|
print(' From:', getLabelForAddress(outboxMessages['sentMessages'][msgNum]['fromAddress']))
|
||||||
print ' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64') # Get the subject
|
print(' Subject:', outboxMessages['sentMessages'][msgNum]['subject'].decode('base64')) # Get the subject
|
||||||
print ' Status:', outboxMessages['sentMessages'][msgNum]['status'] # Get the subject
|
print(' Status:', outboxMessages['sentMessages'][msgNum]['status']) # Get the subject
|
||||||
print ''.join([
|
print(''.join([
|
||||||
' Last Action Time:',
|
' Last Action Time:',
|
||||||
datetime.datetime.fromtimestamp(
|
datetime.datetime.fromtimestamp(
|
||||||
float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
float(outboxMessages['sentMessages'][msgNum]['lastActionTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
])
|
]))
|
||||||
print ' Message:\n'
|
print(' Message:\n')
|
||||||
print message # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
|
print(message) # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
|
||||||
print ' '
|
print(' ')
|
||||||
|
|
||||||
|
|
||||||
def readMsg(msgNum):
|
def readMsg(msgNum):
|
||||||
|
@ -1057,12 +1058,12 @@ def readMsg(msgNum):
|
||||||
inboxMessages = json.loads(api.getAllInboxMessages())
|
inboxMessages = json.loads(api.getAllInboxMessages())
|
||||||
numMessages = len(inboxMessages['inboxMessages'])
|
numMessages = len(inboxMessages['inboxMessages'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
if msgNum >= numMessages:
|
if msgNum >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
# Begin attachment detection
|
# Begin attachment detection
|
||||||
|
@ -1097,17 +1098,17 @@ def readMsg(msgNum):
|
||||||
break
|
break
|
||||||
|
|
||||||
# End attachment Detection
|
# End attachment Detection
|
||||||
print '\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress']) # Get the to address
|
print('\n To:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['toAddress'])) # Get the to address
|
||||||
# Get the from address
|
# Get the from address
|
||||||
print ' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress'])
|
print(' From:', getLabelForAddress(inboxMessages['inboxMessages'][msgNum]['fromAddress']))
|
||||||
print ' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64') # Get the subject
|
print(' Subject:', inboxMessages['inboxMessages'][msgNum]['subject'].decode('base64')) # Get the subject
|
||||||
print ''.join([
|
print(''.join([
|
||||||
' Received:', datetime.datetime.fromtimestamp(
|
' Received:', datetime.datetime.fromtimestamp(
|
||||||
float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
float(inboxMessages['inboxMessages'][msgNum]['receivedTime'])).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
])
|
]))
|
||||||
print ' Message:\n'
|
print(' Message:\n')
|
||||||
print message # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
|
print(message) # inboxMessages['inboxMessages'][msgNum]['message'].decode('base64')
|
||||||
print ' '
|
print(' ')
|
||||||
return inboxMessages['inboxMessages'][msgNum]['msgid']
|
return inboxMessages['inboxMessages'][msgNum]['msgid']
|
||||||
|
|
||||||
|
|
||||||
|
@ -1119,7 +1120,7 @@ def replyMsg(msgNum, forwardORreply):
|
||||||
try:
|
try:
|
||||||
inboxMessages = json.loads(api.getAllInboxMessages())
|
inboxMessages = json.loads(api.getAllInboxMessages())
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1141,14 +1142,14 @@ def replyMsg(msgNum, forwardORreply):
|
||||||
|
|
||||||
if toAdd == "c":
|
if toAdd == "c":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
elif validAddress(toAdd) is False:
|
elif validAddress(toAdd) is False:
|
||||||
print '\n Invalid Address. "c" to cancel. Please try again.\n'
|
print('\n Invalid Address. "c" to cancel. Please try again.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print '\n Invalid Selection. Reply or Forward only'
|
print('\n Invalid Selection. Reply or Forward only')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1180,7 +1181,7 @@ def delMsg(msgNum):
|
||||||
|
|
||||||
msgAck = api.trashMessage(msgId)
|
msgAck = api.trashMessage(msgId)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1197,7 +1198,7 @@ def delSentMsg(msgNum):
|
||||||
msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid']
|
msgId = outboxMessages['sentMessages'][int(msgNum)]['msgid']
|
||||||
msgAck = api.trashSentMessage(msgId)
|
msgAck = api.trashSentMessage(msgId)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1233,7 +1234,7 @@ def buildKnownAddresses():
|
||||||
if entry['address'] not in knownAddresses:
|
if entry['address'] not in knownAddresses:
|
||||||
knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
|
knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1248,7 +1249,7 @@ def buildKnownAddresses():
|
||||||
if entry['address'] not in knownAddresses:
|
if entry['address'] not in knownAddresses:
|
||||||
knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
|
knownAddresses[entry['address']] = "%s (%s)" % (entry['label'].decode('base64'), entry['address'])
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1263,21 +1264,20 @@ def listAddressBookEntries():
|
||||||
if "API Error" in response:
|
if "API Error" in response:
|
||||||
return getAPIErrorCode(response)
|
return getAPIErrorCode(response)
|
||||||
addressBook = json.loads(response)
|
addressBook = json.loads(response)
|
||||||
print
|
print()
|
||||||
print ' --------------------------------------------------------------'
|
print(' --------------------------------------------------------------')
|
||||||
print ' | Label | Address |'
|
print(' | Label | Address |')
|
||||||
print ' |--------------------|---------------------------------------|'
|
print(' |--------------------|---------------------------------------|')
|
||||||
for entry in addressBook['addresses']:
|
for entry in addressBook['addresses']:
|
||||||
label = entry['label'].decode('base64')
|
label = entry['label'].decode('base64')
|
||||||
address = entry['address']
|
address = entry['address']
|
||||||
if len(label) > 19:
|
if len(label) > 19:
|
||||||
label = label[:16] + '...'
|
label = label[:16] + '...'
|
||||||
print ' | ' + label.ljust(19) + '| ' + address.ljust(37) + ' |'
|
print(' | ' + label.ljust(19) + '| ' + address.ljust(37) + ' |')
|
||||||
print ' --------------------------------------------------------------'
|
print(' --------------------------------------------------------------')
|
||||||
print
|
print()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1292,7 +1292,7 @@ def addAddressToAddressBook(address, label):
|
||||||
if "API Error" in response:
|
if "API Error" in response:
|
||||||
return getAPIErrorCode(response)
|
return getAPIErrorCode(response)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1307,7 +1307,7 @@ def deleteAddressFromAddressBook(address):
|
||||||
if "API Error" in response:
|
if "API Error" in response:
|
||||||
return getAPIErrorCode(response)
|
return getAPIErrorCode(response)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1331,7 +1331,7 @@ def markMessageRead(messageID):
|
||||||
if "API Error" in response:
|
if "API Error" in response:
|
||||||
return getAPIErrorCode(response)
|
return getAPIErrorCode(response)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1346,7 +1346,7 @@ def markMessageUnread(messageID):
|
||||||
if "API Error" in response:
|
if "API Error" in response:
|
||||||
return getAPIErrorCode(response)
|
return getAPIErrorCode(response)
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1359,7 +1359,7 @@ def markAllMessagesRead():
|
||||||
try:
|
try:
|
||||||
inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
|
inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
for message in inboxMessages:
|
for message in inboxMessages:
|
||||||
|
@ -1375,7 +1375,7 @@ def markAllMessagesUnread():
|
||||||
try:
|
try:
|
||||||
inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
|
inboxMessages = json.loads(api.getAllInboxMessages())['inboxMessages']
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
for message in inboxMessages:
|
for message in inboxMessages:
|
||||||
|
@ -1391,15 +1391,15 @@ def clientStatus():
|
||||||
try:
|
try:
|
||||||
client_status = json.loads(api.clientStatus())
|
client_status = json.loads(api.clientStatus())
|
||||||
except:
|
except:
|
||||||
print '\n Connection Error\n'
|
print('\n Connection Error\n')
|
||||||
usrPrompt = 0
|
usrPrompt = 0
|
||||||
main()
|
main()
|
||||||
|
|
||||||
print "\nnetworkStatus: " + client_status['networkStatus'] + "\n"
|
print("\nnetworkStatus: " + client_status['networkStatus'] + "\n")
|
||||||
print "\nnetworkConnections: " + str(client_status['networkConnections']) + "\n"
|
print("\nnetworkConnections: " + str(client_status['networkConnections']) + "\n")
|
||||||
print "\nnumberOfPubkeysProcessed: " + str(client_status['numberOfPubkeysProcessed']) + "\n"
|
print("\nnumberOfPubkeysProcessed: " + str(client_status['numberOfPubkeysProcessed']) + "\n")
|
||||||
print "\nnumberOfMessagesProcessed: " + str(client_status['numberOfMessagesProcessed']) + "\n"
|
print("\nnumberOfMessagesProcessed: " + str(client_status['numberOfMessagesProcessed']) + "\n")
|
||||||
print "\nnumberOfBroadcastsProcessed: " + str(client_status['numberOfBroadcastsProcessed']) + "\n"
|
print("\nnumberOfBroadcastsProcessed: " + str(client_status['numberOfBroadcastsProcessed']) + "\n")
|
||||||
|
|
||||||
|
|
||||||
def shutdown():
|
def shutdown():
|
||||||
|
@ -1409,7 +1409,7 @@ def shutdown():
|
||||||
api.shutdown()
|
api.shutdown()
|
||||||
except socket.error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
print "\nShutdown command relayed\n"
|
print("\nShutdown command relayed\n")
|
||||||
|
|
||||||
|
|
||||||
def UI(usrInput):
|
def UI(usrInput):
|
||||||
|
@ -1418,75 +1418,75 @@ def UI(usrInput):
|
||||||
global usrPrompt
|
global usrPrompt
|
||||||
|
|
||||||
if usrInput == "help" or usrInput == "h" or usrInput == "?":
|
if usrInput == "help" or usrInput == "h" or usrInput == "?":
|
||||||
print ' '
|
print(' ')
|
||||||
print ' -------------------------------------------------------------------------'
|
print(' -------------------------------------------------------------------------')
|
||||||
print ' | https://github.com/Dokument/PyBitmessage-Daemon |'
|
print(' | https://github.com/Dokument/PyBitmessage-Daemon |')
|
||||||
print ' |-----------------------------------------------------------------------|'
|
print(' |-----------------------------------------------------------------------|')
|
||||||
print ' | Command | Description |'
|
print(' | Command | Description |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | help | This help file. |'
|
print(' | help | This help file. |')
|
||||||
print ' | apiTest | Tests the API |'
|
print(' | apiTest | Tests the API |')
|
||||||
print ' | addInfo | Returns address information (If valid) |'
|
print(' | addInfo | Returns address information (If valid) |')
|
||||||
print ' | bmSettings | BitMessage settings |'
|
print(' | bmSettings | BitMessage settings |')
|
||||||
print ' | exit | Use anytime to return to main menu |'
|
print(' | exit | Use anytime to return to main menu |')
|
||||||
print ' | quit | Quits the program |'
|
print(' | quit | Quits the program |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | listAddresses | Lists all of the users addresses |'
|
print(' | listAddresses | Lists all of the users addresses |')
|
||||||
print ' | generateAddress | Generates a new address |'
|
print(' | generateAddress | Generates a new address |')
|
||||||
print ' | getAddress | Get determinist address from passphrase |'
|
print(' | getAddress | Get determinist address from passphrase |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | listAddressBookEntries | Lists entries from the Address Book |'
|
print(' | listAddressBookEntries | Lists entries from the Address Book |')
|
||||||
print ' | addAddressBookEntry | Add address to the Address Book |'
|
print(' | addAddressBookEntry | Add address to the Address Book |')
|
||||||
print ' | deleteAddressBookEntry | Deletes address from the Address Book |'
|
print(' | deleteAddressBookEntry | Deletes address from the Address Book |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | subscribe | Subscribes to an address |'
|
print(' | subscribe | Subscribes to an address |')
|
||||||
print ' | unsubscribe | Unsubscribes from an address |'
|
print(' | unsubscribe | Unsubscribes from an address |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | create | Creates a channel |'
|
print(' | create | Creates a channel |')
|
||||||
print ' | join | Joins a channel |'
|
print(' | join | Joins a channel |')
|
||||||
print ' | leave | Leaves a channel |'
|
print(' | leave | Leaves a channel |')
|
||||||
print ' |------------------------|----------------------------------------------|'
|
print(' |------------------------|----------------------------------------------|')
|
||||||
print ' | inbox | Lists the message information for the inbox |'
|
print(' | inbox | Lists the message information for the inbox |')
|
||||||
print ' | outbox | Lists the message information for the outbox |'
|
print(' | outbox | Lists the message information for the outbox |')
|
||||||
print ' | send | Send a new message or broadcast |'
|
print(' | send | Send a new message or broadcast |')
|
||||||
print ' | unread | Lists all unread inbox messages |'
|
print(' | unread | Lists all unread inbox messages |')
|
||||||
print ' | read | Reads a message from the inbox or outbox |'
|
print(' | read | Reads a message from the inbox or outbox |')
|
||||||
print ' | save | Saves message to text file |'
|
print(' | save | Saves message to text file |')
|
||||||
print ' | delete | Deletes a message or all messages |'
|
print(' | delete | Deletes a message or all messages |')
|
||||||
print ' -------------------------------------------------------------------------'
|
print(' -------------------------------------------------------------------------')
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "apitest": # tests the API Connection.
|
elif usrInput == "apitest": # tests the API Connection.
|
||||||
if apiTest():
|
if apiTest():
|
||||||
print '\n API connection test has: PASSED\n'
|
print('\n API connection test has: PASSED\n')
|
||||||
else:
|
else:
|
||||||
print '\n API connection test has: FAILED\n'
|
print('\n API connection test has: FAILED\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "addinfo":
|
elif usrInput == "addinfo":
|
||||||
tmp_address = userInput('\nEnter the Bitmessage Address.')
|
tmp_address = userInput('\nEnter the Bitmessage Address.')
|
||||||
address_information = json.loads(api.decodeAddress(tmp_address))
|
address_information = json.loads(api.decodeAddress(tmp_address))
|
||||||
|
|
||||||
print '\n------------------------------'
|
print('\n------------------------------')
|
||||||
|
|
||||||
if 'success' in str(address_information['status']).lower():
|
if 'success' in str(address_information['status']).lower():
|
||||||
print ' Valid Address'
|
print(' Valid Address')
|
||||||
print ' Address Version: %s' % str(address_information['addressVersion'])
|
print(' Address Version: %s' % str(address_information['addressVersion']))
|
||||||
print ' Stream Number: %s' % str(address_information['streamNumber'])
|
print(' Stream Number: %s' % str(address_information['streamNumber']))
|
||||||
else:
|
else:
|
||||||
print ' Invalid Address !'
|
print(' Invalid Address !')
|
||||||
|
|
||||||
print '------------------------------\n'
|
print('------------------------------\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "bmsettings": # tests the API Connection.
|
elif usrInput == "bmsettings": # tests the API Connection.
|
||||||
bmSettings()
|
bmSettings()
|
||||||
print ' '
|
print(' ')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "quit": # Quits the application
|
elif usrInput == "quit": # Quits the application
|
||||||
print '\n Bye\n'
|
print('\n Bye\n')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
elif usrInput == "listaddresses": # Lists all of the identities in the addressbook
|
elif usrInput == "listaddresses": # Lists all of the identities in the addressbook
|
||||||
|
@ -1508,17 +1508,17 @@ def UI(usrInput):
|
||||||
|
|
||||||
if isRipe == "y":
|
if isRipe == "y":
|
||||||
ripe = True
|
ripe = True
|
||||||
print genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe)
|
print(genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe))
|
||||||
main()
|
main()
|
||||||
elif isRipe == "n":
|
elif isRipe == "n":
|
||||||
ripe = False
|
ripe = False
|
||||||
print genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe)
|
print(genAdd(lbl, deterministic, passphrase, numOfAdd, addVNum, streamNum, ripe))
|
||||||
main()
|
main()
|
||||||
elif isRipe == "exit":
|
elif isRipe == "exit":
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
print '\n Invalid input\n'
|
print('\n Invalid input\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif uInput == "r" or uInput == "random": # Creates a random address with user-defined label
|
elif uInput == "r" or uInput == "random": # Creates a random address with user-defined label
|
||||||
|
@ -1526,18 +1526,18 @@ def UI(usrInput):
|
||||||
null = ''
|
null = ''
|
||||||
lbl = userInput('Enter the label for the new address.')
|
lbl = userInput('Enter the label for the new address.')
|
||||||
|
|
||||||
print genAdd(lbl, deterministic, null, null, null, null, null)
|
print(genAdd(lbl, deterministic, null, null, null, null, null))
|
||||||
main()
|
main()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print '\n Invalid input\n'
|
print('\n Invalid input\n')
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "getaddress": # Gets the address for/from a passphrase
|
elif usrInput == "getaddress": # Gets the address for/from a passphrase
|
||||||
phrase = userInput("Enter the address passphrase.")
|
phrase = userInput("Enter the address passphrase.")
|
||||||
print '\n Working...\n'
|
print('\n Working...\n')
|
||||||
address = getAddress(phrase, 4, 1) # ,vNumber,sNumber)
|
address = getAddress(phrase, 4, 1) # ,vNumber,sNumber)
|
||||||
print '\n Address: ' + address + '\n'
|
print('\n Address: ' + address + '\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1572,17 +1572,17 @@ def UI(usrInput):
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "inbox":
|
elif usrInput == "inbox":
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
inbox()
|
inbox()
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "unread":
|
elif usrInput == "unread":
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
inbox(True)
|
inbox(True)
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "outbox":
|
elif usrInput == "outbox":
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
outbox()
|
outbox()
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1603,14 +1603,14 @@ def UI(usrInput):
|
||||||
uInput = userInput("Would you like to read a message from the (I)nbox or (O)utbox?").lower()
|
uInput = userInput("Would you like to read a message from the (I)nbox or (O)utbox?").lower()
|
||||||
|
|
||||||
if (uInput != 'i' and uInput != 'inbox' and uInput != 'o' and uInput != 'outbox'):
|
if (uInput != 'i' and uInput != 'inbox' and uInput != 'o' and uInput != 'outbox'):
|
||||||
print '\n Invalid Input.\n'
|
print('\n Invalid Input.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
msgNum = int(userInput("What is the number of the message you wish to open?"))
|
msgNum = int(userInput("What is the number of the message you wish to open?"))
|
||||||
|
|
||||||
if (uInput == 'i' or uInput == 'inbox'):
|
if (uInput == 'i' or uInput == 'inbox'):
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
messageID = readMsg(msgNum)
|
messageID = readMsg(msgNum)
|
||||||
|
|
||||||
uInput = userInput("\nWould you like to keep this message unread, (Y)es or (N)o?").lower()
|
uInput = userInput("\nWould you like to keep this message unread, (Y)es or (N)o?").lower()
|
||||||
|
@ -1622,14 +1622,14 @@ def UI(usrInput):
|
||||||
uInput = userInput("\nWould you like to (D)elete, (F)orward, (R)eply to, or (Exit) this message?").lower()
|
uInput = userInput("\nWould you like to (D)elete, (F)orward, (R)eply to, or (Exit) this message?").lower()
|
||||||
|
|
||||||
if uInput in ['r', 'reply']:
|
if uInput in ['r', 'reply']:
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
print ' '
|
print(' ')
|
||||||
replyMsg(msgNum, 'reply')
|
replyMsg(msgNum, 'reply')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
|
|
||||||
elif uInput == 'f' or uInput == 'forward':
|
elif uInput == 'f' or uInput == 'forward':
|
||||||
print '\n Loading...\n'
|
print('\n Loading...\n')
|
||||||
print ' '
|
print(' ')
|
||||||
replyMsg(msgNum, 'forward')
|
replyMsg(msgNum, 'forward')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
|
|
||||||
|
@ -1638,12 +1638,12 @@ def UI(usrInput):
|
||||||
|
|
||||||
if uInput == "y":
|
if uInput == "y":
|
||||||
delMsg(msgNum)
|
delMsg(msgNum)
|
||||||
print '\n Message Deleted.\n'
|
print('\n Message Deleted.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
print '\n Invalid entry\n'
|
print('\n Invalid entry\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
|
|
||||||
elif (uInput == 'o' or uInput == 'outbox'):
|
elif (uInput == 'o' or uInput == 'outbox'):
|
||||||
|
@ -1657,12 +1657,12 @@ def UI(usrInput):
|
||||||
|
|
||||||
if uInput == "y":
|
if uInput == "y":
|
||||||
delSentMsg(msgNum)
|
delSentMsg(msgNum)
|
||||||
print '\n Message Deleted.\n'
|
print('\n Message Deleted.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
print '\n Invalid Entry\n'
|
print('\n Invalid Entry\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
@ -1672,7 +1672,7 @@ def UI(usrInput):
|
||||||
uInput = userInput("Would you like to save a message from the (I)nbox or (O)utbox?").lower()
|
uInput = userInput("Would you like to save a message from the (I)nbox or (O)utbox?").lower()
|
||||||
|
|
||||||
if uInput not in ['i', 'inbox', 'o', 'outbox']:
|
if uInput not in ['i', 'inbox', 'o', 'outbox']:
|
||||||
print '\n Invalid Input.\n'
|
print('\n Invalid Input.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1684,7 +1684,7 @@ def UI(usrInput):
|
||||||
msgNum = int(userInput("What is the number of the message you wish to save?"))
|
msgNum = int(userInput("What is the number of the message you wish to save?"))
|
||||||
|
|
||||||
if msgNum >= numMessages:
|
if msgNum >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1700,7 +1700,7 @@ def UI(usrInput):
|
||||||
msgNum = int(userInput("What is the number of the message you wish to save?"))
|
msgNum = int(userInput("What is the number of the message you wish to save?"))
|
||||||
|
|
||||||
if msgNum >= numMessages:
|
if msgNum >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1729,7 +1729,7 @@ def UI(usrInput):
|
||||||
if msgNum == 'a' or msgNum == 'all':
|
if msgNum == 'a' or msgNum == 'all':
|
||||||
break
|
break
|
||||||
elif int(msgNum) >= numMessages:
|
elif int(msgNum) >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1737,17 +1737,17 @@ def UI(usrInput):
|
||||||
|
|
||||||
if uInput == "y":
|
if uInput == "y":
|
||||||
if msgNum in ['a', 'all']:
|
if msgNum in ['a', 'all']:
|
||||||
print ' '
|
print(' ')
|
||||||
for msgNum in range(0, numMessages): # processes all of the messages in the inbox
|
for msgNum in range(0, numMessages): # processes all of the messages in the inbox
|
||||||
print ' Deleting message ', msgNum + 1, ' of ', numMessages
|
print(' Deleting message ', msgNum + 1, ' of ', numMessages)
|
||||||
delMsg(0)
|
delMsg(0)
|
||||||
|
|
||||||
print '\n Inbox is empty.'
|
print('\n Inbox is empty.')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
delMsg(int(msgNum))
|
delMsg(int(msgNum))
|
||||||
|
|
||||||
print '\n Notice: Message numbers may have changed.\n'
|
print('\n Notice: Message numbers may have changed.\n')
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
|
@ -1763,7 +1763,7 @@ def UI(usrInput):
|
||||||
if msgNum in ['a', 'all']:
|
if msgNum in ['a', 'all']:
|
||||||
break
|
break
|
||||||
elif int(msgNum) >= numMessages:
|
elif int(msgNum) >= numMessages:
|
||||||
print '\n Invalid Message Number.\n'
|
print('\n Invalid Message Number.\n')
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -1771,33 +1771,33 @@ def UI(usrInput):
|
||||||
|
|
||||||
if uInput == "y":
|
if uInput == "y":
|
||||||
if msgNum in ['a', 'all']:
|
if msgNum in ['a', 'all']:
|
||||||
print ' '
|
print(' ')
|
||||||
for msgNum in range(0, numMessages): # processes all of the messages in the outbox
|
for msgNum in range(0, numMessages): # processes all of the messages in the outbox
|
||||||
print ' Deleting message ', msgNum + 1, ' of ', numMessages
|
print(' Deleting message ', msgNum + 1, ' of ', numMessages)
|
||||||
delSentMsg(0)
|
delSentMsg(0)
|
||||||
|
|
||||||
print '\n Outbox is empty.'
|
print('\n Outbox is empty.')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
delSentMsg(int(msgNum))
|
delSentMsg(int(msgNum))
|
||||||
print '\n Notice: Message numbers may have changed.\n'
|
print('\n Notice: Message numbers may have changed.\n')
|
||||||
main()
|
main()
|
||||||
else:
|
else:
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
else:
|
else:
|
||||||
print '\n Invalid Entry.\n'
|
print('\n Invalid Entry.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "exit":
|
elif usrInput == "exit":
|
||||||
print '\n You are already at the main menu. Use "quit" to quit.\n'
|
print('\n You are already at the main menu. Use "quit" to quit.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
elif usrInput == "listaddressbookentries":
|
elif usrInput == "listaddressbookentries":
|
||||||
res = listAddressBookEntries()
|
res = listAddressBookEntries()
|
||||||
if res == 20:
|
if res == 20:
|
||||||
print '\n Error: API function not supported.\n'
|
print('\n Error: API function not supported.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1806,9 +1806,9 @@ def UI(usrInput):
|
||||||
label = userInput('Enter label')
|
label = userInput('Enter label')
|
||||||
res = addAddressToAddressBook(address, label)
|
res = addAddressToAddressBook(address, label)
|
||||||
if res == 16:
|
if res == 16:
|
||||||
print '\n Error: Address already exists in Address Book.\n'
|
print('\n Error: Address already exists in Address Book.\n')
|
||||||
if res == 20:
|
if res == 20:
|
||||||
print '\n Error: API function not supported.\n'
|
print('\n Error: API function not supported.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1816,7 +1816,7 @@ def UI(usrInput):
|
||||||
address = userInput('Enter address')
|
address = userInput('Enter address')
|
||||||
res = deleteAddressFromAddressBook(address)
|
res = deleteAddressFromAddressBook(address)
|
||||||
if res == 20:
|
if res == 20:
|
||||||
print '\n Error: API function not supported.\n'
|
print('\n Error: API function not supported.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1841,7 +1841,7 @@ def UI(usrInput):
|
||||||
main()
|
main()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print '\n "', usrInput, '" is not a command.\n'
|
print('\n "', usrInput, '" is not a command.\n')
|
||||||
usrPrompt = 1
|
usrPrompt = 1
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
@ -1853,24 +1853,24 @@ def main():
|
||||||
global usrPrompt
|
global usrPrompt
|
||||||
|
|
||||||
if usrPrompt == 0:
|
if usrPrompt == 0:
|
||||||
print '\n ------------------------------'
|
print('\n ------------------------------')
|
||||||
print ' | Bitmessage Daemon by .dok |'
|
print(' | Bitmessage Daemon by .dok |')
|
||||||
print ' | Version 0.3.1 for BM 0.6.2 |'
|
print(' | Version 0.3.1 for BM 0.6.2 |')
|
||||||
print ' ------------------------------'
|
print(' ------------------------------')
|
||||||
api = xmlrpclib.ServerProxy(apiData()) # Connect to BitMessage using these api credentials
|
api = xmlrpclib.ServerProxy(apiData()) # Connect to BitMessage using these api credentials
|
||||||
|
|
||||||
if apiTest() is False:
|
if apiTest() is False:
|
||||||
print '\n ****************************************************************'
|
print('\n ****************************************************************')
|
||||||
print ' WARNING: You are not connected to the Bitmessage client.'
|
print(' WARNING: You are not connected to the Bitmessage client.')
|
||||||
print ' Either Bitmessage is not running or your settings are incorrect.'
|
print(' Either Bitmessage is not running or your settings are incorrect.')
|
||||||
print ' Use the command "apiTest" or "bmSettings" to resolve this issue.'
|
print(' Use the command "apiTest" or "bmSettings" to resolve this issue.')
|
||||||
print ' ****************************************************************\n'
|
print(' ****************************************************************\n')
|
||||||
|
|
||||||
print 'Type (H)elp for a list of commands.' # Startup message
|
print('Type (H)elp for a list of commands.') # Startup message
|
||||||
usrPrompt = 2
|
usrPrompt = 2
|
||||||
|
|
||||||
elif usrPrompt == 1:
|
elif usrPrompt == 1:
|
||||||
print '\nType (H)elp for a list of commands.' # Startup message
|
print('\nType (H)elp for a list of commands.') # Startup message
|
||||||
usrPrompt = 2
|
usrPrompt = 2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -258,7 +258,7 @@ def drawtab(stdscr):
|
||||||
stdscr.addstr(6, 18, "Connections", curses.A_BOLD)
|
stdscr.addstr(6, 18, "Connections", curses.A_BOLD)
|
||||||
stdscr.hline(7, 6, '-', 23)
|
stdscr.hline(7, 6, '-', 23)
|
||||||
streamcount = []
|
streamcount = []
|
||||||
for host, stream in connected_hosts:
|
for _, stream in connected_hosts:
|
||||||
if stream >= len(streamcount):
|
if stream >= len(streamcount):
|
||||||
streamcount.append(1)
|
streamcount.append(1)
|
||||||
else:
|
else:
|
||||||
|
@ -1016,7 +1016,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
|
||||||
def loadInbox():
|
def loadInbox():
|
||||||
"""Load the list of messages"""
|
"""Load the list of messages"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print "Loading inbox messages..."
|
print("Loading inbox messages...")
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
where = "toaddress || fromaddress || subject || message"
|
where = "toaddress || fromaddress || subject || message"
|
||||||
|
@ -1068,7 +1068,7 @@ def loadInbox():
|
||||||
def loadSent():
|
def loadSent():
|
||||||
"""Load the messages that sent"""
|
"""Load the messages that sent"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print "Loading sent messages..."
|
print("Loading sent messages...")
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
where = "toaddress || fromaddress || subject || message"
|
where = "toaddress || fromaddress || subject || message"
|
||||||
|
@ -1154,7 +1154,7 @@ def loadSent():
|
||||||
def loadAddrBook():
|
def loadAddrBook():
|
||||||
"""Load address book"""
|
"""Load address book"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print "Loading address book..."
|
print("Loading address book...")
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
|
|
||||||
ret = sqlQuery("SELECT label, address FROM addressbook")
|
ret = sqlQuery("SELECT label, address FROM addressbook")
|
||||||
|
@ -1261,7 +1261,7 @@ def run(stdscr):
|
||||||
def doShutdown():
|
def doShutdown():
|
||||||
"""Shutting the app down"""
|
"""Shutting the app down"""
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
print "Shutting down..."
|
print("Shutting down...")
|
||||||
sys.stdout = printlog
|
sys.stdout = printlog
|
||||||
shutdown.doCleanShutdown()
|
shutdown.doCleanShutdown()
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
Core classes for loading images and converting them to a Texture.
|
Core classes for loading images and converting them to a Texture.
|
||||||
The raw image data can be keep in memory for further access
|
The raw image data can be keep in memory for further access
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ from kivy.uix.image import Image as kiImage
|
||||||
|
|
||||||
|
|
||||||
# constants
|
# constants
|
||||||
RESOLUTION = 128, 128
|
RESOLUTION = 300, 300
|
||||||
V_RESOLUTION = 7, 7
|
V_RESOLUTION = 7, 7
|
||||||
BACKGROUND_COLOR = 255, 255, 255, 255
|
BACKGROUND_COLOR = 255, 255, 255, 255
|
||||||
MODE = "RGB"
|
MODE = "RGB"
|
||||||
|
@ -26,7 +25,6 @@ def generate(Generate_string=None):
|
||||||
image = Image.new(MODE, V_RESOLUTION, BACKGROUND_COLOR)
|
image = Image.new(MODE, V_RESOLUTION, BACKGROUND_COLOR)
|
||||||
image = generate_image(image, color, hash_string)
|
image = generate_image(image, color, hash_string)
|
||||||
image = image.resize(RESOLUTION, 0)
|
image = image.resize(RESOLUTION, 0)
|
||||||
|
|
||||||
data = BytesIO()
|
data = BytesIO()
|
||||||
image.save(data, format='png')
|
image.save(data, format='png')
|
||||||
data.seek(0)
|
data.seek(0)
|
||||||
|
@ -45,13 +43,11 @@ def generate_hash(string):
|
||||||
# make input case insensitive
|
# make input case insensitive
|
||||||
string = str.lower(string)
|
string = str.lower(string)
|
||||||
hash_object = hashlib.md5(str.encode(string))
|
hash_object = hashlib.md5(str.encode(string))
|
||||||
print hash_object.hexdigest()
|
print(hash_object.hexdigest())
|
||||||
|
|
||||||
# returned object is a hex string
|
# returned object is a hex string
|
||||||
return hash_object.hexdigest()
|
return hash_object.hexdigest()
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
print "Error: Please enter a string as an argument."
|
print("Error: Please enter a string as an argument.")
|
||||||
|
|
||||||
|
|
||||||
def random_color(hash_string):
|
def random_color(hash_string):
|
||||||
|
@ -59,35 +55,27 @@ def random_color(hash_string):
|
||||||
# remove first three digits from hex string
|
# remove first three digits from hex string
|
||||||
split = 6
|
split = 6
|
||||||
rgb = hash_string[:split]
|
rgb = hash_string[:split]
|
||||||
|
|
||||||
split = 2
|
split = 2
|
||||||
r = rgb[:split]
|
r = rgb[:split]
|
||||||
g = rgb[split:2 * split]
|
g = rgb[split:2 * split]
|
||||||
b = rgb[2 * split:3 * split]
|
b = rgb[2 * split:3 * split]
|
||||||
|
color = (int(r, 16), int(g, 16), int(b, 16), 0xFF)
|
||||||
color = (int(r, 16), int(g, 16),
|
|
||||||
int(b, 16), 0xFF)
|
|
||||||
|
|
||||||
return color
|
return color
|
||||||
|
|
||||||
|
|
||||||
def generate_image(image, color, hash_string):
|
def generate_image(image, color, hash_string):
|
||||||
"""Generating images"""
|
"""Generating images"""
|
||||||
hash_string = hash_string[6:]
|
hash_string = hash_string[6:]
|
||||||
|
|
||||||
lower_x = 1
|
lower_x = 1
|
||||||
lower_y = 1
|
lower_y = 1
|
||||||
upper_x = int(V_RESOLUTION[0] / 2) + 1
|
upper_x = int(V_RESOLUTION[0] / 2) + 1
|
||||||
upper_y = V_RESOLUTION[1] - 1
|
upper_y = V_RESOLUTION[1] - 1
|
||||||
limit_x = V_RESOLUTION[0] - 1
|
limit_x = V_RESOLUTION[0] - 1
|
||||||
index = 0
|
index = 0
|
||||||
|
|
||||||
for x in range(lower_x, upper_x):
|
for x in range(lower_x, upper_x):
|
||||||
for y in range(lower_y, upper_y):
|
for y in range(lower_y, upper_y):
|
||||||
if int(hash_string[index], 16) % 2 == 0:
|
if int(hash_string[index], 16) % 2 == 0:
|
||||||
image.putpixel((x, y), color)
|
image.putpixel((x, y), color)
|
||||||
image.putpixel((limit_x - x, y), color)
|
image.putpixel((limit_x - x, y), color)
|
||||||
|
|
||||||
index = index + 1
|
index = index + 1
|
||||||
|
|
||||||
return image
|
return image
|
||||||
|
|
|
@ -7,24 +7,24 @@ from helper_sql import sqlQuery
|
||||||
def search_sql(
|
def search_sql(
|
||||||
xAddress="toaddress", account=None, folder="inbox", where=None,
|
xAddress="toaddress", account=None, folder="inbox", where=None,
|
||||||
what=None, unreadOnly=False, start_indx=0, end_indx=20):
|
what=None, unreadOnly=False, start_indx=0, end_indx=20):
|
||||||
"""Method helping for searching mails"""
|
|
||||||
# pylint: disable=too-many-arguments, too-many-branches
|
# pylint: disable=too-many-arguments, too-many-branches
|
||||||
|
"""Method helping for searching mails"""
|
||||||
if what is not None and what != "":
|
if what is not None and what != "":
|
||||||
what = "%" + what + "%"
|
what = "%" + what + "%"
|
||||||
else:
|
else:
|
||||||
what = None
|
what = None
|
||||||
|
if folder in ("sent", "draft"):
|
||||||
if folder == "sent" or folder == "draft":
|
|
||||||
sqlStatementBase = (
|
sqlStatementBase = (
|
||||||
'''SELECT toaddress, fromaddress, subject, message, status,'''
|
'''SELECT toaddress, fromaddress, subject, message, status,'''
|
||||||
''' ackdata, lastactiontime FROM sent ''')
|
''' ackdata, senttime FROM sent '''
|
||||||
|
)
|
||||||
elif folder == "addressbook":
|
elif folder == "addressbook":
|
||||||
sqlStatementBase = '''SELECT label, address From addressbook '''
|
sqlStatementBase = '''SELECT label, address From addressbook '''
|
||||||
else:
|
else:
|
||||||
sqlStatementBase = (
|
sqlStatementBase = (
|
||||||
'''SELECT folder, msgid, toaddress, message, fromaddress,'''
|
'''SELECT folder, msgid, toaddress, message, fromaddress,'''
|
||||||
''' subject, received, read FROM inbox ''')
|
''' subject, received, read FROM inbox '''
|
||||||
|
)
|
||||||
sqlStatementParts = []
|
sqlStatementParts = []
|
||||||
sqlArguments = []
|
sqlArguments = []
|
||||||
if account is not None:
|
if account is not None:
|
||||||
|
@ -60,9 +60,10 @@ def search_sql(
|
||||||
sqlStatementParts.append("read = 0")
|
sqlStatementParts.append("read = 0")
|
||||||
if sqlStatementParts:
|
if sqlStatementParts:
|
||||||
sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts)
|
sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts)
|
||||||
if folder == "sent" or folder == "draft":
|
# if folder in ("sent", "draft"):
|
||||||
|
if folder in ("sent", "draft"):
|
||||||
sqlStatementBase += \
|
sqlStatementBase += \
|
||||||
" ORDER BY lastactiontime DESC limit {0}, {1}".format(
|
"ORDER BY senttime DESC limit {0}, {1}".format(
|
||||||
start_indx, end_indx)
|
start_indx, end_indx)
|
||||||
elif folder == "inbox":
|
elif folder == "inbox":
|
||||||
sqlStatementBase += \
|
sqlStatementBase += \
|
||||||
|
|
24
src/bitmessagekivy/kv/addressbook.kv
Normal file
24
src/bitmessagekivy/kv/addressbook.kv
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<AddressBook>:
|
||||||
|
name: 'addressbook'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
SearchBar:
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 0, 0, 5]
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
||||||
|
ComposerButton:
|
24
src/bitmessagekivy/kv/allmails.kv
Normal file
24
src/bitmessagekivy/kv/allmails.kv
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<Allmails>:
|
||||||
|
name: 'allmails'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 20, 0, 5]
|
||||||
|
spacing: dp(5)
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
||||||
|
ComposerButton:
|
65
src/bitmessagekivy/kv/common_widgets.kv
Normal file
65
src/bitmessagekivy/kv/common_widgets.kv
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<ArrowImg@Image>:
|
||||||
|
source: './images/down-arrow.png' if self.parent.is_open == True else './images/right-arrow.png'
|
||||||
|
size: 15, 15
|
||||||
|
x: self.parent.x + self.parent.width - self.width - 5
|
||||||
|
y: self.parent.y + self.parent.height/2 - self.height + 5
|
||||||
|
|
||||||
|
<SearchBar@BoxLayout>:
|
||||||
|
id: search_bar
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
|
||||||
|
MDIconButton:
|
||||||
|
icon: 'magnify'
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
id: search_field
|
||||||
|
hint_text: 'Search'
|
||||||
|
on_text: app.searchQuery(self)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
||||||
|
|
||||||
|
<Loader@MDSpinner>:
|
||||||
|
id: spinner
|
||||||
|
size_hint: None, None
|
||||||
|
size: dp(46), dp(46)
|
||||||
|
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
|
||||||
|
active: False
|
||||||
|
|
||||||
|
<ComposerButton@BoxLayout>:
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(56)
|
||||||
|
spacing: '10dp'
|
||||||
|
pos_hint: {'center_x':0.45, 'center_y': .1}
|
||||||
|
|
||||||
|
Widget:
|
||||||
|
|
||||||
|
MDFloatingActionButton:
|
||||||
|
icon: 'plus'
|
||||||
|
opposite_colors: True
|
||||||
|
elevation_normal: 8
|
||||||
|
md_bg_color: [0.941, 0, 0,1]
|
||||||
|
on_press: app.root.ids.scr_mngr.current = 'create'
|
||||||
|
on_press: app.clear_composer()
|
||||||
|
|
||||||
|
|
||||||
|
<CopyTextBtn@Button>:
|
||||||
|
id: cpyButton
|
||||||
|
color: 0,0,0,1
|
||||||
|
background_color: (0,0,0,0)
|
||||||
|
center_x: self.parent.center_x * 2 - self.parent.parent.padding[0]/2
|
||||||
|
center_y: self.parent.center_y
|
||||||
|
on_press:app.root.ids.sc14.copy_composer_text(self)
|
||||||
|
Image:
|
||||||
|
source: './images/copy_text.png'
|
||||||
|
center_x: self.parent.center_x
|
||||||
|
center_y: self.parent.center_y
|
||||||
|
size: 20, 20
|
||||||
|
|
||||||
|
|
||||||
|
<ToggleBtn>:
|
||||||
|
#size_hint: None, None
|
||||||
|
size: dp(36), dp(48)
|
||||||
|
pos_hint: {'center_x': .95, 'center_y': .4}
|
||||||
|
on_press: app.root.ids.sc10.toggleAction(self)
|
109
src/bitmessagekivy/kv/composer.kv
Normal file
109
src/bitmessagekivy/kv/composer.kv
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
<DropDownWidget>:
|
||||||
|
ScrollView:
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height + 2 * self.parent.height/4
|
||||||
|
padding: dp(32)
|
||||||
|
spacing: 15
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
MyMDTextField:
|
||||||
|
id: ti
|
||||||
|
hint_text: 'type or select sender address'
|
||||||
|
size_hint_y: None
|
||||||
|
height: 100
|
||||||
|
font_size: '13sp'
|
||||||
|
multiline: False
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(40)
|
||||||
|
CustomSpinner:
|
||||||
|
id: btn
|
||||||
|
background_color: app.theme_cls.primary_dark
|
||||||
|
values: app.variable_1
|
||||||
|
on_text: root.auto_fill_fromaddr() if self.text != 'Select' else ''
|
||||||
|
option_cls: Factory.get("MySpinnerOption")
|
||||||
|
#background_color: color_button if self.state == 'normal' else color_button_pressed
|
||||||
|
#background_down: 'atlas://data/images/defaulttheme/spinner'
|
||||||
|
background_normal: ''
|
||||||
|
background_color: app.theme_cls.primary_color
|
||||||
|
color: color_font
|
||||||
|
font_size: '12.5sp'
|
||||||
|
ArrowImg:
|
||||||
|
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
txt_input: txt_input
|
||||||
|
rv: rv
|
||||||
|
size : (890, 60)
|
||||||
|
MyTextInput:
|
||||||
|
id: txt_input
|
||||||
|
size_hint_y: None
|
||||||
|
font_size: '13sp'
|
||||||
|
height: self.parent.height/2
|
||||||
|
hint_text: 'type, select or scan QR code for recipients address'
|
||||||
|
RV:
|
||||||
|
id: rv
|
||||||
|
MyMDTextField:
|
||||||
|
id: subject
|
||||||
|
hint_text: 'subject'
|
||||||
|
required: True
|
||||||
|
height: 100
|
||||||
|
font_size: '13sp'
|
||||||
|
size_hint_y: None
|
||||||
|
multiline: False
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
|
||||||
|
MyMDTextField:
|
||||||
|
id: body
|
||||||
|
multiline: True
|
||||||
|
hint_text: 'body'
|
||||||
|
size_hint_y: None
|
||||||
|
font_size: '13sp'
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
BoxLayout:
|
||||||
|
spacing:50
|
||||||
|
|
||||||
|
<MyTextInput>:
|
||||||
|
readonly: False
|
||||||
|
multiline: False
|
||||||
|
|
||||||
|
|
||||||
|
<SelectableLabel>:
|
||||||
|
# Draw a background to indicate selection
|
||||||
|
color: 0,0,0,1
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: app.theme_cls.primary_dark if self.selected else (1, 1, 1, 0)
|
||||||
|
Rectangle:
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
|
||||||
|
<RV>:
|
||||||
|
canvas:
|
||||||
|
Color:
|
||||||
|
rgba: 0,0,0,.2
|
||||||
|
|
||||||
|
Line:
|
||||||
|
rectangle: self.x +1 , self.y, self.width - 2, self.height -2
|
||||||
|
bar_width: 10
|
||||||
|
scroll_type:['bars']
|
||||||
|
viewclass: 'SelectableLabel'
|
||||||
|
SelectableRecycleBoxLayout:
|
||||||
|
default_size: None, dp(20)
|
||||||
|
default_size_hint: 1, None
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
orientation: 'vertical'
|
||||||
|
multiselect: False
|
||||||
|
|
||||||
|
|
||||||
|
<MyMDTextField@MDTextField>:
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
20
src/bitmessagekivy/kv/credits.kv
Normal file
20
src/bitmessagekivy/kv/credits.kv
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<Credits>:
|
||||||
|
name: 'credits'
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(200)
|
||||||
|
OneLineListItem:
|
||||||
|
text: "Available Credits"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H4'
|
||||||
|
text: root.available_credits
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
22
src/bitmessagekivy/kv/draft.kv
Normal file
22
src/bitmessagekivy/kv/draft.kv
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<Draft>:
|
||||||
|
name: 'draft'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 20, 0, 5]
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
ComposerButton:
|
32
src/bitmessagekivy/kv/inbox.kv
Normal file
32
src/bitmessagekivy/kv/inbox.kv
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<Inbox>:
|
||||||
|
name: 'inbox'
|
||||||
|
#transition: NoTransition()
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
SearchBar:
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 0, 0, 5]
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
#FloatLayout:
|
||||||
|
# MDScrollViewRefreshLayout:
|
||||||
|
# id: refresh_layout
|
||||||
|
# refresh_callback: root.refresh_callback
|
||||||
|
# root_layout: root.set_root_layout()
|
||||||
|
# MDList:
|
||||||
|
# id: ml
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
||||||
|
ComposerButton:
|
106
src/bitmessagekivy/kv/login.kv
Normal file
106
src/bitmessagekivy/kv/login.kv
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
<Login>:
|
||||||
|
name: 'login'
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(750)
|
||||||
|
padding: dp(10)
|
||||||
|
BoxLayout:
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "You may generate addresses by using either random numbers or by using a passphrase If you use a passphrase, the address is called a deterministic; address The Random Number option is selected by default but deterministic addresses have several \n pros and cons:\n"
|
||||||
|
halign: 'center'
|
||||||
|
color:app.theme_cls.primary_dark
|
||||||
|
BoxLayout:
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "If talk about pros You can recreate your addresses on any computer from memory, You need-not worry about backing up your keys.dat file as long as you can remember your passphrase and aside talk about cons You must remember (or write down) your You must remember the address version number and the stream number along with your passphrase If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you"
|
||||||
|
halign: 'center'
|
||||||
|
color:app.theme_cls.primary_dark
|
||||||
|
MDCheckbox:
|
||||||
|
id: grp_chkbox_1
|
||||||
|
group: 'test'
|
||||||
|
active: True
|
||||||
|
allow_no_selection: False
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "use a random number generator to make an address"
|
||||||
|
halign: 'center'
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.texture_size[1] + dp(4)
|
||||||
|
color: [0.941, 0, 0,1]
|
||||||
|
MDCheckbox:
|
||||||
|
id: grp_chkbox_1
|
||||||
|
group: 'test'
|
||||||
|
allow_no_selection: False
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "use a pseudo number generator to make an address"
|
||||||
|
halign: 'center'
|
||||||
|
size_hint_y: None
|
||||||
|
color: [0.941, 0, 0,1]
|
||||||
|
height: self.texture_size[1] + dp(4)
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
height: dp(40)
|
||||||
|
on_press: app.root.ids.scr_mngr.current = 'random'
|
||||||
|
on_press: app.root.ids.sc7.reset_address_label()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'proceed'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
|
||||||
|
<Random>:
|
||||||
|
name: 'random'
|
||||||
|
ScrollView:
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
padding: dp(20)
|
||||||
|
spacing: 100
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Random Addresses"
|
||||||
|
halign: 'center'
|
||||||
|
color:app.theme_cls.primary_dark
|
||||||
|
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Here you may generate as many addresses as you like, Indeed creating and abandoning addresses is encouraged"
|
||||||
|
halign: 'center'
|
||||||
|
color:app.theme_cls.primary_dark
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
id: label
|
||||||
|
multiline: True
|
||||||
|
hint_text: "Label"
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
on_text: root.add_validation(self)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
height: dp(40)
|
||||||
|
on_release: root.generateaddress(app)
|
||||||
|
opposite_colors: True
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'next'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
84
src/bitmessagekivy/kv/maildetail.kv
Normal file
84
src/bitmessagekivy/kv/maildetail.kv
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<MailDetail>:
|
||||||
|
name: 'mailDetail'
|
||||||
|
# ScrollView:
|
||||||
|
# do_scroll_x: False
|
||||||
|
# BoxLayout:
|
||||||
|
# orientation: 'vertical'
|
||||||
|
# size_hint_y: None
|
||||||
|
# height: dp(500) + self.minimum_height
|
||||||
|
# padding: dp(32)
|
||||||
|
# MDLabel:
|
||||||
|
# font_style: 'Subtitle1'
|
||||||
|
# theme_text_color: 'Primary'
|
||||||
|
# text: root.subject
|
||||||
|
# halign: 'left'
|
||||||
|
# font_size: '20sp'
|
||||||
|
# CopyTextBtn:
|
||||||
|
# MDLabel:
|
||||||
|
# font_style: 'Body1'
|
||||||
|
# theme_text_color: 'Primary'
|
||||||
|
# text: "From: " + root.from_addr
|
||||||
|
# halign: 'left'
|
||||||
|
# CopyTextBtn:
|
||||||
|
# MDLabel:
|
||||||
|
# font_style: 'Body1'
|
||||||
|
# theme_text_color: 'Primary'
|
||||||
|
# text: "To: " + root.to_addr
|
||||||
|
# halign: 'left'
|
||||||
|
# CopyTextBtn:
|
||||||
|
# MDLabel:
|
||||||
|
# font_style: 'Body1'
|
||||||
|
# theme_text_color: 'Primary'
|
||||||
|
# text: root.status
|
||||||
|
# halign: 'left'
|
||||||
|
# MDLabel:
|
||||||
|
# font_style: 'Subtitle2'
|
||||||
|
# theme_text_color: 'Primary'
|
||||||
|
# text: root.message
|
||||||
|
# halign: 'left'
|
||||||
|
# bold: True
|
||||||
|
# CopyTextBtn:
|
||||||
|
# BoxLayout:
|
||||||
|
# orientation: 'vertical'
|
||||||
|
# size_hint_y: None
|
||||||
|
# height: dp(100) + self.minimum_height
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
orientation: 'vertical'
|
||||||
|
height: dp(bod.height) + self.minimum_height
|
||||||
|
padding: dp(20)
|
||||||
|
OneLineListItem:
|
||||||
|
id: subj
|
||||||
|
text: root.subject
|
||||||
|
divider: None
|
||||||
|
disabled: True
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
TwoLineAvatarIconListItem:
|
||||||
|
id: subaft
|
||||||
|
text: root.from_addr
|
||||||
|
secondary_text: 'to ' + root.to_addr
|
||||||
|
divider: None
|
||||||
|
BadgeText:
|
||||||
|
text: root.time_tag
|
||||||
|
halign:'right'
|
||||||
|
font_style:'Caption'
|
||||||
|
AvatarSampleWidget:
|
||||||
|
source: root.avatarImg
|
||||||
|
OneLineListItem:
|
||||||
|
text: root.status
|
||||||
|
divider: None
|
||||||
|
disabled: True
|
||||||
|
font_style: 'Body2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
halign:'left'
|
||||||
|
MDLabel:
|
||||||
|
id: bod
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: root.message
|
||||||
|
halign: 'left'
|
||||||
|
height: self.texture_size[1]
|
||||||
|
Loader:
|
23
src/bitmessagekivy/kv/myaddress.kv
Normal file
23
src/bitmessagekivy/kv/myaddress.kv
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<MyAddress>:
|
||||||
|
name: 'myaddress'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
SearchBar:
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 0, 0, 5]
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: 'My Addresses'
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
FloatLayout:
|
||||||
|
MDScrollViewRefreshLayout:
|
||||||
|
id: refresh_layout
|
||||||
|
refresh_callback: root.refresh_callback
|
||||||
|
root_layout: root
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
87
src/bitmessagekivy/kv/network.kv
Normal file
87
src/bitmessagekivy/kv/network.kv
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<NetworkStat>:
|
||||||
|
name: 'networkstat'
|
||||||
|
MDTabs:
|
||||||
|
id: tab_panel
|
||||||
|
tab_display_mode:'text'
|
||||||
|
|
||||||
|
Tab:
|
||||||
|
text: "Total connections"
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(200)
|
||||||
|
OneLineListItem:
|
||||||
|
text: "Total Connections"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .6, .3
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: root.text_variable_1
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
Tab:
|
||||||
|
text: 'Processes'
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(500)
|
||||||
|
OneLineListItem:
|
||||||
|
text: "person-to-person"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .7, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: root.text_variable_2
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
OneLineListItem:
|
||||||
|
text: "Brodcast"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .7, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: root.text_variable_3
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
OneLineListItem:
|
||||||
|
text: "publickeys"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .7, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: root.text_variable_4
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
OneLineListItem:
|
||||||
|
text: "objects"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .7, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: root.text_variable_5
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
144
src/bitmessagekivy/kv/payment.kv
Normal file
144
src/bitmessagekivy/kv/payment.kv
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
<Payment>:
|
||||||
|
name: 'payment'
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
padding: [dp(app.window_size[0]/16 if app.window_size[0] <= 720 else app.window_size[0]/6 if app.window_size[0] <= 800 else app.window_size[0]/18), dp(10)]
|
||||||
|
spacing: 12
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height + dp(app.window_size[1]) if app.window_size[1] > app.window_size[0] else dp(app.window_size[0])
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
padding: dp(5)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: app.theme_cls.primary_dark
|
||||||
|
Rectangle:
|
||||||
|
# self here refers to the widget i.e FloatLayout
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
MDLabel:
|
||||||
|
size_hint_y: None
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'Platinum'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'We provide subscriptions for proof of work calculation for first month. '
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
id: free_pak
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: '€ 50.0'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDRaisedButton:
|
||||||
|
canvas:
|
||||||
|
Color:
|
||||||
|
rgb: (0.93, 0.93, 0.93)
|
||||||
|
Rectangle:
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.get_available_credits(self)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Get Free Credits'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (0,0,0,1)
|
||||||
|
halign: 'center'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
padding: dp(5)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: app.theme_cls.primary_dark
|
||||||
|
Rectangle:
|
||||||
|
# self here refers to the widget i.e FloatLayout
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
MDLabel:
|
||||||
|
size_hint_y: None
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'Silver'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'We provide for proof of work calculation for six month. '
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: '€ 100.0'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDRaisedButton:
|
||||||
|
canvas:
|
||||||
|
Color:
|
||||||
|
rgb: (0.93, 0.93, 0.93)
|
||||||
|
Rectangle:
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Get Monthly Credits'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (0,0,0,1)
|
||||||
|
halign: 'center'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
padding: dp(5)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: app.theme_cls.primary_dark
|
||||||
|
Rectangle:
|
||||||
|
# self here refers to the widget i.e FloatLayout
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
MDLabel:
|
||||||
|
size_hint_y: None
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'Gold'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: 'We provide for proof of work calculation for 1years. '
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H5'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: '€ 500.0'
|
||||||
|
halign: 'center'
|
||||||
|
color: 1,1,1,1
|
||||||
|
MDRaisedButton:
|
||||||
|
canvas:
|
||||||
|
Color:
|
||||||
|
rgb: (0.93, 0.93, 0.93)
|
||||||
|
Rectangle:
|
||||||
|
pos: self.pos
|
||||||
|
size: self.size
|
||||||
|
size: dp(app.window_size[0] - 2*self.parent.parent.padding[0]) - 10 , 1
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Get Yearly Credits'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (0,0,0,1)
|
||||||
|
halign: 'center'
|
314
src/bitmessagekivy/kv/popup.kv
Normal file
314
src/bitmessagekivy/kv/popup.kv
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
<LoadingPopup>:
|
||||||
|
separator_color: 1, 1, 1, 1
|
||||||
|
background: "White.png"
|
||||||
|
Button:
|
||||||
|
id: btn
|
||||||
|
disabled: True
|
||||||
|
background_disabled_normal: "White.png"
|
||||||
|
Image:
|
||||||
|
source: './images/loader.zip'
|
||||||
|
anim_delay: 0
|
||||||
|
#mipmap: True
|
||||||
|
size: root.size
|
||||||
|
|
||||||
|
|
||||||
|
<GrashofPopup>:
|
||||||
|
id: popup
|
||||||
|
size_hint : (None,None)
|
||||||
|
height: 2*(label.height + address.height) + 10
|
||||||
|
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
||||||
|
title: 'add contact\'s'
|
||||||
|
background: './images/popup.jpeg'
|
||||||
|
title_size: sp(20)
|
||||||
|
title_color: 0.4, 0.3765, 0.3451, 1
|
||||||
|
auto_dismiss: False
|
||||||
|
separator_color: 0.3529, 0.3922, 0.102, 0.7
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: 0.5
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing:dp(20)
|
||||||
|
id: popup_box
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
MDTextField:
|
||||||
|
id: label
|
||||||
|
multiline: False
|
||||||
|
hint_text: "Label"
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
on_text: root.checkLabel_valid(self)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
||||||
|
MDTextField:
|
||||||
|
id: address
|
||||||
|
hint_text: "Address"
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
on_text: root.checkAddress_valid(self)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
||||||
|
BoxLayout:
|
||||||
|
spacing:5
|
||||||
|
orientation: 'horizontal'
|
||||||
|
MDRaisedButton:
|
||||||
|
id: save_addr
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_release:
|
||||||
|
root.savecontact()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Save'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.dismiss()
|
||||||
|
on_press: root.close_pop()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Cancel'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 2, None
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Scan QR code'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
|
||||||
|
<AddbookDetailPopup>:
|
||||||
|
id: addbook_popup
|
||||||
|
size_hint : (None,None)
|
||||||
|
height: 4*(add_label.height)
|
||||||
|
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
||||||
|
background: './images/popup.jpeg'
|
||||||
|
separator_height: 0
|
||||||
|
auto_dismiss: False
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
spacing:dp(70)
|
||||||
|
id: addbook_popup_box
|
||||||
|
orientation: 'vertical'
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing:dp(20)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Label"
|
||||||
|
font_size: '17sp'
|
||||||
|
halign: 'left'
|
||||||
|
MDTextField:
|
||||||
|
id: add_label
|
||||||
|
font_style: 'Body1'
|
||||||
|
font_size: '15sp'
|
||||||
|
halign: 'left'
|
||||||
|
text: root.address_label
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
required: True
|
||||||
|
helper_text_mode: "on_error"
|
||||||
|
on_text: root.checkLabel_valid(self)
|
||||||
|
canvas.before:
|
||||||
|
Color:
|
||||||
|
rgba: (0,0,0,1)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Address"
|
||||||
|
font_size: '17sp'
|
||||||
|
halign: 'left'
|
||||||
|
MDLabel:
|
||||||
|
id: address
|
||||||
|
font_style: 'Body1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: root.address
|
||||||
|
font_size: '15sp'
|
||||||
|
halign: 'left'
|
||||||
|
BoxLayout:
|
||||||
|
id: addbook_btn
|
||||||
|
spacing:5
|
||||||
|
orientation: 'horizontal'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 2, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.send_message_to()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Send message to'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
font_size: '10sp'
|
||||||
|
on_press: root.update_addbook_label(root.address)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Save'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.dismiss()
|
||||||
|
on_press: root.close_pop()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Cancel'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
|
||||||
|
|
||||||
|
<MyaddDetailPopup>:
|
||||||
|
id: myadd_popup
|
||||||
|
size_hint : (None,None)
|
||||||
|
height: 4.5*(myaddr_label.height+ my_add_btn.children[0].height)
|
||||||
|
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
||||||
|
background: './images/popup.jpeg'
|
||||||
|
auto_dismiss: False
|
||||||
|
separator_height: 0
|
||||||
|
BoxLayout:
|
||||||
|
id: myadd_popup_box
|
||||||
|
size_hint_y: None
|
||||||
|
spacing:dp(70)
|
||||||
|
orientation: 'vertical'
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing:dp(25)
|
||||||
|
MDLabel:
|
||||||
|
id: myaddr_label
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Label"
|
||||||
|
font_size: '17sp'
|
||||||
|
halign: 'left'
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: root.address_label
|
||||||
|
font_size: '15sp'
|
||||||
|
halign: 'left'
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Address"
|
||||||
|
font_size: '17sp'
|
||||||
|
halign: 'left'
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: root.address
|
||||||
|
font_size: '15sp'
|
||||||
|
halign: 'left'
|
||||||
|
BoxLayout:
|
||||||
|
id: my_add_btn
|
||||||
|
spacing:5
|
||||||
|
orientation: 'horizontal'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 2, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.send_message_from()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Send message from'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.dismiss()
|
||||||
|
on_press: app.root.ids.scr_mngr.current = 'showqrcode'
|
||||||
|
on_press: app.root.ids.sc15.qrdisplay()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Show QR code'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.dismiss()
|
||||||
|
on_press: root.close_pop()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Cancel'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
|
||||||
|
<AppClosingPopup>:
|
||||||
|
id: closing_popup
|
||||||
|
size_hint : (None,None)
|
||||||
|
height: 1.3*(popup_label.height+ my_add_btn.children[0].height)
|
||||||
|
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
||||||
|
background: './images/popup.jpeg'
|
||||||
|
auto_dismiss: False
|
||||||
|
separator_height: 0
|
||||||
|
BoxLayout:
|
||||||
|
id: myadd_popup_box
|
||||||
|
size_hint_y: None
|
||||||
|
spacing:dp(70)
|
||||||
|
orientation: 'vertical'
|
||||||
|
BoxLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing:dp(25)
|
||||||
|
MDLabel:
|
||||||
|
id: popup_label
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "Bitmessage isn't connected to the network.\n If you quit now, it may cause delivery delays.\n Wait until connected and the synchronisation finishes?"
|
||||||
|
font_size: '17sp'
|
||||||
|
halign: 'center'
|
||||||
|
BoxLayout:
|
||||||
|
id: my_add_btn
|
||||||
|
spacing:5
|
||||||
|
orientation: 'horizontal'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.closingAction(self.children[0].text)
|
||||||
|
on_press: app.stop()
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Yes'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
on_press: root.closingAction(self.children[0].text)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'No'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: 1.5, None
|
||||||
|
height: dp(40)
|
||||||
|
#on_press: root.dismiss()
|
||||||
|
on_press: root.closingAction(self.children[0].text)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Cancel'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
24
src/bitmessagekivy/kv/sent.kv
Normal file
24
src/bitmessagekivy/kv/sent.kv
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<Sent>:
|
||||||
|
name: 'sent'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
SearchBar:
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 0, 0, 5]
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
||||||
|
ComposerButton:
|
68
src/bitmessagekivy/kv/settings.kv
Normal file
68
src/bitmessagekivy/kv/settings.kv
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
<Setting>:
|
||||||
|
name: 'set'
|
||||||
|
ScrollView:
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
size_hint_y: None
|
||||||
|
height: dp(500)
|
||||||
|
OneLineListItem:
|
||||||
|
text: "SERVER SETTINGS"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .6, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Server'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
OneLineListItem:
|
||||||
|
text: "DATA SETTINGS"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .6, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Import or export data'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
OneLineListItem:
|
||||||
|
text: "OTHER SETTINGS"
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDRaisedButton:
|
||||||
|
size_hint: .6, .55
|
||||||
|
height: dp(40)
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'H6'
|
||||||
|
text: 'Restart background service'
|
||||||
|
font_size: '13sp'
|
||||||
|
color: (1,1,1,1)
|
||||||
|
halign: 'center'
|
||||||
|
BoxLayout:
|
||||||
|
AnchorLayout:
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "bitmessage is 11 seconds behind the network"
|
||||||
|
halign: 'center'
|
||||||
|
color: [0.941, 0, 0,1]
|
||||||
|
|
||||||
|
BoxLayout:
|
||||||
|
MDCheckbox:
|
||||||
|
id: chkbox
|
||||||
|
size_hint: None, None
|
||||||
|
size: dp(48), dp(64)
|
||||||
|
active: True
|
||||||
|
MDLabel:
|
||||||
|
font_style: 'Body1'
|
||||||
|
theme_text_color: 'Primary'
|
||||||
|
text: "show settings (for advanced users only)"
|
||||||
|
halign: 'left'
|
||||||
|
color: app.theme_cls.primary_dark
|
24
src/bitmessagekivy/kv/trash.kv
Normal file
24
src/bitmessagekivy/kv/trash.kv
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<Trash>:
|
||||||
|
name: 'trash'
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
spacing: dp(5)
|
||||||
|
GridLayout:
|
||||||
|
id: identi_tag
|
||||||
|
padding: [20, 20, 0, 5]
|
||||||
|
spacing: dp(5)
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
|
MDLabel:
|
||||||
|
text: ''
|
||||||
|
font_style: 'Subtitle2'
|
||||||
|
BoxLayout:
|
||||||
|
orientation:'vertical'
|
||||||
|
ScrollView:
|
||||||
|
id: scroll_y
|
||||||
|
do_scroll_x: False
|
||||||
|
MDList:
|
||||||
|
id: ml
|
||||||
|
Loader:
|
||||||
|
ComposerButton:
|
|
@ -1,51 +1,104 @@
|
||||||
|
#:import IconLeftWidget kivymd.uix.list.IconLeftWidget
|
||||||
#:import Toolbar kivymd.toolbar.Toolbar
|
#:import images_path kivymd.images_path
|
||||||
#:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
|
#:import Spinner kivy.uix.spinner.Spinner
|
||||||
#:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
|
|
||||||
#:import NavigationDrawerSubheader kivymd.navigationdrawer.NavigationDrawerSubheader
|
|
||||||
#:import MDCheckbox kivymd.selectioncontrols.MDCheckbox
|
|
||||||
#:import MDList kivymd.list.MDList
|
|
||||||
#:import OneLineListItem kivymd.list.OneLineListItem
|
|
||||||
#:import MDTextField kivymd.textfields.MDTextField
|
|
||||||
#:import get_color_from_hex kivy.utils.get_color_from_hex
|
|
||||||
#:import colors kivymd.color_definitions.colors
|
|
||||||
#:import MDTabbedPanel kivymd.tabs.MDTabbedPanel
|
|
||||||
#:import MDTab kivymd.tabs.MDTab
|
|
||||||
#:import MDFloatingActionButton kivymd.button.MDFloatingActionButton
|
|
||||||
#:import Factory kivy.factory.Factory
|
#:import Factory kivy.factory.Factory
|
||||||
#:import MDScrollViewRefreshLayout kivymd.refreshlayout.MDScrollViewRefreshLayout
|
|
||||||
#:import MDSpinner kivymd.spinner.MDSpinner
|
#:import MDCheckbox kivymd.uix.selectioncontrol.MDCheckbox
|
||||||
#:import NoTransition kivy.uix.screenmanager.NoTransition
|
#:import MDList kivymd.uix.list.MDList
|
||||||
#:import MDSeparator kivymd.card.MDSeparator
|
#:import OneLineListItem kivymd.uix.list.OneLineListItem
|
||||||
|
#:import MDTextField kivymd.uix.textfield.MDTextField
|
||||||
|
#:import get_color_from_hex kivy.utils.get_color_from_hex
|
||||||
|
#:import MDCard kivymd.uix.card.MDCard
|
||||||
|
#:import colors kivymd.color_definitions.colors
|
||||||
|
#:import MDTabs kivymd.uix.tab.MDTabs
|
||||||
|
#:import MDFloatingActionButton kivymd.uix.button.MDFloatingActionButton
|
||||||
|
#:import Factory kivy.factory.Factory
|
||||||
|
#:import MDScrollViewRefreshLayout kivymd.uix.refreshlayout.MDScrollViewRefreshLayout
|
||||||
|
#:import MDSpinner kivymd.uix.spinner.MDSpinner
|
||||||
|
#:import MDTabsBase kivymd.uix.tab.MDTabsBase
|
||||||
|
<Tab@BoxLayout+MDTabsBase>
|
||||||
|
|
||||||
#:set color_button (0.784, 0.443, 0.216, 1) # brown
|
#:set color_button (0.784, 0.443, 0.216, 1) # brown
|
||||||
#:set color_button_pressed (0.659, 0.522, 0.431, 1) # darker brown
|
#:set color_button_pressed (0.659, 0.522, 0.431, 1) # darker brown
|
||||||
#:set color_font (0.957, 0.890, 0.843, 1) # off white
|
#:set color_font (0.957, 0.890, 0.843, 1) # off white
|
||||||
|
|
||||||
<MyNavigationDrawerIconButton@NavigationDrawerIconButton>:
|
|
||||||
icon: 'checkbox-blank-circle'
|
|
||||||
|
|
||||||
<MySpinnerOption@SpinnerOption>:
|
<MySpinnerOption@SpinnerOption>:
|
||||||
font_size: '12.5sp'
|
font_size: '12.5sp'
|
||||||
background_color: color_button if self.state == 'down' else color_button_pressed
|
#background_color: color_button if self.state == 'down' else color_button_pressed
|
||||||
background_down: 'atlas://data/images/defaulttheme/button'
|
#background_down: 'atlas://data/images/defaulttheme/button'
|
||||||
|
background_normal: ''
|
||||||
|
background_color: app.theme_cls.primary_color
|
||||||
color: color_font
|
color: color_font
|
||||||
|
|
||||||
<ContentNavigationDrawer@Navigatorss>:
|
<NavigationItem>
|
||||||
drawer_logo: './images/drawer_logo1.png'
|
#on_press: root.active = not root.active
|
||||||
|
on_press: root.currentlyActive()
|
||||||
|
active_color: root.theme_cls.primary_color if root.active else root.theme_cls.text_color
|
||||||
|
|
||||||
|
IconLeftWidget:
|
||||||
|
icon: root.icon
|
||||||
|
theme_text_color: "Custom"
|
||||||
|
text_color: root.active_color
|
||||||
|
|
||||||
|
BadgeText:
|
||||||
|
text: f"{root.badge_text}"
|
||||||
|
theme_text_color: "Custom"
|
||||||
|
#text_color: root.active_color
|
||||||
|
halign: 'right'
|
||||||
|
|
||||||
|
<NavigationDrawerDivider>:
|
||||||
|
canvas:
|
||||||
|
Color:
|
||||||
|
rgba: self.theme_cls.divider_color
|
||||||
|
Line:
|
||||||
|
points: root.x, root.y + dp(8), root.x + self.width, root.y + dp(8)
|
||||||
|
|
||||||
|
<ContentNavigationDrawer>
|
||||||
|
|
||||||
|
BoxLayout:
|
||||||
|
orientation: 'vertical'
|
||||||
|
|
||||||
|
FloatLayout:
|
||||||
|
size_hint_y: None
|
||||||
|
height: "200dp"
|
||||||
|
|
||||||
|
BoxLayout:
|
||||||
|
id: top_box
|
||||||
|
size_hint_y: None
|
||||||
|
height: "200dp"
|
||||||
|
#padding: "10dp"
|
||||||
|
x: root.parent.x
|
||||||
|
pos_hint: {"top": 1}
|
||||||
|
Image:
|
||||||
|
#source: './images/drawer_logo1.png'
|
||||||
|
source: app.get_default_logo()
|
||||||
|
|
||||||
|
ScrollView:
|
||||||
|
pos_hint: {"top": 1}
|
||||||
|
|
||||||
|
GridLayout:
|
||||||
|
id: box_item
|
||||||
|
cols: 1
|
||||||
|
size_hint_y: None
|
||||||
|
height: self.minimum_height
|
||||||
NavigationDrawerDivider:
|
NavigationDrawerDivider:
|
||||||
NavigationDrawerSubheader:
|
NavigationDrawerSubheader:
|
||||||
text: "Accounts"
|
text: "Accounts"
|
||||||
NavigationDrawerIconButton:
|
height:"35dp"
|
||||||
|
NavigationItem:
|
||||||
|
size: 50,50
|
||||||
CustomSpinner:
|
CustomSpinner:
|
||||||
id: btn
|
id: btn
|
||||||
pos_hint:{"x":0,"y":.25}
|
pos_hint:{"x":0,"y":0}
|
||||||
option_cls: Factory.get("MySpinnerOption")
|
option_cls: Factory.get("MySpinnerOption")
|
||||||
font_size: '11.9sp'
|
font_size: '10.9sp'
|
||||||
text: app.getDefaultAccData()
|
text: app.getDefaultAccData()
|
||||||
background_color: color_button if self.state == 'normal' else color_button_pressed
|
#background_color: color_button if self.state == 'normal' else color_button_pressed
|
||||||
background_down: 'atlas://data/images/defaulttheme/spinner'
|
#background_down: 'atlas://data/images/defaulttheme/spinner'
|
||||||
color: color_font
|
color: color_font
|
||||||
|
background_normal: ''
|
||||||
|
background_color: app.theme_cls.primary_color
|
||||||
|
#background_color: (0.62,0.67,0.72,1)
|
||||||
values: app.variable_1
|
values: app.variable_1
|
||||||
on_text:app.getCurrentAccountData(self.text)
|
on_text:app.getCurrentAccountData(self.text)
|
||||||
Image:
|
Image:
|
||||||
|
@ -54,109 +107,107 @@
|
||||||
y: self.parent.y + self.parent.height/4
|
y: self.parent.y + self.parent.height/4
|
||||||
size: self.parent.height/2, self.parent.height/2
|
size: self.parent.height/2, self.parent.height/2
|
||||||
ArrowImg:
|
ArrowImg:
|
||||||
NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
id: inbox_cnt
|
id: inbox_cnt
|
||||||
|
text: 'Inbox'
|
||||||
icon: 'email-open'
|
icon: 'email-open'
|
||||||
text: "Inbox"
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'inbox'
|
on_release: app.root.ids.scr_mngr.current = 'inbox'
|
||||||
badge_text: "0"
|
on_release: root.parent.set_state()
|
||||||
on_press: app.load_screen(self)
|
on_press: app.load_screen(self)
|
||||||
NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
id: send_cnt
|
id: send_cnt
|
||||||
|
text: 'Sent'
|
||||||
icon: 'send'
|
icon: 'send'
|
||||||
text: "Sent"
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'sent'
|
on_release: app.root.ids.scr_mngr.current = 'sent'
|
||||||
badge_text: "0"
|
on_release: root.parent.set_state()
|
||||||
NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
id: draft_cnt
|
id: draft_cnt
|
||||||
|
text: 'Draft'
|
||||||
icon: 'message-draw'
|
icon: 'message-draw'
|
||||||
text: "Draft"
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'draft'
|
on_release: app.root.ids.scr_mngr.current = 'draft'
|
||||||
badge_text: "0"
|
on_release: root.parent.set_state()
|
||||||
#NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
#text: "Starred"
|
|
||||||
#icon:'star'
|
|
||||||
#on_release: app.root.ids.scr_mngr.current = 'starred'
|
|
||||||
#badge_text: "0"
|
|
||||||
#NavigationDrawerIconButton:
|
|
||||||
#icon: 'archive'
|
|
||||||
#text: "Archieve"
|
|
||||||
#on_release: app.root.ids.scr_mngr.current = 'archieve'
|
|
||||||
#badge_text: "0"
|
|
||||||
#NavigationDrawerIconButton:
|
|
||||||
#icon: 'email-open-outline'
|
|
||||||
#text: "Spam"
|
|
||||||
#on_release: app.root.ids.scr_mngr.current = 'spam'
|
|
||||||
#badge_text: "0"
|
|
||||||
NavigationDrawerIconButton:
|
|
||||||
id: trash_cnt
|
id: trash_cnt
|
||||||
|
text: 'Trash'
|
||||||
icon: 'delete'
|
icon: 'delete'
|
||||||
text: "Trash"
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'trash'
|
on_release: app.root.ids.scr_mngr.current = 'trash'
|
||||||
badge_text: "0"
|
on_release: root.parent.set_state()
|
||||||
NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
id: allmail_cnt
|
id: allmail_cnt
|
||||||
text: "All Mails"
|
text: 'All Mails'
|
||||||
icon: 'contact-mail'
|
icon: 'contact-mail'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'allmails'
|
on_release: app.root.ids.scr_mngr.current = 'allmails'
|
||||||
badge_text: "0"
|
on_release: root.parent.set_state()
|
||||||
on_press: app.load_screen(self)
|
on_press: app.load_screen(self)
|
||||||
NavigationDrawerDivider:
|
NavigationDrawerDivider:
|
||||||
NavigationDrawerSubheader:
|
NavigationDrawerSubheader:
|
||||||
text: "All labels"
|
text: "All labels"
|
||||||
NavigationDrawerIconButton:
|
NavigationItem:
|
||||||
text: "Address Book"
|
text: 'Address Book'
|
||||||
icon: 'book-multiple'
|
icon: 'book-multiple'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'addressbook'
|
on_release: app.root.ids.scr_mngr.current = 'addressbook'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "Settings"
|
NavigationItem:
|
||||||
|
text: 'Settings'
|
||||||
icon: 'settings'
|
icon: 'settings'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'set'
|
on_release: app.root.ids.scr_mngr.current = 'set'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "Subscriptions/Payment"
|
NavigationItem:
|
||||||
|
text: 'Payment'
|
||||||
icon: 'bell'
|
icon: 'bell'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'payment'
|
on_release: app.root.ids.scr_mngr.current = 'payment'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "Credits"
|
NavigationItem:
|
||||||
|
text: 'Credits'
|
||||||
icon: 'wallet'
|
icon: 'wallet'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'credits'
|
on_release: app.root.ids.scr_mngr.current = 'credits'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "new address"
|
NavigationItem:
|
||||||
|
text: 'New address'
|
||||||
icon: 'account-plus'
|
icon: 'account-plus'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'login'
|
on_release: app.root.ids.scr_mngr.current = 'login'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "Network Status"
|
NavigationItem:
|
||||||
|
text: 'Network status'
|
||||||
icon: 'server-network'
|
icon: 'server-network'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'networkstat'
|
on_release: app.root.ids.scr_mngr.current = 'networkstat'
|
||||||
NavigationDrawerIconButton:
|
on_release: root.parent.set_state()
|
||||||
text: "My Addresses"
|
NavigationItem:
|
||||||
|
text: 'My addresses'
|
||||||
icon: 'account-multiple'
|
icon: 'account-multiple'
|
||||||
|
divider: None
|
||||||
on_release: app.root.ids.scr_mngr.current = 'myaddress'
|
on_release: app.root.ids.scr_mngr.current = 'myaddress'
|
||||||
|
on_release: root.parent.set_state()
|
||||||
|
|
||||||
NavigationLayout:
|
NavigationLayout:
|
||||||
id: nav_layout
|
id: nav_layout
|
||||||
|
|
||||||
ContentNavigationDrawer:
|
MDToolbar:
|
||||||
id: nav_drawer
|
|
||||||
|
|
||||||
FloatLayout:
|
|
||||||
id: float_box
|
|
||||||
BoxLayout:
|
|
||||||
id: box_layout
|
|
||||||
orientation: 'vertical'
|
|
||||||
Toolbar:
|
|
||||||
id: toolbar
|
id: toolbar
|
||||||
title: app.current_address_label()
|
title: app.current_address_label()
|
||||||
opacity: 1 if app.addressexist() else 0
|
opacity: 1 if app.addressexist() else 0
|
||||||
disabled: False if app.addressexist() else True
|
disabled: False if app.addressexist() else True
|
||||||
|
pos_hint: {"top": 1}
|
||||||
md_bg_color: app.theme_cls.primary_color
|
md_bg_color: app.theme_cls.primary_color
|
||||||
background_palette: 'Primary'
|
elevation: 10
|
||||||
background_hue: '500'
|
left_action_items: [['menu', lambda x: nav_drawer.set_state("toggle")]]
|
||||||
left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]]
|
|
||||||
right_action_items: [['account-plus', lambda x: app.addingtoaddressbook()]]
|
right_action_items: [['account-plus', lambda x: app.addingtoaddressbook()]]
|
||||||
|
|
||||||
ScreenManager:
|
ScreenManager:
|
||||||
id: scr_mngr
|
id: scr_mngr
|
||||||
|
size_hint_y: None
|
||||||
|
height: root.height - toolbar.height
|
||||||
Inbox:
|
Inbox:
|
||||||
id:sc1
|
id:sc1
|
||||||
Page:
|
Page:
|
||||||
|
@ -198,1089 +249,27 @@ NavigationLayout:
|
||||||
Archieve:
|
Archieve:
|
||||||
id:sc20
|
id:sc20
|
||||||
|
|
||||||
<Inbox>:
|
MDNavigationDrawer:
|
||||||
name: 'inbox'
|
id: nav_drawer
|
||||||
transition: NoTransition()
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
SearchBar:
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 0, 0, 5]
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
#FloatLayout:
|
|
||||||
# MDScrollViewRefreshLayout:
|
|
||||||
# id: refresh_layout
|
|
||||||
# refresh_callback: root.refresh_callback
|
|
||||||
# root_layout: root.set_root_layout()
|
|
||||||
# MDList:
|
|
||||||
# id: ml
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Sent>:
|
ContentNavigationDrawer:
|
||||||
name: 'sent'
|
id: content_drawer
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
SearchBar:
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 0, 0, 5]
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Trash>:
|
|
||||||
name: 'trash'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 20, 0, 5]
|
|
||||||
spacing: dp(5)
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Draft>:
|
|
||||||
name: 'draft'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 20, 0, 5]
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Starred>:
|
|
||||||
name: 'starred'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Archieve>:
|
|
||||||
name: 'archieve'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Spam>:
|
|
||||||
name: 'spam'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Allmails>:
|
|
||||||
name: 'allmails'
|
|
||||||
#FloatLayout:
|
|
||||||
# MDScrollViewRefreshLayout:
|
|
||||||
# id: refresh_layout
|
|
||||||
# refresh_callback: root.refresh_callback
|
|
||||||
# root_layout: root.set_root_layout()
|
|
||||||
# MDList:
|
|
||||||
# id: ml
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 20, 0, 5]
|
|
||||||
spacing: dp(5)
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Test>:
|
|
||||||
name: 'test'
|
|
||||||
Label:
|
|
||||||
text:"I am in test"
|
|
||||||
color: 0,0,0,1
|
|
||||||
|
|
||||||
<Page>:
|
<Page>:
|
||||||
name: 'page'
|
name: 'page'
|
||||||
Label:
|
Label:
|
||||||
text:"I am on page"
|
text:"I am in Page"
|
||||||
color: 0,0,0,1
|
color: 0,0,0,1
|
||||||
|
|
||||||
<Create>:
|
<Create>:
|
||||||
name: 'create'
|
name: 'create'
|
||||||
Loader:
|
Loader:
|
||||||
|
|
||||||
<Credits>:
|
<Spam>:
|
||||||
name: 'credits'
|
name: 'spam'
|
||||||
ScrollView:
|
Label:
|
||||||
do_scroll_x: False
|
text:"I am in Spam"
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(200)
|
|
||||||
OneLineListItem:
|
|
||||||
text: "Available Credits"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .6, .35
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.available_credits
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<DropDownWidget>:
|
|
||||||
ScrollView:
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height + 2 * self.parent.height/4
|
|
||||||
padding: dp(32)
|
|
||||||
spacing: 15
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
MDTextField:
|
|
||||||
id: ti
|
|
||||||
hint_text: 'type or select sender address'
|
|
||||||
size_hint_y: None
|
|
||||||
height: 100
|
|
||||||
font_size: '13sp'
|
|
||||||
multiline: False
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
|
|
||||||
BoxLayout:
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(40)
|
|
||||||
CustomSpinner:
|
|
||||||
background_color: app.theme_cls.primary_dark
|
|
||||||
id: btn
|
|
||||||
values: app.variable_1
|
|
||||||
on_text: root.auto_fill_fromaddr() if self.text != 'Select' else ''
|
|
||||||
option_cls: Factory.get("MySpinnerOption")
|
|
||||||
background_color: color_button if self.state == 'normal' else color_button_pressed
|
|
||||||
background_down: 'atlas://data/images/defaulttheme/spinner'
|
|
||||||
color: color_font
|
|
||||||
font_size: '12.5sp'
|
|
||||||
ArrowImg:
|
|
||||||
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
txt_input: txt_input
|
|
||||||
rv: rv
|
|
||||||
size : (890, 60)
|
|
||||||
size_hint: 1,1
|
|
||||||
MyTextInput:
|
|
||||||
id: txt_input
|
|
||||||
size_hint_y: None
|
|
||||||
font_size: '13sp'
|
|
||||||
height: self.parent.height/2
|
|
||||||
#hint_text: 'type or search recipients address starting with BM-'
|
|
||||||
hint_text: 'type, select or scan QR code for recipients address'
|
|
||||||
RV:
|
|
||||||
id: rv
|
|
||||||
MDTextField:
|
|
||||||
id: subject
|
|
||||||
hint_text: 'subject'
|
|
||||||
required: True
|
|
||||||
height: 100
|
|
||||||
font_size: '13sp'
|
|
||||||
size_hint_y: None
|
|
||||||
multiline: False
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
|
|
||||||
MDTextField:
|
|
||||||
id: body
|
|
||||||
multiline: True
|
|
||||||
hint_text: 'body'
|
|
||||||
size_hint_y: None
|
|
||||||
font_size: '13sp'
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
BoxLayout:
|
|
||||||
spacing:50
|
|
||||||
|
|
||||||
<MyTextInput>:
|
|
||||||
readonly: False
|
|
||||||
multiline: False
|
|
||||||
|
|
||||||
<SelectableLabel>:
|
|
||||||
# Draw a background to indicate selection
|
|
||||||
color: 0,0,0,1
|
color: 0,0,0,1
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: app.theme_cls.primary_dark if self.selected else (1, 1, 1, 0)
|
|
||||||
Rectangle:
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
|
|
||||||
<RV>:
|
|
||||||
canvas:
|
|
||||||
Color:
|
|
||||||
rgba: 0,0,0,.2
|
|
||||||
|
|
||||||
Line:
|
|
||||||
rectangle: self.x +1 , self.y, self.width - 2, self.height -2
|
|
||||||
bar_width: 10
|
|
||||||
scroll_type:['bars']
|
|
||||||
viewclass: 'SelectableLabel'
|
|
||||||
SelectableRecycleBoxLayout:
|
|
||||||
default_size: None, dp(20)
|
|
||||||
default_size_hint: 1, None
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
orientation: 'vertical'
|
|
||||||
multiselect: False
|
|
||||||
|
|
||||||
|
|
||||||
<Login>:
|
|
||||||
name: 'login'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(750)
|
|
||||||
padding: dp(10)
|
|
||||||
BoxLayout:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Body1'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "You may generate addresses by using either random numbers or by using a passphrase If you use a passphrase, the address is called a deterministic; address The Random Number option is selected by default but deterministic addresses have several \n pros and cons:\n"
|
|
||||||
halign: 'center'
|
|
||||||
bold: True
|
|
||||||
color:app.theme_cls.primary_dark
|
|
||||||
BoxLayout:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Caption'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "If talk about pros You can recreate your addresses on any computer from memory, You need-not worry about backing up your keys.dat file as long as you can remember your passphrase and aside talk about cons You must remember (or write down) your You must remember the address version number and the stream number along with your passphrase If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you"
|
|
||||||
halign: 'center'
|
|
||||||
bold: True
|
|
||||||
color:app.theme_cls.primary_dark
|
|
||||||
MDCheckbox:
|
|
||||||
id: grp_chkbox_1
|
|
||||||
group: 'test'
|
|
||||||
active: True
|
|
||||||
allow_no_selection: False
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Caption'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "use a random number generator to make an address"
|
|
||||||
halign: 'center'
|
|
||||||
size_hint_y: None
|
|
||||||
bold: True
|
|
||||||
height: self.texture_size[1] + dp(4)
|
|
||||||
color: [0.941, 0, 0,1]
|
|
||||||
MDCheckbox:
|
|
||||||
id: grp_chkbox_1
|
|
||||||
group: 'test'
|
|
||||||
allow_no_selection: False
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Caption'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "use a pseudo number generator to make an address"
|
|
||||||
halign: 'center'
|
|
||||||
size_hint_y: None
|
|
||||||
bold: True
|
|
||||||
color: [0.941, 0, 0,1]
|
|
||||||
height: self.texture_size[1] + dp(4)
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
height: dp(40)
|
|
||||||
on_press: app.root.ids.scr_mngr.current = 'random'
|
|
||||||
on_press: app.root.ids.sc7.reset_address_label()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'proceed'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<Random>:
|
|
||||||
name: 'random'
|
|
||||||
ScrollView:
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
padding: dp(20)
|
|
||||||
spacing: 100
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Body1'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Random Addresses"
|
|
||||||
halign: 'center'
|
|
||||||
bold: True
|
|
||||||
color:app.theme_cls.primary_dark
|
|
||||||
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Body1'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Here you may generate as many addresses as you like, Indeed creating and abandoning addresses is encouraged"
|
|
||||||
halign: 'center'
|
|
||||||
bold: True
|
|
||||||
color:app.theme_cls.primary_dark
|
|
||||||
|
|
||||||
MDTextField:
|
|
||||||
id: label
|
|
||||||
multiline: True
|
|
||||||
hint_text: "Label"
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
on_text: root.add_validation(self)
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
height: dp(40)
|
|
||||||
on_release: root.generateaddress(app)
|
|
||||||
opposite_colors: True
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'next'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<Setting>:
|
|
||||||
name: 'set'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(500)
|
|
||||||
OneLineListItem:
|
|
||||||
text: "SERVER SETTINGS"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .6, .55
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Server'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
OneLineListItem:
|
|
||||||
text: "DATA SETTINGS"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .6, .55
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Import or export data'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
OneLineListItem:
|
|
||||||
text: "OTHER SETTINGS"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .6, .55
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Restart background service'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Body1'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "bitmessage is 11 seconds behind the network"
|
|
||||||
halign: 'center'
|
|
||||||
bold: True
|
|
||||||
color: [0.941, 0, 0,1]
|
|
||||||
|
|
||||||
BoxLayout:
|
|
||||||
MDCheckbox:
|
|
||||||
id: chkbox
|
|
||||||
size_hint: None, None
|
|
||||||
size: dp(48), dp(64)
|
|
||||||
active: True
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Body1'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "show settings (for advanced users only)"
|
|
||||||
halign: 'left'
|
|
||||||
bold: True
|
|
||||||
color: app.theme_cls.primary_dark
|
|
||||||
|
|
||||||
<MyAddress>:
|
|
||||||
name: 'myaddress'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
SearchBar:
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 0, 0, 5]
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: 'My Addresses'
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
FloatLayout:
|
|
||||||
MDScrollViewRefreshLayout:
|
|
||||||
id: refresh_layout
|
|
||||||
refresh_callback: root.refresh_callback
|
|
||||||
root_layout: root.set_root_layout()
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<AddressBook>:
|
|
||||||
name: 'addressbook'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing: dp(5)
|
|
||||||
SearchBar:
|
|
||||||
GridLayout:
|
|
||||||
id: identi_tag
|
|
||||||
padding: [20, 0, 0, 5]
|
|
||||||
cols: 1
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
MDLabel:
|
|
||||||
text: ''
|
|
||||||
font_style: 'Body1'
|
|
||||||
bold: True
|
|
||||||
BoxLayout:
|
|
||||||
orientation:'vertical'
|
|
||||||
ScrollView:
|
|
||||||
id: scroll_y
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
Loader:
|
|
||||||
ComposerButton:
|
|
||||||
|
|
||||||
<Payment>:
|
|
||||||
name: 'payment'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
padding: [dp(app.window_size[0]/16 if app.window_size[0] <= 720 else app.window_size[0]/6 if app.window_size[0] <= 800 else app.window_size[0]/18), dp(10)]
|
|
||||||
spacing: 12
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height + dp(app.window_size[1]) if app.window_size[1] > app.window_size[0] else dp(app.window_size[0])
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
padding: dp(5)
|
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: app.theme_cls.primary_dark
|
|
||||||
Rectangle:
|
|
||||||
# self here refers to the widget i.e FloatLayout
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
MDLabel:
|
|
||||||
size_hint_y: None
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'Platinum'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'We provide subscriptions for proof of work calculation for first month. '
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
id: free_pak
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: '€ 50.0'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDRaisedButton:
|
|
||||||
canvas:
|
|
||||||
Color:
|
|
||||||
rgb: (0.93, 0.93, 0.93)
|
|
||||||
Rectangle:
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
size_hint: 1, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.get_available_credits(self)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Get Free Credits'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (0,0,0,1)
|
|
||||||
halign: 'center'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
padding: dp(5)
|
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: app.theme_cls.primary_dark
|
|
||||||
Rectangle:
|
|
||||||
# self here refers to the widget i.e FloatLayout
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
MDLabel:
|
|
||||||
size_hint_y: None
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'Silver'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'We provide for proof of work calculation for six month. '
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: '€ 100.0'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDRaisedButton:
|
|
||||||
canvas:
|
|
||||||
Color:
|
|
||||||
rgb: (0.93, 0.93, 0.93)
|
|
||||||
Rectangle:
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
size_hint: 1, None
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Get Monthly Credits'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (0,0,0,1)
|
|
||||||
halign: 'center'
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
padding: dp(5)
|
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: app.theme_cls.primary_dark
|
|
||||||
Rectangle:
|
|
||||||
# self here refers to the widget i.e FloatLayout
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
MDLabel:
|
|
||||||
size_hint_y: None
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'Gold'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: 'We provide for proof of work calculation for 1years. '
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: '€ 500.0'
|
|
||||||
halign: 'center'
|
|
||||||
color: 1,1,1,1
|
|
||||||
MDRaisedButton:
|
|
||||||
canvas:
|
|
||||||
Color:
|
|
||||||
rgb: (0.93, 0.93, 0.93)
|
|
||||||
Rectangle:
|
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
|
||||||
size_hint: 1, None
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Get Yearly Credits'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (0,0,0,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
|
|
||||||
<GrashofPopup>:
|
|
||||||
id: popup
|
|
||||||
size_hint : (None,None)
|
|
||||||
height: 2*(label.height + address.height) + 10
|
|
||||||
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
|
||||||
title: 'add contact\'s'
|
|
||||||
background: './images/popup.jpeg'
|
|
||||||
title_size: sp(20)
|
|
||||||
title_color: 0.4, 0.3765, 0.3451, 1
|
|
||||||
auto_dismiss: False
|
|
||||||
separator_color: 0.3529, 0.3922, 0.102, 0.7
|
|
||||||
BoxLayout:
|
|
||||||
size_hint_y: 0.5
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing:dp(20)
|
|
||||||
id: popup_box
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
MDTextField:
|
|
||||||
id: label
|
|
||||||
multiline: False
|
|
||||||
hint_text: "Label"
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
on_text: root.checkLabel_valid(self)
|
|
||||||
MDTextField:
|
|
||||||
id: address
|
|
||||||
hint_text: "Address"
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
on_text: root.checkAddress_valid(self)
|
|
||||||
BoxLayout:
|
|
||||||
spacing:5
|
|
||||||
orientation: 'horizontal'
|
|
||||||
MDRaisedButton:
|
|
||||||
id: save_addr
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
on_release:
|
|
||||||
root.savecontact()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Save'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.dismiss()
|
|
||||||
on_press: root.close_pop()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Cancel'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 2, None
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Scan QR code'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
|
|
||||||
<NetworkStat>:
|
|
||||||
name: 'networkstat'
|
|
||||||
MDTabbedPanel:
|
|
||||||
id: tab_panel
|
|
||||||
tab_display_mode:'text'
|
|
||||||
|
|
||||||
MDTab:
|
|
||||||
name: 'connections'
|
|
||||||
text: "Total connections"
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(200)
|
|
||||||
OneLineListItem:
|
|
||||||
text: "Total Connections"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .6, .35
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.text_variable_1
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDTab:
|
|
||||||
name: 'processes'
|
|
||||||
text: 'Processes'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
MDList:
|
|
||||||
id: ml
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(500)
|
|
||||||
OneLineListItem:
|
|
||||||
text: "person-to-person"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .7, .6
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.text_variable_2
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
OneLineListItem:
|
|
||||||
text: "Brodcast"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .7, .6
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.text_variable_3
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
OneLineListItem:
|
|
||||||
text: "publickeys"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .7, .6
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.text_variable_4
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
OneLineListItem:
|
|
||||||
text: "objects"
|
|
||||||
BoxLayout:
|
|
||||||
AnchorLayout:
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: .7, .6
|
|
||||||
height: dp(40)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: root.text_variable_5
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<MailDetail>:
|
|
||||||
name: 'mailDetail'
|
|
||||||
ScrollView:
|
|
||||||
do_scroll_x: False
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(500) + self.minimum_height
|
|
||||||
padding: dp(32)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Headline'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.subject
|
|
||||||
halign: 'left'
|
|
||||||
font_size: '20sp'
|
|
||||||
CopyTextBtn:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "From: " + root.from_addr
|
|
||||||
halign: 'left'
|
|
||||||
CopyTextBtn:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "To: " + root.to_addr
|
|
||||||
halign: 'left'
|
|
||||||
CopyTextBtn:
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.status
|
|
||||||
halign: 'left'
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.message
|
|
||||||
halign: 'left'
|
|
||||||
bold: True
|
|
||||||
CopyTextBtn:
|
|
||||||
BoxLayout:
|
|
||||||
orientation: 'vertical'
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(100) + self.minimum_height
|
|
||||||
Loader:
|
|
||||||
|
|
||||||
<CopyTextBtn@Button>:
|
|
||||||
id: cpyButton
|
|
||||||
color: 0,0,0,1
|
|
||||||
background_color: (0,0,0,0)
|
|
||||||
center_x: self.parent.center_x * 2 - self.parent.parent.padding[0]/2
|
|
||||||
center_y: self.parent.center_y
|
|
||||||
on_press:app.root.ids.sc14.copy_composer_text(self)
|
|
||||||
Image:
|
|
||||||
source: './images/copy_text.png'
|
|
||||||
center_x: self.parent.center_x
|
|
||||||
center_y: self.parent.center_y
|
|
||||||
size: 20, 20
|
|
||||||
|
|
||||||
<ComposerButton@BoxLayout>:
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(56)
|
|
||||||
spacing: '10dp'
|
|
||||||
pos_hint: {'center_x':0.45, 'center_y': .1}
|
|
||||||
|
|
||||||
Widget:
|
|
||||||
|
|
||||||
MDFloatingActionButton:
|
|
||||||
icon: 'plus'
|
|
||||||
opposite_colors: True
|
|
||||||
elevation_normal: 8
|
|
||||||
md_bg_color: [0.941, 0, 0,1]
|
|
||||||
on_press: app.root.ids.scr_mngr.current = 'create'
|
|
||||||
on_press: app.clear_composer()
|
|
||||||
|
|
||||||
<MyaddDetailPopup>:
|
|
||||||
id: myadd_popup
|
|
||||||
size_hint : (None,None)
|
|
||||||
height: 4.5*(myaddr_label.height+ my_add_btn.children[0].height)
|
|
||||||
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
|
||||||
background: './images/popup.jpeg'
|
|
||||||
auto_dismiss: False
|
|
||||||
separator_height: 0
|
|
||||||
BoxLayout:
|
|
||||||
id: myadd_popup_box
|
|
||||||
size_hint_y: None
|
|
||||||
spacing:dp(70)
|
|
||||||
orientation: 'vertical'
|
|
||||||
BoxLayout:
|
|
||||||
size_hint_y: None
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing:dp(25)
|
|
||||||
MDLabel:
|
|
||||||
id: myaddr_label
|
|
||||||
font_style: 'Title'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Label"
|
|
||||||
font_size: '17sp'
|
|
||||||
halign: 'left'
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.address_label
|
|
||||||
font_size: '15sp'
|
|
||||||
halign: 'left'
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Address"
|
|
||||||
font_size: '17sp'
|
|
||||||
halign: 'left'
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.address
|
|
||||||
font_size: '15sp'
|
|
||||||
halign: 'left'
|
|
||||||
BoxLayout:
|
|
||||||
id: my_add_btn
|
|
||||||
spacing:5
|
|
||||||
orientation: 'horizontal'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 2, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.send_message_from()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Send message from'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.dismiss()
|
|
||||||
on_press: app.root.ids.scr_mngr.current = 'showqrcode'
|
|
||||||
on_press: app.root.ids.sc15.qrdisplay()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Show QR code'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.dismiss()
|
|
||||||
on_press: root.close_pop()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Cancel'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<AddbookDetailPopup>:
|
|
||||||
id: addbook_popup
|
|
||||||
size_hint : (None,None)
|
|
||||||
height: 4*(add_label.height)
|
|
||||||
width :app.window_size[0] - (app.window_size[0]/10 if app.app_platform == 'android' else app.window_size[0]/4)
|
|
||||||
background: './images/popup.jpeg'
|
|
||||||
separator_height: 0
|
|
||||||
auto_dismiss: False
|
|
||||||
BoxLayout:
|
|
||||||
size_hint_y: None
|
|
||||||
spacing:dp(70)
|
|
||||||
id: addbook_popup_box
|
|
||||||
orientation: 'vertical'
|
|
||||||
BoxLayout:
|
|
||||||
size_hint_y: None
|
|
||||||
orientation: 'vertical'
|
|
||||||
spacing:dp(20)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Label"
|
|
||||||
font_size: '17sp'
|
|
||||||
halign: 'left'
|
|
||||||
MDTextField:
|
|
||||||
id: add_label
|
|
||||||
font_style: 'Subhead'
|
|
||||||
font_size: '15sp'
|
|
||||||
halign: 'left'
|
|
||||||
text: root.address_label
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
required: True
|
|
||||||
helper_text_mode: "on_error"
|
|
||||||
on_text: root.checkLabel_valid(self)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: "Address"
|
|
||||||
font_size: '17sp'
|
|
||||||
halign: 'left'
|
|
||||||
MDLabel:
|
|
||||||
id: address
|
|
||||||
font_style: 'Subhead'
|
|
||||||
theme_text_color: 'Primary'
|
|
||||||
text: root.address
|
|
||||||
font_size: '15sp'
|
|
||||||
halign: 'left'
|
|
||||||
BoxLayout:
|
|
||||||
id: addbook_btn
|
|
||||||
spacing:5
|
|
||||||
orientation: 'horizontal'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 2, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.send_message_to()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Send message to'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
font_size: '10sp'
|
|
||||||
on_press: root.update_addbook_label(root.address)
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Save'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
MDRaisedButton:
|
|
||||||
size_hint: 1.5, None
|
|
||||||
height: dp(40)
|
|
||||||
on_press: root.dismiss()
|
|
||||||
on_press: root.close_pop()
|
|
||||||
MDLabel:
|
|
||||||
font_style: 'Title'
|
|
||||||
text: 'Cancel'
|
|
||||||
font_size: '13sp'
|
|
||||||
color: (1,1,1,1)
|
|
||||||
halign: 'center'
|
|
||||||
|
|
||||||
<ShowQRCode>:
|
<ShowQRCode>:
|
||||||
name: 'showqrcode'
|
name: 'showqrcode'
|
||||||
|
@ -1288,45 +277,18 @@ NavigationLayout:
|
||||||
orientation: 'vertical'
|
orientation: 'vertical'
|
||||||
id: qr
|
id: qr
|
||||||
|
|
||||||
|
<Starred>:
|
||||||
|
name: 'starred'
|
||||||
|
Label:
|
||||||
|
text:"I am in Starred"
|
||||||
|
color: 0,0,0,1
|
||||||
|
|
||||||
<ArrowImg@Image>:
|
color: 0,0,0,1
|
||||||
source: './images/down-arrow.png' if self.parent.is_open == True else './images/right-arrow.png'
|
|
||||||
size: 15, 15
|
|
||||||
x: self.parent.x + self.parent.width - self.width - 5
|
|
||||||
y: self.parent.y + self.parent.height/2 - self.height + 5
|
|
||||||
|
|
||||||
|
<Archieve>:
|
||||||
|
name: 'archieve'
|
||||||
|
Label:
|
||||||
|
text:"I am in Archieve"
|
||||||
|
color: 0,0,0,1
|
||||||
|
|
||||||
<SearchBar@BoxLayout>:
|
color: 0,0,0,1
|
||||||
id: search_bar
|
|
||||||
size_hint_y: None
|
|
||||||
height: self.minimum_height
|
|
||||||
|
|
||||||
MDIconButton:
|
|
||||||
icon: 'magnify'
|
|
||||||
|
|
||||||
MDTextField:
|
|
||||||
id: search_field
|
|
||||||
hint_text: 'Search'
|
|
||||||
on_text: app.searchQuery(self)
|
|
||||||
|
|
||||||
|
|
||||||
<LoadingPopup>:
|
|
||||||
separator_color: 1, 1, 1, 1
|
|
||||||
background: "White.png"
|
|
||||||
Button:
|
|
||||||
id: btn
|
|
||||||
disabled: True
|
|
||||||
background_disabled_normal: "White.png"
|
|
||||||
Image:
|
|
||||||
source: './images/loader.zip'
|
|
||||||
anim_delay: 0
|
|
||||||
#mipmap: True
|
|
||||||
size: root.size
|
|
||||||
|
|
||||||
|
|
||||||
<Loader@MDSpinner>:
|
|
||||||
id: spinner
|
|
||||||
size_hint: None, None
|
|
||||||
size: dp(46), dp(46)
|
|
||||||
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
|
|
||||||
active: False
|
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
"""
|
"""
|
||||||
Bitmessage android(mobile) interface
|
Bitmessage android(mobile) interface
|
||||||
"""
|
"""
|
||||||
# pylint: disable=relative-import, import-error, no-name-in-module
|
# pylint: disable=too-many-lines,import-error,no-name-in-module,unused-argument
|
||||||
# pylint: disable=too-few-public-methods, too-many-lines, unused-argument
|
# pylint: disable=too-many-ancestors,too-many-locals,useless-super-delegation
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
from bitmessagekivy import identiconGeneration
|
||||||
|
from bitmessagekivy import kivy_helper_search
|
||||||
|
from bitmessagekivy.uikivysignaler import UIkivySignaler
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from helper_sql import sqlExecute, sqlQuery
|
from helper_sql import sqlExecute, sqlQuery
|
||||||
from kivy.app import App
|
from kivymd.app import MDApp
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.core.clipboard import Clipboard
|
from kivy.core.clipboard import Clipboard
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
from kivy.metrics import dp
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ListProperty,
|
ListProperty,
|
||||||
|
@ -35,58 +39,87 @@ from kivy.uix.screenmanager import Screen
|
||||||
from kivy.uix.spinner import Spinner
|
from kivy.uix.spinner import Spinner
|
||||||
from kivy.uix.textinput import TextInput
|
from kivy.uix.textinput import TextInput
|
||||||
from kivy.utils import platform
|
from kivy.utils import platform
|
||||||
|
from kivymd.uix.button import MDIconButton
|
||||||
import kivy_helper_search
|
from kivymd.uix.dialog import MDDialog
|
||||||
from kivymd.button import MDIconButton
|
from kivymd.uix.label import MDLabel
|
||||||
from kivymd.dialog import MDDialog
|
from kivymd.uix.list import (
|
||||||
from kivymd.label import MDLabel
|
|
||||||
from kivymd.list import (
|
|
||||||
ILeftBody,
|
ILeftBody,
|
||||||
ILeftBodyTouch,
|
ILeftBodyTouch,
|
||||||
IRightBodyTouch,
|
IRightBodyTouch,
|
||||||
TwoLineAvatarIconListItem,
|
TwoLineAvatarIconListItem,
|
||||||
TwoLineListItem
|
OneLineIconListItem,
|
||||||
|
OneLineAvatarIconListItem,
|
||||||
|
OneLineListItem
|
||||||
)
|
)
|
||||||
from kivymd.navigationdrawer import (
|
# from kivymd.uix.navigationdrawer import (
|
||||||
MDNavigationDrawer,
|
# MDNavigationDrawer,
|
||||||
NavigationDrawerHeaderBase
|
# NavigationDrawerHeaderBase
|
||||||
)
|
# )
|
||||||
from kivymd.selectioncontrols import MDCheckbox
|
from kivymd.uix.selectioncontrol import MDCheckbox, MDSwitch
|
||||||
from kivymd.theming import ThemeManager
|
|
||||||
|
|
||||||
import queues
|
import queues
|
||||||
from semaphores import kivyuisignaler
|
from semaphores import kivyuisignaler
|
||||||
|
|
||||||
import state
|
import state
|
||||||
from uikivysignaler import UIkivySignaler
|
from addresses import decodeAddress
|
||||||
|
from kivy.config import Config
|
||||||
|
Config.set('input', 'mouse', 'mouse,multitouch_on_demand')
|
||||||
|
# pylint: disable=too-few-public-methods,too-many-arguments,attribute-defined-outside-init
|
||||||
|
|
||||||
import identiconGeneration
|
KVFILES = [
|
||||||
from addresses import addBMIfNotPresent, decodeAddress
|
'settings', 'popup', 'allmails', 'draft',
|
||||||
|
'maildetail', 'common_widgets', 'addressbook',
|
||||||
|
'myaddress', 'composer', 'payment', 'sent',
|
||||||
|
'network', 'login', 'credits', 'trash', 'inbox'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def toast(text):
|
def toast(text):
|
||||||
"""Function displays toast message"""
|
"""Method will display the toast message"""
|
||||||
# pylint: disable=redefined-outer-name
|
# pylint: disable=redefined-outer-name
|
||||||
from kivymd.toast.kivytoast import toast
|
from kivymd.toast.kivytoast import toast
|
||||||
toast(text)
|
toast(text)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class Navigatorss(MDNavigationDrawer):
|
def showLimitedCnt(total_msg):
|
||||||
"""Navigator class (image, title and logo)"""
|
"""This method set the total count limit in badge_text"""
|
||||||
image_source = StringProperty('images/qidenticon_two.png')
|
return "99+" if total_msg > 99 else str(total_msg)
|
||||||
title = StringProperty('Navigation')
|
|
||||||
drawer_logo = StringProperty()
|
|
||||||
|
def ShowTimeHistoy(act_time):
|
||||||
|
"""This method is used to return the message sent or receive time"""
|
||||||
|
from datetime import datetime
|
||||||
|
action_time = datetime.fromtimestamp(int(act_time))
|
||||||
|
crnt_date = datetime.now()
|
||||||
|
duration = crnt_date - action_time
|
||||||
|
display_data = (action_time.strftime('%d/%m/%Y')
|
||||||
|
if duration.days >= 365 else action_time.strftime('%I:%M %p').lstrip('0')
|
||||||
|
if duration.days == 0 and crnt_date.strftime('%d/%m/%Y') == action_time.strftime('%d/%m/%Y')
|
||||||
|
else action_time.strftime("%d %b"))
|
||||||
|
return display_data
|
||||||
|
|
||||||
|
|
||||||
|
def AddTimeWidget(time):
|
||||||
|
"""This method is used to create TimeWidget"""
|
||||||
|
action_time = BadgeText(
|
||||||
|
size_hint= (None, None),
|
||||||
|
text= f"{ShowTimeHistoy(time)}",
|
||||||
|
halign='right',
|
||||||
|
font_style='Caption',
|
||||||
|
size= [65,70])
|
||||||
|
return action_time
|
||||||
|
|
||||||
|
|
||||||
class Inbox(Screen):
|
class Inbox(Screen):
|
||||||
"""Inbox Screen uses screen to show widgets of screens."""
|
"""Inbox Screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
queryreturn = ListProperty()
|
queryreturn = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
account = StringProperty()
|
account = StringProperty()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Method Parsing the address."""
|
"""Method Parsing the address"""
|
||||||
super(Inbox, self).__init__(*args, **kwargs)
|
super(Inbox, self).__init__(*args, **kwargs)
|
||||||
Clock.schedule_once(self.init_ui, 0)
|
Clock.schedule_once(self.init_ui, 0)
|
||||||
|
|
||||||
|
@ -98,12 +131,11 @@ class Inbox(Screen):
|
||||||
state.association = BMConfigParser().addresses()[0]
|
state.association = BMConfigParser().addresses()[0]
|
||||||
|
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock schdule for method inbox accounts."""
|
"""Clock schdule for method inbox accounts"""
|
||||||
self.loadMessagelist()
|
self.loadMessagelist()
|
||||||
|
|
||||||
def loadMessagelist(self, where="", what=""):
|
def loadMessagelist(self, where="", what=""):
|
||||||
"""Load Inbox list for Inbox messages."""
|
"""Load Inbox list for Inbox messages"""
|
||||||
# pylint: disable=too-many-locals
|
|
||||||
self.set_defaultAddress()
|
self.set_defaultAddress()
|
||||||
self.account = state.association
|
self.account = state.association
|
||||||
if state.searcing_text:
|
if state.searcing_text:
|
||||||
|
@ -112,36 +144,46 @@ class Inbox(Screen):
|
||||||
what = state.searcing_text
|
what = state.searcing_text
|
||||||
xAddress = 'toaddress'
|
xAddress = 'toaddress'
|
||||||
data = []
|
data = []
|
||||||
|
self.ids.identi_tag.children[0].text = ''
|
||||||
self.inboxDataQuery(xAddress, where, what)
|
self.inboxDataQuery(xAddress, where, what)
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
if self.queryreturn:
|
if self.queryreturn:
|
||||||
self.ids.identi_tag.children[0].text = 'Inbox'
|
self.ids.identi_tag.children[0].text = 'Inbox'
|
||||||
state.kivyapp.get_inbox_count()
|
state.kivyapp.get_inbox_count()
|
||||||
src_mng_obj = state.kivyapp.root.children[2].children[0].ids
|
self.set_inboxCount(state.inbox_count)
|
||||||
src_mng_obj.inbox_cnt.badge_text = state.inbox_count
|
|
||||||
for mail in self.queryreturn:
|
for mail in self.queryreturn:
|
||||||
# third_text = mail[3].replace('\n', ' ')
|
# third_text = mail[3].replace('\n', ' ')
|
||||||
|
subject = mail[3].decode() if isinstance(mail[3],bytes) else mail[3]
|
||||||
|
body = mail[5].decode() if isinstance(mail[5],bytes) else mail[5]
|
||||||
data.append({
|
data.append({
|
||||||
'text': mail[4].strip(),
|
'text': mail[4].strip(),
|
||||||
'secondary_text': mail[5][:50] + '........' if len(
|
'secondary_text': body[:50] + '........' if len(
|
||||||
mail[5]) >= 50 else (mail[5] + ',' + mail[3].replace(
|
body) >= 50 else (body + ',' + subject.replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
'msgid': mail[1]})
|
'msgid': mail[1], 'received': mail[6]})
|
||||||
self.has_refreshed = True
|
self.has_refreshed = True
|
||||||
self.set_mdList(data)
|
self.set_mdList(data)
|
||||||
self.children[2].children[0].children[0].bind(
|
self.children[2].children[0].children[0].bind(
|
||||||
scroll_y=self.check_scroll_y)
|
scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
|
self.set_inboxCount('0')
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="No message found!" if state.searcing_text
|
text="No message found!" if state.searcing_text
|
||||||
else "yet no message for this account!!!!!!!!!!!!!",
|
else "yet no message for this account!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments
|
def set_inboxCount(self, msgCnt): # pylint: disable=no-self-use
|
||||||
|
"""This method is used to sent inbox message count"""
|
||||||
|
src_mng_obj = state.kivyapp.root.ids.content_drawer.ids.inbox_cnt
|
||||||
|
src_mng_obj.children[0].children[0].text = showLimitedCnt(int(msgCnt))
|
||||||
|
|
||||||
def inboxDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
def inboxDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
||||||
"""This method used for retrieving inbox data"""
|
"""This method is used for retrieving inbox data"""
|
||||||
self.queryreturn = kivy_helper_search.search_sql(
|
self.queryreturn = kivy_helper_search.search_sql(
|
||||||
xAddress, self.account, "inbox", where, what,
|
xAddress, self.account, "inbox", where, what,
|
||||||
False, start_indx, end_indx)
|
False, start_indx, end_indx)
|
||||||
|
@ -158,6 +200,7 @@ class Inbox(Screen):
|
||||||
source='./images/text_images/{}.png'.format(
|
source='./images/text_images/{}.png'.format(
|
||||||
avatarImageFirstLetter(item['secondary_text'].strip()))))
|
avatarImageFirstLetter(item['secondary_text'].strip()))))
|
||||||
meny.bind(on_press=partial(self.inbox_detail, item['msgid']))
|
meny.bind(on_press=partial(self.inbox_detail, item['msgid']))
|
||||||
|
meny.add_widget(AddTimeWidget(item['received']))
|
||||||
carousel = Carousel(direction='right')
|
carousel = Carousel(direction='right')
|
||||||
carousel.height = meny.height
|
carousel.height = meny.height
|
||||||
carousel.size_hint_y = None
|
carousel.size_hint_y = None
|
||||||
|
@ -170,10 +213,10 @@ class Inbox(Screen):
|
||||||
del_btn.bind(on_press=partial(self.delete, item['msgid']))
|
del_btn.bind(on_press=partial(self.delete, item['msgid']))
|
||||||
carousel.add_widget(del_btn)
|
carousel.add_widget(del_btn)
|
||||||
carousel.add_widget(meny)
|
carousel.add_widget(meny)
|
||||||
ach_btn = Button(text='Achieve')
|
# ach_btn = Button(text='Achieve')
|
||||||
ach_btn.background_color = (0, 1, 0, 1)
|
# ach_btn.background_color = (0, 1, 0, 1)
|
||||||
ach_btn.bind(on_press=partial(self.archive, item['msgid']))
|
# ach_btn.bind(on_press=partial(self.archive, item['msgid']))
|
||||||
carousel.add_widget(ach_btn)
|
# carousel.add_widget(ach_btn)
|
||||||
carousel.index = 1
|
carousel.index = 1
|
||||||
self.ids.ml.add_widget(carousel)
|
self.ids.ml.add_widget(carousel)
|
||||||
update_message = len(self.ids.ml.children)
|
update_message = len(self.ids.ml.children)
|
||||||
|
@ -198,10 +241,12 @@ class Inbox(Screen):
|
||||||
self.inboxDataQuery('toaddress', where, what, total_message, 5)
|
self.inboxDataQuery('toaddress', where, what, total_message, 5)
|
||||||
for mail in self.queryreturn:
|
for mail in self.queryreturn:
|
||||||
# third_text = mail[3].replace('\n', ' ')
|
# third_text = mail[3].replace('\n', ' ')
|
||||||
|
subject = mail[3].decode() if isinstance(mail[3],bytes) else mail[3]
|
||||||
|
body = mail[5].decode() if isinstance(mail[5],bytes) else mail[5]
|
||||||
data.append({
|
data.append({
|
||||||
'text': mail[4].strip(),
|
'text': mail[4].strip(),
|
||||||
'secondary_text': mail[5][:50] + '........' if len(
|
'secondary_text': body[:50] + '........' if len(
|
||||||
mail[5]) >= 50 else (mail[5] + ',' + mail[3].replace(
|
body) >= 50 else (body + ',' +subject.replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
'msgid': mail[1]})
|
'msgid': mail[1]})
|
||||||
self.set_mdList(data)
|
self.set_mdList(data)
|
||||||
|
@ -221,22 +266,12 @@ class Inbox(Screen):
|
||||||
def delete(self, data_index, instance, *args):
|
def delete(self, data_index, instance, *args):
|
||||||
"""Delete inbox mail from inbox listing"""
|
"""Delete inbox mail from inbox listing"""
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", str(
|
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", data_index)
|
||||||
data_index))
|
msg_count_objs = self.parent.parent.ids.content_drawer.ids
|
||||||
try:
|
|
||||||
msg_count_objs = (
|
|
||||||
self.parent.parent.parent.parent.children[2].children[0].ids)
|
|
||||||
except Exception:
|
|
||||||
msg_count_objs = (
|
|
||||||
self.parent.parent.parent.parent.parent.children[
|
|
||||||
2].children[0].ids)
|
|
||||||
if int(state.inbox_count) > 0:
|
if int(state.inbox_count) > 0:
|
||||||
msg_count_objs.inbox_cnt.badge_text = str(
|
msg_count_objs.inbox_cnt.children[0].children[0].text = showLimitedCnt(int(state.inbox_count) - 1)
|
||||||
int(state.inbox_count) - 1)
|
msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt(int(state.trash_count) + 1)
|
||||||
msg_count_objs.trash_cnt.badge_text = str(
|
msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt(int(state.all_count) - 1)
|
||||||
int(state.trash_count) + 1)
|
|
||||||
msg_count_objs.allmail_cnt.badge_text = str(
|
|
||||||
int(state.all_count) - 1)
|
|
||||||
state.inbox_count = str(
|
state.inbox_count = str(
|
||||||
int(state.inbox_count) - 1)
|
int(state.inbox_count) - 1)
|
||||||
state.trash_count = str(
|
state.trash_count = str(
|
||||||
|
@ -253,8 +288,7 @@ class Inbox(Screen):
|
||||||
def archive(self, data_index, instance, *args):
|
def archive(self, data_index, instance, *args):
|
||||||
"""Archive inbox mail from inbox listing"""
|
"""Archive inbox mail from inbox listing"""
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;",
|
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;", data_index)
|
||||||
str(data_index))
|
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
self.update_trash()
|
self.update_trash()
|
||||||
|
|
||||||
|
@ -267,7 +301,6 @@ class Inbox(Screen):
|
||||||
self.parent.parent.screens[4].clear_widgets()
|
self.parent.parent.screens[4].clear_widgets()
|
||||||
self.parent.parent.screens[4].add_widget(Trash())
|
self.parent.parent.screens[4].add_widget(Trash())
|
||||||
|
|
||||||
# pylint: disable=attribute-defined-outside-init
|
|
||||||
def refresh_callback(self, *args):
|
def refresh_callback(self, *args):
|
||||||
"""Method updates the state of application,
|
"""Method updates the state of application,
|
||||||
While the spinner remains on the screen"""
|
While the spinner remains on the screen"""
|
||||||
|
@ -282,34 +315,30 @@ class Inbox(Screen):
|
||||||
self.tick = 0
|
self.tick = 0
|
||||||
Clock.schedule_once(refresh_callback, 1)
|
Clock.schedule_once(refresh_callback, 1)
|
||||||
|
|
||||||
# def set_root_layout(self):
|
|
||||||
# """Setting root layout"""
|
|
||||||
# return self.parent.parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
class MyAddress(Screen):
|
class MyAddress(Screen):
|
||||||
"""MyAddress screen uses screen to show widgets of screens."""
|
"""MyAddress screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
addresses_list = ListProperty()
|
addresses_list = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
is_add_created = False
|
is_add_created = False
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Clock schdule for method Myaddress accounts."""
|
"""Clock schdule for method Myaddress accounts"""
|
||||||
super(MyAddress, self).__init__(*args, **kwargs)
|
super(MyAddress, self).__init__(*args, **kwargs)
|
||||||
Clock.schedule_once(self.init_ui, 0)
|
Clock.schedule_once(self.init_ui, 0)
|
||||||
|
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock schdule for method Myaddress accounts"""
|
"""Clock schdule for method Myaddress accounts"""
|
||||||
self.addresses_list = state.kivyapp.variable_1
|
# pylint: disable=unnecessary-lambda, deprecated-lambda
|
||||||
|
# self.addresses_list = state.kivyapp.variable_1
|
||||||
|
self.addresses_list = BMConfigParser().addresses()
|
||||||
if state.searcing_text:
|
if state.searcing_text:
|
||||||
self.ids.refresh_layout.scroll_y = 1.0
|
self.ids.refresh_layout.scroll_y = 1.0
|
||||||
# filtered_list = filter(
|
|
||||||
# lambda addr: self.filter_address(
|
|
||||||
# addr), BMConfigParser().addresses())
|
|
||||||
filtered_list = [
|
filtered_list = [
|
||||||
x
|
x for x in BMConfigParser().addresses()
|
||||||
for x in BMConfigParser().addresses()
|
if self.filter_address(x)
|
||||||
if self.filter_address(x)]
|
]
|
||||||
self.addresses_list = filtered_list
|
self.addresses_list = filtered_list
|
||||||
self.addresses_list = [obj for obj in reversed(self.addresses_list)]
|
self.addresses_list = [obj for obj in reversed(self.addresses_list)]
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
|
@ -320,10 +349,13 @@ class MyAddress(Screen):
|
||||||
self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y)
|
self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="No address found!" if state.searcing_text
|
text="No address found!" if state.searcing_text
|
||||||
else "yet no address is created by user!!!!!!!!!!!!!",
|
else "yet no address is created by user!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
if not state.searcing_text and not self.is_add_created:
|
if not state.searcing_text and not self.is_add_created:
|
||||||
try:
|
try:
|
||||||
|
@ -339,15 +371,41 @@ class MyAddress(Screen):
|
||||||
'text': BMConfigParser().get(address, 'label'),
|
'text': BMConfigParser().get(address, 'label'),
|
||||||
'secondary_text': address})
|
'secondary_text': address})
|
||||||
for item in data:
|
for item in data:
|
||||||
|
is_enable = BMConfigParser().get(item['secondary_text'], 'enabled')
|
||||||
meny = TwoLineAvatarIconListItem(
|
meny = TwoLineAvatarIconListItem(
|
||||||
text=item['text'], secondary_text=item['secondary_text'],
|
text=item['text'], secondary_text=item['secondary_text'],
|
||||||
theme_text_color='Custom',
|
theme_text_color='Custom' if is_enable == 'true' else 'Primary',
|
||||||
text_color=NavigateApp().theme_cls.primary_color)
|
text_color=NavigateApp().theme_cls.primary_color,
|
||||||
|
)
|
||||||
meny.add_widget(AvatarSampleWidget(
|
meny.add_widget(AvatarSampleWidget(
|
||||||
source='./images/text_images/{}.png'.format(
|
source='./images/text_images/{}.png'.format(
|
||||||
avatarImageFirstLetter(item['text'].strip()))))
|
avatarImageFirstLetter(item['text'].strip()))))
|
||||||
meny.bind(on_press=partial(
|
meny.bind(on_press=partial(
|
||||||
self.myadd_detail, item['secondary_text'], item['text']))
|
self.myadd_detail, item['secondary_text'], item['text']))
|
||||||
|
if state.association == item['secondary_text']:
|
||||||
|
meny.add_widget(BadgeText(size_hint= (None, None),
|
||||||
|
text='Active', halign='right',
|
||||||
|
font_style='Body1', size= [50,60],
|
||||||
|
theme_text_color='Custom',
|
||||||
|
text_color=NavigateApp().theme_cls.primary_color))
|
||||||
|
else:
|
||||||
|
meny.add_widget(ToggleBtn(active = True if is_enable == 'true' else False))
|
||||||
|
# carousel = Carousel(direction='right')
|
||||||
|
# carousel.height = meny.height
|
||||||
|
# carousel.size_hint_y = None
|
||||||
|
# carousel.ignore_perpendicular_swipes = True
|
||||||
|
# carousel.data_index = 0
|
||||||
|
# carousel.min_move = 0.2
|
||||||
|
# del_btn = Button(text='Disable' if is_enable == 'true' else 'Enable')
|
||||||
|
# if is_enable == 'true':
|
||||||
|
# del_btn.background_normal = ''
|
||||||
|
# del_btn.background_color = (1, 0, 0, 1) if is_enable == 'true' else (0, 1, 0, 1)
|
||||||
|
# del_btn.bind(
|
||||||
|
# on_press=partial(
|
||||||
|
# self.disableAddress if is_enable == 'true' else self.enableAddress , item['secondary_text']))
|
||||||
|
# carousel.add_widget(del_btn)
|
||||||
|
# carousel.add_widget(meny)
|
||||||
|
# carousel.index = 1
|
||||||
self.ids.ml.add_widget(meny)
|
self.ids.ml.add_widget(meny)
|
||||||
|
|
||||||
def check_scroll_y(self, instance, somethingelse):
|
def check_scroll_y(self, instance, somethingelse):
|
||||||
|
@ -369,18 +427,18 @@ class MyAddress(Screen):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def myadd_detail(fromaddress, label, *args):
|
def myadd_detail(fromaddress, label, *args):
|
||||||
"""Load myaddresses details"""
|
"""Load myaddresses details"""
|
||||||
|
if BMConfigParser().get(fromaddress, 'enabled') == 'true':
|
||||||
p = MyaddDetailPopup()
|
p = MyaddDetailPopup()
|
||||||
p.open()
|
p.open()
|
||||||
p.set_address(fromaddress, label)
|
p.set_address(fromaddress, label)
|
||||||
|
|
||||||
# pylint: disable=attribute-defined-outside-init
|
|
||||||
def refresh_callback(self, *args):
|
def refresh_callback(self, *args):
|
||||||
"""Method updates the state of application,
|
"""Method updates the state of application,
|
||||||
While the spinner remains on the screen"""
|
While the spinner remains on the screen"""
|
||||||
def refresh_callback(interval):
|
def refresh_callback(interval):
|
||||||
"""Method used for loading the myaddress screen data"""
|
"""Method used for loading the myaddress screen data"""
|
||||||
state.searcing_text = ''
|
state.searcing_text = ''
|
||||||
state.kivyapp.root.ids.sc10.children[2].active = False
|
# state.kivyapp.root.ids.sc10.children[2].active = False
|
||||||
self.children[2].children[2].ids.search_field.text = ''
|
self.children[2].children[2].ids.search_field.text = ''
|
||||||
self.has_refreshed = True
|
self.has_refreshed = True
|
||||||
self.ids.ml.clear_widgets()
|
self.ids.ml.clear_widgets()
|
||||||
|
@ -392,22 +450,52 @@ class MyAddress(Screen):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def filter_address(address):
|
def filter_address(address):
|
||||||
"""Method will filter the my address list data"""
|
"""Method will filter the my address list data"""
|
||||||
# if filter(lambda x: (state.searcing_text).lower() in x, [
|
if [
|
||||||
# BMConfigParser().get(
|
x for x in [
|
||||||
# address, 'label').lower(), address.lower()]):
|
BMConfigParser().get(address, 'label').lower(),
|
||||||
if [x for x in [BMConfigParser().get(
|
address.lower()
|
||||||
address, 'label').lower(), address.lower()] if (
|
]
|
||||||
state.searcing_text).lower() in x]:
|
if (state.searcing_text).lower() in x
|
||||||
|
]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def set_root_layout(self):
|
|
||||||
"""Setting root layout"""
|
def disableAddress(self, address, instance):
|
||||||
return self.manager.parent.parent
|
"""This method is use for disabling address"""
|
||||||
|
BMConfigParser().set(str(address), 'enabled', 'false')
|
||||||
|
BMConfigParser().save()
|
||||||
|
instance.parent.parent.theme_text_color = 'Primary'
|
||||||
|
toast('Address disabled')
|
||||||
|
Clock.schedule_once(self.address_permision_callback, 0)
|
||||||
|
|
||||||
|
def enableAddress(self, address, instance):
|
||||||
|
"""This method is use for enabling address"""
|
||||||
|
BMConfigParser().set(address, 'enabled', 'true')
|
||||||
|
BMConfigParser().save()
|
||||||
|
instance.parent.parent.theme_text_color = 'Custom'
|
||||||
|
toast('Address Enabled')
|
||||||
|
Clock.schedule_once(self.address_permision_callback, 0)
|
||||||
|
|
||||||
|
def address_permision_callback(self, dt=0):
|
||||||
|
"""callback for enable or disable addresses"""
|
||||||
|
addresses = [addr for addr in BMConfigParser().addresses()
|
||||||
|
if BMConfigParser().get(str(addr), 'enabled') == 'true']
|
||||||
|
self.parent.parent.ids.content_drawer.ids.btn.values = addresses
|
||||||
|
self.parent.parent.ids.sc3.children[1].ids.btn.values = addresses
|
||||||
|
|
||||||
|
def toggleAction(self, instance):
|
||||||
|
"""This method is used for enable or disable address"""
|
||||||
|
addr = instance.parent.parent.secondary_text
|
||||||
|
if instance.active:
|
||||||
|
self.disableAddress(addr, instance)
|
||||||
|
else:
|
||||||
|
self.enableAddress(addr, instance)
|
||||||
|
|
||||||
|
|
||||||
class AddressBook(Screen):
|
class AddressBook(Screen):
|
||||||
"""AddressBook Screen uses screen to show widgets of screens"""
|
"""AddressBook Screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
queryreturn = ListProperty()
|
queryreturn = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
|
|
||||||
|
@ -419,7 +507,7 @@ class AddressBook(Screen):
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock Schdule for method AddressBook"""
|
"""Clock Schdule for method AddressBook"""
|
||||||
self.loadAddresslist(None, 'All', '')
|
self.loadAddresslist(None, 'All', '')
|
||||||
print dt
|
print(dt)
|
||||||
|
|
||||||
def loadAddresslist(self, account, where="", what=""):
|
def loadAddresslist(self, account, where="", what=""):
|
||||||
"""Clock Schdule for method AddressBook"""
|
"""Clock Schdule for method AddressBook"""
|
||||||
|
@ -439,10 +527,13 @@ class AddressBook(Screen):
|
||||||
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="No contact found!" if state.searcing_text
|
text="No contact found!" if state.searcing_text
|
||||||
else "No contact found yet...... ",
|
else "No contact found yet...... ",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
def set_mdList(self, start_index, end_index):
|
def set_mdList(self, start_index, end_index):
|
||||||
|
@ -504,7 +595,8 @@ class AddressBook(Screen):
|
||||||
def delete_address(self, address, instance, *args):
|
def delete_address(self, address, instance, *args):
|
||||||
"""Delete inbox mail from inbox listing"""
|
"""Delete inbox mail from inbox listing"""
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
if len(self.ids.ml.children) == 0:
|
# if len(self.ids.ml.children) == 0:
|
||||||
|
if self.ids.ml.children is not None:
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"DELETE FROM addressbook WHERE address = '{}';".format(address))
|
"DELETE FROM addressbook WHERE address = '{}';".format(address))
|
||||||
|
@ -513,12 +605,14 @@ class AddressBook(Screen):
|
||||||
class SelectableRecycleBoxLayout(
|
class SelectableRecycleBoxLayout(
|
||||||
FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
|
FocusBehavior, LayoutSelectionBehavior, RecycleBoxLayout):
|
||||||
"""Adds selection and focus behaviour to the view"""
|
"""Adds selection and focus behaviour to the view"""
|
||||||
# pylint: disable = too-many-ancestors, duplicate-bases
|
# pylint: disable = duplicate-bases
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SelectableLabel(RecycleDataViewBehavior, Label):
|
class SelectableLabel(RecycleDataViewBehavior, Label):
|
||||||
"""Add selection support to the Label"""
|
"""Add selection support to the Label"""
|
||||||
|
|
||||||
index = None
|
index = None
|
||||||
selected = BooleanProperty(False)
|
selected = BooleanProperty(False)
|
||||||
selectable = BooleanProperty(True)
|
selectable = BooleanProperty(True)
|
||||||
|
@ -529,8 +623,7 @@ class SelectableLabel(RecycleDataViewBehavior, Label):
|
||||||
return super(SelectableLabel, self).refresh_view_attrs(
|
return super(SelectableLabel, self).refresh_view_attrs(
|
||||||
rv, index, data)
|
rv, index, data)
|
||||||
|
|
||||||
# pylint: disable=inconsistent-return-statements
|
def on_touch_down(self, touch): # pylint: disable=inconsistent-return-statements
|
||||||
def on_touch_down(self, touch):
|
|
||||||
"""Add selection on touch down"""
|
"""Add selection on touch down"""
|
||||||
if super(SelectableLabel, self).on_touch_down(touch):
|
if super(SelectableLabel, self).on_touch_down(touch):
|
||||||
return True
|
return True
|
||||||
|
@ -541,7 +634,7 @@ class SelectableLabel(RecycleDataViewBehavior, Label):
|
||||||
"""Respond to the selection of items in the view"""
|
"""Respond to the selection of items in the view"""
|
||||||
self.selected = is_selected
|
self.selected = is_selected
|
||||||
if is_selected:
|
if is_selected:
|
||||||
print "selection changed to {0}".format(rv.data[index])
|
print("selection changed to {0}".format(rv.data[index]))
|
||||||
rv.parent.txt_input.text = rv.parent.txt_input.text.replace(
|
rv.parent.txt_input.text = rv.parent.txt_input.text.replace(
|
||||||
rv.parent.txt_input.text, rv.data[index]['text'])
|
rv.parent.txt_input.text, rv.data[index]['text'])
|
||||||
|
|
||||||
|
@ -549,26 +642,26 @@ class SelectableLabel(RecycleDataViewBehavior, Label):
|
||||||
class RV(RecycleView):
|
class RV(RecycleView):
|
||||||
"""Recycling View"""
|
"""Recycling View"""
|
||||||
|
|
||||||
def __init__(self, **kwargs): # pylint: disable=useless-super-delegation
|
def __init__(self, **kwargs):
|
||||||
"""Recycling Method"""
|
"""Recycling Method"""
|
||||||
super(RV, self).__init__(**kwargs)
|
super(RV, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class DropDownWidget(BoxLayout):
|
class DropDownWidget(BoxLayout):
|
||||||
"""Adding Dropdown Widget"""
|
"""Adding Dropdown Widget"""
|
||||||
# pylint: disable=too-many-statements, too-many-locals
|
# pylint: disable=too-many-statements
|
||||||
# pylint: disable=inconsistent-return-statements
|
|
||||||
txt_input = ObjectProperty()
|
txt_input = ObjectProperty()
|
||||||
rv = ObjectProperty()
|
rv = ObjectProperty()
|
||||||
|
|
||||||
def send(self, navApp):
|
def send(self, navApp):
|
||||||
"""Send message from one address to another"""
|
"""Send message from one address to another"""
|
||||||
fromAddress = str(self.ids.ti.text)
|
fromAddress = self.ids.ti.text.strip()
|
||||||
toAddress = str(self.ids.txt_input.text)
|
toAddress = self.ids.txt_input.text.strip()
|
||||||
subject = self.ids.subject.text.encode('utf-8').strip()
|
subject = self.ids.subject.text.strip()
|
||||||
message = self.ids.body.text.encode('utf-8').strip()
|
message = self.ids.body.text.strip()
|
||||||
encoding = 3
|
encoding = 3
|
||||||
print "message: ", self.ids.body.text
|
print("message: ", self.ids.body.text)
|
||||||
sendMessageToPeople = True
|
sendMessageToPeople = True
|
||||||
if sendMessageToPeople:
|
if sendMessageToPeople:
|
||||||
if toAddress != '' and subject and message:
|
if toAddress != '' and subject and message:
|
||||||
|
@ -579,23 +672,35 @@ class DropDownWidget(BoxLayout):
|
||||||
if state.detailPageType == 'draft' \
|
if state.detailPageType == 'draft' \
|
||||||
and state.send_draft_mail:
|
and state.send_draft_mail:
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE sent SET toaddress = ?, fromaddress = ? ,"
|
"UPDATE sent SET toaddress = ?"
|
||||||
" subject = ?, message = ?, folder = 'sent' WHERE"
|
", fromaddress = ? , subject = ?"
|
||||||
" ackdata = ?;", toAddress, fromAddress, subject,
|
", message = ?, folder = 'sent'"
|
||||||
message, str(state.send_draft_mail))
|
", senttime = ?, lastactiontime = ?"
|
||||||
|
" WHERE ackdata = ?;",
|
||||||
|
toAddress,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
int(time.time()),
|
||||||
|
int(time.time()),
|
||||||
|
state.send_draft_mail)
|
||||||
self.parent.parent.screens[15].clear_widgets()
|
self.parent.parent.screens[15].clear_widgets()
|
||||||
self.parent.parent.screens[15].add_widget(Draft())
|
self.parent.parent.screens[15].add_widget(Draft())
|
||||||
|
# state.detailPageType = ''
|
||||||
|
# state.send_draft_mail = None
|
||||||
else:
|
else:
|
||||||
|
from addresses import addBMIfNotPresent
|
||||||
toAddress = addBMIfNotPresent(toAddress)
|
toAddress = addBMIfNotPresent(toAddress)
|
||||||
statusIconColor = 'red'
|
statusIconColor = 'red'
|
||||||
if (addressVersionNumber > 4) or (
|
if (addressVersionNumber > 4) or (
|
||||||
addressVersionNumber <= 1):
|
addressVersionNumber <= 1):
|
||||||
print "addressVersionNumber > 4"\
|
print(
|
||||||
" or addressVersionNumber <= 1"
|
"addressVersionNumber > 4"
|
||||||
|
" or addressVersionNumber <= 1")
|
||||||
if streamNumber > 1 or streamNumber == 0:
|
if streamNumber > 1 or streamNumber == 0:
|
||||||
print "streamNumber > 1 or streamNumber == 0"
|
print("streamNumber > 1 or streamNumber == 0")
|
||||||
if statusIconColor == 'red':
|
if statusIconColor == 'red':
|
||||||
print "shared.statusIconColor == 'red'"
|
print("shared.statusIconColor == 'red'")
|
||||||
stealthLevel = BMConfigParser().safeGetInt(
|
stealthLevel = BMConfigParser().safeGetInt(
|
||||||
'bitmessagesettings', 'ackstealthlevel')
|
'bitmessagesettings', 'ackstealthlevel')
|
||||||
from helper_ackPayload import genAckPayload
|
from helper_ackPayload import genAckPayload
|
||||||
|
@ -604,27 +709,36 @@ class DropDownWidget(BoxLayout):
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''INSERT INTO sent VALUES
|
'''INSERT INTO sent VALUES
|
||||||
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
|
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
|
||||||
'', toAddress, ripe, fromAddress, subject, message,
|
'',
|
||||||
ackdata, int(time.time()), int(time.time()), 0,
|
toAddress,
|
||||||
'msgqueued', 0, 'sent', encoding,
|
ripe,
|
||||||
BMConfigParser().getint(
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdata,
|
||||||
|
int(time.time()),
|
||||||
|
int(time.time()),
|
||||||
|
0,
|
||||||
|
'msgqueued',
|
||||||
|
0,
|
||||||
|
'sent',
|
||||||
|
encoding,
|
||||||
|
BMConfigParser().safeGetInt(
|
||||||
'bitmessagesettings', 'ttl'))
|
'bitmessagesettings', 'ttl'))
|
||||||
state.check_sent_acc = fromAddress
|
state.check_sent_acc = fromAddress
|
||||||
state.msg_counter_objs = self.parent.parent.parent.parent\
|
# state.msg_counter_objs = self.parent.parent.parent.parent\
|
||||||
.parent.parent.children[2].children[0].ids
|
# .parent.parent.children[2].children[0].ids
|
||||||
if state.detailPageType == 'draft' and state.send_draft_mail:
|
if state.detailPageType == 'draft' \
|
||||||
|
and state.send_draft_mail:
|
||||||
state.draft_count = str(int(state.draft_count) - 1)
|
state.draft_count = str(int(state.draft_count) - 1)
|
||||||
state.msg_counter_objs.draft_cnt.badge_text = state.draft_count
|
# state.msg_counter_objs.draft_cnt.badge_text = (
|
||||||
|
# state.draft_count)
|
||||||
state.detailPageType = ''
|
state.detailPageType = ''
|
||||||
state.send_draft_mail = None
|
state.send_draft_mail = None
|
||||||
# self.parent.parent.screens[0].ids.ml.clear_widgets()
|
|
||||||
# self.parent.parent.screens[0].loadMessagelist(state.association)
|
|
||||||
self.parent.parent.screens[3].update_sent_messagelist()
|
self.parent.parent.screens[3].update_sent_messagelist()
|
||||||
# self.parent.parent.screens[16].clear_widgets()
|
|
||||||
# self.parent.parent.screens[16].add_widget(Allmails())
|
|
||||||
Clock.schedule_once(self.callback_for_msgsend, 3)
|
Clock.schedule_once(self.callback_for_msgsend, 3)
|
||||||
queues.workerQueue.put(('sendmessage', toAddress))
|
queues.workerQueue.put(('sendmessage', toAddress))
|
||||||
print "sqlExecute successfully #######################"
|
print("sqlExecute successfully #######################")
|
||||||
state.in_composer = True
|
state.in_composer = True
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -643,7 +757,6 @@ class DropDownWidget(BoxLayout):
|
||||||
state.kivyapp.back_press()
|
state.kivyapp.back_press()
|
||||||
toast('sent')
|
toast('sent')
|
||||||
|
|
||||||
# pylint: disable=attribute-defined-outside-init
|
|
||||||
def address_error_message(self, msg):
|
def address_error_message(self, msg):
|
||||||
"""Generates error message"""
|
"""Generates error message"""
|
||||||
width = .8 if platform == 'android' else .55
|
width = .8 if platform == 'android' else .55
|
||||||
|
@ -654,7 +767,7 @@ class DropDownWidget(BoxLayout):
|
||||||
msg_dialog.open()
|
msg_dialog.open()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def callback_for_menu_items(text_item):
|
def callback_for_menu_items(text_item, *arg):
|
||||||
"""Callback of alert box"""
|
"""Callback of alert box"""
|
||||||
toast(text_item)
|
toast(text_item)
|
||||||
|
|
||||||
|
@ -675,14 +788,15 @@ class DropDownWidget(BoxLayout):
|
||||||
|
|
||||||
class MyTextInput(TextInput):
|
class MyTextInput(TextInput):
|
||||||
"""Takes the text input in the field"""
|
"""Takes the text input in the field"""
|
||||||
|
|
||||||
txt_input = ObjectProperty()
|
txt_input = ObjectProperty()
|
||||||
flt_list = ObjectProperty()
|
flt_list = ObjectProperty()
|
||||||
word_list = ListProperty()
|
word_list = ListProperty()
|
||||||
starting_no = NumericProperty(3)
|
starting_no = NumericProperty(3)
|
||||||
suggestion_text = ''
|
suggestion_text = ''
|
||||||
|
|
||||||
def __init__(self, **kwargs): # pylint: disable=useless-super-delegation
|
def __init__(self, **kwargs):
|
||||||
"""Getting Text Input"""
|
"""Getting Text Input."""
|
||||||
super(MyTextInput, self).__init__(**kwargs)
|
super(MyTextInput, self).__init__(**kwargs)
|
||||||
|
|
||||||
def on_text(self, instance, value):
|
def on_text(self, instance, value):
|
||||||
|
@ -712,8 +826,9 @@ class MyTextInput(TextInput):
|
||||||
class Payment(Screen):
|
class Payment(Screen):
|
||||||
"""Payment module"""
|
"""Payment module"""
|
||||||
|
|
||||||
def get_available_credits(self, instance): # pylint: disable=no-self-use
|
def get_available_credits(self, instance):
|
||||||
"""Get the available credits"""
|
"""Get the available credits"""
|
||||||
|
# pylint: disable=no-self-use
|
||||||
state.availabe_credit = instance.parent.children[1].text
|
state.availabe_credit = instance.parent.children[1].text
|
||||||
existing_credits = (
|
existing_credits = (
|
||||||
state.kivyapp.root.ids.sc18.ids.ml.children[0].children[
|
state.kivyapp.root.ids.sc18.ids.ml.children[0].children[
|
||||||
|
@ -730,17 +845,21 @@ class Payment(Screen):
|
||||||
|
|
||||||
|
|
||||||
class Credits(Screen):
|
class Credits(Screen):
|
||||||
"""Module for screen screen"""
|
"""Credits Method"""
|
||||||
available_credits = StringProperty('{0}'.format('0'))
|
|
||||||
|
available_credits = StringProperty(
|
||||||
|
'{0}'.format('0'))
|
||||||
|
|
||||||
|
|
||||||
class Login(Screen):
|
class Login(Screen):
|
||||||
"""Login Screeen"""
|
"""Login Screeen"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NetworkStat(Screen):
|
class NetworkStat(Screen):
|
||||||
"""Method used to show network stat"""
|
"""Method used to show network stat"""
|
||||||
|
|
||||||
text_variable_1 = StringProperty(
|
text_variable_1 = StringProperty(
|
||||||
'{0}::{1}'.format('Total Connections', '0'))
|
'{0}::{1}'.format('Total Connections', '0'))
|
||||||
text_variable_2 = StringProperty(
|
text_variable_2 = StringProperty(
|
||||||
|
@ -774,13 +893,15 @@ class NetworkStat(Screen):
|
||||||
len(objectracker.missingObjects))
|
len(objectracker.missingObjects))
|
||||||
|
|
||||||
|
|
||||||
class ContentNavigationDrawer(Navigatorss):
|
class ContentNavigationDrawer(BoxLayout):
|
||||||
"""Navigate Content Drawer"""
|
"""Navigate Content Drawer"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Random(Screen):
|
class Random(Screen):
|
||||||
"""Generates Random Address"""
|
"""Generates Random Address"""
|
||||||
|
|
||||||
is_active = BooleanProperty(False)
|
is_active = BooleanProperty(False)
|
||||||
checked = StringProperty("")
|
checked = StringProperty("")
|
||||||
|
|
||||||
|
@ -801,16 +922,16 @@ class Random(Screen):
|
||||||
"", eighteenByteRipe, nonceTrialsPerByte,
|
"", eighteenByteRipe, nonceTrialsPerByte,
|
||||||
payloadLengthExtraBytes))
|
payloadLengthExtraBytes))
|
||||||
self.ids.label.text = ''
|
self.ids.label.text = ''
|
||||||
self.parent.parent.children[1].opacity = 1
|
self.parent.parent.ids.toolbar.opacity = 1
|
||||||
self.parent.parent.children[1].disabled = False
|
self.parent.parent.ids.toolbar.disabled = False
|
||||||
state.kivyapp.root.ids.sc10.children[1].active = True
|
state.kivyapp.loadMyAddressScreen(True)
|
||||||
self.manager.current = 'myaddress'
|
self.manager.current = 'myaddress'
|
||||||
Clock.schedule_once(self.address_created_callback, 6)
|
Clock.schedule_once(self.address_created_callback, 6)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def address_created_callback(dt=0):
|
def address_created_callback(dt=0):
|
||||||
"""New address created"""
|
"""New address created"""
|
||||||
state.kivyapp.root.ids.sc10.children[1].active = False
|
state.kivyapp.loadMyAddressScreen(False)
|
||||||
state.kivyapp.root.ids.sc10.ids.ml.clear_widgets()
|
state.kivyapp.root.ids.sc10.ids.ml.clear_widgets()
|
||||||
state.kivyapp.root.ids.sc10.is_add_created = True
|
state.kivyapp.root.ids.sc10.is_add_created = True
|
||||||
state.kivyapp.root.ids.sc10.init_ui()
|
state.kivyapp.root.ids.sc10.init_ui()
|
||||||
|
@ -839,12 +960,13 @@ class Random(Screen):
|
||||||
|
|
||||||
class Sent(Screen):
|
class Sent(Screen):
|
||||||
"""Sent Screen uses screen to show widgets of screens"""
|
"""Sent Screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
queryreturn = ListProperty()
|
queryreturn = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
account = StringProperty()
|
account = StringProperty()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Association with the screen."""
|
"""Association with the screen"""
|
||||||
super(Sent, self).__init__(*args, **kwargs)
|
super(Sent, self).__init__(*args, **kwargs)
|
||||||
if state.association == '':
|
if state.association == '':
|
||||||
if BMConfigParser().addresses():
|
if BMConfigParser().addresses():
|
||||||
|
@ -854,10 +976,10 @@ class Sent(Screen):
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock Schdule for method sent accounts"""
|
"""Clock Schdule for method sent accounts"""
|
||||||
self.loadSent()
|
self.loadSent()
|
||||||
print dt
|
print(dt)
|
||||||
|
|
||||||
def loadSent(self, where="", what=""):
|
def loadSent(self, where="", what=""):
|
||||||
"""Load Sent list for Sent messages."""
|
"""Load Sent list for Sent messages"""
|
||||||
self.account = state.association
|
self.account = state.association
|
||||||
if state.searcing_text:
|
if state.searcing_text:
|
||||||
self.ids.scroll_y.scroll_y = 1.0
|
self.ids.scroll_y.scroll_y = 1.0
|
||||||
|
@ -876,24 +998,33 @@ class Sent(Screen):
|
||||||
'secondary_text': mail[2][:50] + '........' if len(
|
'secondary_text': mail[2][:50] + '........' if len(
|
||||||
mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace(
|
mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
'ackdata': mail[5]})
|
'ackdata': mail[5], 'senttime': mail[6]},)
|
||||||
self.set_mdlist(data, 0)
|
self.set_mdlist(data, 0)
|
||||||
self.has_refreshed = True
|
self.has_refreshed = True
|
||||||
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
|
self.set_sentCount('0')
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="No message found!" if state.searcing_text
|
text="No message found!" if state.searcing_text
|
||||||
else "yet no message for this account!!!!!!!!!!!!!",
|
else "yet no message for this account!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments
|
|
||||||
def sentDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
def sentDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
||||||
"""This method is used to retrieving data from sent table"""
|
"""This method is used to retrieving data from sent table"""
|
||||||
self.queryreturn = kivy_helper_search.search_sql(
|
self.queryreturn = kivy_helper_search.search_sql(
|
||||||
xAddress, self.account, "sent", where, what,
|
xAddress,
|
||||||
False, start_indx, end_indx)
|
self.account,
|
||||||
|
'sent',
|
||||||
|
where,
|
||||||
|
what,
|
||||||
|
False,
|
||||||
|
start_indx,
|
||||||
|
end_indx)
|
||||||
|
|
||||||
def set_mdlist(self, data, set_index=0):
|
def set_mdlist(self, data, set_index=0):
|
||||||
"""This method is used to create the mdList"""
|
"""This method is used to create the mdList"""
|
||||||
|
@ -902,11 +1033,13 @@ class Sent(Screen):
|
||||||
meny = TwoLineAvatarIconListItem(
|
meny = TwoLineAvatarIconListItem(
|
||||||
text=item['text'], secondary_text=item['secondary_text'],
|
text=item['text'], secondary_text=item['secondary_text'],
|
||||||
theme_text_color='Custom',
|
theme_text_color='Custom',
|
||||||
text_color=NavigateApp().theme_cls.primary_color)
|
text_color=NavigateApp().theme_cls.primary_color
|
||||||
|
)
|
||||||
meny.add_widget(AvatarSampleWidget(
|
meny.add_widget(AvatarSampleWidget(
|
||||||
source='./images/text_images/{}.png'.format(
|
source='./images/text_images/{}.png'.format(
|
||||||
avatarImageFirstLetter(item['secondary_text'].strip()))))
|
avatarImageFirstLetter(item['secondary_text'].strip()))))
|
||||||
meny.bind(on_press=partial(self.sent_detail, item['ackdata']))
|
meny.bind(on_press=partial(self.sent_detail, item['ackdata']))
|
||||||
|
meny.add_widget(AddTimeWidget(item['senttime']))
|
||||||
carousel = Carousel(direction='right')
|
carousel = Carousel(direction='right')
|
||||||
carousel.height = meny.height
|
carousel.height = meny.height
|
||||||
carousel.size_hint_y = None
|
carousel.size_hint_y = None
|
||||||
|
@ -919,10 +1052,10 @@ class Sent(Screen):
|
||||||
del_btn.bind(on_press=partial(self.delete, item['ackdata']))
|
del_btn.bind(on_press=partial(self.delete, item['ackdata']))
|
||||||
carousel.add_widget(del_btn)
|
carousel.add_widget(del_btn)
|
||||||
carousel.add_widget(meny)
|
carousel.add_widget(meny)
|
||||||
ach_btn = Button(text='Achieve')
|
# ach_btn = Button(text='Achieve')
|
||||||
ach_btn.background_color = (0, 1, 0, 1)
|
# ach_btn.background_color = (0, 1, 0, 1)
|
||||||
ach_btn.bind(on_press=partial(self.archive, item['ackdata']))
|
# ach_btn.bind(on_press=partial(self.archive, item['ackdata']))
|
||||||
carousel.add_widget(ach_btn)
|
# carousel.add_widget(ach_btn)
|
||||||
carousel.index = 1
|
carousel.index = 1
|
||||||
self.ids.ml.add_widget(carousel, index=set_index)
|
self.ids.ml.add_widget(carousel, index=set_index)
|
||||||
updated_msgs = len(self.ids.ml.children)
|
updated_msgs = len(self.ids.ml.children)
|
||||||
|
@ -947,7 +1080,7 @@ class Sent(Screen):
|
||||||
'secondary_text': mail[2][:50] + '........' if len(
|
'secondary_text': mail[2][:50] + '........' if len(
|
||||||
mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace(
|
mail[2]) >= 50 else (mail[2] + ',' + mail[3].replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
'ackdata': mail[5]})
|
'ackdata': mail[5], 'senttime': mail[6]})
|
||||||
self.set_mdlist(data, total_sent - 1)
|
self.set_mdlist(data, total_sent - 1)
|
||||||
if state.msg_counter_objs and state.association == (
|
if state.msg_counter_objs and state.association == (
|
||||||
state.check_sent_acc):
|
state.check_sent_acc):
|
||||||
|
@ -983,9 +1116,12 @@ class Sent(Screen):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_sentCount(total_sent):
|
def set_sentCount(total_sent):
|
||||||
"""Set the total no. of sent message count"""
|
"""Set the total no. of sent message count"""
|
||||||
src_mng_obj = state.kivyapp.root.children[2].children[0].ids
|
src_mng_obj = state.kivyapp.root.ids.content_drawer.ids.send_cnt
|
||||||
src_mng_obj.send_cnt.badge_text = str(total_sent)
|
if state.association:
|
||||||
state.sent_count = str(total_sent)
|
src_mng_obj.children[0].children[0].text = showLimitedCnt(int(total_sent))
|
||||||
|
state.kivyapp.get_sent_count()
|
||||||
|
else:
|
||||||
|
src_mng_obj.children[0].children[0].text = '0'
|
||||||
|
|
||||||
def sent_detail(self, ackdata, *args):
|
def sent_detail(self, ackdata, *args):
|
||||||
"""Load sent mail details"""
|
"""Load sent mail details"""
|
||||||
|
@ -1001,19 +1137,11 @@ class Sent(Screen):
|
||||||
|
|
||||||
def delete(self, data_index, instance, *args):
|
def delete(self, data_index, instance, *args):
|
||||||
"""Delete sent mail from sent mail listing"""
|
"""Delete sent mail from sent mail listing"""
|
||||||
try:
|
msg_count_objs = self.parent.parent.ids.content_drawer.ids
|
||||||
msg_count_objs = self.parent.parent.parent.parent.children[
|
|
||||||
2].children[0].ids
|
|
||||||
except Exception:
|
|
||||||
msg_count_objs = self.parent.parent.parent.parent.parent.children[
|
|
||||||
2].children[0].ids
|
|
||||||
if int(state.sent_count) > 0:
|
if int(state.sent_count) > 0:
|
||||||
msg_count_objs.send_cnt.badge_text = str(
|
msg_count_objs.send_cnt.children[0].children[0].text = showLimitedCnt(int(state.sent_count) - 1)
|
||||||
int(state.sent_count) - 1)
|
msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt(int(state.trash_count) + 1)
|
||||||
msg_count_objs.trash_cnt.badge_text = str(
|
msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt(int(state.all_count) - 1)
|
||||||
int(state.trash_count) + 1)
|
|
||||||
msg_count_objs.allmail_cnt.badge_text = str(
|
|
||||||
int(state.all_count) - 1)
|
|
||||||
state.sent_count = str(int(state.sent_count) - 1)
|
state.sent_count = str(int(state.sent_count) - 1)
|
||||||
state.trash_count = str(int(state.trash_count) + 1)
|
state.trash_count = str(int(state.trash_count) + 1)
|
||||||
state.all_count = str(int(state.all_count) - 1)
|
state.all_count = str(int(state.all_count) - 1)
|
||||||
|
@ -1021,7 +1149,7 @@ class Sent(Screen):
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE sent SET folder = 'trash'"
|
"UPDATE sent SET folder = 'trash'"
|
||||||
" WHERE ackdata = ?;", str(data_index))
|
" WHERE ackdata = ?;", data_index)
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
toast('Deleted')
|
toast('Deleted')
|
||||||
self.update_trash()
|
self.update_trash()
|
||||||
|
@ -1029,8 +1157,8 @@ class Sent(Screen):
|
||||||
def archive(self, data_index, instance, *args):
|
def archive(self, data_index, instance, *args):
|
||||||
"""Archive sent mail from sent mail listing"""
|
"""Archive sent mail from sent mail listing"""
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE sent SET folder = 'trash' WHERE ackdata = ?;",
|
"UPDATE sent SET folder = 'trash'"
|
||||||
str(data_index))
|
" WHERE ackdata = ?;", data_index)
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
self.update_trash()
|
self.update_trash()
|
||||||
|
|
||||||
|
@ -1050,9 +1178,10 @@ class Sent(Screen):
|
||||||
|
|
||||||
class Trash(Screen):
|
class Trash(Screen):
|
||||||
"""Trash Screen uses screen to show widgets of screens"""
|
"""Trash Screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
trash_messages = ListProperty()
|
trash_messages = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
delete_index = StringProperty()
|
# delete_index = StringProperty()
|
||||||
table_name = StringProperty()
|
table_name = StringProperty()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1061,7 +1190,7 @@ class Trash(Screen):
|
||||||
Clock.schedule_once(self.init_ui, 0)
|
Clock.schedule_once(self.init_ui, 0)
|
||||||
|
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock Schdule for method trash screen."""
|
"""Clock Schdule for method trash screen"""
|
||||||
if state.association == '':
|
if state.association == '':
|
||||||
if BMConfigParser().addresses():
|
if BMConfigParser().addresses():
|
||||||
state.association = BMConfigParser().addresses()[0]
|
state.association = BMConfigParser().addresses()[0]
|
||||||
|
@ -1069,15 +1198,20 @@ class Trash(Screen):
|
||||||
self.trashDataQuery(0, 20)
|
self.trashDataQuery(0, 20)
|
||||||
if self.trash_messages:
|
if self.trash_messages:
|
||||||
self.ids.identi_tag.children[0].text = 'Trash'
|
self.ids.identi_tag.children[0].text = 'Trash'
|
||||||
src_mng_obj = state.kivyapp.root.children[2].children[0].ids
|
# src_mng_obj = state.kivyapp.root.children[2].children[0].ids
|
||||||
src_mng_obj.trash_cnt.badge_text = state.trash_count
|
# src_mng_obj.trash_cnt.badge_text = state.trash_count
|
||||||
|
self.set_TrashCnt(state.trash_count)
|
||||||
self.set_mdList()
|
self.set_mdList()
|
||||||
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
|
self.set_TrashCnt('0')
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="yet no trashed message for this account!!!!!!!!!!!!!",
|
text="yet no trashed message for this account!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
def trashDataQuery(self, start_indx, end_indx):
|
def trashDataQuery(self, start_indx, end_indx):
|
||||||
|
@ -1085,30 +1219,37 @@ class Trash(Screen):
|
||||||
self.trash_messages = sqlQuery(
|
self.trash_messages = sqlQuery(
|
||||||
"SELECT toaddress, fromaddress, subject, message,"
|
"SELECT toaddress, fromaddress, subject, message,"
|
||||||
" folder ||',' || 'sent' as folder, ackdata As"
|
" folder ||',' || 'sent' as folder, ackdata As"
|
||||||
" id, DATE(lastactiontime) As actionTime FROM sent"
|
" id, DATE(senttime) As actionTime, senttime as msgtime FROM sent"
|
||||||
" WHERE folder = 'trash' and fromaddress = '{0}' UNION"
|
" WHERE folder = 'trash' and fromaddress = '{0}' UNION"
|
||||||
" SELECT toaddress, fromaddress, subject, message,"
|
" SELECT toaddress, fromaddress, subject, message,"
|
||||||
" folder ||',' || 'inbox' as folder, msgid As id,"
|
" folder ||',' || 'inbox' as folder, msgid As id,"
|
||||||
" DATE(received) As actionTime FROM inbox"
|
" DATE(received) As actionTime, received as msgtime FROM inbox"
|
||||||
" WHERE folder = 'trash' and toaddress = '{0}'"
|
" WHERE folder = 'trash' and toaddress = '{0}'"
|
||||||
" ORDER BY actionTime DESC limit {1}, {2}".format(
|
" ORDER BY actionTime DESC limit {1}, {2}".format(
|
||||||
state.association, start_indx, end_indx))
|
state.association, start_indx, end_indx))
|
||||||
|
|
||||||
|
def set_TrashCnt(self, Count): # pylint: disable=no-self-use
|
||||||
|
"""This method is used to set trash message count"""
|
||||||
|
trashCnt_obj = state.kivyapp.root.ids.content_drawer.ids.trash_cnt
|
||||||
|
trashCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count))
|
||||||
|
|
||||||
def set_mdList(self):
|
def set_mdList(self):
|
||||||
"""This method is used to create the mdlist"""
|
"""This method is used to create the mdlist"""
|
||||||
total_trash_msg = len(self.ids.ml.children)
|
total_trash_msg = len(self.ids.ml.children)
|
||||||
for item in self.trash_messages:
|
for item in self.trash_messages:
|
||||||
|
subject = item[2].decode() if isinstance(item[2],bytes) else item[2]
|
||||||
|
body = item[3].decode() if isinstance(item[3],bytes) else item[3]
|
||||||
meny = TwoLineAvatarIconListItem(
|
meny = TwoLineAvatarIconListItem(
|
||||||
text=item[1],
|
text=item[1],
|
||||||
secondary_text=item[2][:50] + '........' if len(
|
secondary_text=item[2][:50] + '........' if len(
|
||||||
item[2]) >= 50 else (item[2] + ',' + item[3].replace(
|
subject) >= 50 else (subject + ',' + body.replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
theme_text_color='Custom',
|
theme_text_color='Custom',
|
||||||
text_color=NavigateApp().theme_cls.primary_color)
|
text_color=NavigateApp().theme_cls.primary_color)
|
||||||
img_latter = './images/text_images/{}.png'.format(
|
img_latter = './images/text_images/{}.png'.format(
|
||||||
item[2][0].upper() if (item[2][0].upper() >= 'A' and item[
|
subject[0].upper() if (subject[0].upper() >= 'A' and subject[0].upper() <= 'Z') else '!')
|
||||||
2][0].upper() <= 'Z') else '!')
|
|
||||||
meny.add_widget(AvatarSampleWidget(source=img_latter))
|
meny.add_widget(AvatarSampleWidget(source=img_latter))
|
||||||
|
meny.add_widget(AddTimeWidget(item[7]))
|
||||||
carousel = Carousel(direction='right')
|
carousel = Carousel(direction='right')
|
||||||
carousel.height = meny.height
|
carousel.height = meny.height
|
||||||
carousel.size_hint_y = None
|
carousel.size_hint_y = None
|
||||||
|
@ -1159,13 +1300,15 @@ class Trash(Screen):
|
||||||
width = .8 if platform == 'android' else .55
|
width = .8 if platform == 'android' else .55
|
||||||
delete_msg_dialog = MDDialog(
|
delete_msg_dialog = MDDialog(
|
||||||
text='Are you sure you want to delete this'
|
text='Are you sure you want to delete this'
|
||||||
' message permanently from trash?', title='',
|
' message permanently from trash?',
|
||||||
size_hint=(width, .25), text_button_ok='Yes',
|
title='',
|
||||||
|
size_hint=(width, .25),
|
||||||
|
text_button_ok='Yes',
|
||||||
text_button_cancel='No',
|
text_button_cancel='No',
|
||||||
events_callback=self.callback_for_delete_msg)
|
events_callback=self.callback_for_delete_msg)
|
||||||
delete_msg_dialog.open()
|
delete_msg_dialog.open()
|
||||||
|
|
||||||
def callback_for_delete_msg(self, text_item):
|
def callback_for_delete_msg(self, text_item, *arg):
|
||||||
"""Getting the callback of alert box"""
|
"""Getting the callback of alert box"""
|
||||||
if text_item == 'Yes':
|
if text_item == 'Yes':
|
||||||
self.delete_message_from_trash()
|
self.delete_message_from_trash()
|
||||||
|
@ -1177,22 +1320,21 @@ class Trash(Screen):
|
||||||
self.children[1].active = True
|
self.children[1].active = True
|
||||||
if self.table_name == 'inbox':
|
if self.table_name == 'inbox':
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"DELETE FROM inbox WHERE msgid = ?;",
|
"DELETE FROM inbox WHERE msgid = ?;", self.delete_index)
|
||||||
str(self.delete_index))
|
|
||||||
elif self.table_name == 'sent':
|
elif self.table_name == 'sent':
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"DELETE FROM sent WHERE ackdata = ?;",
|
"DELETE FROM sent WHERE ackdata = ?;", self.delete_index)
|
||||||
str(self.delete_index))
|
|
||||||
msg_count_objs = state.kivyapp.root.children[2].children[0].ids
|
|
||||||
if int(state.trash_count) > 0:
|
if int(state.trash_count) > 0:
|
||||||
msg_count_objs.trash_cnt.badge_text = str(
|
# msg_count_objs.trash_cnt.badge_text = str(
|
||||||
int(state.trash_count) - 1)
|
# int(state.trash_count) - 1)
|
||||||
|
self.set_TrashCnt(int(state.trash_count) - 1)
|
||||||
state.trash_count = str(int(state.trash_count) - 1)
|
state.trash_count = str(int(state.trash_count) - 1)
|
||||||
Clock.schedule_once(self.callback_for_screen_load, 1)
|
Clock.schedule_once(self.callback_for_screen_load, 1)
|
||||||
|
|
||||||
|
|
||||||
class Page(Screen):
|
class Page(Screen):
|
||||||
"""Page Screen show widgets of page"""
|
"""Page Screen show widgets of page"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -1212,15 +1354,19 @@ class Create(Screen):
|
||||||
|
|
||||||
class Setting(Screen):
|
class Setting(Screen):
|
||||||
"""Setting the Screen components"""
|
"""Setting the Screen components"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NavigateApp(App): # pylint: disable=too-many-public-methods
|
class NavigateApp(MDApp):
|
||||||
"""Navigation Layout of class"""
|
"""Navigation Layout of class"""
|
||||||
theme_cls = ThemeManager()
|
# pylint: disable=too-many-public-methods,inconsistent-return-statements
|
||||||
|
|
||||||
|
# theme_cls = ThemeManager()
|
||||||
previous_date = ObjectProperty()
|
previous_date = ObjectProperty()
|
||||||
obj_1 = ObjectProperty()
|
obj_1 = ObjectProperty()
|
||||||
variable_1 = ListProperty(BMConfigParser().addresses())
|
variable_1 = ListProperty(addr for addr in BMConfigParser().addresses()
|
||||||
|
if BMConfigParser().get(str(addr), 'enabled') == 'true')
|
||||||
nav_drawer = ObjectProperty()
|
nav_drawer = ObjectProperty()
|
||||||
state.screen_density = Window.size
|
state.screen_density = Window.size
|
||||||
window_size = state.screen_density
|
window_size = state.screen_density
|
||||||
|
@ -1228,34 +1374,24 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
title = "PyBitmessage"
|
title = "PyBitmessage"
|
||||||
imgstatus = False
|
imgstatus = False
|
||||||
count = 0
|
count = 0
|
||||||
menu_items = [
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
{'viewclass': 'MDMenuItem', 'text': 'Example item'},
|
|
||||||
]
|
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
"""Method builds the widget"""
|
"""Method builds the widget"""
|
||||||
main_widget = Builder.load_file(
|
for kv_file in KVFILES:
|
||||||
os.path.join(os.path.dirname(__file__), 'main.kv'))
|
Builder.load_file(os.path.join(os.path.dirname(__file__), "kv/{}.kv").format(kv_file))
|
||||||
self.nav_drawer = Navigatorss()
|
|
||||||
self.obj_1 = AddressBook()
|
self.obj_1 = AddressBook()
|
||||||
kivysignalthread = UIkivySignaler()
|
kivysignalthread = UIkivySignaler()
|
||||||
kivysignalthread.daemon = True
|
kivysignalthread.daemon = True
|
||||||
kivysignalthread.start()
|
kivysignalthread.start()
|
||||||
Window.bind(on_keyboard=self.on_key)
|
Window.bind(on_keyboard=self.on_key, on_request_close=self.on_request_close)
|
||||||
return main_widget
|
return Builder.load_file(
|
||||||
|
os.path.join(os.path.dirname(__file__), 'main.kv'))
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Running the widgets"""
|
"""Running the widgets"""
|
||||||
kivyuisignaler.release()
|
kivyuisignaler.release()
|
||||||
super(NavigateApp, self).run()
|
super(NavigateApp, self).run()
|
||||||
|
|
||||||
# pylint: disable=inconsistent-return-statements
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def showmeaddresses(name="text"):
|
def showmeaddresses(name="text"):
|
||||||
"""Show the addresses in spinner to make as dropdown"""
|
"""Show the addresses in spinner to make as dropdown"""
|
||||||
|
@ -1279,10 +1415,13 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
state.searcing_text = ''
|
state.searcing_text = ''
|
||||||
LoadingPopup().open()
|
LoadingPopup().open()
|
||||||
self.set_message_count()
|
self.set_message_count()
|
||||||
|
for nav_obj in self.root.ids.content_drawer.children[
|
||||||
|
0].children[0].children[0].children:
|
||||||
|
nav_obj.active = True if nav_obj.text == 'Inbox' else False
|
||||||
Clock.schedule_once(self.setCurrentAccountData, 0.5)
|
Clock.schedule_once(self.setCurrentAccountData, 0.5)
|
||||||
|
|
||||||
def setCurrentAccountData(self, dt=0):
|
def setCurrentAccountData(self, dt=0):
|
||||||
"""This method set the current accout data on all the screens."""
|
"""This method set the current accout data on all the screens"""
|
||||||
self.root.ids.sc1.ids.ml.clear_widgets()
|
self.root.ids.sc1.ids.ml.clear_widgets()
|
||||||
self.root.ids.sc1.loadMessagelist(state.association)
|
self.root.ids.sc1.loadMessagelist(state.association)
|
||||||
|
|
||||||
|
@ -1299,6 +1438,9 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
self.root.ids.sc17.clear_widgets()
|
self.root.ids.sc17.clear_widgets()
|
||||||
self.root.ids.sc17.add_widget(Allmails())
|
self.root.ids.sc17.add_widget(Allmails())
|
||||||
|
|
||||||
|
self.root.ids.sc10.ids.ml.clear_widgets()
|
||||||
|
self.root.ids.sc10.init_ui()
|
||||||
|
|
||||||
self.root.ids.scr_mngr.current = 'inbox'
|
self.root.ids.scr_mngr.current = 'inbox'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -1339,7 +1481,7 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
if not os.path.exists(directory):
|
if not os.path.exists(directory):
|
||||||
os.makedirs(directory)
|
os.makedirs(directory)
|
||||||
except OSError:
|
except OSError:
|
||||||
print 'Error: Creating directory. ' + directory
|
print('Error: Creating directory. ' + directory)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_image():
|
def get_default_image():
|
||||||
|
@ -1349,6 +1491,14 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
BMConfigParser().addresses()[0])
|
BMConfigParser().addresses()[0])
|
||||||
return './images/no_identicons.png'
|
return './images/no_identicons.png'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_default_logo():
|
||||||
|
"""Getting default logo image"""
|
||||||
|
if BMConfigParser().addresses():
|
||||||
|
return './images/default_identicon/{}.png'.format(
|
||||||
|
BMConfigParser().addresses()[0])
|
||||||
|
return './images/drawer_logo1.png'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def addressexist():
|
def addressexist():
|
||||||
"""Checking address existence"""
|
"""Checking address existence"""
|
||||||
|
@ -1357,6 +1507,7 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def on_key(self, window, key, *args):
|
def on_key(self, window, key, *args):
|
||||||
|
# pylint: disable=inconsistent-return-statements
|
||||||
"""Method is used for going on previous screen"""
|
"""Method is used for going on previous screen"""
|
||||||
if key == 27:
|
if key == 27:
|
||||||
if state.in_search_mode and self.root.ids.scr_mngr.current != (
|
if state.in_search_mode and self.root.ids.scr_mngr.current != (
|
||||||
|
@ -1390,7 +1541,7 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
self.root.ids.sc11.children[1].active = True
|
self.root.ids.sc11.children[1].active = True
|
||||||
Clock.schedule_once(self.search_callback, 0.5)
|
Clock.schedule_once(self.search_callback, 0.5)
|
||||||
elif state.search_screen == 'myaddress':
|
elif state.search_screen == 'myaddress':
|
||||||
self.root.ids.sc10.children[1].active = True
|
self.loadMyAddressScreen(True)
|
||||||
Clock.schedule_once(self.search_callback, 0.5)
|
Clock.schedule_once(self.search_callback, 0.5)
|
||||||
elif state.search_screen == 'sent':
|
elif state.search_screen == 'sent':
|
||||||
self.root.ids.sc4.children[1].active = True
|
self.root.ids.sc4.children[1].active = True
|
||||||
|
@ -1409,13 +1560,20 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
elif state.search_screen == 'myaddress':
|
elif state.search_screen == 'myaddress':
|
||||||
self.root.ids.sc10.ids.ml.clear_widgets()
|
self.root.ids.sc10.ids.ml.clear_widgets()
|
||||||
self.root.ids.sc10.init_ui()
|
self.root.ids.sc10.init_ui()
|
||||||
self.root.ids.sc10.children[1].active = False
|
self.loadMyAddressScreen(False)
|
||||||
else:
|
else:
|
||||||
self.root.ids.sc4.ids.ml.clear_widgets()
|
self.root.ids.sc4.ids.ml.clear_widgets()
|
||||||
self.root.ids.sc4.loadSent(state.association)
|
self.root.ids.sc4.loadSent(state.association)
|
||||||
self.root.ids.sc4.children[1].active = False
|
self.root.ids.sc4.children[1].active = False
|
||||||
self.root.ids.scr_mngr.current = state.search_screen
|
self.root.ids.scr_mngr.current = state.search_screen
|
||||||
|
|
||||||
|
def loadMyAddressScreen(self, action):
|
||||||
|
"""loadMyAddressScreen method spin the loader"""
|
||||||
|
if len(self.root.ids.sc10.children) <= 2:
|
||||||
|
self.root.ids.sc10.children[0].active = action
|
||||||
|
else:
|
||||||
|
self.root.ids.sc10.children[1].active = action
|
||||||
|
|
||||||
def save_draft(self):
|
def save_draft(self):
|
||||||
"""Saving drafts messages"""
|
"""Saving drafts messages"""
|
||||||
composer_objs = self.root
|
composer_objs = self.root
|
||||||
|
@ -1460,12 +1618,20 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
['send',
|
['send',
|
||||||
lambda x: self.root.ids.sc3.children[1].send(self)]]
|
lambda x: self.root.ids.sc3.children[1].send(self)]]
|
||||||
|
|
||||||
|
def set_toolbar_for_QrCode(self):
|
||||||
|
"""This method is use for setting Qr code toolbar."""
|
||||||
|
self.root.ids.toolbar.left_action_items = [
|
||||||
|
['arrow-left', lambda x: self.back_press()]]
|
||||||
|
self.root.ids.toolbar.right_action_items = []
|
||||||
|
|
||||||
def set_common_header(self):
|
def set_common_header(self):
|
||||||
"""Common header for all window"""
|
"""Common header for all window"""
|
||||||
self.root.ids.toolbar.right_action_items = [
|
self.root.ids.toolbar.right_action_items = [
|
||||||
['account-plus', lambda x: self.addingtoaddressbook()]]
|
['account-plus', lambda x: self.addingtoaddressbook()]]
|
||||||
|
# self.root.ids.toolbar.left_action_items = [
|
||||||
|
# ['menu', lambda x: self.root.toggle_nav_drawer()]]
|
||||||
self.root.ids.toolbar.left_action_items = [
|
self.root.ids.toolbar.left_action_items = [
|
||||||
['menu', lambda x: self.root.toggle_nav_drawer()]]
|
['menu', lambda x: self.root.ids.nav_drawer.set_state("toggle")]]
|
||||||
return
|
return
|
||||||
|
|
||||||
def back_press(self):
|
def back_press(self):
|
||||||
|
@ -1483,7 +1649,8 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
self.root.ids.scr_mngr.current = 'inbox' \
|
self.root.ids.scr_mngr.current = 'inbox' \
|
||||||
if state.in_composer else 'allmails'\
|
if state.in_composer else 'allmails'\
|
||||||
if state.is_allmail else state.detailPageType\
|
if state.is_allmail else state.detailPageType\
|
||||||
if state.detailPageType else 'inbox'
|
if state.detailPageType else 'myaddress'\
|
||||||
|
if self.root.ids.scr_mngr.current == 'showqrcode' else 'inbox'
|
||||||
self.root.ids.scr_mngr.transition.direction = 'right'
|
self.root.ids.scr_mngr.transition.direction = 'right'
|
||||||
self.root.ids.scr_mngr.transition.bind(on_complete=self.reset)
|
self.root.ids.scr_mngr.transition.bind(on_complete=self.reset)
|
||||||
if state.is_allmail or state.detailPageType == 'draft':
|
if state.is_allmail or state.detailPageType == 'draft':
|
||||||
|
@ -1532,15 +1699,15 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
msg_counter_objs.allmail_cnt.badge_text = state.all_count
|
msg_counter_objs.allmail_cnt.badge_text = state.all_count
|
||||||
|
|
||||||
def on_start(self):
|
def on_start(self):
|
||||||
"""Method activates on start"""
|
"""Setting message count"""
|
||||||
self.set_message_count()
|
self.set_message_count()
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def on_stop():
|
# def on_stop():
|
||||||
"""On stop methos is used for stoping the runing script"""
|
# """On stop methos is used for stoping the runing script"""
|
||||||
print "*******************EXITING FROM APPLICATION*******************"
|
# print("*******************EXITING FROM APPLICATION*******************")
|
||||||
import shutdown
|
# import shutdown
|
||||||
shutdown.doCleanShutdown()
|
# shutdown.doCleanShutdown()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def current_address_label(current_add_label=None, current_addr=None):
|
def current_address_label(current_add_label=None, current_addr=None):
|
||||||
|
@ -1555,7 +1722,7 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
f_name = first_name.split()
|
f_name = first_name.split()
|
||||||
label = f_name[0][:14].capitalize() + '...' if len(
|
label = f_name[0][:14].capitalize() + '...' if len(
|
||||||
f_name[0]) > 15 else f_name[0].capitalize()
|
f_name[0]) > 15 else f_name[0].capitalize()
|
||||||
address = ' (' + addr + '...)'
|
address = ' (' + addr + ')'
|
||||||
return label + address
|
return label + address
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -1583,8 +1750,9 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
self.refreshScreen()
|
self.refreshScreen()
|
||||||
state.in_search_mode = False
|
state.in_search_mode = False
|
||||||
|
|
||||||
def refreshScreen(self): # pylint: disable=unused-variable
|
def refreshScreen(self):
|
||||||
"""Method show search button only on inbox or sent screen"""
|
"""Method show search button only on inbox or sent screen"""
|
||||||
|
# pylint: disable=unused-variable
|
||||||
state.searcing_text = ''
|
state.searcing_text = ''
|
||||||
if state.search_screen == 'inbox':
|
if state.search_screen == 'inbox':
|
||||||
try:
|
try:
|
||||||
|
@ -1604,11 +1772,11 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
elif state.search_screen == 'myaddress':
|
elif state.search_screen == 'myaddress':
|
||||||
try:
|
try:
|
||||||
self.root.ids.sc10.children[
|
self.root.ids.sc10.children[
|
||||||
3].children[2].ids.search_field.text = ''
|
1].children[2].ids.search_field.text = ''
|
||||||
except Exception:
|
except Exception:
|
||||||
self.root.ids.sc10.children[
|
self.root.ids.sc10.children[
|
||||||
2].children[2].ids.search_field.text = ''
|
2].children[2].ids.search_field.text = ''
|
||||||
self.root.ids.sc10.children[1].active = True
|
self.loadMyAddressScreen(True)
|
||||||
Clock.schedule_once(self.search_callback, 0.5)
|
Clock.schedule_once(self.search_callback, 0.5)
|
||||||
else:
|
else:
|
||||||
self.root.ids.sc4.children[
|
self.root.ids.sc4.children[
|
||||||
|
@ -1620,8 +1788,9 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
def set_identicon(self, text):
|
def set_identicon(self, text):
|
||||||
"""Show identicon in address spinner"""
|
"""Show identicon in address spinner"""
|
||||||
img = identiconGeneration.generate(text)
|
img = identiconGeneration.generate(text)
|
||||||
self.root.children[2].children[0].ids.btn.children[1].texture = (
|
self.root.children[0].children[0].ids.btn.children[1].texture = (img.texture)
|
||||||
img.texture)
|
# below line is for displaing logo
|
||||||
|
self.root.ids.content_drawer.ids.top_box.children[0].texture = (img.texture)
|
||||||
|
|
||||||
def set_mail_detail_header(self):
|
def set_mail_detail_header(self):
|
||||||
"""Setting the details of the page"""
|
"""Setting the details of the page"""
|
||||||
|
@ -1663,23 +1832,31 @@ class NavigateApp(App): # pylint: disable=too-many-public-methods
|
||||||
self.root.ids.sc1.loadMessagelist(state.association)
|
self.root.ids.sc1.loadMessagelist(state.association)
|
||||||
self.root.ids.sc1.children[1].active = False
|
self.root.ids.sc1.children[1].active = False
|
||||||
elif instance.text == 'All Mails':
|
elif instance.text == 'All Mails':
|
||||||
if len(self.root.ids.sc17.ids.ml.children) <= 2:
|
# if len(self.root.ids.sc17.ids.ml.children) <= 2:
|
||||||
|
# self.root.ids.sc17.clear_widgets()
|
||||||
|
# self.root.ids.sc17.add_widget(Allmails())
|
||||||
|
# else:
|
||||||
|
# self.root.ids.sc17.ids.ml.clear_widgets()
|
||||||
|
# self.root.ids.sc17.loadMessagelist()
|
||||||
self.root.ids.sc17.clear_widgets()
|
self.root.ids.sc17.clear_widgets()
|
||||||
self.root.ids.sc17.add_widget(Allmails())
|
self.root.ids.sc17.add_widget(Allmails())
|
||||||
else:
|
|
||||||
self.root.ids.sc17.ids.ml.clear_widgets()
|
|
||||||
self.root.ids.sc17.loadMessagelist()
|
|
||||||
try:
|
try:
|
||||||
self.root.ids.sc17.children[1].active = False
|
self.root.ids.sc17.children[1].active = False
|
||||||
except Exception:
|
except Exception:
|
||||||
self.root.ids.sc17.children[0].children[1].active = False
|
self.root.ids.sc17.children[0].children[1].active = False
|
||||||
|
|
||||||
|
def on_request_close(self, *args): # pylint: disable=no-self-use
|
||||||
|
"""This method is for app closing request"""
|
||||||
|
AppClosingPopup().open()
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class GrashofPopup(Popup):
|
class GrashofPopup(Popup):
|
||||||
"""Moule for save contacts and error messages"""
|
"""Moule for save contacts and error messages"""
|
||||||
|
|
||||||
valid = False
|
valid = False
|
||||||
|
|
||||||
def __init__(self, **kwargs): # pylint: disable=useless-super-delegation
|
def __init__(self, **kwargs):
|
||||||
"""Grash of pop screen settings"""
|
"""Grash of pop screen settings"""
|
||||||
super(GrashofPopup, self).__init__(**kwargs)
|
super(GrashofPopup, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
@ -1717,8 +1894,10 @@ class GrashofPopup(Popup):
|
||||||
|
|
||||||
def checkAddress_valid(self, instance):
|
def checkAddress_valid(self, instance):
|
||||||
"""Checking address is valid or not"""
|
"""Checking address is valid or not"""
|
||||||
|
# my_addresses = (
|
||||||
|
# self.parent.children[1].children[2].children[0].ids.btn.values)
|
||||||
my_addresses = (
|
my_addresses = (
|
||||||
self.parent.children[1].children[2].children[0].ids.btn.values)
|
self.parent.children[1].children[0].children[0].ids.btn.values)
|
||||||
add_book = [addr[1] for addr in kivy_helper_search.search_sql(
|
add_book = [addr[1] for addr in kivy_helper_search.search_sql(
|
||||||
folder="addressbook")]
|
folder="addressbook")]
|
||||||
entered_text = str(instance.text).strip()
|
entered_text = str(instance.text).strip()
|
||||||
|
@ -1769,10 +1948,13 @@ class GrashofPopup(Popup):
|
||||||
elif status == 'missingbm':
|
elif status == 'missingbm':
|
||||||
text = "The address should start with ''BM-''"
|
text = "The address should start with ''BM-''"
|
||||||
elif status == 'checksumfailed':
|
elif status == 'checksumfailed':
|
||||||
text = "The address is not typed or copied correctly(the checksum failed)."
|
text = (
|
||||||
|
"The address is not typed or copied correctly"
|
||||||
|
" (the checksum failed).")
|
||||||
elif status == 'versiontoohigh':
|
elif status == 'versiontoohigh':
|
||||||
text = "The version number of this address is higher"\
|
text = (
|
||||||
" than this software can support. Please upgrade Bitmessage."
|
"The version number of this address is higher than this"
|
||||||
|
" software can support. Please upgrade Bitmessage.")
|
||||||
elif status == 'invalidcharacters':
|
elif status == 'invalidcharacters':
|
||||||
text = "The address contains invalid characters."
|
text = "The address contains invalid characters."
|
||||||
elif status == 'ripetooshort':
|
elif status == 'ripetooshort':
|
||||||
|
@ -1786,52 +1968,38 @@ class GrashofPopup(Popup):
|
||||||
|
|
||||||
class AvatarSampleWidget(ILeftBody, Image):
|
class AvatarSampleWidget(ILeftBody, Image):
|
||||||
"""Avatar Sample Widget"""
|
"""Avatar Sample Widget"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IconLeftSampleWidget(ILeftBodyTouch, MDIconButton):
|
class IconLeftSampleWidget(ILeftBodyTouch, MDIconButton):
|
||||||
"""Left icon sample widget"""
|
"""Left icon sample widget"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IconRightSampleWidget(IRightBodyTouch, MDCheckbox):
|
class IconRightSampleWidget(IRightBodyTouch, MDCheckbox):
|
||||||
"""Right icon sample widget"""
|
"""Right icon sample widget"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NavigationDrawerTwoLineListItem(
|
class ToggleBtn(IRightBodyTouch, MDSwitch):
|
||||||
TwoLineListItem, NavigationDrawerHeaderBase):
|
"""Right toggle button widget"""
|
||||||
"""Navigation Drawer in Listitems"""
|
|
||||||
address_property = StringProperty()
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
"""Method for Navigation Drawer"""
|
|
||||||
super(NavigationDrawerTwoLineListItem, self).__init__(**kwargs)
|
|
||||||
Clock.schedule_once(lambda dt: self.setup())
|
|
||||||
|
|
||||||
def setup(self):
|
|
||||||
"""Bind Controller.current_account property"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_current_account(self, account):
|
|
||||||
"""Account detail"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _update_specific_text_color(self, instance, value):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _set_active(self, active, list_):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MailDetail(Screen):
|
class MailDetail(Screen):
|
||||||
"""MailDetail Screen uses to show the detail of mails"""
|
"""MailDetail Screen uses to show the detail of mails"""
|
||||||
|
|
||||||
to_addr = StringProperty()
|
to_addr = StringProperty()
|
||||||
from_addr = StringProperty()
|
from_addr = StringProperty()
|
||||||
subject = StringProperty()
|
subject = StringProperty()
|
||||||
message = StringProperty()
|
message = StringProperty()
|
||||||
status = StringProperty()
|
status = StringProperty()
|
||||||
page_type = StringProperty()
|
page_type = StringProperty()
|
||||||
|
time_tag = StringProperty()
|
||||||
|
avatarImg = StringProperty()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Mail Details method"""
|
"""Mail Details method"""
|
||||||
|
@ -1844,31 +2012,37 @@ class MailDetail(Screen):
|
||||||
if state.detailPageType == 'sent' or state.detailPageType == 'draft':
|
if state.detailPageType == 'sent' or state.detailPageType == 'draft':
|
||||||
data = sqlQuery(
|
data = sqlQuery(
|
||||||
"select toaddress, fromaddress, subject, message, status,"
|
"select toaddress, fromaddress, subject, message, status,"
|
||||||
" ackdata from sent where ackdata = ?;", state.mail_id)
|
" ackdata, senttime from sent where ackdata = ?;", state.mail_id)
|
||||||
state.status = self
|
state.status = self
|
||||||
state.ackdata = data[0][5]
|
state.ackdata = data[0][5]
|
||||||
self.assign_mail_details(data)
|
self.assign_mail_details(data)
|
||||||
state.kivyapp.set_mail_detail_header()
|
state.kivyapp.set_mail_detail_header()
|
||||||
elif state.detailPageType == 'inbox':
|
elif state.detailPageType == 'inbox':
|
||||||
data = sqlQuery(
|
data = sqlQuery(
|
||||||
"select toaddress, fromaddress, subject, message from inbox"
|
"select toaddress, fromaddress, subject, message, received from inbox"
|
||||||
" where msgid = ?;", str(state.mail_id))
|
" where msgid = ?;", state.mail_id)
|
||||||
self.assign_mail_details(data)
|
self.assign_mail_details(data)
|
||||||
state.kivyapp.set_mail_detail_header()
|
state.kivyapp.set_mail_detail_header()
|
||||||
|
|
||||||
def assign_mail_details(self, data):
|
def assign_mail_details(self, data):
|
||||||
"""Assigning mail details"""
|
"""Assigning mail details"""
|
||||||
|
subject = data[0][2].decode() if isinstance(data[0][2],bytes) else data[0][2]
|
||||||
|
body = data[0][3].decode() if isinstance(data[0][2],bytes) else data[0][3]
|
||||||
self.to_addr = data[0][0]
|
self.to_addr = data[0][0]
|
||||||
self.from_addr = data[0][1]
|
self.from_addr = data[0][1]
|
||||||
self.subject = data[0][2].upper(
|
|
||||||
) if data[0][2].upper() else '(no subject)'
|
self.subject = subject.upper(
|
||||||
self.message = data[0][3]
|
) if subject.upper() else '(no subject)'
|
||||||
if len(data[0]) == 6:
|
self.message = body
|
||||||
|
if len(data[0]) == 7:
|
||||||
self.status = data[0][4]
|
self.status = data[0][4]
|
||||||
|
self.time_tag = ShowTimeHistoy(data[0][4]) if state.detailPageType == 'inbox' else ShowTimeHistoy(data[0][6])
|
||||||
|
self.avatarImg = './images/text_images/{0}.png'.format(
|
||||||
|
'avatar.png' if state.detailPageType == 'draft' else avatarImageFirstLetter(self.subject.strip()))
|
||||||
|
|
||||||
def delete_mail(self):
|
def delete_mail(self):
|
||||||
"""Method for mail delete"""
|
"""Method for mail delete"""
|
||||||
msg_count_objs = state.kivyapp.root.children[2].children[0].ids
|
msg_count_objs = state.kivyapp.root.ids.content_drawer.ids
|
||||||
state.searcing_text = ''
|
state.searcing_text = ''
|
||||||
self.children[0].children[0].active = True
|
self.children[0].children[0].active = True
|
||||||
if state.detailPageType == 'sent':
|
if state.detailPageType == 'sent':
|
||||||
|
@ -1876,9 +2050,9 @@ class MailDetail(Screen):
|
||||||
2].children[2].ids.search_field.text = ''
|
2].children[2].ids.search_field.text = ''
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE sent SET folder = 'trash' WHERE"
|
"UPDATE sent SET folder = 'trash' WHERE"
|
||||||
" ackdata = ?;", str(state.mail_id))
|
" ackdata = ?;", state.mail_id)
|
||||||
msg_count_objs.send_cnt.badge_text = str(int(state.sent_count) - 1) if int(state.sent_count) else '0'
|
msg_count_objs.send_cnt.children[0].children[0].text = str(int(state.sent_count) - 1)
|
||||||
state.sent_count = str(int(state.sent_count) - 1) if int(state.sent_count) else '0'
|
state.sent_count = str(int(state.sent_count) - 1)
|
||||||
self.parent.screens[3].ids.ml.clear_widgets()
|
self.parent.screens[3].ids.ml.clear_widgets()
|
||||||
self.parent.screens[3].loadSent(state.association)
|
self.parent.screens[3].loadSent(state.association)
|
||||||
elif state.detailPageType == 'inbox':
|
elif state.detailPageType == 'inbox':
|
||||||
|
@ -1888,29 +2062,26 @@ class MailDetail(Screen):
|
||||||
2].ids.search_field.text = ''
|
2].ids.search_field.text = ''
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE inbox SET folder = 'trash' WHERE"
|
"UPDATE inbox SET folder = 'trash' WHERE"
|
||||||
" msgid = ?;", str(state.mail_id))
|
" msgid = ?;", state.mail_id)
|
||||||
msg_count_objs.inbox_cnt.badge_text = str(
|
msg_count_objs.inbox_cnt.children[0].children[0].text = str(
|
||||||
int(state.inbox_count) - 1) if int(state.inbox_count) else '0'
|
int(state.inbox_count) - 1)
|
||||||
state.inbox_count = str(int(state.inbox_count) - 1) if int(state.inbox_count) else '0'
|
state.inbox_count = str(int(state.inbox_count) - 1)
|
||||||
self.parent.screens[0].ids.ml.clear_widgets()
|
self.parent.screens[0].ids.ml.clear_widgets()
|
||||||
self.parent.screens[0].loadMessagelist(state.association)
|
self.parent.screens[0].loadMessagelist(state.association)
|
||||||
|
|
||||||
elif state.detailPageType == 'draft':
|
elif state.detailPageType == 'draft':
|
||||||
sqlExecute(
|
sqlExecute("DELETE FROM sent WHERE ackdata = ?;", state.mail_id)
|
||||||
"DELETE FROM sent WHERE ackdata = ?;", str(state.mail_id))
|
msg_count_objs.draft_cnt.children[0].children[0].text = str(
|
||||||
msg_count_objs.draft_cnt.badge_text = str(
|
|
||||||
int(state.draft_count) - 1)
|
int(state.draft_count) - 1)
|
||||||
state.draft_count = str(int(state.draft_count) - 1)
|
state.draft_count = str(int(state.draft_count) - 1)
|
||||||
self.parent.screens[15].clear_widgets()
|
self.parent.screens[15].clear_widgets()
|
||||||
self.parent.screens[15].add_widget(Draft())
|
self.parent.screens[15].add_widget(Draft())
|
||||||
|
|
||||||
# self.parent.current = 'allmails' \
|
|
||||||
# if state.is_allmail else state.detailPageType
|
|
||||||
if state.detailPageType != 'draft':
|
if state.detailPageType != 'draft':
|
||||||
msg_count_objs.trash_cnt.badge_text = str(
|
msg_count_objs.trash_cnt.children[0].children[0].text = str(
|
||||||
int(state.trash_count) + 1)
|
int(state.trash_count) + 1)
|
||||||
msg_count_objs.allmail_cnt.badge_text = str(
|
msg_count_objs.allmail_cnt.children[0].children[0].text = str(
|
||||||
int(state.all_count) - 1) if int(state.all_count) else '0'
|
int(state.all_count) - 1)
|
||||||
state.trash_count = str(int(state.trash_count) + 1)
|
state.trash_count = str(int(state.trash_count) + 1)
|
||||||
state.all_count = str(int(state.all_count) - 1) if int(state.all_count) else '0'
|
state.all_count = str(int(state.all_count) - 1) if int(state.all_count) else '0'
|
||||||
self.parent.screens[4].clear_widgets()
|
self.parent.screens[4].clear_widgets()
|
||||||
|
@ -1932,7 +2103,7 @@ class MailDetail(Screen):
|
||||||
"""Reply inbox messages"""
|
"""Reply inbox messages"""
|
||||||
data = sqlQuery(
|
data = sqlQuery(
|
||||||
"select toaddress, fromaddress, subject, message from inbox where"
|
"select toaddress, fromaddress, subject, message from inbox where"
|
||||||
" msgid = ?;", str(state.mail_id))
|
" msgid = ?;", state.mail_id)
|
||||||
composer_obj = self.parent.screens[2].children[1].ids
|
composer_obj = self.parent.screens[2].children[1].ids
|
||||||
composer_obj.ti.text = data[0][0]
|
composer_obj.ti.text = data[0][0]
|
||||||
composer_obj.btn.text = data[0][0]
|
composer_obj.btn.text = data[0][0]
|
||||||
|
@ -1948,9 +2119,9 @@ class MailDetail(Screen):
|
||||||
state.send_draft_mail = state.mail_id
|
state.send_draft_mail = state.mail_id
|
||||||
data = sqlQuery(
|
data = sqlQuery(
|
||||||
"select toaddress, fromaddress, subject, message from sent where"
|
"select toaddress, fromaddress, subject, message from sent where"
|
||||||
" ackdata = ?;", str(state.mail_id))
|
" ackdata = ?;", state.mail_id)
|
||||||
composer_ids = (
|
composer_ids = (
|
||||||
self.parent.parent.parent.parent.parent.ids.sc3.children[1].ids)
|
self.parent.parent.ids.sc3.children[1].ids)
|
||||||
composer_ids.ti.text = data[0][1]
|
composer_ids.ti.text = data[0][1]
|
||||||
composer_ids.btn.text = data[0][1]
|
composer_ids.btn.text = data[0][1]
|
||||||
composer_ids.txt_input.text = data[0][0]
|
composer_ids.txt_input.text = data[0][0]
|
||||||
|
@ -1972,10 +2143,11 @@ class MailDetail(Screen):
|
||||||
|
|
||||||
class MyaddDetailPopup(Popup):
|
class MyaddDetailPopup(Popup):
|
||||||
"""MyaddDetailPopup pop is used for showing my address detail"""
|
"""MyaddDetailPopup pop is used for showing my address detail"""
|
||||||
|
|
||||||
address_label = StringProperty()
|
address_label = StringProperty()
|
||||||
address = StringProperty()
|
address = StringProperty()
|
||||||
|
|
||||||
def __init__(self, **kwargs): # pylint: disable=useless-super-delegation
|
def __init__(self, **kwargs):
|
||||||
"""My Address Details screen setting"""
|
"""My Address Details screen setting"""
|
||||||
super(MyaddDetailPopup, self).__init__(**kwargs)
|
super(MyaddDetailPopup, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
@ -2004,12 +2176,12 @@ class MyaddDetailPopup(Popup):
|
||||||
|
|
||||||
class AddbookDetailPopup(Popup):
|
class AddbookDetailPopup(Popup):
|
||||||
"""AddbookDetailPopup pop is used for showing my address detail"""
|
"""AddbookDetailPopup pop is used for showing my address detail"""
|
||||||
|
|
||||||
address_label = StringProperty()
|
address_label = StringProperty()
|
||||||
address = StringProperty()
|
address = StringProperty()
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Set screen of address detail page"""
|
"""Set screen of address detail page"""
|
||||||
# pylint: disable=useless-super-delegation
|
|
||||||
super(AddbookDetailPopup, self).__init__(**kwargs)
|
super(AddbookDetailPopup, self).__init__(**kwargs)
|
||||||
|
|
||||||
def set_addbook_data(self, address, label):
|
def set_addbook_data(self, address, label):
|
||||||
|
@ -2073,17 +2245,21 @@ class ShowQRCode(Screen):
|
||||||
"""ShowQRCode Screen uses to show the detail of mails"""
|
"""ShowQRCode Screen uses to show the detail of mails"""
|
||||||
|
|
||||||
def qrdisplay(self):
|
def qrdisplay(self):
|
||||||
"""Showing QR Code"""
|
"""Method used for showing QR Code"""
|
||||||
# self.manager.parent.parent.parent.ids.search_bar.clear_widgets()
|
|
||||||
self.ids.qr.clear_widgets()
|
self.ids.qr.clear_widgets()
|
||||||
|
state.kivyapp.set_toolbar_for_QrCode()
|
||||||
from kivy.garden.qrcode import QRCodeWidget
|
from kivy.garden.qrcode import QRCodeWidget
|
||||||
self.ids.qr.add_widget(QRCodeWidget(
|
try:
|
||||||
data=self.manager.get_parent_window().children[0].address))
|
address = self.manager.get_parent_window().children[0].address
|
||||||
|
except Exception:
|
||||||
|
address = self.manager.get_parent_window().children[1].address
|
||||||
|
self.ids.qr.add_widget(QRCodeWidget(data=address))
|
||||||
toast('Show QR code')
|
toast('Show QR code')
|
||||||
|
|
||||||
|
|
||||||
class Draft(Screen):
|
class Draft(Screen):
|
||||||
"""Draft screen is used to show the list of draft messages"""
|
"""Draft screen is used to show the list of draft messages"""
|
||||||
|
|
||||||
data = ListProperty()
|
data = ListProperty()
|
||||||
account = StringProperty()
|
account = StringProperty()
|
||||||
queryreturn = ListProperty()
|
queryreturn = ListProperty()
|
||||||
|
@ -2100,41 +2276,47 @@ class Draft(Screen):
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock Schdule for method draft accounts"""
|
"""Clock Schdule for method draft accounts"""
|
||||||
self.sentaccounts()
|
self.sentaccounts()
|
||||||
print dt
|
print(dt)
|
||||||
|
|
||||||
def sentaccounts(self):
|
def sentaccounts(self):
|
||||||
"""Load draft accounts."""
|
"""Load draft accounts"""
|
||||||
self.account = state.association
|
self.account = state.association
|
||||||
self.loadDraft()
|
self.loadDraft()
|
||||||
|
|
||||||
def loadDraft(self, where="", what=""):
|
def loadDraft(self, where="", what=""):
|
||||||
"""Load draft list for Draft messages."""
|
"""Load draft list for Draft messages"""
|
||||||
xAddress = 'fromaddress'
|
xAddress = 'fromaddress'
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
self.draftDataQuery(xAddress, where, what)
|
self.draftDataQuery(xAddress, where, what)
|
||||||
if state.msg_counter_objs:
|
# if state.msg_counter_objs:
|
||||||
state.msg_counter_objs.draft_cnt.badge_text = str(
|
# state.msg_counter_objs.draft_cnt.children[0].children[0].text = showLimitedCnt(len(self.queryreturn))
|
||||||
len(self.queryreturn))
|
|
||||||
if self.queryreturn:
|
if self.queryreturn:
|
||||||
self.ids.identi_tag.children[0].text = 'Draft'
|
self.ids.identi_tag.children[0].text = 'Draft'
|
||||||
src_mng_obj = state.kivyapp.root.children[2].children[0].ids
|
self.set_draftCnt(state.draft_count)
|
||||||
src_mng_obj.draft_cnt.badge_text = state.draft_count
|
|
||||||
self.set_mdList()
|
self.set_mdList()
|
||||||
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
|
self.set_draftCnt('0')
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="yet no message for this account!!!!!!!!!!!!!",
|
text="yet no message for this account!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments
|
|
||||||
def draftDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
def draftDataQuery(self, xAddress, where, what, start_indx=0, end_indx=20):
|
||||||
"""This methosd is for retrieving draft messages"""
|
"""This methosd is for retrieving draft messages"""
|
||||||
self.queryreturn = kivy_helper_search.search_sql(
|
self.queryreturn = kivy_helper_search.search_sql(
|
||||||
xAddress, self.account, "draft", where, what,
|
xAddress, self.account, "draft", where, what,
|
||||||
False, start_indx, end_indx)
|
False, start_indx, end_indx)
|
||||||
|
|
||||||
|
def set_draftCnt(self, Count): # pylint: disable=no-self-use
|
||||||
|
"""This method set the count of draft mails"""
|
||||||
|
draftCnt_obj = state.kivyapp.root.ids.content_drawer.ids.draft_cnt
|
||||||
|
draftCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count))
|
||||||
|
|
||||||
def set_mdList(self):
|
def set_mdList(self):
|
||||||
"""This method is used to create mdlist"""
|
"""This method is used to create mdlist"""
|
||||||
data = []
|
data = []
|
||||||
|
@ -2147,7 +2329,7 @@ class Draft(Screen):
|
||||||
mail[2]) > 10 else mail[2] + '\n' + " " + (
|
mail[2]) > 10 else mail[2] + '\n' + " " + (
|
||||||
third_text[:25] + '...!') if len(
|
third_text[:25] + '...!') if len(
|
||||||
third_text) > 25 else third_text,
|
third_text) > 25 else third_text,
|
||||||
'ackdata': mail[5]})
|
'ackdata': mail[5], 'senttime': mail[6]})
|
||||||
for item in data:
|
for item in data:
|
||||||
meny = TwoLineAvatarIconListItem(
|
meny = TwoLineAvatarIconListItem(
|
||||||
text='Draft', secondary_text=item['text'],
|
text='Draft', secondary_text=item['text'],
|
||||||
|
@ -2157,6 +2339,7 @@ class Draft(Screen):
|
||||||
source='./images/avatar.png'))
|
source='./images/avatar.png'))
|
||||||
meny.bind(on_press=partial(
|
meny.bind(on_press=partial(
|
||||||
self.draft_detail, item['ackdata']))
|
self.draft_detail, item['ackdata']))
|
||||||
|
meny.add_widget(AddTimeWidget(item['senttime']))
|
||||||
carousel = Carousel(direction='right')
|
carousel = Carousel(direction='right')
|
||||||
carousel.height = meny.height
|
carousel.height = meny.height
|
||||||
carousel.size_hint_y = None
|
carousel.size_hint_y = None
|
||||||
|
@ -2202,26 +2385,29 @@ class Draft(Screen):
|
||||||
|
|
||||||
def delete_draft(self, data_index, instance, *args):
|
def delete_draft(self, data_index, instance, *args):
|
||||||
"""Delete draft message permanently"""
|
"""Delete draft message permanently"""
|
||||||
sqlExecute("DELETE FROM sent WHERE ackdata = ?;", str(
|
sqlExecute("DELETE FROM sent WHERE ackdata = ?;", data_index)
|
||||||
data_index))
|
# try:
|
||||||
try:
|
# msg_count_objs = (
|
||||||
msg_count_objs = (
|
# self.parent.parent.parent.parent.parent.children[
|
||||||
self.parent.parent.parent.parent.parent.parent.children[
|
# 2].children[0].ids)
|
||||||
2].children[0].ids)
|
# except Exception:
|
||||||
except Exception:
|
# msg_count_objs = (
|
||||||
msg_count_objs = self.parent.parent.parent.parent.parent.children[
|
# self.parent.parent.parent.parent.parent.parent.children[
|
||||||
2].children[0].ids
|
# 2].children[0].ids)
|
||||||
|
# msg_count_objs = self.parent.parent.parent.parent.parent.children[
|
||||||
|
# 2].children[0].ids
|
||||||
if int(state.draft_count) > 0:
|
if int(state.draft_count) > 0:
|
||||||
msg_count_objs.draft_cnt.badge_text = str(
|
# msg_count_objs.draft_cnt.badge_text = str(
|
||||||
int(state.draft_count) - 1)
|
# int(state.draft_count) - 1)
|
||||||
state.draft_count = str(int(state.draft_count) - 1)
|
state.draft_count = str(int(state.draft_count) - 1)
|
||||||
|
self.set_draftCnt(state.draft_count)
|
||||||
if int(state.draft_count) <= 0:
|
if int(state.draft_count) <= 0:
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
toast('Deleted')
|
toast('Deleted')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def draft_msg(src_object): # pylint: disable=too-many-locals
|
def draft_msg(src_object):
|
||||||
"""Save draft mails"""
|
"""Save draft mails"""
|
||||||
composer_object = state.kivyapp.root.ids.sc3.children[1].ids
|
composer_object = state.kivyapp.root.ids.sc3.children[1].ids
|
||||||
fromAddress = str(composer_object.ti.text)
|
fromAddress = str(composer_object.ti.text)
|
||||||
|
@ -2232,6 +2418,7 @@ class Draft(Screen):
|
||||||
sendMessageToPeople = True
|
sendMessageToPeople = True
|
||||||
if sendMessageToPeople:
|
if sendMessageToPeople:
|
||||||
streamNumber, ripe = decodeAddress(toAddress)[2:]
|
streamNumber, ripe = decodeAddress(toAddress)[2:]
|
||||||
|
from addresses import addBMIfNotPresent
|
||||||
toAddress = addBMIfNotPresent(toAddress)
|
toAddress = addBMIfNotPresent(toAddress)
|
||||||
stealthLevel = BMConfigParser().safeGetInt(
|
stealthLevel = BMConfigParser().safeGetInt(
|
||||||
'bitmessagesettings', 'ackstealthlevel')
|
'bitmessagesettings', 'ackstealthlevel')
|
||||||
|
@ -2239,12 +2426,24 @@ class Draft(Screen):
|
||||||
ackdata = genAckPayload(streamNumber, stealthLevel)
|
ackdata = genAckPayload(streamNumber, stealthLevel)
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'''INSERT INTO sent VALUES
|
'''INSERT INTO sent VALUES
|
||||||
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', '', toAddress, ripe,
|
(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
|
||||||
fromAddress, subject, message, ackdata, int(time.time()),
|
'',
|
||||||
int(time.time()), 0, 'msgqueued', 0, 'draft', encoding,
|
toAddress,
|
||||||
BMConfigParser().getint('bitmessagesettings', 'ttl'))
|
ripe,
|
||||||
|
fromAddress,
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
ackdata,
|
||||||
|
int(time.time()),
|
||||||
|
int(time.time()),
|
||||||
|
0,
|
||||||
|
'msgqueued',
|
||||||
|
0,
|
||||||
|
'draft',
|
||||||
|
encoding,
|
||||||
|
BMConfigParser().safeGetInt('bitmessagesettings', 'ttl'))
|
||||||
state.msg_counter_objs = src_object.children[2].children[0].ids
|
state.msg_counter_objs = src_object.children[2].children[0].ids
|
||||||
state.draft_count = str(int(state.draft_count) + 1)
|
state.draft_count = str(int(state.draft_count) + 1) if state.association == fromAddress else state.draft_count
|
||||||
src_object.ids.sc16.clear_widgets()
|
src_object.ids.sc16.clear_widgets()
|
||||||
src_object.ids.sc16.add_widget(Draft())
|
src_object.ids.sc16.add_widget(Draft())
|
||||||
toast('Save draft')
|
toast('Save draft')
|
||||||
|
@ -2255,20 +2454,21 @@ class CustomSpinner(Spinner):
|
||||||
"""This class is used for setting spinner size"""
|
"""This class is used for setting spinner size"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Setting size of spinner"""
|
"""Method used for setting size of spinner"""
|
||||||
super(CustomSpinner, self).__init__(*args, **kwargs)
|
super(CustomSpinner, self).__init__(*args, **kwargs)
|
||||||
self.dropdown_cls.max_height = Window.size[1] / 3
|
self.dropdown_cls.max_height = Window.size[1] / 3
|
||||||
|
|
||||||
|
|
||||||
class Allmails(Screen):
|
class Allmails(Screen):
|
||||||
"""All mails Screen uses screen to show widgets of screens"""
|
"""All mails Screen uses screen to show widgets of screens"""
|
||||||
|
|
||||||
data = ListProperty()
|
data = ListProperty()
|
||||||
has_refreshed = True
|
has_refreshed = True
|
||||||
all_mails = ListProperty()
|
all_mails = ListProperty()
|
||||||
account = StringProperty()
|
account = StringProperty()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""Method Parsing the address."""
|
"""Method Parsing the address"""
|
||||||
super(Allmails, self).__init__(*args, **kwargs)
|
super(Allmails, self).__init__(*args, **kwargs)
|
||||||
if state.association == '':
|
if state.association == '':
|
||||||
if BMConfigParser().addresses():
|
if BMConfigParser().addresses():
|
||||||
|
@ -2278,10 +2478,10 @@ class Allmails(Screen):
|
||||||
def init_ui(self, dt=0):
|
def init_ui(self, dt=0):
|
||||||
"""Clock Schdule for method all mails"""
|
"""Clock Schdule for method all mails"""
|
||||||
self.loadMessagelist()
|
self.loadMessagelist()
|
||||||
print dt
|
print(dt)
|
||||||
|
|
||||||
def loadMessagelist(self):
|
def loadMessagelist(self):
|
||||||
"""Load Inbox, Sent anf Draft list of messages."""
|
"""Load Inbox, Sent anf Draft list of messages"""
|
||||||
self.account = state.association
|
self.account = state.association
|
||||||
self.ids.identi_tag.children[0].text = ''
|
self.ids.identi_tag.children[0].text = ''
|
||||||
self.allMessageQuery(0, 20)
|
self.allMessageQuery(0, 20)
|
||||||
|
@ -2291,47 +2491,58 @@ class Allmails(Screen):
|
||||||
state.kivyapp.get_sent_count()
|
state.kivyapp.get_sent_count()
|
||||||
state.all_count = str(
|
state.all_count = str(
|
||||||
int(state.sent_count) + int(state.inbox_count))
|
int(state.sent_count) + int(state.inbox_count))
|
||||||
state.kivyapp.root.children[2].children[
|
self.set_AllmailCnt(state.all_count)
|
||||||
0].ids.allmail_cnt.badge_text = state.all_count
|
|
||||||
self.set_mdlist()
|
self.set_mdlist()
|
||||||
# self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y)
|
# self.ids.refresh_layout.bind(scroll_y=self.check_scroll_y)
|
||||||
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
self.ids.scroll_y.bind(scroll_y=self.check_scroll_y)
|
||||||
else:
|
else:
|
||||||
|
self.set_AllmailCnt('0')
|
||||||
content = MDLabel(
|
content = MDLabel(
|
||||||
font_style='Body1', theme_text_color='Primary',
|
font_style='Caption',
|
||||||
|
theme_text_color='Primary',
|
||||||
text="yet no message for this account!!!!!!!!!!!!!",
|
text="yet no message for this account!!!!!!!!!!!!!",
|
||||||
halign='center', bold=True, size_hint_y=None, valign='top')
|
halign='center',
|
||||||
|
size_hint_y=None,
|
||||||
|
valign='top')
|
||||||
self.ids.ml.add_widget(content)
|
self.ids.ml.add_widget(content)
|
||||||
|
|
||||||
def allMessageQuery(self, start_indx, end_indx):
|
def allMessageQuery(self, start_indx, end_indx):
|
||||||
"""Retrieving data from inbox or sent both tables"""
|
"""Retrieving data from inbox or sent both tables"""
|
||||||
self.all_mails = sqlQuery(
|
self.all_mails = sqlQuery(
|
||||||
"SELECT toaddress, fromaddress, subject, message, folder, ackdata"
|
"SELECT toaddress, fromaddress, subject, message, folder, ackdata"
|
||||||
" As id, DATE(lastactiontime) As actionTime FROM sent WHERE"
|
" As id, DATE(senttime) As actionTime, senttime as msgtime FROM sent WHERE"
|
||||||
" folder = 'sent' and fromaddress = '{0}'"
|
" folder = 'sent' and fromaddress = '{0}'"
|
||||||
" UNION SELECT toaddress, fromaddress, subject, message, folder,"
|
" UNION SELECT toaddress, fromaddress, subject, message, folder,"
|
||||||
" msgid As id, DATE(received) As actionTime FROM inbox"
|
" msgid As id, DATE(received) As actionTime, received as msgtime FROM inbox"
|
||||||
" WHERE folder = 'inbox' and toaddress = '{0}'"
|
" WHERE folder = 'inbox' and toaddress = '{0}'"
|
||||||
" ORDER BY actionTime DESC limit {1}, {2}".format(
|
" ORDER BY actionTime DESC limit {1}, {2}".format(
|
||||||
self.account, start_indx, end_indx))
|
self.account, start_indx, end_indx))
|
||||||
|
|
||||||
|
def set_AllmailCnt(self, Count): # pylint: disable=no-self-use
|
||||||
|
"""This method is used to set allmails message count"""
|
||||||
|
allmailCnt_obj = state.kivyapp.root.ids.content_drawer.ids.allmail_cnt
|
||||||
|
allmailCnt_obj.children[0].children[0].text = showLimitedCnt(int(Count))
|
||||||
|
|
||||||
def set_mdlist(self):
|
def set_mdlist(self):
|
||||||
"""This method is used to create mdList for allmaills"""
|
"""This method is used to create mdList for allmaills"""
|
||||||
data_exist = len(self.ids.ml.children)
|
data_exist = len(self.ids.ml.children)
|
||||||
for item in self.all_mails:
|
for item in self.all_mails:
|
||||||
|
body = item[3].decode() if isinstance(item[3],bytes) else item[3]
|
||||||
|
subject = item[2].decode() if isinstance(item[2],bytes) else item[2]
|
||||||
meny = TwoLineAvatarIconListItem(
|
meny = TwoLineAvatarIconListItem(
|
||||||
text=item[1],
|
text=item[1],
|
||||||
secondary_text=item[2][:50] + '........' if len(
|
secondary_text=body[:50] + '........' if len(
|
||||||
item[2]) >= 50 else (
|
body) >= 50 else (
|
||||||
item[2] + ',' + item[3].replace(
|
body + ',' + subject.replace(
|
||||||
'\n', ''))[0:50] + '........',
|
'\n', ''))[0:50] + '........',
|
||||||
theme_text_color='Custom',
|
theme_text_color='Custom',
|
||||||
text_color=NavigateApp().theme_cls.primary_color)
|
text_color=NavigateApp().theme_cls.primary_color)
|
||||||
meny.add_widget(AvatarSampleWidget(
|
meny.add_widget(AvatarSampleWidget(
|
||||||
source='./images/text_images/{}.png'.format(
|
source='./images/text_images/{}.png'.format(
|
||||||
avatarImageFirstLetter(item[2].strip()))))
|
avatarImageFirstLetter(body.strip()))))
|
||||||
meny.bind(on_press=partial(
|
meny.bind(on_press=partial(
|
||||||
self.mail_detail, item[5], item[4]))
|
self.mail_detail, item[5], item[4]))
|
||||||
|
meny.add_widget(AddTimeWidget(item[7]))
|
||||||
carousel = Carousel(direction='right')
|
carousel = Carousel(direction='right')
|
||||||
carousel.height = meny.height
|
carousel.height = meny.height
|
||||||
carousel.size_hint_y = None
|
carousel.size_hint_y = None
|
||||||
|
@ -2383,33 +2594,30 @@ class Allmails(Screen):
|
||||||
if folder == 'inbox':
|
if folder == 'inbox':
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;",
|
"UPDATE inbox SET folder = 'trash' WHERE msgid = ?;",
|
||||||
str(unique_id))
|
unique_id)
|
||||||
else:
|
else:
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
"UPDATE sent SET folder = 'trash' WHERE ackdata = ?;",
|
"UPDATE sent SET folder = 'trash' WHERE ackdata = ?;",
|
||||||
str(unique_id))
|
unique_id)
|
||||||
self.ids.ml.remove_widget(instance.parent.parent)
|
self.ids.ml.remove_widget(instance.parent.parent)
|
||||||
try:
|
try:
|
||||||
msg_count_objs = self.parent.parent.parent.parent.parent.children[
|
msg_count_objs = self.parent.parent.ids.content_drawer.ids
|
||||||
2].children[0].ids
|
nav_lay_obj = self.parent.parent.ids
|
||||||
nav_lay_obj = self.parent.parent.parent.parent.parent.ids
|
|
||||||
except Exception:
|
except Exception:
|
||||||
msg_count_objs = self.parent.parent.parent.parent.parent.parent.children[
|
msg_count_objs = self.parent.parent.parent.ids.content_drawer.ids
|
||||||
2].children[0].ids
|
nav_lay_obj = self.parent.parent.parent.ids
|
||||||
nav_lay_obj = self.parent.parent.parent.parent.parent.parent.ids
|
|
||||||
if folder == 'inbox':
|
if folder == 'inbox':
|
||||||
msg_count_objs.inbox_cnt.badge_text = str(
|
msg_count_objs.inbox_cnt.children[0].children[0].text = showLimitedCnt(int(state.inbox_count) - 1)
|
||||||
int(state.inbox_count) - 1)
|
|
||||||
state.inbox_count = str(int(state.inbox_count) - 1)
|
state.inbox_count = str(int(state.inbox_count) - 1)
|
||||||
nav_lay_obj.sc1.ids.ml.clear_widgets()
|
nav_lay_obj.sc1.ids.ml.clear_widgets()
|
||||||
nav_lay_obj.sc1.loadMessagelist(state.association)
|
nav_lay_obj.sc1.loadMessagelist(state.association)
|
||||||
else:
|
else:
|
||||||
msg_count_objs.send_cnt.badge_text = str(int(state.sent_count) - 1)
|
msg_count_objs.send_cnt.children[0].children[0].text = showLimitedCnt(int(state.sent_count) - 1)
|
||||||
state.sent_count = str(int(state.sent_count) - 1)
|
state.sent_count = str(int(state.sent_count) - 1)
|
||||||
nav_lay_obj.sc4.ids.ml.clear_widgets()
|
nav_lay_obj.sc4.ids.ml.clear_widgets()
|
||||||
nav_lay_obj.sc4.loadSent(state.association)
|
nav_lay_obj.sc4.loadSent(state.association)
|
||||||
msg_count_objs.trash_cnt.badge_text = str(int(state.trash_count) + 1)
|
msg_count_objs.trash_cnt.children[0].children[0].text = showLimitedCnt(int(state.trash_count) + 1)
|
||||||
msg_count_objs.allmail_cnt.badge_text = str(int(state.all_count) - 1)
|
msg_count_objs.allmail_cnt.children[0].children[0].text = showLimitedCnt(int(state.all_count) - 1)
|
||||||
state.trash_count = str(int(state.trash_count) + 1)
|
state.trash_count = str(int(state.trash_count) + 1)
|
||||||
state.all_count = str(int(state.all_count) - 1)
|
state.all_count = str(int(state.all_count) - 1)
|
||||||
if int(state.all_count) <= 0:
|
if int(state.all_count) <= 0:
|
||||||
|
@ -2418,7 +2626,6 @@ class Allmails(Screen):
|
||||||
nav_lay_obj.sc5.add_widget(Trash())
|
nav_lay_obj.sc5.add_widget(Trash())
|
||||||
nav_lay_obj.sc17.remove_widget(instance.parent.parent)
|
nav_lay_obj.sc17.remove_widget(instance.parent.parent)
|
||||||
|
|
||||||
# pylint: disable=attribute-defined-outside-init
|
|
||||||
def refresh_callback(self, *args):
|
def refresh_callback(self, *args):
|
||||||
"""Method updates the state of application,
|
"""Method updates the state of application,
|
||||||
While the spinner remains on the screen"""
|
While the spinner remains on the screen"""
|
||||||
|
@ -2435,13 +2642,6 @@ class Allmails(Screen):
|
||||||
self.tick = 0
|
self.tick = 0
|
||||||
Clock.schedule_once(refresh_callback, 1)
|
Clock.schedule_once(refresh_callback, 1)
|
||||||
|
|
||||||
def set_root_layout(self):
|
|
||||||
"""Setting root layout"""
|
|
||||||
try:
|
|
||||||
return self.manager.parent.parent
|
|
||||||
except Exception:
|
|
||||||
return state.kivyapp.root.ids.float_box
|
|
||||||
|
|
||||||
|
|
||||||
def avatarImageFirstLetter(letter_string):
|
def avatarImageFirstLetter(letter_string):
|
||||||
"""This function is used to the first letter for the avatar image"""
|
"""This function is used to the first letter for the avatar image"""
|
||||||
|
@ -2483,3 +2683,72 @@ class LoadingPopup(Popup):
|
||||||
def dismiss_popup(self, dt):
|
def dismiss_popup(self, dt):
|
||||||
"""Dismiss popups"""
|
"""Dismiss popups"""
|
||||||
self.dismiss()
|
self.dismiss()
|
||||||
|
|
||||||
|
|
||||||
|
class AddressDropdown(OneLineIconListItem):
|
||||||
|
"""AddressDropdown showns all the addresses"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BadgeText(IRightBodyTouch, MDLabel):
|
||||||
|
"""Class for badgetext"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class NavigationItem(OneLineAvatarIconListItem):
|
||||||
|
"""NavigationItem class is for button behaviour"""
|
||||||
|
badge_text = StringProperty()
|
||||||
|
icon = StringProperty()
|
||||||
|
active = BooleanProperty(False)
|
||||||
|
|
||||||
|
def currentlyActive(self):
|
||||||
|
for nav_obj in self.parent.children:
|
||||||
|
nav_obj.active = False
|
||||||
|
self.active = True
|
||||||
|
|
||||||
|
|
||||||
|
class NavigationDrawerDivider(OneLineListItem):
|
||||||
|
"""
|
||||||
|
A small full-width divider that can be placed
|
||||||
|
in the :class:`MDNavigationDrawer`
|
||||||
|
"""
|
||||||
|
|
||||||
|
disabled = True
|
||||||
|
divider = None
|
||||||
|
_txt_top_pad = NumericProperty(dp(8))
|
||||||
|
_txt_bot_pad = NumericProperty(dp(8))
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
# pylint: disable=bad-super-call
|
||||||
|
super(OneLineListItem, self).__init__(**kwargs)
|
||||||
|
self.height = dp(16)
|
||||||
|
|
||||||
|
|
||||||
|
class NavigationDrawerSubheader(OneLineListItem):
|
||||||
|
"""
|
||||||
|
A subheader for separating content in :class:`MDNavigationDrawer`
|
||||||
|
|
||||||
|
Works well alongside :class:`NavigationDrawerDivider`
|
||||||
|
"""
|
||||||
|
|
||||||
|
disabled = True
|
||||||
|
divider = None
|
||||||
|
theme_text_color = 'Secondary'
|
||||||
|
|
||||||
|
|
||||||
|
class AppClosingPopup(Popup):
|
||||||
|
"""Class for app closing popup"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(AppClosingPopup, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def closingAction(self, text):
|
||||||
|
"""Action on closing window"""
|
||||||
|
if text == 'Yes':
|
||||||
|
print("*******************EXITING FROM APPLICATION*******************")
|
||||||
|
import shutdown
|
||||||
|
shutdown.doCleanShutdown()
|
||||||
|
else:
|
||||||
|
self.dismiss()
|
||||||
|
toast(text)
|
||||||
|
|
|
@ -25,4 +25,4 @@ class UIkivySignaler(Thread):
|
||||||
elif command == 'updateSentItemStatusByAckdata':
|
elif command == 'updateSentItemStatusByAckdata':
|
||||||
state.kivyapp.status_dispatching(data)
|
state.kivyapp.status_dispatching(data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print e
|
print(e)
|
||||||
|
|
|
@ -27,8 +27,10 @@ import depends
|
||||||
import shared
|
import shared
|
||||||
import shutdown
|
import shutdown
|
||||||
import state
|
import state
|
||||||
|
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger # this should go before any threads
|
# this should go before any threads
|
||||||
|
from debug import logger
|
||||||
from helper_startup import (
|
from helper_startup import (
|
||||||
isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections,
|
isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections,
|
||||||
start_proxyconfig
|
start_proxyconfig
|
||||||
|
@ -158,13 +160,13 @@ def signal_handler(signum, frame):
|
||||||
if shared.thisapp.daemon or not state.enableGUI:
|
if shared.thisapp.daemon or not state.enableGUI:
|
||||||
shutdown.doCleanShutdown()
|
shutdown.doCleanShutdown()
|
||||||
else:
|
else:
|
||||||
print '# Thread: %s(%d)' % (thread.name, thread.ident)
|
print('# Thread: {}({})'.format(thread.name, thread.ident))
|
||||||
for filename, lineno, name, line in traceback.extract_stack(frame):
|
for filename, lineno, name, line in traceback.extract_stack(frame):
|
||||||
print 'File: "%s", line %d, in %s' % (filename, lineno, name)
|
print("File: '{}', line {}, in {}" .format(filename, lineno, name))
|
||||||
if line:
|
if line:
|
||||||
print ' %s' % line.strip()
|
print(' {}'.format(line.strip()))
|
||||||
print 'Unfortunately you cannot use Ctrl+C when running the UI \
|
print('Unfortunately you cannot use Ctrl+C when running the UI \
|
||||||
because the UI captures the signal.'
|
because the UI captures the signal.')
|
||||||
|
|
||||||
|
|
||||||
class Main(object):
|
class Main(object):
|
||||||
|
@ -199,7 +201,8 @@ class Main(object):
|
||||||
if os.path.isfile(os.path.join(
|
if os.path.isfile(os.path.join(
|
||||||
state.appdata, 'unittest.lock')):
|
state.appdata, 'unittest.lock')):
|
||||||
daemon = True
|
daemon = True
|
||||||
state.enableGUI = False # run without a UI
|
# run without a UI
|
||||||
|
state.enableGUI = False
|
||||||
# Fallback: in case when no api command was issued
|
# Fallback: in case when no api command was issued
|
||||||
state.last_api_response = time.time()
|
state.last_api_response = time.time()
|
||||||
# Apply special settings
|
# Apply special settings
|
||||||
|
@ -215,7 +218,8 @@ class Main(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
if daemon:
|
if daemon:
|
||||||
state.enableGUI = False # run without a UI
|
# run without a UI
|
||||||
|
state.enableGUI = False
|
||||||
|
|
||||||
# is the application already running? If yes then exit.
|
# is the application already running? If yes then exit.
|
||||||
if state.enableGUI and not state.curses and not state.kivy and not depends.check_pyqt():
|
if state.enableGUI and not state.curses and not state.kivy and not depends.check_pyqt():
|
||||||
|
@ -239,18 +243,17 @@ class Main(object):
|
||||||
|
|
||||||
if daemon:
|
if daemon:
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Running as a daemon. Send TERM signal to end.'
|
print('Running as a daemon. Send TERM signal to end.')
|
||||||
self.daemonize()
|
self.daemonize()
|
||||||
|
|
||||||
self.setSignalHandler()
|
self.setSignalHandler()
|
||||||
|
|
||||||
set_thread_name("PyBitmessage")
|
set_thread_name("PyBitmessage")
|
||||||
|
|
||||||
state.dandelion = config.safeGetInt('network', 'dandelion')
|
state.dandelion = config.safeGet('network', 'dandelion')
|
||||||
# dandelion requires outbound connections, without them,
|
# dandelion requires outbound connections, without them,
|
||||||
# stem objects will get stuck forever
|
# stem objects will get stuck forever
|
||||||
if state.dandelion and not config.safeGetBoolean(
|
if state.dandelion and not (config.safeGet('bitmessagesettings', 'sendoutgoingconnections') == 'True'):
|
||||||
'bitmessagesettings', 'sendoutgoingconnections'):
|
|
||||||
state.dandelion = 0
|
state.dandelion = 0
|
||||||
|
|
||||||
if state.testmode or config.safeGetBoolean(
|
if state.testmode or config.safeGetBoolean(
|
||||||
|
@ -262,7 +265,6 @@ class Main(object):
|
||||||
|
|
||||||
readKnownNodes()
|
readKnownNodes()
|
||||||
|
|
||||||
|
|
||||||
# Not needed if objproc is disabled
|
# Not needed if objproc is disabled
|
||||||
if state.enableObjProc:
|
if state.enableObjProc:
|
||||||
|
|
||||||
|
@ -321,7 +323,8 @@ class Main(object):
|
||||||
shared.reloadBroadcastSendersForWhichImWatching()
|
shared.reloadBroadcastSendersForWhichImWatching()
|
||||||
# API is also objproc dependent
|
# API is also objproc dependent
|
||||||
if config.safeGetBoolean('bitmessagesettings', 'apienabled'):
|
if config.safeGetBoolean('bitmessagesettings', 'apienabled'):
|
||||||
import api # pylint: disable=relative-import
|
# pylint: disable=relative-import
|
||||||
|
import api
|
||||||
singleAPIThread = api.singleAPI()
|
singleAPIThread = api.singleAPI()
|
||||||
# close the main program even if there are threads left
|
# close the main program even if there are threads left
|
||||||
singleAPIThread.daemon = True
|
singleAPIThread.daemon = True
|
||||||
|
@ -333,7 +336,7 @@ class Main(object):
|
||||||
asyncoreThread = BMNetworkThread()
|
asyncoreThread = BMNetworkThread()
|
||||||
asyncoreThread.daemon = True
|
asyncoreThread.daemon = True
|
||||||
asyncoreThread.start()
|
asyncoreThread.start()
|
||||||
for i in range(config.getint('threads', 'receive')):
|
for i in range(config.safeGet('threads', 'receive')):
|
||||||
receiveQueueThread = ReceiveQueueThread(i)
|
receiveQueueThread = ReceiveQueueThread(i)
|
||||||
receiveQueueThread.daemon = True
|
receiveQueueThread.daemon = True
|
||||||
receiveQueueThread.start()
|
receiveQueueThread.start()
|
||||||
|
@ -365,12 +368,13 @@ class Main(object):
|
||||||
if state.curses:
|
if state.curses:
|
||||||
if not depends.check_curses():
|
if not depends.check_curses():
|
||||||
sys.exit()
|
sys.exit()
|
||||||
print 'Running with curses'
|
print('Running with curses')
|
||||||
import bitmessagecurses
|
import bitmessagecurses
|
||||||
bitmessagecurses.runwrapper()
|
bitmessagecurses.runwrapper()
|
||||||
|
|
||||||
elif state.kivy:
|
elif state.kivy:
|
||||||
config.remove_option('bitmessagesettings', 'dontconnect')
|
config.remove_option('bitmessagesettings', 'dontconnect')
|
||||||
|
# pylint: disable=no-member,import-error,no-name-in-module,relative-import
|
||||||
from bitmessagekivy.mpybit import NavigateApp
|
from bitmessagekivy.mpybit import NavigateApp
|
||||||
state.kivyapp = NavigateApp()
|
state.kivyapp = NavigateApp()
|
||||||
state.kivyapp.run()
|
state.kivyapp.run()
|
||||||
|
@ -420,7 +424,8 @@ class Main(object):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
parentPid = os.getpid()
|
parentPid = os.getpid()
|
||||||
shared.thisapp.lock() # relock
|
# relock
|
||||||
|
shared.thisapp.lock()
|
||||||
|
|
||||||
os.umask(0)
|
os.umask(0)
|
||||||
try:
|
try:
|
||||||
|
@ -435,13 +440,16 @@ class Main(object):
|
||||||
# wait until child ready
|
# wait until child ready
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
os._exit(0) # pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
|
os._exit(0)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# fork not implemented
|
# fork not implemented
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
shared.thisapp.lock() # relock
|
# relock
|
||||||
shared.thisapp.lockPid = None # indicate we're the final child
|
shared.thisapp.lock()
|
||||||
|
# indicate we're the final child
|
||||||
|
shared.thisapp.lockPid = None
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
if not sys.platform.startswith('win'):
|
if not sys.platform.startswith('win'):
|
||||||
|
@ -481,7 +489,7 @@ All parameters are optional.
|
||||||
def stop():
|
def stop():
|
||||||
"""Stop main application"""
|
"""Stop main application"""
|
||||||
with shared.printLock:
|
with shared.printLock:
|
||||||
print 'Stopping Bitmessage Deamon.'
|
print('Stopping Bitmessage Deamon.')
|
||||||
shutdown.doCleanShutdown()
|
shutdown.doCleanShutdown()
|
||||||
|
|
||||||
# .. todo:: nice function but no one is using this
|
# .. todo:: nice function but no one is using this
|
||||||
|
|
|
@ -14,7 +14,7 @@ import network.stats
|
||||||
import shared
|
import shared
|
||||||
import widgets
|
import widgets
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from retranslateui import RetranslateMixin
|
from retranslateui import RetranslateMixin
|
||||||
from tr import _translate
|
from tr import _translate
|
||||||
from uisignaler import UISignaler
|
from uisignaler import UISignaler
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from Queue import Queue
|
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
class BMStatusBar(QtGui.QStatusBar):
|
class BMStatusBar(QtGui.QStatusBar):
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
"""
|
"""
|
||||||
BMConfigParser class definition and default configuration settings
|
BMConfigParser class definition and default configuration settings
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=no-self-use, arguments-differ
|
||||||
import ConfigParser
|
import configparser
|
||||||
|
import shutil
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -42,39 +43,36 @@ BMConfigDefaults = {
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class BMConfigParser(ConfigParser.SafeConfigParser):
|
class BMConfigParser(configparser.ConfigParser):
|
||||||
"""
|
"""Singleton class inherited from ConfigParsedadfeConfigParser
|
||||||
Singleton class inherited from :class:`ConfigParser.SafeConfigParser`
|
with additional methods specific to bitmessage config."""
|
||||||
with additional methods specific to bitmessage config.
|
|
||||||
"""
|
|
||||||
# pylint: disable=too-many-ancestors
|
# pylint: disable=too-many-ancestors
|
||||||
|
|
||||||
_temp = {}
|
_temp = {}
|
||||||
|
|
||||||
def set(self, section, option, value=None):
|
def set(self, section, option, value=None):
|
||||||
if self._optcre is self.OPTCRE or value:
|
if self._optcre is self.OPTCRE or value:
|
||||||
if not isinstance(value, basestring):
|
if not isinstance(value, str):
|
||||||
raise TypeError("option values must be strings")
|
raise TypeError("option values must be strings")
|
||||||
if not self.validate(section, option, value):
|
if not self.validate(section, option, value):
|
||||||
raise ValueError("Invalid value %s" % value)
|
raise ValueError("Invalid value %s" % value)
|
||||||
return ConfigParser.ConfigParser.set(self, section, option, value)
|
return configparser.ConfigParser.set(self, section, option, value)
|
||||||
|
|
||||||
def get(self, section, option, raw=False, variables=None):
|
def get(self, section, option, raw=False, variables=None):
|
||||||
# pylint: disable=arguments-differ
|
# pylint: disable=unused-argument
|
||||||
try:
|
try:
|
||||||
if section == "bitmessagesettings" and option == "timeformat":
|
if section == "bitmessagesettings" and option == "timeformat":
|
||||||
return ConfigParser.ConfigParser.get(
|
return configparser.ConfigParser.get(
|
||||||
self, section, option, raw, variables)
|
self, section, option, raw=True, vars=variables)
|
||||||
try:
|
try:
|
||||||
return self._temp[section][option]
|
return self._temp[section][option]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
return ConfigParser.ConfigParser.get(
|
return configparser.ConfigParser.get(
|
||||||
self, section, option, True, variables)
|
self, section, option, raw=True, vars=variables)
|
||||||
except ConfigParser.InterpolationError:
|
except configparser.InterpolationError:
|
||||||
return ConfigParser.ConfigParser.get(
|
return configparser.ConfigParser.get(
|
||||||
self, section, option, True, variables)
|
self, section, option, raw=True, vars=variables)
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) as e:
|
except (configparser.NoSectionError, configparser.NoOptionError) as e:
|
||||||
try:
|
try:
|
||||||
return BMConfigDefaults[section][option]
|
return BMConfigDefaults[section][option]
|
||||||
except (KeyError, ValueError, AttributeError):
|
except (KeyError, ValueError, AttributeError):
|
||||||
|
@ -89,9 +87,13 @@ class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
|
|
||||||
def safeGetBoolean(self, section, field):
|
def safeGetBoolean(self, section, field):
|
||||||
"""Return value as boolean, False on exceptions"""
|
"""Return value as boolean, False on exceptions"""
|
||||||
|
config = configparser.ConfigParser()
|
||||||
try:
|
try:
|
||||||
return self.getboolean(section, field)
|
# Used in the python2.7
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError,
|
# return self.getboolean(section, field)
|
||||||
|
# Used in the python3.5.2
|
||||||
|
return config.getboolean(section, field)
|
||||||
|
except (configparser.NoSectionError, configparser.NoOptionError,
|
||||||
ValueError, AttributeError):
|
ValueError, AttributeError):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -99,8 +101,11 @@ class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
"""Return value as integer, default on exceptions,
|
"""Return value as integer, default on exceptions,
|
||||||
0 if default missing"""
|
0 if default missing"""
|
||||||
try:
|
try:
|
||||||
return self.getint(section, field)
|
# Used in the python2.7
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError,
|
# return self.getint(section, field)
|
||||||
|
# Used in the python3.7.0
|
||||||
|
return int(self.get(section, field))
|
||||||
|
except (configparser.NoSectionError, configparser.NoOptionError,
|
||||||
ValueError, AttributeError):
|
ValueError, AttributeError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
@ -108,38 +113,38 @@ class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
"""Return value as is, default on exceptions, None if default missing"""
|
"""Return value as is, default on exceptions, None if default missing"""
|
||||||
try:
|
try:
|
||||||
return self.get(section, option)
|
return self.get(section, option)
|
||||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError,
|
except (configparser.NoSectionError, configparser.NoOptionError,
|
||||||
ValueError, AttributeError):
|
ValueError, AttributeError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def items(self, section, raw=False, variables=None):
|
def items(self, section, raw=False, variables=None):
|
||||||
|
# pylint: disable=signature-differs
|
||||||
"""Return section variables as parent,
|
"""Return section variables as parent,
|
||||||
but override the "raw" argument to always True"""
|
but override the "raw" argument to always True"""
|
||||||
# pylint: disable=arguments-differ
|
return configparser.ConfigParser.items(self, section, True, variables)
|
||||||
return ConfigParser.ConfigParser.items(self, section, True, variables)
|
|
||||||
|
|
||||||
@staticmethod
|
def addresses(self):
|
||||||
def addresses():
|
|
||||||
"""Return a list of local bitmessage addresses (from section labels)"""
|
"""Return a list of local bitmessage addresses (from section labels)"""
|
||||||
return [
|
return [x for x in BMConfigParser().sections() if x.startswith('BM-')]
|
||||||
x for x in BMConfigParser().sections() if x.startswith('BM-')]
|
|
||||||
|
|
||||||
def read(self, filenames):
|
def read(self, filenames):
|
||||||
ConfigParser.ConfigParser.read(self, filenames)
|
configparser.ConfigParser.read(self, filenames)
|
||||||
for section in self.sections():
|
for section in self.sections():
|
||||||
for option in self.options(section):
|
for option in self.options(section):
|
||||||
try:
|
try:
|
||||||
if not self.validate(
|
if not self.validate(
|
||||||
section, option,
|
section, option,
|
||||||
ConfigParser.ConfigParser.get(self, section, option)
|
self[section][option]
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
newVal = BMConfigDefaults[section][option]
|
newVal = BMConfigDefaults[section][option]
|
||||||
|
except configparser.NoSectionError:
|
||||||
|
continue
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
ConfigParser.ConfigParser.set(
|
configparser.ConfigParser.set(
|
||||||
self, section, option, newVal)
|
self, section, option, newVal)
|
||||||
except ConfigParser.InterpolationError:
|
except configparser.InterpolationError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
@ -158,7 +163,7 @@ class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
# didn't exist before.
|
# didn't exist before.
|
||||||
fileNameExisted = False
|
fileNameExisted = False
|
||||||
# write the file
|
# write the file
|
||||||
with open(fileName, 'wb') as configfile:
|
with open(fileName, 'w') as configfile:
|
||||||
self.write(configfile)
|
self.write(configfile)
|
||||||
# delete the backup
|
# delete the backup
|
||||||
if fileNameExisted:
|
if fileNameExisted:
|
||||||
|
@ -167,7 +172,8 @@ class BMConfigParser(ConfigParser.SafeConfigParser):
|
||||||
def validate(self, section, option, value):
|
def validate(self, section, option, value):
|
||||||
"""Input validator interface (using factory pattern)"""
|
"""Input validator interface (using factory pattern)"""
|
||||||
try:
|
try:
|
||||||
return getattr(self, 'validate_%s_%s' % (section, option))(value)
|
return getattr(self, 'validate_{}_{}'.format(
|
||||||
|
section, option))(value)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,13 @@ import tr
|
||||||
from addresses import decodeAddress, encodeAddress, encodeVarint
|
from addresses import decodeAddress, encodeAddress, encodeVarint
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from fallback import RIPEMD160Hash
|
from fallback import RIPEMD160Hash
|
||||||
from network import StoppableThread
|
|
||||||
from pyelliptic import arithmetic
|
from pyelliptic import arithmetic
|
||||||
from pyelliptic.openssl import OpenSSL
|
from pyelliptic.openssl import OpenSSL
|
||||||
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class addressGenerator(StoppableThread):
|
class addressGenerator(StoppableThread):
|
||||||
"""A thread for creating addresses"""
|
"""A thread for creating addresses"""
|
||||||
|
|
||||||
name = "addressGenerator"
|
name = "addressGenerator"
|
||||||
|
|
||||||
def stopThread(self):
|
def stopThread(self):
|
||||||
|
@ -142,7 +141,7 @@ class addressGenerator(StoppableThread):
|
||||||
ripe = RIPEMD160Hash(sha.digest()).digest()
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
if (
|
if (
|
||||||
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] ==
|
ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash] ==
|
||||||
'\x00' * numberOfNullBytesDemandedOnFrontOfRipeHash
|
'\x00'.encode('utf-8') * numberOfNullBytesDemandedOnFrontOfRipeHash
|
||||||
):
|
):
|
||||||
break
|
break
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
|
@ -159,19 +158,20 @@ class addressGenerator(StoppableThread):
|
||||||
# The user must have a pretty fast computer.
|
# The user must have a pretty fast computer.
|
||||||
# time.time() - startTime equaled zero.
|
# time.time() - startTime equaled zero.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
address = encodeAddress(
|
address = encodeAddress(
|
||||||
addressVersionNumber, streamNumber, ripe)
|
addressVersionNumber, streamNumber, ripe)
|
||||||
|
|
||||||
# An excellent way for us to store our keys
|
# An excellent way for us to store our keys
|
||||||
# is in Wallet Import Format. Let us convert now.
|
# is in Wallet Import Format. Let us convert now.
|
||||||
# https://en.bitcoin.it/wiki/Wallet_import_format
|
# https://en.bitcoin.it/wiki/Wallet_import_format
|
||||||
privSigningKey = '\x80' + potentialPrivSigningKey
|
privSigningKey = '\x80'.encode('utf-8')[1:] + potentialPrivSigningKey
|
||||||
checksum = hashlib.sha256(hashlib.sha256(
|
checksum = hashlib.sha256(hashlib.sha256(
|
||||||
privSigningKey).digest()).digest()[0:4]
|
privSigningKey).digest()).digest()[0:4]
|
||||||
privSigningKeyWIF = arithmetic.changebase(
|
privSigningKeyWIF = arithmetic.changebase(
|
||||||
privSigningKey + checksum, 256, 58)
|
privSigningKey + checksum, 256, 58)
|
||||||
|
|
||||||
privEncryptionKey = '\x80' + potentialPrivEncryptionKey
|
privEncryptionKey = '\x80'.encode('utf-8')[1:] + potentialPrivEncryptionKey
|
||||||
checksum = hashlib.sha256(hashlib.sha256(
|
checksum = hashlib.sha256(hashlib.sha256(
|
||||||
privEncryptionKey).digest()).digest()[0:4]
|
privEncryptionKey).digest()).digest()[0:4]
|
||||||
privEncryptionKeyWIF = arithmetic.changebase(
|
privEncryptionKeyWIF = arithmetic.changebase(
|
||||||
|
@ -193,7 +193,6 @@ class addressGenerator(StoppableThread):
|
||||||
# The API and the join and create Chan functionality
|
# The API and the join and create Chan functionality
|
||||||
# both need information back from the address generator.
|
# both need information back from the address generator.
|
||||||
queues.apiAddressGeneratorReturnQueue.put(address)
|
queues.apiAddressGeneratorReturnQueue.put(address)
|
||||||
|
|
||||||
queues.UISignalQueue.put((
|
queues.UISignalQueue.put((
|
||||||
'updateStatusBar', ""
|
'updateStatusBar', ""
|
||||||
))
|
))
|
||||||
|
@ -207,9 +206,14 @@ class addressGenerator(StoppableThread):
|
||||||
queues.workerQueue.put((
|
queues.workerQueue.put((
|
||||||
'sendOutOrStoreMyV4Pubkey', address))
|
'sendOutOrStoreMyV4Pubkey', address))
|
||||||
|
|
||||||
elif command == 'createDeterministicAddresses' \
|
# elif command == 'createDeterministicAddresses' \
|
||||||
or command == 'getDeterministicAddress' \
|
# or command == 'getDeterministicAddress' \
|
||||||
or command == 'createChan' or command == 'joinChan':
|
# or command == 'createChan' or command == 'joinChan':
|
||||||
|
elif command in (
|
||||||
|
'createDeterministicAddresses',
|
||||||
|
'getDeterministicAddress',
|
||||||
|
'createChan',
|
||||||
|
'joinChan'):
|
||||||
if not deterministicPassphrase:
|
if not deterministicPassphrase:
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
'You are creating deterministic'
|
'You are creating deterministic'
|
||||||
|
@ -334,8 +338,8 @@ class addressGenerator(StoppableThread):
|
||||||
BMConfigParser().set(address, 'label', label)
|
BMConfigParser().set(address, 'label', label)
|
||||||
BMConfigParser().set(address, 'enabled', 'true')
|
BMConfigParser().set(address, 'enabled', 'true')
|
||||||
BMConfigParser().set(address, 'decoy', 'false')
|
BMConfigParser().set(address, 'decoy', 'false')
|
||||||
if command == 'joinChan' \
|
# if command == 'joinChan' or command == 'createChan':
|
||||||
or command == 'createChan':
|
if command in ('joinChan', 'createChan'):
|
||||||
BMConfigParser().set(address, 'chan', 'true')
|
BMConfigParser().set(address, 'chan', 'true')
|
||||||
BMConfigParser().set(
|
BMConfigParser().set(
|
||||||
address, 'noncetrialsperbyte',
|
address, 'noncetrialsperbyte',
|
||||||
|
@ -386,8 +390,12 @@ class addressGenerator(StoppableThread):
|
||||||
address)
|
address)
|
||||||
|
|
||||||
# Done generating addresses.
|
# Done generating addresses.
|
||||||
if command == 'createDeterministicAddresses' \
|
# if command == 'createDeterministicAddresses' \
|
||||||
or command == 'joinChan' or command == 'createChan':
|
# or command == 'joinChan' or command == 'createChan':
|
||||||
|
if command in (
|
||||||
|
'createDeterministicAddresses',
|
||||||
|
'joinChan',
|
||||||
|
'createChan'):
|
||||||
queues.apiAddressGeneratorReturnQueue.put(
|
queues.apiAddressGeneratorReturnQueue.put(
|
||||||
listOfNewAddressesToSendOutThroughTheAPI)
|
listOfNewAddressesToSendOutThroughTheAPI)
|
||||||
elif command == 'getDeterministicAddress':
|
elif command == 'getDeterministicAddress':
|
||||||
|
|
|
@ -47,7 +47,7 @@ class objectProcessor(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
threading.Thread.__init__(self, name="objectProcessor")
|
threading.Thread.__init__(self, name="objectProcessor")
|
||||||
random.seed()
|
random.seed()
|
||||||
# It may be the case that the last time Bitmessage was running,
|
# It may be the case that the last time Bitmes0sage was running,
|
||||||
# the user closed it before it finished processing everything in the
|
# the user closed it before it finished processing everything in the
|
||||||
# objectProcessorQueue. Assuming that Bitmessage wasn't closed
|
# objectProcessorQueue. Assuming that Bitmessage wasn't closed
|
||||||
# forcefully, it should have saved the data in the queue into the
|
# forcefully, it should have saved the data in the queue into the
|
||||||
|
@ -68,9 +68,7 @@ class objectProcessor(threading.Thread):
|
||||||
"""Process the objects from `.queues.objectProcessorQueue`"""
|
"""Process the objects from `.queues.objectProcessorQueue`"""
|
||||||
while True:
|
while True:
|
||||||
objectType, data = queues.objectProcessorQueue.get()
|
objectType, data = queues.objectProcessorQueue.get()
|
||||||
|
|
||||||
self.checkackdata(data)
|
self.checkackdata(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if objectType == protocol.OBJECT_GETPUBKEY:
|
if objectType == protocol.OBJECT_GETPUBKEY:
|
||||||
self.processgetpubkey(data)
|
self.processgetpubkey(data)
|
||||||
|
@ -140,9 +138,9 @@ class objectProcessor(threading.Thread):
|
||||||
# bypass nonce and time, retain object type/version/stream + body
|
# bypass nonce and time, retain object type/version/stream + body
|
||||||
readPosition = 16
|
readPosition = 16
|
||||||
|
|
||||||
if data[readPosition:] in shared.ackdataForWhichImWatching:
|
if bytes(data[readPosition:]) in shared.ackdataForWhichImWatching:
|
||||||
logger.info('This object is an acknowledgement bound for me.')
|
logger.info('This object is an acknowledgement bound for me.')
|
||||||
del shared.ackdataForWhichImWatching[data[readPosition:]]
|
del shared.ackdataForWhichImWatching[bytes(data[readPosition:])]
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
'UPDATE sent SET status=?, lastactiontime=?'
|
'UPDATE sent SET status=?, lastactiontime=?'
|
||||||
' WHERE ackdata=?',
|
' WHERE ackdata=?',
|
||||||
|
@ -223,7 +221,7 @@ class objectProcessor(threading.Thread):
|
||||||
'the hash requested in this getpubkey request is: %s',
|
'the hash requested in this getpubkey request is: %s',
|
||||||
hexlify(requestedHash))
|
hexlify(requestedHash))
|
||||||
# if this address hash is one of mine
|
# if this address hash is one of mine
|
||||||
if requestedHash in shared.myAddressesByHash:
|
if bytes(requestedHash) in shared.myAddressesByHash:
|
||||||
myAddress = shared.myAddressesByHash[requestedHash]
|
myAddress = shared.myAddressesByHash[requestedHash]
|
||||||
elif requestedAddressVersionNumber >= 4:
|
elif requestedAddressVersionNumber >= 4:
|
||||||
requestedTag = data[readPosition:readPosition + 32]
|
requestedTag = data[readPosition:readPosition + 32]
|
||||||
|
@ -235,8 +233,8 @@ class objectProcessor(threading.Thread):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'the tag requested in this getpubkey request is: %s',
|
'the tag requested in this getpubkey request is: %s',
|
||||||
hexlify(requestedTag))
|
hexlify(requestedTag))
|
||||||
if requestedTag in shared.myAddressesByTag:
|
if bytes(requestedTag) in shared.myAddressesByTag:
|
||||||
myAddress = shared.myAddressesByTag[requestedTag]
|
myAddress = shared.myAddressesByTag[bytes(requestedTag)]
|
||||||
|
|
||||||
if myAddress == '':
|
if myAddress == '':
|
||||||
logger.info('This getpubkey request is not for any of my keys.')
|
logger.info('This getpubkey request is not for any of my keys.')
|
||||||
|
@ -330,7 +328,7 @@ class objectProcessor(threading.Thread):
|
||||||
dataToStore = data[20:readPosition]
|
dataToStore = data[20:readPosition]
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(
|
sha.update(
|
||||||
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
|
'\x04'.encode() + publicSigningKey + '\x04'.encode() + publicEncryptionKey)
|
||||||
ripe = RIPEMD160Hash(sha.digest()).digest()
|
ripe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
|
|
||||||
if logger.isEnabledFor(logging.DEBUG):
|
if logger.isEnabledFor(logging.DEBUG):
|
||||||
|
@ -369,9 +367,9 @@ class objectProcessor(threading.Thread):
|
||||||
' Sanity check failed.')
|
' Sanity check failed.')
|
||||||
return
|
return
|
||||||
readPosition += 4
|
readPosition += 4
|
||||||
publicSigningKey = '\x04' + data[readPosition:readPosition + 64]
|
publicSigningKey = ('\x04').encode() + data[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
publicEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
|
publicEncryptionKey = ('\x04').encode() + data[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
_, specifiedNonceTrialsPerByteLength = decodeVarint(
|
_, specifiedNonceTrialsPerByteLength = decodeVarint(
|
||||||
data[readPosition:readPosition + 10])
|
data[readPosition:readPosition + 10])
|
||||||
|
@ -385,9 +383,9 @@ class objectProcessor(threading.Thread):
|
||||||
signatureLength, signatureLengthLength = decodeVarint(
|
signatureLength, signatureLengthLength = decodeVarint(
|
||||||
data[readPosition:readPosition + 10])
|
data[readPosition:readPosition + 10])
|
||||||
readPosition += signatureLengthLength
|
readPosition += signatureLengthLength
|
||||||
signature = data[readPosition:readPosition + signatureLength]
|
signature = bytes(data[readPosition:readPosition + signatureLength])
|
||||||
if highlevelcrypto.verify(
|
if highlevelcrypto.verify(
|
||||||
data[8:endOfSignedDataPosition],
|
bytes(data[8:endOfSignedDataPosition]),
|
||||||
signature, hexlify(publicSigningKey)):
|
signature, hexlify(publicSigningKey)):
|
||||||
logger.debug('ECDSA verify passed (within processpubkey)')
|
logger.debug('ECDSA verify passed (within processpubkey)')
|
||||||
else:
|
else:
|
||||||
|
@ -435,14 +433,14 @@ class objectProcessor(threading.Thread):
|
||||||
return
|
return
|
||||||
|
|
||||||
tag = data[readPosition:readPosition + 32]
|
tag = data[readPosition:readPosition + 32]
|
||||||
if tag not in state.neededPubkeys:
|
if bytes(tag) not in state.neededPubkeys:
|
||||||
logger.info(
|
logger.info(
|
||||||
'We don\'t need this v4 pubkey. We didn\'t ask for it.')
|
'We don\'t need this v4 pubkey. We didn\'t ask for it.')
|
||||||
return
|
return
|
||||||
|
|
||||||
# Let us try to decrypt the pubkey
|
# Let us try to decrypt the pubkey
|
||||||
toAddress, _ = state.neededPubkeys[tag]
|
toAddress, _ = state.neededPubkeys[bytes(tag)] #check with py2
|
||||||
if protocol.decryptAndCheckPubkeyPayload(data, toAddress) == \
|
if protocol.decryptAndCheckPubkeyPayload(bytes(data), toAddress) == \
|
||||||
'successful':
|
'successful':
|
||||||
# At this point we know that we have been waiting on this
|
# At this point we know that we have been waiting on this
|
||||||
# pubkey. This function will command the workerThread
|
# pubkey. This function will command the workerThread
|
||||||
|
@ -480,16 +478,15 @@ class objectProcessor(threading.Thread):
|
||||||
|
|
||||||
# This is not an acknowledgement bound for me. See if it is a message
|
# This is not an acknowledgement bound for me. See if it is a message
|
||||||
# bound for me by trying to decrypt it with my private keys.
|
# bound for me by trying to decrypt it with my private keys.
|
||||||
|
|
||||||
for key, cryptorObject in sorted(
|
for key, cryptorObject in sorted(
|
||||||
shared.myECCryptorObjects.items(),
|
shared.myECCryptorObjects.items(),
|
||||||
key=lambda x: random.random()):
|
key=lambda x: random.random()):
|
||||||
try:
|
try:
|
||||||
# continue decryption attempts to avoid timing attacks
|
# continue decryption attempts to avoid timing attacks
|
||||||
if initialDecryptionSuccessful:
|
if initialDecryptionSuccessful:
|
||||||
cryptorObject.decrypt(data[readPosition:])
|
cryptorObject.decrypt(bytes(data[readPosition:]))
|
||||||
else:
|
else:
|
||||||
decryptedData = cryptorObject.decrypt(data[readPosition:])
|
decryptedData = cryptorObject.decrypt(bytes(data[readPosition:]))
|
||||||
# This is the RIPE hash of my pubkeys. We need this
|
# This is the RIPE hash of my pubkeys. We need this
|
||||||
# below to compare to the destination_ripe included
|
# below to compare to the destination_ripe included
|
||||||
# in the encrypted data.
|
# in the encrypted data.
|
||||||
|
@ -537,9 +534,9 @@ class objectProcessor(threading.Thread):
|
||||||
return
|
return
|
||||||
readPosition += sendersStreamNumberLength
|
readPosition += sendersStreamNumberLength
|
||||||
readPosition += 4
|
readPosition += 4
|
||||||
pubSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
pubSigningKey = '\x04'.encode() + decryptedData[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
pubEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
pubEncryptionKey = '\x04'.encode() + decryptedData[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
if sendersAddressVersionNumber >= 3:
|
if sendersAddressVersionNumber >= 3:
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = \
|
requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = \
|
||||||
|
@ -590,7 +587,7 @@ class objectProcessor(threading.Thread):
|
||||||
readPosition += signatureLengthLength
|
readPosition += signatureLengthLength
|
||||||
signature = decryptedData[
|
signature = decryptedData[
|
||||||
readPosition:readPosition + signatureLength]
|
readPosition:readPosition + signatureLength]
|
||||||
signedData = data[8:20] + encodeVarint(1) + encodeVarint(
|
signedData = bytes(data[8:20]) + encodeVarint(1) + encodeVarint(
|
||||||
streamNumberAsClaimedByMsg
|
streamNumberAsClaimedByMsg
|
||||||
) + decryptedData[:positionOfBottomOfAckData]
|
) + decryptedData[:positionOfBottomOfAckData]
|
||||||
|
|
||||||
|
@ -636,7 +633,6 @@ class objectProcessor(threading.Thread):
|
||||||
# pubkey in order to send a message. If we are, it will do the POW
|
# pubkey in order to send a message. If we are, it will do the POW
|
||||||
# and send it.
|
# and send it.
|
||||||
self.possibleNewPubkey(fromAddress)
|
self.possibleNewPubkey(fromAddress)
|
||||||
|
|
||||||
# If this message is bound for one of my version 3 addresses (or
|
# If this message is bound for one of my version 3 addresses (or
|
||||||
# higher), then we must check to make sure it meets our demanded
|
# higher), then we must check to make sure it meets our demanded
|
||||||
# proof of work requirement. If this is bound for one of my chan
|
# proof of work requirement. If this is bound for one of my chan
|
||||||
|
@ -649,10 +645,10 @@ class objectProcessor(threading.Thread):
|
||||||
# If I'm not friendly with this person:
|
# If I'm not friendly with this person:
|
||||||
if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(
|
if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(
|
||||||
fromAddress):
|
fromAddress):
|
||||||
requiredNonceTrialsPerByte = BMConfigParser().getint(
|
requiredNonceTrialsPerByte = int(BMConfigParser().get(
|
||||||
toAddress, 'noncetrialsperbyte')
|
toAddress, 'noncetrialsperbyte'))
|
||||||
requiredPayloadLengthExtraBytes = BMConfigParser().getint(
|
requiredPayloadLengthExtraBytes = int(BMConfigParser().get(
|
||||||
toAddress, 'payloadlengthextrabytes')
|
toAddress, 'payloadlengthextrabytes'))
|
||||||
if not protocol.isProofOfWorkSufficient(
|
if not protocol.isProofOfWorkSufficient(
|
||||||
data, requiredNonceTrialsPerByte,
|
data, requiredNonceTrialsPerByte,
|
||||||
requiredPayloadLengthExtraBytes):
|
requiredPayloadLengthExtraBytes):
|
||||||
|
@ -685,7 +681,6 @@ class objectProcessor(threading.Thread):
|
||||||
toLabel = BMConfigParser().get(toAddress, 'label')
|
toLabel = BMConfigParser().get(toAddress, 'label')
|
||||||
if toLabel == '':
|
if toLabel == '':
|
||||||
toLabel = toAddress
|
toLabel = toAddress
|
||||||
|
|
||||||
try:
|
try:
|
||||||
decodedMessage = helper_msgcoding.MsgDecode(
|
decodedMessage = helper_msgcoding.MsgDecode(
|
||||||
messageEncodingType, message)
|
messageEncodingType, message)
|
||||||
|
@ -868,7 +863,7 @@ class objectProcessor(threading.Thread):
|
||||||
elif broadcastVersion == 5:
|
elif broadcastVersion == 5:
|
||||||
embeddedTag = data[readPosition:readPosition + 32]
|
embeddedTag = data[readPosition:readPosition + 32]
|
||||||
readPosition += 32
|
readPosition += 32
|
||||||
if embeddedTag not in shared.MyECSubscriptionCryptorObjects:
|
if bytes(embeddedTag) not in shared.MyECSubscriptionCryptorObjects:
|
||||||
logger.debug('We\'re not interested in this broadcast.')
|
logger.debug('We\'re not interested in this broadcast.')
|
||||||
return
|
return
|
||||||
# We are interested in this broadcast because of its tag.
|
# We are interested in this broadcast because of its tag.
|
||||||
|
@ -1122,8 +1117,8 @@ class objectProcessor(threading.Thread):
|
||||||
if checksum != hashlib.sha512(payload).digest()[0:4]:
|
if checksum != hashlib.sha512(payload).digest()[0:4]:
|
||||||
logger.info('ackdata checksum wrong. Not sending ackdata.')
|
logger.info('ackdata checksum wrong. Not sending ackdata.')
|
||||||
return False
|
return False
|
||||||
command = command.rstrip('\x00')
|
command = command.rstrip('\x00'.encode())
|
||||||
if command != 'object':
|
if command != 'object'.encode():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,8 @@ import tr
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from helper_sql import sqlExecute, sqlQuery
|
from helper_sql import sqlExecute, sqlQuery
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network import BMConnectionPool, StoppableThread
|
from network.connectionpool import BMConnectionPool
|
||||||
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class singleCleaner(StoppableThread):
|
class singleCleaner(StoppableThread):
|
||||||
|
@ -136,6 +137,7 @@ class singleCleaner(StoppableThread):
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
# inv/object tracking
|
# inv/object tracking
|
||||||
|
|
||||||
for connection in BMConnectionPool().connections():
|
for connection in BMConnectionPool().connections():
|
||||||
connection.clean()
|
connection.clean()
|
||||||
|
|
||||||
|
@ -199,6 +201,10 @@ def deleteTrashMsgPermonantly():
|
||||||
"""This method is used to delete old messages"""
|
"""This method is used to delete old messages"""
|
||||||
ndays_before_time = datetime.now() - timedelta(days=30)
|
ndays_before_time = datetime.now() - timedelta(days=30)
|
||||||
old_messages = time.mktime(ndays_before_time.timetuple())
|
old_messages = time.mktime(ndays_before_time.timetuple())
|
||||||
sqlExecute("delete from sent where folder = 'trash' and lastactiontime <= ?;", int(old_messages))
|
sqlExecute(
|
||||||
sqlExecute("delete from inbox where folder = 'trash' and received <= ?;", int(old_messages))
|
"delete from sent where folder = 'trash' and lastactiontime <= ?;",
|
||||||
|
int(old_messages))
|
||||||
|
sqlExecute(
|
||||||
|
"delete from inbox where folder = 'trash' and received <= ?;",
|
||||||
|
int(old_messages))
|
||||||
return
|
return
|
||||||
|
|
|
@ -28,10 +28,11 @@ import tr
|
||||||
from addresses import (
|
from addresses import (
|
||||||
calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint
|
calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint
|
||||||
)
|
)
|
||||||
|
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from helper_sql import sqlExecute, sqlQuery
|
from helper_sql import sqlExecute, sqlQuery
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
# This thread, of which there is only one, does the heavy lifting:
|
# This thread, of which there is only one, does the heavy lifting:
|
||||||
# calculating POWs.
|
# calculating POWs.
|
||||||
|
@ -227,6 +228,7 @@ class singleWorker(StoppableThread):
|
||||||
if log_time:
|
if log_time:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
|
print("nonce calculated value#############################", nonce)
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'%s Found proof of work %s Nonce: %s',
|
'%s Found proof of work %s Nonce: %s',
|
||||||
log_prefix, trialValue, nonce
|
log_prefix, trialValue, nonce
|
||||||
|
@ -400,7 +402,7 @@ class singleWorker(StoppableThread):
|
||||||
TTL = int(28 * 24 * 60 * 60 + helper_random.randomrandrange(-300, 300))
|
TTL = int(28 * 24 * 60 * 60 + helper_random.randomrandrange(-300, 300))
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
payload = pack('>Q', (embeddedTime))
|
payload = pack('>Q', (embeddedTime))
|
||||||
payload += '\x00\x00\x00\x01' # object type: pubkey
|
payload += '\x00\x00\x00\x01'.encode() # object type: pubkey
|
||||||
payload += encodeVarint(addressVersionNumber) # Address version number
|
payload += encodeVarint(addressVersionNumber) # Address version number
|
||||||
payload += encodeVarint(streamNumber)
|
payload += encodeVarint(streamNumber)
|
||||||
dataToEncrypt = protocol.getBitfield(myAddress)
|
dataToEncrypt = protocol.getBitfield(myAddress)
|
||||||
|
@ -419,10 +421,10 @@ class singleWorker(StoppableThread):
|
||||||
|
|
||||||
dataToEncrypt += pubSigningKey + pubEncryptionKey
|
dataToEncrypt += pubSigningKey + pubEncryptionKey
|
||||||
|
|
||||||
dataToEncrypt += encodeVarint(BMConfigParser().getint(
|
dataToEncrypt += encodeVarint(int(BMConfigParser().get(
|
||||||
myAddress, 'noncetrialsperbyte'))
|
myAddress, 'noncetrialsperbyte')))
|
||||||
dataToEncrypt += encodeVarint(BMConfigParser().getint(
|
dataToEncrypt += encodeVarint(int(BMConfigParser().get(
|
||||||
myAddress, 'payloadlengthextrabytes'))
|
myAddress, 'payloadlengthextrabytes')))
|
||||||
|
|
||||||
# When we encrypt, we'll use a hash of the data
|
# When we encrypt, we'll use a hash of the data
|
||||||
# contained in an address as a decryption key. This way
|
# contained in an address as a decryption key. This way
|
||||||
|
@ -453,7 +455,7 @@ class singleWorker(StoppableThread):
|
||||||
|
|
||||||
inventoryHash = calculateInventoryHash(payload)
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
objectType = 1
|
objectType = 1
|
||||||
Inventory()[inventoryHash] = (
|
Inventory()._realInventory[inventoryHash] = (
|
||||||
objectType, streamNumber, payload, embeddedTime,
|
objectType, streamNumber, payload, embeddedTime,
|
||||||
doubleHashOfAddressData[32:]
|
doubleHashOfAddressData[32:]
|
||||||
)
|
)
|
||||||
|
@ -809,7 +811,6 @@ class singleWorker(StoppableThread):
|
||||||
highlevelcrypto.makeCryptor(
|
highlevelcrypto.makeCryptor(
|
||||||
hexlify(privEncryptionKey))
|
hexlify(privEncryptionKey))
|
||||||
)
|
)
|
||||||
|
|
||||||
for value in Inventory().by_type_and_tag(1, toTag):
|
for value in Inventory().by_type_and_tag(1, toTag):
|
||||||
# if valid, this function also puts it
|
# if valid, this function also puts it
|
||||||
# in the pubkeys table.
|
# in the pubkeys table.
|
||||||
|
@ -855,17 +856,14 @@ class singleWorker(StoppableThread):
|
||||||
self.requestPubKey(toaddress)
|
self.requestPubKey(toaddress)
|
||||||
# on with the next msg on which we can do some work
|
# on with the next msg on which we can do some work
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# At this point we know that we have the necessary pubkey
|
# At this point we know that we have the necessary pubkey
|
||||||
# in the pubkeys table.
|
# in the pubkeys table.
|
||||||
|
|
||||||
TTL *= 2**retryNumber
|
TTL *= 2**retryNumber
|
||||||
if TTL > 28 * 24 * 60 * 60:
|
if TTL > 28 * 24 * 60 * 60:
|
||||||
TTL = 28 * 24 * 60 * 60
|
TTL = 28 * 24 * 60 * 60
|
||||||
# add some randomness to the TTL
|
# add some randomness to the TTL
|
||||||
TTL = int(TTL + helper_random.randomrandrange(-300, 300))
|
TTL = int(TTL + helper_random.randomrandrange(-300, 300))
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
|
|
||||||
# if we aren't sending this to ourselves or a chan
|
# if we aren't sending this to ourselves or a chan
|
||||||
if not BMConfigParser().has_section(toaddress):
|
if not BMConfigParser().has_section(toaddress):
|
||||||
shared.ackdataForWhichImWatching[ackdata] = 0
|
shared.ackdataForWhichImWatching[ackdata] = 0
|
||||||
|
@ -877,14 +875,15 @@ class singleWorker(StoppableThread):
|
||||||
"Looking up the receiver\'s public key"))
|
"Looking up the receiver\'s public key"))
|
||||||
))
|
))
|
||||||
self.logger.info('Sending a message.')
|
self.logger.info('Sending a message.')
|
||||||
self.logger.debug(
|
# self.logger.debug(
|
||||||
'First 150 characters of message: %s',
|
# 'First 150 characters of message: %s',
|
||||||
repr(message[:150])
|
# repr(message[:150])
|
||||||
)
|
# )
|
||||||
|
|
||||||
# Let us fetch the recipient's public key out of
|
# Let us fetch the recipient's public key out of
|
||||||
# our database. If the required proof of work difficulty
|
# our database. If the required proof of work difficulty
|
||||||
# is too hard then we'll abort.
|
# is too hard then we'll abort.
|
||||||
|
|
||||||
queryreturn = sqlQuery(
|
queryreturn = sqlQuery(
|
||||||
'SELECT transmitdata FROM pubkeys WHERE address=?',
|
'SELECT transmitdata FROM pubkeys WHERE address=?',
|
||||||
toaddress)
|
toaddress)
|
||||||
|
@ -951,7 +950,6 @@ class singleWorker(StoppableThread):
|
||||||
pubEncryptionKeyBase256 = pubkeyPayload[
|
pubEncryptionKeyBase256 = pubkeyPayload[
|
||||||
readPosition:readPosition + 64]
|
readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
|
|
||||||
# Let us fetch the amount of work required by the recipient.
|
# Let us fetch the amount of work required by the recipient.
|
||||||
if toAddressVersionNumber == 2:
|
if toAddressVersionNumber == 2:
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte = \
|
requiredAverageProofOfWorkNonceTrialsPerByte = \
|
||||||
|
@ -967,6 +965,7 @@ class singleWorker(StoppableThread):
|
||||||
"There is no required difficulty for"
|
"There is no required difficulty for"
|
||||||
" version 2 addresses like this."))
|
" version 2 addresses like this."))
|
||||||
))
|
))
|
||||||
|
|
||||||
elif toAddressVersionNumber >= 3:
|
elif toAddressVersionNumber >= 3:
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte, \
|
requiredAverageProofOfWorkNonceTrialsPerByte, \
|
||||||
varintLength = decodeVarint(
|
varintLength = decodeVarint(
|
||||||
|
@ -993,7 +992,6 @@ class singleWorker(StoppableThread):
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte,
|
requiredAverageProofOfWorkNonceTrialsPerByte,
|
||||||
requiredPayloadLengthExtraBytes
|
requiredPayloadLengthExtraBytes
|
||||||
)
|
)
|
||||||
|
|
||||||
queues.UISignalQueue.put(
|
queues.UISignalQueue.put(
|
||||||
(
|
(
|
||||||
'updateSentItemStatusByAckdata',
|
'updateSentItemStatusByAckdata',
|
||||||
|
@ -1018,17 +1016,15 @@ class singleWorker(StoppableThread):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if status != 'forcepow':
|
if status != 'forcepow':
|
||||||
maxacceptablenoncetrialsperbyte = BMConfigParser().getint(
|
maxacceptablenoncetrialsperbyte = int(BMConfigParser().get(
|
||||||
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte')
|
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte'))
|
||||||
maxacceptablepayloadlengthextrabytes = BMConfigParser().getint(
|
maxacceptablepayloadlengthextrabytes = int(BMConfigParser().get(
|
||||||
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')
|
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes'))
|
||||||
cond1 = maxacceptablenoncetrialsperbyte and \
|
cond1 = maxacceptablenoncetrialsperbyte and \
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte > maxacceptablenoncetrialsperbyte
|
requiredAverageProofOfWorkNonceTrialsPerByte > maxacceptablenoncetrialsperbyte
|
||||||
cond2 = maxacceptablepayloadlengthextrabytes and \
|
cond2 = maxacceptablepayloadlengthextrabytes and \
|
||||||
requiredPayloadLengthExtraBytes > maxacceptablepayloadlengthextrabytes
|
requiredPayloadLengthExtraBytes > maxacceptablepayloadlengthextrabytes
|
||||||
|
|
||||||
if cond1 or cond2:
|
if cond1 or cond2:
|
||||||
# The demanded difficulty is more than
|
# The demanded difficulty is more than
|
||||||
# we are willing to do.
|
# we are willing to do.
|
||||||
|
@ -1056,7 +1052,6 @@ class singleWorker(StoppableThread):
|
||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
'First 150 characters of message: %r', message[:150])
|
'First 150 characters of message: %r', message[:150])
|
||||||
behaviorBitfield = protocol.getBitfield(fromaddress)
|
behaviorBitfield = protocol.getBitfield(fromaddress)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
privEncryptionKeyBase58 = BMConfigParser().get(
|
privEncryptionKeyBase58 = BMConfigParser().get(
|
||||||
toaddress, 'privencryptionkey')
|
toaddress, 'privencryptionkey')
|
||||||
|
@ -1093,7 +1088,6 @@ class singleWorker(StoppableThread):
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Doing work necessary to send message."))
|
"Doing work necessary to send message."))
|
||||||
))
|
))
|
||||||
|
|
||||||
# Now we can start to assemble our message.
|
# Now we can start to assemble our message.
|
||||||
payload = encodeVarint(fromAddressVersionNumber)
|
payload = encodeVarint(fromAddressVersionNumber)
|
||||||
payload += encodeVarint(fromStreamNumber)
|
payload += encodeVarint(fromStreamNumber)
|
||||||
|
@ -1101,7 +1095,6 @@ class singleWorker(StoppableThread):
|
||||||
# that can be expected from me. (See
|
# that can be expected from me. (See
|
||||||
# https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features)
|
# https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features)
|
||||||
payload += protocol.getBitfield(fromaddress)
|
payload += protocol.getBitfield(fromaddress)
|
||||||
|
|
||||||
# We need to convert our private keys to public keys in order
|
# We need to convert our private keys to public keys in order
|
||||||
# to include them.
|
# to include them.
|
||||||
try:
|
try:
|
||||||
|
@ -1118,9 +1111,7 @@ class singleWorker(StoppableThread):
|
||||||
" (your address) in the keys.dat file."))
|
" (your address) in the keys.dat file."))
|
||||||
))
|
))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
payload += pubSigningKey + pubEncryptionKey
|
payload += pubSigningKey + pubEncryptionKey
|
||||||
|
|
||||||
if fromAddressVersionNumber >= 3:
|
if fromAddressVersionNumber >= 3:
|
||||||
# If the receiver of our message is in our address book,
|
# If the receiver of our message is in our address book,
|
||||||
# subscriptions list, or whitelist then we will allow them to
|
# subscriptions list, or whitelist then we will allow them to
|
||||||
|
@ -1133,11 +1124,10 @@ class singleWorker(StoppableThread):
|
||||||
payload += encodeVarint(
|
payload += encodeVarint(
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes)
|
defaults.networkDefaultPayloadLengthExtraBytes)
|
||||||
else:
|
else:
|
||||||
payload += encodeVarint(BMConfigParser().getint(
|
payload += encodeVarint(int(BMConfigParser().get(
|
||||||
fromaddress, 'noncetrialsperbyte'))
|
fromaddress, 'noncetrialsperbyte')))
|
||||||
payload += encodeVarint(BMConfigParser().getint(
|
payload += encodeVarint(int(BMConfigParser().get(
|
||||||
fromaddress, 'payloadlengthextrabytes'))
|
fromaddress, 'payloadlengthextrabytes')))
|
||||||
|
|
||||||
# This hash will be checked by the receiver of the message
|
# This hash will be checked by the receiver of the message
|
||||||
# to verify that toRipe belongs to them. This prevents
|
# to verify that toRipe belongs to them. This prevents
|
||||||
# a Surreptitious Forwarding Attack.
|
# a Surreptitious Forwarding Attack.
|
||||||
|
@ -1168,8 +1158,8 @@ class singleWorker(StoppableThread):
|
||||||
fullAckPayload = self.generateFullAckMessage(
|
fullAckPayload = self.generateFullAckMessage(
|
||||||
ackdata, toStreamNumber, TTL)
|
ackdata, toStreamNumber, TTL)
|
||||||
payload += encodeVarint(len(fullAckPayload))
|
payload += encodeVarint(len(fullAckPayload))
|
||||||
payload += fullAckPayload
|
payload += fullAckPayload if isinstance(fullAckPayload,bytes) else fullAckPayload.encode()
|
||||||
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + \
|
dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02'.encode() + \
|
||||||
encodeVarint(1) + encodeVarint(toStreamNumber) + payload
|
encodeVarint(1) + encodeVarint(toStreamNumber) + payload
|
||||||
signature = highlevelcrypto.sign(dataToSign, privSigningKeyHex)
|
signature = highlevelcrypto.sign(dataToSign, privSigningKeyHex)
|
||||||
payload += encodeVarint(len(signature))
|
payload += encodeVarint(len(signature))
|
||||||
|
@ -1178,7 +1168,7 @@ class singleWorker(StoppableThread):
|
||||||
# We have assembled the data that will be encrypted.
|
# We have assembled the data that will be encrypted.
|
||||||
try:
|
try:
|
||||||
encrypted = highlevelcrypto.encrypt(
|
encrypted = highlevelcrypto.encrypt(
|
||||||
payload, "04" + hexlify(pubEncryptionKeyBase256)
|
payload, "04".encode() + hexlify(pubEncryptionKeyBase256)
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
|
@ -1195,9 +1185,8 @@ class singleWorker(StoppableThread):
|
||||||
).arg(l10n.formatTimestamp()))
|
).arg(l10n.formatTimestamp()))
|
||||||
))
|
))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
encryptedPayload = pack('>Q', embeddedTime)
|
encryptedPayload = pack('>Q', embeddedTime)
|
||||||
encryptedPayload += '\x00\x00\x00\x02' # object type: msg
|
encryptedPayload += '\x00\x00\x00\x02'.encode() # object type: msg
|
||||||
encryptedPayload += encodeVarint(1) # msg version
|
encryptedPayload += encodeVarint(1) # msg version
|
||||||
encryptedPayload += encodeVarint(toStreamNumber) + encrypted
|
encryptedPayload += encodeVarint(toStreamNumber) + encrypted
|
||||||
target = 2 ** 64 / (
|
target = 2 ** 64 / (
|
||||||
|
@ -1211,17 +1200,16 @@ class singleWorker(StoppableThread):
|
||||||
))
|
))
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'(For msg message) Doing proof of work. Total required'
|
'(For msg message) Doing proof of work. Total required'
|
||||||
' difficulty: %f. Required small message difficulty: %f.',
|
' difficulty: {}. Required small message difficulty: {}.'.format
|
||||||
float(requiredAverageProofOfWorkNonceTrialsPerByte) /
|
(float(requiredAverageProofOfWorkNonceTrialsPerByte) /
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
float(requiredPayloadLengthExtraBytes) /
|
float(requiredPayloadLengthExtraBytes) /
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes
|
defaults.networkDefaultPayloadLengthExtraBytes)
|
||||||
)
|
)
|
||||||
|
|
||||||
powStartTime = time.time()
|
powStartTime = time.time()
|
||||||
initialHash = hashlib.sha512(encryptedPayload).digest()
|
initialHash = hashlib.sha512(encryptedPayload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
print("nonce calculated value#############################", nonce)
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'(For msg message) Found proof of work %s Nonce: %s',
|
'(For msg message) Found proof of work %s Nonce: %s',
|
||||||
trialValue, nonce
|
trialValue, nonce
|
||||||
|
@ -1234,7 +1222,6 @@ class singleWorker(StoppableThread):
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
encryptedPayload = pack('>Q', nonce) + encryptedPayload
|
encryptedPayload = pack('>Q', nonce) + encryptedPayload
|
||||||
|
|
||||||
# Sanity check. The encryptedPayload size should never be
|
# Sanity check. The encryptedPayload size should never be
|
||||||
|
@ -1248,10 +1235,11 @@ class singleWorker(StoppableThread):
|
||||||
len(encryptedPayload)
|
len(encryptedPayload)
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
inventoryHash = calculateInventoryHash(encryptedPayload)
|
inventoryHash = calculateInventoryHash(encryptedPayload)
|
||||||
objectType = 2
|
objectType = 2
|
||||||
Inventory()[inventoryHash] = (
|
inventoryHashlist = (
|
||||||
|
objectType, toStreamNumber,encryptedPayload, embeddedTime, '')
|
||||||
|
Inventory()._realInventory[inventoryHash] = (
|
||||||
objectType, toStreamNumber, encryptedPayload, embeddedTime, '')
|
objectType, toStreamNumber, encryptedPayload, embeddedTime, '')
|
||||||
if BMConfigParser().has_section(toaddress) or \
|
if BMConfigParser().has_section(toaddress) or \
|
||||||
not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK):
|
not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK):
|
||||||
|
@ -1260,7 +1248,7 @@ class singleWorker(StoppableThread):
|
||||||
ackdata,
|
ackdata,
|
||||||
tr._translate(
|
tr._translate(
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Message sent. Sent at %1"
|
"Mobileessage sent. Sent at %1"
|
||||||
).arg(l10n.formatTimestamp()))))
|
).arg(l10n.formatTimestamp()))))
|
||||||
else:
|
else:
|
||||||
# not sending to a chan or one of my addresses
|
# not sending to a chan or one of my addresses
|
||||||
|
@ -1278,7 +1266,6 @@ class singleWorker(StoppableThread):
|
||||||
hexlify(inventoryHash)
|
hexlify(inventoryHash)
|
||||||
)
|
)
|
||||||
queues.invQueue.put((toStreamNumber, inventoryHash))
|
queues.invQueue.put((toStreamNumber, inventoryHash))
|
||||||
|
|
||||||
# Update the sent message in the sent table with the
|
# Update the sent message in the sent table with the
|
||||||
# necessary information.
|
# necessary information.
|
||||||
if BMConfigParser().has_section(toaddress) or \
|
if BMConfigParser().has_section(toaddress) or \
|
||||||
|
@ -1294,7 +1281,6 @@ class singleWorker(StoppableThread):
|
||||||
inventoryHash, newStatus, retryNumber + 1,
|
inventoryHash, newStatus, retryNumber + 1,
|
||||||
sleepTill, int(time.time()), ackdata
|
sleepTill, int(time.time()), ackdata
|
||||||
)
|
)
|
||||||
|
|
||||||
# If we are sending to ourselves or a chan, let's put
|
# If we are sending to ourselves or a chan, let's put
|
||||||
# the message in our own inbox.
|
# the message in our own inbox.
|
||||||
if BMConfigParser().has_section(toaddress):
|
if BMConfigParser().has_section(toaddress):
|
||||||
|
@ -1332,7 +1318,6 @@ class singleWorker(StoppableThread):
|
||||||
toAddress
|
toAddress
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
queryReturn = sqlQuery(
|
queryReturn = sqlQuery(
|
||||||
'''SELECT retrynumber FROM sent WHERE toaddress=? '''
|
'''SELECT retrynumber FROM sent WHERE toaddress=? '''
|
||||||
''' AND (status='doingpubkeypow' OR status='awaitingpubkey') '''
|
''' AND (status='doingpubkeypow' OR status='awaitingpubkey') '''
|
||||||
|
@ -1347,7 +1332,6 @@ class singleWorker(StoppableThread):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
retryNumber = queryReturn[0][0]
|
retryNumber = queryReturn[0][0]
|
||||||
|
|
||||||
if addressVersionNumber <= 3:
|
if addressVersionNumber <= 3:
|
||||||
state.neededPubkeys[toAddress] = 0
|
state.neededPubkeys[toAddress] = 0
|
||||||
elif addressVersionNumber >= 4:
|
elif addressVersionNumber >= 4:
|
||||||
|
@ -1383,7 +1367,7 @@ class singleWorker(StoppableThread):
|
||||||
TTL = TTL + helper_random.randomrandrange(-300, 300)
|
TTL = TTL + helper_random.randomrandrange(-300, 300)
|
||||||
embeddedTime = int(time.time() + TTL)
|
embeddedTime = int(time.time() + TTL)
|
||||||
payload = pack('>Q', embeddedTime)
|
payload = pack('>Q', embeddedTime)
|
||||||
payload += '\x00\x00\x00\x00' # object type: getpubkey
|
payload += '\x00\x00\x00\x00'.encode() # object type: getpubkey
|
||||||
payload += encodeVarint(addressVersionNumber)
|
payload += encodeVarint(addressVersionNumber)
|
||||||
payload += encodeVarint(streamNumber)
|
payload += encodeVarint(streamNumber)
|
||||||
if addressVersionNumber <= 3:
|
if addressVersionNumber <= 3:
|
||||||
|
@ -1406,16 +1390,14 @@ class singleWorker(StoppableThread):
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Doing work necessary to request encryption key."))
|
"Doing work necessary to request encryption key."))
|
||||||
))
|
))
|
||||||
|
|
||||||
payload = self._doPOWDefaults(payload, TTL)
|
payload = self._doPOWDefaults(payload, TTL)
|
||||||
|
|
||||||
inventoryHash = calculateInventoryHash(payload)
|
inventoryHash = calculateInventoryHash(payload)
|
||||||
objectType = 1
|
objectType = 1
|
||||||
Inventory()[inventoryHash] = (
|
Inventory()._realInventory[inventoryHash] = (
|
||||||
objectType, streamNumber, payload, embeddedTime, '')
|
objectType, streamNumber, payload, embeddedTime, '')
|
||||||
|
# Inventory()._realInventory[inventoryHashlist]
|
||||||
self.logger.info('sending inv (for the getpubkey message)')
|
self.logger.info('sending inv (for the getpubkey message)')
|
||||||
queues.invQueue.put((streamNumber, inventoryHash))
|
queues.invQueue.put((streamNumber, inventoryHash))
|
||||||
|
|
||||||
# wait 10% past expiration
|
# wait 10% past expiration
|
||||||
sleeptill = int(time.time() + TTL * 1.1)
|
sleeptill = int(time.time() + TTL * 1.1)
|
||||||
sqlExecute(
|
sqlExecute(
|
||||||
|
@ -1424,7 +1406,6 @@ class singleWorker(StoppableThread):
|
||||||
''' WHERE toaddress=? AND (status='doingpubkeypow' OR '''
|
''' WHERE toaddress=? AND (status='doingpubkeypow' OR '''
|
||||||
''' status='awaitingpubkey') ''',
|
''' status='awaitingpubkey') ''',
|
||||||
int(time.time()), retryNumber + 1, sleeptill, toAddress)
|
int(time.time()), retryNumber + 1, sleeptill, toAddress)
|
||||||
|
|
||||||
queues.UISignalQueue.put((
|
queues.UISignalQueue.put((
|
||||||
'updateStatusBar',
|
'updateStatusBar',
|
||||||
tr._translate(
|
tr._translate(
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
SMTP client thread for delivering emails
|
SMTP client thread for delivering emails
|
||||||
"""
|
"""
|
||||||
# pylint: disable=unused-variable
|
# pylint: disable=unused-variable
|
||||||
|
|
||||||
import smtplib
|
import smtplib
|
||||||
import urlparse
|
import urlparse
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
@ -51,10 +50,12 @@ class smtpDeliver(StoppableThread):
|
||||||
ackData, message = data
|
ackData, message = data
|
||||||
elif command == 'displayNewInboxMessage':
|
elif command == 'displayNewInboxMessage':
|
||||||
inventoryHash, toAddress, fromAddress, subject, body = data
|
inventoryHash, toAddress, fromAddress, subject, body = data
|
||||||
dest = BMConfigParser().safeGet("bitmessagesettings", "smtpdeliver", '')
|
dest = BMConfigParser().safeGet(
|
||||||
|
"bitmessagesettings", "smtpdeliver", '')
|
||||||
if dest == '':
|
if dest == '':
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
|
# pylint: disable=deprecated-lambda
|
||||||
u = urlparse.urlparse(dest)
|
u = urlparse.urlparse(dest)
|
||||||
to = urlparse.parse_qs(u.query)['to']
|
to = urlparse.parse_qs(u.query)['to']
|
||||||
client = smtplib.SMTP(u.hostname, u.port)
|
client = smtplib.SMTP(u.hostname, u.port)
|
||||||
|
@ -67,7 +68,9 @@ class smtpDeliver(StoppableThread):
|
||||||
lambda x: x == toAddress, BMConfigParser().addresses())
|
lambda x: x == toAddress, BMConfigParser().addresses())
|
||||||
)
|
)
|
||||||
if toLabel:
|
if toLabel:
|
||||||
msg['To'] = "\"%s\" <%s>" % (Header(toLabel[0], 'utf-8'), toAddress + '@' + SMTPDOMAIN)
|
msg['To'] = "\"%s\" <%s>" % (
|
||||||
|
Header(toLabel[0], 'utf-8'),
|
||||||
|
toAddress + '@' + SMTPDOMAIN)
|
||||||
else:
|
else:
|
||||||
msg['To'] = toAddress + '@' + SMTPDOMAIN
|
msg['To'] = toAddress + '@' + SMTPDOMAIN
|
||||||
client.ehlo()
|
client.ehlo()
|
||||||
|
@ -81,7 +84,8 @@ class smtpDeliver(StoppableThread):
|
||||||
except:
|
except:
|
||||||
self.logger.error('smtp delivery error', exc_info=True)
|
self.logger.error('smtp delivery error', exc_info=True)
|
||||||
elif command == 'displayNewSentMessage':
|
elif command == 'displayNewSentMessage':
|
||||||
toAddress, fromLabel, fromAddress, subject, message, ackdata = data
|
toAddress, fromLabel, fromAddress, subject, message, ackdata = \
|
||||||
|
data
|
||||||
elif command == 'updateNetworkStatusTab':
|
elif command == 'updateNetworkStatusTab':
|
||||||
pass
|
pass
|
||||||
elif command == 'updateNumberOfMessagesProcessed':
|
elif command == 'updateNumberOfMessagesProcessed':
|
||||||
|
|
|
@ -82,9 +82,11 @@ class sqlThread(threading.Thread):
|
||||||
# If the settings version is equal to 2 or 3 then the
|
# If the settings version is equal to 2 or 3 then the
|
||||||
# sqlThread will modify the pubkeys table and change
|
# sqlThread will modify the pubkeys table and change
|
||||||
# the settings version to 4.
|
# the settings version to 4.
|
||||||
settingsversion = BMConfigParser().getint(
|
# settingsversion = BMConfigParser().getint('bitmessagesettings', 'settingsversion')
|
||||||
'bitmessagesettings', 'settingsversion')
|
# In the Python3 I am below condition converting into int
|
||||||
|
# settingsversion = int(BMConfigParser().get('bitmessagesettings', 'settingsversion') \
|
||||||
|
# if BMConfigParser().get('bitmessagesettings', 'settingsversion') else 0)
|
||||||
|
settingsversion = BMConfigParser().safeGetInt('bitmessagesettings', 'settingsvesion')
|
||||||
# People running earlier versions of PyBitmessage do not have the
|
# People running earlier versions of PyBitmessage do not have the
|
||||||
# usedpersonally field in their pubkeys table. Let's add it.
|
# usedpersonally field in their pubkeys table. Let's add it.
|
||||||
if settingsversion == 2:
|
if settingsversion == 2:
|
||||||
|
@ -211,7 +213,8 @@ class sqlThread(threading.Thread):
|
||||||
parameters = ''
|
parameters = ''
|
||||||
self.cur.execute(item, parameters)
|
self.cur.execute(item, parameters)
|
||||||
currentVersion = int(self.cur.fetchall()[0][0])
|
currentVersion = int(self.cur.fetchall()[0][0])
|
||||||
if currentVersion == 1 or currentVersion == 3:
|
# if currentVersion == 1 or currentVersion == 3:
|
||||||
|
if currentVersion in (1, 3):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'In messages.dat database, adding tag field to'
|
'In messages.dat database, adding tag field to'
|
||||||
' the inventory table.')
|
' the inventory table.')
|
||||||
|
@ -569,6 +572,7 @@ class sqlThread(threading.Thread):
|
||||||
rowcount = 0
|
rowcount = 0
|
||||||
# print 'item', item
|
# print 'item', item
|
||||||
# print 'parameters', parameters
|
# print 'parameters', parameters
|
||||||
|
# if 'inbox' in item:
|
||||||
try:
|
try:
|
||||||
self.cur.execute(item, parameters)
|
self.cur.execute(item, parameters)
|
||||||
rowcount = self.cur.rowcount
|
rowcount = self.cur.rowcount
|
||||||
|
|
10
src/debug.py
10
src/debug.py
|
@ -35,7 +35,7 @@ Logging is thread-safe so you don't have to worry about locks,
|
||||||
just import and log.
|
just import and log.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import ConfigParser
|
import configparser
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
import os
|
import os
|
||||||
|
@ -73,7 +73,7 @@ def configureLogging():
|
||||||
False,
|
False,
|
||||||
'Loaded logger configuration from %s' % logging_config
|
'Loaded logger configuration from %s' % logging_config
|
||||||
)
|
)
|
||||||
except (OSError, ConfigParser.NoSectionError):
|
except (OSError, configparser.NoSectionError):
|
||||||
if os.path.isfile(logging_config):
|
if os.path.isfile(logging_config):
|
||||||
fail_msg = \
|
fail_msg = \
|
||||||
'Failed to load logger configuration from %s, using default' \
|
'Failed to load logger configuration from %s, using default' \
|
||||||
|
@ -148,7 +148,11 @@ def resetLogging():
|
||||||
|
|
||||||
|
|
||||||
# !
|
# !
|
||||||
|
try:
|
||||||
preconfigured, msg = configureLogging()
|
preconfigured, msg = configureLogging()
|
||||||
logger = logging.getLogger('default')
|
|
||||||
if msg:
|
if msg:
|
||||||
logger.log(logging.WARNING if preconfigured else logging.INFO, msg)
|
logger.log(logging.WARNING if preconfigured else logging.INFO, msg)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
logger = logging.getLogger('default')
|
||||||
|
|
|
@ -366,6 +366,7 @@ def check_pyqt():
|
||||||
Here we are checking for PyQt4 with its version, as for it require
|
Here we are checking for PyQt4 with its version, as for it require
|
||||||
PyQt 4.8 or later.
|
PyQt 4.8 or later.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
QtCore = try_import(
|
QtCore = try_import(
|
||||||
'PyQt4.QtCore', 'PyBitmessage requires PyQt 4.8 or later and Qt 4.7 or later.')
|
'PyQt4.QtCore', 'PyBitmessage requires PyQt 4.8 or later and Qt 4.7 or later.')
|
||||||
|
|
||||||
|
@ -421,11 +422,11 @@ def check_dependencies(verbose=False, optional=False):
|
||||||
'PyBitmessage requires Python 2.7.4 or greater'
|
'PyBitmessage requires Python 2.7.4 or greater'
|
||||||
' (but not Python 3+)')
|
' (but not Python 3+)')
|
||||||
has_all_dependencies = False
|
has_all_dependencies = False
|
||||||
if sys.hexversion >= 0x3000000:
|
# if sys.hexversion >= 0x3000000:
|
||||||
logger.error(
|
# logger.error(
|
||||||
'PyBitmessage does not support Python 3+. Python 2.7.4'
|
# 'PyBitmessage does not support Python 3+. Python 2.7.4'
|
||||||
' or greater is required.')
|
# ' or greater is required.')
|
||||||
has_all_dependencies = False
|
# has_all_dependencies = False
|
||||||
|
|
||||||
check_functions = [check_ripemd160, check_sqlite, check_openssl]
|
check_functions = [check_ripemd160, check_sqlite, check_openssl]
|
||||||
if optional:
|
if optional:
|
||||||
|
|
|
@ -99,14 +99,14 @@ class MsgDecode(object):
|
||||||
def decodeExtended(self, data):
|
def decodeExtended(self, data):
|
||||||
"""Handle extended encoding"""
|
"""Handle extended encoding"""
|
||||||
dc = zlib.decompressobj()
|
dc = zlib.decompressobj()
|
||||||
tmp = ""
|
tmp = bytes()
|
||||||
while len(tmp) <= BMConfigParser().safeGetInt("zlib", "maxsize"):
|
while len(tmp) <= BMConfigParser().safeGetInt("zlib", "maxsize"):
|
||||||
try:
|
try:
|
||||||
got = dc.decompress(
|
got = dc.decompress(
|
||||||
data, BMConfigParser().safeGetInt("zlib", "maxsize") +
|
data, BMConfigParser().safeGetInt("zlib", "maxsize") +
|
||||||
1 - len(tmp))
|
1 - len(tmp))
|
||||||
# EOF
|
# EOF
|
||||||
if got == "":
|
if got == bytes():
|
||||||
break
|
break
|
||||||
tmp += got
|
tmp += got
|
||||||
data = dc.unconsumed_tail
|
data = dc.unconsumed_tail
|
||||||
|
@ -128,7 +128,6 @@ class MsgDecode(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.error("Message type missing")
|
logger.error("Message type missing")
|
||||||
raise MsgDecodeException("Message type missing")
|
raise MsgDecodeException("Message type missing")
|
||||||
|
|
||||||
msgObj = messagetypes.constructObject(tmp)
|
msgObj = messagetypes.constructObject(tmp)
|
||||||
if msgObj is None:
|
if msgObj is None:
|
||||||
raise MsgDecodeException("Malformed message")
|
raise MsgDecodeException("Malformed message")
|
||||||
|
@ -142,7 +141,7 @@ class MsgDecode(object):
|
||||||
|
|
||||||
def decodeSimple(self, data):
|
def decodeSimple(self, data):
|
||||||
"""Handle simple encoding"""
|
"""Handle simple encoding"""
|
||||||
bodyPositionIndex = string.find(data, '\nBody:')
|
bodyPositionIndex = bytes.find(data, '\nBody:'.encode())
|
||||||
if bodyPositionIndex > 1:
|
if bodyPositionIndex > 1:
|
||||||
subject = data[8:bodyPositionIndex]
|
subject = data[8:bodyPositionIndex]
|
||||||
# Only save and show the first 500 characters of the subject.
|
# Only save and show the first 500 characters of the subject.
|
||||||
|
|
|
@ -7,6 +7,7 @@ try:
|
||||||
haveQt = True
|
haveQt = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
haveQt = False
|
haveQt = False
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
|
||||||
|
|
||||||
def search_translate(context, text):
|
def search_translate(context, text):
|
||||||
|
@ -18,7 +19,7 @@ def search_translate(context, text):
|
||||||
|
|
||||||
def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, what=None, unreadOnly=False):
|
def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, what=None, unreadOnly=False):
|
||||||
"""Perform a search in mailbox tables"""
|
"""Perform a search in mailbox tables"""
|
||||||
# pylint: disable=too-many-arguments, too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
if what is not None and what != "":
|
if what is not None and what != "":
|
||||||
what = "%" + what + "%"
|
what = "%" + what + "%"
|
||||||
if where == search_translate("MainWindow", "To"):
|
if where == search_translate("MainWindow", "To"):
|
||||||
|
@ -75,7 +76,6 @@ def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, w
|
||||||
|
|
||||||
def check_match(toAddress, fromAddress, subject, message, where=None, what=None):
|
def check_match(toAddress, fromAddress, subject, message, where=None, what=None):
|
||||||
"""Check if a single message matches a filter (used when new messages are added to messagelists)"""
|
"""Check if a single message matches a filter (used when new messages are added to messagelists)"""
|
||||||
# pylint: disable=too-many-arguments
|
|
||||||
if what is not None and what != "":
|
if what is not None and what != "":
|
||||||
if where in (search_translate("MainWindow", "To"), search_translate("MainWindow", "All")):
|
if where in (search_translate("MainWindow", "To"), search_translate("MainWindow", "All")):
|
||||||
if what.lower() not in toAddress.lower():
|
if what.lower() not in toAddress.lower():
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Insert values into sent table
|
Insert values into sent table
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from helper_sql import sqlExecute
|
from helper_sql import sqlExecute
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ SQLite objects can only be used from one thread.
|
||||||
or isn't thread-safe.
|
or isn't thread-safe.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import Queue
|
|
||||||
import threading
|
import threading
|
||||||
|
import queue as Queue
|
||||||
|
|
||||||
sqlSubmitQueue = Queue.Queue()
|
sqlSubmitQueue = Queue.Queue()
|
||||||
"""the queue for SQL"""
|
"""the queue for SQL"""
|
||||||
|
@ -29,7 +29,6 @@ sqlLock = threading.Lock()
|
||||||
def sqlQuery(sqlStatement, *args):
|
def sqlQuery(sqlStatement, *args):
|
||||||
"""
|
"""
|
||||||
Query sqlite and return results
|
Query sqlite and return results
|
||||||
|
|
||||||
:param str sqlStatement: SQL statement string
|
:param str sqlStatement: SQL statement string
|
||||||
:param list args: SQL query parameters
|
:param list args: SQL query parameters
|
||||||
:rtype: list
|
:rtype: list
|
||||||
|
@ -102,7 +101,7 @@ def sqlStoredProcedure(procName):
|
||||||
sqlLock.release()
|
sqlLock.release()
|
||||||
|
|
||||||
|
|
||||||
class SqlBulkExecute(object):
|
class SqlBulkExecute(object): # pylint: disable=no-init
|
||||||
"""This is used when you have to execute the same statement in a cycle."""
|
"""This is used when you have to execute the same statement in a cycle."""
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
|
|
|
@ -129,7 +129,9 @@ def loadConfig():
|
||||||
def updateConfig():
|
def updateConfig():
|
||||||
"""Save the config"""
|
"""Save the config"""
|
||||||
config = BMConfigParser()
|
config = BMConfigParser()
|
||||||
settingsversion = config.getint('bitmessagesettings', 'settingsversion')
|
# Used python2.7
|
||||||
|
# settingsversion = int(BMConfigParser().get('bitmessagesettings', 'settingsversion') \
|
||||||
|
settingsversion = BMConfigParser().safeGetInt('bitmessagesettings', 'settingsvesion')
|
||||||
if settingsversion == 1:
|
if settingsversion == 1:
|
||||||
config.set('bitmessagesettings', 'socksproxytype', 'none')
|
config.set('bitmessagesettings', 'socksproxytype', 'none')
|
||||||
config.set('bitmessagesettings', 'sockshostname', 'localhost')
|
config.set('bitmessagesettings', 'sockshostname', 'localhost')
|
||||||
|
|
|
@ -19,17 +19,18 @@ def makeCryptor(privkey):
|
||||||
"""Return a private `.pyelliptic.ECC` instance"""
|
"""Return a private `.pyelliptic.ECC` instance"""
|
||||||
private_key = a.changebase(privkey, 16, 256, minlen=32)
|
private_key = a.changebase(privkey, 16, 256, minlen=32)
|
||||||
public_key = pointMult(private_key)
|
public_key = pointMult(private_key)
|
||||||
privkey_bin = '\x02\xca\x00\x20' + private_key
|
privkey_bin = '\x02\xca\x00\x20'.encode('raw_unicode_escape') + private_key
|
||||||
pubkey_bin = '\x02\xca\x00\x20' + public_key[1:-32] + '\x00\x20' + public_key[-32:]
|
pubkey_bin = '\x02\xca\x00\x20'.encode(
|
||||||
cryptor = pyelliptic.ECC(
|
'raw_unicode_escape') + public_key[1:-32] + '\x00\x20'.encode(
|
||||||
curve='secp256k1', privkey=privkey_bin, pubkey=pubkey_bin)
|
'utf-8') + public_key[-32:]
|
||||||
|
cryptor = pyelliptic.ECC(curve='secp256k1', privkey=privkey_bin, pubkey=pubkey_bin)
|
||||||
return cryptor
|
return cryptor
|
||||||
|
|
||||||
|
|
||||||
def hexToPubkey(pubkey):
|
def hexToPubkey(pubkey):
|
||||||
"""Convert a pubkey from hex to binary"""
|
"""Convert a pubkey from hex to binary"""
|
||||||
pubkey_raw = a.changebase(pubkey[2:], 16, 256, minlen=64)
|
pubkey_raw = a.changebase(pubkey[2:], 16, 256, minlen=64)
|
||||||
pubkey_bin = '\x02\xca\x00 ' + pubkey_raw[:32] + '\x00 ' + pubkey_raw[32:]
|
pubkey_bin = '\x02\xca\x00 '.encode('raw_unicode_escape') + pubkey_raw[:32] + '\x00 '.encode() + pubkey_raw[32:]
|
||||||
return pubkey_bin
|
return pubkey_bin
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ def encrypt(msg, hexPubkey):
|
||||||
|
|
||||||
|
|
||||||
def decrypt(msg, hexPrivkey):
|
def decrypt(msg, hexPrivkey):
|
||||||
|
print("SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS#################################################")
|
||||||
"""Decrypts message with hex private key"""
|
"""Decrypts message with hex private key"""
|
||||||
return makeCryptor(hexPrivkey).decrypt(msg)
|
return makeCryptor(hexPrivkey).decrypt(msg)
|
||||||
|
|
||||||
|
|
|
@ -46,12 +46,18 @@ def json_serialize_knownnodes(output):
|
||||||
Reorganize knownnodes dict and write it as JSON to output
|
Reorganize knownnodes dict and write it as JSON to output
|
||||||
"""
|
"""
|
||||||
_serialized = []
|
_serialized = []
|
||||||
for stream, peers in knownNodes.iteritems():
|
for stream, peers in iter(knownNodes.items()):
|
||||||
for peer, info in peers.iteritems():
|
for peer, info in iter(peers.items()):
|
||||||
info.update(rating=round(info.get('rating', 0), 2))
|
info.update(rating=round(info.get('rating', 0), 2))
|
||||||
|
# pylint: disable=unidiomatic-typecheck
|
||||||
|
if type(peer[0]) != bytes:
|
||||||
|
_serialized.append({'stream': stream, 'peer': peer._asdict(), 'info': info})
|
||||||
|
else:
|
||||||
|
from collections import OrderedDict
|
||||||
_serialized.append({
|
_serialized.append({
|
||||||
'stream': stream, 'peer': peer._asdict(), 'info': info
|
'stream': stream,
|
||||||
})
|
'peer': OrderedDict({'host': str(peer[0].decode()), 'port': int(peer[1])}),
|
||||||
|
'info': info})
|
||||||
json.dump(_serialized, output, indent=4)
|
json.dump(_serialized, output, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +96,7 @@ def saveKnownNodes(dirName=None):
|
||||||
if dirName is None:
|
if dirName is None:
|
||||||
dirName = state.appdata
|
dirName = state.appdata
|
||||||
with knownNodesLock:
|
with knownNodesLock:
|
||||||
with open(os.path.join(dirName, 'knownnodes.dat'), 'wb') as output:
|
with open(os.path.join(dirName, 'knownnodes.dat'), 'w') as output:
|
||||||
json_serialize_knownnodes(output)
|
json_serialize_knownnodes(output)
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,7 +127,7 @@ def readKnownNodes():
|
||||||
except ValueError:
|
except ValueError:
|
||||||
source.seek(0)
|
source.seek(0)
|
||||||
pickle_deserialize_old_knownnodes(source)
|
pickle_deserialize_old_knownnodes(source)
|
||||||
except (IOError, OSError, KeyError, EOFError):
|
except (IOError, OSError, KeyError, EOFError, pickle.UnpicklingError):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Failed to read nodes from knownnodes.dat', exc_info=True)
|
'Failed to read nodes from knownnodes.dat', exc_info=True)
|
||||||
createDefaultKnownNodes()
|
createDefaultKnownNodes()
|
||||||
|
@ -143,7 +149,7 @@ def increaseRating(peer):
|
||||||
increaseAmount = 0.1
|
increaseAmount = 0.1
|
||||||
maxRating = 1
|
maxRating = 1
|
||||||
with knownNodesLock:
|
with knownNodesLock:
|
||||||
for stream in knownNodes.keys():
|
for stream in [key for key in knownNodes.keys()]:
|
||||||
try:
|
try:
|
||||||
knownNodes[stream][peer]["rating"] = min(
|
knownNodes[stream][peer]["rating"] = min(
|
||||||
knownNodes[stream][peer]["rating"] + increaseAmount,
|
knownNodes[stream][peer]["rating"] + increaseAmount,
|
||||||
|
|
28
src/l10n.py
28
src/l10n.py
|
@ -64,20 +64,31 @@ else:
|
||||||
if time_format != DEFAULT_TIME_FORMAT:
|
if time_format != DEFAULT_TIME_FORMAT:
|
||||||
try:
|
try:
|
||||||
# Check day names
|
# Check day names
|
||||||
for i in xrange(7):
|
new_time_format = time_format
|
||||||
unicode(time.strftime(time_format, (0, 0, 0, 0, 0, 0, i, 0, 0)), encoding)
|
import sys
|
||||||
|
if sys.version_info >= (3, 0, 0) and time_format == '%%c':
|
||||||
|
time_format = '%c'
|
||||||
|
for i in range(7):
|
||||||
|
# this work for python2.7
|
||||||
|
# unicode(time.strftime(time_format, (0, 0, 0, 0, 0, 0, i, 0, 0)), encoding)
|
||||||
|
# this code for the python3
|
||||||
|
(time.strftime(time_format, (0, 0, 0, 0, 0, 0, i, 0, 0))).encode()
|
||||||
# Check month names
|
# Check month names
|
||||||
for i in xrange(1, 13):
|
for i in range(1, 13):
|
||||||
unicode(time.strftime(time_format, (0, i, 0, 0, 0, 0, 0, 0, 0)), encoding)
|
# unicode(time.strftime(time_format, (0, i, 0, 0, 0, 0, 0, 0, 0)), encoding)
|
||||||
|
(time.strftime(time_format, (0, i, 0, 0, 0, 0, 0, 0, 0))).encode()
|
||||||
|
|
||||||
# Check AM/PM
|
# Check AM/PM
|
||||||
unicode(time.strftime(time_format, (0, 0, 0, 11, 0, 0, 0, 0, 0)), encoding)
|
(time.strftime(time_format, (0, 0, 0, 11, 0, 0, 0, 0, 0))).encode()
|
||||||
unicode(time.strftime(time_format, (0, 0, 0, 13, 0, 0, 0, 0, 0)), encoding)
|
(time.strftime(time_format, (0, 0, 0, 13, 0, 0, 0, 0, 0))).encode()
|
||||||
# Check DST
|
# Check DST
|
||||||
unicode(time.strftime(time_format, (0, 0, 0, 0, 0, 0, 0, 0, 1)), encoding)
|
(time.strftime(time_format, (0, 0, 0, 0, 0, 0, 0, 0, 1))).encode()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
logger.exception('Could not decode locale formatted timestamp')
|
logger.exception('Could not decode locale formatted timestamp')
|
||||||
time_format = DEFAULT_TIME_FORMAT
|
time_format = DEFAULT_TIME_FORMAT
|
||||||
encoding = DEFAULT_ENCODING
|
encoding = DEFAULT_ENCODING
|
||||||
|
time_format = new_time_format
|
||||||
|
|
||||||
|
|
||||||
def setlocale(category, newlocale):
|
def setlocale(category, newlocale):
|
||||||
|
@ -111,7 +122,8 @@ def formatTimestamp(timestamp=None, as_unicode=True):
|
||||||
timestring = time.strftime(time_format)
|
timestring = time.strftime(time_format)
|
||||||
|
|
||||||
if as_unicode:
|
if as_unicode:
|
||||||
return unicode(timestring, encoding)
|
return (timestring.encode('utf-8'))
|
||||||
|
# return unicode(timestring, encoding)
|
||||||
return timestring
|
return timestring
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
"""This module is for thread start."""
|
"""This module is for thread start."""
|
||||||
import state
|
import state
|
||||||
from bitmessagemain import main
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
state.kivy = True
|
state.kivy = True
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from os import listdir, path
|
from os import listdir, path
|
||||||
from string import lower
|
|
||||||
try:
|
try:
|
||||||
from kivy.utils import platform
|
from kivy.utils import platform
|
||||||
except:
|
except:
|
||||||
|
@ -16,7 +15,7 @@ logger = logging.getLogger('default')
|
||||||
class MsgBase(object): # pylint: disable=too-few-public-methods
|
class MsgBase(object): # pylint: disable=too-few-public-methods
|
||||||
"""Base class for message types"""
|
"""Base class for message types"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.data = {"": lower(type(self).__name__)}
|
self.data = {"": (type(self).__name__).lower()}
|
||||||
|
|
||||||
|
|
||||||
def constructObject(data):
|
def constructObject(data):
|
||||||
|
|
|
@ -14,13 +14,17 @@ class Message(MsgBase):
|
||||||
"""Decode a message"""
|
"""Decode a message"""
|
||||||
# UTF-8 and variable type validator
|
# UTF-8 and variable type validator
|
||||||
if isinstance(data["subject"], str):
|
if isinstance(data["subject"], str):
|
||||||
self.subject = unicode(data["subject"], 'utf-8', 'replace')
|
# Unicode is depreciated
|
||||||
|
self.subject =data["subject"]
|
||||||
else:
|
else:
|
||||||
self.subject = unicode(str(data["subject"]), 'utf-8', 'replace')
|
# Unicode is depreciated
|
||||||
|
self.subject = str(data["subject"])
|
||||||
if isinstance(data["body"], str):
|
if isinstance(data["body"], str):
|
||||||
self.body = unicode(data["body"], 'utf-8', 'replace')
|
# Unicode is depreciated
|
||||||
|
self.body = data["body"]
|
||||||
else:
|
else:
|
||||||
self.body = unicode(str(data["body"]), 'utf-8', 'replace')
|
# Unicode is depreciated
|
||||||
|
self.body = str(data["body"])
|
||||||
|
|
||||||
def encode(self, data):
|
def encode(self, data):
|
||||||
"""Encode a message"""
|
"""Encode a message"""
|
||||||
|
|
|
@ -3,7 +3,7 @@ A queue with multiple internal subqueues.
|
||||||
Elements are added into a random subqueue, and retrieval rotates
|
Elements are added into a random subqueue, and retrieval rotates
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import Queue
|
import queue as Queue
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
import helper_random
|
import helper_random
|
||||||
|
@ -22,7 +22,7 @@ class MultiQueue(Queue.Queue):
|
||||||
Queue.Queue.__init__(self, maxsize)
|
Queue.Queue.__init__(self, maxsize)
|
||||||
|
|
||||||
# Initialize the queue representation
|
# Initialize the queue representation
|
||||||
def _init(self, maxsize):
|
def _init(self, _):
|
||||||
self.iter = 0
|
self.iter = 0
|
||||||
self.queues = []
|
self.queues = []
|
||||||
for _ in range(self.queueCount):
|
for _ in range(self.queueCount):
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
"""
|
from network.addrthread import AddrThread
|
||||||
Network subsystem packages
|
from network.announcethread import AnnounceThread
|
||||||
"""
|
from network.connectionpool import BMConnectionPool
|
||||||
from addrthread import AddrThread
|
from network.dandelion import Dandelion
|
||||||
from announcethread import AnnounceThread
|
from network.downloadthread import DownloadThread
|
||||||
from connectionpool import BMConnectionPool
|
from network.invthread import InvThread
|
||||||
from dandelion import Dandelion
|
from network.networkthread import BMNetworkThread
|
||||||
from downloadthread import DownloadThread
|
from network.receivequeuethread import ReceiveQueueThread
|
||||||
from invthread import InvThread
|
from network.threads import StoppableThread
|
||||||
from networkthread import BMNetworkThread
|
from network.uploadthread import UploadThread
|
||||||
from receivequeuethread import ReceiveQueueThread
|
|
||||||
from threads import StoppableThread
|
|
||||||
from uploadthread import UploadThread
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
"""
|
"""
|
||||||
Announce addresses as they are received from other hosts
|
Announce addresses as they are received from other hosts
|
||||||
"""
|
"""
|
||||||
import Queue
|
import queue as Queue
|
||||||
|
|
||||||
import state
|
import state
|
||||||
from helper_random import randomshuffle
|
from helper_random import randomshuffle
|
||||||
from network.assemble import assemble_addr
|
from network.assemble import assemble_addr
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from queues import addrQueue
|
from queues import addrQueue
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class AddrThread(StoppableThread):
|
class AddrThread(StoppableThread):
|
||||||
|
|
|
@ -8,7 +8,7 @@ import time
|
||||||
|
|
||||||
import network.asyncore_pollchoose as asyncore
|
import network.asyncore_pollchoose as asyncore
|
||||||
import state
|
import state
|
||||||
from threads import BusyError, nonBlocking
|
from network.threads import BusyError, nonBlocking
|
||||||
|
|
||||||
|
|
||||||
class ProcessingError(Exception):
|
class ProcessingError(Exception):
|
||||||
|
@ -29,7 +29,10 @@ class AdvancedDispatcher(asyncore.dispatcher):
|
||||||
_buf_len = 131072 # 128kB
|
_buf_len = 131072 # 128kB
|
||||||
|
|
||||||
def __init__(self, sock=None):
|
def __init__(self, sock=None):
|
||||||
if not hasattr(self, '_map'):
|
# python 2 below condition is used
|
||||||
|
# if not hasattr(self, '_map'):
|
||||||
|
# python 3 below condition is used
|
||||||
|
if '_map' not in dir(self):
|
||||||
asyncore.dispatcher.__init__(self, sock)
|
asyncore.dispatcher.__init__(self, sock)
|
||||||
self.read_buf = bytearray()
|
self.read_buf = bytearray()
|
||||||
self.write_buf = bytearray()
|
self.write_buf = bytearray()
|
||||||
|
|
|
@ -8,8 +8,8 @@ from bmconfigparser import BMConfigParser
|
||||||
from network.assemble import assemble_addr
|
from network.assemble import assemble_addr
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from network.udp import UDPSocket
|
from network.udp import UDPSocket
|
||||||
from node import Peer
|
from network.node import Peer
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class AnnounceThread(StoppableThread):
|
class AnnounceThread(StoppableThread):
|
||||||
|
@ -29,12 +29,15 @@ class AnnounceThread(StoppableThread):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def announceSelf():
|
def announceSelf():
|
||||||
"""Announce our presence"""
|
"""Announce our presence"""
|
||||||
for connection in BMConnectionPool().udpSockets.values():
|
for connection in [udpSockets for udpSockets in BMConnectionPool().udpSockets.values()]:
|
||||||
if not connection.announcing:
|
if not connection.announcing:
|
||||||
continue
|
continue
|
||||||
for stream in state.streamsInWhichIAmParticipating:
|
for stream in state.streamsInWhichIAmParticipating:
|
||||||
addr = (
|
addr = (
|
||||||
stream,
|
stream,
|
||||||
|
# state.Peer('127.0.0.1',int( BMConfigParser().safeGet("bitmessagesettings", "port"))),
|
||||||
|
# int(time.time()))
|
||||||
|
# connection.append_write_buf(BMProto.assembleAddr([addr]))
|
||||||
Peer(
|
Peer(
|
||||||
'127.0.0.1',
|
'127.0.0.1',
|
||||||
BMConfigParser().safeGetInt(
|
BMConfigParser().safeGetInt(
|
||||||
|
|
|
@ -14,13 +14,14 @@ def assemble_addr(peerList):
|
||||||
if isinstance(peerList, Peer):
|
if isinstance(peerList, Peer):
|
||||||
peerList = [peerList]
|
peerList = [peerList]
|
||||||
if not peerList:
|
if not peerList:
|
||||||
return b''
|
return bytes()
|
||||||
retval = b''
|
retval = bytes()
|
||||||
for i in range(0, len(peerList), MAX_ADDR_COUNT):
|
for i in range(0, len(peerList), MAX_ADDR_COUNT):
|
||||||
payload = addresses.encodeVarint(len(peerList[i:i + MAX_ADDR_COUNT]))
|
payload = addresses.encodeVarint(len(peerList[i:i + MAX_ADDR_COUNT]))
|
||||||
for stream, peer, timestamp in peerList[i:i + MAX_ADDR_COUNT]:
|
for stream, peer, timestamp in peerList[i:i + MAX_ADDR_COUNT]:
|
||||||
# 64-bit time
|
payload += struct.pack(
|
||||||
payload += struct.pack('>Q', timestamp)
|
'>Q', int(timestamp)) # 64-bit time
|
||||||
|
|
||||||
payload += struct.pack('>I', stream)
|
payload += struct.pack('>I', stream)
|
||||||
# service bit flags offered by this node
|
# service bit flags offered by this node
|
||||||
payload += struct.pack('>q', 1)
|
payload += struct.pack('>q', 1)
|
||||||
|
|
|
@ -60,6 +60,7 @@ def _strerror(err):
|
||||||
if err in errorcode:
|
if err in errorcode:
|
||||||
return errorcode[err]
|
return errorcode[err]
|
||||||
return "Unknown error %s" % err
|
return "Unknown error %s" % err
|
||||||
|
# ret18 ("Unknown error {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
class ExitNow(Exception):
|
class ExitNow(Exception):
|
||||||
|
@ -205,25 +206,24 @@ def select_poller(timeout=0.0, map=None):
|
||||||
if map is None:
|
if map is None:
|
||||||
map = socket_map
|
map = socket_map
|
||||||
if map:
|
if map:
|
||||||
r = []
|
rd = []
|
||||||
w = []
|
wt = []
|
||||||
e = []
|
ex = []
|
||||||
for fd, obj in list(map.items()):
|
for fd, obj in list(map.items()):
|
||||||
is_r = obj.readable()
|
is_r = obj.readable()
|
||||||
is_w = obj.writable()
|
is_w = obj.writable()
|
||||||
if is_r:
|
if is_r:
|
||||||
r.append(fd)
|
rd.append(fd)
|
||||||
# accepting sockets should not be writable
|
# accepting sockets should not be writable
|
||||||
if is_w and not obj.accepting:
|
if is_w and not obj.accepting:
|
||||||
w.append(fd)
|
wt.append(fd)
|
||||||
if is_r or is_w:
|
if is_r or is_w:
|
||||||
e.append(fd)
|
ex.append(fd)
|
||||||
if [] == r == w == e:
|
if [] == rd == wt == ex:
|
||||||
time.sleep(timeout)
|
time.sleep(timeout)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r, w, e = select.select(r, w, e, timeout)
|
rd, wt, ex = select.select(rd, wt, ex, timeout)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
return
|
return
|
||||||
except socket.error as err:
|
except socket.error as err:
|
||||||
|
@ -233,19 +233,19 @@ def select_poller(timeout=0.0, map=None):
|
||||||
if err.args[0] in (WSAENOTSOCK, ):
|
if err.args[0] in (WSAENOTSOCK, ):
|
||||||
return
|
return
|
||||||
|
|
||||||
for fd in helper_random.randomsample(r, len(r)):
|
for fd in helper_random.randomsample(rd, len(rd)):
|
||||||
obj = map.get(fd)
|
obj = map.get(fd)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
continue
|
continue
|
||||||
read(obj)
|
read(obj)
|
||||||
|
|
||||||
for fd in helper_random.randomsample(w, len(w)):
|
for fd in helper_random.randomsample(wt, len(wt)):
|
||||||
obj = map.get(fd)
|
obj = map.get(fd)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
continue
|
continue
|
||||||
write(obj)
|
write(obj)
|
||||||
|
|
||||||
for fd in e:
|
for fd in ex:
|
||||||
obj = map.get(fd)
|
obj = map.get(fd)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
continue
|
continue
|
||||||
|
@ -441,7 +441,7 @@ def kqueue_poller(timeout=0.0, map=None):
|
||||||
current_thread().stop.wait(timeout)
|
current_thread().stop.wait(timeout)
|
||||||
|
|
||||||
|
|
||||||
def loop(timeout=30.0, use_poll=False, map=None, count=None, poller=None):
|
def loop(timeout=30.0, _=False, map=None, count=None, poller=None):
|
||||||
"""Poll in a loop, until count or timeout is reached"""
|
"""Poll in a loop, until count or timeout is reached"""
|
||||||
|
|
||||||
if map is None:
|
if map is None:
|
||||||
|
@ -452,18 +452,18 @@ def loop(timeout=30.0, use_poll=False, map=None, count=None, poller=None):
|
||||||
# argument which should no longer be used in favor of
|
# argument which should no longer be used in favor of
|
||||||
# "poller"
|
# "poller"
|
||||||
|
|
||||||
if poller is None:
|
# if poller is None:
|
||||||
if use_poll:
|
# if use_poll:
|
||||||
poller = poll_poller
|
# poller = poll_poller
|
||||||
elif hasattr(select, 'epoll'):
|
# elif hasattr(select, 'epoll'):
|
||||||
poller = epoll_poller
|
# poller = epoll_poller
|
||||||
elif hasattr(select, 'kqueue'):
|
# elif hasattr(select, 'kqueue'):
|
||||||
poller = kqueue_poller
|
# poller = kqueue_poller
|
||||||
elif hasattr(select, 'poll'):
|
# elif hasattr(select, 'poll'):
|
||||||
poller = poll_poller
|
# poller = poll_poller
|
||||||
elif hasattr(select, 'select'):
|
# elif hasattr(select, 'select'):
|
||||||
|
# poller = select_poller
|
||||||
poller = select_poller
|
poller = select_poller
|
||||||
|
|
||||||
if timeout == 0:
|
if timeout == 0:
|
||||||
deadline = 0
|
deadline = 0
|
||||||
else:
|
else:
|
||||||
|
@ -729,9 +729,9 @@ class dispatcher(object):
|
||||||
try:
|
try:
|
||||||
retattr = getattr(self.socket, attr)
|
retattr = getattr(self.socket, attr)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AttributeError(
|
raise AttributeError("{} instance has no attribute {}"
|
||||||
"%s instance has no attribute '%s'"
|
.format(self.__class__.__name__, attr))
|
||||||
% (self.__class__.__name__, attr))
|
|
||||||
else:
|
else:
|
||||||
msg = "%(me)s.%(attr)s is deprecated; use %(me)s.socket.%(attr)s"\
|
msg = "%(me)s.%(attr)s is deprecated; use %(me)s.socket.%(attr)s"\
|
||||||
" instead" % {'me': self.__class__.__name__, 'attr': attr}
|
" instead" % {'me': self.__class__.__name__, 'attr': attr}
|
||||||
|
@ -749,7 +749,7 @@ class dispatcher(object):
|
||||||
def log_info(self, message, log_type='info'):
|
def log_info(self, message, log_type='info'):
|
||||||
"""Conditionally print a message"""
|
"""Conditionally print a message"""
|
||||||
if log_type not in self.ignore_log_types:
|
if log_type not in self.ignore_log_types:
|
||||||
print '%s: %s' % (log_type, message)
|
print('{}: {}'.format(log_type, message))
|
||||||
|
|
||||||
def handle_read_event(self):
|
def handle_read_event(self):
|
||||||
"""Handle a read event"""
|
"""Handle a read event"""
|
||||||
|
|
|
@ -116,7 +116,7 @@ class BMObject(object): # pylint: disable=too-many-instance-attributes
|
||||||
# if it's a stem duplicate, pretend we don't have it
|
# if it's a stem duplicate, pretend we don't have it
|
||||||
if Dandelion().hasHash(self.inventoryHash):
|
if Dandelion().hasHash(self.inventoryHash):
|
||||||
return
|
return
|
||||||
if self.inventoryHash in Inventory():
|
if self.inventoryHash in Inventory()._realInventory:
|
||||||
raise BMObjectAlreadyHaveError()
|
raise BMObjectAlreadyHaveError()
|
||||||
|
|
||||||
def checkObjectByType(self):
|
def checkObjectByType(self):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Bitmessage Protocol
|
Bitmessage Protocol
|
||||||
"""
|
"""
|
||||||
# pylint: disable=attribute-defined-outside-init, too-few-public-methods
|
# pylint: disable=attribute-defined-outside-init, too-few-public-methods, logging-format-interpolation
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
|
@ -11,7 +11,7 @@ import time
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
|
|
||||||
import addresses
|
import addresses
|
||||||
import connectionpool
|
from network import connectionpool
|
||||||
import knownnodes
|
import knownnodes
|
||||||
import protocol
|
import protocol
|
||||||
import state
|
import state
|
||||||
|
@ -29,10 +29,10 @@ from network.constants import (
|
||||||
)
|
)
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
from network.proxy import ProxyError
|
from network.proxy import ProxyError
|
||||||
from node import Node, Peer
|
from network.objectracker import missingObjects, ObjectTracker
|
||||||
from objectracker import ObjectTracker, missingObjects
|
from network.node import Node, Peer
|
||||||
from queues import invQueue, objectProcessorQueue, portCheckerQueue
|
from queues import objectProcessorQueue, portCheckerQueue, invQueue, addrQueue
|
||||||
from randomtrackingdict import RandomTrackingDict
|
from network.randomtrackingdict import RandomTrackingDict
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
@ -83,9 +83,10 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
"""Process incoming header"""
|
"""Process incoming header"""
|
||||||
self.magic, self.command, self.payloadLength, self.checksum = \
|
self.magic, self.command, self.payloadLength, self.checksum = \
|
||||||
protocol.Header.unpack(self.read_buf[:protocol.Header.size])
|
protocol.Header.unpack(self.read_buf[:protocol.Header.size])
|
||||||
self.command = self.command.rstrip('\x00')
|
# its shoule be in string
|
||||||
|
self.command = self.command.rstrip('\x00'.encode('utf-8'))
|
||||||
|
# pylint: disable=global-statement
|
||||||
if self.magic != 0xE9BEB4D9:
|
if self.magic != 0xE9BEB4D9:
|
||||||
# skip 1 byte in order to sync
|
|
||||||
self.set_state("bm_header", length=1)
|
self.set_state("bm_header", length=1)
|
||||||
self.bm_proto_reset()
|
self.bm_proto_reset()
|
||||||
logger.debug('Bad magic')
|
logger.debug('Bad magic')
|
||||||
|
@ -100,7 +101,8 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
length=protocol.Header.size, expectBytes=self.payloadLength)
|
length=protocol.Header.size, expectBytes=self.payloadLength)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def state_bm_command(self): # pylint: disable=too-many-branches
|
def state_bm_command(self):
|
||||||
|
# pylint: disable=too-many-branches, too-many-statements
|
||||||
"""Process incoming command"""
|
"""Process incoming command"""
|
||||||
self.payload = self.read_buf[:self.payloadLength]
|
self.payload = self.read_buf[:self.payloadLength]
|
||||||
if self.checksum != hashlib.sha512(self.payload).digest()[0:4]:
|
if self.checksum != hashlib.sha512(self.payload).digest()[0:4]:
|
||||||
|
@ -108,15 +110,17 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
self.invalid = True
|
self.invalid = True
|
||||||
retval = True
|
retval = True
|
||||||
if not self.fullyEstablished and self.command not in (
|
if not self.fullyEstablished and self.command not in (
|
||||||
"error", "version", "verack"):
|
"error".encode(), "version".encode(), "verack".encode()):
|
||||||
logger.error(
|
logger.error(
|
||||||
'Received command %s before connection was fully'
|
'Received command {} before connection was fully'
|
||||||
' established, ignoring', self.command)
|
' established, ignoring'.format(self.command))
|
||||||
self.invalid = True
|
self.invalid = True
|
||||||
if not self.invalid:
|
if not self.invalid:
|
||||||
try:
|
try:
|
||||||
|
command = self.command.decode() if self.command else self.command
|
||||||
|
|
||||||
retval = getattr(
|
retval = getattr(
|
||||||
self, "bm_command_" + str(self.command).lower())()
|
self, "bm_command_" + command)()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# unimplemented command
|
# unimplemented command
|
||||||
logger.debug('unimplemented command %s', self.command)
|
logger.debug('unimplemented command %s', self.command)
|
||||||
|
@ -137,15 +141,17 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
except BMObjectAlreadyHaveError:
|
except BMObjectAlreadyHaveError:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%(host)s:%(port)i already got object, skipping',
|
'%(host)s:%(port)i already got object, skipping',
|
||||||
self.destination._asdict())
|
self.destinaestion._asdict())
|
||||||
except struct.error:
|
except struct.error:
|
||||||
logger.debug('decoding error, skipping')
|
logger.debug('decoding error, skipping')
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
elif self.socket.type == socket.SOCK_DGRAM:
|
elif self.socket.type == socket.SOCK_DGRAM:
|
||||||
# broken read, ignore
|
# broken read, ignore
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
logger.debug('Closing due to invalid command %s', self.command)
|
logger.debug('Closing due to invalid command {}'.format(self.command))
|
||||||
self.close_reason = "Invalid command %s" % self.command
|
self.close_reason = ("Invalid command {}".format(self.command))
|
||||||
self.set_state("close")
|
self.set_state("close")
|
||||||
return False
|
return False
|
||||||
if retval:
|
if retval:
|
||||||
|
@ -171,17 +177,17 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
"""Decode node details from the payload"""
|
"""Decode node details from the payload"""
|
||||||
# protocol.checkIPAddress()
|
# protocol.checkIPAddress()
|
||||||
services, host, port = self.decode_payload_content("Q16sH")
|
services, host, port = self.decode_payload_content("Q16sH")
|
||||||
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF'.encode('raw_unicode_escape'):
|
||||||
host = socket.inet_ntop(socket.AF_INET, str(host[12:16]))
|
host = socket.inet_ntop(socket.AF_INET, host[12:16])
|
||||||
elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43':
|
elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43'.encode('raw_unicode_escape'):
|
||||||
# Onion, based on BMD/bitcoind
|
# Onion, based on BMD/bitcoind
|
||||||
host = base64.b32encode(host[6:]).lower() + ".onion"
|
host = base64.b32encode(host[6:]).lower() + ".onion"
|
||||||
else:
|
else:
|
||||||
host = socket.inet_ntop(socket.AF_INET6, str(host))
|
host = socket.inet_ntop(socket.AF_INET6, host)
|
||||||
if host == "":
|
if host == "":
|
||||||
# This can happen on Windows systems which are not 64-bit
|
# This can happen on Windows systems which are not 64-bit
|
||||||
# compatible so let us drop the IPv6 address.
|
# compatible so let us drop the IPv6 address.
|
||||||
host = socket.inet_ntop(socket.AF_INET, str(host[12:16]))
|
host = socket.inet_ntop(socket.AF_INET, host[12:16])
|
||||||
|
|
||||||
return Node(services, host, port)
|
return Node(services, host, port)
|
||||||
|
|
||||||
|
@ -329,13 +335,14 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
If we have them and some other conditions are fulfilled,
|
If we have them and some other conditions are fulfilled,
|
||||||
append them to the write queue.
|
append them to the write queue.
|
||||||
"""
|
"""
|
||||||
|
# 32 an array bit long strings
|
||||||
items = self.decode_payload_content("l32s")
|
items = self.decode_payload_content("l32s")
|
||||||
# skip?
|
# skip?
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now < self.skipUntil:
|
if now < self.skipUntil:
|
||||||
return True
|
return True
|
||||||
for i in items:
|
for i in items:
|
||||||
self.pendingUpload[str(i)] = now
|
self.pendingUpload[bytes(i)] = now
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _command_inv(self, dandelion=False):
|
def _command_inv(self, dandelion=False):
|
||||||
|
@ -349,9 +356,8 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
# ignore dinv if dandelion turned off
|
# ignore dinv if dandelion turned off
|
||||||
if dandelion and not state.dandelion:
|
if dandelion and not state.dandelion:
|
||||||
return True
|
return True
|
||||||
|
for i in map(bytes, items):
|
||||||
for i in map(str, items):
|
if i in Inventory()._realInventory and not Dandelion().hasHash(i):
|
||||||
if i in Inventory() and not Dandelion().hasHash(i):
|
|
||||||
continue
|
continue
|
||||||
if dandelion and not Dandelion().hasHash(i):
|
if dandelion and not Dandelion().hasHash(i):
|
||||||
Dandelion().addHash(i, self)
|
Dandelion().addHash(i, self)
|
||||||
|
@ -403,7 +409,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
try:
|
try:
|
||||||
self.object.checkObjectByType()
|
self.object.checkObjectByType()
|
||||||
objectProcessorQueue.put((
|
objectProcessorQueue.put((
|
||||||
self.object.objectType, buffer(self.object.data)))
|
self.object.objectType, memoryview(self.object.data)))
|
||||||
except BMObjectInvalidError:
|
except BMObjectInvalidError:
|
||||||
BMProto.stopDownloadingObject(self.object.inventoryHash, True)
|
BMProto.stopDownloadingObject(self.object.inventoryHash, True)
|
||||||
else:
|
else:
|
||||||
|
@ -412,16 +418,15 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if self.object.inventoryHash in Inventory() and Dandelion().hasHash(
|
if self.object.inventoryHash in Inventory()._realInventory and Dandelion().hasHash(self.object.inventoryHash):
|
||||||
self.object.inventoryHash):
|
Dandelion().removeHash(self.object.inventoryHash, "cycle detection")
|
||||||
Dandelion().removeHash(
|
[self.object.inventoryHash] = (
|
||||||
self.object.inventoryHash, "cycle detection")
|
|
||||||
|
|
||||||
Inventory()[self.object.inventoryHash] = (
|
|
||||||
self.object.objectType, self.object.streamNumber,
|
self.object.objectType, self.object.streamNumber,
|
||||||
buffer(self.payload[objectOffset:]), self.object.expiresTime,
|
memoryview(self.payload[objectOffset:]), self.object.expiresTime,
|
||||||
buffer(self.object.tag)
|
memoryview(self.object.tag)
|
||||||
)
|
)
|
||||||
|
Inventory()[self.object.inventoryHash]
|
||||||
self.handleReceivedObject(
|
self.handleReceivedObject(
|
||||||
self.object.streamNumber, self.object.inventoryHash)
|
self.object.streamNumber, self.object.inventoryHash)
|
||||||
invQueue.put((
|
invQueue.put((
|
||||||
|
@ -434,10 +439,11 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
|
|
||||||
def bm_command_addr(self):
|
def bm_command_addr(self):
|
||||||
"""Incoming addresses, process them"""
|
"""Incoming addresses, process them"""
|
||||||
# pylint: disable=redefined-outer-name
|
addresses = self._decode_addr() # pylint: disable=redefined-outer-name
|
||||||
addresses = self._decode_addr()
|
for i in addresses:
|
||||||
for seenTime, stream, _, ip, port in addresses:
|
seenTime, stream, _, ip, port = i
|
||||||
decodedIP = protocol.checkIPAddress(str(ip))
|
decodedIP = protocol.checkIPAddress(bytes(ip))
|
||||||
|
|
||||||
if stream not in state.streamsInWhichIAmParticipating:
|
if stream not in state.streamsInWhichIAmParticipating:
|
||||||
continue
|
continue
|
||||||
if (
|
if (
|
||||||
|
@ -452,8 +458,7 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
continue
|
continue
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if len(knownnodes.knownNodes[stream]) < \
|
if len(knownnodes.knownNodes[stream]) < BMConfigParser().safeGetInt("knownnodes", "maxnodes"):
|
||||||
BMConfigParser().safeGetInt("knownnodes", "maxnodes"):
|
|
||||||
with knownnodes.knownNodesLock:
|
with knownnodes.knownNodesLock:
|
||||||
try:
|
try:
|
||||||
knownnodes.knownNodes[stream][peer]["lastseen"] = \
|
knownnodes.knownNodes[stream][peer]["lastseen"] = \
|
||||||
|
@ -539,13 +544,16 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'%(host)s:%(port)i sending version',
|
'%(host)s:%(port)i sending version',
|
||||||
self.destination._asdict())
|
self.destination._asdict())
|
||||||
if ((self.services & protocol.NODE_SSL == protocol.NODE_SSL) and
|
if self.services & protocol.NODE_SSL == protocol.NODE_SSL:
|
||||||
protocol.haveSSL(not self.isOutbound)):
|
# self.isSSL = True
|
||||||
self.isSSL = True
|
pass
|
||||||
if not self.verackReceived:
|
if not self.verackReceived:
|
||||||
return True
|
return True
|
||||||
|
# self.set_state(
|
||||||
|
# "tls_init" if self.isSSL else "connection_fully_established",
|
||||||
|
# length=self.payloadLength, expectBytes=0)
|
||||||
self.set_state(
|
self.set_state(
|
||||||
"tls_init" if self.isSSL else "connection_fully_established",
|
"connection_fully_established",
|
||||||
length=self.payloadLength, expectBytes=0)
|
length=self.payloadLength, expectBytes=0)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -595,8 +603,8 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
errorText="Too many connections from your IP."
|
errorText="Too many connections from your IP."
|
||||||
" Closing connection.", fatal=2))
|
" Closing connection.", fatal=2))
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Closed connection to %s because we are already'
|
'Closed connection to {} because we are already connected'
|
||||||
' connected to that IP.', self.destination)
|
' to that IP.'.format(self.destination))
|
||||||
return False
|
return False
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -628,7 +636,6 @@ class BMProto(AdvancedDispatcher, ObjectTracker):
|
||||||
"Closed connection to %s because I'm connected to myself.",
|
"Closed connection to %s because I'm connected to myself.",
|
||||||
self.destination)
|
self.destination)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Select which node to connect to
|
Select which node to connect to
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches, logging-format-interpolation, unidiomatic-typecheck
|
||||||
import logging
|
import logging
|
||||||
import random # nosec
|
import random # nosec
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ logger = logging.getLogger('default')
|
||||||
def getDiscoveredPeer():
|
def getDiscoveredPeer():
|
||||||
"""Get a peer from the local peer discovery list"""
|
"""Get a peer from the local peer discovery list"""
|
||||||
try:
|
try:
|
||||||
peer = random.choice(state.discoveredPeers.keys())
|
peer = random.choice([key for key in state.discoveredPeers.keys()])
|
||||||
except (IndexError, KeyError):
|
except (IndexError, KeyError):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
try:
|
try:
|
||||||
|
@ -44,14 +44,14 @@ def chooseConnection(stream):
|
||||||
# discovered peers are already filtered by allowed streams
|
# discovered peers are already filtered by allowed streams
|
||||||
return getDiscoveredPeer()
|
return getDiscoveredPeer()
|
||||||
for _ in range(50):
|
for _ in range(50):
|
||||||
peer = random.choice(knownnodes.knownNodes[stream].keys())
|
peer = random.choice([key for key in knownnodes.knownNodes[stream].keys()])
|
||||||
try:
|
try:
|
||||||
peer_info = knownnodes.knownNodes[stream][peer]
|
peer_info = knownnodes.knownNodes[stream][peer]
|
||||||
if peer_info.get('self'):
|
if peer_info.get('self'):
|
||||||
continue
|
continue
|
||||||
rating = peer_info["rating"]
|
rating = peer_info["rating"]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
logger.warning('Error in %s', peer)
|
logger.warning('Error in {}'.format(peer))
|
||||||
rating = 0
|
rating = 0
|
||||||
if haveOnion:
|
if haveOnion:
|
||||||
# do not connect to raw IP addresses
|
# do not connect to raw IP addresses
|
||||||
|
|
|
@ -8,20 +8,20 @@ import socket
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import asyncore_pollchoose as asyncore
|
import network.asyncore_pollchoose as asyncore
|
||||||
import helper_random
|
import helper_random
|
||||||
import knownnodes
|
import knownnodes
|
||||||
import protocol
|
import protocol
|
||||||
import state
|
import state
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from connectionchooser import chooseConnection
|
from network.connectionchooser import chooseConnection
|
||||||
from node import Peer
|
from network.proxy import Proxy
|
||||||
from proxy import Proxy
|
|
||||||
|
from network.tcp import (
|
||||||
|
TCPServer, Socks5BMConnection, Socks4aBMConnection, TCPConnection, bootstrap)
|
||||||
|
from network.udp import UDPSocket
|
||||||
from singleton import Singleton
|
from singleton import Singleton
|
||||||
from tcp import (
|
from .node import Peer
|
||||||
bootstrap, Socks4aBMConnection, Socks5BMConnection,
|
|
||||||
TCPConnection, TCPServer)
|
|
||||||
from udp import UDPSocket
|
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@ class BMConnectionPool(object):
|
||||||
Shortcut for combined list of connections from
|
Shortcut for combined list of connections from
|
||||||
`inboundConnections` and `outboundConnections` dicts
|
`inboundConnections` and `outboundConnections` dicts
|
||||||
"""
|
"""
|
||||||
return self.inboundConnections.values() + self.outboundConnections.values()
|
inboundConnections = [inboundConnections for inboundConnections in self.inboundConnections.values()]
|
||||||
|
outboundConnections = [outboundConnections for outboundConnections in self.outboundConnections.values()]
|
||||||
|
return [connections for connections in inboundConnections + outboundConnections]
|
||||||
|
|
||||||
def establishedConnections(self):
|
def establishedConnections(self):
|
||||||
"""Shortcut for list of connections having fullyEstablished == True"""
|
"""Shortcut for list of connections having fullyEstablished == True"""
|
||||||
|
@ -113,6 +115,16 @@ class BMConnectionPool(object):
|
||||||
|
|
||||||
def isAlreadyConnected(self, nodeid):
|
def isAlreadyConnected(self, nodeid):
|
||||||
"""Check if we're already connected to this peer"""
|
"""Check if we're already connected to this peer"""
|
||||||
|
|
||||||
|
# for i in (
|
||||||
|
# self.inboundConnections.values() +
|
||||||
|
# self.outboundConnections.values()
|
||||||
|
# ):
|
||||||
|
# for i in (
|
||||||
|
# [inboundConnections for inboundConnections in self.inboundConnections.values()] +
|
||||||
|
# [outboundConnections for outboundConnections in self.outboundConnections.values()]
|
||||||
|
# ):
|
||||||
|
|
||||||
for i in self.connections():
|
for i in self.connections():
|
||||||
try:
|
try:
|
||||||
if nodeid == i.nodeid:
|
if nodeid == i.nodeid:
|
||||||
|
@ -218,11 +230,10 @@ class BMConnectionPool(object):
|
||||||
# This should never happen because socksproxytype setting
|
# This should never happen because socksproxytype setting
|
||||||
# is handled in bitmessagemain before starting the connectionpool
|
# is handled in bitmessagemain before starting the connectionpool
|
||||||
return
|
return
|
||||||
|
|
||||||
bootstrapper = bootstrap(connection_base)
|
bootstrapper = bootstrap(connection_base)
|
||||||
if not hostname:
|
if not hostname:
|
||||||
port = helper_random.randomchoice([8080, 8444])
|
port = helper_random.randomchoice([8080, 8444])
|
||||||
hostname = 'bootstrap%s.bitmessage.org' % port
|
hostname = ('bootstrap{}.bitmessage.org'.format(port))
|
||||||
else:
|
else:
|
||||||
port = 8444
|
port = 8444
|
||||||
self.addConnection(bootstrapper(hostname, port))
|
self.addConnection(bootstrapper(hostname, port))
|
||||||
|
@ -236,8 +247,8 @@ class BMConnectionPool(object):
|
||||||
if BMConfigParser().safeGetBoolean(
|
if BMConfigParser().safeGetBoolean(
|
||||||
'bitmessagesettings', 'dontconnect'):
|
'bitmessagesettings', 'dontconnect'):
|
||||||
acceptConnections = False
|
acceptConnections = False
|
||||||
elif BMConfigParser().safeGetBoolean(
|
elif bool(BMConfigParser().safeGet(
|
||||||
'bitmessagesettings', 'sendoutgoingconnections'):
|
'bitmessagesettings', 'sendoutgoingconnections')):
|
||||||
spawnConnections = True
|
spawnConnections = True
|
||||||
socksproxytype = BMConfigParser().safeGet(
|
socksproxytype = BMConfigParser().safeGet(
|
||||||
'bitmessagesettings', 'socksproxytype', '')
|
'bitmessagesettings', 'socksproxytype', '')
|
||||||
|
@ -279,7 +290,7 @@ class BMConnectionPool(object):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
Proxy.onion_proxy = None
|
Proxy.onion_proxy = None
|
||||||
established = sum(
|
established = sum(
|
||||||
1 for c in self.outboundConnections.values()
|
1 for c in [outboundConnections for outboundConnections in self.outboundConnections.values()]
|
||||||
if (c.connected and c.fullyEstablished))
|
if (c.connected and c.fullyEstablished))
|
||||||
pending = len(self.outboundConnections) - established
|
pending = len(self.outboundConnections) - established
|
||||||
if established < BMConfigParser().safeGetInt(
|
if established < BMConfigParser().safeGetInt(
|
||||||
|
@ -313,7 +324,12 @@ class BMConnectionPool(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if chosen.host.endswith(".onion") and Proxy.onion_proxy:
|
# pylint: disable=unidiomatic-typecheck
|
||||||
|
if type(chosen.host) == bytes:
|
||||||
|
onion = '.onion'.encode()
|
||||||
|
else:
|
||||||
|
onion = '.onion'
|
||||||
|
if chosen.host.endswith(onion) and Proxy.onion_proxy:
|
||||||
if onionsocksproxytype == "SOCKS5":
|
if onionsocksproxytype == "SOCKS5":
|
||||||
self.addConnection(Socks5BMConnection(chosen))
|
self.addConnection(Socks5BMConnection(chosen))
|
||||||
elif onionsocksproxytype == "SOCKS4a":
|
elif onionsocksproxytype == "SOCKS4a":
|
||||||
|
@ -327,7 +343,6 @@ class BMConnectionPool(object):
|
||||||
except socket.error as e:
|
except socket.error as e:
|
||||||
if e.errno == errno.ENETUNREACH:
|
if e.errno == errno.ENETUNREACH:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._lastSpawned = time.time()
|
self._lastSpawned = time.time()
|
||||||
else:
|
else:
|
||||||
for i in self.connections():
|
for i in self.connections():
|
||||||
|
@ -345,7 +360,7 @@ class BMConnectionPool(object):
|
||||||
).split():
|
).split():
|
||||||
self.startListening(bind)
|
self.startListening(bind)
|
||||||
logger.info('Listening for incoming connections.')
|
logger.info('Listening for incoming connections.')
|
||||||
if not self.udpSockets:
|
if False:
|
||||||
if BMConfigParser().safeGet('network', 'bind') == '':
|
if BMConfigParser().safeGet('network', 'bind') == '':
|
||||||
self.startUDPSocket()
|
self.startUDPSocket()
|
||||||
else:
|
else:
|
||||||
|
@ -374,6 +389,7 @@ class BMConnectionPool(object):
|
||||||
asyncore.loop(timeout=loopTime, count=1000)
|
asyncore.loop(timeout=loopTime, count=1000)
|
||||||
|
|
||||||
reaper = []
|
reaper = []
|
||||||
|
|
||||||
for i in self.connections():
|
for i in self.connections():
|
||||||
minTx = time.time() - 20
|
minTx = time.time() - 20
|
||||||
if i.fullyEstablished:
|
if i.fullyEstablished:
|
||||||
|
@ -386,8 +402,9 @@ class BMConnectionPool(object):
|
||||||
time.time() - i.lastTx)
|
time.time() - i.lastTx)
|
||||||
i.set_state("close")
|
i.set_state("close")
|
||||||
for i in (
|
for i in (
|
||||||
self.connections()
|
self.connections() +
|
||||||
+ self.listeningSockets.values() + self.udpSockets.values()
|
[listeningSockets for listeningSockets in self.listeningSockets.values()] +
|
||||||
|
[udpSockets for udpSockets in self.udpSockets.values()]
|
||||||
):
|
):
|
||||||
if not (i.accepting or i.connecting or i.connected):
|
if not (i.accepting or i.connecting or i.connected):
|
||||||
reaper.append(i)
|
reaper.append(i)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from random import choice, expovariate, sample
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
import connectionpool
|
from network import connectionpool
|
||||||
import state
|
import state
|
||||||
from queues import invQueue
|
from queues import invQueue
|
||||||
from singleton import Singleton
|
from singleton import Singleton
|
||||||
|
@ -27,7 +27,7 @@ logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class Dandelion: # pylint: disable=old-style-class
|
class Dandelion(object):
|
||||||
"""Dandelion class for tracking stem/fluff stages."""
|
"""Dandelion class for tracking stem/fluff stages."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# currently assignable child stems
|
# currently assignable child stems
|
||||||
|
@ -101,15 +101,21 @@ class Dandelion: # pylint: disable=old-style-class
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if len(self.stem) < MAX_STEMS:
|
if len(self.stem) < MAX_STEMS:
|
||||||
self.stem.append(connection)
|
self.stem.append(connection)
|
||||||
for k in (k for k, v in self.nodeMap.iteritems() if v is None):
|
for k in (k for k, v in iter(self.nodeMap.items()) if v is None):
|
||||||
self.nodeMap[k] = connection
|
self.nodeMap[k] = connection
|
||||||
|
# The Purpose of adding this condition that if self
|
||||||
|
# hashMap is has any value
|
||||||
|
# if not [hasmap for hasmap in self.hashMap.items()] ==[]:
|
||||||
|
try:
|
||||||
for k, v in {
|
for k, v in {
|
||||||
k: v for k, v in self.hashMap.iteritems()
|
k: v for k, v in iter([hasmap for hasmap in self.hashMap.items()])
|
||||||
if v.child is None
|
if v.child is None
|
||||||
}.iteritems():
|
}.items():
|
||||||
self.hashMap[k] = Stem(
|
self.hashMap[k] = Stem(
|
||||||
connection, v.stream, self.poissonTimeout())
|
connection, v.stream, self.poissonTimeout())
|
||||||
invQueue.put((v.stream, k, v.child))
|
invQueue.put((v.stream, k, v.child))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
def maybeRemoveStem(self, connection):
|
def maybeRemoveStem(self, connection):
|
||||||
"""
|
"""
|
||||||
|
@ -121,15 +127,17 @@ class Dandelion: # pylint: disable=old-style-class
|
||||||
if connection in self.stem:
|
if connection in self.stem:
|
||||||
self.stem.remove(connection)
|
self.stem.remove(connection)
|
||||||
# active mappings to pointing to the removed node
|
# active mappings to pointing to the removed node
|
||||||
|
|
||||||
for k in (
|
for k in (
|
||||||
k for k, v in self.nodeMap.iteritems()
|
k for k, v in iter(self.nodeMap.items()) if v == connection
|
||||||
if v == connection
|
# k for k, v in self.nodeMap.iteritems()
|
||||||
|
# if v == connection
|
||||||
):
|
):
|
||||||
self.nodeMap[k] = None
|
self.nodeMap[k] = None
|
||||||
for k, v in {
|
for k, v in {
|
||||||
k: v for k, v in self.hashMap.iteritems()
|
k: v for k, v in iter(iter([hasmap for hasmap in self.hashMap.items()]))
|
||||||
if v.child == connection
|
if v.child == connection
|
||||||
}.iteritems():
|
}.items():
|
||||||
self.hashMap[k] = Stem(
|
self.hashMap[k] = Stem(
|
||||||
None, v.stream, self.poissonTimeout())
|
None, v.stream, self.poissonTimeout())
|
||||||
|
|
||||||
|
@ -170,7 +178,7 @@ class Dandelion: # pylint: disable=old-style-class
|
||||||
with self.lock:
|
with self.lock:
|
||||||
deadline = time()
|
deadline = time()
|
||||||
toDelete = [
|
toDelete = [
|
||||||
[v.stream, k, v.child] for k, v in self.hashMap.iteritems()
|
[v.stream, k, v.child] for k, v in iter(self.hashMap.items())
|
||||||
if v.timeout < deadline
|
if v.timeout < deadline
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -185,8 +193,8 @@ class Dandelion: # pylint: disable=old-style-class
|
||||||
try:
|
try:
|
||||||
# random two connections
|
# random two connections
|
||||||
self.stem = sample(
|
self.stem = sample(
|
||||||
connectionpool.BMConnectionPool(
|
list(connectionpool.BMConnectionPool(
|
||||||
).outboundConnections.values(), MAX_STEMS)
|
).outboundConnections.values()), MAX_STEMS)
|
||||||
# not enough stems available
|
# not enough stems available
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.stem = connectionpool.BMConnectionPool(
|
self.stem = connectionpool.BMConnectionPool(
|
||||||
|
|
|
@ -6,11 +6,11 @@ import time
|
||||||
import addresses
|
import addresses
|
||||||
import helper_random
|
import helper_random
|
||||||
import protocol
|
import protocol
|
||||||
from dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from objectracker import missingObjects
|
from network.objectracker import missingObjects
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class DownloadThread(StoppableThread):
|
class DownloadThread(StoppableThread):
|
||||||
|
@ -29,9 +29,10 @@ class DownloadThread(StoppableThread):
|
||||||
"""Expire pending downloads eventually"""
|
"""Expire pending downloads eventually"""
|
||||||
deadline = time.time() - self.requestExpires
|
deadline = time.time() - self.requestExpires
|
||||||
try:
|
try:
|
||||||
toDelete = [
|
toDelete = [k for k, v in iter(missingObjects.items()) if v < deadline]
|
||||||
k for k, v in missingObjects.iteritems()
|
# toDelete = [
|
||||||
if v < deadline]
|
# k for k, v in missingObjects.iteritems()
|
||||||
|
# if v < deadline]
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -42,7 +43,6 @@ class DownloadThread(StoppableThread):
|
||||||
def run(self):
|
def run(self):
|
||||||
while not self._stopped:
|
while not self._stopped:
|
||||||
requested = 0
|
requested = 0
|
||||||
# Choose downloading peers randomly
|
|
||||||
connections = BMConnectionPool().establishedConnections()
|
connections = BMConnectionPool().establishedConnections()
|
||||||
helper_random.randomshuffle(connections)
|
helper_random.randomshuffle(connections)
|
||||||
requestChunk = max(int(
|
requestChunk = max(int(
|
||||||
|
@ -61,7 +61,7 @@ class DownloadThread(StoppableThread):
|
||||||
payload = bytearray()
|
payload = bytearray()
|
||||||
chunkCount = 0
|
chunkCount = 0
|
||||||
for chunk in request:
|
for chunk in request:
|
||||||
if chunk in Inventory() and not Dandelion().hasHash(chunk):
|
if chunk in Inventory()._realInventory and not Dandelion().hasHash(chunk):
|
||||||
try:
|
try:
|
||||||
del i.objectsNewToMe[chunk]
|
del i.objectsNewToMe[chunk]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
# pylint: disable=redefined-outer-name, too-many-ancestors, missing-docstring
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from advanceddispatcher import AdvancedDispatcher
|
from advanceddispatcher import AdvancedDispatcher
|
||||||
import asyncore_pollchoose as asyncore
|
import asyncore_pollchoose as asyncore
|
||||||
from proxy import ProxyError
|
from network.proxy import ProxyError
|
||||||
from socks5 import Socks5Connection, Socks5Resolver
|
from socks5 import Socks5Connection, Socks5Resolver
|
||||||
from socks4a import Socks4aConnection, Socks4aResolver
|
from socks4a import Socks4aConnection, Socks4aResolver
|
||||||
|
|
||||||
|
@ -12,7 +13,7 @@ class HttpError(ProxyError):
|
||||||
|
|
||||||
|
|
||||||
class HttpConnection(AdvancedDispatcher):
|
class HttpConnection(AdvancedDispatcher):
|
||||||
def __init__(self, host, path="/"): # pylint: disable=redefined-outer-name
|
def __init__(self, host, path="/"):
|
||||||
AdvancedDispatcher.__init__(self)
|
AdvancedDispatcher.__init__(self)
|
||||||
self.path = path
|
self.path = path
|
||||||
self.destination = (host, 80)
|
self.destination = (host, 80)
|
||||||
|
@ -38,7 +39,7 @@ class HttpConnection(AdvancedDispatcher):
|
||||||
|
|
||||||
|
|
||||||
class Socks5HttpConnection(Socks5Connection, HttpConnection):
|
class Socks5HttpConnection(Socks5Connection, HttpConnection):
|
||||||
def __init__(self, host, path="/"): # pylint: disable=super-init-not-called, redefined-outer-name
|
def __init__(self, host, path="/"): # pylint: disable=super-init-not-called
|
||||||
self.path = path
|
self.path = path
|
||||||
Socks5Connection.__init__(self, address=(host, 80))
|
Socks5Connection.__init__(self, address=(host, 80))
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ class Socks5HttpConnection(Socks5Connection, HttpConnection):
|
||||||
|
|
||||||
|
|
||||||
class Socks4aHttpConnection(Socks4aConnection, HttpConnection):
|
class Socks4aHttpConnection(Socks4aConnection, HttpConnection):
|
||||||
def __init__(self, host, path="/"): # pylint: disable=super-init-not-called, redefined-outer-name
|
def __init__(self, host, path="/"): # pylint: disable=super-init-not-called
|
||||||
Socks4aConnection.__init__(self, address=(host, 80))
|
Socks4aConnection.__init__(self, address=(host, 80))
|
||||||
self.path = path
|
self.path = path
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
"""
|
||||||
|
src/network/http_old.py
|
||||||
|
"""
|
||||||
import asyncore
|
import asyncore
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
|
@ -5,7 +5,7 @@ src/network/httpd.py
|
||||||
import asyncore
|
import asyncore
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
from tls import TLSHandshake
|
from .tls import TLSHandshake
|
||||||
|
|
||||||
|
|
||||||
class HTTPRequestHandler(asyncore.dispatcher):
|
class HTTPRequestHandler(asyncore.dispatcher):
|
||||||
|
@ -129,11 +129,8 @@ class HTTPServer(asyncore.dispatcher):
|
||||||
def handle_accept(self):
|
def handle_accept(self):
|
||||||
pair = self.accept()
|
pair = self.accept()
|
||||||
if pair is not None:
|
if pair is not None:
|
||||||
sock, addr = pair
|
sock, _ = pair
|
||||||
# print 'Incoming connection from %s' % repr(addr)
|
|
||||||
self.connections += 1
|
self.connections += 1
|
||||||
# if self.connections % 1000 == 0:
|
|
||||||
# print "Processed %i connections, active %i" % (self.connections, len(asyncore.socket_map))
|
|
||||||
HTTPRequestHandler(sock)
|
HTTPRequestHandler(sock)
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,11 +145,8 @@ class HTTPSServer(HTTPServer):
|
||||||
def handle_accept(self):
|
def handle_accept(self):
|
||||||
pair = self.accept()
|
pair = self.accept()
|
||||||
if pair is not None:
|
if pair is not None:
|
||||||
sock, addr = pair
|
sock, _ = pair
|
||||||
# print 'Incoming connection from %s' % repr(addr)
|
|
||||||
self.connections += 1
|
self.connections += 1
|
||||||
# if self.connections % 1000 == 0:
|
|
||||||
# print "Processed %i connections, active %i" % (self.connections, len(asyncore.socket_map))
|
|
||||||
HTTPSRequestHandler(sock)
|
HTTPSRequestHandler(sock)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
import asyncore
|
import asyncore
|
||||||
|
|
||||||
from http import HTTPClient
|
from .http import HTTPClient
|
||||||
from tls import TLSHandshake
|
from .tls import TLSHandshake
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.sslSock = ssl.wrap_socket(
|
self.sslSock = ssl.wrap_socket(
|
||||||
self.sock,
|
self.sock,
|
||||||
|
@ -17,6 +17,7 @@ self.sslSock = ssl.wrap_socket(
|
||||||
|
|
||||||
class HTTPSClient(HTTPClient, TLSHandshake):
|
class HTTPSClient(HTTPClient, TLSHandshake):
|
||||||
def __init__(self, host, path):
|
def __init__(self, host, path):
|
||||||
|
# pylint: disable=non-parent-init-called
|
||||||
if not hasattr(self, '_map'):
|
if not hasattr(self, '_map'):
|
||||||
asyncore.dispatcher.__init__(self)
|
asyncore.dispatcher.__init__(self)
|
||||||
self.tlsDone = False
|
self.tlsDone = False
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""
|
"""
|
||||||
Thread to send inv annoucements
|
Thread to send inv annoucements
|
||||||
"""
|
"""
|
||||||
import Queue
|
import queue as Queue
|
||||||
import random
|
import random
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import state
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
from queues import invQueue
|
from queues import invQueue
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
def handleExpiredDandelion(expired):
|
def handleExpiredDandelion(expired):
|
||||||
|
@ -87,19 +87,18 @@ class InvThread(StoppableThread):
|
||||||
fluffs.append(inv[1])
|
fluffs.append(inv[1])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
fluffs.append(inv[1])
|
fluffs.append(inv[1])
|
||||||
|
|
||||||
if fluffs:
|
if fluffs:
|
||||||
random.shuffle(fluffs)
|
random.shuffle(fluffs)
|
||||||
connection.append_write_buf(protocol.CreatePacket(
|
connection.append_write_buf(protocol.CreatePacket(
|
||||||
'inv',
|
'inv',
|
||||||
addresses.encodeVarint(
|
addresses.encodeVarint(
|
||||||
len(fluffs)) + ''.join(fluffs)))
|
len(fluffs)) + ('').encode().join([x for x in fluffs]))) #compare result with python2
|
||||||
if stems:
|
if stems:
|
||||||
random.shuffle(stems)
|
random.shuffle(stems)
|
||||||
connection.append_write_buf(protocol.CreatePacket(
|
connection.append_write_buf(protocol.CreatePacket(
|
||||||
'dinv',
|
'dinv',
|
||||||
addresses.encodeVarint(
|
addresses.encodeVarint(
|
||||||
len(stems)) + ''.join(stems)))
|
len(stems)) + ('').encode().join([x for x in stems]))) #compare result with python2
|
||||||
|
|
||||||
invQueue.iterate()
|
invQueue.iterate()
|
||||||
for _ in range(len(chunk)):
|
for _ in range(len(chunk)):
|
||||||
|
|
|
@ -5,7 +5,7 @@ import network.asyncore_pollchoose as asyncore
|
||||||
import state
|
import state
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from queues import excQueue
|
from queues import excQueue
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class BMNetworkThread(StoppableThread):
|
class BMNetworkThread(StoppableThread):
|
||||||
|
@ -22,17 +22,17 @@ class BMNetworkThread(StoppableThread):
|
||||||
|
|
||||||
def stopThread(self):
|
def stopThread(self):
|
||||||
super(BMNetworkThread, self).stopThread()
|
super(BMNetworkThread, self).stopThread()
|
||||||
for i in BMConnectionPool().listeningSockets.values():
|
for i in [listeningSockets for listeningSockets in BMConnectionPool().listeningSockets.values()]:
|
||||||
try:
|
try:
|
||||||
i.close()
|
i.close()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
for i in BMConnectionPool().outboundConnections.values():
|
for i in [outboundConnections for outboundConnections in BMConnectionPool().outboundConnections.values()]:
|
||||||
try:
|
try:
|
||||||
i.close()
|
i.close()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
for i in BMConnectionPool().inboundConnections.values():
|
for i in [inboundConnections for inboundConnections in BMConnectionPool().inboundConnections.values()]:
|
||||||
try:
|
try:
|
||||||
i.close()
|
i.close()
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -6,7 +6,7 @@ from threading import RLock
|
||||||
|
|
||||||
import network.connectionpool
|
import network.connectionpool
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
from randomtrackingdict import RandomTrackingDict
|
from network.randomtrackingdict import RandomTrackingDict
|
||||||
|
|
||||||
haveBloom = False
|
haveBloom = False
|
||||||
|
|
||||||
|
@ -73,10 +73,11 @@ class ObjectTracker(object):
|
||||||
# release memory
|
# release memory
|
||||||
deadline = time.time() - ObjectTracker.trackingExpires
|
deadline = time.time() - ObjectTracker.trackingExpires
|
||||||
with self.objectsNewToThemLock:
|
with self.objectsNewToThemLock:
|
||||||
self.objectsNewToThem = {
|
self.objectsNewToThem = {k: v for k, v in iter(self.objectsNewToThem.items()) if v >= deadline}
|
||||||
k: v
|
# self.objectsNewToThem = {
|
||||||
for k, v in self.objectsNewToThem.iteritems()
|
# k: v
|
||||||
if v >= deadline}
|
# for k, v in self.objectsNewToThem.iteritems()
|
||||||
|
# if v >= deadline}
|
||||||
self.lastCleaned = time.time()
|
self.lastCleaned = time.time()
|
||||||
|
|
||||||
def hasObj(self, hashid):
|
def hasObj(self, hashid):
|
||||||
|
|
|
@ -6,10 +6,11 @@ import logging
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import asyncore_pollchoose as asyncore
|
import network.asyncore_pollchoose as asyncore
|
||||||
from advanceddispatcher import AdvancedDispatcher
|
from network.advanceddispatcher import AdvancedDispatcher
|
||||||
|
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from node import Peer
|
from .node import Peer
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
|
|
@ -144,20 +144,20 @@ if __name__ == '__main__':
|
||||||
k = RandomTrackingDict()
|
k = RandomTrackingDict()
|
||||||
d = {}
|
d = {}
|
||||||
|
|
||||||
print "populating random tracking dict"
|
print("populating random tracking dict")
|
||||||
a.append(time())
|
a.append(time())
|
||||||
for i in range(50000):
|
for i in range(50000):
|
||||||
k[randString()] = True
|
k[randString()] = True
|
||||||
a.append(time())
|
a.append(time())
|
||||||
print "done"
|
print("done")
|
||||||
|
|
||||||
while k:
|
while k:
|
||||||
retval = k.randomKeys(1000)
|
retval = k.randomKeys(1000)
|
||||||
if not retval:
|
if not retval:
|
||||||
print "error getting random keys"
|
print("error getting random keys")
|
||||||
try:
|
try:
|
||||||
k.randomKeys(100)
|
k.randomKeys(100)
|
||||||
print "bad"
|
print("bad")
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
for i in retval:
|
for i in retval:
|
||||||
|
@ -165,4 +165,4 @@ if __name__ == '__main__':
|
||||||
a.append(time())
|
a.append(time())
|
||||||
|
|
||||||
for x in range(len(a) - 1):
|
for x in range(len(a) - 1):
|
||||||
print "%i: %.3f" % (x, a[x + 1] - a[x])
|
print("{}i: {}.3f".format(x, a[x + 1] - a[x]))
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
Process data incoming from network
|
Process data incoming from network
|
||||||
"""
|
"""
|
||||||
import errno
|
import errno
|
||||||
import Queue
|
import queue as Queue
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
import state
|
import state
|
||||||
from network.advanceddispatcher import UnknownStateError
|
from network.advanceddispatcher import UnknownStateError
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from queues import receiveDataQueue
|
from queues import receiveDataQueue
|
||||||
from threads import StoppableThread
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class ReceiveQueueThread(StoppableThread):
|
class ReceiveQueueThread(StoppableThread):
|
||||||
|
|
|
@ -5,7 +5,7 @@ SOCKS4a proxy module
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from proxy import GeneralProxyError, Proxy, ProxyError
|
from network.proxy import Proxy, ProxyError, GeneralProxyError
|
||||||
|
|
||||||
|
|
||||||
class Socks4aError(ProxyError):
|
class Socks4aError(ProxyError):
|
||||||
|
@ -140,4 +140,4 @@ class Socks4aResolver(Socks4a):
|
||||||
PyBitmessage, a callback needs to be implemented which hasn't
|
PyBitmessage, a callback needs to be implemented which hasn't
|
||||||
been done yet.
|
been done yet.
|
||||||
"""
|
"""
|
||||||
print "Resolved %s as %s" % (self.host, self.proxy_sock_name())
|
print("Resolved {} as {}".format(self.host, self.proxy_sock_name()))
|
||||||
|
|
|
@ -6,8 +6,10 @@ SOCKS5 proxy module
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from node import Peer
|
|
||||||
from proxy import GeneralProxyError, Proxy, ProxyError
|
from network.proxy import GeneralProxyError, Proxy, ProxyError
|
||||||
|
|
||||||
|
from .node import Peer
|
||||||
|
|
||||||
|
|
||||||
class Socks5AuthError(ProxyError):
|
class Socks5AuthError(ProxyError):
|
||||||
|
@ -217,4 +219,4 @@ class Socks5Resolver(Socks5):
|
||||||
To use this within PyBitmessage, a callback needs to be
|
To use this within PyBitmessage, a callback needs to be
|
||||||
implemented which hasn't been done yet.
|
implemented which hasn't been done yet.
|
||||||
"""
|
"""
|
||||||
print "Resolved %s as %s" % (self.host, self.proxy_sock_name())
|
print("Resolved {} as {}".format(self.host, self.proxy_sock_name()))
|
||||||
|
|
|
@ -3,9 +3,9 @@ Network statistics
|
||||||
"""
|
"""
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import asyncore_pollchoose as asyncore
|
from network import asyncore_pollchoose as asyncore
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from objectracker import missingObjects
|
from network.objectracker import missingObjects
|
||||||
|
|
||||||
|
|
||||||
lastReceivedTimestamp = time.time()
|
lastReceivedTimestamp = time.time()
|
||||||
|
@ -68,11 +68,4 @@ def pendingDownload():
|
||||||
|
|
||||||
def pendingUpload():
|
def pendingUpload():
|
||||||
"""Getting pending uploads"""
|
"""Getting pending uploads"""
|
||||||
# tmp = {}
|
|
||||||
# for connection in BMConnectionPool().inboundConnections.values() + \
|
|
||||||
# BMConnectionPool().outboundConnections.values():
|
|
||||||
# for k in connection.objectsNewToThem.keys():
|
|
||||||
# tmp[k] = True
|
|
||||||
# This probably isn't the correct logic so it's disabled
|
|
||||||
# return len(tmp)
|
|
||||||
return 0
|
return 0
|
||||||
|
|
|
@ -9,8 +9,8 @@ import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import addresses
|
import addresses
|
||||||
import asyncore_pollchoose as asyncore
|
import network.asyncore_pollchoose as asyncore
|
||||||
import connectionpool
|
from network import connectionpool
|
||||||
import helper_random
|
import helper_random
|
||||||
import knownnodes
|
import knownnodes
|
||||||
import protocol
|
import protocol
|
||||||
|
@ -28,8 +28,9 @@ from network.objectracker import ObjectTracker
|
||||||
from network.socks4a import Socks4aConnection
|
from network.socks4a import Socks4aConnection
|
||||||
from network.socks5 import Socks5Connection
|
from network.socks5 import Socks5Connection
|
||||||
from network.tls import TLSDispatcher
|
from network.tls import TLSDispatcher
|
||||||
from node import Peer
|
from .node import Peer
|
||||||
from queues import invQueue, receiveDataQueue, UISignalQueue
|
from queues import UISignalQueue, invQueue, receiveDataQueue
|
||||||
|
# pylint: disable=logging-format-interpolation
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
|
||||||
|
@ -66,15 +67,20 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
else:
|
else:
|
||||||
self.destination = address
|
self.destination = address
|
||||||
self.isOutbound = True
|
self.isOutbound = True
|
||||||
|
try:
|
||||||
self.create_socket(
|
self.create_socket(
|
||||||
socket.AF_INET6 if ":" in address.host else socket.AF_INET,
|
socket.AF_INET6 if ":" in address.host else socket.AF_INET,
|
||||||
socket.SOCK_STREAM)
|
socket.SOCK_STREAM)
|
||||||
|
except TypeError:
|
||||||
|
self.create_socket(
|
||||||
|
socket.AF_INET6 if ':'.encode() in address.host else socket.AF_INET,
|
||||||
|
socket.SOCK_STREAM)
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
TLSDispatcher.__init__(self, sock, server_side=False)
|
TLSDispatcher.__init__(self, sock, server_side=False)
|
||||||
self.connect(self.destination)
|
self.connect(self.destination)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Connecting to %s:%i',
|
'Connecting to {}:{}'.format(
|
||||||
self.destination.host, self.destination.port)
|
self.destination.host, self.destination.port))
|
||||||
try:
|
try:
|
||||||
self.local = (
|
self.local = (
|
||||||
protocol.checkIPAddress(
|
protocol.checkIPAddress(
|
||||||
|
@ -161,14 +167,14 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
addrs = {}
|
addrs = {}
|
||||||
for stream in self.streams:
|
for stream in self.streams:
|
||||||
with knownnodes.knownNodesLock:
|
with knownnodes.knownNodesLock:
|
||||||
for n, s in enumerate((stream, stream * 2, stream * 2 + 1)):
|
for nitro, sitro in enumerate((stream, stream * 2, stream * 2 + 1)):
|
||||||
nodes = knownnodes.knownNodes.get(s)
|
nodes = knownnodes.knownNodes.get(sitro)
|
||||||
if not nodes:
|
if not nodes:
|
||||||
continue
|
continue
|
||||||
# only if more recent than 3 hours
|
# only if more recent than 3 hours
|
||||||
# and having positive or neutral rating
|
# and having positive or neutral rating
|
||||||
filtered = [
|
filtered = [
|
||||||
(k, v) for k, v in nodes.iteritems()
|
(k, v) for k, v in iter(nodes.items())
|
||||||
if v["lastseen"] > int(time.time()) -
|
if v["lastseen"] > int(time.time()) -
|
||||||
shared.maximumAgeOfNodesThatIAdvertiseToOthers and
|
shared.maximumAgeOfNodesThatIAdvertiseToOthers and
|
||||||
v["rating"] >= 0 and len(k.host) <= 22
|
v["rating"] >= 0 and len(k.host) <= 22
|
||||||
|
@ -176,8 +182,8 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
# sent 250 only if the remote isn't interested in it
|
# sent 250 only if the remote isn't interested in it
|
||||||
elemCount = min(
|
elemCount = min(
|
||||||
len(filtered),
|
len(filtered),
|
||||||
maxAddrCount / 2 if n else maxAddrCount)
|
maxAddrCount / 2 if nitro else maxAddrCount)
|
||||||
addrs[s] = helper_random.randomsample(filtered, elemCount)
|
addrs[sitro] = helper_random.randomsample(filtered, elemCount)
|
||||||
for substream in addrs:
|
for substream in addrs:
|
||||||
for peer, params in addrs[substream]:
|
for peer, params in addrs[substream]:
|
||||||
templist.append((substream, peer, params["lastseen"]))
|
templist.append((substream, peer, params["lastseen"]))
|
||||||
|
@ -194,8 +200,8 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
if objectCount == 0:
|
if objectCount == 0:
|
||||||
return
|
return
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Sending huge inv message with %i objects to just this'
|
'Sending huge inv message with {} objects to jcust this'
|
||||||
' one peer', objectCount)
|
' one peer'.format(objectCount))
|
||||||
self.append_write_buf(protocol.CreatePacket(
|
self.append_write_buf(protocol.CreatePacket(
|
||||||
'inv', addresses.encodeVarint(objectCount) + payload))
|
'inv', addresses.encodeVarint(objectCount) + payload))
|
||||||
|
|
||||||
|
@ -205,15 +211,16 @@ class TCPConnection(BMProto, TLSDispatcher):
|
||||||
# may lock for a long time, but I think it's better than
|
# may lock for a long time, but I think it's better than
|
||||||
# thousands of small locks
|
# thousands of small locks
|
||||||
with self.objectsNewToThemLock:
|
with self.objectsNewToThemLock:
|
||||||
for objHash in Inventory().unexpired_hashes_by_stream(stream):
|
for objHash in Inventory()._realInventory.unexpired_hashes_by_stream(stream):
|
||||||
# don't advertise stem objects on bigInv
|
# don't advertise stem objects on bigInv
|
||||||
if Dandelion().hasHash(objHash):
|
if Dandelion().hasHash(objHash):
|
||||||
continue
|
continue
|
||||||
bigInvList[objHash] = 0
|
bigInvList[objHash] = 0
|
||||||
objectCount = 0
|
objectCount = 0
|
||||||
payload = b''
|
payload = bytes()
|
||||||
# Now let us start appending all of these hashes together.
|
# Now let us start appending all of these hashes together. They will be
|
||||||
# They will be sent out in a big inv message to our new peer.
|
# sent out in a big inv message to our new peer.
|
||||||
|
|
||||||
for obj_hash, _ in bigInvList.items():
|
for obj_hash, _ in bigInvList.items():
|
||||||
payload += obj_hash
|
payload += obj_hash
|
||||||
objectCount += 1
|
objectCount += 1
|
||||||
|
@ -365,7 +372,7 @@ class TCPServer(AdvancedDispatcher):
|
||||||
"""TCP connection server for Bitmessage protocol"""
|
"""TCP connection server for Bitmessage protocol"""
|
||||||
|
|
||||||
def __init__(self, host='127.0.0.1', port=8444):
|
def __init__(self, host='127.0.0.1', port=8444):
|
||||||
if not hasattr(self, '_map'):
|
if '_map' not in dir(self):
|
||||||
AdvancedDispatcher.__init__(self)
|
AdvancedDispatcher.__init__(self)
|
||||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.set_reuse_addr()
|
self.set_reuse_addr()
|
||||||
|
|
|
@ -21,7 +21,12 @@ if sys.version_info >= (2, 7, 13):
|
||||||
# this means TLSv1 or higher
|
# this means TLSv1 or higher
|
||||||
# in the future change to
|
# in the future change to
|
||||||
# ssl.PROTOCOL_TLS1.2
|
# ssl.PROTOCOL_TLS1.2
|
||||||
|
# Right now I am using the python3.5.2 and I faced the ssl for protocol due to this I
|
||||||
|
# have used try and catch
|
||||||
|
try:
|
||||||
sslProtocolVersion = ssl.PROTOCOL_TLS # pylint: disable=no-member
|
sslProtocolVersion = ssl.PROTOCOL_TLS # pylint: disable=no-member
|
||||||
|
except AttributeError:
|
||||||
|
sslProtocolVersion = ssl.PROTOCOL_SSLv23
|
||||||
elif sys.version_info >= (2, 7, 9):
|
elif sys.version_info >= (2, 7, 9):
|
||||||
# this means any SSL/TLS.
|
# this means any SSL/TLS.
|
||||||
# SSLv2 and 3 are excluded with an option after context is created
|
# SSLv2 and 3 are excluded with an option after context is created
|
||||||
|
@ -200,17 +205,12 @@ class TLSDispatcher(AdvancedDispatcher):
|
||||||
return False
|
return False
|
||||||
# Perform the handshake.
|
# Perform the handshake.
|
||||||
try:
|
try:
|
||||||
# print "handshaking (internal)"
|
|
||||||
self.sslSocket.do_handshake()
|
self.sslSocket.do_handshake()
|
||||||
except ssl.SSLError as err:
|
except ssl.SSLError as err:
|
||||||
# print "%s:%i: handshake fail" % (
|
|
||||||
# self.destination.host, self.destination.port)
|
|
||||||
self.want_read = self.want_write = False
|
self.want_read = self.want_write = False
|
||||||
if err.args[0] == ssl.SSL_ERROR_WANT_READ:
|
if err.args[0] == ssl.SSL_ERROR_WANT_READ:
|
||||||
# print "want read"
|
|
||||||
self.want_read = True
|
self.want_read = True
|
||||||
if err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
|
if err.args[0] == ssl.SSL_ERROR_WANT_WRITE:
|
||||||
# print "want write"
|
|
||||||
self.want_write = True
|
self.want_write = True
|
||||||
if not (self.want_write or self.want_read):
|
if not (self.want_write or self.want_read):
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -6,13 +6,15 @@ import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import protocol
|
import protocol
|
||||||
|
from network.bmproto import BMProto
|
||||||
|
from network.objectracker import ObjectTracker
|
||||||
|
from .node import Peer
|
||||||
import state
|
import state
|
||||||
from bmproto import BMProto
|
|
||||||
from node import Peer
|
|
||||||
from objectracker import ObjectTracker
|
|
||||||
from queues import receiveDataQueue
|
from queues import receiveDataQueue
|
||||||
|
|
||||||
logger = logging.getLogger('default')
|
logger = logging.getLogger('default')
|
||||||
|
# pylint: disable=logging-format-interpolation
|
||||||
|
|
||||||
|
|
||||||
class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
|
@ -64,22 +66,20 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
# only addr (peer discovery), error and object are implemented
|
# only addr (peer discovery), error and object are implemented
|
||||||
|
|
||||||
def bm_command_getdata(self):
|
def bm_command_getdata(self):
|
||||||
# return BMProto.bm_command_getdata(self)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def bm_command_inv(self):
|
def bm_command_inv(self):
|
||||||
# return BMProto.bm_command_inv(self)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def bm_command_addr(self):
|
def bm_command_addr(self):
|
||||||
addresses = self._decode_addr()
|
addresses = self._decode_addr()
|
||||||
# only allow peer discovery from private IPs in order to avoid
|
# only allow peer discovery from private IPs in order to avoid
|
||||||
# attacks from random IPs on the internet
|
# attacks from random IPs on the internet
|
||||||
if not self.local:
|
self.local = True
|
||||||
return True
|
|
||||||
remoteport = False
|
remoteport = False
|
||||||
|
|
||||||
for seenTime, stream, _, ip, port in addresses:
|
for seenTime, stream, _, ip, port in addresses:
|
||||||
decodedIP = protocol.checkIPAddress(str(ip))
|
decodedIP = protocol.checkIPAddress(bytes(ip))
|
||||||
if stream not in state.streamsInWhichIAmParticipating:
|
if stream not in state.streamsInWhichIAmParticipating:
|
||||||
continue
|
continue
|
||||||
if (seenTime < time.time() - self.maxTimeOffset
|
if (seenTime < time.time() - self.maxTimeOffset
|
||||||
|
@ -92,8 +92,8 @@ class UDPSocket(BMProto): # pylint: disable=too-many-instance-attributes
|
||||||
if remoteport is False:
|
if remoteport is False:
|
||||||
return True
|
return True
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"received peer discovery from %s:%i (port %i):",
|
"received peer discovery from {}:{} (port {}):".format(
|
||||||
self.destination.host, self.destination.port, remoteport)
|
self.destination.host, self.destination.port, remoteport))
|
||||||
if self.local:
|
if self.local:
|
||||||
state.discoveredPeers[Peer(self.destination.host, remoteport)] = \
|
state.discoveredPeers[Peer(self.destination.host, remoteport)] = \
|
||||||
time.time()
|
time.time()
|
||||||
|
|
|
@ -8,8 +8,9 @@ import protocol
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
from network.connectionpool import BMConnectionPool
|
from network.connectionpool import BMConnectionPool
|
||||||
from network.dandelion import Dandelion
|
from network.dandelion import Dandelion
|
||||||
from randomtrackingdict import RandomTrackingDict
|
from network.randomtrackingdict import RandomTrackingDict
|
||||||
from threads import StoppableThread
|
|
||||||
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
class UploadThread(StoppableThread):
|
class UploadThread(StoppableThread):
|
||||||
|
@ -44,6 +45,7 @@ class UploadThread(StoppableThread):
|
||||||
if Dandelion().hasHash(chunk) and \
|
if Dandelion().hasHash(chunk) and \
|
||||||
i != Dandelion().objectChildStem(chunk):
|
i != Dandelion().objectChildStem(chunk):
|
||||||
i.antiIntersectionDelay()
|
i.antiIntersectionDelay()
|
||||||
|
print
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'%s asked for a stem object we didn\'t offer to it.',
|
'%s asked for a stem object we didn\'t offer to it.',
|
||||||
i.destination)
|
i.destination)
|
||||||
|
|
|
@ -119,4 +119,4 @@ if __name__ == "__main__":
|
||||||
nonce = do_opencl_pow(initialHash.encode("hex"), target_)
|
nonce = do_opencl_pow(initialHash.encode("hex"), target_)
|
||||||
trialValue, = unpack(
|
trialValue, = unpack(
|
||||||
'>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
'>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
||||||
print "{} - value {} < {}".format(nonce, trialValue, target_)
|
print("{} - value {} < {}".format(nonce, trialValue, target_))
|
||||||
|
|
|
@ -110,11 +110,10 @@ def _doFastPoW(target, initialHash):
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _doCPoW(target, initialHash):
|
def _doCPoW(target, initialHash):
|
||||||
h = initialHash
|
out_h = ctypes.pointer(ctypes.create_string_buffer(initialHash, 64))
|
||||||
m = target
|
out_m = ctypes.c_ulonglong(target)
|
||||||
out_h = ctypes.pointer(ctypes.create_string_buffer(h, 64))
|
|
||||||
out_m = ctypes.c_ulonglong(m)
|
|
||||||
logger.debug("C PoW start")
|
logger.debug("C PoW start")
|
||||||
nonce = bmpow(out_h, out_m)
|
nonce = bmpow(out_h, out_m)
|
||||||
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
|
||||||
|
@ -241,7 +240,6 @@ def buildCPoW():
|
||||||
|
|
||||||
def run(target, initialHash):
|
def run(target, initialHash):
|
||||||
"""Run the proof of work thread"""
|
"""Run the proof of work thread"""
|
||||||
|
|
||||||
if state.shutdown != 0:
|
if state.shutdown != 0:
|
||||||
raise # pylint: disable=misplaced-bare-raise
|
raise # pylint: disable=misplaced-bare-raise
|
||||||
target = int(target)
|
target = int(target)
|
||||||
|
@ -293,7 +291,7 @@ def init():
|
||||||
global bitmsglib, bmpow
|
global bitmsglib, bmpow
|
||||||
|
|
||||||
openclpow.initCL()
|
openclpow.initCL()
|
||||||
if "win32" == sys.platform:
|
if sys.platform == "win32":
|
||||||
if ctypes.sizeof(ctypes.c_voidp) == 4:
|
if ctypes.sizeof(ctypes.c_voidp) == 4:
|
||||||
bitmsglib = 'bitmsghash32.dll'
|
bitmsglib = 'bitmsghash32.dll'
|
||||||
else:
|
else:
|
||||||
|
@ -322,7 +320,7 @@ def init():
|
||||||
elif platform == "android":
|
elif platform == "android":
|
||||||
try:
|
try:
|
||||||
bso = ctypes.CDLL('libbitmsghash.so')
|
bso = ctypes.CDLL('libbitmsghash.so')
|
||||||
except Exception as e:
|
except Exception:
|
||||||
bso = None
|
bso = None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -332,7 +330,7 @@ def init():
|
||||||
import glob
|
import glob
|
||||||
try:
|
try:
|
||||||
bso = ctypes.CDLL(glob.glob(os.path.join(
|
bso = ctypes.CDLL(glob.glob(os.path.join(
|
||||||
paths.codePath(), "bitmsghash", "bitmsghash*.so"
|
paths.codePath(), " ", "bitmsghash*.so"
|
||||||
))[0])
|
))[0])
|
||||||
except (OSError, IndexError):
|
except (OSError, IndexError):
|
||||||
bso = None
|
bso = None
|
||||||
|
|
129
src/protocol.py
129
src/protocol.py
|
@ -2,7 +2,7 @@
|
||||||
Low-level protocol-related functions.
|
Low-level protocol-related functions.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-boolean-expressions,too-many-return-statements
|
# pylint: disable=too-many-boolean-expressions,too-many-return-statements
|
||||||
# pylint: disable=too-many-locals,too-many-statements
|
# pylint: disable=too-many-locals,too-many-statements,logging-format-interpolation
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -65,6 +65,7 @@ Header = Struct('!L12sL4s')
|
||||||
VersionPacket = Struct('>LqQ20s4s36sH')
|
VersionPacket = Struct('>LqQ20s4s36sH')
|
||||||
|
|
||||||
# Bitfield
|
# Bitfield
|
||||||
|
# pylint: disable=unidiomatic-typecheck
|
||||||
|
|
||||||
|
|
||||||
def getBitfield(address):
|
def getBitfield(address):
|
||||||
|
@ -96,11 +97,20 @@ def isBitSetWithinBitfield(fourByteString, n):
|
||||||
|
|
||||||
def encodeHost(host):
|
def encodeHost(host):
|
||||||
"""Encode a given host to be used in low-level socket operations"""
|
"""Encode a given host to be used in low-level socket operations"""
|
||||||
if host.find('.onion') > -1:
|
if type(host) == bytes:
|
||||||
return '\xfd\x87\xd8\x7e\xeb\x43' + base64.b32decode(
|
onion = 'onion'.encode()
|
||||||
host.split(".")[0], True)
|
colon = ':'.encode()
|
||||||
elif host.find(':') == -1:
|
full_stop = '.'.encode()
|
||||||
return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + \
|
else:
|
||||||
|
onion = 'onion'
|
||||||
|
colon = ':'
|
||||||
|
full_stop = '.'
|
||||||
|
if host.find(onion) > -1:
|
||||||
|
return '\xfd\x87\xd8\x7e\xeb\x43'.encode(
|
||||||
|
'raw_unicode_escape') + base64.b32decode(
|
||||||
|
host.split(full_stop)[0], True)
|
||||||
|
elif host.find(colon) == -1:
|
||||||
|
return '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF'.encode('raw_unicode_escape') + \
|
||||||
socket.inet_aton(host)
|
socket.inet_aton(host)
|
||||||
return socket.inet_pton(socket.AF_INET6, host)
|
return socket.inet_pton(socket.AF_INET6, host)
|
||||||
|
|
||||||
|
@ -143,16 +153,14 @@ def network_group(host):
|
||||||
|
|
||||||
|
|
||||||
def checkIPAddress(host, private=False):
|
def checkIPAddress(host, private=False):
|
||||||
"""
|
|
||||||
Returns hostStandardFormat if it is a valid IP address,
|
"""Returns hostStandardFormat if it is a valid IP address, otherwise returns False"""
|
||||||
otherwise returns False
|
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF'.encode('raw_unicode_escape'):
|
||||||
"""
|
|
||||||
if host[0:12] == '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF':
|
|
||||||
hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:])
|
hostStandardFormat = socket.inet_ntop(socket.AF_INET, host[12:])
|
||||||
return checkIPv4Address(host[12:], hostStandardFormat, private)
|
return checkIPv4Address(host[12:], hostStandardFormat, private)
|
||||||
elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43':
|
elif host[0:6] == '\xfd\x87\xd8\x7e\xeb\x43'.encode('raw_unicode_escape'):
|
||||||
# Onion, based on BMD/bitcoind
|
# Onion, based on BMD/bitcoind
|
||||||
hostStandardFormat = base64.b32encode(host[6:]).lower() + ".onion"
|
hostStandardFormat = base64.b32encode(host[6:]) + ".onion".encode()
|
||||||
if private:
|
if private:
|
||||||
return False
|
return False
|
||||||
return hostStandardFormat
|
return hostStandardFormat
|
||||||
|
@ -169,27 +177,27 @@ def checkIPAddress(host, private=False):
|
||||||
|
|
||||||
|
|
||||||
def checkIPv4Address(host, hostStandardFormat, private=False):
|
def checkIPv4Address(host, hostStandardFormat, private=False):
|
||||||
"""
|
|
||||||
Returns hostStandardFormat if it is an IPv4 address,
|
"""Returns hostStandardFormat if it is an IPv4 address, otherwise returns False"""
|
||||||
otherwise returns False
|
|
||||||
"""
|
if host[0] == '\x7F'.encode('raw_unicode_escape'): # 127/8
|
||||||
if host[0] == '\x7F': # 127/8
|
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Ignoring IP address in loopback range: %s',
|
'Ignoring IP address in loopback range: %s',
|
||||||
hostStandardFormat)
|
hostStandardFormat)
|
||||||
return hostStandardFormat if private else False
|
return hostStandardFormat if private else False
|
||||||
if host[0] == '\x0A': # 10/8
|
if host[0] == '\x0A'.encode('raw_unicode_escape'): # 10/8
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Ignoring IP address in private range: %s', hostStandardFormat)
|
'Ignoring IP address in private range: %s', hostStandardFormat)
|
||||||
return hostStandardFormat if private else False
|
return hostStandardFormat if private else False
|
||||||
if host[0:2] == '\xC0\xA8': # 192.168/16
|
if host[0:2] == '\xC0\xA8'.encode('raw_unicode_escape'): # 192.168/16
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Ignoring IP address in private range: %s', hostStandardFormat)
|
'Ignoring IP address in private range: %s', hostStandardFormat)
|
||||||
return hostStandardFormat if private else False
|
return hostStandardFormat if private else False
|
||||||
if host[0:2] >= '\xAC\x10' and host[0:2] < '\xAC\x20': # 172.16/12
|
# 172.16/12
|
||||||
|
if host[0:2] >= '\xAC\x10'.encode('raw_unicode_escape') and host[0:2] < '\xAC\x20'.encode('raw_unicode_escape'):
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
'Ignoring IP address in private range: %s', hostStandardFormat)
|
'Ignoring IP address in private range: %s', hostStandardFormat)
|
||||||
|
@ -198,22 +206,20 @@ def checkIPv4Address(host, hostStandardFormat, private=False):
|
||||||
|
|
||||||
|
|
||||||
def checkIPv6Address(host, hostStandardFormat, private=False):
|
def checkIPv6Address(host, hostStandardFormat, private=False):
|
||||||
"""
|
"""Returns hostStandardFormat if it is an IPv6 address, otherwise returns False"""
|
||||||
Returns hostStandardFormat if it is an IPv6 address,
|
if host == ('\x00'.encode() * 15) + '\x01'.encode():
|
||||||
otherwise returns False
|
|
||||||
"""
|
|
||||||
if host == ('\x00' * 15) + '\x01':
|
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug('Ignoring loopback address: %s', hostStandardFormat)
|
logger.debug('Ignoring loopback address: {}'.format(hostStandardFormat))
|
||||||
return False
|
return False
|
||||||
if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80:
|
if host[0] == '\xFE' and (ord(host[1]) & 0xc0) == 0x80:
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug('Ignoring local address: %s', hostStandardFormat)
|
logger.debug('Ignoring local address: {}'.format(hostStandardFormat))
|
||||||
return hostStandardFormat if private else False
|
return hostStandardFormat if private else False
|
||||||
if (ord(host[0]) & 0xfe) == 0xfc:
|
if (ord(host[0:1]) & 0xfe) == 0xfc:
|
||||||
if not private:
|
if not private:
|
||||||
logger.debug(
|
logger.debug('Ignoring unique local address: {}'.format(hostStandardFormat))
|
||||||
'Ignoring unique local address: %s', hostStandardFormat)
|
|
||||||
return hostStandardFormat if private else False
|
return hostStandardFormat if private else False
|
||||||
return False if private else hostStandardFormat
|
return False if private else hostStandardFormat
|
||||||
|
|
||||||
|
@ -225,6 +231,7 @@ def haveSSL(server=False):
|
||||||
python < 2.7.9's ssl library does not support ECDSA server due to
|
python < 2.7.9's ssl library does not support ECDSA server due to
|
||||||
missing initialisation of available curves, but client works ok
|
missing initialisation of available curves, but client works ok
|
||||||
"""
|
"""
|
||||||
|
return False
|
||||||
if not server:
|
if not server:
|
||||||
return True
|
return True
|
||||||
elif sys.version_info >= (2, 7, 9):
|
elif sys.version_info >= (2, 7, 9):
|
||||||
|
@ -269,7 +276,7 @@ def isProofOfWorkSufficient(
|
||||||
if TTL < 300:
|
if TTL < 300:
|
||||||
TTL = 300
|
TTL = 300
|
||||||
POW, = unpack('>Q', hashlib.sha512(hashlib.sha512(
|
POW, = unpack('>Q', hashlib.sha512(hashlib.sha512(
|
||||||
data[:8] + hashlib.sha512(data[8:]).digest()
|
bytes(data[:8]) + hashlib.sha512(data[8:]).digest()
|
||||||
).digest()).digest()[0:8])
|
).digest()).digest()[0:8])
|
||||||
return POW <= 2 ** 64 / (
|
return POW <= 2 ** 64 / (
|
||||||
nonceTrialsPerByte * (
|
nonceTrialsPerByte * (
|
||||||
|
@ -281,24 +288,20 @@ def isProofOfWorkSufficient(
|
||||||
|
|
||||||
|
|
||||||
def CreatePacket(command, payload=''):
|
def CreatePacket(command, payload=''):
|
||||||
"""Construct and return a packet"""
|
"""Construct and return a number of bytes from a payload"""
|
||||||
|
payload = payload if type(payload) in [bytes, bytearray] else payload.encode()
|
||||||
payload_length = len(payload)
|
payload_length = len(payload)
|
||||||
checksum = hashlib.sha512(payload).digest()[0:4]
|
checksum = hashlib.sha512(payload).digest()[0:4]
|
||||||
|
byte = bytearray(Header.size + payload_length)
|
||||||
b = bytearray(Header.size + payload_length)
|
Header.pack_into(byte, 0, 0xE9BEB4D9, command.encode(), payload_length, checksum)
|
||||||
Header.pack_into(b, 0, 0xE9BEB4D9, command, payload_length, checksum)
|
byte[Header.size:] = payload
|
||||||
b[Header.size:] = payload
|
return bytes(byte)
|
||||||
return bytes(b)
|
|
||||||
|
|
||||||
|
|
||||||
def assembleVersionMessage(
|
def assembleVersionMessage(remoteHost, remotePort, participatingStreams, server=False, nodeid=None):
|
||||||
remoteHost, remotePort, participatingStreams, server=False, nodeid=None
|
"""Construct the payload of a version message, return the resultng bytes of running CreatePacket() on it"""
|
||||||
):
|
payload = bytes()
|
||||||
"""
|
|
||||||
Construct the payload of a version message,
|
|
||||||
return the resulting bytes of running `CreatePacket` on it
|
|
||||||
"""
|
|
||||||
payload = ''
|
|
||||||
payload += pack('>L', 3) # protocol version.
|
payload += pack('>L', 3) # protocol version.
|
||||||
# bitflags of the services I offer.
|
# bitflags of the services I offer.
|
||||||
payload += pack(
|
payload += pack(
|
||||||
|
@ -331,10 +334,10 @@ def assembleVersionMessage(
|
||||||
(NODE_SSL if haveSSL(server) else 0) |
|
(NODE_SSL if haveSSL(server) else 0) |
|
||||||
(NODE_DANDELION if state.dandelion else 0)
|
(NODE_DANDELION if state.dandelion else 0)
|
||||||
)
|
)
|
||||||
# = 127.0.0.1. This will be ignored by the remote host.
|
# = 127.0.0.1. This will be ignored by the remote host. The actual remote connected IP will be used.
|
||||||
# The actual remote connected IP will be used.
|
# python3 need to check
|
||||||
payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF' + pack(
|
payload += '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF'.encode('raw_unicode_escape') + pack('>L', 2130706433)
|
||||||
'>L', 2130706433)
|
|
||||||
# we have a separate extPort and incoming over clearnet
|
# we have a separate extPort and incoming over clearnet
|
||||||
# or outgoing through clearnet
|
# or outgoing through clearnet
|
||||||
extport = BMConfigParser().safeGetInt('bitmessagesettings', 'extport')
|
extport = BMConfigParser().safeGetInt('bitmessagesettings', 'extport')
|
||||||
|
@ -345,11 +348,9 @@ def assembleVersionMessage(
|
||||||
):
|
):
|
||||||
payload += pack('>H', extport)
|
payload += pack('>H', extport)
|
||||||
elif checkSocksIP(remoteHost) and server: # incoming connection over Tor
|
elif checkSocksIP(remoteHost) and server: # incoming connection over Tor
|
||||||
payload += pack(
|
payload += pack('>H', int(BMConfigParser().safeGet('bitmessagesettings', 'onionport')))
|
||||||
'>H', BMConfigParser().getint('bitmessagesettings', 'onionport'))
|
|
||||||
else: # no extport and not incoming over Tor
|
else: # no extport and not incoming over Tor
|
||||||
payload += pack(
|
payload += pack('>H', int(BMConfigParser().safeGet('bitmessagesettings', 'port')))
|
||||||
'>H', BMConfigParser().getint('bitmessagesettings', 'port'))
|
|
||||||
|
|
||||||
if nodeid is not None:
|
if nodeid is not None:
|
||||||
payload += nodeid[0:8]
|
payload += nodeid[0:8]
|
||||||
|
@ -357,7 +358,7 @@ def assembleVersionMessage(
|
||||||
payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf
|
payload += eightBytesOfRandomDataUsedToDetectConnectionsToSelf
|
||||||
userAgent = '/PyBitmessage:' + softwareVersion + '/'
|
userAgent = '/PyBitmessage:' + softwareVersion + '/'
|
||||||
payload += encodeVarint(len(userAgent))
|
payload += encodeVarint(len(userAgent))
|
||||||
payload += userAgent
|
payload += userAgent.encode()
|
||||||
|
|
||||||
# Streams
|
# Streams
|
||||||
payload += encodeVarint(len(participatingStreams))
|
payload += encodeVarint(len(participatingStreams))
|
||||||
|
@ -380,9 +381,9 @@ def assembleErrorMessage(fatal=0, banTime=0, inventoryVector='', errorText=''):
|
||||||
payload = encodeVarint(fatal)
|
payload = encodeVarint(fatal)
|
||||||
payload += encodeVarint(banTime)
|
payload += encodeVarint(banTime)
|
||||||
payload += encodeVarint(len(inventoryVector))
|
payload += encodeVarint(len(inventoryVector))
|
||||||
payload += inventoryVector
|
payload += inventoryVector.encode() if type(payload) == bytes else inventoryVector
|
||||||
payload += encodeVarint(len(errorText))
|
payload += encodeVarint(len(errorText))
|
||||||
payload += errorText
|
payload += errorText.encode() if type(payload) == bytes else errorText
|
||||||
return CreatePacket('error', payload)
|
return CreatePacket('error', payload)
|
||||||
|
|
||||||
|
|
||||||
|
@ -430,7 +431,7 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
encryptedData = data[readPosition:]
|
encryptedData = data[readPosition:]
|
||||||
|
|
||||||
# Let us try to decrypt the pubkey
|
# Let us try to decrypt the pubkey
|
||||||
toAddress, cryptorObject = state.neededPubkeys[tag]
|
toAddress, cryptorObject = state.neededPubkeys[bytes(tag)]
|
||||||
if toAddress != address:
|
if toAddress != address:
|
||||||
logger.critical(
|
logger.critical(
|
||||||
'decryptAndCheckPubkeyPayload failed due to toAddress'
|
'decryptAndCheckPubkeyPayload failed due to toAddress'
|
||||||
|
@ -443,6 +444,7 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
# That sort of address-malleability should have been caught
|
# That sort of address-malleability should have been caught
|
||||||
# by the UI or API and an error given to the user.
|
# by the UI or API and an error given to the user.
|
||||||
return 'failed'
|
return 'failed'
|
||||||
|
print("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW#################################################")
|
||||||
try:
|
try:
|
||||||
decryptedData = cryptorObject.decrypt(encryptedData)
|
decryptedData = cryptorObject.decrypt(encryptedData)
|
||||||
except:
|
except:
|
||||||
|
@ -450,13 +452,13 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
# but tagged it with a tag for which we are watching.
|
# but tagged it with a tag for which we are watching.
|
||||||
logger.info('Pubkey decryption was unsuccessful.')
|
logger.info('Pubkey decryption was unsuccessful.')
|
||||||
return 'failed'
|
return 'failed'
|
||||||
|
|
||||||
readPosition = 0
|
readPosition = 0
|
||||||
# bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
|
# bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
|
||||||
readPosition += 4
|
readPosition += 4
|
||||||
publicSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
print("working fine till here#################################################################")
|
||||||
|
publicSigningKey = '\x04'.encode() + decryptedData[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
publicEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
publicEncryptionKey = '\x04'.encode() + decryptedData[readPosition:readPosition + 64]
|
||||||
readPosition += 64
|
readPosition += 64
|
||||||
specifiedNonceTrialsPerByteLength = decodeVarint(
|
specifiedNonceTrialsPerByteLength = decodeVarint(
|
||||||
decryptedData[readPosition:readPosition + 10])[1]
|
decryptedData[readPosition:readPosition + 10])[1]
|
||||||
|
@ -470,7 +472,6 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
decryptedData[readPosition:readPosition + 10])
|
decryptedData[readPosition:readPosition + 10])
|
||||||
readPosition += signatureLengthLength
|
readPosition += signatureLengthLength
|
||||||
signature = decryptedData[readPosition:readPosition + signatureLength]
|
signature = decryptedData[readPosition:readPosition + signatureLength]
|
||||||
|
|
||||||
if not highlevelcrypto.verify(
|
if not highlevelcrypto.verify(
|
||||||
signedData, signature, hexlify(publicSigningKey)):
|
signedData, signature, hexlify(publicSigningKey)):
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -479,11 +480,9 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
'ECDSA verify passed (within decryptAndCheckPubkeyPayload)')
|
'ECDSA verify passed (within decryptAndCheckPubkeyPayload)')
|
||||||
|
|
||||||
sha = hashlib.new('sha512')
|
sha = hashlib.new('sha512')
|
||||||
sha.update(publicSigningKey + publicEncryptionKey)
|
sha.update(publicSigningKey + publicEncryptionKey)
|
||||||
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
|
embeddedRipe = RIPEMD160Hash(sha.digest()).digest()
|
||||||
|
|
||||||
if embeddedRipe != ripe:
|
if embeddedRipe != ripe:
|
||||||
# Although this pubkey object had the tag were were looking for
|
# Although this pubkey object had the tag were were looking for
|
||||||
# and was encrypted with the correct encryption key,
|
# and was encrypted with the correct encryption key,
|
||||||
|
@ -502,9 +501,9 @@ def decryptAndCheckPubkeyPayload(data, address):
|
||||||
addressVersion, streamNumber, hexlify(ripe),
|
addressVersion, streamNumber, hexlify(ripe),
|
||||||
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
|
hexlify(publicSigningKey), hexlify(publicEncryptionKey)
|
||||||
)
|
)
|
||||||
|
|
||||||
t = (address, addressVersion, storedData, int(time.time()), 'yes')
|
t = (address, addressVersion, storedData, int(time.time()), 'yes')
|
||||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||||
|
print("successful Insertion of pubkey hurray#################################################")
|
||||||
return 'successful'
|
return 'successful'
|
||||||
except varintDecodeError:
|
except varintDecodeError:
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
|
@ -29,11 +29,13 @@ def get_code_string(base):
|
||||||
elif base == 10:
|
elif base == 10:
|
||||||
return '0123456789'
|
return '0123456789'
|
||||||
elif base == 16:
|
elif base == 16:
|
||||||
return "0123456789abcdef"
|
return ("0123456789abcdef").encode()
|
||||||
elif base == 58:
|
elif base == 58:
|
||||||
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
elif base == 256:
|
elif base == 256:
|
||||||
return ''.join([chr(x) for x in range(256)])
|
# raw_unicode_escape is used because in the python3 after range(161) its genreate
|
||||||
|
# the speical character so avoiding that function we have used the raw_unicode method
|
||||||
|
return bytes(range(0, 256))
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid base!")
|
raise ValueError("Invalid base!")
|
||||||
|
|
||||||
|
@ -41,10 +43,10 @@ def get_code_string(base):
|
||||||
def encode(val, base, minlen=0):
|
def encode(val, base, minlen=0):
|
||||||
"""Returns the encoded string"""
|
"""Returns the encoded string"""
|
||||||
code_string = get_code_string(base)
|
code_string = get_code_string(base)
|
||||||
result = ""
|
result = str.encode('') if type(code_string) is bytes else ''
|
||||||
while val > 0:
|
while val > 0:
|
||||||
result = code_string[val % base] + result
|
result = code_string[val % base:val % base + 1] + result
|
||||||
val /= base
|
val = val // base
|
||||||
if len(result) < minlen:
|
if len(result) < minlen:
|
||||||
result = code_string[0] * (minlen - len(result)) + result
|
result = code_string[0] * (minlen - len(result)) + result
|
||||||
return result
|
return result
|
||||||
|
@ -58,7 +60,7 @@ def decode(string, base):
|
||||||
string = string.lower()
|
string = string.lower()
|
||||||
while string:
|
while string:
|
||||||
result *= base
|
result *= base
|
||||||
result += code_string.find(string[0])
|
result += code_string.find(string[0:1])
|
||||||
string = string[1:]
|
string = string[1:]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ Symmetric Encryption
|
||||||
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
from openssl import OpenSSL
|
from .openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=redefined-builtin
|
# pylint: disable=redefined-builtin
|
||||||
|
|
|
@ -10,9 +10,9 @@ Asymmetric cryptography using elliptic curves
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
from cipher import Cipher
|
from pyelliptic.cipher import Cipher
|
||||||
from hash import equals, hmac_sha256
|
from pyelliptic.hash import equals, hmac_sha256
|
||||||
from openssl import OpenSSL
|
from pyelliptic.openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
class ECC(object):
|
class ECC(object):
|
||||||
|
@ -62,7 +62,6 @@ class ECC(object):
|
||||||
self.curve = OpenSSL.get_curve(curve)
|
self.curve = OpenSSL.get_curve(curve)
|
||||||
else:
|
else:
|
||||||
self.curve = curve
|
self.curve = curve
|
||||||
|
|
||||||
if pubkey_x is not None and pubkey_y is not None:
|
if pubkey_x is not None and pubkey_y is not None:
|
||||||
self._set_keys(pubkey_x, pubkey_y, raw_privkey)
|
self._set_keys(pubkey_x, pubkey_y, raw_privkey)
|
||||||
elif pubkey is not None:
|
elif pubkey is not None:
|
||||||
|
@ -294,7 +293,6 @@ class ECC(object):
|
||||||
if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
|
if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"[OpenSSL] EC_KEY_set_private_key FAIL ...")
|
"[OpenSSL] EC_KEY_set_private_key FAIL ...")
|
||||||
|
|
||||||
group = OpenSSL.EC_KEY_get0_group(key)
|
group = OpenSSL.EC_KEY_get0_group(key)
|
||||||
pub_key = OpenSSL.EC_POINT_new(group)
|
pub_key = OpenSSL.EC_POINT_new(group)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ Wrappers for hash functions from OpenSSL.
|
||||||
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
|
||||||
# See LICENSE for details.
|
# See LICENSE for details.
|
||||||
|
|
||||||
from openssl import OpenSSL
|
from .openssl import OpenSSL
|
||||||
|
|
||||||
|
|
||||||
# For python3
|
# For python3
|
||||||
|
|
|
@ -82,7 +82,7 @@ class _OpenSSL(object):
|
||||||
"""Build the wrapper"""
|
"""Build the wrapper"""
|
||||||
self._lib = ctypes.CDLL(library)
|
self._lib = ctypes.CDLL(library)
|
||||||
self._version, self._hexversion, self._cflags = get_version(self._lib)
|
self._version, self._hexversion, self._cflags = get_version(self._lib)
|
||||||
self._libreSSL = self._version.startswith("LibreSSL")
|
self._libreSSL = (self._version).decode("utf-8").startswith("OpenSSL")
|
||||||
|
|
||||||
self.pointer = ctypes.pointer
|
self.pointer = ctypes.pointer
|
||||||
self.c_int = ctypes.c_int
|
self.c_int = ctypes.c_int
|
||||||
|
@ -723,6 +723,7 @@ def loadOpenSSL():
|
||||||
libdir.append('libssl.so')
|
libdir.append('libssl.so')
|
||||||
libdir.append('libcrypto.so.1.0.0')
|
libdir.append('libcrypto.so.1.0.0')
|
||||||
libdir.append('libssl.so.1.0.0')
|
libdir.append('libssl.so.1.0.0')
|
||||||
|
libdir.append('libcrypto.so.1.0.2')
|
||||||
if 'linux' in sys.platform or 'darwin' in sys.platform or 'bsd' in sys.platform:
|
if 'linux' in sys.platform or 'darwin' in sys.platform or 'bsd' in sys.platform:
|
||||||
try:
|
try:
|
||||||
libdir.append(find_library('ssl'))
|
libdir.append(find_library('ssl'))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Most of the queues used by bitmessage threads are defined here."""
|
"""Most of the queues used by bitmessage threads are defined here."""
|
||||||
|
import queue as Queue
|
||||||
|
|
||||||
import Queue
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ class ObjectProcessorQueue(Queue.Queue):
|
||||||
self.curSize = 0
|
self.curSize = 0
|
||||||
|
|
||||||
def put(self, item, block=True, timeout=None):
|
def put(self, item, block=True, timeout=None):
|
||||||
|
"""Putting values in queues"""
|
||||||
while self.curSize >= self.maxSize:
|
while self.curSize >= self.maxSize:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
with self.sizeLock:
|
with self.sizeLock:
|
||||||
|
@ -28,6 +29,7 @@ class ObjectProcessorQueue(Queue.Queue):
|
||||||
Queue.Queue.put(self, item, block, timeout)
|
Queue.Queue.put(self, item, block, timeout)
|
||||||
|
|
||||||
def get(self, block=True, timeout=None):
|
def get(self, block=True, timeout=None):
|
||||||
|
"""Getting values from queues"""
|
||||||
item = Queue.Queue.get(self, block, timeout)
|
item = Queue.Queue.get(self, block, timeout)
|
||||||
with self.sizeLock:
|
with self.sizeLock:
|
||||||
self.curSize -= len(item[1])
|
self.curSize -= len(item[1])
|
||||||
|
|
|
@ -25,9 +25,8 @@ from addresses import decodeAddress, encodeVarint
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from helper_sql import sqlQuery
|
from helper_sql import sqlQuery
|
||||||
|
|
||||||
from pyelliptic import arithmetic
|
from pyelliptic import arithmetic
|
||||||
|
# pylint: disable=logging-format-interpolation
|
||||||
|
|
||||||
verbose = 1
|
verbose = 1
|
||||||
# This is obsolete with the change to protocol v3
|
# This is obsolete with the change to protocol v3
|
||||||
|
@ -113,23 +112,21 @@ def decodeWalletImportFormat(WIFstring):
|
||||||
"""
|
"""
|
||||||
fullString = arithmetic.changebase(WIFstring, 58, 256)
|
fullString = arithmetic.changebase(WIFstring, 58, 256)
|
||||||
privkey = fullString[:-4]
|
privkey = fullString[:-4]
|
||||||
if fullString[-4:] != \
|
if fullString[-4:] != hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
|
||||||
hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
|
|
||||||
logger.critical(
|
logger.critical(
|
||||||
'Major problem! When trying to decode one of your'
|
'Major problem! When trying to decode one of your'
|
||||||
' private keys, the checksum failed. Here are the first'
|
' private keys, the checksum failed. Here are the first'
|
||||||
' 6 characters of the PRIVATE key: %s',
|
' 6 characters of the PRIVATE key: {}'.format(str(WIFstring)[:6])
|
||||||
str(WIFstring)[:6]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
os._exit(0) # pylint: disable=protected-access
|
os._exit(0) # pylint: disable=protected-access
|
||||||
# return ""
|
if privkey[0:1] == '\x80'.encode()[1:]: # checksum passed
|
||||||
elif privkey[0] == '\x80': # checksum passed
|
|
||||||
return privkey[1:]
|
return privkey[1:]
|
||||||
|
|
||||||
logger.critical(
|
logger.critical(
|
||||||
'Major problem! When trying to decode one of your private keys,'
|
'Major problem! When trying to decode one of your private keys,'
|
||||||
' the checksum passed but the key doesn\'t begin with hex 80.'
|
' the checksum passed but the key doesn\'t begin with hex 80.'
|
||||||
' Here is the PRIVATE key: %s', WIFstring
|
' Here is the PRIVATE key: {}'.format(WIFstring)
|
||||||
)
|
)
|
||||||
os._exit(0) # pylint: disable=protected-access
|
os._exit(0) # pylint: disable=protected-access
|
||||||
|
|
||||||
|
@ -147,7 +144,7 @@ def reloadMyAddressHashes():
|
||||||
state.appdata, 'keys.dat'))
|
state.appdata, 'keys.dat'))
|
||||||
hasEnabledKeys = False
|
hasEnabledKeys = False
|
||||||
for addressInKeysFile in BMConfigParser().addresses():
|
for addressInKeysFile in BMConfigParser().addresses():
|
||||||
isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled')
|
isEnabled = BMConfigParser().safeGet(addressInKeysFile, 'enabled')
|
||||||
if isEnabled:
|
if isEnabled:
|
||||||
hasEnabledKeys = True
|
hasEnabledKeys = True
|
||||||
# status
|
# status
|
||||||
|
@ -195,7 +192,6 @@ def reloadBroadcastSendersForWhichImWatching():
|
||||||
# Now, for all addresses, even version 2 addresses,
|
# Now, for all addresses, even version 2 addresses,
|
||||||
# we should create Cryptor objects in a dictionary which we will
|
# we should create Cryptor objects in a dictionary which we will
|
||||||
# use to attempt to decrypt encrypted broadcast messages.
|
# use to attempt to decrypt encrypted broadcast messages.
|
||||||
|
|
||||||
if addressVersionNumber <= 3:
|
if addressVersionNumber <= 3:
|
||||||
privEncryptionKey = hashlib.sha512(
|
privEncryptionKey = hashlib.sha512(
|
||||||
encodeVarint(addressVersionNumber) +
|
encodeVarint(addressVersionNumber) +
|
||||||
|
@ -220,6 +216,7 @@ def fixPotentiallyInvalidUTF8Data(text):
|
||||||
unicode(text, 'utf-8')
|
unicode(text, 'utf-8')
|
||||||
return text
|
return text
|
||||||
except:
|
except:
|
||||||
|
|
||||||
return 'Part of the message is corrupt. The message cannot be' \
|
return 'Part of the message is corrupt. The message cannot be' \
|
||||||
' displayed the normal way.\n\n' + repr(text)
|
' displayed the normal way.\n\n' + repr(text)
|
||||||
|
|
||||||
|
@ -246,7 +243,7 @@ def checkSensitiveFilePermissions(filename):
|
||||||
shell=True,
|
shell=True,
|
||||||
stderr=subprocess.STDOUT
|
stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if 'fuseblk' in fstype:
|
if 'fuseblk'.encode() in fstype:
|
||||||
logger.info(
|
logger.info(
|
||||||
'Skipping file permissions check for %s.'
|
'Skipping file permissions check for %s.'
|
||||||
' Filesystem fuseblk detected.', filename)
|
' Filesystem fuseblk detected.', filename)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""shutdown function"""
|
"""shutdown function"""
|
||||||
import os
|
import os
|
||||||
import Queue
|
import queue as Queue
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ class singleinstance(object):
|
||||||
fcntl.lockf(self.fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
fcntl.lockf(self.fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
self.lockPid = os.getpid()
|
self.lockPid = os.getpid()
|
||||||
except IOError:
|
except IOError:
|
||||||
print 'Another instance of this application is already running'
|
print('Another instance of this application is already running')
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
else:
|
else:
|
||||||
pidLine = "%i\n" % self.lockPid
|
pidLine = "%i\n" % self.lockPid
|
||||||
|
@ -97,9 +97,8 @@ class singleinstance(object):
|
||||||
fcntl.lockf(self.fp, fcntl.LOCK_UN)
|
fcntl.lockf(self.fp, fcntl.LOCK_UN)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return
|
return
|
||||||
print "Cleaning up lockfile"
|
print("Cleaning up lockfile")
|
||||||
try:
|
try:
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
if hasattr(self, 'fd'):
|
if hasattr(self, 'fd'):
|
||||||
|
|
45
src/state.py
45
src/state.py
|
@ -1,43 +1,30 @@
|
||||||
"""
|
"""
|
||||||
Global runtime variables.
|
src/state.py
|
||||||
|
=================================
|
||||||
"""
|
"""
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
neededPubkeys = {}
|
neededPubkeys = {}
|
||||||
streamsInWhichIAmParticipating = []
|
streamsInWhichIAmParticipating = []
|
||||||
|
# For UPnP
|
||||||
extPort = None
|
extPort = None
|
||||||
"""For UPnP"""
|
# for Tor hidden service
|
||||||
|
|
||||||
socksIP = None
|
socksIP = None
|
||||||
"""for Tor hidden service"""
|
# Network protocols availability, initialised below
|
||||||
|
networkProtocolAvailability = None
|
||||||
appdata = ''
|
appdata = '' # holds the location of the application data storage directory
|
||||||
"""holds the location of the application data storage directory"""
|
# Set to 1 by the doCleanShutdown function.
|
||||||
|
# Used to tell the proof of work worker threads to exit.
|
||||||
shutdown = 0
|
shutdown = 0
|
||||||
"""
|
|
||||||
Set to 1 by the `.shutdown.doCleanShutdown` function.
|
|
||||||
Used to tell the threads to exit.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Component control flags - set on startup, do not change during runtime
|
# Component control flags - set on startup, do not change during runtime
|
||||||
# The defaults are for standalone GUI (default operating mode)
|
# The defaults are for standalone GUI (default operating mode)
|
||||||
enableNetwork = True
|
enableNetwork = True # enable network threads
|
||||||
"""enable network threads"""
|
enableObjProc = True # enable object processing threads
|
||||||
enableObjProc = True
|
enableAPI = True # enable API (if configured)
|
||||||
"""enable object processing thread"""
|
enableGUI = True # enable GUI (QT or ncurses)
|
||||||
enableAPI = True
|
enableSTDIO = False # enable STDIO threads
|
||||||
"""enable API (if configured)"""
|
|
||||||
enableGUI = True
|
|
||||||
"""enable GUI (QT or ncurses)"""
|
|
||||||
enableSTDIO = False
|
|
||||||
"""enable STDIO threads"""
|
|
||||||
curses = False
|
curses = False
|
||||||
|
sqlReady = False # set to true by sqlTread when ready for processing
|
||||||
sqlReady = False
|
|
||||||
"""set to true by `.threads.sqlThread` when ready for processing"""
|
|
||||||
|
|
||||||
maximumNumberOfHalfOpenConnections = 0
|
maximumNumberOfHalfOpenConnections = 0
|
||||||
invThread = None
|
invThread = None
|
||||||
addrThread = None
|
addrThread = None
|
||||||
|
@ -68,8 +55,6 @@ def resetNetworkProtocolAvailability():
|
||||||
|
|
||||||
resetNetworkProtocolAvailability()
|
resetNetworkProtocolAvailability()
|
||||||
|
|
||||||
discoveredPeers = {}
|
|
||||||
|
|
||||||
dandelion = 0
|
dandelion = 0
|
||||||
|
|
||||||
testmode = False
|
testmode = False
|
||||||
|
|
|
@ -8,7 +8,7 @@ from os import listdir, makedirs, path, remove, rmdir
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
|
||||||
from paths import lookupAppdataFolder
|
from paths import lookupAppdataFolder
|
||||||
from storage import InventoryItem, InventoryStorage
|
from storage.storage import InventoryStorage, InventoryItem
|
||||||
|
|
||||||
|
|
||||||
class FilesystemInventory(InventoryStorage):
|
class FilesystemInventory(InventoryStorage):
|
||||||
|
@ -162,7 +162,7 @@ class FilesystemInventory(InventoryStorage):
|
||||||
newInventory[streamNumber][hashId] = InventoryItem(
|
newInventory[streamNumber][hashId] = InventoryItem(
|
||||||
objectType, streamNumber, None, expiresTime, tag)
|
objectType, streamNumber, None, expiresTime, tag)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print "error loading %s" % (hexlify(hashId))
|
print ("error loading {}".format((hexlify(hashId))))
|
||||||
self._inventory = newInventory
|
self._inventory = newInventory
|
||||||
# for i, v in self._inventory.items():
|
# for i, v in self._inventory.items():
|
||||||
# print "loaded stream: %s, %i items" % (i, len(v))
|
# print "loaded stream: %s, %i items" % (i, len(v))
|
||||||
|
|
|
@ -5,8 +5,9 @@ import sqlite3
|
||||||
import time
|
import time
|
||||||
from threading import RLock
|
from threading import RLock
|
||||||
|
|
||||||
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery
|
|
||||||
from storage import InventoryItem, InventoryStorage
|
from helper_sql import sqlQuery, SqlBulkExecute, sqlExecute
|
||||||
|
from storage.storage import InventoryStorage, InventoryItem
|
||||||
|
|
||||||
|
|
||||||
class SqliteInventory(InventoryStorage): # pylint: disable=too-many-ancestors
|
class SqliteInventory(InventoryStorage): # pylint: disable=too-many-ancestors
|
||||||
|
@ -87,9 +88,10 @@ class SqliteInventory(InventoryStorage): # pylint: disable=too-many-ancestors
|
||||||
t = int(time.time())
|
t = int(time.time())
|
||||||
hashes = [x for x, value in self._inventory.items()
|
hashes = [x for x, value in self._inventory.items()
|
||||||
if value.stream == stream and value.expires > t]
|
if value.stream == stream and value.expires > t]
|
||||||
hashes += (str(payload) for payload, in sqlQuery(
|
hashes += (payload for payload, in sqlQuery(
|
||||||
'SELECT hash FROM inventory WHERE streamnumber=?'
|
'SELECT hash FROM inventory WHERE streamnumber=?'
|
||||||
' AND expirestime>?', stream, t))
|
' AND expirestime>?', stream, t))
|
||||||
|
# print('sqlllllllllllllllllllllllllllllllllll',hashes)
|
||||||
return hashes
|
return hashes
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# Import the libraries.
|
|
||||||
import pdb;pdb.set_trace()
|
|
||||||
import pydenticon100000000000000000000000
|
|
||||||
import hashlib
|
|
||||||
# Set-up some test data.
|
|
||||||
users = ["alice", "bob", "eve", "dave"]
|
|
||||||
# Set-up a list of foreground colours (taken from Sigil).
|
|
||||||
foreground = ["rgb(45,79,255)",
|
|
||||||
"rgb(254,180,44)",
|
|
||||||
"rgb(226,121,234)",
|
|
||||||
"rgb(30,179,253)",
|
|
||||||
"rgb(232,77,65)",
|
|
||||||
"rgb(49,203,115)",
|
|
||||||
"rgb(141,69,170)"]
|
|
||||||
# Set-up a background colour (taken from Sigil).
|
|
||||||
background = "rgb(224,224,224)"
|
|
||||||
# Set-up the padding (top, bottom, left, right) in pixels.
|
|
||||||
padding = (20, 20, 20, 20)
|
|
||||||
# Instantiate a generator that will create 5x5 block identicons using SHA1
|
|
||||||
# digest.
|
|
||||||
generator = pydenticon.Generator(5, 5, digest=hashlib.sha1, foreground=foreground, background=background)
|
|
||||||
|
|
||||||
# identicon_ascii = generator.generate("john.doe@example.com", 200, 200,
|
|
||||||
# output_format="ascii")
|
|
||||||
|
|
||||||
# print identicon_ascii
|
|
||||||
for user in users:
|
|
||||||
identicon = generator.generate(user, 200, 200, padding=padding, output_format="png")
|
|
||||||
filename = user + ".png"
|
|
||||||
with open(filename, "wb") as f:
|
|
||||||
f.write(identicon)
|
|
|
@ -5,7 +5,7 @@ Tests for core and those that do not work outside
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pickle # nosec
|
import pickle # nosec
|
||||||
import Queue
|
import queue as Queue
|
||||||
import random # nosec
|
import random # nosec
|
||||||
import string
|
import string
|
||||||
import time
|
import time
|
||||||
|
|
|
@ -10,6 +10,7 @@ class TestNetworkGroup(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
def test_network_group(self):
|
def test_network_group(self):
|
||||||
"""Test various types of network groups"""
|
"""Test various types of network groups"""
|
||||||
|
# pylint: disable=import-error
|
||||||
from pybitmessage.protocol import network_group
|
from pybitmessage.protocol import network_group
|
||||||
|
|
||||||
test_ip = '1.2.3.4'
|
test_ip = '1.2.3.4'
|
||||||
|
|
21
src/tr.py
21
src/tr.py
|
@ -6,17 +6,17 @@ import os
|
||||||
import state
|
import state
|
||||||
|
|
||||||
|
|
||||||
class translateClass:
|
class translateClass(object):
|
||||||
"""
|
"""
|
||||||
This is used so that the translateText function can be used
|
This is used so that the translateText function can be used
|
||||||
when we are in daemon mode and not using any QT functions.
|
when we are in daemon mode and not using any QT functions.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=old-style-class,too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, context, text):
|
def __init__(self, context, text):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.text = text
|
self.text = text
|
||||||
|
|
||||||
def arg(self, argument): # pylint: disable=unused-argument
|
def arg(self, _):
|
||||||
"""Replace argument placeholders"""
|
"""Replace argument placeholders"""
|
||||||
if '%' in self.text:
|
if '%' in self.text:
|
||||||
return translateClass(self.context, self.text.replace('%', '', 1))
|
return translateClass(self.context, self.text.replace('%', '', 1))
|
||||||
|
@ -25,8 +25,7 @@ class translateClass:
|
||||||
return self.text
|
return self.text
|
||||||
|
|
||||||
|
|
||||||
def _translate(context, text, disambiguation=None, encoding=None, n=None):
|
def _translate(context, text, disambiguation=None, encoding=None, n=None): # pylint: disable=unused-argument
|
||||||
# pylint: disable=unused-argument
|
|
||||||
return translateText(context, text, n)
|
return translateText(context, text, n)
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,13 +39,13 @@ def translateText(context, text, n=None):
|
||||||
try:
|
try:
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print 'PyBitmessage requires PyQt unless you want to run it as a daemon'\
|
print('PyBitmessage requires PyQt unless you want to run it as a daemon and interact with it using the API\
|
||||||
' and interact with it using the API.'\
|
.You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download\
|
||||||
' You can download PyQt from http://www.riverbankcomputing.com/software/pyqt/download'\
|
or by searching Google for \'PyQt Download\'.\
|
||||||
' or by searching Google for \'PyQt Download\'.'\
|
If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon')
|
||||||
' If you want to run in daemon mode, see https://bitmessage.org/wiki/Daemon'
|
print('Error message:', err)
|
||||||
print 'Error message:', err
|
|
||||||
os._exit(0) # pylint: disable=protected-access
|
os._exit(0) # pylint: disable=protected-access
|
||||||
|
|
||||||
if n is None:
|
if n is None:
|
||||||
return QtGui.QApplication.translate(context, text)
|
return QtGui.QApplication.translate(context, text)
|
||||||
return QtGui.QApplication.translate(context, text, None, QtCore.QCoreApplication.CodecForTr, n)
|
return QtGui.QApplication.translate(context, text, None, QtCore.QCoreApplication.CodecForTr, n)
|
||||||
|
|
37
src/upnp.py
37
src/upnp.py
|
@ -1,8 +1,8 @@
|
||||||
# pylint: disable=too-many-statements,too-many-branches,protected-access,no-self-use
|
"""
|
||||||
"""
|
|
||||||
Complete UPnP port forwarding implementation in separate thread.
|
Complete UPnP port forwarding implementation in separate thread.
|
||||||
Reference: http://mattscodecave.com/posts/using-python-and-upnp-to-forward-a-port
|
Reference: http://mattscodecave.com/posts/using-python-and-upnp-to-forward-a-port
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements,too-many-branches,protected-access,no-self-use
|
||||||
|
|
||||||
import httplib
|
import httplib
|
||||||
import socket
|
import socket
|
||||||
|
@ -18,8 +18,9 @@ import state
|
||||||
import tr
|
import tr
|
||||||
from bmconfigparser import BMConfigParser
|
from bmconfigparser import BMConfigParser
|
||||||
from debug import logger
|
from debug import logger
|
||||||
from network import BMConnectionPool, StoppableThread
|
from network.connectionpool import BMConnectionPool
|
||||||
from network.node import Peer
|
from network.node import Peer
|
||||||
|
from network.threads import StoppableThread
|
||||||
|
|
||||||
|
|
||||||
def createRequestXML(service, action, arguments=None):
|
def createRequestXML(service, action, arguments=None):
|
||||||
|
@ -82,6 +83,7 @@ class UPnPError(Exception):
|
||||||
|
|
||||||
class Router: # pylint: disable=old-style-class
|
class Router: # pylint: disable=old-style-class
|
||||||
"""Encapulate routing"""
|
"""Encapulate routing"""
|
||||||
|
|
||||||
name = ""
|
name = ""
|
||||||
path = ""
|
path = ""
|
||||||
address = None
|
address = None
|
||||||
|
@ -151,7 +153,6 @@ class Router: # pylint: disable=old-style-class
|
||||||
|
|
||||||
def DeletePortMapping(self, externalPort, protocol):
|
def DeletePortMapping(self, externalPort, protocol):
|
||||||
"""Delete UPnP port mapping"""
|
"""Delete UPnP port mapping"""
|
||||||
|
|
||||||
resp = self.soapRequest(self.upnp_schema + ':1', 'DeletePortMapping', [
|
resp = self.soapRequest(self.upnp_schema + ':1', 'DeletePortMapping', [
|
||||||
('NewRemoteHost', ''),
|
('NewRemoteHost', ''),
|
||||||
('NewExternalPort', str(externalPort)),
|
('NewExternalPort', str(externalPort)),
|
||||||
|
@ -162,16 +163,12 @@ class Router: # pylint: disable=old-style-class
|
||||||
|
|
||||||
def GetExternalIPAddress(self):
|
def GetExternalIPAddress(self):
|
||||||
"""Get the external address"""
|
"""Get the external address"""
|
||||||
|
resp = self.soapRequest(self.upnp_schema + ':1', 'GetExternalIPAddress')
|
||||||
resp = self.soapRequest(
|
|
||||||
self.upnp_schema + ':1', 'GetExternalIPAddress')
|
|
||||||
dom = parseString(resp.read())
|
dom = parseString(resp.read())
|
||||||
return dom.getElementsByTagName(
|
return dom.getElementsByTagName('NewExternalIPAddress')[0].childNodes[0].data
|
||||||
'NewExternalIPAddress')[0].childNodes[0].data
|
|
||||||
|
|
||||||
def soapRequest(self, service, action, arguments=None):
|
def soapRequest(self, service, action, arguments=None):
|
||||||
"""Make a request to a router"""
|
"""Make a request to a router"""
|
||||||
|
|
||||||
conn = httplib.HTTPConnection(self.routerPath.hostname, self.routerPath.port)
|
conn = httplib.HTTPConnection(self.routerPath.hostname, self.routerPath.port)
|
||||||
conn.request(
|
conn.request(
|
||||||
'POST',
|
'POST',
|
||||||
|
@ -222,7 +219,6 @@ class uPnPThread(StoppableThread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Start the thread to manage UPnP activity"""
|
"""Start the thread to manage UPnP activity"""
|
||||||
|
|
||||||
logger.debug("Starting UPnP thread")
|
logger.debug("Starting UPnP thread")
|
||||||
logger.debug("Local IP: %s", self.localIP)
|
logger.debug("Local IP: %s", self.localIP)
|
||||||
lastSent = 0
|
lastSent = 0
|
||||||
|
@ -260,16 +256,12 @@ class uPnPThread(StoppableThread):
|
||||||
self.routers.append(newRouter)
|
self.routers.append(newRouter)
|
||||||
self.createPortMapping(newRouter)
|
self.createPortMapping(newRouter)
|
||||||
try:
|
try:
|
||||||
self_peer = Peer(
|
self_peer = Peer(newRouter.GetExternalIPAddress(), self.extPort)
|
||||||
newRouter.GetExternalIPAddress(),
|
|
||||||
self.extPort
|
|
||||||
)
|
|
||||||
except:
|
except:
|
||||||
logger.debug('Failed to get external IP')
|
logger.debug('Failed to get external IP')
|
||||||
else:
|
else:
|
||||||
with knownnodes.knownNodesLock:
|
with knownnodes.knownNodesLock:
|
||||||
knownnodes.addKnownNode(
|
knownnodes.addKnownNode(1, self_peer, is_self=True)
|
||||||
1, self_peer, is_self=True)
|
|
||||||
queues.UISignalQueue.put(('updateStatusBar', tr._translate(
|
queues.UISignalQueue.put(('updateStatusBar', tr._translate(
|
||||||
"MainWindow", 'UPnP port mapping established on port %1'
|
"MainWindow", 'UPnP port mapping established on port %1'
|
||||||
).arg(str(self.extPort))))
|
).arg(str(self.extPort))))
|
||||||
|
@ -295,12 +287,12 @@ class uPnPThread(StoppableThread):
|
||||||
deleted = True
|
deleted = True
|
||||||
self.deletePortMapping(router)
|
self.deletePortMapping(router)
|
||||||
if deleted:
|
if deleted:
|
||||||
queues.UISignalQueue.put(('updateStatusBar', tr._translate("MainWindow", 'UPnP port mapping removed')))
|
queues.UISignalQueue.put(
|
||||||
|
('updateStatusBar', tr._translate("MainWindow", 'UPnP port mapping removed')))
|
||||||
logger.debug("UPnP thread done")
|
logger.debug("UPnP thread done")
|
||||||
|
|
||||||
def getLocalIP(self):
|
def getLocalIP(self):
|
||||||
"""Get the local IP of the node"""
|
"""Get the local IP of the node"""
|
||||||
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
s.connect((uPnPThread.GOOGLE_DNS, 1))
|
s.connect((uPnPThread.GOOGLE_DNS, 1))
|
||||||
|
@ -308,7 +300,6 @@ class uPnPThread(StoppableThread):
|
||||||
|
|
||||||
def sendSearchRouter(self):
|
def sendSearchRouter(self):
|
||||||
"""Querying for UPnP services"""
|
"""Querying for UPnP services"""
|
||||||
|
|
||||||
ssdpRequest = "M-SEARCH * HTTP/1.1\r\n" + \
|
ssdpRequest = "M-SEARCH * HTTP/1.1\r\n" + \
|
||||||
"HOST: %s:%d\r\n" % (uPnPThread.SSDP_ADDR, uPnPThread.SSDP_PORT) + \
|
"HOST: %s:%d\r\n" % (uPnPThread.SSDP_ADDR, uPnPThread.SSDP_PORT) + \
|
||||||
"MAN: \"ssdp:discover\"\r\n" + \
|
"MAN: \"ssdp:discover\"\r\n" + \
|
||||||
|
@ -323,7 +314,6 @@ class uPnPThread(StoppableThread):
|
||||||
|
|
||||||
def createPortMapping(self, router):
|
def createPortMapping(self, router):
|
||||||
"""Add a port mapping"""
|
"""Add a port mapping"""
|
||||||
|
|
||||||
for i in range(50):
|
for i in range(50):
|
||||||
try:
|
try:
|
||||||
localIP = self.localIP
|
localIP = self.localIP
|
||||||
|
@ -335,10 +325,7 @@ class uPnPThread(StoppableThread):
|
||||||
extPort = randint(32767, 65535)
|
extPort = randint(32767, 65535)
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Attempt %i, requesting UPnP mapping for %s:%i on external port %i",
|
"Attempt %i, requesting UPnP mapping for %s:%i on external port %i",
|
||||||
i,
|
i, localIP, self.localPort, extPort)
|
||||||
localIP,
|
|
||||||
self.localPort,
|
|
||||||
extPort)
|
|
||||||
router.AddPortMapping(extPort, self.localPort, localIP, 'TCP', 'BitMessage')
|
router.AddPortMapping(extPort, self.localPort, localIP, 'TCP', 'BitMessage')
|
||||||
self.extPort = extPort
|
self.extPort = extPort
|
||||||
BMConfigParser().set('bitmessagesettings', 'extport', str(extPort))
|
BMConfigParser().set('bitmessagesettings', 'extport', str(extPort))
|
||||||
|
|
Reference in New Issue
Block a user