2019-09-23 11:42:40 +02:00
|
|
|
"""
|
2019-12-27 15:12:57 +01:00
|
|
|
Bitmessage commandline interface
|
2019-09-23 11:42:40 +02:00
|
|
|
"""
|
2014-04-18 07:48:42 +02:00
|
|
|
# Copyright (c) 2014 Luke Montalvo <lukemontalvo@gmail.com>
|
2014-04-29 07:10:33 +02:00
|
|
|
# This file adds a alternative commandline interface, feel free to critique and fork
|
2019-09-23 11:42:40 +02:00
|
|
|
#
|
2014-05-01 02:29:04 +02:00
|
|
|
# This has only been tested on Arch Linux and Linux Mint
|
2014-04-19 20:45:37 +02:00
|
|
|
# Dependencies:
|
|
|
|
# * from python2-pip
|
|
|
|
# * python2-pythondialog
|
|
|
|
# * dialog
|
2014-04-18 07:48:42 +02:00
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
import ConfigParser
|
|
|
|
import curses
|
2014-04-18 07:48:42 +02:00
|
|
|
import os
|
|
|
|
import sys
|
2014-04-19 20:45:37 +02:00
|
|
|
import time
|
2019-09-23 11:42:40 +02:00
|
|
|
from textwrap import fill
|
2014-04-19 20:45:37 +02:00
|
|
|
from threading import Timer
|
|
|
|
|
|
|
|
from dialog import Dialog
|
2017-02-08 13:41:56 +01:00
|
|
|
import l10n
|
2019-09-23 11:42:40 +02:00
|
|
|
import network.stats
|
2017-02-08 13:41:56 +01:00
|
|
|
import queues
|
|
|
|
import shared
|
|
|
|
import shutdown
|
2018-11-01 15:28:42 +01:00
|
|
|
|
2019-12-27 15:12:57 +01:00
|
|
|
from addresses import addBMIfNotPresent, decodeAddress
|
|
|
|
from bmconfigparser import BMConfigParser
|
|
|
|
from helper_ackPayload import genAckPayload
|
|
|
|
from helper_sql import sqlExecute, sqlQuery
|
|
|
|
from inventory import Inventory
|
|
|
|
# pylint: disable=global-statement
|
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
|
2019-12-27 15:12:57 +01:00
|
|
|
quit_ = False
|
2014-04-18 07:48:42 +02:00
|
|
|
menutab = 1
|
|
|
|
menu = ["Inbox", "Send", "Sent", "Your Identities", "Subscriptions", "Address Book", "Blacklist", "Network Status"]
|
2014-04-19 20:57:08 +02:00
|
|
|
naptime = 100
|
2014-04-18 07:48:42 +02:00
|
|
|
log = ""
|
2014-04-19 20:45:37 +02:00
|
|
|
logpad = None
|
|
|
|
inventorydata = 0
|
|
|
|
startuptime = time.time()
|
2014-04-29 07:10:33 +02:00
|
|
|
|
|
|
|
inbox = []
|
|
|
|
inboxcur = 0
|
2014-04-30 04:45:41 +02:00
|
|
|
sentbox = []
|
2014-04-29 07:10:33 +02:00
|
|
|
sentcur = 0
|
2014-04-18 07:48:42 +02:00
|
|
|
addresses = []
|
|
|
|
addrcur = 0
|
2014-04-19 20:45:37 +02:00
|
|
|
addrcopy = 0
|
2014-04-29 07:10:33 +02:00
|
|
|
subscriptions = []
|
|
|
|
subcur = 0
|
|
|
|
addrbook = []
|
|
|
|
abookcur = 0
|
|
|
|
blacklist = []
|
|
|
|
blackcur = 0
|
2014-04-30 04:45:41 +02:00
|
|
|
bwtype = "black"
|
2014-04-29 07:10:33 +02:00
|
|
|
|
|
|
|
BROADCAST_STR = "[Broadcast subscribers]"
|
2014-04-18 07:48:42 +02:00
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2019-12-27 15:12:57 +01:00
|
|
|
class printLog(object):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Printing logs"""
|
2019-12-27 15:12:57 +01:00
|
|
|
# pylint: disable=no-self-use
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
def write(self, output):
|
2019-12-27 15:12:57 +01:00
|
|
|
"""Write logs"""
|
2014-04-18 07:48:42 +02:00
|
|
|
global log
|
|
|
|
log += output
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
def flush(self):
|
2019-12-27 15:12:57 +01:00
|
|
|
"""Flush logs"""
|
2014-04-19 20:45:37 +02:00
|
|
|
pass
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
2019-12-27 15:12:57 +01:00
|
|
|
class errLog(object):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Error logs"""
|
2019-12-27 15:12:57 +01:00
|
|
|
# pylint: disable=no-self-use
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
def write(self, output):
|
2019-12-27 15:12:57 +01:00
|
|
|
"""Write error logs"""
|
2014-04-19 20:45:37 +02:00
|
|
|
global log
|
2019-09-23 11:42:40 +02:00
|
|
|
log += "!" + output
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
def flush(self):
|
2019-12-27 15:12:57 +01:00
|
|
|
"""Flush error logs"""
|
2014-04-19 20:45:37 +02:00
|
|
|
pass
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
printlog = printLog()
|
2014-04-19 20:45:37 +02:00
|
|
|
errlog = errLog()
|
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
|
|
|
|
def cpair(a):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Color pairs"""
|
2014-04-18 07:48:42 +02:00
|
|
|
r = curses.color_pair(a)
|
2019-09-23 11:42:40 +02:00
|
|
|
if r not in range(1, curses.COLOR_PAIRS - 1):
|
2014-04-18 07:48:42 +02:00
|
|
|
r = curses.color_pair(0)
|
|
|
|
return r
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
2014-04-29 07:10:33 +02:00
|
|
|
def ascii(s):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""ASCII values"""
|
2014-04-29 07:10:33 +02:00
|
|
|
r = ""
|
|
|
|
for c in s:
|
|
|
|
if ord(c) in range(128):
|
|
|
|
r += c
|
|
|
|
return r
|
2014-04-18 07:48:42 +02:00
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
def drawmenu(stdscr):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Creating menu's"""
|
2014-04-18 07:48:42 +02:00
|
|
|
menustr = " "
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, _ in enumerate(menu):
|
|
|
|
if menutab == i + 1:
|
2014-04-18 07:48:42 +02:00
|
|
|
menustr = menustr[:-1]
|
|
|
|
menustr += "["
|
2019-09-23 11:42:40 +02:00
|
|
|
menustr += str(i + 1) + menu[i]
|
|
|
|
if menutab == i + 1:
|
2014-04-18 07:48:42 +02:00
|
|
|
menustr += "] "
|
2019-09-23 11:42:40 +02:00
|
|
|
elif i != len(menu) - 1:
|
2014-04-18 07:48:42 +02:00
|
|
|
menustr += " "
|
|
|
|
stdscr.addstr(2, 5, menustr, curses.A_UNDERLINE)
|
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2016-06-30 12:28:17 +02:00
|
|
|
def set_background_title(d, title):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Setting background title"""
|
2016-06-30 12:28:17 +02:00
|
|
|
try:
|
|
|
|
d.set_background_title(title)
|
|
|
|
except:
|
|
|
|
d.add_persistent_args(("--backtitle", title))
|
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2016-06-30 12:28:17 +02:00
|
|
|
def scrollbox(d, text, height=None, width=None):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Setting scroll box"""
|
2016-06-30 12:28:17 +02:00
|
|
|
try:
|
2019-09-23 11:42:40 +02:00
|
|
|
d.scrollbox(text, height, width, exit_label="Continue")
|
2016-06-30 12:28:17 +02:00
|
|
|
except:
|
2019-09-23 11:42:40 +02:00
|
|
|
d.msgbox(text, height or 0, width or 0, ok_label="Continue")
|
|
|
|
|
2016-06-30 12:28:17 +02:00
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
def resetlookups():
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Reset the Inventory Lookups"""
|
2019-12-27 15:12:57 +01:00
|
|
|
global inventorydata
|
2017-01-10 21:15:35 +01:00
|
|
|
inventorydata = Inventory().numberOfInventoryLookupsPerformed
|
|
|
|
Inventory().numberOfInventoryLookupsPerformed = 0
|
2014-04-29 07:10:33 +02:00
|
|
|
Timer(1, resetlookups, ()).start()
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
2019-12-27 15:12:57 +01:00
|
|
|
def drawtab(stdscr):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Method for drawing different tabs"""
|
2019-12-27 15:12:57 +01:00
|
|
|
# pylint: disable=too-many-branches, too-many-statements
|
2019-09-23 11:42:40 +02:00
|
|
|
if menutab in range(1, len(menu) + 1):
|
|
|
|
if menutab == 1: # Inbox
|
2014-04-29 07:10:33 +02:00
|
|
|
stdscr.addstr(3, 5, "To", curses.A_BOLD)
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(3, 40, "From", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 80, "Subject", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 120, "Time Received", curses.A_BOLD)
|
|
|
|
stdscr.hline(4, 5, '-', 121)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(inbox[max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):]):
|
|
|
|
if 6 + i < curses.LINES:
|
2014-04-29 07:10:33 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == inboxcur - max(min(len(inbox) - curses.LINES + 6, inboxcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-29 07:10:33 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
if item[7] is False: # If not read, highlight
|
2014-04-29 07:10:33 +02:00
|
|
|
a = a | curses.A_BOLD
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(5 + i, 5, item[1][:34], a)
|
|
|
|
stdscr.addstr(5 + i, 40, item[3][:39], a)
|
|
|
|
stdscr.addstr(5 + i, 80, item[5][:39], a)
|
|
|
|
stdscr.addstr(5 + i, 120, item[6][:39], a)
|
|
|
|
elif menutab == 3: # Sent
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(3, 5, "To", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 40, "From", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 80, "Subject", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 120, "Status", curses.A_BOLD)
|
|
|
|
stdscr.hline(4, 5, '-', 121)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(sentbox[max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):]):
|
|
|
|
if 6 + i < curses.LINES:
|
2014-04-30 04:45:41 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == sentcur - max(min(len(sentbox) - curses.LINES + 6, sentcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(5 + i, 5, item[0][:34], a)
|
|
|
|
stdscr.addstr(5 + i, 40, item[2][:39], a)
|
|
|
|
stdscr.addstr(5 + i, 80, item[4][:39], a)
|
|
|
|
stdscr.addstr(5 + i, 120, item[5][:39], a)
|
|
|
|
elif menutab == 2 or menutab == 4: # Send or Identities
|
2014-04-19 20:45:37 +02:00
|
|
|
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(3, 40, "Address", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 80, "Stream", curses.A_BOLD)
|
|
|
|
stdscr.hline(4, 5, '-', 81)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(addresses[max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):]):
|
|
|
|
if 6 + i < curses.LINES:
|
2014-04-30 04:45:41 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == addrcur - max(min(len(addresses) - curses.LINES + 6, addrcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
if item[1] and item[3] not in [8, 9]: # Embolden enabled, non-special addresses
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_BOLD
|
2019-09-23 11:42:40 +02:00
|
|
|
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, 80, str(1)[:39], a)
|
|
|
|
elif menutab == 5: # Subscriptions
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 80, "Address", curses.A_BOLD)
|
|
|
|
stdscr.addstr(3, 120, "Enabled", curses.A_BOLD)
|
|
|
|
stdscr.hline(4, 5, '-', 121)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(subscriptions[max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):]):
|
|
|
|
if 6 + i < curses.LINES:
|
2014-04-30 04:45:41 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == subcur - max(min(len(subscriptions) - curses.LINES + 6, subcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
if item[2]: # Embolden enabled subscriptions
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_BOLD
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(5 + i, 5, item[0][:74], a)
|
|
|
|
stdscr.addstr(5 + i, 80, item[1][:39], a)
|
|
|
|
stdscr.addstr(5 + i, 120, str(item[2]), a)
|
|
|
|
elif menutab == 6: # Address book
|
2014-04-29 07:10:33 +02:00
|
|
|
stdscr.addstr(3, 5, "Label", curses.A_BOLD)
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(3, 40, "Address", curses.A_BOLD)
|
|
|
|
stdscr.hline(4, 5, '-', 41)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(addrbook[max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):]):
|
|
|
|
if 6 + i < curses.LINES:
|
2014-04-30 04:45:41 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == abookcur - max(min(len(addrbook) - curses.LINES + 6, abookcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(5 + i, 5, item[0][:34], a)
|
|
|
|
stdscr.addstr(5 + i, 40, item[1][:39], a)
|
|
|
|
elif menutab == 7: # Blacklist
|
|
|
|
stdscr.addstr(3, 5, "Type: " + bwtype)
|
2014-04-30 04:45:41 +02:00
|
|
|
stdscr.addstr(4, 5, "Label", curses.A_BOLD)
|
|
|
|
stdscr.addstr(4, 80, "Address", curses.A_BOLD)
|
|
|
|
stdscr.addstr(4, 120, "Enabled", curses.A_BOLD)
|
|
|
|
stdscr.hline(5, 5, '-', 121)
|
2019-09-23 11:42:40 +02:00
|
|
|
for i, item in enumerate(blacklist[max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):]):
|
|
|
|
if 7 + i < curses.LINES:
|
2014-04-30 04:45:41 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if i == blackcur - max(min(len(blacklist) - curses.LINES + 6, blackcur - 5), 0):
|
|
|
|
# Highlight current address
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_REVERSE
|
2019-09-23 11:42:40 +02:00
|
|
|
if item[2]: # Embolden enabled subscriptions
|
2014-04-30 04:45:41 +02:00
|
|
|
a = a | curses.A_BOLD
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(6 + i, 5, item[0][:74], a)
|
|
|
|
stdscr.addstr(6 + i, 80, item[1][:39], a)
|
|
|
|
stdscr.addstr(6 + i, 120, str(item[2]), a)
|
|
|
|
elif menutab == 8: # Network status
|
2014-04-19 20:45:37 +02:00
|
|
|
# Connection data
|
2018-11-01 15:28:42 +01:00
|
|
|
connected_hosts = network.stats.connectedHostsList()
|
|
|
|
stdscr.addstr(
|
|
|
|
4, 5, "Total Connections: " +
|
|
|
|
str(len(connected_hosts)).ljust(2)
|
|
|
|
)
|
2014-04-19 20:45:37 +02:00
|
|
|
stdscr.addstr(6, 6, "Stream #", curses.A_BOLD)
|
2014-04-19 20:57:08 +02:00
|
|
|
stdscr.addstr(6, 18, "Connections", curses.A_BOLD)
|
|
|
|
stdscr.hline(7, 6, '-', 23)
|
2014-04-19 20:45:37 +02:00
|
|
|
streamcount = []
|
2018-11-01 15:28:42 +01:00
|
|
|
for host, stream in connected_hosts:
|
2014-04-19 20:45:37 +02:00
|
|
|
if stream >= len(streamcount):
|
|
|
|
streamcount.append(1)
|
|
|
|
else:
|
|
|
|
streamcount[stream] += 1
|
|
|
|
for i, item in enumerate(streamcount):
|
2014-04-19 20:57:08 +02:00
|
|
|
if i < 4:
|
2014-04-19 20:45:37 +02:00
|
|
|
if i == 0:
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(8 + i, 6, "?")
|
2014-04-19 20:45:37 +02:00
|
|
|
else:
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(8 + i, 6, str(i))
|
|
|
|
stdscr.addstr(8 + i, 18, str(item).ljust(2))
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
# Uptime and processing data
|
2019-09-23 11:42:40 +02:00
|
|
|
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(8, 40, "Processed " + str(
|
|
|
|
shared.numberOfBroadcastsProcessed).ljust(4) + " broadcast messages.")
|
|
|
|
stdscr.addstr(9, 40, "Processed " + str(
|
|
|
|
shared.numberOfPubkeysProcessed).ljust(4) + " public keys.")
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
# Inventory data
|
2019-09-23 11:42:40 +02:00
|
|
|
stdscr.addstr(11, 35, "Inventory lookups per second: " + str(inventorydata).ljust(3))
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
# Log
|
|
|
|
stdscr.addstr(13, 6, "Log", curses.A_BOLD)
|
|
|
|
n = log.count('\n')
|
|
|
|
if n > 0:
|
2019-12-27 15:12:57 +01:00
|
|
|
lg = log.split('\n')
|
2014-04-19 20:45:37 +02:00
|
|
|
if n > 512:
|
2019-12-27 15:12:57 +01:00
|
|
|
del lg[:(n - 256)]
|
2014-04-19 20:45:37 +02:00
|
|
|
logpad.erase()
|
2019-12-27 15:12:57 +01:00
|
|
|
n = len(lg)
|
|
|
|
for i, item in enumerate(lg):
|
2014-04-19 20:45:37 +02:00
|
|
|
a = 0
|
2019-09-23 11:42:40 +02:00
|
|
|
if item and item[0] == '!':
|
2014-04-19 20:45:37 +02:00
|
|
|
a = curses.color_pair(1)
|
|
|
|
item = item[1:]
|
|
|
|
logpad.addstr(i, 0, item, a)
|
2019-09-23 11:42:40 +02:00
|
|
|
logpad.refresh(n - curses.LINES + 2, 0, 14, 6, curses.LINES - 2, curses.COLS - 7)
|
2014-04-18 07:48:42 +02:00
|
|
|
stdscr.refresh()
|
|
|
|
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-18 07:48:42 +02:00
|
|
|
def redraw(stdscr):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Redraw menu"""
|
2014-04-18 07:48:42 +02:00
|
|
|
stdscr.erase()
|
|
|
|
stdscr.border()
|
|
|
|
drawmenu(stdscr)
|
|
|
|
stdscr.refresh()
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
2014-04-19 20:45:37 +02:00
|
|
|
def dialogreset(stdscr):
|
2019-09-23 11:42:40 +02:00
|
|
|
"""Resetting dialogue"""
|
2014-04-19 20:45:37 +02:00
|
|
|
stdscr.clear()
|
|
|
|
stdscr.keypad(1)
|
|
|
|
curses.curs_set(0)
|
2019-09-23 11:42:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
# pylint: disable=too-many-branches, too-many-statements
|
2014-04-18 07:48:42 +02:00
|
|
|
def handlech(c, stdscr):
|
2019-12-27 15:12:57 +01:00
|
|
|
"""Handle character given on the command-line interface"""
|
|
|
|
# pylint: disable=redefined-outer-name, too-many-nested-blocks, too-many-locals
|
2014-04-18 07:48:42 +02:00
|
|
|
if c != curses.ERR:
|
2014-05-01 02:03:12 +02:00
|
|
|
global inboxcur, addrcur, sentcur, subcur, abookcur, blackcur
|
2019-09-23 11:42:40 +02:00
|
|
|
if c in range(256):
|
2014-04-18 07:48:42 +02:00
|
|
|
if chr(c) in '12345678':
|
2014-04-29 07:10:33 +02:00
|
|
|
global menutab
|
2014-04-18 07:48:42 +02:00
|
|
|
menutab = int(chr(c))
|
|
|
|
elif chr(c) == 'q':
|
2019-12-27 15:12:57 +01:00
|
|
|
global quit_
|
|
|
|
quit_ = True
|
2014-04-19 20:45:37 +02:00
|
|
|
elif chr(c) == '\n':
|
2014-04-30 04:45:41 +02:00
|
|
|
curses.curs_set(1)
|
|
|
|
d = Dialog(dialog="dialog")
|
2014-04-29 07:10:33 +02:00
|
|
|
if menutab == 1:
|
2016-06-30 12:28:17 +02:00
|
|
|
set_background_title(d, "Inbox Message Dialog Box")
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.menu(
|
|
|
|
"Do what with \"" + inbox[inboxcur][5] + "\" from \"" + inbox[inboxcur][3] + "\"?",
|
|
|
|
choices=[
|
|
|
|
("1", "View message"),
|
2014-04-29 07:10:33 +02:00
|
|
|
("2", "Mark message as unread"),
|
|
|
|
("3", "Reply"),
|
|
|
|
("4", "Add sender to Address Book"),
|
|
|
|
("5", "Save message as text file"),
|
|
|
|
("6", "Move to trash")])
|
|
|
|
if r == d.DIALOG_OK:
|
2019-09-23 11:42:40 +02:00
|
|
|
if t == "1": # View
|
|
|
|
set_background_title(
|
|
|
|
d,
|
|
|
|
"\"" +
|
|
|
|
inbox[inboxcur][5] +
|
|
|
|
"\" from \"" +
|
|
|
|
inbox[inboxcur][3] +
|
|
|
|
"\" to \"" +
|
|
|
|
inbox[inboxcur][1] +
|
|
|
|
"\"")
|
|
|
|
data = "" # pyint: disable=redefined-outer-name
|
2014-04-29 07:10:33 +02:00
|
|
|
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0])
|
|
|
|
if ret != []:
|
|
|
|
for row in ret:
|
2014-05-01 02:03:12 +02:00
|
|
|
data, = row
|
|
|
|
data = shared.fixPotentiallyInvalidUTF8Data(data)
|
|
|
|
msg = ""
|
|
|
|
for i, item in enumerate(data.split("\n")):
|
2019-09-23 11:42:40 +02:00
|
|
|
msg += fill(item, replace_whitespace=False) + "\n"
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode(ascii(msg)), 30, 80)
|
2014-04-29 07:10:33 +02:00
|
|
|
sqlExecute("UPDATE inbox SET read=1 WHERE msgid=?", inbox[inboxcur][0])
|
|
|
|
inbox[inboxcur][7] = 1
|
|
|
|
else:
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode("Could not fetch message."))
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "2": # Mark unread
|
2014-04-29 07:10:33 +02:00
|
|
|
sqlExecute("UPDATE inbox SET read=0 WHERE msgid=?", inbox[inboxcur][0])
|
|
|
|
inbox[inboxcur][7] = 0
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "3": # Reply
|
2014-04-29 07:10:33 +02:00
|
|
|
curses.curs_set(1)
|
|
|
|
m = inbox[inboxcur]
|
|
|
|
fromaddr = m[4]
|
|
|
|
ischan = False
|
|
|
|
for i, item in enumerate(addresses):
|
|
|
|
if fromaddr == item[2] and item[3] != 0:
|
|
|
|
ischan = True
|
|
|
|
break
|
2019-12-27 15:12:57 +01:00
|
|
|
if not addresses[i][1]: # pylint: disable=undefined-loop-variable
|
2019-09-23 11:42:40 +02:00
|
|
|
scrollbox(d, unicode(
|
|
|
|
"Sending address disabled, please either enable it"
|
|
|
|
"or choose a different address."))
|
2014-04-29 07:10:33 +02:00
|
|
|
return
|
|
|
|
toaddr = m[2]
|
|
|
|
if ischan:
|
|
|
|
toaddr = fromaddr
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-29 07:10:33 +02:00
|
|
|
subject = m[5]
|
|
|
|
if not m[5][:4] == "Re: ":
|
2019-09-23 11:42:40 +02:00
|
|
|
subject = "Re: " + m[5]
|
2014-04-29 07:10:33 +02:00
|
|
|
body = ""
|
|
|
|
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", m[0])
|
|
|
|
if ret != []:
|
|
|
|
body = "\n\n------------------------------------------------------\n"
|
|
|
|
for row in ret:
|
|
|
|
body, = row
|
2019-09-23 11:42:40 +02:00
|
|
|
|
2014-04-30 04:45:41 +02:00
|
|
|
sendMessage(fromaddr, toaddr, ischan, subject, body, True)
|
2014-04-29 07:10:33 +02:00
|
|
|
dialogreset(stdscr)
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "4": # Add to Address Book
|
2014-04-29 07:10:33 +02:00
|
|
|
addr = inbox[inboxcur][4]
|
2019-09-23 11:42:40 +02:00
|
|
|
if addr not in [item[1] for i, item in enumerate(addrbook)]:
|
|
|
|
r, t = d.inputbox("Label for address \"" + addr + "\"")
|
2014-04-29 07:10:33 +02:00
|
|
|
if r == d.DIALOG_OK:
|
2014-05-01 02:03:12 +02:00
|
|
|
label = t
|
|
|
|
sqlExecute("INSERT INTO addressbook VALUES (?,?)", label, addr)
|
|
|
|
# Prepend entry
|
|
|
|
addrbook.reverse()
|
|
|
|
addrbook.append([label, addr])
|
|
|
|
addrbook.reverse()
|
2014-04-29 07:10:33 +02:00
|
|
|
else:
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode("The selected address is already in the Address Book."))
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "5": # Save message
|
2019-09-23 11:42:40 +02:00
|
|
|
set_background_title(d, "Save \"" + inbox[inboxcur][5] + "\" as text file")
|
|
|
|
r, t = d.inputbox("Filename", init=inbox[inboxcur][5] + ".txt")
|
2014-04-29 07:10:33 +02:00
|
|
|
if r == d.DIALOG_OK:
|
|
|
|
msg = ""
|
|
|
|
ret = sqlQuery("SELECT message FROM inbox WHERE msgid=?", inbox[inboxcur][0])
|
|
|
|
if ret != []:
|
|
|
|
for row in ret:
|
|
|
|
msg, = row
|
2019-12-27 15:12:57 +01:00
|
|
|
fh = open(t, "a") # Open in append mode just in case
|
2014-04-29 07:10:33 +02:00
|
|
|
fh.write(msg)
|
|
|
|
fh.close()
|
|
|
|
else:
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode("Could not fetch message."))
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "6": # Move to trash
|
2014-04-29 07:10:33 +02:00
|
|
|
sqlExecute("UPDATE inbox SET folder='trash' WHERE msgid=?", inbox[inboxcur][0])
|
|
|
|
del inbox[inboxcur]
|
2019-09-23 11:42:40 +02:00
|
|
|
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."))
|
2014-04-29 07:10:33 +02:00
|
|
|
elif menutab == 2:
|
2014-05-01 02:29:04 +02:00
|
|
|
a = ""
|
2019-12-27 15:12:57 +01:00
|
|
|
if addresses[addrcur][3] != 0: # if current address is a chan
|
2014-05-01 02:29:04 +02:00
|
|
|
a = addresses[addrcur][2]
|
|
|
|
sendMessage(addresses[addrcur][2], a)
|
2014-04-30 04:45:41 +02:00
|
|
|
elif menutab == 3:
|
2016-06-30 12:28:17 +02:00
|
|
|
set_background_title(d, "Sent Messages Dialog Box")
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.menu(
|
|
|
|
"Do what with \"" + sentbox[sentcur][4] + "\" to \"" + sentbox[sentcur][0] + "\"?",
|
|
|
|
choices=[
|
|
|
|
("1", "View message"),
|
2014-04-30 04:45:41 +02:00
|
|
|
("2", "Move to trash")])
|
|
|
|
if r == d.DIALOG_OK:
|
2019-09-23 11:42:40 +02:00
|
|
|
if t == "1": # View
|
|
|
|
set_background_title(
|
|
|
|
d,
|
|
|
|
"\"" +
|
|
|
|
sentbox[sentcur][4] +
|
|
|
|
"\" from \"" +
|
|
|
|
sentbox[sentcur][3] +
|
|
|
|
"\" to \"" +
|
|
|
|
sentbox[sentcur][1] +
|
|
|
|
"\"")
|
2014-05-01 02:03:12 +02:00
|
|
|
data = ""
|
2019-09-23 11:42:40 +02:00
|
|
|
ret = sqlQuery(
|
|
|
|
"SELECT message FROM sent WHERE subject=? AND ackdata=?",
|
|
|
|
sentbox[sentcur][4],
|
|
|
|
sentbox[sentcur][6])
|
2014-04-30 04:45:41 +02:00
|
|
|
if ret != []:
|
|
|
|
for row in ret:
|
2014-05-01 02:03:12 +02:00
|
|
|
data, = row
|
|
|
|
data = shared.fixPotentiallyInvalidUTF8Data(data)
|
|
|
|
msg = ""
|
|
|
|
for i, item in enumerate(data.split("\n")):
|
2019-09-23 11:42:40 +02:00
|
|
|
msg += fill(item, replace_whitespace=False) + "\n"
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode(ascii(msg)), 30, 80)
|
2014-04-30 04:45:41 +02:00
|
|
|
else:
|
2016-06-30 12:28:17 +02:00
|
|
|
scrollbox(d, unicode("Could not fetch message."))
|
2019-12-27 15:12:57 +01:00
|
|
|
elif t == "2": # Move to trash
|
2019-09-23 11:42:40 +02:00
|
|
|
sqlExecute(
|
|
|
|
"UPDATE sent SET folder='trash' WHERE subject=? AND ackdata=?",
|
|
|
|
sentbox[sentcur][4],
|
|
|
|
sentbox[sentcur][6])
|
2014-04-30 04:45:41 +02:00
|
|
|
del sentbox[sentcur]
|
2019-09-23 11:42:40 +02:00
|
|
|
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."))
|
2014-04-29 07:10:33 +02:00
|
|
|
elif menutab == 4:
|
2016-06-30 12:28:17 +02:00
|
|
|
set_background_title(d, "Your Identities Dialog Box")
|
|
|
|
if len(addresses) <= addrcur:
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.menu(
|
|
|
|
"Do what with addresses?",
|
|
|
|
choices=[
|
|
|
|
("1", "Create new address")])
|
2016-06-30 12:28:17 +02:00
|
|
|
else:
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.menu(
|
|
|
|
"Do what with \"" + addresses[addrcur][0] + "\" : \"" + addresses[addrcur][2] + "\"?",
|
|
|
|
choices=[
|
|
|
|
("1", "Create new address"),
|
2016-06-30 12:28:17 +02:00
|
|
|
("2", "Send a message from this address"),
|
|
|
|
("3", "Rename"),
|
|
|
|
("4", "Enable"),
|
|
|
|
("5", "Disable"),
|
|
|
|
("6", "Delete"),
|
|
|
|
("7", "Special address behavior")])
|
2014-04-19 20:45:37 +02:00
|
|
|
if r == d.DIALOG_OK:
|
2019-12-27 15:12:57 +01:00
|
|
|
if t == "1": # Create new address
|
2016-06-30 12:28:17 +02:00
|
|
|
set_background_title(d, "Create new address")
|
2019-09-23 11:42:40 +02:00
|
|
|
scrollbox(
|
|
|
|
d, unicode(
|
|
|
|
"Here you may generate as many addresses as you like.\n"
|
|
|
|
"Indeed, creating and abandoning addresses is encouraged.\n"
|
|
|
|
"Deterministic addresses have several pros and cons:\n"
|
|
|
|
"\nPros:\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"
|
|
|
|
"Cons:\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"
|
|
|
|
" * If you choose a weak passphrase someone may be able to brute-force it"
|
|
|
|
" \n and then send and receive messages as you"))
|
|
|
|
r, t = d.menu(
|
|
|
|
"Choose an address generation technique",
|
|
|
|
choices=[
|
|
|
|
("1", "Use a random number generator"),
|
2014-04-19 20:45:37 +02:00
|
|
|
("2", "Use a passphrase")])
|
|
|
|
if r == d.DIALOG_OK:
|
|
|
|
if t == "1":
|
2016-06-30 12:28:17 +02:00
|
|
|
set_background_title(d, "Randomly generate address")
|
2014-04-19 20:45:37 +02:00
|
|
|
r, t = d.inputbox("Label (not shown to anyone except you)")
|
|
|
|
label = ""
|
2019-09-23 11:42:40 +02:00
|
|
|
if r == d.DIALOG_OK and t:
|
2014-04-19 20:45:37 +02:00
|
|
|
label = t
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.menu(
|
|
|
|
"Choose a stream",
|
|
|
|
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)")])
|
2014-04-19 20:45:37 +02:00
|
|
|
if r == d.DIALOG_OK:
|
|
|
|
if t == "1":
|
|
|
|
stream = 1
|
|
|
|
elif t == "2":
|
|
|
|
addrs = []
|
|
|
|
for i, item in enumerate(addresses):
|
|
|
|
addrs.append([str(i), item[2]])
|
|
|
|
r, t = d.menu("Choose an existing address's stream", choices=addrs)
|
|
|
|
if r == d.DIALOG_OK:
|
|
|
|
stream = decodeAddress(addrs[int(t)][1])[2]
|
|
|
|
shorten = False
|
2019-09-23 11:42:40 +02:00
|
|
|
r, t = d.checklist(
|
|
|
|
"Miscellaneous options",
|
|
|
|
choices=[(
|
|
|
|
"1",
|
|
|
|
"Spend time shortening the address",
|
|
|
|
1 if shorten else 0)])
|
2014-04-19 20:45:37 +02:00
|
|
|
if r == d.DIALOG_OK and "1" in t:
|
|
|
|
shorten = True
|
2019-09-23 11:42:40 +02:00
|
|
|
queues.addressGeneratorQueue.put((
|
|
|
|
"createRandomAddress",
|
|
|
|
4,
|
|
|
|
stream,
|
|
|
|
label,
|
|
|
|