Merge branch 'v0.6' of https://github.com/surbhicis/PyBitmessage into UiChanges

This commit is contained in:
surbhi 2019-09-24 17:48:17 +05:30
commit a4565d169d
No known key found for this signature in database
GPG Key ID: 88928762974D3618

View File

@ -1,3 +1,8 @@
"""
src/bitmessagecurses/__init__.py
================================
"""
# Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com> # Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com>
# This file adds a alternative commandline interface, feel free to critique and fork # This file adds a alternative commandline interface, feel free to critique and fork
# #
@ -7,34 +12,29 @@
# * python2-pythondialog # * python2-pythondialog
# * dialog # * dialog
import ConfigParser
import curses
import os import os
import sys import sys
import StringIO
from textwrap import *
import time import time
from time import strftime, localtime from textwrap import fill
from threading import Timer from threading import Timer
import curses from addresses import addBMIfNotPresent, decodeAddress
import dialog
from dialog import Dialog
from helper_sql import *
from helper_ackPayload import genAckPayload
from addresses import *
import ConfigParser
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from dialog import Dialog
from helper_ackPayload import genAckPayload
from helper_sql import sqlExecute, sqlQuery
from inventory import Inventory from inventory import Inventory
import l10n import l10n
import network.stats
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
import queues import queues
import shared import shared
import shutdown import shutdown
import network.stats
quit = False quit = False # pylint: disable=redefined-builtin
menutab = 1 menutab = 1
menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"] menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"]
naptime = 100 naptime = 100
@ -60,37 +60,55 @@ bwtype = "black"
BROADCAST_STR = "[Broadcast subscribers]" BROADCAST_STR = "[Broadcast subscribers]"
class printLog:
class printLog: # pylint: disable=no-self-use, no-init, old-style-class
"""Printing logs"""
def write(self, output): def write(self, output):
# pylint: disable=global-statement
global log global log
log += output log += output
def flush(self): def flush(self):
pass pass
class errLog:
class errLog: # pylint: disable=no-self-use, no-init, old-style-class
"""Error logs"""
def write(self, output): def write(self, output):
# pylint: disable=global-statement
global log global log
log += "!" + output log += "!" + output
def flush(self): def flush(self):
pass pass
printlog = printLog() printlog = printLog()
errlog = errLog() errlog = errLog()
def cpair(a): def cpair(a):
"""Color pairs"""
r = curses.color_pair(a) r = curses.color_pair(a)
if r not in range(1, curses.COLOR_PAIRS - 1): if r not in range(1, curses.COLOR_PAIRS - 1):
r = curses.color_pair(0) r = curses.color_pair(0)
return r return r
def ascii(s): def ascii(s):
"""ASCII values"""
r = "" r = ""
for c in s: for c in s:
if ord(c) in range(128): if ord(c) in range(128):
r += c r += c
return r return r
def drawmenu(stdscr): def drawmenu(stdscr):
"""Creating menu's"""
menustr = " " menustr = " "
for i in range(0, len(menu)): for i, _ in enumerate(menu):
if menutab == i + 1: if menutab == i + 1:
menustr = menustr[:-1] menustr = menustr[:-1]
menustr += "[" menustr += "["
@ -101,24 +119,33 @@ def drawmenu(stdscr):
menustr += " " menustr += " "
stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE) stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE)
def set_background_title(d, title): def set_background_title(d, title):
"""Setting background title"""
try: try:
d.set_background_title(title) d.set_background_title(title)
except: except:
d.add_persistent_args(("--backtitle", title)) d.add_persistent_args(("--backtitle", title))
def scrollbox(d, text, height=None, width=None): def scrollbox(d, text, height=None, width=None):
"""Setting scroll box"""
try: try:
d.scrollbox(text, height, width, exit_label="Continue") d.scrollbox(text, height, width, exit_label="Continue")
except: except:
d.msgbox(text, height or 0, width or 0, ok_label="Continue") d.msgbox(text, height or 0, width or 0, ok_label="Continue")
def resetlookups(): def resetlookups():
global inventorydata """Reset the Inventory Lookups"""
global inventorydata # pylint: disable=global-statement
inventorydata = Inventory().numberOfInventoryLookupsPerformed inventorydata = Inventory().numberOfInventoryLookupsPerformed
Inventory().numberOfInventoryLookupsPerformed = 0 Inventory().numberOfInventoryLookupsPerformed = 0
Timer(1, resetlookups, ()).start() Timer(1, resetlookups, ()).start()
def drawtab(stdscr):
def drawtab(stdscr): # pylint: disable=too-many-branches, too-many-statements
"""Method for drawing different tabs"""
if menutab in range(1, len(menu) + 1): if menutab in range(1, len(menu) + 1):
if menutab == 1: # Inbox if menutab == 1: # Inbox
stdscr.addstr(3, 5, "To", curses.A_BOLD) stdscr.addstr(3, 5, "To", curses.A_BOLD)
@ -129,9 +156,10 @@ def drawtab(stdscr):
for i, item in enumerate(inbox[max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):]): for i, item in enumerate(inbox[max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):]):
if 6 + i < curses.LINES: if 6 + i < curses.LINES:
a = 0 a = 0
if i == inboxcur - max(min(len(inbox)-curses.LINES+6, inboxcur-5), 0): # Highlight current address if i == inboxcur - max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
if item[7] == False: # If not read, highlight if item[7] is False: # If not read, highlight
a = a | curses.A_BOLD a = a | curses.A_BOLD
stdscr.addstr(5 + i, 5, item[1][:34], a) stdscr.addstr(5 + i, 5, item[1][:34], a)
stdscr.addstr(5 + i, 40, item[3][:39], a) stdscr.addstr(5 + i, 40, item[3][:39], a)
@ -146,7 +174,8 @@ def drawtab(stdscr):
for i, item in enumerate(sentbox[max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):]): for i, item in enumerate(sentbox[max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):]):
if 6 + i < curses.LINES: if 6 + i < curses.LINES:
a = 0 a = 0
if i == sentcur - max(min(len(sentbox)-curses.LINES+6, sentcur-5), 0): # Highlight current address if i == sentcur - max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
stdscr.addstr(5 + i, 5, item[0][:34], a) stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[2][:39], a) stdscr.addstr(5 + i, 40, item[2][:39], a)
@ -160,9 +189,10 @@ def drawtab(stdscr):
for i, item in enumerate(addresses[max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):]): for i, item in enumerate(addresses[max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):]):
if 6 + i < curses.LINES: if 6 + i < curses.LINES:
a = 0 a = 0
if i == addrcur - max(min(len(addresses)-curses.LINES+6, addrcur-5), 0): # Highlight current address if i == addrcur - max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
if item[1] == True and item[3] not in [8,9]: # Embolden enabled, non-special addresses if item[1] and item[3] not in [8, 9]: # Embolden enabled, non-special addresses
a = a | curses.A_BOLD a = a | curses.A_BOLD
stdscr.addstr(5 + i, 5, item[0][:34], a) stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[2][:39], cpair(item[3]) | a) stdscr.addstr(5 + i, 40, item[2][:39], cpair(item[3]) | a)
@ -175,9 +205,10 @@ def drawtab(stdscr):
for i, item in enumerate(subscriptions[max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):]): for i, item in enumerate(subscriptions[max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):]):
if 6 + i < curses.LINES: if 6 + i < curses.LINES:
a = 0 a = 0
if i == subcur - max(min(len(subscriptions)-curses.LINES+6, subcur-5), 0): # Highlight current address if i == subcur - max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
if item[2] == True: # Embolden enabled subscriptions if item[2]: # Embolden enabled subscriptions
a = a | curses.A_BOLD a = a | curses.A_BOLD
stdscr.addstr(5 + i, 5, item[0][:74], a) stdscr.addstr(5 + i, 5, item[0][:74], a)
stdscr.addstr(5 + i, 80, item[1][:39], a) stdscr.addstr(5 + i, 80, item[1][:39], a)
@ -189,7 +220,8 @@ def drawtab(stdscr):
for i, item in enumerate(addrbook[max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):]): for i, item in enumerate(addrbook[max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):]):
if 6 + i < curses.LINES: if 6 + i < curses.LINES:
a = 0 a = 0
if i == abookcur - max(min(len(addrbook)-curses.LINES+6, abookcur-5), 0): # Highlight current address if i == abookcur - max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
stdscr.addstr(5 + i, 5, item[0][:34], a) stdscr.addstr(5 + i, 5, item[0][:34], a)
stdscr.addstr(5 + i, 40, item[1][:39], a) stdscr.addstr(5 + i, 40, item[1][:39], a)
@ -202,9 +234,10 @@ def drawtab(stdscr):
for i, item in enumerate(blacklist[max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):]): for i, item in enumerate(blacklist[max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):]):
if 7 + i < curses.LINES: if 7 + i < curses.LINES:
a = 0 a = 0
if i == blackcur - max(min(len(blacklist)-curses.LINES+6, blackcur-5), 0): # Highlight current address if i == blackcur - max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):
# Highlight current address
a = a | curses.A_REVERSE a = a | curses.A_REVERSE
if item[2] == True: # Embolden enabled subscriptions if item[2]: # Embolden enabled subscriptions
a = a | curses.A_BOLD a = a | curses.A_BOLD
stdscr.addstr(6 + i, 5, item[0][:74], a) stdscr.addstr(6 + i, 5, item[0][:74], a)
stdscr.addstr(6 + i, 80, item[1][:39], a) stdscr.addstr(6 + i, 80, item[1][:39], a)
@ -235,9 +268,12 @@ def drawtab(stdscr):
# Uptime and processing data # Uptime and processing data
stdscr.addstr(6, 35, "Since startup on " + l10n.formatTimestamp(startuptime, False)) stdscr.addstr(6, 35, "Since startup on " + l10n.formatTimestamp(startuptime, False))
stdscr.addstr(7, 40, "Processed "+str(shared.numberOfMessagesProcessed).ljust(4)+" person-to-person messages.") stdscr.addstr(7, 40, "Processed " + str(
stdscr.addstr(8, 40, "Processed "+str(shared.numberOfBroadcastsProcessed).ljust(4)+" broadcast messages.") shared.numberOfMessagesProcessed).ljust(4) + " person-to-person messages.")
stdscr.addstr(9, 40, "Processed "+str(shared.numberOfPubkeysProcessed).ljust(4)+" public keys.") stdscr.addstr(8, 40, "Processed " + str(
shared.numberOfBroadcastsProcessed).ljust(4) + " broadcast messages.")
stdscr.addstr(9, 40, "Processed " + str(
shared.numberOfPubkeysProcessed).ljust(4) + " public keys.")
# Inventory data # Inventory data
stdscr.addstr(11, 35, "Inventory lookups per second: " + str(inventorydata).ljust(3)) stdscr.addstr(11, 35, "Inventory lookups per second: " + str(inventorydata).ljust(3))
@ -253,23 +289,32 @@ def drawtab(stdscr):
n = len(l) n = len(l)
for i, item in enumerate(l): for i, item in enumerate(l):
a = 0 a = 0
if len(item) > 0 and item[0] == '!': if item and item[0] == '!':
a = curses.color_pair(1) a = curses.color_pair(1)
item = item[1:] item = item[1:]
logpad.addstr(i, 0, item, a) logpad.addstr(i, 0, item, a)
logpad.refresh(n - curses.LINES + 2, 0, 14, 6, curses.LINES - 2, curses.COLS - 7) logpad.refresh(n - curses.LINES + 2, 0, 14, 6, curses.LINES - 2, curses.COLS - 7)
stdscr.refresh() stdscr.refresh()
def redraw(stdscr): def redraw(stdscr):
"""Redraw menu"""
stdscr.erase() stdscr.erase()
stdscr.border() stdscr.border()
drawmenu(stdscr) drawmenu(stdscr)
stdscr.refresh() stdscr.refresh()
def dialogreset(stdscr): def dialogreset(stdscr):
"""Resetting dialogue"""
stdscr.clear() stdscr.clear()
stdscr.keypad(1) stdscr.keypad(1)
curses.curs_set(0) curses.curs_set(0)
# pylint: disable=too-many-branches, too-many-statements
def handlech(c, stdscr): def handlech(c, stdscr):
# pylint: disable=redefined-outer-name, too-many-nested-blocks, too-many-locals, global-statement
if c != curses.ERR: if c != curses.ERR:
global inboxcur, addrcur, sentcur, subcur, abookcur, blackcur global inboxcur, addrcur, sentcur, subcur, abookcur, blackcur
if c in range(256): if c in range(256):
@ -284,8 +329,10 @@ def handlech(c, stdscr):
d = Dialog(dialog="dialog") d = Dialog(dialog="dialog")
if menutab == 1: if menutab == 1:
set_background_title(d, "Inbox Message Dialog Box") set_background_title(d, "Inbox Message Dialog Box")
r, t = d.menu("Do what with \""+inbox[inboxcur][5]+"\" from \""+inbox[inboxcur][3]+"\"?", r, t = d.menu(
choices=[("1", "View message"), "Do what with \"" + inbox[inboxcur][5] + "\" from \"" + inbox[inboxcur][3] + "\"?",
choices=[
("1", "View message"),
("2", "Mark message as unread"), ("2", "Mark message as unread"),
("3", "Reply"), ("3", "Reply"),
("4", "Add sender to Address Book"), ("4", "Add sender to Address Book"),
@ -293,8 +340,16 @@ def handlech(c, stdscr):
("6", "Move to trash")]) ("6", "Move to trash")])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": # View if t == "1": # View
set_background_title(d, "\""+inbox[inboxcur][5]+"\" from \""+inbox[inboxcur][3]+"\" to \""+inbox[inboxcur][1]+"\"") set_background_title(
data = "" d,
"\"" +
inbox[inboxcur][5] +
"\" from \"" +
inbox[inboxcur][3] +
"\" to \"" +
inbox[inboxcur][1] +
"\"")
data = "" # pyint: disable=redefined-outer-name
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0]) ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0])
if ret != []: if ret != []:
for row in ret: for row in ret:
@ -320,8 +375,10 @@ def handlech(c, stdscr):
if fromaddr == item[2] and item[3] != 0: if fromaddr == item[2] and item[3] != 0:
ischan = True ischan = True
break break
if not addresses[i][1]: if not addresses[i][1]: # pylint: disable=undefined-loop-variable
scrollbox(d, unicode("Sending address disabled, please either enable it or choose a different address.")) scrollbox(d, unicode(
"Sending address disabled, please either enable it"
"or choose a different address."))
return return
toaddr = m[2] toaddr = m[2]
if ischan: if ischan:
@ -369,7 +426,9 @@ def handlech(c, stdscr):
elif t == "6": # Move to trash elif t == "6": # Move to trash
sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", inbox[inboxcur][0]) sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", inbox[inboxcur][0])
del inbox[inboxcur] del inbox[inboxcur]
scrollbox(d, unicode("Message moved to trash. There is no interface to view your trash, \nbut the message is still on disk if you are desperate to recover it.")) scrollbox(d, unicode(
"Message moved to trash. There is no interface to view your trash,"
" \nbut the message is still on disk if you are desperate to recover it."))
elif menutab == 2: elif menutab == 2:
a = "" a = ""
if addresses[addrcur][3] != 0: # if current address is a chan if addresses[addrcur][3] != 0: # if current address is a chan
@ -377,14 +436,27 @@ def handlech(c, stdscr):
sendMessage(addresses[addrcur][2], a) sendMessage(addresses[addrcur][2], a)
elif menutab == 3: elif menutab == 3:
set_background_title(d, "Sent Messages Dialog Box") set_background_title(d, "Sent Messages Dialog Box")
r, t = d.menu("Do what with \""+sentbox[sentcur][4]+"\" to \""+sentbox[sentcur][0]+"\"?", r, t = d.menu(
choices=[("1", "View message"), "Do what with \"" + sentbox[sentcur][4] + "\" to \"" + sentbox[sentcur][0] + "\"?",
choices=[
("1", "View message"),
("2", "Move to trash")]) ("2", "Move to trash")])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": # View if t == "1": # View
set_background_title(d, "\""+sentbox[sentcur][4]+"\" from \""+sentbox[sentcur][3]+"\" to \""+sentbox[sentcur][1]+"\"") set_background_title(
d,
"\"" +
sentbox[sentcur][4] +
"\" from \"" +
sentbox[sentcur][3] +
"\" to \"" +
sentbox[sentcur][1] +
"\"")
data = "" data = ""
ret = sqlQuery("SELECT message FROM sent WHERE subject=? AND ackdata=?", sentbox[sentcur][4], sentbox[sentcur][6]) ret = sqlQuery(
"SELECT message FROM sent WHERE subject=? AND ackdata=?",
sentbox[sentcur][4],
sentbox[sentcur][6])
if ret != []: if ret != []:
for row in ret: for row in ret:
data, = row data, = row
@ -396,17 +468,26 @@ def handlech(c, stdscr):
else: else:
scrollbox(d, unicode("Could not fetch message.")) scrollbox(d, unicode("Could not fetch message."))
elif t == "2": # Move to trash elif t == "2": # Move to trash
sqlExecute("UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?", sentbox[sentcur][4], sentbox[sentcur][6]) sqlExecute(
"UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?",
sentbox[sentcur][4],
sentbox[sentcur][6])
del sentbox[sentcur] del sentbox[sentcur]
scrollbox(d, unicode("Message moved to trash. There is no interface to view your trash, \nbut the message is still on disk if you are desperate to recover it.")) scrollbox(d, unicode(
"Message moved to trash. There is no interface to view your trash"
" \nbut the message is still on disk if you are desperate to recover it."))
elif menutab == 4: elif menutab == 4:
set_background_title(d, "Your Identities Dialog Box") set_background_title(d, "Your Identities Dialog Box")
if len(addresses) <= addrcur: if len(addresses) <= addrcur:
r, t = d.menu("Do what with addresses?", r, t = d.menu(
choices=[("1", "Create new address")]) "Do what with addresses?",
choices=[
("1", "Create new address")])
else: else:
r, t = d.menu("Do what with \""+addresses[addrcur][0]+"\" : \""+addresses[addrcur][2]+"\"?", r, t = d.menu(
choices=[("1", "Create new address"), "Do what with \"" + addresses[addrcur][0] + "\" : \"" + addresses[addrcur][2] + "\"?",
choices=[
("1", "Create new address"),
("2", "Send a message from this address"), ("2", "Send a message from this address"),
("3", "Rename"), ("3", "Rename"),
("4", "Enable"), ("4", "Enable"),
@ -416,29 +497,39 @@ def handlech(c, stdscr):
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": # Create new address if t == "1": # Create new address
set_background_title(d, "Create new address") set_background_title(d, "Create new address")
scrollbox(d, unicode("Here you may generate as many addresses as you like.\n" scrollbox(
d, unicode(
"Here you may generate as many addresses as you like.\n"
"Indeed, creating and abandoning addresses is encouraged.\n" "Indeed, creating and abandoning addresses is encouraged.\n"
"Deterministic addresses have several pros and cons:\n" "Deterministic addresses have several pros and cons:\n"
"\nPros:\n" "\nPros:\n"
" * You can recreate your addresses on any computer from memory\n" " * You can recreate your addresses on any computer from memory\n"
" * You need not worry about backing up your keys.dat file as long as you \n can remember your passphrase\n" " * You need not worry about backing up your keys.dat file as long as you"
" \n can remember your passphrase\n"
"Cons:\n" "Cons:\n"
" * You must remember (or write down) your passphrase in order to recreate \n your keys if they are lost\n" " * You must remember (or write down) your passphrase in order to recreate"
" \n your keys if they are lost\n"
" * You must also remember the address version and stream numbers\n" " * You must also remember the address version and stream numbers\n"
" * If you choose a weak passphrase someone may be able to brute-force it \n and then send and receive messages as you")) " * If you choose a weak passphrase someone may be able to brute-force it"
r, t = d.menu("Choose an address generation technique", " \n and then send and receive messages as you"))
choices=[("1", "Use a random number generator"), r, t = d.menu(
"Choose an address generation technique",
choices=[
("1", "Use a random number generator"),
("2", "Use a passphrase")]) ("2", "Use a passphrase")])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": if t == "1":
set_background_title(d, "Randomly generate address") set_background_title(d, "Randomly generate address")
r, t = d.inputbox("Label (not shown to anyone except you)") r, t = d.inputbox("Label (not shown to anyone except you)")
label = "" label = ""
if r == d.DIALOG_OK and len(t) > 0: if r == d.DIALOG_OK and t:
label = t label = t
r, t = d.menu("Choose a stream", r, t = d.menu(
choices=[("1", "Use the most available stream"),("", "(Best if this is the first of many addresses you will create)"), "Choose a stream",
("2", "Use the same stream as an existing address"),("", "(Saves you some bandwidth and processing power)")]) choices=[("1", "Use the most available stream"),
("", "(Best if this is the first of many addresses you will create)"),
("2", "Use the same stream as an existing address"),
("", "(Saves you some bandwidth and processing power)")])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": if t == "1":
stream = 1 stream = 1
@ -450,34 +541,61 @@ def handlech(c, stdscr):
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
stream = decodeAddress(addrs[int(t)][1])[2] stream = decodeAddress(addrs[int(t)][1])[2]
shorten = False shorten = False
r, t = d.checklist("Miscellaneous options", r, t = d.checklist(
choices=[("1", "Spend time shortening the address", 1 if shorten else 0)]) "Miscellaneous options",
choices=[(
"1",
"Spend time shortening the address",
1 if shorten else 0)])
if r == d.DIALOG_OK and "1" in t: if r == d.DIALOG_OK and "1" in t:
shorten = True shorten = True
queues.addressGeneratorQueue.put(("createRandomAddress", 4, stream, label, 1, "", shorten)) queues.addressGeneratorQueue.put((
"createRandomAddress",
4,
stream,
label,
1,
"",
shorten))
elif t == "2": elif t == "2":
set_background_title(d, "Make deterministic addresses") set_background_title(d, "Make deterministic addresses")
r, t = d.passwordform("Enter passphrase", r, t = d.passwordform(
[("Passphrase", 1, 1, "", 2, 1, 64, 128), "Enter passphrase",
[
("Passphrase", 1, 1, "", 2, 1, 64, 128),
("Confirm passphrase", 3, 1, "", 4, 1, 64, 128)], ("Confirm passphrase", 3, 1, "", 4, 1, 64, 128)],
form_height=4, insecure=True) form_height=4, insecure=True)
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t[0] == t[1]: if t[0] == t[1]:
passphrase = t[0] passphrase = t[0]
r, t = d.rangebox("Number of addresses to generate", r, t = d.rangebox(
width=48, min=1, max=99, init=8) "Number of addresses to generate",
width=48,
min=1,
max=99,
init=8)
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
number = t number = t
stream = 1 stream = 1
shorten = False shorten = False
r, t = d.checklist("Miscellaneous options", r, t = d.checklist(
choices=[("1", "Spend time shortening the address", 1 if shorten else 0)]) "Miscellaneous options",
choices=[(
"1",
"Spend time shortening the address",
1 if shorten else 0)])
if r == d.DIALOG_OK and "1" in t: if r == d.DIALOG_OK and "1" in t:
shorten = True shorten = True
scrollbox(d, unicode("In addition to your passphrase, be sure to remember the following numbers:\n" scrollbox(
d, unicode(
"In addition to your passphrase, be sure to remember the"
" following numbers:\n"
"\n * Address version number: " + str(4) + "\n" "\n * Address version number: " + str(4) + "\n"
" * Stream number: " + str(stream))) " * Stream number: " + str(stream)))
queues.addressGeneratorQueue.put(('createDeterministicAddresses', 4, stream, "unused deterministic address", number, str(passphrase), shorten)) queues.addressGeneratorQueue.put(
('createDeterministicAddresses', 4, stream,
"unused deterministic address", number,
str(passphrase), shorten))
else: else:
scrollbox(d, unicode("Passphrases do not match")) scrollbox(d, unicode("Passphrases do not match"))
elif t == "2": # Send a message elif t == "2": # Send a message
@ -527,20 +645,23 @@ def handlech(c, stdscr):
a = addresses[addrcur][2] a = addresses[addrcur][2]
set_background_title(d, "Special address behavior") set_background_title(d, "Special address behavior")
if BMConfigParser().safeGetBoolean(a, "chan"): if BMConfigParser().safeGetBoolean(a, "chan"):
scrollbox(d, unicode("This is a chan address. You cannot use it as a pseudo-mailing list.")) scrollbox(d, unicode(
"This is a chan address. You cannot use it as a pseudo-mailing list."))
else: else:
m = BMConfigParser().safeGetBoolean(a, "mailinglist") m = BMConfigParser().safeGetBoolean(a, "mailinglist")
r, t = d.radiolist("Select address behavior", r, t = d.radiolist(
choices=[("1", "Behave as a normal address", not m), "Select address behavior",
choices=[
("1", "Behave as a normal address", not m),
("2", "Behave as a pseudo-mailing-list address", m)]) ("2", "Behave as a pseudo-mailing-list address", m)])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1" and m == True: if t == "1" and m:
BMConfigParser().set(a, "mailinglist", "false") BMConfigParser().set(a, "mailinglist", "false")
if addresses[addrcur][1]: if addresses[addrcur][1]:
addresses[addrcur][3] = 0 # Set color to black addresses[addrcur][3] = 0 # Set color to black
else: else:
addresses[addrcur][3] = 8 # Set color to gray addresses[addrcur][3] = 8 # Set color to gray
elif t == "2" and m == False: elif t == "2" and m is False:
try: try:
mn = BMConfigParser().get(a, "mailinglistname") mn = BMConfigParser().get(a, "mailinglistname")
except ConfigParser.NoOptionError: except ConfigParser.NoOptionError:
@ -556,11 +677,15 @@ def handlech(c, stdscr):
elif menutab == 5: elif menutab == 5:
set_background_title(d, "Subscriptions Dialog Box") set_background_title(d, "Subscriptions Dialog Box")
if len(subscriptions) <= subcur: if len(subscriptions) <= subcur:
r, t = d.menu("Do what with subscription to \""+subscriptions[subcur][0]+"\"?", r, t = d.menu(
choices=[("1", "Add new subscription")]) "Do what with subscription to \"" + subscriptions[subcur][0] + "\"?",
choices=[
("1", "Add new subscription")])
else: else:
r, t = d.menu("Do what with subscription to \""+subscriptions[subcur][0]+"\"?", r, t = d.menu(
choices=[("1", "Add new subscription"), "Do what with subscription to \"" + subscriptions[subcur][0] + "\"?",
choices=[
("1", "Add new subscription"),
("2", "Delete this subscription"), ("2", "Delete this subscription"),
("3", "Enable"), ("3", "Enable"),
("4", "Disable")]) ("4", "Disable")])
@ -581,27 +706,39 @@ def handlech(c, stdscr):
sqlExecute("INSERT INTO subscriptions VALUES (?,?,?)", label, addr, True) sqlExecute("INSERT INTO subscriptions VALUES (?,?,?)", label, addr, True)
shared.reloadBroadcastSendersForWhichImWatching() shared.reloadBroadcastSendersForWhichImWatching()
elif t == "2": elif t == "2":
r, t = d.inpuxbox("Type in \"I want to delete this subscription\"") r, t = d.inputbox("Type in \"I want to delete this subscription\"")
if r == d.DIALOG_OK and t == "I want to delete this subscription": if r == d.DIALOG_OK and t == "I want to delete this subscription":
sqlExecute("DELETE FROM subscriptions WHERE label=? AND address=?", subscriptions[subcur][0], subscriptions[subcur][1]) sqlExecute(
"DELETE FROM subscriptions WHERE label=? AND address=?",
subscriptions[subcur][0],
subscriptions[subcur][1])
shared.reloadBroadcastSendersForWhichImWatching() shared.reloadBroadcastSendersForWhichImWatching()
del subscriptions[subcur] del subscriptions[subcur]
elif t == "3": elif t == "3":
sqlExecute("UPDATE subscriptions SET enabled=1 WHERE label=? AND address=?", subscriptions[subcur][0], subscriptions[subcur][1]) sqlExecute(
"UPDATE subscriptions SET enabled=1 WHERE label=? AND address=?",
subscriptions[subcur][0],
subscriptions[subcur][1])
shared.reloadBroadcastSendersForWhichImWatching() shared.reloadBroadcastSendersForWhichImWatching()
subscriptions[subcur][2] = True subscriptions[subcur][2] = True
elif t == "4": elif t == "4":
sqlExecute("UPDATE subscriptions SET enabled=0 WHERE label=? AND address=?", subscriptions[subcur][0], subscriptions[subcur][1]) sqlExecute(
"UPDATE subscriptions SET enabled=0 WHERE label=? AND address=?",
subscriptions[subcur][0],
subscriptions[subcur][1])
shared.reloadBroadcastSendersForWhichImWatching() shared.reloadBroadcastSendersForWhichImWatching()
subscriptions[subcur][2] = False subscriptions[subcur][2] = False
elif menutab == 6: elif menutab == 6:
set_background_title(d, "Address Book Dialog Box") set_background_title(d, "Address Book Dialog Box")
if len(addrbook) <= abookcur: if len(addrbook) <= abookcur:
r, t = d.menu("Do what with addressbook?", r, t = d.menu(
"Do what with addressbook?",
choices=[("3", "Add new address to Address Book")]) choices=[("3", "Add new address to Address Book")])
else: else:
r, t = d.menu("Do what with \""+addrbook[abookcur][0]+"\" : \""+addrbook[abookcur][1]+"\"", r, t = d.menu(
choices=[("1", "Send a message to this address"), "Do what with \"" + addrbook[abookcur][0] + "\" : \"" + addrbook[abookcur][1] + "\"",
choices=[
("1", "Send a message to this address"),
("2", "Subscribe to this address"), ("2", "Subscribe to this address"),
("3", "Add new address to Address Book"), ("3", "Add new address to Address Book"),
("4", "Delete this address")]) ("4", "Delete this address")])
@ -636,25 +773,39 @@ def handlech(c, stdscr):
elif t == "4": elif t == "4":
r, t = d.inputbox("Type in \"I want to delete this Address Book entry\"") r, t = d.inputbox("Type in \"I want to delete this Address Book entry\"")
if r == d.DIALOG_OK and t == "I want to delete this Address Book entry": if r == d.DIALOG_OK and t == "I want to delete this Address Book entry":
sqlExecute("DELETE FROM addressbook WHERE label=? AND address=?", addrbook[abookcur][0], addrbook[abookcur][1]) sqlExecute(
"DELETE FROM addressbook WHERE label=? AND address=?",
addrbook[abookcur][0],
addrbook[abookcur][1])
del addrbook[abookcur] del addrbook[abookcur]
elif menutab == 7: elif menutab == 7:
set_background_title(d, "Blacklist Dialog Box") set_background_title(d, "Blacklist Dialog Box")
r, t = d.menu("Do what with \""+blacklist[blackcur][0]+"\" : \""+blacklist[blackcur][1]+"\"?", r, t = d.menu(
choices=[("1", "Delete"), "Do what with \"" + blacklist[blackcur][0] + "\" : \"" + blacklist[blackcur][1] + "\"?",
choices=[
("1", "Delete"),
("2", "Enable"), ("2", "Enable"),
("3", "Disable")]) ("3", "Disable")])
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
if t == "1": if t == "1":
r, t = d.inputbox("Type in \"I want to delete this Blacklist entry\"") r, t = d.inputbox("Type in \"I want to delete this Blacklist entry\"")
if r == d.DIALOG_OK and t == "I want to delete this Blacklist entry": if r == d.DIALOG_OK and t == "I want to delete this Blacklist entry":
sqlExecute("DELETE FROM blacklist WHERE label=? AND address=?", blacklist[blackcur][0], blacklist[blackcur][1]) sqlExecute(
"DELETE FROM blacklist WHERE label=? AND address=?",
blacklist[blackcur][0],
blacklist[blackcur][1])
del blacklist[blackcur] del blacklist[blackcur]
elif t == "2": elif t == "2":
sqlExecute("UPDATE blacklist SET enabled=1 WHERE label=? AND address=?", blacklist[blackcur][0], blacklist[blackcur][1]) sqlExecute(
"UPDATE blacklist SET enabled=1 WHERE label=? AND address=?",
blacklist[blackcur][0],
blacklist[blackcur][1])
blacklist[blackcur][2] = True blacklist[blackcur][2] = True
elif t == "3": elif t == "3":
sqlExecute("UPDATE blacklist SET enabled=0 WHERE label=? AND address=?", blacklist[blackcur][0], blacklist[blackcur][1]) sqlExecute(
"UPDATE blacklist SET enabled=0 WHERE label=? AND address=?",
blacklist[blackcur][0],
blacklist[blackcur][1])
blacklist[blackcur][2] = False blacklist[blackcur][2] = False
dialogreset(stdscr) dialogreset(stdscr)
else: else:
@ -711,21 +862,30 @@ def handlech(c, stdscr):
if menutab == 7: if menutab == 7:
blackcur = len(blackcur) - 1 blackcur = len(blackcur) - 1
redraw(stdscr) redraw(stdscr)
# pylint: disable=too-many-locals, too-many-arguments
def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=False): def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=False):
"""Method for message sending"""
if sender == "": if sender == "":
return return
d = Dialog(dialog="dialog") d = Dialog(dialog="dialog")
set_background_title(d, "Send a message") set_background_title(d, "Send a message")
if recv == "": if recv == "":
r, t = d.inputbox("Recipient address (Cancel to load from the Address Book or leave blank to broadcast)", 10, 60) r, t = d.inputbox(
"Recipient address (Cancel to load from the Address Book or leave blank to broadcast)",
10,
60)
if r != d.DIALOG_OK: if r != d.DIALOG_OK:
global menutab global menutab # pylint: disable=global-statement
menutab = 6 menutab = 6
return return
recv = t recv = t
if broadcast == None and sender != recv: if broadcast is None and sender != recv:
r, t = d.radiolist("How to send the message?", r, t = d.radiolist(
choices=[("1", "Send to one or more specific people", 1), "How to send the message?",
choices=[
("1", "Send to one or more specific people", 1),
("2", "Broadcast to everyone who is subscribed to your address", 0)]) ("2", "Broadcast to everyone who is subscribed to your address", 0)])
if r != d.DIALOG_OK: if r != d.DIALOG_OK:
return return
@ -751,6 +911,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
list(set(recvlist)) # Remove exact duplicates list(set(recvlist)) # Remove exact duplicates
for addr in recvlist: for addr in recvlist:
if addr != "": if addr != "":
# pylint: disable=redefined-outer-name
status, version, stream, ripe = decodeAddress(addr) status, version, stream, ripe = decodeAddress(addr)
if status != "success": if status != "success":
set_background_title(d, "Recipient address error") set_background_title(d, "Recipient address error")
@ -762,13 +923,17 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
elif status == "invalidcharacters": elif status == "invalidcharacters":
err += "The address contains invalid characters." err += "The address contains invalid characters."
elif status == "versiontoohigh": elif status == "versiontoohigh":
err += "The address version is too high. Either you need to upgrade your Bitmessage software or your acquaintance is doing something clever." err += ("The address version is too high. Either you need to upgrade your Bitmessage software"
" or your acquaintance is doing something clever.")
elif status == "ripetooshort": elif status == "ripetooshort":
err += "Some data encoded in the address is too short. There might be something wrong with the software of your acquaintance." err += ("Some data encoded in the address is too short. There might be something wrong with"
" the software of your acquaintance.")
elif status == "ripetoolong": elif status == "ripetoolong":
err += "Some data encoded in the address is too long. There might be something wrong with the software of your acquaintance." err += ("Some data encoded in the address is too long. There might be something wrong with"
" the software of your acquaintance.")
elif status == "varintmalformed": elif status == "varintmalformed":
err += "Some data encoded in the address is malformed. There might be something wrong with the software of your acquaintance." err += ("Some data encoded in the address is malformed. There might be something wrong with"
" the software of your acquaintance.")
else: else:
err += "It is unknown what is wrong with the address." err += "It is unknown what is wrong with the address."
scrollbox(d, unicode(err)) scrollbox(d, unicode(err))
@ -776,17 +941,24 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
addr = addBMIfNotPresent(addr) addr = addBMIfNotPresent(addr)
if version > 4 or version <= 1: if version > 4 or version <= 1:
set_background_title(d, "Recipient address error") set_background_title(d, "Recipient address error")
scrollbox(d, unicode("Could not understand version number " + version + "of address" + addr + ".")) scrollbox(d, unicode(
"Could not understand version number " +
version +
"of address" +
addr +
"."))
continue continue
if stream > 1 or stream == 0: if stream > 1 or stream == 0:
set_background_title(d, "Recipient address error") set_background_title(d, "Recipient address error")
scrollbox(d, unicode("Bitmessage currently only supports stream numbers of 1, unlike as requested for address " + addr + ".")) scrollbox(d, unicode(
"Bitmessage currently only supports stream numbers of 1,"
"unlike as requested for address " + addr + "."))
continue continue
if not network.stats.connectedHostsList(): if not network.stats.connectedHostsList():
set_background_title(d, "Not connected warning") set_background_title(d, "Not connected warning")
scrollbox(d, unicode("Because you are not currently connected to the network, ")) scrollbox(d, unicode("Because you are not currently connected to the network, "))
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel') stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
ackdata = genAckPayload(streamNumber, stealthLevel) ackdata = genAckPayload(decodeAddress(addr)[2], stealthLevel)
sqlExecute( sqlExecute(
"INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", "INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
"", "",
@ -811,7 +983,7 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
scrollbox(d, unicode("You must specify an address to send the message from.")) scrollbox(d, unicode("You must specify an address to send the message from."))
else: else:
# dummy ackdata, no need for stealth # dummy ackdata, no need for stealth
ackdata = genAckPayload(streamNumber, 0) ackdata = genAckPayload(decodeAddress(addr)[2], 0)
recv = BROADCAST_STR recv = BROADCAST_STR
ripe = "" ripe = ""
sqlExecute( sqlExecute(
@ -833,9 +1005,12 @@ def sendMessage(sender="", recv="", broadcast=None, subject="", body="", reply=F
BMConfigParser().getint('bitmessagesettings', 'ttl')) BMConfigParser().getint('bitmessagesettings', 'ttl'))
queues.workerQueue.put(('sendbroadcast', '')) queues.workerQueue.put(('sendbroadcast', ''))
# pylint: disable=redefined-outer-name, too-many-locals
def loadInbox(): def loadInbox():
"""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"
@ -879,12 +1054,15 @@ def loadInbox():
fromlabel = shared.fixPotentiallyInvalidUTF8Data(fromlabel) fromlabel = shared.fixPotentiallyInvalidUTF8Data(fromlabel)
# Load into array # Load into array
inbox.append([msgid, tolabel, toaddr, fromlabel, fromaddr, subject, inbox.append([msgid, tolabel, toaddr, fromlabel, fromaddr, subject, l10n.formatTimestamp(
l10n.formatTimestamp(received, False), read]) received, False), read])
inbox.reverse() inbox.reverse()
def loadSent(): def loadSent():
"""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"
@ -955,12 +1133,22 @@ def loadSent():
statstr = "Unknown status " + status + " at " + t + "." statstr = "Unknown status " + status + " at " + t + "."
# Load into array # Load into array
sentbox.append([tolabel, toaddr, fromlabel, fromaddr, subject, statstr, ackdata, sentbox.append([
tolabel,
toaddr,
fromlabel,
fromaddr,
subject,
statstr,
ackdata,
l10n.formatTimestamp(lastactiontime, False)]) l10n.formatTimestamp(lastactiontime, False)])
sentbox.reverse() sentbox.reverse()
def loadAddrBook(): def loadAddrBook():
"""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")
@ -969,14 +1157,20 @@ def loadAddrBook():
label = shared.fixPotentiallyInvalidUTF8Data(label) label = shared.fixPotentiallyInvalidUTF8Data(label)
addrbook.append([label, addr]) addrbook.append([label, addr])
addrbook.reverse() addrbook.reverse()
def loadSubscriptions(): def loadSubscriptions():
"""Load subscription functionality"""
ret = sqlQuery("SELECT label, address, enabled FROM subscriptions") ret = sqlQuery("SELECT label, address, enabled FROM subscriptions")
for row in ret: for row in ret:
label, address, enabled = row label, address, enabled = row
subscriptions.append([label, address, enabled]) subscriptions.append([label, address, enabled])
subscriptions.reverse() subscriptions.reverse()
def loadBlackWhiteList(): def loadBlackWhiteList():
global bwtype """load black/white list"""
global bwtype # pylint: disable=global-statement
bwtype = BMConfigParser().get("bitmessagesettings", "blackwhitelist") bwtype = BMConfigParser().get("bitmessagesettings", "blackwhitelist")
if bwtype == "black": if bwtype == "black":
ret = sqlQuery("SELECT label, address, enabled FROM blacklist") ret = sqlQuery("SELECT label, address, enabled FROM blacklist")
@ -987,6 +1181,7 @@ def loadBlackWhiteList():
blacklist.append([label, address, enabled]) blacklist.append([label, address, enabled])
blacklist.reverse() blacklist.reverse()
def runwrapper(): def runwrapper():
sys.stdout = printlog sys.stdout = printlog
# sys.stderr = errlog # sys.stderr = errlog
@ -1000,7 +1195,7 @@ def runwrapper():
stdscr = curses.initscr() stdscr = curses.initscr()
global logpad global logpad # pylint: disable=global-statement
logpad = curses.newpad(1024, curses.COLS) logpad = curses.newpad(1024, curses.COLS)
stdscr.nodelay(0) stdscr.nodelay(0)
@ -1010,6 +1205,7 @@ def runwrapper():
curses.wrapper(run) curses.wrapper(run)
doShutdown() doShutdown()
def run(stdscr): def run(stdscr):
# Schedule inventory lookup data # Schedule inventory lookup data
resetlookups() resetlookups()
@ -1050,16 +1246,18 @@ def run(stdscr):
stdscr.clear() stdscr.clear()
redraw(stdscr) redraw(stdscr)
while quit == False: while quit is False:
drawtab(stdscr) drawtab(stdscr)
handlech(stdscr.getch(), stdscr) handlech(stdscr.getch(), stdscr)
def doShutdown(): def doShutdown():
"""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__
sys.stderr = sys.__stderr__ sys.stderr = sys.__stderr__
os._exit(0) os._exit(0) # pylint: disable=protected-access