Global imports.

This commit is contained in:
Dmitri Bogomolov 2020-07-10 18:53:35 +03:00
parent 16a11775e8
commit 525aa099f3
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13
82 changed files with 1404 additions and 1323 deletions

View File

@ -72,28 +72,24 @@ from binascii import hexlify, unhexlify
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from struct import pack from struct import pack
import defaults from . import (
import helper_inbox defaults, helper_inbox, helper_sent, proofofwork, queues, shared, shutdown,
import helper_sent state
import network.stats )
import proofofwork from .addresses import (
import queues
import shared
import shutdown
import state
from addresses import (
addBMIfNotPresent, addBMIfNotPresent,
calculateInventoryHash, calculateInventoryHash,
decodeAddress, decodeAddress,
decodeVarint, decodeVarint,
varintDecodeError varintDecodeError
) )
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from debug import logger from .debug import logger
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 import stats
from version import softwareVersion from .network.threads import StoppableThread
from .version import softwareVersion
try: # TODO: write tests for XML vulnerabilities try: # TODO: write tests for XML vulnerabilities
from defusedxml.xmlrpc import monkey_patch from defusedxml.xmlrpc import monkey_patch
@ -1392,7 +1388,7 @@ class BMRPCDispatcher(object):
or "connectedAndReceivingIncomingConnections". or "connectedAndReceivingIncomingConnections".
""" """
connections_num = len(network.stats.connectedHostsList()) connections_num = len(stats.connectedHostsList())
if connections_num == 0: if connections_num == 0:
networkStatus = 'notConnected' networkStatus = 'notConnected'
elif state.clientHasReceivedIncomingConnections: elif state.clientHasReceivedIncomingConnections:
@ -1404,7 +1400,7 @@ class BMRPCDispatcher(object):
'numberOfMessagesProcessed': state.numberOfMessagesProcessed, 'numberOfMessagesProcessed': state.numberOfMessagesProcessed,
'numberOfBroadcastsProcessed': state.numberOfBroadcastsProcessed, 'numberOfBroadcastsProcessed': state.numberOfBroadcastsProcessed,
'numberOfPubkeysProcessed': state.numberOfPubkeysProcessed, 'numberOfPubkeysProcessed': state.numberOfPubkeysProcessed,
'pendingDownload': network.stats.pendingDownload(), 'pendingDownload': stats.pendingDownload(),
'networkStatus': networkStatus, 'networkStatus': networkStatus,
'softwareName': 'PyBitmessage', 'softwareName': 'PyBitmessage',
'softwareVersion': softwareVersion 'softwareVersion': softwareVersion

View File

@ -12,13 +12,7 @@ The PyBitmessage startup script
import os import os
import sys import sys
try: from . import depends
import pathmagic
except ImportError:
from pybitmessage import pathmagic
app_dir = pathmagic.setup()
import depends
depends.check_dependencies() depends.check_dependencies()
import ctypes import ctypes
@ -32,28 +26,28 @@ import time
import traceback import traceback
from struct import pack from struct import pack
import defaults from . import defaults, shared, shutdown, state
import shared from .bmconfigparser import BMConfigParser
import shutdown from .debug import logger # this should go before any threads
import state from .helper_startup import (
from bmconfigparser import BMConfigParser
from debug import logger # this should go before any threads
from helper_startup import (
adjustHalfOpenConnectionsLimit, start_proxyconfig) adjustHalfOpenConnectionsLimit, start_proxyconfig)
from inventory import Inventory from .inventory import Inventory
# Network objects and threads # Network objects and threads
from network import ( from .network import (
BMConnectionPool, Dandelion, AddrThread, AnnounceThread, BMNetworkThread, BMConnectionPool, Dandelion, AddrThread, AnnounceThread, BMNetworkThread,
InvThread, ReceiveQueueThread, DownloadThread, UploadThread InvThread, ReceiveQueueThread, DownloadThread, UploadThread
) )
from network.knownnodes import readKnownNodes from .network.knownnodes import readKnownNodes
from singleinstance import singleinstance from .singleinstance import singleinstance
# Synchronous threads # Synchronous threads
from threads import ( from .threads import (
set_thread_name, printLock, set_thread_name, printLock,
addressGenerator, objectProcessor, singleCleaner, singleWorker, sqlThread) addressGenerator, objectProcessor, singleCleaner, singleWorker, sqlThread)
app_dir = os.path.dirname(os.path.abspath(__file__))
def _fixSocket(): def _fixSocket():
if sys.platform.startswith('linux'): if sys.platform.startswith('linux'):
socket.SO_BINDTODEVICE = 25 socket.SO_BINDTODEVICE = 25
@ -272,14 +266,14 @@ class Main(object):
# SMTP delivery thread # SMTP delivery thread
if daemon and config.safeGet( if daemon and config.safeGet(
'bitmessagesettings', 'smtpdeliver', '') != '': 'bitmessagesettings', 'smtpdeliver', '') != '':
from class_smtpDeliver import smtpDeliver from .class_smtpDeliver import smtpDeliver
smtpDeliveryThread = smtpDeliver() smtpDeliveryThread = smtpDeliver()
smtpDeliveryThread.start() smtpDeliveryThread.start()
# SMTP daemon thread # SMTP daemon thread
if daemon and config.safeGetBoolean( if daemon and config.safeGetBoolean(
'bitmessagesettings', 'smtpd'): 'bitmessagesettings', 'smtpd'):
from class_smtpServer import smtpServer from .class_smtpServer import smtpServer
smtpServerThread = smtpServer() smtpServerThread = smtpServer()
smtpServerThread.start() smtpServerThread.start()
@ -304,7 +298,7 @@ class Main(object):
# 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 from . 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
@ -339,7 +333,7 @@ class Main(object):
state.uploadThread.start() state.uploadThread.start()
if config.safeGetBoolean('bitmessagesettings', 'upnp'): if config.safeGetBoolean('bitmessagesettings', 'upnp'):
import upnp from . import upnp
upnpThread = upnp.uPnPThread() upnpThread = upnp.uPnPThread()
upnpThread.start() upnpThread.start()
else: else:
@ -351,10 +345,10 @@ class Main(object):
if not depends.check_curses(): if not depends.check_curses():
sys.exit() sys.exit()
print('Running with curses') print('Running with curses')
import bitmessagecurses from . import bitmessagecurses
bitmessagecurses.runwrapper() bitmessagecurses.runwrapper()
else: else:
import bitmessageqt from . import bitmessageqt
bitmessageqt.run() bitmessageqt.run()
else: else:
config.remove_option('bitmessagesettings', 'dontconnect') config.remove_option('bitmessagesettings', 'dontconnect')
@ -370,8 +364,7 @@ class Main(object):
elif not state.enableGUI: elif not state.enableGUI:
state.enableGUI = True state.enableGUI = True
try: try:
# pylint: disable=relative-import from .tests import core as test_core
from tests import core as test_core
except ImportError: except ImportError:
self.stop() self.stop()
return return

View File

@ -4,6 +4,7 @@ PyQt based UI for bitmessage, the main module
import hashlib import hashlib
import locale import locale
import logging
import os import os
import random import random
import string import string
@ -18,53 +19,50 @@ from sqlite3 import register_adapter
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.QtNetwork import QLocalSocket, QLocalServer from PyQt4.QtNetwork import QLocalSocket, QLocalServer
import shared from pybitmessage import (
import state helper_addressbook, helper_search, helper_sent, l10n, namecoin, paths,
from debug import logger queues, shared, shutdown, state)
from tr import _translate from pybitmessage.addresses import decodeAddress, addBMIfNotPresent
from addresses import decodeAddress, addBMIfNotPresent from pybitmessage.bmconfigparser import BMConfigParser
from bitmessageui import Ui_MainWindow from pybitmessage.debug import logger
from bmconfigparser import BMConfigParser from pybitmessage.helper_ackPayload import genAckPayload
import namecoin from pybitmessage.helper_sql import (
from messageview import MessageView sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure)
from migrationwizard import Ui_MigrationWizard from pybitmessage.network.stats import pendingDownload, pendingUpload
from foldertree import ( from pybitmessage.proofofwork import getPowType
from pybitmessage.tr import _translate
# This is needed for tray icon
import .bitmessage_icons_rc # noqa:F401 pylint: disable=unused-import
from . import dialogs, settingsmixin, sound, support
from .account import (
accountClass, AccountColor, BMAccount, GatewayAccount,
getSortedAccounts, getSortedSubscriptions, MailchuckAccount)
from .bitmessageui import Ui_MainWindow
from .foldertree import (
AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget, AccountMixin, Ui_FolderWidget, Ui_AddressWidget, Ui_SubscriptionWidget,
MessageList_AddressWidget, MessageList_SubjectWidget, MessageList_AddressWidget, MessageList_SubjectWidget,
Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress, Ui_AddressBookWidgetItemLabel, Ui_AddressBookWidgetItemAddress,
MessageList_TimeWidget) MessageList_TimeWidget)
import settingsmixin from .messageview import MessageView
import support from .statusbar import BMStatusBar
from helper_sql import sqlQuery, sqlExecute, sqlExecuteChunked, sqlStoredProcedure from .uisignaler import UISignaler
import helper_addressbook from .utils import str_broadcast_subscribers, avatarize
import helper_search
import l10n
from utils import str_broadcast_subscribers, avatarize
from account import (
getSortedAccounts, getSortedSubscriptions, accountClass, BMAccount,
GatewayAccount, MailchuckAccount, AccountColor)
import dialogs
from network.stats import pendingDownload, pendingUpload
from uisignaler import UISignaler
import paths
from proofofwork import getPowType
import queues
import shutdown
from statusbar import BMStatusBar
import sound
# This is needed for tray icon
import bitmessage_icons_rc # noqa:F401 pylint: disable=unused-import
import helper_sent
try: try:
from plugins.plugin import get_plugin, get_plugins from pybitmessage.plugins.plugin import get_plugin, get_plugins
except ImportError: except ImportError:
get_plugins = False get_plugins = False
logger = logging.getLogger('default')
# TODO: rewrite # TODO: rewrite
def powQueueSize(): def powQueueSize():
"""Returns the size of queues.workerQueue including current unfinished work""" """
Returns the size of queues.workerQueue including current unfinished work
"""
queue_len = queues.workerQueue.qsize() queue_len = queues.workerQueue.qsize()
for thread in threading.enumerate(): for thread in threading.enumerate():
try: try:
@ -435,7 +433,6 @@ class MyForm(settingsmixin.SMainWindow):
if treeWidget.isSortingEnabled(): if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False) treeWidget.setSortingEnabled(False)
widgets = {}
i = 0 i = 0
while i < treeWidget.topLevelItemCount(): while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i) widget = treeWidget.topLevelItem(i)
@ -453,7 +450,8 @@ class MyForm(settingsmixin.SMainWindow):
while j < widget.childCount(): while j < widget.childCount():
subwidget = widget.child(j) subwidget = widget.child(j)
try: try:
subwidget.setUnreadCount(db[toAddress][subwidget.folderName]['count']) subwidget.setUnreadCount(
db[toAddress][subwidget.folderName]['count'])
unread += db[toAddress][subwidget.folderName]['count'] unread += db[toAddress][subwidget.folderName]['count']
db[toAddress].pop(subwidget.folderName, None) db[toAddress].pop(subwidget.folderName, None)
except: except:
@ -467,7 +465,8 @@ class MyForm(settingsmixin.SMainWindow):
j = 0 j = 0
for f, c in db[toAddress].iteritems(): for f, c in db[toAddress].iteritems():
try: try:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c['count']) subwidget = Ui_FolderWidget(
widget, j, toAddress, f, c['count'])
except KeyError: except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0) subwidget = Ui_FolderWidget(widget, j, toAddress, f, 0)
j += 1 j += 1
@ -477,12 +476,18 @@ class MyForm(settingsmixin.SMainWindow):
i = 0 i = 0
for toAddress in db: for toAddress in db:
widget = Ui_SubscriptionWidget(treeWidget, i, toAddress, db[toAddress]["inbox"]['count'], db[toAddress]["inbox"]['label'], db[toAddress]["inbox"]['enabled']) widget = Ui_SubscriptionWidget(
treeWidget, i, toAddress,
db[toAddress]["inbox"]['count'],
db[toAddress]["inbox"]['label'],
db[toAddress]["inbox"]['enabled'])
j = 0 j = 0
unread = 0 unread = 0
for folder in folders: for folder in folders:
try: try:
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]['count']) subwidget = Ui_FolderWidget(
widget, j, toAddress, folder,
db[toAddress][folder]['count'])
unread += db[toAddress][folder]['count'] unread += db[toAddress][folder]['count']
except KeyError: except KeyError:
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0) subwidget = Ui_FolderWidget(widget, j, toAddress, folder, 0)
@ -518,8 +523,8 @@ class MyForm(settingsmixin.SMainWindow):
toAddress, 'enabled') toAddress, 'enabled')
isChan = BMConfigParser().safeGetBoolean( isChan = BMConfigParser().safeGetBoolean(
toAddress, 'chan') toAddress, 'chan')
isMaillinglist = BMConfigParser().safeGetBoolean( # isMaillinglist = BMConfigParser().safeGetBoolean(
toAddress, 'mailinglist') # toAddress, 'mailinglist')
if treeWidget == self.ui.treeWidgetYourIdentities: if treeWidget == self.ui.treeWidgetYourIdentities:
if isChan: if isChan:
@ -536,7 +541,9 @@ class MyForm(settingsmixin.SMainWindow):
# get number of (unread) messages # get number of (unread) messages
total = 0 total = 0
queryreturn = sqlQuery('SELECT toaddress, folder, count(msgid) as cnt FROM inbox WHERE read = 0 GROUP BY toaddress, folder') queryreturn = sqlQuery(
'SELECT toaddress, folder, count(msgid) as cnt FROM inbox'
' WHERE read = 0 GROUP BY toaddress, folder')
for row in queryreturn: for row in queryreturn:
toaddress, folder, cnt = row toaddress, folder, cnt = row
total += cnt total += cnt
@ -553,7 +560,6 @@ class MyForm(settingsmixin.SMainWindow):
if treeWidget.isSortingEnabled(): if treeWidget.isSortingEnabled():
treeWidget.setSortingEnabled(False) treeWidget.setSortingEnabled(False)
widgets = {}
i = 0 i = 0
while i < treeWidget.topLevelItemCount(): while i < treeWidget.topLevelItemCount():
widget = treeWidget.topLevelItem(i) widget = treeWidget.topLevelItem(i)
@ -586,7 +592,7 @@ class MyForm(settingsmixin.SMainWindow):
if len(db[toAddress]) > 0: if len(db[toAddress]) > 0:
j = 0 j = 0
for f, c in db[toAddress].iteritems(): for f, c in db[toAddress].iteritems():
if toAddress is not None and tab == 'messages' and folder == "new": if toAddress and tab == 'messages' and folder == "new":
continue continue
subwidget = Ui_FolderWidget(widget, j, toAddress, f, c) subwidget = Ui_FolderWidget(widget, j, toAddress, f, c)
if subwidget.folderName not in ("new", "trash", "sent"): if subwidget.folderName not in ("new", "trash", "sent"):
@ -598,13 +604,16 @@ class MyForm(settingsmixin.SMainWindow):
i = 0 i = 0
for toAddress in db: for toAddress in db:
widget = Ui_AddressWidget(treeWidget, i, toAddress, db[toAddress]["inbox"], enabled[toAddress]) widget = Ui_AddressWidget(
treeWidget, i, toAddress,
db[toAddress]["inbox"], enabled[toAddress])
j = 0 j = 0
unread = 0 unread = 0
for folder in folders: for folder in folders:
if toAddress is not None and tab == 'messages' and folder == "new": if toAddress and tab == 'messages' and folder == "new":
continue continue
subwidget = Ui_FolderWidget(widget, j, toAddress, folder, db[toAddress][folder]) subwidget = Ui_FolderWidget(
widget, j, toAddress, folder, db[toAddress][folder])
if subwidget.folderName not in ("new", "trash", "sent"): if subwidget.folderName not in ("new", "trash", "sent"):
unread += db[toAddress][folder] unread += db[toAddress][folder]
j += 1 j += 1
@ -632,10 +641,13 @@ class MyForm(settingsmixin.SMainWindow):
addressInKeysFile) addressInKeysFile)
if addressVersionNumber == 1: if addressVersionNumber == 1:
displayMsg = _translate( displayMsg = _translate(
"MainWindow", "One of your addresses, %1, is an old version 1 address. Version 1 addresses are no longer supported. " "MainWindow",
+ "May we delete it now?").arg(addressInKeysFile) "One of your addresses, %1, is an old version 1 address."
" Version 1 addresses are no longer supported."
" May we delete it now?").arg(addressInKeysFile)
reply = QtGui.QMessageBox.question( reply = QtGui.QMessageBox.question(
self, 'Message', displayMsg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) self, 'Message', displayMsg,
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
BMConfigParser().remove_section(addressInKeysFile) BMConfigParser().remove_section(addressInKeysFile)
BMConfigParser().save() BMConfigParser().save()
@ -743,12 +755,13 @@ class MyForm(settingsmixin.SMainWindow):
self.unreadCount = 0 self.unreadCount = 0
# Set the icon sizes for the identicons # Set the icon sizes for the identicons
identicon_size = 3*7 identicon_size = 3 * 7
self.ui.tableWidgetInbox.setIconSize(QtCore.QSize(identicon_size, identicon_size)) for widget in (
self.ui.treeWidgetChans.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.tableWidgetInbox, self.ui.treeWidgetChans,
self.ui.treeWidgetYourIdentities.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.treeWidgetYourIdentities, self.ui.treeWidgetSubscriptions,
self.ui.treeWidgetSubscriptions.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.ui.tableWidgetAddressBook
self.ui.tableWidgetAddressBook.setIconSize(QtCore.QSize(identicon_size, identicon_size)) ):
widget.setIconSize(QtCore.QSize(identicon_size, identicon_size))
self.UISignalThread = UISignaler.get() self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
@ -809,11 +822,12 @@ class MyForm(settingsmixin.SMainWindow):
# Put the TTL slider in the correct spot # Put the TTL slider in the correct spot
TTL = BMConfigParser().getint('bitmessagesettings', 'ttl') TTL = BMConfigParser().getint('bitmessagesettings', 'ttl')
if TTL < 3600: # an hour if TTL < 3600: # an hour
TTL = 3600 TTL = 3600
elif TTL > 28*24*60*60: # 28 days elif TTL > 28 * 24 * 60 * 60: # 28 days
TTL = 28*24*60*60 TTL = 28 * 24 * 60 * 60
self.ui.horizontalSliderTTL.setSliderPosition((TTL - 3600) ** (1/3.199)) self.ui.horizontalSliderTTL.setSliderPosition(
(TTL - 3600) ** (1 / 3.199))
self.updateHumanFriendlyTTLDescription(TTL) self.updateHumanFriendlyTTLDescription(TTL)
QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL( QtCore.QObject.connect(self.ui.horizontalSliderTTL, QtCore.SIGNAL(
@ -873,21 +887,24 @@ class MyForm(settingsmixin.SMainWindow):
BMConfigParser().save() BMConfigParser().save()
def updateHumanFriendlyTTLDescription(self, TTL): def updateHumanFriendlyTTLDescription(self, TTL):
numberOfHours = int(round(TTL / (60*60))) numberOfHours = int(round(TTL / (60 * 60)))
font = QtGui.QFont() font = QtGui.QFont()
stylesheet = "" stylesheet = ""
if numberOfHours < 48: if numberOfHours < 48:
self.ui.labelHumanFriendlyTTLDescription.setText( self.ui.labelHumanFriendlyTTLDescription.setText(
_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfHours) + _translate(
", " + "MainWindow", "%n hour(s)", None, numberOfHours
_translate("MainWindow", "not recommended for chans", None, QtCore.QCoreApplication.CodecForTr) ) + ", "
) + _translate(
"MainWindow", "not recommended for chans")
)
stylesheet = "QLabel { color : red; }" stylesheet = "QLabel { color : red; }"
font.setBold(True) font.setBold(True)
else: else:
numberOfDays = int(round(TTL / (24*60*60))) numberOfDays = int(round(TTL / (24 * 60 * 60)))
self.ui.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n day(s)", None, QtCore.QCoreApplication.CodecForTr, numberOfDays)) self.ui.labelHumanFriendlyTTLDescription.setText(_translate(
"MainWindow", "%n day(s)", None, numberOfDays))
font.setBold(False) font.setBold(False)
self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet) self.ui.labelHumanFriendlyTTLDescription.setStyleSheet(stylesheet)
self.ui.labelHumanFriendlyTTLDescription.setFont(font) self.ui.labelHumanFriendlyTTLDescription.setFont(font)
@ -900,7 +917,8 @@ class MyForm(settingsmixin.SMainWindow):
else: else:
self.show() self.show()
self.setWindowState( self.setWindowState(
self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) self.windowState()
& ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
self.raise_() self.raise_()
self.activateWindow() self.activateWindow()
@ -1449,6 +1467,7 @@ class MyForm(settingsmixin.SMainWindow):
self._player = QtGui.QSound.play self._player = QtGui.QSound.play
if not get_plugins: if not get_plugins:
self._theme_player = None
return return
_plugin = get_plugin('notification.message') _plugin = get_plugin('notification.message')
@ -1557,36 +1576,77 @@ class MyForm(settingsmixin.SMainWindow):
# may manage your keys by editing the keys.dat file stored in # may manage your keys by editing the keys.dat file stored in
# the same directory as this program. It is important that you # the same directory as this program. It is important that you
# back up this file.', QMessageBox.Ok) # back up this file.', QMessageBox.Ok)
reply = QtGui.QMessageBox.information(self, 'keys.dat?', _translate( reply = QtGui.QMessageBox.information(
"MainWindow", "You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file."), QtGui.QMessageBox.Ok) self, 'keys.dat?', _translate(
"MainWindow",
"You may manage your keys by editing the keys.dat"
" file stored in the same directory as this program."
" It is important that you back up this file."
), QtGui.QMessageBox.Ok)
else: else:
QtGui.QMessageBox.information(self, 'keys.dat?', _translate( QtGui.QMessageBox.information(
"MainWindow", "You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important that you back up this file.").arg(state.appdata), QtGui.QMessageBox.Ok) self, 'keys.dat?', _translate(
elif sys.platform == 'win32' or sys.platform == 'win64': "MainWindow",
"You may manage your keys by editing the keys.dat"
" file stored in\n %1 \nIt is important that"
" you back up this file.").arg(state.appdata),
QtGui.QMessageBox.Ok)
elif sys.platform.startswith('win'):
if state.appdata == '': if state.appdata == '':
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate( reply = QtGui.QMessageBox.question(
"MainWindow", "You may manage your keys by editing the keys.dat file stored in the same directory as this program. It is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) self, _translate("MainWindow", "Open keys.dat?"),
_translate(
"MainWindow",
"You may manage your keys by editing the keys.dat"
" file stored in the same directory as this program."
" It is important that you back up this file."
" Would you like to open the file now?"
" (Be sure to close Bitmessage before making"
" any changes.)"), QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)
else: else:
reply = QtGui.QMessageBox.question(self, _translate("MainWindow", "Open keys.dat?"), _translate( reply = QtGui.QMessageBox.question(
"MainWindow", "You may manage your keys by editing the keys.dat file stored in\n %1 \nIt is important that you back up this file. Would you like to open the file now? (Be sure to close Bitmessage before making any changes.)").arg(state.appdata), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) self, _translate("MainWindow", "Open keys.dat?"),
_translate(
"MainWindow",
"You may manage your keys by editing the keys.dat"
" file stored in\n %1 \nIt is important that"
" you back up this file. Would you like to open"
" the file now? (Be sure to close Bitmessage before"
" making any changes.)").arg(state.appdata),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
openKeysFile() openKeysFile()
# menu button 'delete all treshed messages' # menu button 'delete all treshed messages'
def click_actionDeleteAllTrashedMessages(self): def click_actionDeleteAllTrashedMessages(self):
if QtGui.QMessageBox.question(self, _translate("MainWindow", "Delete trash?"), _translate("MainWindow", "Are you sure you want to delete all trashed messages?"), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No) == QtGui.QMessageBox.No: if QtGui.QMessageBox.question(
self, _translate("MainWindow", "Delete trash?"),
_translate(
"MainWindow",
"Are you sure you want to delete all trashed messages?"
), QtGui.QMessageBox.Yes, QtGui.QMessageBox.No
) == QtGui.QMessageBox.No:
return return
sqlStoredProcedure('deleteandvacuume') sqlStoredProcedure('deleteandvacuume')
self.rerenderTabTreeMessages() self.rerenderTabTreeMessages()
self.rerenderTabTreeSubscriptions() self.rerenderTabTreeSubscriptions()
self.rerenderTabTreeChans() self.rerenderTabTreeChans()
if self.getCurrentFolder(self.ui.treeWidgetYourIdentities) == "trash": if self.getCurrentFolder(self.ui.treeWidgetYourIdentities) == "trash":
self.loadMessagelist(self.ui.tableWidgetInbox, self.getCurrentAccount(self.ui.treeWidgetYourIdentities), "trash") self.loadMessagelist(
self.ui.tableWidgetInbox,
self.getCurrentAccount(self.ui.treeWidgetYourIdentities),
"trash")
elif self.getCurrentFolder(self.ui.treeWidgetSubscriptions) == "trash": elif self.getCurrentFolder(self.ui.treeWidgetSubscriptions) == "trash":
self.loadMessagelist(self.ui.tableWidgetInboxSubscriptions, self.getCurrentAccount(self.ui.treeWidgetSubscriptions), "trash") self.loadMessagelist(
self.ui.tableWidgetInboxSubscriptions,
self.getCurrentAccount(self.ui.treeWidgetSubscriptions),
"trash")
elif self.getCurrentFolder(self.ui.treeWidgetChans) == "trash": elif self.getCurrentFolder(self.ui.treeWidgetChans) == "trash":
self.loadMessagelist(self.ui.tableWidgetInboxChans, self.getCurrentAccount(self.ui.treeWidgetChans), "trash") self.loadMessagelist(
self.ui.tableWidgetInboxChans,
self.getCurrentAccount(self.ui.treeWidgetChans), "trash")
# menu button 'regenerate deterministic addresses' # menu button 'regenerate deterministic addresses'
def click_actionRegenerateDeterministicAddresses(self): def click_actionRegenerateDeterministicAddresses(self):
@ -1653,13 +1713,6 @@ class MyForm(settingsmixin.SMainWindow):
else: else:
self._firstrun = False self._firstrun = False
def showMigrationWizard(self, level):
self.migrationWizardInstance = Ui_MigrationWizard(["a"])
if self.migrationWizardInstance.exec_():
pass
else:
pass
def changeEvent(self, event): def changeEvent(self, event):
if event.type() == QtCore.QEvent.LanguageChange: if event.type() == QtCore.QEvent.LanguageChange:
self.ui.retranslateUi(self) self.ui.retranslateUi(self)
@ -1672,7 +1725,9 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.blackwhitelist.init_blacklist_popup_menu(False) self.ui.blackwhitelist.init_blacklist_popup_menu(False)
if event.type() == QtCore.QEvent.WindowStateChange: if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized: if self.windowState() & QtCore.Qt.WindowMinimized:
if BMConfigParser().getboolean('bitmessagesettings', 'minimizetotray') and not 'darwin' in sys.platform: if BMConfigParser().getboolean(
'bitmessagesettings', 'minimizetotray'
) and 'darwin' not in sys.platform:
QtCore.QTimer.singleShot(0, self.appIndicatorHide) QtCore.QTimer.singleShot(0, self.appIndicatorHide)
elif event.oldState() & QtCore.Qt.WindowMinimized: elif event.oldState() & QtCore.Qt.WindowMinimized:
# The window state has just been changed to # The window state has just been changed to
@ -1788,7 +1843,8 @@ class MyForm(settingsmixin.SMainWindow):
painter.setPen( painter.setPen(
QtGui.QPen(QtGui.QColor(255, 0, 0), QtCore.Qt.SolidPattern)) QtGui.QPen(QtGui.QColor(255, 0, 0), QtCore.Qt.SolidPattern))
painter.setFont(font) painter.setFont(font)
painter.drawText(24-rect.right()-marginX, -rect.top()+marginY, txt) painter.drawText(
24 - rect.right() - marginX, - rect.top() + marginY, txt)
painter.end() painter.end()
return QtGui.QIcon(pixmap) return QtGui.QIcon(pixmap)
@ -1804,7 +1860,8 @@ class MyForm(settingsmixin.SMainWindow):
def findInboxUnreadCount(self, count=None): def findInboxUnreadCount(self, count=None):
if count is None: if count is None:
queryreturn = sqlQuery('''SELECT count(*) from inbox WHERE folder='inbox' and read=0''') queryreturn = sqlQuery(
"SELECT count(*) from inbox WHERE folder='inbox' and read=0")
cnt = 0 cnt = 0
for row in queryreturn: for row in queryreturn:
cnt, = row cnt, = row
@ -1834,7 +1891,11 @@ class MyForm(settingsmixin.SMainWindow):
sent.item(i, 3).setToolTip(textToDisplay) sent.item(i, 3).setToolTip(textToDisplay)
try: try:
newlinePosition = textToDisplay.indexOf('\n') newlinePosition = textToDisplay.indexOf('\n')
except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. # If someone misses adding a "_translate" to a string
# before passing it to this function, this function
# won't receive a qstring which will cause an exception.
# ? why textToDisplay isn't unicode
except AttributeError:
newlinePosition = 0 newlinePosition = 0
if newlinePosition > 1: if newlinePosition > 1:
sent.item(i, 3).setText( sent.item(i, 3).setText(
@ -1862,7 +1923,11 @@ class MyForm(settingsmixin.SMainWindow):
sent.item(i, 3).setToolTip(textToDisplay) sent.item(i, 3).setToolTip(textToDisplay)
try: try:
newlinePosition = textToDisplay.indexOf('\n') newlinePosition = textToDisplay.indexOf('\n')
except: # If someone misses adding a "_translate" to a string before passing it to this function, this function won't receive a qstring which will cause an exception. # If someone misses adding a "_translate" to a string
# before passing it to this function, this function
# won't receive a qstring which will cause an exception.
# ? why textToDisplay isn't unicode
except AttributeError:
newlinePosition = 0 newlinePosition = 0
if newlinePosition > 1: if newlinePosition > 1:
sent.item(i, 3).setText( sent.item(i, 3).setText(
@ -1898,8 +1963,7 @@ class MyForm(settingsmixin.SMainWindow):
"MainWindow", "MainWindow",
"New version of PyBitmessage is available: %1. Download it" "New version of PyBitmessage is available: %1. Download it"
" from https://github.com/Bitmessage/PyBitmessage/releases/latest" " from https://github.com/Bitmessage/PyBitmessage/releases/latest"
).arg(self.notifiedNewVersion) ).arg(self.notifiedNewVersion))
)
def displayAlert(self, title, text, exitAfterUserClicksOk): def displayAlert(self, title, text, exitAfterUserClicksOk):
self.updateStatusBar(text) self.updateStatusBar(text)
@ -1908,17 +1972,25 @@ class MyForm(settingsmixin.SMainWindow):
os._exit(0) os._exit(0)
def rerenderMessagelistFromLabels(self): def rerenderMessagelistFromLabels(self):
for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions
):
for i in range(messagelist.rowCount()): for i in range(messagelist.rowCount()):
messagelist.item(i, 1).setLabel() messagelist.item(i, 1).setLabel()
def rerenderMessagelistToLabels(self): def rerenderMessagelistToLabels(self):
for messagelist in (self.ui.tableWidgetInbox, self.ui.tableWidgetInboxChans, self.ui.tableWidgetInboxSubscriptions): for messagelist in (
self.ui.tableWidgetInbox,
self.ui.tableWidgetInboxChans,
self.ui.tableWidgetInboxSubscriptions
):
for i in range(messagelist.rowCount()): for i in range(messagelist.rowCount()):
messagelist.item(i, 0).setLabel() messagelist.item(i, 0).setLabel()
def rerenderAddressBook(self): def rerenderAddressBook(self):
def addRow (address, label, type): def addRow(address, label, type):
self.ui.tableWidgetAddressBook.insertRow(0) self.ui.tableWidgetAddressBook.insertRow(0)
newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type) newItem = Ui_AddressBookWidgetItemLabel(address, unicode(label, 'utf-8'), type)
self.ui.tableWidgetAddressBook.setItem(0, 0, newItem) self.ui.tableWidgetAddressBook.setItem(0, 0, newItem)
@ -1931,26 +2003,27 @@ class MyForm(settingsmixin.SMainWindow):
oldRows[item.address] = [item.label, item.type, i] oldRows[item.address] = [item.label, item.type, i]
if self.ui.tableWidgetAddressBook.rowCount() == 0: if self.ui.tableWidgetAddressBook.rowCount() == 0:
self.ui.tableWidgetAddressBook.horizontalHeader().setSortIndicator(0, QtCore.Qt.AscendingOrder) self.ui.tableWidgetAddressBook.horizontalHeader().setSortIndicator(
0, QtCore.Qt.AscendingOrder)
if self.ui.tableWidgetAddressBook.isSortingEnabled(): if self.ui.tableWidgetAddressBook.isSortingEnabled():
self.ui.tableWidgetAddressBook.setSortingEnabled(False) self.ui.tableWidgetAddressBook.setSortingEnabled(False)
newRows = {} newRows = {}
# subscriptions # subscriptions
queryreturn = sqlQuery('SELECT label, address FROM subscriptions WHERE enabled = 1') for label, address in sqlQuery(
for row in queryreturn: 'SELECT label, address FROM subscriptions WHERE enabled = 1'):
label, address = row
newRows[address] = [label, AccountMixin.SUBSCRIPTION] newRows[address] = [label, AccountMixin.SUBSCRIPTION]
# chans # chans
addresses = getSortedAccounts() addresses = getSortedAccounts()
for address in addresses: for address in addresses:
account = accountClass(address) account = accountClass(address)
if (account.type == AccountMixin.CHAN and BMConfigParser().safeGetBoolean(address, 'enabled')): if (
account.type == AccountMixin.CHAN
and BMConfigParser().safeGetBoolean(address, 'enabled')
):
newRows[address] = [account.getLabel(), AccountMixin.CHAN] newRows[address] = [account.getLabel(), AccountMixin.CHAN]
# normal accounts # normal accounts
queryreturn = sqlQuery('SELECT * FROM addressbook') for label, address in sqlQuery('SELECT label, address FROM addressbook'):
for row in queryreturn:
label, address = row
newRows[address] = [label, AccountMixin.NORMAL] newRows[address] = [label, AccountMixin.NORMAL]
completerList = [] completerList = []
@ -1976,11 +2049,17 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderTabTreeSubscriptions() self.rerenderTabTreeSubscriptions()
def click_pushButtonTTL(self): def click_pushButtonTTL(self):
QtGui.QMessageBox.information(self, 'Time To Live', _translate( QtGui.QMessageBox.information(
"MainWindow", """The TTL, or Time-To-Live is the length of time that the network will hold the message. self, 'Time To Live', _translate(
The recipient must get it during this time. If your Bitmessage client does not hear an acknowledgement, it "MainWindow",
will resend the message automatically. The longer the Time-To-Live, the "The TTL, or Time-To-Live is the length of time that"
more work your computer must do to send the message. A Time-To-Live of four or five days is often appropriate."""), QtGui.QMessageBox.Ok) " the network will hold the message. The recipient must"
" get it during this time. If your Bitmessage client does"
" not hear an acknowledgement, it will resend the message"
" automatically. The longer the Time-To-Live, the more"
" work your computer must do to send the message. A"
" Time-To-Live of four or five days is often appropriate."
), QtWidgets.QMessageBox.Ok)
def click_pushButtonClear(self): def click_pushButtonClear(self):
self.ui.lineEditSubject.setText("") self.ui.lineEditSubject.setText("")
@ -1989,7 +2068,9 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.comboBoxSendFrom.setCurrentIndex(0) self.ui.comboBoxSendFrom.setCurrentIndex(0)
def click_pushButtonSend(self): def click_pushButtonSend(self):
encoding = 3 if QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier else 2 encoding = (
3 if QtGui.QApplication.queryKeyboardModifiers()
& QtCore.Qt.ShiftModifier else 2)
self.statusbar.clearMessage() self.statusbar.clearMessage()
@ -2013,14 +2094,13 @@ class MyForm(settingsmixin.SMainWindow):
subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8()) subject = str(self.ui.lineEditSubjectBroadcast.text().toUtf8())
message = str( message = str(
self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8()) self.ui.textEditMessageBroadcast.document().toPlainText().toUtf8())
"""
The whole network message must fit in 2^18 bytes. # The whole network message must fit in 2^18 bytes.
Let's assume 500 bytes of overhead. If someone wants to get that # Let's assume 500 bytes of overhead. If someone wants to get that
too an exact number you are welcome to but I think that it would # too an exact number you are welcome to but I think that it would
be a better use of time to support message continuation so that # be a better use of time to support message continuation so that
users can send messages of any length. # users can send messages of any length.
""" if len(message) > 2 ** 18 - 500:
if len(message) > (2 ** 18 - 500):
QtGui.QMessageBox.about( QtGui.QMessageBox.about(
self, _translate("MainWindow", "Message too long"), self, _translate("MainWindow", "Message too long"),
_translate( _translate(
@ -2053,18 +2133,32 @@ class MyForm(settingsmixin.SMainWindow):
subject = acct.subject subject = acct.subject
toAddress = acct.toAddress toAddress = acct.toAddress
else: else:
if QtGui.QMessageBox.question(self, "Sending an email?", _translate("MainWindow", if QtGui.QMessageBox.question(
"You are trying to send an email instead of a bitmessage. This requires registering with a gateway. Attempt to register?"), self, "Sending an email?",
QtGui.QMessageBox.Yes|QtGui.QMessageBox.No) != QtGui.QMessageBox.Yes: _translate(
"MainWindow",
"You are trying to send an email"
" instead of a bitmessage. This"
" requires registering with a"
" gateway. Attempt to register?"
), QtWidgets.QMessageBox.Yes
| QtWidgets.QMessageBox.No
) != QtWidgets.QMessageBox.Yes:
continue continue
email = acct.getLabel() email = acct.getLabel()
if email[-14:] != "@mailchuck.com": #attempt register # attempt register
if email[-14:] != "@mailchuck.com":
# 12 character random email address # 12 character random email address
email = ''.join(random.SystemRandom().choice(string.ascii_lowercase) for _ in range(12)) + "@mailchuck.com" email = u''.join(
random.SystemRandom().choice(
string.ascii_lowercase
) for _ in range(12)
) + "@mailchuck.com"
acct = MailchuckAccount(fromAddress) acct = MailchuckAccount(fromAddress)
acct.register(email) acct.register(email)
BMConfigParser().set(fromAddress, 'label', email) BMConfigParser().set(fromAddress, 'label', email)
BMConfigParser().set(fromAddress, 'gateway', 'mailchuck') BMConfigParser().set(
fromAddress, 'gateway', 'mailchuck')
BMConfigParser().save() BMConfigParser().save()
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2072,35 +2166,38 @@ class MyForm(settingsmixin.SMainWindow):
" an email gateway. Sending registration" " an email gateway. Sending registration"
" now as %1, please wait for the registration" " now as %1, please wait for the registration"
" to be processed before retrying sending." " to be processed before retrying sending."
).arg(email) ).arg(email))
)
return return
status, addressVersionNumber, streamNumber = decodeAddress(toAddress)[:3] status, addressVersionNumber, streamNumber = \
decodeAddress(toAddress)[:3]
if status != 'success': if status != 'success':
try: try:
toAddress = unicode(toAddress, 'utf-8', 'ignore') toAddress = unicode(toAddress, 'utf-8', 'ignore')
except: except UnicodeDecodeError:
pass logger.warning(
logger.error('Error: Could not decode recipient address ' + toAddress + ':' + status) "Failed decoding toAddress ):", exc_info=True)
logger.error(
'Error: Could not decode recipient address %s: %s',
toAddress_value, status)
if status == 'missingbm': if status == 'missingbm':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Bitmessage addresses start with" "Error: Bitmessage addresses start with"
" BM- Please check the recipient address %1" " BM- Please check the recipient address %1"
).arg(toAddress)) ).arg(toAddress))
elif status == 'checksumfailed': elif status == 'checksumfailed':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: The recipient address %1 is not" "Error: The recipient address %1 is not"
" typed or copied correctly. Please check it." " typed or copied correctly. Please check it."
).arg(toAddress)) ).arg(toAddress))
elif status == 'invalidcharacters': elif status == 'invalidcharacters':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: The recipient address %1 contains" "Error: The recipient address %1 contains"
" invalid characters. Please check it." " invalid characters. Please check it."
).arg(toAddress)) ).arg(toAddress))
elif status == 'versiontoohigh': elif status == 'versiontoohigh':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2108,7 +2205,7 @@ class MyForm(settingsmixin.SMainWindow):
" %1 is too high. Either you need to upgrade" " %1 is too high. Either you need to upgrade"
" your Bitmessage software or your" " your Bitmessage software or your"
" acquaintance is being clever." " acquaintance is being clever."
).arg(toAddress)) ).arg(toAddress))
elif status == 'ripetooshort': elif status == 'ripetooshort':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2116,7 +2213,7 @@ class MyForm(settingsmixin.SMainWindow):
" address %1 is too short. There might be" " address %1 is too short. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).arg(toAddress))
elif status == 'ripetoolong': elif status == 'ripetoolong':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2124,7 +2221,7 @@ class MyForm(settingsmixin.SMainWindow):
" address %1 is too long. There might be" " address %1 is too long. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).arg(toAddress))
elif status == 'varintmalformed': elif status == 'varintmalformed':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -2132,30 +2229,46 @@ class MyForm(settingsmixin.SMainWindow):
" address %1 is malformed. There might be" " address %1 is malformed. There might be"
" something wrong with the software of" " something wrong with the software of"
" your acquaintance." " your acquaintance."
).arg(toAddress)) ).arg(toAddress))
else: else:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: Something is wrong with the" "Error: Something is wrong with the"
" recipient address %1." " recipient address %1."
).arg(toAddress)) ).arg(toAddress))
elif fromAddress == '': elif fromAddress == '':
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Error: You must specify a From address. If you" "Error: You must specify a From address. If you"
" don\'t have one, go to the" " don\'t have one, go to the"
" \'Your Identities\' tab.") " \'Your Identities\' tab."))
)
else: else:
toAddress = addBMIfNotPresent(toAddress) toAddress = addBMIfNotPresent(toAddress)
if addressVersionNumber > 4 or addressVersionNumber <= 1: if addressVersionNumber > 4 or addressVersionNumber <= 1:
QtGui.QMessageBox.about(self, _translate("MainWindow", "Address version number"), _translate( QtGui.QMessageBox.about(
"MainWindow", "Concerning the address %1, Bitmessage cannot understand address version numbers of %2. Perhaps upgrade Bitmessage to the latest version.").arg(toAddress).arg(str(addressVersionNumber))) self,
_translate(
"MainWindow", "Address version number"),
_translate(
"MainWindow",
"Concerning the address %1, Bitmessage"
" cannot understand address version"
" numbers of %2. Perhaps upgrade"
" Bitmessage to the latest version."
).arg(toAddress, addressVersionNumber))
continue continue
if streamNumber > 1 or streamNumber == 0: if streamNumber > 1 or streamNumber == 0:
QtGui.QMessageBox.about(self, _translate("MainWindow", "Stream number"), _translate( QtGui.QMessageBox.about(
"MainWindow", "Concerning the address %1, Bitmessage cannot handle stream numbers of %2. Perhaps upgrade Bitmessage to the latest version.").arg(toAddress).arg(str(streamNumber))) self,
_translate("MainWindow", "Stream number"),
_translate(
"MainWindow",
"Concerning the address %1, Bitmessage"
" cannot handle stream numbers of %2."
" Perhaps upgrade Bitmessage to the"
" latest version."
).format(toAddress, streamNumber))
continue continue
self.statusbar.clearMessage() self.statusbar.clearMessage()
if state.statusIconColor == 'red': if state.statusIconColor == 'red':
@ -2251,7 +2364,8 @@ class MyForm(settingsmixin.SMainWindow):
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Fetched address from namecoin identity.")) "MainWindow", "Fetched address from namecoin identity."))
def setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(self, address): def setBroadcastEnablementDependingOnWhetherThisIsAMailingListAddress(
self, address):
# If this is a chan then don't let people broadcast because no one # If this is a chan then don't let people broadcast because no one
# should subscribe to chan addresses. # should subscribe to chan addresses.
self.ui.tabWidgetSend.setCurrentIndex( self.ui.tabWidgetSend.setCurrentIndex(
@ -2264,15 +2378,21 @@ class MyForm(settingsmixin.SMainWindow):
def rerenderComboBoxSendFrom(self): def rerenderComboBoxSendFrom(self):
self.ui.comboBoxSendFrom.clear() self.ui.comboBoxSendFrom.clear()
for addressInKeysFile in getSortedAccounts(): for addressInKeysFile in getSortedAccounts():
# I realize that this is poor programming practice but I don't care.
# It's easier for others to read.
isEnabled = BMConfigParser().getboolean( isEnabled = BMConfigParser().getboolean(
addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read. addressInKeysFile, 'enabled')
isMaillinglist = BMConfigParser().safeGetBoolean(addressInKeysFile, 'mailinglist') isMaillinglist = BMConfigParser().safeGetBoolean(
addressInKeysFile, 'mailinglist')
if isEnabled and not isMaillinglist: if isEnabled and not isMaillinglist:
label = unicode(BMConfigParser().get(addressInKeysFile, 'label'), 'utf-8', 'ignore').strip() label = unicode(
BMConfigParser().get(addressInKeysFile, 'label'),
'utf-8', 'ignore').strip()
if label == "": if label == "":
label = addressInKeysFile label = addressInKeysFile
self.ui.comboBoxSendFrom.addItem(avatarize(addressInKeysFile), label, addressInKeysFile) self.ui.comboBoxSendFrom.addItem(
# self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder) avatarize(addressInKeysFile), label, addressInKeysFile)
# self.ui.comboBoxSendFrom.model().sort(1, Qt.AscendingOrder)
for i in range(self.ui.comboBoxSendFrom.count()): for i in range(self.ui.comboBoxSendFrom.count()):
address = str(self.ui.comboBoxSendFrom.itemData( address = str(self.ui.comboBoxSendFrom.itemData(
i, QtCore.Qt.UserRole).toString()) i, QtCore.Qt.UserRole).toString())
@ -2288,14 +2408,19 @@ class MyForm(settingsmixin.SMainWindow):
def rerenderComboBoxSendFromBroadcast(self): def rerenderComboBoxSendFromBroadcast(self):
self.ui.comboBoxSendFromBroadcast.clear() self.ui.comboBoxSendFromBroadcast.clear()
for addressInKeysFile in getSortedAccounts(): for addressInKeysFile in getSortedAccounts():
# I realize that this is poor programming practice but I don't care.
# It's easier for others to read.
isEnabled = BMConfigParser().getboolean( isEnabled = BMConfigParser().getboolean(
addressInKeysFile, 'enabled') # I realize that this is poor programming practice but I don't care. It's easier for others to read. addressInKeysFile, 'enabled')
isChan = BMConfigParser().safeGetBoolean(addressInKeysFile, 'chan') isChan = BMConfigParser().safeGetBoolean(addressInKeysFile, 'chan')
if isEnabled and not isChan: if isEnabled and not isChan:
label = unicode(BMConfigParser().get(addressInKeysFile, 'label'), 'utf-8', 'ignore').strip() label = unicode(
BMConfigParser().get(addressInKeysFile, 'label'),
'utf-8', 'ignore').strip()
if label == "": if label == "":
label = addressInKeysFile label = addressInKeysFile
self.ui.comboBoxSendFromBroadcast.addItem(avatarize(addressInKeysFile), label, addressInKeysFile) self.ui.comboBoxSendFromBroadcast.addItem(
avatarize(addressInKeysFile), label, addressInKeysFile)
for i in range(self.ui.comboBoxSendFromBroadcast.count()): for i in range(self.ui.comboBoxSendFromBroadcast.count()):
address = str(self.ui.comboBoxSendFromBroadcast.itemData( address = str(self.ui.comboBoxSendFromBroadcast.itemData(
i, QtCore.Qt.UserRole).toString()) i, QtCore.Qt.UserRole).toString())
@ -2303,7 +2428,7 @@ class MyForm(settingsmixin.SMainWindow):
i, AccountColor(address).accountColor(), i, AccountColor(address).accountColor(),
QtCore.Qt.ForegroundRole) QtCore.Qt.ForegroundRole)
self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '') self.ui.comboBoxSendFromBroadcast.insertItem(0, '', '')
if(self.ui.comboBoxSendFromBroadcast.count() == 2): if self.ui.comboBoxSendFromBroadcast.count() == 2:
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1) self.ui.comboBoxSendFromBroadcast.setCurrentIndex(1)
else: else:
self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0) self.ui.comboBoxSendFromBroadcast.setCurrentIndex(0)
@ -2454,9 +2579,10 @@ class MyForm(settingsmixin.SMainWindow):
# and such, but it must also be checked here. # and such, but it must also be checked here.
if shared.isAddressInMySubscriptionsList(address): if shared.isAddressInMySubscriptionsList(address):
return return
# Add to database (perhaps this should be separated from the MyForm class) # Add to database
# (perhaps this should be separated from the MyForm class)
sqlExecute( sqlExecute(
'''INSERT INTO subscriptions VALUES (?,?,?)''', 'INSERT INTO subscriptions VALUES (?,?,?)',
label, address, True label, address, True
) )
self.rerenderMessagelistFromLabels() self.rerenderMessagelistFromLabels()
@ -2572,11 +2698,11 @@ class MyForm(settingsmixin.SMainWindow):
msgids = [] msgids = []
for i in range(0, idCount): for i in range(0, idCount):
msgids.append(tableWidget.item(i, 3).data()) msgids.append(tableWidget.item(i, 3).data())
for col in xrange(tableWidget.columnCount()): for col in range(tableWidget.columnCount()):
tableWidget.item(i, col).setUnread(False) tableWidget.item(i, col).setUnread(False)
markread = sqlExecuteChunked( markread = sqlExecuteChunked(
"UPDATE inbox SET read = 1 WHERE msgid IN({0}) AND read=0", 'UPDATE inbox SET read = 1 WHERE msgid IN({0}) AND read=0',
idCount, *msgids idCount, *msgids
) )
@ -2626,21 +2752,20 @@ class MyForm(settingsmixin.SMainWindow):
waitForSync = False waitForSync = False
# C PoW currently doesn't support interrupting and OpenCL is untested # C PoW currently doesn't support interrupting and OpenCL is untested
if getPowType() == "python" and (powQueueSize() > 0 or pendingUpload() > 0): if getPowType() == "python" and (
powQueueSize() > 0 or pendingUpload() > 0):
reply = QtGui.QMessageBox.question( reply = QtGui.QMessageBox.question(
self, _translate("MainWindow", "Proof of work pending"), self, _translate("MainWindow", "Proof of work pending"),
_translate( _translate(
"MainWindow", "MainWindow",
"%n object(s) pending proof of work", None, "%n object(s) pending proof of work", None, powQueueSize()
QtCore.QCoreApplication.CodecForTr, powQueueSize() ) + ", "
) + ", " + + _translate(
_translate(
"MainWindow", "MainWindow",
"%n object(s) waiting to be distributed", None, "%n object(s) waiting to be distributed", None,
QtCore.QCoreApplication.CodecForTr, pendingUpload() pendingUpload()
) + "\n\n" + ) + "\n\n"
_translate( + _translate("MainWindow", "Wait until these tasks finish?"),
"MainWindow", "Wait until these tasks finish?"),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.No: if reply == QtGui.QMessageBox.No:
@ -2656,17 +2781,16 @@ class MyForm(settingsmixin.SMainWindow):
"Bitmessage hasn't synchronised with the network," "Bitmessage hasn't synchronised with the network,"
" %n object(s) to be downloaded. If you quit now," " %n object(s) to be downloaded. If you quit now,"
" it may cause delivery delays. Wait until the" " it may cause delivery delays. Wait until the"
" synchronisation finishes?", None, " synchronisation finishes?", None, pendingDownload()
QtCore.QCoreApplication.CodecForTr, pendingDownload() ), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
self.wait = waitForSync = True self.wait = waitForSync = True
elif reply == QtGui.QMessageBox.Cancel: elif reply == QtGui.QMessageBox.Cancel:
return return
if state.statusIconColor == 'red' and not BMConfigParser().safeGetBoolean( if state.statusIconColor == 'red' \
and not BMConfigParser().safeGetBoolean(
'bitmessagesettings', 'dontconnect'): 'bitmessagesettings', 'dontconnect'):
reply = QtGui.QMessageBox.question( reply = QtGui.QMessageBox.question(
self, _translate("MainWindow", "Not connected"), self, _translate("MainWindow", "Not connected"),
@ -2675,8 +2799,7 @@ class MyForm(settingsmixin.SMainWindow):
"Bitmessage isn't connected to the network. If you" "Bitmessage isn't connected to the network. If you"
" quit now, it may cause delivery delays. Wait until" " quit now, it may cause delivery delays. Wait until"
" connected and the synchronisation finishes?" " connected and the synchronisation finishes?"
), ), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
| QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel) | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
waitForConnection = True waitForConnection = True
@ -2722,8 +2845,9 @@ class MyForm(settingsmixin.SMainWindow):
if curWorkerQueue > 0: if curWorkerQueue > 0:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "Waiting for PoW to finish... %1%" "MainWindow", "Waiting for PoW to finish... %1%"
).arg(50 * (maxWorkerQueue - curWorkerQueue) / ).arg(
maxWorkerQueue)) 50 * (maxWorkerQueue - curWorkerQueue) / maxWorkerQueue)
)
time.sleep(0.5) time.sleep(0.5)
QtCore.QCoreApplication.processEvents( QtCore.QCoreApplication.processEvents(
QtCore.QEventLoop.AllEvents, 1000 QtCore.QEventLoop.AllEvents, 1000
@ -2816,21 +2940,28 @@ class MyForm(settingsmixin.SMainWindow):
if not msgid: if not msgid:
return return
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid) 'SELECT message FROM inbox WHERE msgid=?', msgid)
if queryreturn != []: try:
for row in queryreturn: lines = queryreturn[-1][0].split('\n')
messageText, = row except IndexError:
lines = ''
lines = messageText.split('\n')
totalLines = len(lines) totalLines = len(lines)
for i in xrange(totalLines): for i in range(totalLines):
if 'Message ostensibly from ' in lines[i]: if 'Message ostensibly from ' in lines[i]:
lines[i] = '<p style="font-size: 12px; color: grey;">%s</span></p>' % ( lines[i] = (
lines[i]) '<p style="font-size: 12px; color: grey;">%s</span></p>'
elif lines[i] == '------------------------------------------------------': % (lines[i])
elif (
lines[i]
== '------------------------------------------------------'
):
lines[i] = '<hr>' lines[i] = '<hr>'
elif lines[i] == '' and (i+1) < totalLines and \ elif (
lines[i+1] != '------------------------------------------------------': lines[i] == '' and (i+1) < totalLines
and lines[i+1]
!= '------------------------------------------------------'
):
lines[i] = '<br><br>' lines[i] = '<br><br>'
content = ' '.join(lines) # To keep the whitespace between lines content = ' '.join(lines) # To keep the whitespace between lines
content = shared.fixPotentiallyInvalidUTF8Data(content) content = shared.fixPotentiallyInvalidUTF8Data(content)
@ -2861,18 +2992,14 @@ class MyForm(settingsmixin.SMainWindow):
) )
self.propagateUnreadCount() self.propagateUnreadCount()
# tableWidget.selectRow(currentRow + 1)
# This doesn't de-select the last message if you try to mark it
# unread, but that doesn't interfere. Might not be necessary.
# We could also select upwards, but then our problem would be
# with the topmost message.
# tableWidget.clearSelection() manages to mark the message
# as read again.
# Format predefined text on message reply. # Format predefined text on message reply.
def quoted_text(self, message): def quoted_text(self, message):
if not BMConfigParser().safeGetBoolean('bitmessagesettings', 'replybelow'): if not BMConfigParser().safeGetBoolean(
return '\n\n------------------------------------------------------\n' + message 'bitmessagesettings', 'replybelow'):
return (
'\n\n------------------------------------------------------\n'
+ message)
quoteWrapper = textwrap.TextWrapper( quoteWrapper = textwrap.TextWrapper(
replace_whitespace=False, initial_indent='> ', replace_whitespace=False, initial_indent='> ',
@ -2938,8 +3065,8 @@ class MyForm(settingsmixin.SMainWindow):
currentInboxRow, column_from).address currentInboxRow, column_from).address
msgid = tableWidget.item(currentInboxRow, 3).data() msgid = tableWidget.item(currentInboxRow, 3).data()
queryreturn = sqlQuery( queryreturn = sqlQuery(
"SELECT message FROM inbox WHERE msgid=?", msgid 'SELECT message FROM inbox WHERE msgid=?', msgid
) or sqlQuery("SELECT message FROM sent WHERE ackdata=?", msgid) ) or sqlQuery('SELECT message FROM sent WHERE ackdata=?', msgid)
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
messageAtCurrentInboxRow, = row messageAtCurrentInboxRow, = row
@ -2957,7 +3084,7 @@ class MyForm(settingsmixin.SMainWindow):
self.ui.tabWidgetSend.setCurrentIndex( self.ui.tabWidgetSend.setCurrentIndex(
self.ui.tabWidgetSend.indexOf(self.ui.sendDirect) self.ui.tabWidgetSend.indexOf(self.ui.sendDirect)
) )
# toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow # toAddressAtCurrentInboxRow = fromAddressAtCurrentInboxRow
elif not BMConfigParser().has_section(toAddressAtCurrentInboxRow): elif not BMConfigParser().has_section(toAddressAtCurrentInboxRow):
QtGui.QMessageBox.information( QtGui.QMessageBox.information(
self, _translate("MainWindow", "Address is gone"), self, _translate("MainWindow", "Address is gone"),
@ -3053,18 +3180,19 @@ class MyForm(settingsmixin.SMainWindow):
recipientAddress = tableWidget.item( recipientAddress = tableWidget.item(
currentInboxRow, 0).data(QtCore.Qt.UserRole) currentInboxRow, 0).data(QtCore.Qt.UserRole)
# Let's make sure that it isn't already in the address book # Let's make sure that it isn't already in the address book
queryreturn = sqlQuery('''select * from blacklist where address=?''', queryreturn = sqlQuery(
addressAtCurrentInboxRow) 'SELECT * FROM blacklist WHERE address=?', addressAtCurrentInboxRow)
if queryreturn == []: if queryreturn == []:
label = "\"" + tableWidget.item(currentInboxRow, 2).subject + "\" in " + BMConfigParser().get(recipientAddress, "label") label = "\"" + tableWidget.item(
sqlExecute('''INSERT INTO blacklist VALUES (?,?, ?)''', currentInboxRow, 2).subject + "\" in " + BMConfigParser().get(
label, recipientAddress, "label")
addressAtCurrentInboxRow, True) sqlExecute(
'INSERT INTO blacklist VALUES (?,?, ?)',
label, addressAtCurrentInboxRow, True)
self.ui.blackwhitelist.rerenderBlackWhiteList() self.ui.blackwhitelist.rerenderBlackWhiteList()
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
"Entry added to the blacklist. Edit the label to your liking.") "Entry added to the blacklist. Edit the label to your liking."))
)
else: else:
self.updateStatusBar(_translate( self.updateStatusBar(_translate(
"MainWindow", "MainWindow",
@ -3169,14 +3297,17 @@ class MyForm(settingsmixin.SMainWindow):
# Retrieve the message data out of the SQL database # Retrieve the message data out of the SQL database
msgid = tableWidget.item(currentInboxRow, 3).data() msgid = tableWidget.item(currentInboxRow, 3).data()
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select message from inbox where msgid=?''', msgid) 'SELECT message FROM inbox WHERE msgid=?', msgid)
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
message, = row message, = row
defaultFilename = "".join(x for x in subjectAtCurrentInboxRow if x.isalnum()) + '.txt' defaultFilename = "".join(
filename = QtGui.QFileDialog.getSaveFileName(self, _translate("MainWindow","Save As..."), defaultFilename, "Text files (*.txt);;All files (*.*)") x for x in subjectAtCurrentInboxRow if x.isalnum()) + '.txt'
if filename == '': filename = QtGui.QFileDialog.getSaveFileName(
self, _translate("MainWindow", "Save As..."), defaultFilename,
"Text files (*.txt);;All files (*.*)")
if not filename:
return return
try: try:
f = open(filename, 'w') f = open(filename, 'w')
@ -3188,11 +3319,13 @@ class MyForm(settingsmixin.SMainWindow):
# Send item on the Sent tab to trash # Send item on the Sent tab to trash
def on_action_SentTrash(self): def on_action_SentTrash(self):
currentRow = 0
tableWidget = self.getCurrentMessagelist() tableWidget = self.getCurrentMessagelist()
if not tableWidget: if not tableWidget:
return return
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
shifted = QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier shifted = (QtGui.QApplication.queryKeyboardModifiers()
& QtCore.Qt.ShiftModifier)
while tableWidget.selectedIndexes() != []: while tableWidget.selectedIndexes() != []:
currentRow = tableWidget.selectedIndexes()[0].row() currentRow = tableWidget.selectedIndexes()[0].row()
ackdataToTrash = tableWidget.item(currentRow, 3).data() ackdataToTrash = tableWidget.item(currentRow, 3).data()
@ -3215,13 +3348,17 @@ class MyForm(settingsmixin.SMainWindow):
currentRow, 0).data(QtCore.Qt.UserRole) currentRow, 0).data(QtCore.Qt.UserRole)
toRipe = decodeAddress(addressAtCurrentRow)[3] toRipe = decodeAddress(addressAtCurrentRow)[3]
sqlExecute( sqlExecute(
'''UPDATE sent SET status='forcepow' WHERE toripe=? AND status='toodifficult' and folder='sent' ''', "UPDATE sent SET status='forcepow'"
" WHERE toripe=? AND status='toodifficult' and folder='sent'",
toRipe) toRipe)
queryreturn = sqlQuery('''select ackdata FROM sent WHERE status='forcepow' ''') queryreturn = sqlQuery(
"SELECT ackdata FROM sent WHERE status='forcepow'")
for row in queryreturn: for row in queryreturn:
ackdata, = row ackdata, = row
queues.UISignalQueue.put(('updateSentItemStatusByAckdata', ( queues.UISignalQueue.put((
ackdata, 'Overriding maximum-difficulty setting. Work queued.'))) 'updateSentItemStatusByAckdata',
(ackdata, 'Overriding maximum-difficulty setting. Work queued.')
))
queues.workerQueue.put(('sendmessage', '')) queues.workerQueue.put(('sendmessage', ''))
def on_action_SentClipboard(self): def on_action_SentClipboard(self):
@ -3663,10 +3800,8 @@ class MyForm(settingsmixin.SMainWindow):
if not os.path.exists(state.appdata + 'avatars/'): if not os.path.exists(state.appdata + 'avatars/'):
os.makedirs(state.appdata + 'avatars/') os.makedirs(state.appdata + 'avatars/')
hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest() hash = hashlib.md5(addBMIfNotPresent(addressAtCurrentRow)).hexdigest()
extensions = [
'PNG', 'GIF', 'JPG', 'JPEG', 'SVG', 'BMP', 'MNG', 'PBM',
'PGM', 'PPM', 'TIFF', 'XBM', 'XPM', 'TGA']
# http://pyqt.sourceforge.net/Docs/PyQt4/qimagereader.html#supportedImageFormats
names = { names = {
'BMP': 'Windows Bitmap', 'BMP': 'Windows Bitmap',
'GIF': 'Graphic Interchange Format', 'GIF': 'Graphic Interchange Format',
@ -3685,7 +3820,7 @@ class MyForm(settingsmixin.SMainWindow):
filters = [] filters = []
all_images_filter = [] all_images_filter = []
current_files = [] current_files = []
for ext in extensions: for ext in names:
filters += [names[ext] + ' (*.' + ext.lower() + ')'] filters += [names[ext] + ' (*.' + ext.lower() + ')']
all_images_filter += ['*.' + ext.lower()] all_images_filter += ['*.' + ext.lower()]
upper = state.appdata + 'avatars/' + hash + '.' + ext.upper() upper = state.appdata + 'avatars/' + hash + '.' + ext.upper()
@ -3799,16 +3934,22 @@ class MyForm(settingsmixin.SMainWindow):
currentItem = self.getCurrentItem() currentItem = self.getCurrentItem()
self.popMenuYourIdentities = QtGui.QMenu(self) self.popMenuYourIdentities = QtGui.QMenu(self)
if isinstance(currentItem, Ui_AddressWidget): if isinstance(currentItem, Ui_AddressWidget):
self.popMenuYourIdentities.addAction(self.actionNewYourIdentities) self.popMenuYourIdentities.addAction(
self.actionNewYourIdentities)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
self.popMenuYourIdentities.addAction(self.actionClipboardYourIdentities) self.popMenuYourIdentities.addAction(
self.actionClipboardYourIdentities)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
if currentItem.isEnabled: if currentItem.isEnabled:
self.popMenuYourIdentities.addAction(self.actionDisableYourIdentities) self.popMenuYourIdentities.addAction(
self.actionDisableYourIdentities)
else: else:
self.popMenuYourIdentities.addAction(self.actionEnableYourIdentities) self.popMenuYourIdentities.addAction(
self.popMenuYourIdentities.addAction(self.actionSetAvatarYourIdentities) self.actionEnableYourIdentities)
self.popMenuYourIdentities.addAction(self.actionSpecialAddressBehaviorYourIdentities) self.popMenuYourIdentities.addAction(
self.actionSetAvatarYourIdentities)
self.popMenuYourIdentities.addAction(
self.actionSpecialAddressBehaviorYourIdentities)
self.popMenuYourIdentities.addAction(self.actionEmailGateway) self.popMenuYourIdentities.addAction(self.actionEmailGateway)
self.popMenuYourIdentities.addSeparator() self.popMenuYourIdentities.addSeparator()
if currentItem.type != AccountMixin.ALL: if currentItem.type != AccountMixin.ALL:
@ -3912,7 +4053,8 @@ class MyForm(settingsmixin.SMainWindow):
# menu option (Force Send) if it is. # menu option (Force Send) if it is.
if currentRow >= 0: if currentRow >= 0:
ackData = self.ui.tableWidgetInbox.item(currentRow, 3).data() ackData = self.ui.tableWidgetInbox.item(currentRow, 3).data()
queryreturn = sqlQuery('''SELECT status FROM sent where ackdata=?''', ackData) queryreturn = sqlQuery(
'SELECT status FROM sent where ackdata=?', ackData)
for row in queryreturn: for row in queryreturn:
status, = row status, = row
if status == 'toodifficult': if status == 'toodifficult':
@ -3996,7 +4138,9 @@ class MyForm(settingsmixin.SMainWindow):
self.rerenderMessagelistFromLabels() self.rerenderMessagelistFromLabels()
if item.type != AccountMixin.SUBSCRIPTION: if item.type != AccountMixin.SUBSCRIPTION:
self.rerenderMessagelistToLabels() self.rerenderMessagelistToLabels()
if item.type in (AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION): if item.type in (
AccountMixin.NORMAL, AccountMixin.CHAN, AccountMixin.SUBSCRIPTION
):
self.rerenderAddressBook() self.rerenderAddressBook()
self.recurDepth -= 1 self.recurDepth -= 1
@ -4009,7 +4153,7 @@ class MyForm(settingsmixin.SMainWindow):
folder = self.getCurrentFolder() folder = self.getCurrentFolder()
if msgid: if msgid:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''SELECT message FROM %s WHERE %s=?''' % ( 'SELECT message FROM %s WHERE %s=?' % (
('sent', 'ackdata') if folder == 'sent' ('sent', 'ackdata') if folder == 'sent'
else ('inbox', 'msgid') else ('inbox', 'msgid')
), msgid ), msgid
@ -4032,7 +4176,7 @@ class MyForm(settingsmixin.SMainWindow):
self.updateUnreadStatus(tableWidget, currentRow, msgid) self.updateUnreadStatus(tableWidget, currentRow, msgid)
# propagate # propagate
if folder != 'sent' and sqlExecute( if folder != 'sent' and sqlExecute(
'''UPDATE inbox SET read=1 WHERE msgid=? AND read=0''', 'UPDATE inbox SET read=1 WHERE msgid=? AND read=0',
msgid msgid
) > 0: ) > 0:
self.propagateUnreadCount() self.propagateUnreadCount()
@ -4188,12 +4332,6 @@ def run():
if myapp._firstrun: if myapp._firstrun:
myapp.showConnectDialog() # ask the user if we may connect myapp.showConnectDialog() # ask the user if we may connect
# try:
# if BMConfigParser().get('bitmessagesettings', 'mailchuck') < 1:
# myapp.showMigrationWizard(BMConfigParser().get('bitmessagesettings', 'mailchuck'))
# except:
# myapp.showMigrationWizard(0)
# only show after wizards and connect dialogs have completed # only show after wizards and connect dialogs have completed
if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'): if not BMConfigParser().getboolean('bitmessagesettings', 'startintray'):
myapp.show() myapp.show()

View File

@ -1,10 +1,6 @@
# pylint: disable=too-many-instance-attributes,attribute-defined-outside-init # pylint: disable=too-many-instance-attributes,attribute-defined-outside-init
""" """
account.py
==========
Account related functions. Account related functions.
""" """
from __future__ import absolute_import from __future__ import absolute_import
@ -14,13 +10,12 @@ import re
import sys import sys
import time import time
from PyQt4 import QtGui from pybitmessage import queues
from pybitmessage.addresses import decodeAddress
import queues from pybitmessage.bmconfigparser import BMConfigParser
from addresses import decodeAddress from pybitmessage.helper_ackPayload import genAckPayload
from bmconfigparser import BMConfigParser from pybitmessage.helper_sql import sqlQuery, sqlExecute
from helper_ackPayload import genAckPayload from pybitmessage.tr import _translate
from helper_sql import sqlQuery, sqlExecute
from .foldertree import AccountMixin from .foldertree import AccountMixin
from .utils import str_broadcast_subscribers from .utils import str_broadcast_subscribers
@ -292,7 +287,7 @@ class MailchuckAccount(GatewayAccount):
self.toAddress = self.registrationAddress self.toAddress = self.registrationAddress
self.subject = "config" self.subject = "config"
self.message = QtGui.QApplication.translate( self.message = _translate(
"Mailchuck", "Mailchuck",
"""# You can use this to configure your email gateway account """# You can use this to configure your email gateway account
# Uncomment the setting you want to use # Uncomment the setting you want to use

View File

@ -1,22 +1,26 @@
""" """
Dialogs that work with BM address. Dialogs that work with BM address.
""" """
# pylint: disable=attribute-defined-outside-init,too-few-public-methods,relative-import # pylint: disable=too-few-public-methods
# https://github.com/PyCQA/pylint/issues/471
import hashlib import hashlib
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import queues from pybitmessage import queues
import widgets from pybitmessage.addresses import (
from account import AccountMixin, GatewayAccount, MailchuckAccount, accountClass, getSortedAccounts addBMIfNotPresent, decodeAddress, encodeVarint)
from addresses import addBMIfNotPresent, decodeAddress, encodeVarint from pybitmessage.inventory import Inventory
from inventory import Inventory from pybitmessage.tr import _translate
from tr import _translate from . import widgets
from .account import (
accountClass, AccountMixin, GatewayAccount, getSortedAccounts,
MailchuckAccount)
class AddressCheckMixin(object): class AddressCheckMixin(object):
"""Base address validation class for QT UI""" """Base address validation class for Qt UI"""
def __init__(self): def __init__(self):
self.valid = False self.valid = False
@ -28,12 +32,12 @@ class AddressCheckMixin(object):
def _onSuccess(self, addressVersion, streamNumber, ripe): def _onSuccess(self, addressVersion, streamNumber, ripe):
pass pass
def addressChanged(self, QString): def addressChanged(self, address):
""" """
Address validation callback, performs validation and gives feedback Address validation callback, performs validation and gives feedback
""" """
status, addressVersion, streamNumber, ripe = decodeAddress( status, addressVersion, streamNumber, ripe = decodeAddress(
str(QString)) str(address))
self.valid = status == 'success' self.valid = status == 'success'
if self.valid: if self.valid:
self.labelAddressCheck.setText( self.labelAddressCheck.setText(
@ -84,9 +88,10 @@ class AddressDataDialog(QtGui.QDialog, AddressCheckMixin):
def __init__(self, parent): def __init__(self, parent):
super(AddressDataDialog, self).__init__(parent) super(AddressDataDialog, self).__init__(parent)
self.parent = parent self.parent = parent
self.data = None
def accept(self): def accept(self):
"""Callback for QDIalog accepting value""" """Callback for QDialog accepting value"""
if self.valid: if self.valid:
self.data = ( self.data = (
addBMIfNotPresent(str(self.lineEditAddress.text())), addBMIfNotPresent(str(self.lineEditAddress.text())),
@ -180,6 +185,7 @@ class NewSubscriptionDialog(AddressDataDialog):
super(NewSubscriptionDialog, self).__init__(parent) super(NewSubscriptionDialog, self).__init__(parent)
widgets.load('newsubscriptiondialog.ui', self) widgets.load('newsubscriptiondialog.ui', self)
AddressCheckMixin.__init__(self) AddressCheckMixin.__init__(self)
self.recent = []
def _onSuccess(self, addressVersion, streamNumber, ripe): def _onSuccess(self, addressVersion, streamNumber, ripe):
if addressVersion <= 3: if addressVersion <= 3:
@ -256,7 +262,8 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
self.radioButtonBehaviorMailingList.click() self.radioButtonBehaviorMailingList.click()
else: else:
self.radioButtonBehaveNormalAddress.click() self.radioButtonBehaveNormalAddress.click()
mailingListName = config.safeGet(self.address, 'mailinglistname', '') mailingListName = config.safeGet(
self.address, 'mailinglistname', '')
self.lineEditMailingListName.setText( self.lineEditMailingListName.setText(
unicode(mailingListName, 'utf-8') unicode(mailingListName, 'utf-8')
) )
@ -297,6 +304,7 @@ class EmailGatewayDialog(QtGui.QDialog):
widgets.load('emailgateway.ui', self) widgets.load('emailgateway.ui', self)
self.parent = parent self.parent = parent
self.config = config self.config = config
self.data = None
if account: if account:
self.acct = account self.acct = account
self.setWindowTitle(_translate( self.setWindowTitle(_translate(

View File

@ -1,29 +1,26 @@
""" """
Address validator module. The validator for address and passphrase QLineEdits
used in `.dialogs.NewChanDialog`.
""" """
# pylint: disable=too-many-branches,too-many-arguments # pylint: disable=too-many-arguments
from PyQt4 import QtGui from PyQt4 import QtGui
from Queue import Empty from six.moves import queue
from account import getSortedAccounts from pybitmessage.addresses import addBMIfNotPresent, decodeAddress
from addresses import decodeAddress, addBMIfNotPresent from pybitmessage.queues import (
from queues import apiAddressGeneratorReturnQueue, addressGeneratorQueue addressGeneratorQueue, apiAddressGeneratorReturnQueue)
from tr import _translate from pybitmessage.tr import _translate
from utils import str_chan from .account import getSortedAccounts
from .utils import str_chan
class AddressPassPhraseValidatorMixin(object): class AddressPassPhraseValidatorMixin(object):
"""Bitmessage address or passphrase validator class for Qt UI""" """Bitmessage address or passphrase validator class for Qt UI"""
def setParams( def setParams(
self, self, passPhraseObject=None, addressObject=None,
passPhraseObject=None, feedBackObject=None, buttonBox=None, addressMandatory=True
addressObject=None,
feedBackObject=None,
buttonBox=None,
addressMandatory=True,
): ):
"""Initialisation"""
self.addressObject = addressObject self.addressObject = addressObject
self.passPhraseObject = passPhraseObject self.passPhraseObject = passPhraseObject
self.feedBackObject = feedBackObject self.feedBackObject = feedBackObject
@ -75,8 +72,9 @@ class AddressPassPhraseValidatorMixin(object):
while True: while True:
try: try:
addressGeneratorReturnValue = apiAddressGeneratorReturnQueue.get(False) addressGeneratorReturnValue = \
except Empty: apiAddressGeneratorReturnQueue.get(False)
except queue.Empty:
if gotOne: if gotOne:
break break
else: else:
@ -85,16 +83,18 @@ class AddressPassPhraseValidatorMixin(object):
gotOne = True gotOne = True
if not addressGeneratorReturnValue: if not addressGeneratorReturnValue:
self.setError(_translate("AddressValidator", "Address already present as one of your identities.")) self.setError(_translate(
"AddressValidator",
"Address already present as one of your identities."))
return (QtGui.QValidator.Intermediate, 0) return (QtGui.QValidator.Intermediate, 0)
if addressGeneratorReturnValue[0] == 'chan name does not match address': if addressGeneratorReturnValue[0] == 'chan name does not match address':
self.setError( self.setError(_translate(
_translate( "AddressValidator",
"AddressValidator", "Although the Bitmessage address you entered was valid,"
"Although the Bitmessage address you " " it doesn\'t match the chan name."))
"entered was valid, it doesn't match the chan name."))
return (QtGui.QValidator.Intermediate, 0) return (QtGui.QValidator.Intermediate, 0)
self.setOK(_translate("MainWindow", "Passphrase and address appear to be valid.")) self.setOK(_translate(
"MainWindow", "Passphrase and address appear to be valid."))
def returnValid(self): def returnValid(self):
"""Return the value of whether the validation was successful""" """Return the value of whether the validation was successful"""
@ -119,29 +119,32 @@ class AddressPassPhraseValidatorMixin(object):
# no chan name # no chan name
if passPhrase is None: if passPhrase is None:
self.setError(_translate("AddressValidator", "Chan name/passphrase needed. You didn't enter a chan name.")) self.setError(_translate(
"AddressValidator",
"Chan name/passphrase needed. You didn't enter a chan name."))
return (QtGui.QValidator.Intermediate, pos) return (QtGui.QValidator.Intermediate, pos)
if self.addressMandatory or address is not None: if self.addressMandatory or address is not None:
# check if address already exists: # check if address already exists:
if address in getSortedAccounts(): if address in getSortedAccounts():
self.setError(_translate("AddressValidator", "Address already present as one of your identities.")) self.setError(_translate(
"AddressValidator",
"Address already present as one of your identities."))
return (QtGui.QValidator.Intermediate, pos) return (QtGui.QValidator.Intermediate, pos)
# version too high # version too high
if decodeAddress(address)[0] == 'versiontoohigh': if decodeAddress(address)[0] == 'versiontoohigh':
self.setError( self.setError(_translate(
_translate( "AddressValidator",
"AddressValidator", "Address too new. Although that Bitmessage address"
"Address too new. Although that Bitmessage" " might be valid, its version number is too new for us"
" address might be valid, its version number" " to handle. Perhaps you need to upgrade Bitmessage."))
" is too new for us to handle. Perhaps you need"
" to upgrade Bitmessage."))
return (QtGui.QValidator.Intermediate, pos) return (QtGui.QValidator.Intermediate, pos)
# invalid # invalid
if decodeAddress(address)[0] != 'success': if decodeAddress(address)[0] != 'success':
self.setError(_translate("AddressValidator", "The Bitmessage address is not valid.")) self.setError(_translate(
"AddressValidator", "The Bitmessage address is not valid."))
return (QtGui.QValidator.Intermediate, pos) return (QtGui.QValidator.Intermediate, pos)
# this just disables the OK button without changing the feedback text # this just disables the OK button without changing the feedback text
@ -151,7 +154,10 @@ class AddressPassPhraseValidatorMixin(object):
# check through generator # check through generator
if address is None: if address is None:
addressGeneratorQueue.put(('createChan', 4, 1, str_chan + ' ' + str(passPhrase), passPhrase, False)) addressGeneratorQueue.put((
'createChan', 4, 1,
str_chan + ' ' + str(passPhrase), passPhrase, False
))
else: else:
addressGeneratorQueue.put( addressGeneratorQueue.put(
('joinChan', addBMIfNotPresent(address), ('joinChan', addBMIfNotPresent(address),
@ -168,13 +174,22 @@ class AddressPassPhraseValidatorMixin(object):
class AddressValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin): class AddressValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin):
"""AddressValidator class for Qt UI""" """AddressValidator class for Qt UI"""
def __init__(self, parent=None, passPhraseObject=None, feedBackObject=None, buttonBox=None, addressMandatory=True): def __init__(
self, parent=None, passPhraseObject=None, feedBackObject=None,
buttonBox=None, addressMandatory=True
):
super(AddressValidator, self).__init__(parent) super(AddressValidator, self).__init__(parent)
self.setParams(passPhraseObject, parent, feedBackObject, buttonBox, addressMandatory) self.setParams(
passPhraseObject, parent, feedBackObject, buttonBox,
addressMandatory)
class PassPhraseValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin): class PassPhraseValidator(QtGui.QValidator, AddressPassPhraseValidatorMixin):
"""PassPhraseValidator class for Qt UI""" """PassPhraseValidator class for Qt UI"""
def __init__(self, parent=None, addressObject=None, feedBackObject=None, buttonBox=None, addressMandatory=False): def __init__(
self, parent=None, addressObject=None, feedBackObject=None,
buttonBox=None, addressMandatory=False
):
super(PassPhraseValidator, self).__init__(parent) super(PassPhraseValidator, self).__init__(parent)
self.setParams(parent, addressObject, feedBackObject, buttonBox, addressMandatory) self.setParams(
parent, addressObject, feedBackObject, buttonBox, addressMandatory)

View File

@ -1,20 +1,16 @@
# -*- coding: utf-8 -*- # pylint: skip-file
# flake8: noqa
# Form implementation generated from reading ui file 'bitmessageui.ui'
#
# Created: Mon Mar 23 22:18:07 2015
# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from bmconfigparser import BMConfigParser
from foldertree import AddressBookCompleter from pybitmessage.bmconfigparser import BMConfigParser
from messageview import MessageView from pybitmessage.tr import _translate
from messagecompose import MessageCompose from . import settingsmixin, bitmessage_icons_rc
import settingsmixin from .blacklist import Blacklist
from networkstatus import NetworkStatus from .foldertree import AddressBookCompleter
from blacklist import Blacklist from .messageview import MessageView
from .messagecompose import MessageCompose
from .networkstatus import NetworkStatus
try: try:
_fromUtf8 = QtCore.QString.fromUtf8 _fromUtf8 = QtCore.QString.fromUtf8
@ -22,19 +18,6 @@ except AttributeError:
def _fromUtf8(s): def _fromUtf8(s):
return s return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None):
if n is None:
return QtGui.QApplication.translate(context, text, disambig, _encoding)
else:
return QtGui.QApplication.translate(context, text, disambig, _encoding, n)
except AttributeError:
def _translate(context, text, disambig, encoding = QtCore.QCoreApplication.CodecForTr, n = None):
if n is None:
return QtGui.QApplication.translate(context, text, disambig)
else:
return QtGui.QApplication.translate(context, text, disambig, QtCore.QCoreApplication.CodecForTr, n)
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
@ -774,8 +757,6 @@ class Ui_MainWindow(object):
self.updateNetworkSwitchMenuLabel() self.updateNetworkSwitchMenuLabel()
import bitmessage_icons_rc
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
@ -785,4 +766,3 @@ if __name__ == "__main__":
ui.setupUi(MainWindow) ui.setupUi(MainWindow)
MainWindow.show() MainWindow.show()
sys.exit(app.exec_()) sys.exit(app.exec_())

View File

@ -1,15 +1,15 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import widgets from pybitmessage.addresses import addBMIfNotPresent
from addresses import addBMIfNotPresent from pybitmessage.bmconfigparser import BMConfigParser
from bmconfigparser import BMConfigParser from pybitmessage.helper_sql import sqlExecute, sqlQuery
from dialogs import AddAddressDialog from pybitmessage.queues import UISignalQueue
from helper_sql import sqlExecute, sqlQuery from pybitmessage.tr import _translate
from queues import UISignalQueue from . import widgets
from retranslateui import RetranslateMixin from .dialogs import AddAddressDialog
from tr import _translate from .retranslateui import RetranslateMixin
from uisignaler import UISignaler from .uisignaler import UISignaler
from utils import avatarize from .utils import avatarize
class Blacklist(QtGui.QWidget, RetranslateMixin): class Blacklist(QtGui.QWidget, RetranslateMixin):
@ -22,33 +22,39 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
QtCore.QObject.connect(self.radioButtonWhitelist, QtCore.SIGNAL( QtCore.QObject.connect(self.radioButtonWhitelist, QtCore.SIGNAL(
"clicked()"), self.click_radioButtonWhitelist) "clicked()"), self.click_radioButtonWhitelist)
QtCore.QObject.connect(self.pushButtonAddBlacklist, QtCore.SIGNAL( QtCore.QObject.connect(self.pushButtonAddBlacklist, QtCore.SIGNAL(
"clicked()"), self.click_pushButtonAddBlacklist) "clicked()"), self.click_pushButtonAddBlacklist)
self.init_blacklist_popup_menu() self.init_blacklist_popup_menu()
# Initialize blacklist # Initialize blacklist
QtCore.QObject.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( QtCore.QObject.connect(self.tableWidgetBlacklist, QtCore.SIGNAL(
"itemChanged(QTableWidgetItem *)"), self.tableWidgetBlacklistItemChanged) "itemChanged(QTableWidgetItem *)"),
self.tableWidgetBlacklistItemChanged)
# Set the icon sizes for the identicons # Set the icon sizes for the identicons
identicon_size = 3*7 identicon_size = 3 * 7
self.tableWidgetBlacklist.setIconSize(QtCore.QSize(identicon_size, identicon_size)) self.tableWidgetBlacklist.setIconSize(QtCore.QSize(
identicon_size, identicon_size))
self.UISignalThread = UISignaler.get() self.UISignalThread = UISignaler.get()
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL( QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
"rerenderBlackWhiteList()"), self.rerenderBlackWhiteList) "rerenderBlackWhiteList()"), self.rerenderBlackWhiteList)
def click_radioButtonBlacklist(self): def click_radioButtonBlacklist(self):
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'white': if BMConfigParser().get(
BMConfigParser().set('bitmessagesettings', 'blackwhitelist', 'black') 'bitmessagesettings', 'blackwhitelist') == 'white':
BMConfigParser().set(
'bitmessagesettings', 'blackwhitelist', 'black')
BMConfigParser().save() BMConfigParser().save()
# self.tableWidgetBlacklist.clearContents() # self.tableWidgetBlacklist.clearContents()
self.tableWidgetBlacklist.setRowCount(0) self.tableWidgetBlacklist.setRowCount(0)
self.rerenderBlackWhiteList() self.rerenderBlackWhiteList()
def click_radioButtonWhitelist(self): def click_radioButtonWhitelist(self):
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
BMConfigParser().set('bitmessagesettings', 'blackwhitelist', 'white') 'bitmessagesettings', 'blackwhitelist') == 'black':
BMConfigParser().set(
'bitmessagesettings', 'blackwhitelist', 'white')
BMConfigParser().save() BMConfigParser().save()
# self.tableWidgetBlacklist.clearContents() # self.tableWidgetBlacklist.clearContents()
self.tableWidgetBlacklist.setRowCount(0) self.tableWidgetBlacklist.setRowCount(0)
@ -65,16 +71,18 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
# address book. The user cannot add it again or else it will # address book. The user cannot add it again or else it will
# cause problems when updating and deleting the entry. # cause problems when updating and deleting the entry.
t = (address,) t = (address,)
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
sql = '''select * from blacklist where address=?''' 'bitmessagesettings', 'blackwhitelist') == 'black':
sql = 'SELECT * FROM blacklist WHERE address=?'
else: else:
sql = '''select * from whitelist where address=?''' sql = 'SELECT * FROM whitelist WHERE address=?'
queryreturn = sqlQuery(sql,*t) queryreturn = sqlQuery(sql, *t)
if queryreturn == []: if queryreturn == []:
self.tableWidgetBlacklist.setSortingEnabled(False) self.tableWidgetBlacklist.setSortingEnabled(False)
self.tableWidgetBlacklist.insertRow(0) self.tableWidgetBlacklist.insertRow(0)
newItem = QtGui.QTableWidgetItem(unicode( newItem = QtGui.QTableWidgetItem(unicode(
self.NewBlacklistDialogInstance.lineEditLabel.text().toUtf8(), 'utf-8')) self.NewBlacklistDialogInstance.lineEditLabel.text(
).toUtf8(), 'utf-8'))
newItem.setIcon(avatarize(address)) newItem.setIcon(avatarize(address))
self.tableWidgetBlacklist.setItem(0, 0, newItem) self.tableWidgetBlacklist.setItem(0, 0, newItem)
newItem = QtGui.QTableWidgetItem(address) newItem = QtGui.QTableWidgetItem(address)
@ -82,11 +90,14 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
self.tableWidgetBlacklist.setItem(0, 1, newItem) self.tableWidgetBlacklist.setItem(0, 1, newItem)
self.tableWidgetBlacklist.setSortingEnabled(True) self.tableWidgetBlacklist.setSortingEnabled(True)
t = (str(self.NewBlacklistDialogInstance.lineEditLabel.text().toUtf8()), address, True) t = (str(
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': self.NewBlacklistDialogInstance.lineEditLabel.text(
sql = '''INSERT INTO blacklist VALUES (?,?,?)''' ).toUtf8()), address, True)
if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sql = 'INSERT INTO blacklist VALUES (?,?,?)'
else: else:
sql = '''INSERT INTO whitelist VALUES (?,?,?)''' sql = 'INSERT INTO whitelist VALUES (?,?,?)'
sqlExecute(sql, *t) sqlExecute(sql, *t)
else: else:
UISignalQueue.put(( UISignalQueue.put((
@ -110,42 +121,44 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
addressitem = self.tableWidgetBlacklist.item(item.row(), 1) addressitem = self.tableWidgetBlacklist.item(item.row(), 1)
if isinstance(addressitem, QtGui.QTableWidgetItem): if isinstance(addressitem, QtGui.QTableWidgetItem):
if self.radioButtonBlacklist.isChecked(): if self.radioButtonBlacklist.isChecked():
sqlExecute('''UPDATE blacklist SET label=? WHERE address=?''', sqlExecute(
str(item.text()), str(addressitem.text())) 'UPDATE blacklist SET label=? WHERE address=?',
str(item.text()), str(addressitem.text()))
else: else:
sqlExecute('''UPDATE whitelist SET label=? WHERE address=?''', sqlExecute(
str(item.text()), str(addressitem.text())) 'UPDATE whitelist SET label=? WHERE address=?',
str(item.text()), str(addressitem.text()))
def init_blacklist_popup_menu(self, connectSignal=True): def init_blacklist_popup_menu(self, connectSignal=True):
# Popup menu for the Blacklist page # Popup menu for the Blacklist page
self.blacklistContextMenuToolbar = QtGui.QToolBar() self.blacklistContextMenuToolbar = QtGui.QToolBar()
# Actions # Actions
self.actionBlacklistNew = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistNew = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Add new entry"), self.on_action_BlacklistNew) "MainWindow", "Add new entry"), self.on_action_BlacklistNew)
self.actionBlacklistDelete = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistDelete = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Delete"), self.on_action_BlacklistDelete) "MainWindow", "Delete"), self.on_action_BlacklistDelete)
self.actionBlacklistClipboard = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistClipboard = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Copy address to clipboard"), "MainWindow", "Copy address to clipboard"),
self.on_action_BlacklistClipboard) self.on_action_BlacklistClipboard)
self.actionBlacklistEnable = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistEnable = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Enable"), self.on_action_BlacklistEnable) "MainWindow", "Enable"), self.on_action_BlacklistEnable)
self.actionBlacklistDisable = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistDisable = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Disable"), self.on_action_BlacklistDisable) "MainWindow", "Disable"), self.on_action_BlacklistDisable)
self.actionBlacklistSetAvatar = self.blacklistContextMenuToolbar.addAction( self.actionBlacklistSetAvatar = \
_translate( self.blacklistContextMenuToolbar.addAction(_translate(
"MainWindow", "Set avatar..."), "MainWindow", "Set avatar..."),
self.on_action_BlacklistSetAvatar) self.on_action_BlacklistSetAvatar)
self.tableWidgetBlacklist.setContextMenuPolicy( self.tableWidgetBlacklist.setContextMenuPolicy(
QtCore.Qt.CustomContextMenu) QtCore.Qt.CustomContextMenu)
if connectSignal: if connectSignal:
self.connect(self.tableWidgetBlacklist, QtCore.SIGNAL( self.connect(self.tableWidgetBlacklist, QtCore.SIGNAL(
'customContextMenuRequested(const QPoint&)'), 'customContextMenuRequested(const QPoint&)'),
self.on_context_menuBlacklist) self.on_context_menuBlacklist)
self.popMenuBlacklist = QtGui.QMenu(self) self.popMenuBlacklist = QtGui.QMenu(self)
# self.popMenuBlacklist.addAction( self.actionBlacklistNew ) # self.popMenuBlacklist.addAction( self.actionBlacklistNew )
self.popMenuBlacklist.addAction(self.actionBlacklistDelete) self.popMenuBlacklist.addAction(self.actionBlacklistDelete)
@ -158,16 +171,21 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
def rerenderBlackWhiteList(self): def rerenderBlackWhiteList(self):
tabs = self.parent().parent() tabs = self.parent().parent()
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Blacklist')) 'bitmessagesettings', 'blackwhitelist') == 'black':
tabs.setTabText(
tabs.indexOf(self), _translate('blacklist', 'Blacklist'))
else: else:
tabs.setTabText(tabs.indexOf(self), _translate('blacklist', 'Whitelist')) tabs.setTabText(
tabs.indexOf(self), _translate('blacklist', 'Whitelist'))
self.tableWidgetBlacklist.setRowCount(0) self.tableWidgetBlacklist.setRowCount(0)
listType = BMConfigParser().get('bitmessagesettings', 'blackwhitelist') listType = BMConfigParser().get('bitmessagesettings', 'blackwhitelist')
if listType == 'black': if listType == 'black':
queryreturn = sqlQuery('''SELECT label, address, enabled FROM blacklist''') queryreturn = sqlQuery(
'SELECT label, address, enabled FROM blacklist')
else: else:
queryreturn = sqlQuery('''SELECT label, address, enabled FROM whitelist''') queryreturn = sqlQuery(
'SELECT label, address, enabled FROM whitelist')
self.tableWidgetBlacklist.setSortingEnabled(False) self.tableWidgetBlacklist.setSortingEnabled(False)
for row in queryreturn: for row in queryreturn:
label, address, enabled = row label, address, enabled = row
@ -195,13 +213,14 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow, 0).text().toUtf8() currentRow, 0).text().toUtf8()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sqlExecute( sqlExecute(
'''DELETE FROM blacklist WHERE label=? AND address=?''', 'DELETE FROM blacklist WHERE label=? AND address=?',
str(labelAtCurrentRow), str(addressAtCurrentRow)) str(labelAtCurrentRow), str(addressAtCurrentRow))
else: else:
sqlExecute( sqlExecute(
'''DELETE FROM whitelist WHERE label=? AND address=?''', 'DELETE FROM whitelist WHERE label=? AND address=?',
str(labelAtCurrentRow), str(addressAtCurrentRow)) str(labelAtCurrentRow), str(addressAtCurrentRow))
self.tableWidgetBlacklist.removeRow(currentRow) self.tableWidgetBlacklist.removeRow(currentRow)
@ -220,17 +239,18 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow = self.tableWidgetBlacklist.currentRow() currentRow = self.tableWidgetBlacklist.currentRow()
addressAtCurrentRow = self.tableWidgetBlacklist.item( addressAtCurrentRow = self.tableWidgetBlacklist.item(
currentRow, 1).text() currentRow, 1).text()
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 0).setTextColor(
currentRow, 0).setTextColor(QtGui.QApplication.palette().text().color()) QtGui.QApplication.palette().text().color())
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(currentRow, 1).setTextColor(
currentRow, 1).setTextColor(QtGui.QApplication.palette().text().color()) QtGui.QApplication.palette().text().color())
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sqlExecute( sqlExecute(
'''UPDATE blacklist SET enabled=1 WHERE address=?''', 'UPDATE blacklist SET enabled=1 WHERE address=?',
str(addressAtCurrentRow)) str(addressAtCurrentRow))
else: else:
sqlExecute( sqlExecute(
'''UPDATE whitelist SET enabled=1 WHERE address=?''', 'UPDATE whitelist SET enabled=1 WHERE address=?',
str(addressAtCurrentRow)) str(addressAtCurrentRow))
def on_action_BlacklistDisable(self): def on_action_BlacklistDisable(self):
@ -241,12 +261,15 @@ class Blacklist(QtGui.QWidget, RetranslateMixin):
currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128)) currentRow, 0).setTextColor(QtGui.QColor(128, 128, 128))
self.tableWidgetBlacklist.item( self.tableWidgetBlacklist.item(
currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128)) currentRow, 1).setTextColor(QtGui.QColor(128, 128, 128))
if BMConfigParser().get('bitmessagesettings', 'blackwhitelist') == 'black': if BMConfigParser().get(
'bitmessagesettings', 'blackwhitelist') == 'black':
sqlExecute( sqlExecute(
'''UPDATE blacklist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) 'UPDATE blacklist SET enabled=0 WHERE address=?',
str(addressAtCurrentRow))
else: else:
sqlExecute( sqlExecute(
'''UPDATE whitelist SET enabled=0 WHERE address=?''', str(addressAtCurrentRow)) 'UPDATE whitelist SET enabled=0 WHERE address=?',
str(addressAtCurrentRow))
def on_action_BlacklistSetAvatar(self): def on_action_BlacklistSetAvatar(self):
self.window().on_action_SetAvatar(self.tableWidgetBlacklist) self.window().on_action_SetAvatar(self.tableWidgetBlacklist)

View File

@ -1,20 +1,20 @@
""" """
Custom dialog classes All dialogs are available in this module.
""" """
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
from PyQt4 import QtGui from PyQt4 import QtGui
import paths from pybitmessage import paths
import widgets from pybitmessage.tr import _translate
from address_dialogs import ( from pybitmessage.version import softwareVersion
from .address_dialogs import (
AddAddressDialog, EmailGatewayDialog, NewAddressDialog, AddAddressDialog, EmailGatewayDialog, NewAddressDialog,
NewSubscriptionDialog, RegenerateAddressesDialog, NewSubscriptionDialog, RegenerateAddressesDialog,
SpecialAddressBehaviorDialog SpecialAddressBehaviorDialog
) )
from newchandialog import NewChanDialog from . import widgets
from settings import SettingsDialog from .newchandialog import NewChanDialog
from tr import _translate from .settings import SettingsDialog
from version import softwareVersion
__all__ = [ __all__ = [
@ -26,7 +26,7 @@ __all__ = [
class AboutDialog(QtGui.QDialog): class AboutDialog(QtGui.QDialog):
"""The `About` dialog""" """The "About" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(AboutDialog, self).__init__(parent) super(AboutDialog, self).__init__(parent)
widgets.load('about.ui', self) widgets.load('about.ui', self)
@ -45,7 +45,7 @@ class AboutDialog(QtGui.QDialog):
try: try:
self.label_2.setText( self.label_2.setText(
self.label_2.text().replace( self.label_2.text().replace(
'2020', str(last_commit.get('time').year) '2021', str(last_commit.get('time').year)
)) ))
except AttributeError: except AttributeError:
pass pass
@ -54,7 +54,7 @@ class AboutDialog(QtGui.QDialog):
class IconGlossaryDialog(QtGui.QDialog): class IconGlossaryDialog(QtGui.QDialog):
"""The `Icon Glossary` dialog, explaining the status icon colors""" """The "Icon Glossary" dialog, explaining the status icon colors"""
def __init__(self, parent=None, config=None): def __init__(self, parent=None, config=None):
super(IconGlossaryDialog, self).__init__(parent) super(IconGlossaryDialog, self).__init__(parent)
widgets.load('iconglossary.ui', self) widgets.load('iconglossary.ui', self)
@ -70,7 +70,7 @@ class IconGlossaryDialog(QtGui.QDialog):
class HelpDialog(QtGui.QDialog): class HelpDialog(QtGui.QDialog):
"""The `Help` dialog""" """The "Help" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(HelpDialog, self).__init__(parent) super(HelpDialog, self).__init__(parent)
widgets.load('help.ui', self) widgets.load('help.ui', self)
@ -78,7 +78,7 @@ class HelpDialog(QtGui.QDialog):
class ConnectDialog(QtGui.QDialog): class ConnectDialog(QtGui.QDialog):
"""The `Connect` dialog""" """The "Connect" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(ConnectDialog, self).__init__(parent) super(ConnectDialog, self).__init__(parent)
widgets.load('connect.ui', self) widgets.load('connect.ui', self)

View File

@ -1,18 +1,18 @@
""" """
Folder tree and messagelist widgets definitions. Folder tree and messagelist widgets definitions.
""" """
# pylint: disable=too-many-arguments,bad-super-call # pylint: disable=too-many-arguments
# pylint: disable=attribute-defined-outside-init # pylint: disable=attribute-defined-outside-init
from cgi import escape from cgi import escape
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from bmconfigparser import BMConfigParser from pybitmessage.bmconfigparser import BMConfigParser
from helper_sql import sqlExecute, sqlQuery from pybitmessage.helper_sql import sqlExecute, sqlQuery
from settingsmixin import SettingsMixin from pybitmessage.tr import _translate
from tr import _translate from .settingsmixin import SettingsMixin
from utils import avatarize from .utils import avatarize
# for pylupdate # for pylupdate
_translate("MainWindow", "inbox") _translate("MainWindow", "inbox")
@ -33,29 +33,29 @@ class AccountMixin(object):
BROADCAST = 5 BROADCAST = 5
def accountColor(self): def accountColor(self):
"""QT UI color for an account""" """Qt UI color for an account"""
if not self.isEnabled: if not self.isEnabled:
return QtGui.QColor(128, 128, 128) return QtGui.QColor(128, 128, 128)
elif self.type == self.CHAN: elif self.type == self.CHAN:
return QtGui.QColor(216, 119, 0) return QtGui.QColor(216, 119, 0)
elif self.type in [self.MAILINGLIST, self.SUBSCRIPTION]: elif self.type in (self.MAILINGLIST, self.SUBSCRIPTION):
return QtGui.QColor(137, 4, 177) return QtGui.QColor(137, 4, 177)
return QtGui.QApplication.palette().text().color() return QtGui.QApplication.palette().text().color()
def folderColor(self): def folderColor(self):
"""QT UI color for a folder""" """Qt UI color for a folder"""
if not self.parent().isEnabled: if not self.parent().isEnabled:
return QtGui.QColor(128, 128, 128) return QtGui.QColor(128, 128, 128)
return QtGui.QApplication.palette().text().color() return QtGui.QApplication.palette().text().color()
def accountBrush(self): def accountBrush(self):
"""Account brush (for QT UI)""" """Account brush (for Qt UI)"""
brush = QtGui.QBrush(self.accountColor()) brush = QtGui.QBrush(self.accountColor())
brush.setStyle(QtCore.Qt.NoBrush) brush.setStyle(QtCore.Qt.NoBrush)
return brush return brush
def folderBrush(self): def folderBrush(self):
"""Folder brush (for QT UI)""" """Folder brush (for Qt UI)"""
brush = QtGui.QBrush(self.folderColor()) brush = QtGui.QBrush(self.folderColor())
brush.setStyle(QtCore.Qt.NoBrush) brush.setStyle(QtCore.Qt.NoBrush)
return brush return brush
@ -87,7 +87,7 @@ class AccountMixin(object):
self.emitDataChanged() self.emitDataChanged()
def setEnabled(self, enabled): def setEnabled(self, enabled):
"""Set account enabled (QT UI)""" """Set account enabled (Qt UI)"""
self.isEnabled = enabled self.isEnabled = enabled
try: try:
self.setExpanded(enabled) self.setExpanded(enabled)
@ -101,7 +101,7 @@ class AccountMixin(object):
self.emitDataChanged() self.emitDataChanged()
def setType(self): def setType(self):
"""Set account type (QT UI)""" """Set account type (Qt UI)"""
self.setFlags(self.flags() | QtCore.Qt.ItemIsEditable) self.setFlags(self.flags() | QtCore.Qt.ItemIsEditable)
if self.address is None: if self.address is None:
self.type = self.ALL self.type = self.ALL
@ -111,15 +111,15 @@ class AccountMixin(object):
elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'): elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'):
self.type = self.MAILINGLIST self.type = self.MAILINGLIST
elif sqlQuery( elif sqlQuery(
'''select label from subscriptions where address=?''', self.address): 'SELECT label FROM subscriptions WHERE address=?', self.address
):
self.type = AccountMixin.SUBSCRIPTION self.type = AccountMixin.SUBSCRIPTION
else: else:
self.type = self.NORMAL self.type = self.NORMAL
def defaultLabel(self): def defaultLabel(self):
"""Default label (in case no label is set manually)""" """Default label (in case no label is set manually)"""
queryreturn = None queryreturn = retval = None
retval = None
if self.type in ( if self.type in (
AccountMixin.NORMAL, AccountMixin.NORMAL,
AccountMixin.CHAN, AccountMixin.MAILINGLIST): AccountMixin.CHAN, AccountMixin.MAILINGLIST):
@ -128,15 +128,14 @@ class AccountMixin(object):
BMConfigParser().get(self.address, 'label'), 'utf-8') BMConfigParser().get(self.address, 'label'), 'utf-8')
except Exception: except Exception:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from addressbook where address=?''', self.address) 'SELECT label FROM addressbook WHERE address=?',
self.address)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?',
if queryreturn is not None: self.address)
if queryreturn != []: if queryreturn:
for row in queryreturn: retval = unicode(queryreturn[-1][0], 'utf-8')
retval, = row
retval = unicode(retval, 'utf-8')
elif self.address is None or self.type == AccountMixin.ALL: elif self.address is None or self.type == AccountMixin.ALL:
return unicode( return unicode(
str(_translate("MainWindow", "All accounts")), 'utf-8') str(_translate("MainWindow", "All accounts")), 'utf-8')
@ -157,7 +156,7 @@ class BMTreeWidgetItem(QtGui.QTreeWidgetItem, AccountMixin):
return " (" + str(self.unreadCount) + ")" if unreadCount else "" return " (" + str(self.unreadCount) + ")" if unreadCount else ""
def data(self, column, role): def data(self, column, role):
"""Override internal QT method for returning object data""" """Override internal Qt method for returning object data"""
if column == 0: if column == 0:
if role == QtCore.Qt.DisplayRole: if role == QtCore.Qt.DisplayRole:
return self._getLabel() + self._getAddressBracket( return self._getLabel() + self._getAddressBracket(
@ -190,11 +189,11 @@ class Ui_FolderWidget(BMTreeWidgetItem):
return _translate("MainWindow", self.folderName) return _translate("MainWindow", self.folderName)
def setFolderName(self, fname): def setFolderName(self, fname):
"""Set folder name (for QT UI)""" """Set folder name (for Qt UI)"""
self.folderName = str(fname) self.folderName = str(fname)
def data(self, column, role): def data(self, column, role):
"""Override internal QT method for returning object data""" """Override internal Qt method for returning object data"""
if column == 0 and role == QtCore.Qt.ForegroundRole: if column == 0 and role == QtCore.Qt.ForegroundRole:
return self.folderBrush() return self.folderBrush()
return super(Ui_FolderWidget, self).data(column, role) return super(Ui_FolderWidget, self).data(column, role)
@ -221,7 +220,8 @@ class Ui_FolderWidget(BMTreeWidgetItem):
class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin): class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
"""Item in the account/folder tree representing an account""" """Item in the account/folder tree representing an account"""
def __init__(self, parent, pos=0, address=None, unreadCount=0, enabled=True): def __init__(
self, parent, pos=0, address=None, unreadCount=0, enabled=True):
super(Ui_AddressWidget, self).__init__( super(Ui_AddressWidget, self).__init__(
parent, pos, address, unreadCount) parent, pos, address, unreadCount)
self.setEnabled(enabled) self.setEnabled(enabled)
@ -250,7 +250,7 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
return ret return ret
def data(self, column, role): def data(self, column, role):
"""Override internal QT method for returning object data""" """Override internal Qt method for returning object data"""
if column == 0: if column == 0:
if role == QtCore.Qt.DecorationRole: if role == QtCore.Qt.DecorationRole:
return avatarize( return avatarize(
@ -260,7 +260,10 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
return super(Ui_AddressWidget, self).data(column, role) return super(Ui_AddressWidget, self).data(column, role)
def setData(self, column, role, value): def setData(self, column, role, value):
"""Save account label (if you edit in the the UI, this will be triggered and will save it to keys.dat)""" """
Save account label (if you edit in the the UI, this will be
triggered and will save it to keys.dat)
"""
if role == QtCore.Qt.EditRole \ if role == QtCore.Qt.EditRole \
and self.type != AccountMixin.SUBSCRIPTION: and self.type != AccountMixin.SUBSCRIPTION:
BMConfigParser().set( BMConfigParser().set(
@ -273,7 +276,7 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
return super(Ui_AddressWidget, self).setData(column, role, value) return super(Ui_AddressWidget, self).setData(column, role, value)
def setAddress(self, address): def setAddress(self, address):
"""Set address to object (for QT UI)""" """Set address to object (for Qt UI)"""
super(Ui_AddressWidget, self).setAddress(address) super(Ui_AddressWidget, self).setAddress(address)
self.setData(0, QtCore.Qt.UserRole, self.address) self.setData(0, QtCore.Qt.UserRole, self.address)
@ -295,19 +298,21 @@ class Ui_AddressWidget(BMTreeWidgetItem, SettingsMixin):
if self._getSortRank() < other._getSortRank() else reverse if self._getSortRank() < other._getSortRank() else reverse
) )
return super(QtGui.QTreeWidgetItem, self).__lt__(other) return super(Ui_AddressWidget, self).__lt__(other)
class Ui_SubscriptionWidget(Ui_AddressWidget): class Ui_SubscriptionWidget(Ui_AddressWidget):
"""Special treating of subscription addresses""" """Special treating of subscription addresses"""
# pylint: disable=unused-argument # pylint: disable=unused-argument
def __init__(self, parent, pos=0, address="", unreadCount=0, label="", enabled=True): def __init__(
self, parent, pos=0, address="", unreadCount=0, label="", enabled=True
):
super(Ui_SubscriptionWidget, self).__init__( super(Ui_SubscriptionWidget, self).__init__(
parent, pos, address, unreadCount, enabled) parent, pos, address, unreadCount, enabled)
def _getLabel(self): def _getLabel(self):
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?', self.address)
if queryreturn != []: if queryreturn != []:
for row in queryreturn: for row in queryreturn:
retval, = row retval, = row
@ -328,7 +333,7 @@ class Ui_SubscriptionWidget(Ui_AddressWidget):
else: else:
label = unicode(value, 'utf-8', 'ignore') label = unicode(value, 'utf-8', 'ignore')
sqlExecute( sqlExecute(
'''UPDATE subscriptions SET label=? WHERE address=?''', 'UPDATE subscriptions SET label=? WHERE address=?',
label, self.address) label, self.address)
return super(Ui_SubscriptionWidget, self).setData(column, role, value) return super(Ui_SubscriptionWidget, self).setData(column, role, value)
@ -354,7 +359,7 @@ class BMTableWidgetItem(QtGui.QTableWidgetItem, SettingsMixin):
self.unread = unread self.unread = unread
def data(self, role): def data(self, role):
"""Return object data (QT UI)""" """Return object data (Qt UI)"""
if role in ( if role in (
QtCore.Qt.DisplayRole, QtCore.Qt.EditRole, QtCore.Qt.ToolTipRole QtCore.Qt.DisplayRole, QtCore.Qt.EditRole, QtCore.Qt.ToolTipRole
): ):
@ -378,7 +383,7 @@ class BMAddressWidget(BMTableWidgetItem, AccountMixin):
return self.label return self.label
def data(self, role): def data(self, role):
"""Return object data (QT UI)""" """Return object data (Qt UI)"""
if role == QtCore.Qt.ToolTipRole: if role == QtCore.Qt.ToolTipRole:
return self.label + " (" + self.address + ")" return self.label + " (" + self.address + ")"
elif role == QtCore.Qt.DecorationRole: elif role == QtCore.Qt.DecorationRole:
@ -412,10 +417,12 @@ class MessageList_AddressWidget(BMAddressWidget):
'utf-8', 'ignore') 'utf-8', 'ignore')
except: except:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from addressbook where address=?''', self.address) 'SELECT label FROM addressbook WHERE address=?',
self.address)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
queryreturn = sqlQuery( queryreturn = sqlQuery(
'''select label from subscriptions where address=?''', self.address) 'SELECT label FROM subscriptions WHERE address=?',
self.address)
if queryreturn: if queryreturn:
for row in queryreturn: for row in queryreturn:
newLabel = unicode(row[0], 'utf-8', 'ignore') newLabel = unicode(row[0], 'utf-8', 'ignore')
@ -423,7 +430,7 @@ class MessageList_AddressWidget(BMAddressWidget):
self.label = newLabel self.label = newLabel
def data(self, role): def data(self, role):
"""Return object data (QT UI)""" """Return object data (Qt UI)"""
if role == QtCore.Qt.UserRole: if role == QtCore.Qt.UserRole:
return self.address return self.address
return super(MessageList_AddressWidget, self).data(role) return super(MessageList_AddressWidget, self).data(role)
@ -438,7 +445,7 @@ class MessageList_AddressWidget(BMAddressWidget):
def __lt__(self, other): def __lt__(self, other):
if isinstance(other, MessageList_AddressWidget): if isinstance(other, MessageList_AddressWidget):
return self.label.lower() < other.label.lower() return self.label.lower() < other.label.lower()
return super(QtGui.QTableWidgetItem, self).__lt__(other) return super(MessageList_AddressWidget, self).__lt__(other)
class MessageList_SubjectWidget(BMTableWidgetItem): class MessageList_SubjectWidget(BMTableWidgetItem):
@ -452,7 +459,7 @@ class MessageList_SubjectWidget(BMTableWidgetItem):
self.subject = subject self.subject = subject
def data(self, role): def data(self, role):
"""Return object data (QT UI)""" """Return object data (Qt UI)"""
if role == QtCore.Qt.UserRole: if role == QtCore.Qt.UserRole:
return self.subject return self.subject
if role == QtCore.Qt.ToolTipRole: if role == QtCore.Qt.ToolTipRole:
@ -463,7 +470,7 @@ class MessageList_SubjectWidget(BMTableWidgetItem):
def __lt__(self, other): def __lt__(self, other):
if isinstance(other, MessageList_SubjectWidget): if isinstance(other, MessageList_SubjectWidget):
return self.label.lower() < other.label.lower() return self.label.lower() < other.label.lower()
return super(QtGui.QTableWidgetItem, self).__lt__(other) return super(MessageList_SubjectWidget, self).__lt__(other)
# In order for the time columns on the Inbox and Sent tabs to be sorted # In order for the time columns on the Inbox and Sent tabs to be sorted
@ -525,9 +532,13 @@ class Ui_AddressBookWidgetItem(BMAddressWidget):
BMConfigParser().set(self.address, 'label', self.label) BMConfigParser().set(self.address, 'label', self.label)
BMConfigParser().save() BMConfigParser().save()
except: except:
sqlExecute('''UPDATE addressbook set label=? WHERE address=?''', self.label, self.address) sqlExecute(
'UPDATE addressbook set label=? WHERE address=?',
self.label, self.address)
elif self.type == AccountMixin.SUBSCRIPTION: elif self.type == AccountMixin.SUBSCRIPTION:
sqlExecute('''UPDATE subscriptions set label=? WHERE address=?''', self.label, self.address) sqlExecute(
'UPDATE subscriptions set label=? WHERE address=?',
self.label, self.address)
else: else:
pass pass
return super(Ui_AddressBookWidgetItem, self).setData(role, value) return super(Ui_AddressBookWidgetItem, self).setData(role, value)
@ -577,7 +588,8 @@ class AddressBookCompleter(QtGui.QCompleter):
super(AddressBookCompleter, self).__init__() super(AddressBookCompleter, self).__init__()
self.cursorPos = -1 self.cursorPos = -1
def onCursorPositionChanged(self, oldPos, newPos): # pylint: disable=unused-argument def onCursorPositionChanged(self, oldPos, newPos):
# pylint: disable=unused-argument
"""Callback for cursor position change""" """Callback for cursor position change"""
if oldPos != self.cursorPos: if oldPos != self.cursorPos:
self.cursorPos = -1 self.cursorPos = -1

View File

@ -1,30 +1,32 @@
"""Language Box Module for Locale Settings""" """LanguageBox widget is for selecting UI language"""
# pylint: disable=too-few-public-methods,bad-continuation
import glob import glob
import os import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import paths from pybitmessage import paths
from bmconfigparser import BMConfigParser from pybitmessage.bmconfigparser import BMConfigParser
from pybitmessage.tr import _translate
# pylint: disable=too-few-public-methods
class LanguageBox(QtGui.QComboBox): class LanguageBox(QtGui.QComboBox):
"""LanguageBox class for Qt UI""" """A subclass of `QtWidgets.QComboBox` for selecting language"""
languageName = { languageName = {
"system": "System Settings", "eo": "Esperanto", "system": "System Settings", "eo": "Esperanto",
"en_pirate": "Pirate English" "en_pirate": "Pirate English"
} }
def __init__(self, parent=None): def __init__(self, parent=None):
super(QtGui.QComboBox, self).__init__(parent) super(LanguageBox, self).__init__(parent)
self.populate() self.populate()
def populate(self): def populate(self):
"""Populates drop down list with all available languages.""" """Populates drop down list with all available languages."""
self.clear() self.clear()
localesPath = os.path.join(paths.codePath(), 'translations') localesPath = os.path.join(paths.codePath(), 'translations')
self.addItem(QtGui.QApplication.translate( self.addItem(_translate(
"settingsDialog", "System Settings", "system"), "system") "settingsDialog", "System Settings", "system"), "system")
self.setCurrentIndex(0) self.setCurrentIndex(0)
self.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically) self.setInsertPolicy(QtGui.QComboBox.InsertAlphabetically)
@ -42,7 +44,7 @@ class LanguageBox(QtGui.QComboBox):
locale.nativeLanguageName() or localeShort, localeShort) locale.nativeLanguageName() or localeShort, localeShort)
configuredLocale = BMConfigParser().safeGet( configuredLocale = BMConfigParser().safeGet(
'bitmessagesettings', 'userlocale', "system") 'bitmessagesettings', 'userlocale', 'system')
for i in range(self.count()): for i in range(self.count()):
if self.itemData(i) == configuredLocale: if self.itemData(i) == configuredLocale:
self.setCurrentIndex(i) self.setCurrentIndex(i)

View File

@ -1,33 +1,36 @@
""" """The MessageCompose class definition"""
Message editor with a wheel zoom functionality
"""
# pylint: disable=bad-continuation
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from pybitmessage.tr import _translate
class MessageCompose(QtGui.QTextEdit): class MessageCompose(QtGui.QTextEdit):
"""Editor class with wheel zoom functionality""" """Editor class with wheel zoom functionality"""
def __init__(self, parent=0): def __init__(self, parent=None):
super(MessageCompose, self).__init__(parent) super(MessageCompose, self).__init__(parent)
# we'll deal with this later when we have a new message format
self.setAcceptRichText(False) self.setAcceptRichText(False)
self.defaultFontPointSize = self.currentFont().pointSize() self.defaultFontPointSize = self.currentFont().pointSize()
def wheelEvent(self, event): def wheelEvent(self, event):
"""Mouse wheel scroll event handler""" """Mouse wheel scroll event handler"""
if ( if ((
QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier QtGui.QApplication.queryKeyboardModifiers()
) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical: & QtCore.Qt.ControlModifier
) == QtCore.Qt.ControlModifier
and event.orientation() == QtCore.Qt.Vertical
):
if event.delta() > 0: if event.delta() > 0:
self.zoomIn(1) self.zoomIn(1)
else: else:
self.zoomOut(1) self.zoomOut(1)
zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize
QtGui.QApplication.activeWindow().statusBar().showMessage( QtGui.QApplication.activeWindow().statusBar().showMessage(
QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg( _translate("MainWindow", "Zoom level %1%").arg(str(
str(zoom) # zoom percentage
) self.currentFont().pointSize() * 100
) / self.defaultFontPointSize
)))
else: else:
# in QTextEdit, super does not zoom, only scroll # in QTextEdit, super does not zoom, only scroll
super(MessageCompose, self).wheelEvent(event) super(MessageCompose, self).wheelEvent(event)

View File

@ -1,14 +1,13 @@
""" """
Custom message viewer with support for switching between HTML and plain Custom message viewer with support for switching between HTML and plain
text rendering, HTML sanitization, lazy rendering (as you scroll down), text rendering, HTML sanitization, lazy rendering (as you scroll down),
zoom and URL click warning popup zoom and URL click warning popup.
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from safehtmlparser import SafeHTMLParser from pybitmessage.tr import _translate
from tr import _translate from .safehtmlparser import SafeHTMLParser
class MessageView(QtGui.QTextBrowser): class MessageView(QtGui.QTextBrowser):
@ -16,7 +15,7 @@ class MessageView(QtGui.QTextBrowser):
MODE_PLAIN = 0 MODE_PLAIN = 0
MODE_HTML = 1 MODE_HTML = 1
def __init__(self, parent=0): def __init__(self, parent=None):
super(MessageView, self).__init__(parent) super(MessageView, self).__init__(parent)
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
self.html = None self.html = None
@ -38,8 +37,11 @@ class MessageView(QtGui.QTextBrowser):
def mousePressEvent(self, event): def mousePressEvent(self, event):
"""Mouse press button event handler""" """Mouse press button event handler"""
if event.button() == QtCore.Qt.LeftButton and self.html and self.html.has_html and self.cursorForPosition( if (
event.pos()).block().blockNumber() == 0: event.button() == QtCore.Qt.LeftButton
and self.html and self.html.has_html
and self.cursorForPosition(event.pos()).block().blockNumber() == 0
):
if self.mode == MessageView.MODE_PLAIN: if self.mode == MessageView.MODE_PLAIN:
self.showHTML() self.showHTML()
else: else:
@ -61,9 +63,7 @@ class MessageView(QtGui.QTextBrowser):
def setWrappingWidth(self, width=None): def setWrappingWidth(self, width=None):
"""Set word-wrapping width""" """Set word-wrapping width"""
self.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth) self.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth)
if width is None: self.setLineWrapColumnOrWidth(width or self.width())
width = self.width()
self.setLineWrapColumnOrWidth(width)
def confirmURL(self, link): def confirmURL(self, link):
"""Show a dialog requesting URL opening confirmation""" """Show a dialog requesting URL opening confirmation"""
@ -84,14 +84,13 @@ class MessageView(QtGui.QTextBrowser):
window.ui.textEditMessage.setFocus() window.ui.textEditMessage.setFocus()
return return
reply = QtGui.QMessageBox.warning( reply = QtGui.QMessageBox.warning(
self, self, _translate("MessageView", "Follow external link"),
QtGui.QApplication.translate( _translate(
"MessageView", "MessageView",
"Follow external link"), "The link \"%1\" will open in a browser. It may be"
QtGui.QApplication.translate( " a security risk, it could de-anonymise you"
"MessageView", " or download malicious data. Are you sure?").arg(
"The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you" unicode(link.toString())),
" or download malicious data. Are you sure?").arg(unicode(link.toString())),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No) QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes: if reply == QtGui.QMessageBox.Yes:
@ -99,15 +98,15 @@ class MessageView(QtGui.QTextBrowser):
def loadResource(self, restype, name): def loadResource(self, restype, name):
""" """
Callback for loading referenced objects, such as an image. For security reasons at the moment doesn't do Callback for loading referenced objects, such as an image.
anything) For security reasons at the moment doesn't do anything
""" """
pass pass
def lazyRender(self): def lazyRender(self):
""" """
Partially render a message. This is to avoid UI freezing when loading huge messages. It continues loading as Partially render a message. This is to avoid UI freezing when
you scroll down. loading huge messages. It continues loading as you scroll down.
""" """
if self.rendering: if self.rendering:
return return
@ -123,7 +122,8 @@ class MessageView(QtGui.QTextBrowser):
pos = self.out.find(">", self.outpos) pos = self.out.find(">", self.outpos)
if pos > self.outpos: if pos > self.outpos:
self.outpos = pos + 1 self.outpos = pos + 1
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor) cursor.movePosition(
QtGui.QTextCursor.End, QtGui.QTextCursor.MoveAnchor)
cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos])) cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos]))
self.verticalScrollBar().setValue(position) self.verticalScrollBar().setValue(position)
self.rendering = False self.rendering = False
@ -133,9 +133,11 @@ class MessageView(QtGui.QTextBrowser):
self.mode = MessageView.MODE_PLAIN self.mode = MessageView.MODE_PLAIN
out = self.html.raw out = self.html.raw
if self.html.has_html: if self.html.has_html:
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode( out = (
QtGui.QApplication.translate( '<div align="center" style="text-decoration: underline;"><b>'
"MessageView", "HTML detected, click here to display")) + "</b></div><br/>" + out + _translate(
"MessageView", "HTML detected, click here to display"
) + '</b></div><br/>' + out)
self.out = out self.out = out
self.outpos = 0 self.outpos = 0
self.setHtml("") self.setHtml("")
@ -145,9 +147,10 @@ class MessageView(QtGui.QTextBrowser):
"""Render message as HTML""" """Render message as HTML"""
self.mode = MessageView.MODE_HTML self.mode = MessageView.MODE_HTML
out = self.html.sanitised out = self.html.sanitised
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode( self.out = (
QtGui.QApplication.translate("MessageView", "Click here to disable HTML")) + "</b></div><br/>" + out '<div align="center" style="text-decoration: underline;"><b>'
self.out = out + _translate("MessageView", "Click here to disable HTML")
+ '</b></div><br/>' + self.html.sanitised)
self.outpos = 0 self.outpos = 0
self.setHtml("") self.setHtml("")
self.lazyRender() self.lazyRender()

View File

@ -6,15 +6,13 @@ import time
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import l10n from pybitmessage import l10n, state
import network.stats from pybitmessage.inventory import Inventory
import state from pybitmessage.network import BMConnectionPool, knownnodes, stats
import widgets from pybitmessage.tr import _translate
from inventory import Inventory from . import widgets
from network import BMConnectionPool, knownnodes from .retranslateui import RetranslateMixin
from retranslateui import RetranslateMixin from .uisignaler import UISignaler
from tr import _translate
from uisignaler import UISignaler
class NetworkStatus(QtGui.QWidget, RetranslateMixin): class NetworkStatus(QtGui.QWidget, RetranslateMixin):
@ -58,20 +56,15 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
"""Stop counter update timer""" """Stop counter update timer"""
self.timer.stop() self.timer.stop()
@staticmethod
def formatBytes(self, num): def formatBytes(self, num):
"""Format bytes nicely (SI prefixes)""" """Format bytes nicely (SI prefixes)"""
# pylint: disable=no-self-use for x in (
for x in [ _translate("networkstatus", "byte(s)", None, num),
_translate( _translate("networkstatus", "kB"),
"networkstatus", _translate("networkstatus", "MB"),
"byte(s)", _translate("networkstatus", "GB")
None, ):
QtCore.QCoreApplication.CodecForTr,
num),
"kB",
"MB",
"GB",
]:
if num < 1000.0: if num < 1000.0:
return "%3.0f %s" % (num, x) return "%3.0f %s" % (num, x)
num /= 1000.0 num /= 1000.0
@ -85,64 +78,44 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
def updateNumberOfObjectsToBeSynced(self): def updateNumberOfObjectsToBeSynced(self):
"""Update the counter for number of objects to be synced""" """Update the counter for number of objects to be synced"""
self.labelSyncStatus.setText( self.labelSyncStatus.setText(_translate(
_translate( "networkstatus", "Object(s) to be synced: %n", None,
"networkstatus", stats.pendingDownload() + stats.pendingUpload()))
"Object(s) to be synced: %n",
None,
QtCore.QCoreApplication.CodecForTr,
network.stats.pendingDownload()
+ network.stats.pendingUpload()))
def updateNumberOfMessagesProcessed(self): def updateNumberOfMessagesProcessed(self):
"""Update the counter for number of processed messages""" """Update the counter for number of processed messages"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelMessageCount.setText( self.labelMessageCount.setText(_translate(
_translate( "networkstatus", "Processed %n person-to-person message(s).", None,
"networkstatus", state.numberOfMessagesProcessed))
"Processed %n person-to-person message(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfMessagesProcessed))
def updateNumberOfBroadcastsProcessed(self): def updateNumberOfBroadcastsProcessed(self):
"""Update the counter for the number of processed broadcasts""" """Update the counter for the number of processed broadcasts"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelBroadcastCount.setText( self.labelBroadcastCount.setText(_translate(
_translate( "networkstatus", "Processed %n broadcast message(s).", None,
"networkstatus", state.numberOfBroadcastsProcessed))
"Processed %n broadcast message(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfBroadcastsProcessed))
def updateNumberOfPubkeysProcessed(self): def updateNumberOfPubkeysProcessed(self):
"""Update the counter for the number of processed pubkeys""" """Update the counter for the number of processed pubkeys"""
self.updateNumberOfObjectsToBeSynced() self.updateNumberOfObjectsToBeSynced()
self.labelPubkeyCount.setText( self.labelPubkeyCount.setText(_translate(
_translate( "networkstatus", "Processed %n public key(s).", None,
"networkstatus", state.numberOfPubkeysProcessed))
"Processed %n public key(s).",
None,
QtCore.QCoreApplication.CodecForTr,
state.numberOfPubkeysProcessed))
def updateNumberOfBytes(self): def updateNumberOfBytes(self):
""" """
This function is run every two seconds, so we divide the rate of bytes This function is run every two seconds, so we divide the rate
sent and received by 2. of bytes sent and received by 2.
""" """
self.labelBytesRecvCount.setText( self.labelBytesRecvCount.setText(_translate(
_translate( "networkstatus", "Down: %1/s Total: %2").arg(
"networkstatus", self.formatByteRate(stats.downloadSpeed()),
"Down: %1/s Total: %2").arg( self.formatBytes(stats.receivedBytes())))
self.formatByteRate(network.stats.downloadSpeed()), self.labelBytesSentCount.setText(_translate(
self.formatBytes(network.stats.receivedBytes()))) "networkstatus", "Up: %1/s Total: %2").arg(
self.labelBytesSentCount.setText( self.formatByteRate(stats.uploadSpeed()),
_translate( self.formatBytes(stats.sentBytes())))
"networkstatus", "Up: %1/s Total: %2").arg(
self.formatByteRate(network.stats.uploadSpeed()),
self.formatBytes(network.stats.sentBytes())))
def updateNetworkStatusTab(self, outbound, add, destination): def updateNetworkStatusTab(self, outbound, add, destination):
"""Add or remove an entry to the list of connected peers""" """Add or remove an entry to the list of connected peers"""
@ -170,7 +143,8 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
self.tableWidgetConnectionCount.insertRow(0) self.tableWidgetConnectionCount.insertRow(0)
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 0, 0, 0,
QtGui.QTableWidgetItem("%s:%i" % (destination.host, destination.port)) QtGui.QTableWidgetItem("%s:%i" % (
destination.host, destination.port))
) )
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
0, 2, 0, 2,
@ -186,7 +160,8 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
) )
try: try:
# .. todo:: FIXME: hard coded stream no # .. todo:: FIXME: hard coded stream no
rating = "%.1f" % (knownnodes.knownNodes[1][destination]['rating']) rating = "%.1f" % (
knownnodes.knownNodes[1][destination]['rating'])
except KeyError: except KeyError:
rating = "-" rating = "-"
self.tableWidgetConnectionCount.setItem( self.tableWidgetConnectionCount.setItem(
@ -217,18 +192,20 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
_translate( _translate(
"networkstatus", "Total Connections: %1").arg( "networkstatus", "Total Connections: %1").arg(
str(self.tableWidgetConnectionCount.rowCount()))) str(self.tableWidgetConnectionCount.rowCount())))
# FYI: The 'singlelistener' thread sets the icon color to green when it # FYI: The 'singlelistener' thread sets the icon color to green
# receives an incoming connection, meaning that the user's firewall is # when it receives an incoming connection, meaning that the user's
# configured correctly. # firewall is configured correctly.
if self.tableWidgetConnectionCount.rowCount() and state.statusIconColor == 'red': if self.tableWidgetConnectionCount.rowCount():
self.window().setStatusIcon('yellow') if state.statusIconColor == 'red':
elif self.tableWidgetConnectionCount.rowCount() == 0 and state.statusIconColor != "red": self.window().setStatusIcon('yellow')
elif state.statusIconColor != "red":
self.window().setStatusIcon('red') self.window().setStatusIcon('red')
# timer driven # timer driven
def runEveryTwoSeconds(self): def runEveryTwoSeconds(self):
"""Updates counters, runs every 2 seconds if the timer is running""" """Updates counters, runs every 2 seconds if the timer is running"""
self.labelLookupsPerSecond.setText(_translate("networkstatus", "Inventory lookups per second: %1").arg( self.labelLookupsPerSecond.setText(_translate(
"networkstatus", "Inventory lookups per second: %1").arg(
str(Inventory().numberOfInventoryLookupsPerformed / 2))) str(Inventory().numberOfInventoryLookupsPerformed / 2)))
Inventory().numberOfInventoryLookupsPerformed = 0 Inventory().numberOfInventoryLookupsPerformed = 0
self.updateNumberOfBytes() self.updateNumberOfBytes()
@ -237,10 +214,9 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
def retranslateUi(self): def retranslateUi(self):
"""Conventional Qt Designer method for dynamic l10n""" """Conventional Qt Designer method for dynamic l10n"""
super(NetworkStatus, self).retranslateUi() super(NetworkStatus, self).retranslateUi()
self.labelTotalConnections.setText( self.labelTotalConnections.setText(_translate(
_translate( "networkstatus", "Total Connections: %1").arg(
"networkstatus", "Total Connections: %1").arg( str(self.tableWidgetConnectionCount.rowCount())))
str(self.tableWidgetConnectionCount.rowCount())))
self.labelStartupTime.setText(_translate( self.labelStartupTime.setText(_translate(
"networkstatus", "Since startup on %1" "networkstatus", "Since startup on %1"
).arg(l10n.formatTimestamp(self.startup))) ).arg(l10n.formatTimestamp(self.startup)))

View File

@ -1,40 +1,30 @@
""" """
src/bitmessageqt/newchandialog.py NewChanDialog class definition
=================================
""" """
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import widgets from pybitmessage.addresses import addBMIfNotPresent
from addresses import addBMIfNotPresent from pybitmessage.queues import (
from addressvalidator import AddressValidator, PassPhraseValidator
from queues import (
addressGeneratorQueue, apiAddressGeneratorReturnQueue, UISignalQueue) addressGeneratorQueue, apiAddressGeneratorReturnQueue, UISignalQueue)
from tr import _translate from pybitmessage.tr import _translate
from utils import str_chan from . import widgets
from .addressvalidator import AddressValidator, PassPhraseValidator
from .utils import str_chan
class NewChanDialog(QtGui.QDialog): class NewChanDialog(QtGui.QDialog):
"""The `New Chan` dialog""" """The "New Chan" dialog"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(NewChanDialog, self).__init__(parent) super(NewChanDialog, self).__init__(parent)
widgets.load('newchandialog.ui', self) widgets.load('newchandialog.ui', self)
self.parent = parent self.parent = parent
self.chanAddress.setValidator( self.chanAddress.setValidator(AddressValidator(
AddressValidator( self.chanAddress, self.chanPassPhrase, self.validatorFeedback,
self.chanAddress, self.buttonBox, False))
self.chanPassPhrase, self.chanPassPhrase.setValidator(PassPhraseValidator(
self.validatorFeedback, self.chanPassPhrase, self.chanAddress, self.validatorFeedback,
self.buttonBox, self.buttonBox, False))
False))
self.chanPassPhrase.setValidator(
PassPhraseValidator(
self.chanPassPhrase,
self.chanAddress,
self.validatorFeedback,
self.buttonBox,
False))
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
QtCore.QObject.connect( # pylint: disable=no-member QtCore.QObject.connect( # pylint: disable=no-member

View File

@ -1,7 +1,8 @@
from os import path
from PyQt4 import QtGui from PyQt4 import QtGui
from debug import logger
import widgets from . import widgets
class RetranslateMixin(object): class RetranslateMixin(object):
def retranslateUi(self): def retranslateUi(self):
@ -12,7 +13,9 @@ class RetranslateMixin(object):
if callable(setTextMethod): if callable(setTextMethod):
getattr(self, attr).setText(getattr(defaults, attr).text()) getattr(self, attr).setText(getattr(defaults, attr).text())
elif isinstance(value, QtGui.QTableWidget): elif isinstance(value, QtGui.QTableWidget):
for i in range (value.columnCount()): for i in range(value.columnCount()):
getattr(self, attr).horizontalHeaderItem(i).setText(getattr(defaults, attr).horizontalHeaderItem(i).text()) getattr(self, attr).horizontalHeaderItem(i).setText(
for i in range (value.rowCount()): getattr(defaults, attr).horizontalHeaderItem(i).text())
getattr(self, attr).verticalHeaderItem(i).setText(getattr(defaults, attr).verticalHeaderItem(i).text()) for i in range(value.rowCount()):
getattr(self, attr).verticalHeaderItem(i).setText(
getattr(defaults, attr).verticalHeaderItem(i).text())

View File

@ -8,20 +8,15 @@ import tempfile
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import debug from pybitmessage import (
import defaults debug, defaults, namecoin, openclpow, paths, queues, state)
import namecoin from pybitmessage.bmconfigparser import BMConfigParser
import openclpow from pybitmessage.helper_sql import sqlExecute, sqlStoredProcedure
import paths from pybitmessage.helper_startup import start_proxyconfig
import queues from pybitmessage.network import knownnodes, AnnounceThread
import state from pybitmessage.network.asyncore_pollchoose import set_rates
import widgets from pybitmessage.tr import _translate
from bmconfigparser import BMConfigParser from . import widgets
from helper_sql import sqlExecute, sqlStoredProcedure
from helper_startup import start_proxyconfig
from network import knownnodes, AnnounceThread
from network.asyncore_pollchoose import set_rates
from tr import _translate
def getSOCKSProxyType(config): def getSOCKSProxyType(config):

View File

@ -1,7 +1,7 @@
# pylint: disable=unused-argument """BMStatusBar class definition"""
"""Status bar Module"""
from time import time from time import time
from PyQt4 import QtGui from PyQt4 import QtGui
@ -16,21 +16,26 @@ class BMStatusBar(QtGui.QStatusBar):
self.timer = self.startTimer(BMStatusBar.duration) self.timer = self.startTimer(BMStatusBar.duration)
self.iterator = 0 self.iterator = 0
def timerEvent(self, event): def timerEvent(self, event): # pylint: disable=unused-argument
"""an event handler which allows to queue and prioritise messages to """
An event handler which allows to queue and prioritise messages to
show in the status bar, for example if many messages come very quickly show in the status bar, for example if many messages come very quickly
after one another, it adds delays and so on""" after one another, it adds delays and so on.
"""
while len(self.important) > 0: while len(self.important) > 0:
self.iterator += 1 self.iterator += 1
try: try:
if time() > self.important[self.iterator][1] + BMStatusBar.deleteAfter: if (
self.important[self.iterator][1]
+ BMStatusBar.deleteAfter < time()
):
del self.important[self.iterator] del self.important[self.iterator]
self.iterator -= 1 self.iterator -= 1
continue continue
except IndexError: except IndexError:
self.iterator = -1 self.iterator = -1
continue continue
super(BMStatusBar, self).showMessage(self.important[self.iterator][0], 0) self.showMessage(self.important[self.iterator][0], 0)
break break
def addImportant(self, message): def addImportant(self, message):

View File

@ -1,29 +1,25 @@
"""Composing support request message functions.""" """Composing support request message functions."""
# pylint: disable=no-member
import ctypes import ctypes
import os
import ssl import ssl
import sys import sys
import time import time
from PyQt4 import QtCore from PyQt4 import QtCore
import account from pybitmessage import defaults, paths, proofofwork, queues, state
import defaults from pybitmessage.bmconfigparser import BMConfigParser
import network.stats from pybitmessage.helper_sql import sqlExecute, sqlQuery
import paths from pybitmessage.l10n import getTranslationLanguage
import proofofwork from pybitmessage.network import stats
import queues from pybitmessage.openclpow import openclEnabled
import state from pybitmessage.pyelliptic.openssl import OpenSSL
from bmconfigparser import BMConfigParser from pybitmessage.tr import _translate
from foldertree import AccountMixin from pybitmessage.version import softwareVersion
from helper_sql import sqlExecute, sqlQuery from . import account
from l10n import getTranslationLanguage from .foldertree import AccountMixin
from openclpow import openclEnabled from .settings import getSOCKSProxyType
from pyelliptic.openssl import OpenSSL
from settings import getSOCKSProxyType
from version import softwareVersion
from tr import _translate
# this is BM support address going to Peter Surda # this is BM support address going to Peter Surda
@ -31,7 +27,7 @@ OLD_SUPPORT_ADDRESS = 'BM-2cTkCtMYkrSPwFTpgcBrMrf5d8oZwvMZWK'
SUPPORT_ADDRESS = 'BM-2cUdgkDDAahwPAU6oD2A7DnjqZz3hgY832' SUPPORT_ADDRESS = 'BM-2cUdgkDDAahwPAU6oD2A7DnjqZz3hgY832'
SUPPORT_LABEL = _translate("Support", "PyBitmessage support") SUPPORT_LABEL = _translate("Support", "PyBitmessage support")
SUPPORT_MY_LABEL = _translate("Support", "My new address") SUPPORT_MY_LABEL = _translate("Support", "My new address")
SUPPORT_SUBJECT = 'Support request' SUPPORT_SUBJECT = _translate("Support", "Support request")
SUPPORT_MESSAGE = _translate("Support", ''' SUPPORT_MESSAGE = _translate("Support", '''
You can use this message to send a report to one of the PyBitmessage core \ You can use this message to send a report to one of the PyBitmessage core \
developers regarding PyBitmessage or the mailchuck.com email service. \ developers regarding PyBitmessage or the mailchuck.com email service. \
@ -67,8 +63,12 @@ Connected hosts: {}
def checkAddressBook(myapp): def checkAddressBook(myapp):
"""
Add "PyBitmessage support" address to address book, remove old one if found.
"""
sqlExecute('DELETE from addressbook WHERE address=?', OLD_SUPPORT_ADDRESS) sqlExecute('DELETE from addressbook WHERE address=?', OLD_SUPPORT_ADDRESS)
queryreturn = sqlQuery('SELECT * FROM addressbook WHERE address=?', SUPPORT_ADDRESS) queryreturn = sqlQuery(
'SELECT * FROM addressbook WHERE address=?', SUPPORT_ADDRESS)
if queryreturn == []: if queryreturn == []:
sqlExecute( sqlExecute(
'INSERT INTO addressbook VALUES (?,?)', 'INSERT INTO addressbook VALUES (?,?)',
@ -77,14 +77,17 @@ def checkAddressBook(myapp):
def checkHasNormalAddress(): def checkHasNormalAddress():
"""Returns first enabled normal address or False if not found."""
for address in account.getSortedAccounts(): for address in account.getSortedAccounts():
acct = account.accountClass(address) acct = account.accountClass(address)
if acct.type == AccountMixin.NORMAL and BMConfigParser().safeGetBoolean(address, 'enabled'): if acct.type == AccountMixin.NORMAL and BMConfigParser().safeGetBoolean(
address, 'enabled'):
return address return address
return False return False
def createAddressIfNeeded(myapp): def createAddressIfNeeded(myapp):
"""Checks if user has any anabled normal address, creates new one if no."""
if not checkHasNormalAddress(): if not checkHasNormalAddress():
queues.addressGeneratorQueue.put(( queues.addressGeneratorQueue.put((
'createRandomAddress', 4, 1, 'createRandomAddress', 4, 1,
@ -100,6 +103,9 @@ def createAddressIfNeeded(myapp):
def createSupportMessage(myapp): def createSupportMessage(myapp):
"""
Prepare the support request message and switch to tab "Send"
"""
checkAddressBook(myapp) checkAddressBook(myapp)
address = createAddressIfNeeded(myapp) address = createAddressIfNeeded(myapp)
if state.shutdown: if state.shutdown:
@ -119,15 +125,12 @@ def createSupportMessage(myapp):
if commit: if commit:
version += " GIT " + commit version += " GIT " + commit
os = sys.platform if sys.platform.startswith("win"):
if os == "win32": # pylint: disable=no-member
windowsversion = sys.getwindowsversion() osname = "Windows %s.%s" % sys.getwindowsversion()[:2]
os = "Windows " + str(windowsversion[0]) + "." + str(windowsversion[1])
else: else:
try: try:
from os import uname osname = '{0} {2}'.format(*os.uname())
unixversion = uname()
os = unixversion[0] + " " + unixversion[2]
except: except:
pass pass
architecture = "32" if ctypes.sizeof(ctypes.c_voidp) == 4 else "64" architecture = "32" if ctypes.sizeof(ctypes.c_voidp) == 4 else "64"
@ -139,15 +142,15 @@ def createSupportMessage(myapp):
frozen = "N/A" frozen = "N/A"
if paths.frozen: if paths.frozen:
frozen = paths.frozen frozen = paths.frozen
portablemode = "True" if state.appdata == paths.lookupExeFolder() else "False" portablemode = str(state.appdata == paths.lookupExeFolder())
cpow = "True" if proofofwork.bmpow else "False" cpow = "True" if proofofwork.bmpow else "False"
openclpow = str( openclpow = str(
BMConfigParser().safeGet('bitmessagesettings', 'opencl') BMConfigParser().safeGet('bitmessagesettings', 'opencl')
) if openclEnabled() else "None" ) if openclEnabled() else "None"
locale = getTranslationLanguage() locale = getTranslationLanguage()
socks = getSOCKSProxyType(BMConfigParser()) or "N/A" socks = getSOCKSProxyType(BMConfigParser()) or 'N/A'
upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', "N/A") upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', 'N/A')
connectedhosts = len(network.stats.connectedHostsList()) connectedhosts = len(stats.connectedHostsList())
myapp.ui.textEditMessage.setText(unicode(SUPPORT_MESSAGE, 'utf-8').format( myapp.ui.textEditMessage.setText(unicode(SUPPORT_MESSAGE, 'utf-8').format(
version, os, architecture, pythonversion, opensslversion, frozen, version, os, architecture, pythonversion, opensslversion, frozen,

View File

@ -1,8 +1,8 @@
from PyQt4.QtCore import QThread, SIGNAL
import sys import sys
import queues from PyQt4.QtCore import QThread, SIGNAL
from pybitmessage import queues
class UISignaler(QThread): class UISignaler(QThread):

View File

@ -3,9 +3,9 @@ import os
from PyQt4 import QtGui from PyQt4 import QtGui
import state from pybitmessage import state
from addresses import addBMIfNotPresent from pybitmessage.addresses import addBMIfNotPresent
from bmconfigparser import BMConfigParser from pybitmessage.bmconfigparser import BMConfigParser
str_broadcast_subscribers = '[Broadcast subscribers]' str_broadcast_subscribers = '[Broadcast subscribers]'
str_chan = '[chan]' str_chan = '[chan]'

View File

@ -1,13 +1,18 @@
from PyQt4 import uic
import os.path import os.path
import paths
import sys from PyQt4 import uic
from pybitmessage import paths
def resource_path(resFile): def resource_path(resFile):
baseDir = paths.codePath() baseDir = paths.codePath()
for subDir in ["ui", "bitmessageqt"]: for subDir in ("ui", "bitmessageqt"):
if os.path.isdir(os.path.join(baseDir, subDir)) and os.path.isfile(os.path.join(baseDir, subDir, resFile)): path = os.path.join(baseDir, subDir, resFile)
return os.path.join(baseDir, subDir, resFile) if os.path.isfile(path):
return path
def load(resFile, widget): def load(resFile, widget):
uic.loadUi(resource_path(resFile), widget) uic.loadUi(resource_path(resFile), widget)

View File

@ -10,8 +10,8 @@ from datetime import datetime
from six import string_types from six import string_types
from six.moves import configparser from six.moves import configparser
import state from . import state
from singleton import Singleton from .singleton import Singleton
SafeConfigParser = configparser.SafeConfigParser SafeConfigParser = configparser.SafeConfigParser

View File

@ -5,18 +5,14 @@ import hashlib
import time import time
from binascii import hexlify from binascii import hexlify
import defaults from . import defaults, highlevelcrypto, queues, shared, state
import highlevelcrypto from .addresses import decodeAddress, encodeAddress, encodeVarint
import queues from .bmconfigparser import BMConfigParser
import shared from .fallback import RIPEMD160Hash
import state from .network import StoppableThread
import tr from .pyelliptic import arithmetic
from addresses import decodeAddress, encodeAddress, encodeVarint from .pyelliptic.openssl import OpenSSL
from bmconfigparser import BMConfigParser from .tr import _translate
from fallback import RIPEMD160Hash
from network import StoppableThread
from pyelliptic import arithmetic
from pyelliptic.openssl import OpenSSL
class addressGenerator(StoppableThread): class addressGenerator(StoppableThread):
@ -120,7 +116,7 @@ class addressGenerator(StoppableThread):
if command == 'createRandomAddress': if command == 'createRandomAddress':
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "Generating one new address") "MainWindow", "Generating one new address")
)) ))
# This next section is a little bit strange. We're going # This next section is a little bit strange. We're going
@ -199,7 +195,7 @@ class addressGenerator(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "MainWindow",
"Done generating address. Doing work necessary" "Done generating address. Doing work necessary"
" to broadcast it...") " to broadcast it...")
@ -214,9 +210,10 @@ class addressGenerator(StoppableThread):
queues.workerQueue.put(( queues.workerQueue.put((
'sendOutOrStoreMyV4Pubkey', address)) 'sendOutOrStoreMyV4Pubkey', address))
elif command == 'createDeterministicAddresses' \ elif command in (
or command == 'getDeterministicAddress' \ 'createDeterministicAddresses', 'getDeterministicAddress',
or command == 'createChan' or command == 'joinChan': 'createChan', 'joinChan'
):
if not deterministicPassphrase: if not deterministicPassphrase:
self.logger.warning( self.logger.warning(
'You are creating deterministic' 'You are creating deterministic'
@ -225,7 +222,7 @@ class addressGenerator(StoppableThread):
if command == 'createDeterministicAddresses': if command == 'createDeterministicAddresses':
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "MainWindow",
"Generating %1 new addresses." "Generating %1 new addresses."
).arg(str(numberOfAddressesToMake)) ).arg(str(numberOfAddressesToMake))
@ -248,12 +245,12 @@ class addressGenerator(StoppableThread):
while True: while True:
numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
potentialPrivSigningKey = hashlib.sha512( potentialPrivSigningKey = hashlib.sha512(
deterministicPassphrase + deterministicPassphrase
encodeVarint(signingKeyNonce) + encodeVarint(signingKeyNonce)
).digest()[:32] ).digest()[:32]
potentialPrivEncryptionKey = hashlib.sha512( potentialPrivEncryptionKey = hashlib.sha512(
deterministicPassphrase + deterministicPassphrase
encodeVarint(encryptionKeyNonce) + encodeVarint(encryptionKeyNonce)
).digest()[:32] ).digest()[:32]
potentialPubSigningKey = highlevelcrypto.pointMult( potentialPubSigningKey = highlevelcrypto.pointMult(
potentialPrivSigningKey) potentialPrivSigningKey)
@ -330,7 +327,7 @@ class addressGenerator(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "MainWindow",
"%1 is already in 'Your Identities'." "%1 is already in 'Your Identities'."
" Not adding it again." " Not adding it again."
@ -369,8 +366,8 @@ class addressGenerator(StoppableThread):
hexlify(potentialPrivEncryptionKey)) hexlify(potentialPrivEncryptionKey))
shared.myAddressesByHash[ripe] = address shared.myAddressesByHash[ripe] = address
tag = hashlib.sha512(hashlib.sha512( tag = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + ripe + encodeVarint(streamNumber) + ripe
).digest()).digest()[32:] ).digest()).digest()[32:]
shared.myAddressesByTag[tag] = address shared.myAddressesByTag[tag] = address
if addressVersionNumber == 3: if addressVersionNumber == 3:
@ -384,7 +381,7 @@ class addressGenerator(StoppableThread):
'sendOutOrStoreMyV4Pubkey', address)) 'sendOutOrStoreMyV4Pubkey', address))
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "Done generating address") "MainWindow", "Done generating address")
)) ))
elif saveAddressToDisk and not live \ elif saveAddressToDisk and not live \
@ -401,6 +398,6 @@ class addressGenerator(StoppableThread):
queues.apiAddressGeneratorReturnQueue.put(address) queues.apiAddressGeneratorReturnQueue.put(address)
else: else:
raise Exception( raise Exception(
"Error in the addressGenerator thread. Thread was" + "Error in the addressGenerator thread. Thread was"
" given a command it could not understand: " + command) + " given a command it could not understand: " + command)
queues.addressGeneratorQueue.task_done() queues.addressGeneratorQueue.task_done()

View File

@ -12,27 +12,20 @@ import time
from binascii import hexlify from binascii import hexlify
from subprocess import call # nosec from subprocess import call # nosec
import helper_bitcoin from . import (
import helper_inbox helper_bitcoin, helper_inbox, helper_msgcoding, helper_sent,
import helper_msgcoding highlevelcrypto, l10n, protocol, queues, shared, state
import helper_sent )
import highlevelcrypto from .addresses import (
import l10n
import protocol
import queues
import shared
import state
import tr
from addresses import (
calculateInventoryHash, decodeAddress, decodeVarint, calculateInventoryHash, decodeAddress, decodeVarint,
encodeAddress, encodeVarint, varintDecodeError encodeAddress, encodeVarint, varintDecodeError
) )
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from fallback import RIPEMD160Hash from .fallback import RIPEMD160Hash
from helper_sql import sql_ready, SqlBulkExecute, sqlExecute, sqlQuery from .helper_sql import sql_ready, SqlBulkExecute, sqlExecute, sqlQuery
from network import bmproto, knownnodes from .network import bmproto, knownnodes
from network.node import Peer from .network.node import Peer
# pylint: disable=too-many-locals, too-many-return-statements, too-many-branches, too-many-statements from .tr import _translate
logger = logging.getLogger('default') logger = logging.getLogger('default')
@ -150,7 +143,7 @@ class objectProcessor(threading.Thread):
'updateSentItemStatusByAckdata', 'updateSentItemStatusByAckdata',
( (
data[readPosition:], data[readPosition:],
tr._translate( _translate(
"MainWindow", "MainWindow",
"Acknowledgement of the message received %1" "Acknowledgement of the message received %1"
).arg(l10n.formatTimestamp()) ).arg(l10n.formatTimestamp())
@ -763,10 +756,10 @@ class objectProcessor(threading.Thread):
# Don't send ACK if invalid, blacklisted senders, invisible # Don't send ACK if invalid, blacklisted senders, invisible
# messages, disabled or chan # messages, disabled or chan
if ( if (
self.ackDataHasAValidHeader(ackData) and not blockMessage and self.ackDataHasAValidHeader(ackData) and not blockMessage
messageEncodingType != 0 and and messageEncodingType != 0
not BMConfigParser().safeGetBoolean(toAddress, 'dontsendack') and and not BMConfigParser().safeGetBoolean(toAddress, 'dontsendack')
not BMConfigParser().safeGetBoolean(toAddress, 'chan') and not BMConfigParser().safeGetBoolean(toAddress, 'chan')
): ):
self._ack_obj.send_data(ackData[24:]) self._ack_obj.send_data(ackData[24:])
@ -934,8 +927,8 @@ class objectProcessor(threading.Thread):
return return
elif broadcastVersion == 5: elif broadcastVersion == 5:
calculatedTag = hashlib.sha512(hashlib.sha512( calculatedTag = hashlib.sha512(hashlib.sha512(
encodeVarint(sendersAddressVersion) + encodeVarint(sendersAddressVersion)
encodeVarint(sendersStream) + calculatedRipe + encodeVarint(sendersStream) + calculatedRipe
).digest()).digest()[32:] ).digest()).digest()[32:]
if calculatedTag != embeddedTag: if calculatedTag != embeddedTag:
logger.debug( logger.debug(

View File

@ -23,13 +23,12 @@ import gc
import os import os
import time import time
import queues from . import queues, state
import state from .bmconfigparser import BMConfigParser
import tr from .helper_sql import sqlExecute, sqlQuery
from bmconfigparser import BMConfigParser from .inventory import Inventory
from helper_sql import sqlExecute, sqlQuery from .network import BMConnectionPool, knownnodes, StoppableThread
from inventory import Inventory from .tr import _translate
from network import BMConnectionPool, knownnodes, StoppableThread
#: Equals 4 weeks. You could make this longer if you want #: Equals 4 weeks. You could make this longer if you want
@ -121,7 +120,6 @@ class singleCleaner(StoppableThread):
# while writing it to disk # while writing it to disk
knownnodes.cleanupKnownNodes() knownnodes.cleanupKnownNodes()
except Exception as err: except Exception as err:
# pylint: disable=protected-access
if "Errno 28" in str(err): if "Errno 28" in str(err):
self.logger.fatal( self.logger.fatal(
'(while writing knownnodes to disk)' '(while writing knownnodes to disk)'
@ -129,8 +127,8 @@ class singleCleaner(StoppableThread):
) )
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', 'alert',
(tr._translate("MainWindow", "Disk full"), (_translate("MainWindow", "Disk full"),
tr._translate( _translate(
"MainWindow", "MainWindow",
'Alert: Your disk or data storage volume' 'Alert: Your disk or data storage volume'
' is full. Bitmessage will now exit.'), ' is full. Bitmessage will now exit.'),
@ -179,8 +177,8 @@ class singleCleaner(StoppableThread):
'Doing work necessary to again attempt to request a public key...' 'Doing work necessary to again attempt to request a public key...'
)) ))
sqlExecute( sqlExecute(
'''UPDATE sent SET status='msgqueued' WHERE toaddress=? AND folder='sent' ''', "UPDATE sent SET status='msgqueued'"
address) " WHERE toaddress=? AND folder='sent'", address)
queues.workerQueue.put(('sendmessage', '')) queues.workerQueue.put(('sendmessage', ''))
def resendMsg(self, ackdata): def resendMsg(self, ackdata):
@ -190,8 +188,8 @@ class singleCleaner(StoppableThread):
' to our msg. Sending again.' ' to our msg. Sending again.'
) )
sqlExecute( sqlExecute(
'''UPDATE sent SET status='msgqueued' WHERE ackdata=? AND folder='sent' ''', "UPDATE sent SET status='msgqueued'"
ackdata) " WHERE ackdata=? AND folder='sent'", ackdata)
queues.workerQueue.put(('sendmessage', '')) queues.workerQueue.put(('sendmessage', ''))
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',

View File

@ -1,7 +1,7 @@
""" """
Thread for performing PoW Thread for performing PoW
""" """
# pylint: disable=protected-access,too-many-branches,too-many-statements # pylint: disable=too-many-branches,too-many-statements
# pylint: disable=no-self-use,too-many-lines,too-many-locals # pylint: disable=no-self-use,too-many-lines,too-many-locals
from __future__ import division from __future__ import division
@ -12,26 +12,18 @@ from binascii import hexlify, unhexlify
from struct import pack from struct import pack
from subprocess import call # nosec from subprocess import call # nosec
import defaults from . import (
import helper_inbox defaults, helper_inbox, helper_msgcoding, helper_random, helper_sql,
import helper_msgcoding highlevelcrypto, l10n, proofofwork, protocol, queues, shared, state
import helper_random )
import helper_sql from .addresses import (
import highlevelcrypto
import l10n
import proofofwork
import protocol
import queues
import shared
import state
import tr
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 knownnodes, StoppableThread from .network import knownnodes, StoppableThread
from .tr import _translate
def sizeof_fmt(num, suffix='h/s'): def sizeof_fmt(num, suffix='h/s'):
@ -81,8 +73,8 @@ class singleWorker(StoppableThread):
state.neededPubkeys[toAddress] = 0 state.neededPubkeys[toAddress] = 0
elif toAddressVersionNumber >= 4: elif toAddressVersionNumber >= 4:
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512( doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
encodeVarint(toAddressVersionNumber) + encodeVarint(toAddressVersionNumber)
encodeVarint(toStreamNumber) + toRipe + encodeVarint(toStreamNumber) + toRipe
).digest()).digest() ).digest()).digest()
# Note that this is the first half of the sha512 hash. # Note that this is the first half of the sha512 hash.
privEncryptionKey = doubleHashOfAddressData[:32] privEncryptionKey = doubleHashOfAddressData[:32]
@ -220,11 +212,11 @@ class singleWorker(StoppableThread):
log_time=False): log_time=False):
target = 2 ** 64 / ( target = 2 ** 64 / (
defaults.networkDefaultProofOfWorkNonceTrialsPerByte * ( defaults.networkDefaultProofOfWorkNonceTrialsPerByte * (
len(payload) + 8 + len(payload) + 8
defaults.networkDefaultPayloadLengthExtraBytes + (( + defaults.networkDefaultPayloadLengthExtraBytes + ((
TTL * ( TTL * (
len(payload) + 8 + len(payload) + 8
defaults.networkDefaultPayloadLengthExtraBytes + defaults.networkDefaultPayloadLengthExtraBytes
)) / (2 ** 16)) )) / (2 ** 16))
)) ))
initialHash = hashlib.sha512(payload).digest() initialHash = hashlib.sha512(payload).digest()
@ -249,8 +241,10 @@ class singleWorker(StoppableThread):
return payload return payload
def doPOWForMyV2Pubkey(self, adressHash): def doPOWForMyV2Pubkey(self, adressHash):
""" This function also broadcasts out the pubkey """
message once it is done with the POW""" This function also broadcasts out the pubkey
message once it is done with the POW
"""
# Look up my stream number based on my address hash # Look up my stream number based on my address hash
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
# status # status
@ -306,9 +300,10 @@ class singleWorker(StoppableThread):
def sendOutOrStoreMyV3Pubkey(self, adressHash): def sendOutOrStoreMyV3Pubkey(self, adressHash):
""" """
If this isn't a chan address, this function assembles the pubkey data, does the necessary POW and sends it out. If this isn't a chan address, this function assembles the pubkey data,
If it *is* a chan then it assembles the pubkey and stores is in the pubkey table so that we can send messages does the necessary POW and sends it out. If it *is* a chan then
to "ourselves". it assembles the pubkey and stores is in the pubkey table so that
we can send messages to "ourselves".
""" """
try: try:
myAddress = shared.myAddressesByHash[adressHash] myAddress = shared.myAddressesByHash[adressHash]
@ -389,9 +384,10 @@ class singleWorker(StoppableThread):
def sendOutOrStoreMyV4Pubkey(self, myAddress): def sendOutOrStoreMyV4Pubkey(self, myAddress):
""" """
It doesn't send directly anymore. It put is to a queue for another thread to send at an appropriate time, It doesn't send directly anymore. It put is to a queue for another
whereas in the past it directly appended it to the outgoing buffer, I think. Same with all the other methods in thread to send at an appropriate time, whereas in the past it directly
this class. appended it to the outgoing buffer, I think. Same with all the other
methods in this class.
""" """
if not BMConfigParser().has_section(myAddress): if not BMConfigParser().has_section(myAddress):
# The address has been deleted. # The address has been deleted.
@ -438,8 +434,8 @@ class singleWorker(StoppableThread):
# know which pubkey object to try to decrypt # know which pubkey object to try to decrypt
# when they want to send a message. # when they want to send a message.
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512( doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + addressHash + encodeVarint(streamNumber) + addressHash
).digest()).digest() ).digest()).digest()
payload += doubleHashOfAddressData[32:] # the tag payload += doubleHashOfAddressData[32:] # the tag
signature = highlevelcrypto.sign( signature = highlevelcrypto.sign(
@ -518,7 +514,10 @@ class singleWorker(StoppableThread):
queues.invQueue.put((streamNumber, inventoryHash)) queues.invQueue.put((streamNumber, inventoryHash))
def sendBroadcast(self): def sendBroadcast(self):
"""Send a broadcast-type object (assemble the object, perform PoW and put it to the inv announcement queue)""" """
Send a broadcast-type object (assemble the object, perform PoW
and put it to the inv announcement queue)
"""
# Reset just in case # Reset just in case
sqlExecute( sqlExecute(
'''UPDATE sent SET status='broadcastqueued' ''' '''UPDATE sent SET status='broadcastqueued' '''
@ -550,7 +549,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Error! Could not find sender address" "Error! Could not find sender address"
" (your address) in the keys.dat file.")) " (your address) in the keys.dat file."))
@ -588,8 +587,8 @@ class singleWorker(StoppableThread):
payload += encodeVarint(streamNumber) payload += encodeVarint(streamNumber)
if addressVersionNumber >= 4: if addressVersionNumber >= 4:
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512( doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + ripe + encodeVarint(streamNumber) + ripe
).digest()).digest() ).digest()).digest()
tag = doubleHashOfAddressData[32:] tag = doubleHashOfAddressData[32:]
payload += tag payload += tag
@ -628,8 +627,8 @@ class singleWorker(StoppableThread):
# Internet connections and being stored on the disk of 3rd parties. # Internet connections and being stored on the disk of 3rd parties.
if addressVersionNumber <= 3: if addressVersionNumber <= 3:
privEncryptionKey = hashlib.sha512( privEncryptionKey = hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + ripe + encodeVarint(streamNumber) + ripe
).digest()[:32] ).digest()[:32]
else: else:
privEncryptionKey = doubleHashOfAddressData[:32] privEncryptionKey = doubleHashOfAddressData[:32]
@ -641,7 +640,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Doing work necessary to send broadcast...")) "Doing work necessary to send broadcast..."))
)) ))
@ -674,7 +673,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Broadcast sent on %1" "Broadcast sent on %1"
).arg(l10n.formatTimestamp())) ).arg(l10n.formatTimestamp()))
@ -689,7 +688,10 @@ class singleWorker(StoppableThread):
) )
def sendMsg(self): def sendMsg(self):
"""Send a message-type object (assemble the object, perform PoW and put it to the inv announcement queue)""" """
Send a message-type object (assemble the object, perform PoW
and put it to the inv announcement queue)
"""
# pylint: disable=too-many-nested-blocks # pylint: disable=too-many-nested-blocks
# Reset just in case # Reset just in case
sqlExecute( sqlExecute(
@ -770,8 +772,8 @@ class singleWorker(StoppableThread):
toTag = '' toTag = ''
else: else:
toTag = hashlib.sha512(hashlib.sha512( toTag = hashlib.sha512(hashlib.sha512(
encodeVarint(toAddressVersionNumber) + encodeVarint(toAddressVersionNumber)
encodeVarint(toStreamNumber) + toRipe + encodeVarint(toStreamNumber) + toRipe
).digest()).digest()[32:] ).digest()).digest()[32:]
if toaddress in state.neededPubkeys or \ if toaddress in state.neededPubkeys or \
toTag in state.neededPubkeys: toTag in state.neededPubkeys:
@ -786,7 +788,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toaddress, toaddress,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Encryption key was requested earlier.")) "Encryption key was requested earlier."))
)) ))
@ -808,7 +810,8 @@ class singleWorker(StoppableThread):
if toAddressVersionNumber >= 4: if toAddressVersionNumber >= 4:
doubleHashOfToAddressData = hashlib.sha512( doubleHashOfToAddressData = hashlib.sha512(
hashlib.sha512( hashlib.sha512(
encodeVarint(toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe encodeVarint(toAddressVersionNumber)
+ encodeVarint(toStreamNumber) + toRipe
).digest() ).digest()
).digest() ).digest()
# The first half of the sha512 hash. # The first half of the sha512 hash.
@ -859,7 +862,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toaddress, toaddress,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Sending a request for the" "Sending a request for the"
" recipient\'s encryption key.")) " recipient\'s encryption key."))
@ -884,7 +887,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Looking up the receiver\'s public key")) "Looking up the receiver\'s public key"))
)) ))
@ -942,7 +945,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Problem: Destination is a mobile" "Problem: Destination is a mobile"
" device who requests that the" " device who requests that the"
@ -973,7 +976,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Doing work necessary to send message.\n" "Doing work necessary to send message.\n"
"There is no required difficulty for" "There is no required difficulty for"
@ -1011,7 +1014,7 @@ class singleWorker(StoppableThread):
'updateSentItemStatusByAckdata', 'updateSentItemStatusByAckdata',
( (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Doing work necessary to send message.\n" "Doing work necessary to send message.\n"
"Receiver\'s required difficulty: %1" "Receiver\'s required difficulty: %1"
@ -1051,7 +1054,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Problem: The work demanded by" "Problem: The work demanded by"
" the recipient (%1 and %2) is" " the recipient (%1 and %2) is"
@ -1076,7 +1079,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Problem: You are trying to send a" "Problem: You are trying to send a"
" message to yourself or a chan but your" " message to yourself or a chan but your"
@ -1101,7 +1104,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Doing work necessary to send message.")) "Doing work necessary to send message."))
)) ))
@ -1124,7 +1127,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Error! Could not find sender address" "Error! Could not find sender address"
" (your address) in the keys.dat file.")) " (your address) in the keys.dat file."))
@ -1200,7 +1203,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Problem: The recipient\'s encryption key is" "Problem: The recipient\'s encryption key is"
" no good. Could not encrypt message. %1" " no good. Could not encrypt message. %1"
@ -1214,20 +1217,20 @@ class singleWorker(StoppableThread):
encryptedPayload += encodeVarint(toStreamNumber) + encrypted encryptedPayload += encodeVarint(toStreamNumber) + encrypted
target = 2 ** 64 / ( target = 2 ** 64 / (
requiredAverageProofOfWorkNonceTrialsPerByte * ( requiredAverageProofOfWorkNonceTrialsPerByte * (
len(encryptedPayload) + 8 + len(encryptedPayload) + 8
requiredPayloadLengthExtraBytes + (( + requiredPayloadLengthExtraBytes + ((
TTL * ( TTL * (
len(encryptedPayload) + 8 + len(encryptedPayload) + 8
requiredPayloadLengthExtraBytes + requiredPayloadLengthExtraBytes
)) / (2 ** 16)) )) / (2 ** 16))
)) ))
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: %f. Required small message difficulty: %f.',
float(requiredAverageProofOfWorkNonceTrialsPerByte) / float(requiredAverageProofOfWorkNonceTrialsPerByte)
defaults.networkDefaultProofOfWorkNonceTrialsPerByte, / defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
float(requiredPayloadLengthExtraBytes) / float(requiredPayloadLengthExtraBytes)
defaults.networkDefaultPayloadLengthExtraBytes / defaults.networkDefaultPayloadLengthExtraBytes
) )
powStartTime = time.time() powStartTime = time.time()
@ -1269,7 +1272,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Message sent. Sent at %1" "Message sent. Sent at %1"
).arg(l10n.formatTimestamp())))) ).arg(l10n.formatTimestamp()))))
@ -1278,7 +1281,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByAckdata', ( 'updateSentItemStatusByAckdata', (
ackdata, ackdata,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Message sent. Waiting for acknowledgement." "Message sent. Waiting for acknowledgement."
" Sent on %1" " Sent on %1"
@ -1369,13 +1372,13 @@ class singleWorker(StoppableThread):
# Note that this is the first half of the sha512 hash. # Note that this is the first half of the sha512 hash.
privEncryptionKey = hashlib.sha512(hashlib.sha512( privEncryptionKey = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + ripe + encodeVarint(streamNumber) + ripe
).digest()).digest()[:32] ).digest()).digest()[:32]
# Note that this is the second half of the sha512 hash. # Note that this is the second half of the sha512 hash.
tag = hashlib.sha512(hashlib.sha512( tag = hashlib.sha512(hashlib.sha512(
encodeVarint(addressVersionNumber) + encodeVarint(addressVersionNumber)
encodeVarint(streamNumber) + ripe + encodeVarint(streamNumber) + ripe
).digest()).digest()[32:] ).digest()).digest()[32:]
if tag not in state.neededPubkeys: if tag not in state.neededPubkeys:
# We'll need this for when we receive a pubkey reply: # We'll need this for when we receive a pubkey reply:
@ -1412,7 +1415,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toAddress, toAddress,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Doing work necessary to request encryption key.")) "Doing work necessary to request encryption key."))
)) ))
@ -1437,7 +1440,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', 'updateStatusBar',
tr._translate( _translate(
"MainWindow", "MainWindow",
"Broadcasting the public key request. This program will" "Broadcasting the public key request. This program will"
" auto-retry if they are offline.") " auto-retry if they are offline.")
@ -1445,7 +1448,7 @@ class singleWorker(StoppableThread):
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateSentItemStatusByToAddress', ( 'updateSentItemStatusByToAddress', (
toAddress, toAddress,
tr._translate( _translate(
"MainWindow", "MainWindow",
"Sending public key request. Waiting for reply." "Sending public key request. Waiting for reply."
" Requested at %1" " Requested at %1"

View File

@ -8,10 +8,9 @@ import urlparse
from email.header import Header from email.header import Header
from email.mime.text import MIMEText from email.mime.text import MIMEText
import queues from . import queues, state
import state from .bmconfigparser import BMConfigParser
from bmconfigparser import BMConfigParser from .network.threads import StoppableThread
from network.threads import StoppableThread
SMTPDOMAIN = "bmaddr.lan" SMTPDOMAIN = "bmaddr.lan"

View File

@ -13,13 +13,13 @@ import time
from email.header import decode_header from email.header import decode_header
from email.parser import Parser from email.parser import Parser
import queues from . import queues
from addresses import decodeAddress from .addresses import decodeAddress
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from helper_ackPayload import genAckPayload from .helper_ackPayload import genAckPayload
from helper_sql import sqlExecute from .helper_sql import sqlExecute
from network.threads import StoppableThread from .network.threads import StoppableThread
from version import softwareVersion from .version import softwareVersion
SMTPDOMAIN = "bmaddr.lan" SMTPDOMAIN = "bmaddr.lan"
LISTENPORT = 8425 LISTENPORT = 8425

View File

@ -9,28 +9,12 @@ import sys
import threading import threading
import time import time
if sys.version_info[0] == 3: from . import helper_sql, helper_startup, paths, queues, state
from . import helper_sql from .addresses import encodeAddress
from . import helper_startup from .bmconfigparser import BMConfigParser
from . import paths from .debug import logger
from . import queues from .tr import _translate
from . import state # pylint: disable=attribute-defined-outside-init
from . import tr
from .bmconfigparser import BMConfigParser
from .debug import logger
# pylint: disable=attribute-defined-outside-init,protected-access
from .addresses import encodeAddress
else:
import helper_sql
import helper_startup
import paths
import queues
import state
import tr
from bmconfigparser import BMConfigParser
from debug import logger
# pylint: disable=attribute-defined-outside-init,protected-access
from addresses import encodeAddress
class sqlThread(threading.Thread): class sqlThread(threading.Thread):
@ -450,16 +434,15 @@ class sqlThread(threading.Thread):
except Exception as err: except Exception as err:
if str(err) == 'database or disk is full': if str(err) == 'database or disk is full':
logger.fatal( logger.fatal(
'(While null value test) Alert: Your disk or data storage volume is full.' '(While null value test) Alert: Your disk or data storage'
' sqlThread will now exit.') ' volume is full. sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume is full."
tr._translate( " Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
else: else:
@ -480,16 +463,15 @@ class sqlThread(threading.Thread):
except Exception as err: except Exception as err:
if str(err) == 'database or disk is full': if str(err) == 'database or disk is full':
logger.fatal( logger.fatal(
'(While VACUUM) Alert: Your disk or data storage volume is full.' '(While VACUUM) Alert: Your disk or data storage'
' sqlThread will now exit.') ' volume is full. sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
item = '''update settings set value=? WHERE key='lastvacuumtime';''' item = '''update settings set value=? WHERE key='lastvacuumtime';'''
@ -510,12 +492,11 @@ class sqlThread(threading.Thread):
' sqlThread will now exit.') ' sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
elif item == 'exit': elif item == 'exit':
@ -535,12 +516,11 @@ class sqlThread(threading.Thread):
' sqlThread will now exit.') ' sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
self.conn.close() self.conn.close()
@ -561,12 +541,11 @@ class sqlThread(threading.Thread):
' sqlThread will now exit.') ' sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
self.conn.close() self.conn.close()
@ -588,12 +567,11 @@ class sqlThread(threading.Thread):
' sqlThread will now exit.') ' sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
else: else:
@ -609,12 +587,11 @@ class sqlThread(threading.Thread):
' sqlThread will now exit.') ' sqlThread will now exit.')
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'alert', ( 'alert', (
tr._translate( _translate("MainWindow", "Disk full"),
_translate(
"MainWindow", "MainWindow",
"Disk full"), "Alert: Your disk or data storage volume"
tr._translate( " is full. Bitmessage will now exit."),
"MainWindow",
'Alert: Your disk or data storage volume is full. Bitmessage will now exit.'),
True))) True)))
os._exit(0) os._exit(0)
else: else:

View File

@ -28,33 +28,21 @@ Use:
>>> import logging >>> import logging
>>> logger = logging.getLogger('default') >>> logger = logging.getLogger('default')
The old form: ``from debug import logger`` is also may be used, The old form: ``from .debug import logger`` is also may be used,
but only in the top level modules. but only in the top level modules.
Logging is thread-safe so you don't have to worry about locks, Logging is thread-safe so you don't have to worry about locks,
just import and log. just import and log.
""" """
# import ConfigParser
import sys
if sys.version_info[0] == 3:
# python 3
import configparser as ConfigParser
else:
# python 2
import ConfigParser
import logging import logging
import logging.config import logging.config
import os import os
import sys import sys
if sys.version_info[0] == 3: from six.moves import configparser
from . import helper_startup
from . import state from . import helper_startup, state
else:
import helper_startup
import state
helper_startup.loadConfig() helper_startup.loadConfig()
@ -86,7 +74,7 @@ def configureLogging():
False, False,
'Loaded logger configuration from %s' % logging_config 'Loaded logger configuration from %s' % logging_config
) )
except (OSError, ConfigParser.NoSectionError, KeyError): except (OSError, configparser.NoSectionError, KeyError):
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' \
@ -161,7 +149,6 @@ def resetLogging():
# ! # !
preconfigured, msg = configureLogging() preconfigured, msg = configureLogging()
logger = logging.getLogger('default') logger = logging.getLogger('default')
if msg: if msg:

View File

@ -5,9 +5,8 @@ This module is for generating ack payload
from binascii import hexlify from binascii import hexlify
from struct import pack from struct import pack
import helper_random from . import helper_random, highlevelcrypto
import highlevelcrypto from .addresses import encodeVarint
from addresses import encodeVarint
def genAckPayload(streamNumber=1, stealthLevel=0): def genAckPayload(streamNumber=1, stealthLevel=0):

View File

@ -4,8 +4,8 @@ Calculates bitcoin and testnet address from pubkey
import hashlib import hashlib
from debug import logger from .debug import logger
from pyelliptic import arithmetic from .pyelliptic import arithmetic
def calculateBitcoinAddressFromPubkey(pubkey): def calculateBitcoinAddressFromPubkey(pubkey):

View File

@ -1,7 +1,7 @@
"""Helper Inbox performs inbox messages related operations""" """Helper Inbox performs inbox messages related operations"""
import queues from . import queues
from helper_sql import sqlExecute, sqlQuery from .helper_sql import sqlExecute, sqlQuery
def insert(t): def insert(t):

View File

@ -5,10 +5,10 @@ Message encoding end decoding functions
import string import string
import zlib import zlib
import messagetypes from . import messagetypes
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from debug import logger from .debug import logger
from tr import _translate from .tr import _translate
try: try:
import msgpack import msgpack
@ -16,7 +16,7 @@ except ImportError:
try: try:
import umsgpack as msgpack import umsgpack as msgpack
except ImportError: except ImportError:
import fallback.umsgpack.umsgpack as msgpack from .fallback.umsgpack import umsgpack as msgpack
BITMESSAGE_ENCODING_IGNORE = 0 BITMESSAGE_ENCODING_IGNORE = 0
BITMESSAGE_ENCODING_TRIVIAL = 1 BITMESSAGE_ENCODING_TRIVIAL = 1
@ -103,8 +103,8 @@ class MsgDecode(object):
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 == "":
break break

View File

@ -1,12 +1,12 @@
"""Convenience functions for random operations. Not suitable for security / cryptography operations.""" """
Convenience functions for random operations.
Not suitable for security / cryptography operations.
"""
import os import os
import random import random
import sys
if sys.version_info[0] == 3: from .pyelliptic.openssl import OpenSSL
from .pyelliptic.openssl import OpenSSL
else:
from pyelliptic.openssl import OpenSSL
NoneType = type(None) NoneType = type(None)

View File

@ -3,8 +3,8 @@ Additional SQL helper for searching messages.
Used by :mod:`.bitmessageqt`. Used by :mod:`.bitmessageqt`.
""" """
from helper_sql import sqlQuery from .helper_sql import sqlQuery
from tr import _translate from .tr import _translate
def search_sql( def search_sql(

View File

@ -4,10 +4,11 @@ Insert values into sent table
import time import time
import uuid import uuid
from addresses import decodeAddress
from bmconfigparser import BMConfigParser from .addresses import decodeAddress
from helper_ackPayload import genAckPayload from .bmconfigparser import BMConfigParser
from helper_sql import sqlExecute from .helper_ackPayload import genAckPayload
from .helper_sql import sqlExecute
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments

View File

@ -10,22 +10,11 @@ import sys
import time import time
from distutils.version import StrictVersion from distutils.version import StrictVersion
import sys from . import defaults, helper_random, paths, state
if sys.version_info[0] == 3: from .bmconfigparser import BMConfigParser
from . import defaults
from . import helper_random
from . import paths
from . import state
from .bmconfigparser import BMConfigParser
else:
import defaults
import helper_random
import paths
import state
from bmconfigparser import BMConfigParser
try: try:
from plugins.plugin import get_plugin from .plugins.plugin import get_plugin
except ImportError: except ImportError:
get_plugin = None get_plugin = None
@ -180,8 +169,9 @@ def updateConfig():
# acts as a salt # acts as a salt
config.set( config.set(
'bitmessagesettings', 'identiconsuffix', ''.join( 'bitmessagesettings', 'identiconsuffix', ''.join(
helper_random.randomchoice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") helper_random.randomchoice(
for x in range(12) "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
) for x in range(12)
) )
) # a twelve character pseudo-password to salt the identicons ) # a twelve character pseudo-password to salt the identicons
@ -249,14 +239,15 @@ def updateConfig():
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte') == 0: 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte') == 0:
config.set( config.set(
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte', 'bitmessagesettings', 'maxacceptablenoncetrialsperbyte',
str(defaults.ridiculousDifficulty * str(defaults.ridiculousDifficulty
defaults.networkDefaultProofOfWorkNonceTrialsPerByte) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
) )
if config.safeGetInt('bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') == 0: if config.safeGetInt(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes') == 0:
config.set( config.set(
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes', 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes',
str(defaults.ridiculousDifficulty * str(defaults.ridiculousDifficulty
defaults.networkDefaultPayloadLengthExtraBytes) * defaults.networkDefaultPayloadLengthExtraBytes)
) )
if not config.has_option('bitmessagesettings', 'onionhostname'): if not config.has_option('bitmessagesettings', 'onionhostname'):
@ -298,8 +289,8 @@ def adjustHalfOpenConnectionsLimit():
# connections at a time. # connections at a time.
VER_THIS = StrictVersion(platform.version()) VER_THIS = StrictVersion(platform.version())
is_limited = ( is_limited = (
StrictVersion("5.1.2600") <= VER_THIS and StrictVersion("5.1.2600") <= VER_THIS
StrictVersion("6.0.6000") >= VER_THIS and StrictVersion("6.0.6000") >= VER_THIS
) )
except ValueError: except ValueError:
pass pass

View File

@ -9,10 +9,10 @@ High level cryptographic functions based on `.pyelliptic` OpenSSL bindings.
from binascii import hexlify from binascii import hexlify
import pyelliptic from . import pyelliptic
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from pyelliptic import OpenSSL from .pyelliptic import OpenSSL
from pyelliptic import arithmetic as a from .pyelliptic import arithmetic as a
def makeCryptor(privkey): def makeCryptor(privkey):

View File

@ -3,8 +3,8 @@
# TODO make this dynamic, and watch out for frozen, like with messagetypes # TODO make this dynamic, and watch out for frozen, like with messagetypes
import storage.filesystem import storage.filesystem
import storage.sqlite import storage.sqlite
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from singleton import Singleton from .singleton import Singleton
@Singleton @Singleton

View File

@ -5,7 +5,7 @@ import logging
import os import os
import time import time
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -3,21 +3,14 @@ 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 sys
if sys.version_info[0] == 3:
import queue as Queue
else:
import Queue
from collections import deque from collections import deque
if sys.version_info[0] == 3: from six.moves import queue
from . import helper_random
else: from . import helper_random
import helper_random
class MultiQueue(Queue.Queue): class MultiQueue(queue.Queue):
"""A base queue class""" """A base queue class"""
# pylint: disable=redefined-builtin,attribute-defined-outside-init # pylint: disable=redefined-builtin,attribute-defined-outside-init
defaultQueueCount = 10 defaultQueueCount = 10
@ -27,7 +20,7 @@ class MultiQueue(Queue.Queue):
self.queueCount = MultiQueue.defaultQueueCount self.queueCount = MultiQueue.defaultQueueCount
else: else:
self.queueCount = count self.queueCount = count
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, maxsize):
@ -42,7 +35,8 @@ class MultiQueue(Queue.Queue):
# Put a new item in the queue # Put a new item in the queue
def _put(self, item): def _put(self, item):
# self.queue.append(item) # self.queue.append(item)
self.queues[helper_random.randomrandrange(self.queueCount)].append((item)) self.queues[helper_random.randomrandrange(self.queueCount)].append(
(item))
# Get an item from the queue # Get an item from the queue
def _get(self): def _get(self):

View File

@ -10,11 +10,11 @@ import os
import socket import socket
import sys import sys
import defaults from . import defaults
import tr # translate from .addresses import decodeAddress
from addresses import decodeAddress from .bmconfigparser import BMConfigParser
from bmconfigparser import BMConfigParser from .debug import logger
from debug import logger from .tr import _translate
configSection = "bitmessagesettings" configSection = "bitmessagesettings"
@ -92,7 +92,7 @@ class namecoinConnection(object):
res = self.callRPC("data", ["getValue", string]) res = self.callRPC("data", ["getValue", string])
res = res["reply"] res = res["reply"]
if not res: if not res:
return (tr._translate( return (_translate(
"MainWindow", 'The name %1 was not found.' "MainWindow", 'The name %1 was not found.'
).arg(unicode(string)), None) ).arg(unicode(string)), None)
else: else:
@ -103,16 +103,16 @@ class namecoinConnection(object):
errmsg = exc.error["message"] errmsg = exc.error["message"]
else: else:
errmsg = exc.error errmsg = exc.error
return (tr._translate( return (_translate(
"MainWindow", 'The namecoin query failed (%1)' "MainWindow", 'The namecoin query failed (%1)'
).arg(unicode(errmsg)), None) ).arg(unicode(errmsg)), None)
except AssertionError: except AssertionError:
return (tr._translate( return (_translate(
"MainWindow", 'Unknown namecoin interface type: %1' "MainWindow", 'Unknown namecoin interface type: %1'
).arg(unicode(self.nmctype)), None) ).arg(unicode(self.nmctype)), None)
except Exception: except Exception:
logger.exception("Namecoin query exception") logger.exception("Namecoin query exception")
return (tr._translate( return (_translate(
"MainWindow", 'The namecoin query failed.'), None) "MainWindow", 'The namecoin query failed.'), None)
try: try:
@ -130,7 +130,7 @@ class namecoinConnection(object):
return ( return (
None, "%s <%s>" % (display_name, res) None, "%s <%s>" % (display_name, res)
) if valid else ( ) if valid else (
tr._translate( _translate(
"MainWindow", "MainWindow",
'The name %1 has no associated Bitmessage address.' 'The name %1 has no associated Bitmessage address.'
).arg(unicode(string)), None) ).arg(unicode(string)), None)
@ -159,7 +159,7 @@ class namecoinConnection(object):
versStr = "0.%d.%d.%d" % (v1, v2, v3) versStr = "0.%d.%d.%d" % (v1, v2, v3)
message = ( message = (
'success', 'success',
tr._translate( _translate(
"MainWindow", "MainWindow",
'Success! Namecoind version %1 running.').arg( 'Success! Namecoind version %1 running.').arg(
unicode(versStr))) unicode(versStr)))
@ -168,14 +168,13 @@ class namecoinConnection(object):
res = self.callRPC("data", ["status"]) res = self.callRPC("data", ["status"])
prefix = "Plugin data running" prefix = "Plugin data running"
if ("reply" in res) and res["reply"][:len(prefix)] == prefix: if ("reply" in res) and res["reply"][:len(prefix)] == prefix:
return ('success', tr._translate("MainWindow", 'Success! NMControll is up and running.')) return ('success', _translate("MainWindow", 'Success! NMControll is up and running.'))
logger.error("Unexpected nmcontrol reply: %s", res) logger.error("Unexpected nmcontrol reply: %s", res)
message = ('failed', tr._translate("MainWindow", 'Couldn\'t understand NMControl.')) message = ('failed', _translate("MainWindow", 'Couldn\'t understand NMControl.'))
else: else:
print ("Unsupported Namecoin type") sys.exit("Unsupported Namecoin type")
sys.exit(1)
return message return message
@ -183,7 +182,7 @@ class namecoinConnection(object):
logger.info("Namecoin connection test failure") logger.info("Namecoin connection test failure")
return ( return (
'failed', 'failed',
tr._translate( _translate(
"MainWindow", "The connection to namecoin failed.") "MainWindow", "The connection to namecoin failed.")
) )

View File

@ -1,16 +1,16 @@
""" """
Network subsystem packages Network subsystem packages
""" """
from addrthread import AddrThread from .addrthread import AddrThread
from announcethread import AnnounceThread from .announcethread import AnnounceThread
from connectionpool import BMConnectionPool from .connectionpool import BMConnectionPool
from dandelion import Dandelion from .dandelion import Dandelion
from downloadthread import DownloadThread from .downloadthread import DownloadThread
from invthread import InvThread from .invthread import InvThread
from networkthread import BMNetworkThread from .networkthread import BMNetworkThread
from receivequeuethread import ReceiveQueueThread from .receivequeuethread import ReceiveQueueThread
from threads import StoppableThread from .threads import StoppableThread
from uploadthread import UploadThread from .uploadthread import UploadThread
__all__ = [ __all__ = [

View File

@ -1,14 +1,14 @@
""" """
Announce addresses as they are received from other hosts Announce addresses as they are received from other hosts
""" """
import Queue from six.moves import queue
import state from pybitmessage import state
from helper_random import randomshuffle from pybitmessage.helper_random import randomshuffle
from network.assemble import assemble_addr from pybitmessage.queues import addrQueue
from network.connectionpool import BMConnectionPool from .assemble import assemble_addr
from queues import addrQueue from .connectionpool import BMConnectionPool
from threads import StoppableThread from .threads import StoppableThread
class AddrThread(StoppableThread): class AddrThread(StoppableThread):
@ -22,7 +22,7 @@ class AddrThread(StoppableThread):
try: try:
data = addrQueue.get(False) data = addrQueue.get(False)
chunk.append(data) chunk.append(data)
except Queue.Empty: except queue.Empty:
break break
if chunk: if chunk:

View File

@ -5,9 +5,9 @@ import socket
import threading import threading
import time import time
import network.asyncore_pollchoose as asyncore from pybitmessage import state
import state from . import asyncore_pollchoose as asyncore
from threads import BusyError, nonBlocking from .threads import BusyError, nonBlocking
class ProcessingError(Exception): class ProcessingError(Exception):

View File

@ -3,12 +3,12 @@ Announce myself (node address)
""" """
import time import time
import state from pybitmessage import state
from bmconfigparser import BMConfigParser from pybitmessage.bmconfigparser import BMConfigParser
from network.assemble import assemble_addr from .assemble import assemble_addr
from network.connectionpool import BMConnectionPool from .connectionpool import BMConnectionPool
from node import Peer from .node import Peer
from threads import StoppableThread from .threads import StoppableThread
class AnnounceThread(StoppableThread): class AnnounceThread(StoppableThread):

View File

@ -3,10 +3,10 @@ Create bitmessage protocol command packets
""" """
import struct import struct
import addresses from pybitmessage import addresses
from network.constants import MAX_ADDR_COUNT from pybitmessage.protocol import CreatePacket, encodeHost
from network.node import Peer from .constants import MAX_ADDR_COUNT
from protocol import CreatePacket, encodeHost from .node import Peer
def assemble_addr(peerList): def assemble_addr(peerList):

View File

@ -19,7 +19,7 @@ from errno import (
) )
from threading import current_thread from threading import current_thread
import helper_random from pybitmessage import helper_random
try: try:
from errno import WSAEWOULDBLOCK from errno import WSAEWOULDBLOCK

View File

@ -4,11 +4,10 @@ BMObject and it's exceptions.
import logging import logging
import time import time
import protocol from pybitmessage import protocol, state
import state from pybitmessage.addresses import calculateInventoryHash
from addresses import calculateInventoryHash from pybitmessage.inventory import Inventory
from inventory import Inventory from .dandelion import Dandelion
from network.dandelion import Dandelion
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -10,29 +10,26 @@ import struct
import time import time
from binascii import hexlify from binascii import hexlify
import addresses from pybitmessage import addresses, protocol, state
import connectionpool from pybitmessage.bmconfigparser import BMConfigParser
import knownnodes from pybitmessage.inventory import Inventory
import protocol from pybitmessage.queues import invQueue, objectProcessorQueue, portCheckerQueue
import state from . import connectionpool, knownnodes
from bmconfigparser import BMConfigParser from .advanceddispatcher import AdvancedDispatcher
from inventory import Inventory from .bmobject import (
from network.advanceddispatcher import AdvancedDispatcher
from network.bmobject import (
BMObject, BMObjectAlreadyHaveError, BMObjectExpiredError, BMObject, BMObjectAlreadyHaveError, BMObjectExpiredError,
BMObjectInsufficientPOWError, BMObjectInvalidDataError, BMObjectInsufficientPOWError, BMObjectInvalidDataError,
BMObjectInvalidError, BMObjectUnwantedStreamError BMObjectInvalidError, BMObjectUnwantedStreamError
) )
from network.constants import ( from .constants import (
ADDRESS_ALIVE, MAX_MESSAGE_SIZE, MAX_OBJECT_COUNT, ADDRESS_ALIVE, MAX_MESSAGE_SIZE, MAX_OBJECT_COUNT,
MAX_OBJECT_PAYLOAD_SIZE, MAX_TIME_OFFSET MAX_OBJECT_PAYLOAD_SIZE, MAX_TIME_OFFSET
) )
from network.dandelion import Dandelion from .dandelion import Dandelion
from network.proxy import ProxyError from .proxy import ProxyError
from node import Node, Peer from .node import Node, Peer
from objectracker import ObjectTracker, missingObjects from .objectracker import ObjectTracker, missingObjects
from queues import invQueue, objectProcessorQueue, portCheckerQueue from .randomtrackingdict import RandomTrackingDict
from randomtrackingdict import RandomTrackingDict
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -5,11 +5,10 @@ Select which node to connect to
import logging import logging
import random # nosec import random # nosec
import knownnodes from pybitmessage import protocol, state
import protocol from pybitmessage.bmconfigparser import BMConfigParser
import state from pybitmessage.queues import queue, portCheckerQueue
from bmconfigparser import BMConfigParser from .knownnodes import knownNodes
from queues import Queue, portCheckerQueue
logger = logging.getLogger('default') logger = logging.getLogger('default')
@ -37,16 +36,16 @@ def chooseConnection(stream):
retval = portCheckerQueue.get(False) retval = portCheckerQueue.get(False)
portCheckerQueue.task_done() portCheckerQueue.task_done()
return retval return retval
except Queue.Empty: except queue.Empty:
pass pass
# with a probability of 0.5, connect to a discovered peer # with a probability of 0.5, connect to a discovered peer
if random.choice((False, True)) and not haveOnion: if random.choice((False, True)) and not haveOnion:
# 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(knownNodes[stream].keys())
try: try:
peer_info = knownnodes.knownNodes[stream][peer] peer_info = knownNodes[stream][peer]
if peer_info.get('self'): if peer_info.get('self'):
continue continue
rating = peer_info["rating"] rating = peer_info["rating"]

View File

@ -9,15 +9,13 @@ import sys
import time import time
import asyncore_pollchoose as asyncore import asyncore_pollchoose as asyncore
import helper_random
import knownnodes import knownnodes
import protocol from pybitmessage import helper_random, protocol, state
import state from pybitmessage.bmconfigparser import BMConfigParser
from bmconfigparser import BMConfigParser from pybitmessage.singleton import Singleton
from connectionchooser import chooseConnection from connectionchooser import chooseConnection
from node import Peer from node import Peer
from proxy import Proxy from proxy import Proxy
from singleton import Singleton
from tcp import ( from tcp import (
bootstrap, Socks4aBMConnection, Socks5BMConnection, bootstrap, Socks4aBMConnection, Socks5BMConnection,
TCPConnection, TCPServer) TCPConnection, TCPServer)

View File

@ -7,10 +7,10 @@ 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 pybitmessage import state
import state from pybitmessage.queues import invQueue
from queues import invQueue from pybitmessage.singleton import Singleton
from singleton import Singleton from .connectionpool import BMConnectionPool
# randomise routes after 600 seconds # randomise routes after 600 seconds
REASSIGN_INTERVAL = 600 REASSIGN_INTERVAL = 600
@ -185,12 +185,10 @@ class Dandelion: # pylint: disable=old-style-class
try: try:
# random two connections # random two connections
self.stem = sample( self.stem = sample(
connectionpool.BMConnectionPool( 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 = BMConnectionPool().outboundConnections.values()
).outboundConnections.values()
self.nodeMap = {} self.nodeMap = {}
# hashMap stays to cater for pending stems # hashMap stays to cater for pending stems
self.refresh = time() + REASSIGN_INTERVAL self.refresh = time() + REASSIGN_INTERVAL

View File

@ -3,14 +3,12 @@
""" """
import time import time
import addresses from pybitmessage import addresses, helper_random, protocol
import helper_random from pybitmessage.inventory import Inventory
import protocol from .connectionpool import BMConnectionPool
from dandelion import Dandelion from .dandelion import Dandelion
from inventory import Inventory from .objectracker import missingObjects
from network.connectionpool import BMConnectionPool from .threads import StoppableThread
from objectracker import missingObjects
from threads import StoppableThread
class DownloadThread(StoppableThread): class DownloadThread(StoppableThread):

View File

@ -1,17 +1,17 @@
""" """
Thread to send inv annoucements Thread to send inv annoucements
""" """
import Queue
import random import random
from time import time from time import time
import addresses from six.moves import queue
import protocol
import state from pybitmessage import addresses, protocol, state
from network.connectionpool import BMConnectionPool from pybitmessage.queues import invQueue
from network.dandelion import Dandelion from .connectionpool import BMConnectionPool
from queues import invQueue from .dandelion import Dandelion
from threads import StoppableThread from .threads import StoppableThread
def handleExpiredDandelion(expired): def handleExpiredDandelion(expired):
@ -59,7 +59,7 @@ class InvThread(StoppableThread):
# locally generated # locally generated
if len(data) == 2 or data[2] is None: if len(data) == 2 or data[2] is None:
self.handleLocallyGenerated(data[0], data[1]) self.handleLocallyGenerated(data[0], data[1])
except Queue.Empty: except queue.Empty:
break break
if chunk: if chunk:

View File

@ -15,9 +15,9 @@ try:
except ImportError: except ImportError:
from collections import Iterable from collections import Iterable
import state from pybitmessage import state
from bmconfigparser import BMConfigParser from pybitmessage.bmconfigparser import BMConfigParser
from network.node import Peer from .node import Peer
state.Peer = Peer state.Peer = Peer

View File

@ -1,11 +1,12 @@
""" """
A thread to handle network concerns A thread to handle network concerns
""" """
import network.asyncore_pollchoose as asyncore
import state from pybitmessage import state
from network.connectionpool import BMConnectionPool from pybitmessage.queues import excQueue
from queues import excQueue from . import asyncore_pollchoose as asyncore
from threads import StoppableThread from .connectionpool import BMConnectionPool
from .threads import StoppableThread
class BMNetworkThread(StoppableThread): class BMNetworkThread(StoppableThread):

View File

@ -4,9 +4,9 @@ Module for tracking objects
import time import time
from threading import RLock from threading import RLock
import network.connectionpool from .connectionpool import BMConnectionPool
from network.dandelion import Dandelion from .dandelion import Dandelion
from randomtrackingdict import RandomTrackingDict from .randomtrackingdict import RandomTrackingDict
haveBloom = False haveBloom = False
@ -100,15 +100,15 @@ class ObjectTracker(object):
def handleReceivedObject(self, streamNumber, hashid): def handleReceivedObject(self, streamNumber, hashid):
"""Handling received object""" """Handling received object"""
for i in network.connectionpool.BMConnectionPool().connections(): for i in BMConnectionPool().connections():
if not i.fullyEstablished: if not i.fullyEstablished:
continue continue
try: try:
del i.objectsNewToMe[hashid] del i.objectsNewToMe[hashid]
except KeyError: except KeyError:
if streamNumber in i.streams and ( if streamNumber in i.streams and (
not Dandelion().hasHash(hashid) or not Dandelion().hasHash(hashid)
Dandelion().objectChildStem(hashid) == i): or Dandelion().objectChildStem(hashid) == i):
with i.objectsNewToThemLock: with i.objectsNewToThemLock:
i.objectsNewToThem[hashid] = time.time() i.objectsNewToThem[hashid] = time.time()
# update stream number, # update stream number,

View File

@ -6,10 +6,10 @@ import logging
import socket import socket
import time import time
import asyncore_pollchoose as asyncore from pybitmessage.bmconfigparser import BMConfigParser
from advanceddispatcher import AdvancedDispatcher from . import asyncore_pollchoose as asyncore
from bmconfigparser import BMConfigParser from .advanceddispatcher import AdvancedDispatcher
from node import Peer from .node import Peer
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -2,14 +2,15 @@
Process data incoming from network Process data incoming from network
""" """
import errno import errno
import Queue
import socket import socket
import state from six.moves import queue
from network.advanceddispatcher import UnknownStateError
from network.connectionpool import BMConnectionPool from pybitmessage import state
from queues import receiveDataQueue from pybitmessage.queues import receiveDataQueue
from threads import StoppableThread from .advanceddispatcher import UnknownStateError
from .connectionpool import BMConnectionPool
from .threads import StoppableThread
class ReceiveQueueThread(StoppableThread): class ReceiveQueueThread(StoppableThread):
@ -22,7 +23,7 @@ class ReceiveQueueThread(StoppableThread):
while not self._stopped and state.shutdown == 0: while not self._stopped and state.shutdown == 0:
try: try:
dest = receiveDataQueue.get(block=True, timeout=1) dest = receiveDataQueue.get(block=True, timeout=1)
except Queue.Empty: except queue.Empty:
continue continue
if self._stopped or state.shutdown: if self._stopped or state.shutdown:

View File

@ -6,7 +6,7 @@ import logging
import socket import socket
import struct import struct
from proxy import GeneralProxyError, Proxy, ProxyError from .proxy import GeneralProxyError, Proxy, ProxyError
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -7,8 +7,8 @@ import logging
import socket import socket
import struct import struct
from node import Peer from .node import Peer
from proxy import GeneralProxyError, Proxy, ProxyError from .proxy import GeneralProxyError, Proxy, ProxyError
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -3,9 +3,9 @@ Network statistics
""" """
import time import time
import asyncore_pollchoose as asyncore from . import asyncore_pollchoose as asyncore
from network.connectionpool import BMConnectionPool from .connectionpool import BMConnectionPool
from objectracker import missingObjects from .objectracker import missingObjects
lastReceivedTimestamp = time.time() lastReceivedTimestamp = time.time()

View File

@ -2,35 +2,32 @@
TCP protocol handler TCP protocol handler
""" """
# pylint: disable=too-many-ancestors # pylint: disable=too-many-ancestors
import l10n
import logging import logging
import math import math
import random import random
import socket import socket
import time import time
import addresses from pybitmessage import addresses, helper_random, l10n, protocol, state
import asyncore_pollchoose as asyncore from pybitmessage.bmconfigparser import BMConfigParser
import connectionpool from pybitmessage.helper_random import randomBytes
import helper_random from pybitmessage.inventory import Inventory
import knownnodes from pybitmessage.queues import invQueue, receiveDataQueue, UISignalQueue
import protocol from pybitmessage.tr import _translate
import state from . import asyncore_pollchoose as asyncore
from bmconfigparser import BMConfigParser from . import connectionpool, knownnodes
from helper_random import randomBytes from .advanceddispatcher import AdvancedDispatcher
from inventory import Inventory from .assemble import assemble_addr
from network.advanceddispatcher import AdvancedDispatcher from .bmproto import BMProto
from network.assemble import assemble_addr from .constants import MAX_OBJECT_COUNT
from network.bmproto import BMProto from .dandelion import Dandelion
from network.constants import MAX_OBJECT_COUNT from .objectracker import ObjectTracker
from network.dandelion import Dandelion from .socks4a import Socks4aConnection
from network.objectracker import ObjectTracker from .socks5 import Socks5Connection
from network.socks4a import Socks4aConnection from .tls import TLSDispatcher
from network.socks5 import Socks5Connection from .node import Peer
from network.tls import TLSDispatcher
from node import Peer
from queues import invQueue, receiveDataQueue, UISignalQueue
from tr import _translate
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -7,10 +7,10 @@ import socket
import ssl import ssl
import sys import sys
import network.asyncore_pollchoose as asyncore from pybitmessage import paths
import paths from pybitmessage.queues import receiveDataQueue
from network.advanceddispatcher import AdvancedDispatcher from . import asyncore_pollchoose as asyncore
from queues import receiveDataQueue from .advanceddispatcher import AdvancedDispatcher
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -5,13 +5,13 @@ import logging
import socket import socket
import time import time
import protocol from pybitmessage import protocol, state
import state from pybitmessage.queues import receiveDataQueue
from bmproto import BMProto from .bmproto import BMProto
from constants import MAX_TIME_OFFSET from .constants import MAX_TIME_OFFSET
from node import Peer from .node import Peer
from objectracker import ObjectTracker from .objectracker import ObjectTracker
from queues import receiveDataQueue
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -3,13 +3,12 @@
""" """
import time import time
import helper_random from pybitmessage import helper_random, protocol
import protocol from pybitmessage.inventory import Inventory
from inventory import Inventory from .connectionpool import BMConnectionPool
from network.connectionpool import BMConnectionPool from .dandelion import Dandelion
from network.dandelion import Dandelion from .randomtrackingdict import RandomTrackingDict
from randomtrackingdict import RandomTrackingDict from .threads import StoppableThread
from threads import StoppableThread
class UploadThread(StoppableThread): class UploadThread(StoppableThread):

View File

@ -5,9 +5,9 @@ import logging
import os import os
from struct import pack from struct import pack
import paths from . import paths
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from state import shutdown from .state import shutdown
try: try:
import numpy import numpy

View File

@ -11,13 +11,10 @@ import time
from struct import pack, unpack from struct import pack, unpack
from subprocess import call from subprocess import call
import openclpow from . import openclpow, paths, queues, state
import paths from .bmconfigparser import BMConfigParser
import queues from .debug import logger
import state from .tr import _translate
import tr
from bmconfigparser import BMConfigParser
from debug import logger
bitmsglib = 'bitmsghash.so' bitmsglib = 'bitmsghash.so'
bmpow = None bmpow = None
@ -34,8 +31,10 @@ def _set_idle():
import win32process import win32process
import win32con import win32con
pid = win32api.GetCurrentProcessId() pid = win32api.GetCurrentProcessId()
handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) handle = win32api.OpenProcess(
win32process.SetPriorityClass(handle, win32process.IDLE_PRIORITY_CLASS) win32con.PROCESS_ALL_ACCESS, True, pid)
win32process.SetPriorityClass(
handle, win32process.IDLE_PRIORITY_CLASS)
except: except:
# Windows 64-bit # Windows 64-bit
pass pass
@ -82,7 +81,8 @@ def _doFastPoW(target, initialHash):
pool = Pool(processes=pool_size) pool = Pool(processes=pool_size)
result = [] result = []
for i in range(pool_size): for i in range(pool_size):
result.append(pool.apply_async(_pool_worker, args=(i, initialHash, target, pool_size))) result.append(pool.apply_async(
_pool_worker, args=(i, initialHash, target, pool_size)))
while True: while True:
if state.shutdown > 0: if state.shutdown > 0:
@ -115,35 +115,39 @@ def _doCPoW(target, initialHash):
out_m = ctypes.c_ulonglong(m) 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])
if state.shutdown != 0: if state.shutdown != 0:
raise StopIteration("Interrupted") raise StopIteration("Interrupted")
logger.debug("C PoW done") logger.debug("C PoW done")
return [trialValue, nonce] return trialValue, nonce
def _doGPUPoW(target, initialHash): def _doGPUPoW(target, initialHash):
logger.debug("GPU PoW start") logger.debug("GPU PoW start")
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target) nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
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])
if trialValue > target: if trialValue > target:
deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus) deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus)
queues.UISignalQueue.put(( queues.UISignalQueue.put((
'updateStatusBar', ( 'updateStatusBar', (
tr._translate( _translate(
"MainWindow", "MainWindow",
'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.' "Your GPU(s) did not calculate correctly, disabling OpenCL."
), " Please report to the developers."), 1)
1))) ))
logger.error( logger.error(
"Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.", 'Your GPUs (%s) did not calculate correctly, disabling OpenCL.'
deviceNames) ' Please report to the developers.', deviceNames)
openclpow.enabledGpus = [] openclpow.enabledGpus = []
raise Exception("GPU did not calculate correctly.") raise Exception("GPU did not calculate correctly.")
if state.shutdown != 0: if state.shutdown != 0:
raise StopIteration("Interrupted") raise StopIteration("Interrupted")
logger.debug("GPU PoW done") logger.debug("GPU PoW done")
return [trialValue, nonce] return trialValue, nonce
def estimate(difficulty, format=False): # pylint: disable=redefined-builtin def estimate(difficulty, format=False): # pylint: disable=redefined-builtin
@ -189,26 +193,30 @@ def getPowType():
def notifyBuild(tried=False): def notifyBuild(tried=False):
"""Notify the user of the success or otherwise of building the PoW C module""" """
Notify the user of the success or otherwise of building the PoW C module
"""
if bmpow: if bmpow:
queues.UISignalQueue.put(('updateStatusBar', (tr._translate( queues.UISignalQueue.put((
"proofofwork", "C PoW module built successfully."), 1))) 'updateStatusBar', (
_translate("proofofwork", "C PoW module built successfully."),
1)
))
elif tried: elif tried:
queues.UISignalQueue.put( queues.UISignalQueue.put((
( 'updateStatusBar', (
'updateStatusBar', ( _translate(
tr._translate( "proofofwork",
"proofofwork", "Failed to build C PoW module. Please build it manually."),
"Failed to build C PoW module. Please build it manually." 1)
), ))
1
)
)
)
else: else:
queues.UISignalQueue.put(('updateStatusBar', (tr._translate( queues.UISignalQueue.put((
"proofofwork", "C PoW module unavailable. Please build it."), 1))) 'updateStatusBar', (
_translate(
"proofofwork", "C PoW module unavailable. Please build it."
), 1)
))
def buildCPoW(): def buildCPoW():
@ -224,11 +232,15 @@ def buildCPoW():
try: try:
if "bsd" in sys.platform: if "bsd" in sys.platform:
# BSD make # BSD make
call(["make", "-C", os.path.join(paths.codePath(), "bitmsghash"), '-f', 'Makefile.bsd']) call([
"make", "-C", os.path.join(paths.codePath(), "bitmsghash"),
'-f', 'Makefile.bsd'
])
else: else:
# GNU make # GNU make
call(["make", "-C", os.path.join(paths.codePath(), "bitmsghash")]) call(["make", "-C", os.path.join(paths.codePath(), "bitmsghash")])
if os.path.exists(os.path.join(paths.codePath(), "bitmsghash", "bitmsghash.so")): if os.path.exists(
os.path.join(paths.codePath(), "bitmsghash", "bitmsghash.so")):
init() init()
notifyBuild(True) notifyBuild(True)
else: else:
@ -298,7 +310,8 @@ def init():
bitmsglib = 'bitmsghash64.dll' bitmsglib = 'bitmsghash64.dll'
try: try:
# MSVS # MSVS
bso = ctypes.WinDLL(os.path.join(paths.codePath(), "bitmsghash", bitmsglib)) bso = ctypes.WinDLL(
os.path.join(paths.codePath(), "bitmsghash", bitmsglib))
logger.info("Loaded C PoW DLL (stdcall) %s", bitmsglib) logger.info("Loaded C PoW DLL (stdcall) %s", bitmsglib)
bmpow = bso.BitmessagePOW bmpow = bso.BitmessagePOW
bmpow.restype = ctypes.c_ulonglong bmpow.restype = ctypes.c_ulonglong
@ -307,21 +320,24 @@ def init():
except ValueError: except ValueError:
try: try:
# MinGW # MinGW
bso = ctypes.CDLL(os.path.join(paths.codePath(), "bitmsghash", bitmsglib)) bso = ctypes.CDLL(
os.path.join(paths.codePath(), "bitmsghash", bitmsglib))
logger.info("Loaded C PoW DLL (cdecl) %s", bitmsglib) logger.info("Loaded C PoW DLL (cdecl) %s", bitmsglib)
bmpow = bso.BitmessagePOW bmpow = bso.BitmessagePOW
bmpow.restype = ctypes.c_ulonglong bmpow.restype = ctypes.c_ulonglong
_doCPoW(2**63, "") _doCPoW(2**63, "")
logger.info("Successfully tested C PoW DLL (cdecl) %s", bitmsglib) logger.info(
except Exception as e: "Successfully tested C PoW DLL (cdecl) %s", bitmsglib)
logger.error("Error: %s", e, exc_info=True) except Exception:
logger.error("C PoW test fail.", exc_info=True)
bso = None bso = None
except Exception as e: except Exception as e:
logger.error("Error: %s", e, exc_info=True) logger.error("Error: %s", e, exc_info=True)
bso = None bso = None
else: else:
try: try:
bso = ctypes.CDLL(os.path.join(paths.codePath(), "bitmsghash", bitmsglib)) bso = ctypes.CDLL(
os.path.join(paths.codePath(), "bitmsghash", bitmsglib))
except OSError: except OSError:
import glob import glob
try: try:

View File

@ -13,16 +13,14 @@ import time
from binascii import hexlify from binascii import hexlify
from struct import Struct, pack, unpack from struct import Struct, pack, unpack
import defaults from . import defaults, highlevelcrypto, state
import highlevelcrypto from .addresses import (
import state
from addresses import (
encodeVarint, decodeVarint, decodeAddress, varintDecodeError) encodeVarint, decodeVarint, decodeAddress, varintDecodeError)
from bmconfigparser import BMConfigParser from .bmconfigparser import BMConfigParser
from debug import logger from .debug import logger
from fallback import RIPEMD160Hash from .fallback import RIPEMD160Hash
from helper_sql import sqlExecute from .helper_sql import sqlExecute
from version import softwareVersion from .version import softwareVersion
# Service flags # Service flags
#: This is a normal network node #: This is a normal network node

View File

@ -2,24 +2,19 @@
import threading import threading
import time import time
try:
import queue as Queue
except ImportError:
import Queue
try: from six.moves import queue
from multiqueue import MultiQueue
except ImportError: from .multiqueue import MultiQueue
from .multiqueue import MultiQueue
class ObjectProcessorQueue(Queue.Queue): class ObjectProcessorQueue(queue.Queue):
"""Special queue class using lock for `.threads.objectProcessor`""" """Special queue class using lock for `.threads.objectProcessor`"""
maxSize = 32000000 maxSize = 32000000
def __init__(self): def __init__(self):
Queue.Queue.__init__(self) queue.Queue.__init__(self)
self.sizeLock = threading.Lock() self.sizeLock = threading.Lock()
#: in Bytes. We maintain this to prevent nodes from flooding us #: in Bytes. We maintain this to prevent nodes from flooding us
#: with objects which take up too much memory. If this gets #: with objects which take up too much memory. If this gets
@ -31,27 +26,27 @@ class ObjectProcessorQueue(Queue.Queue):
time.sleep(1) time.sleep(1)
with self.sizeLock: with self.sizeLock:
self.curSize += len(item[1]) self.curSize += len(item[1])
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):
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])
return item return item
workerQueue = Queue.Queue() workerQueue = queue.Queue()
UISignalQueue = Queue.Queue() UISignalQueue = queue.Queue()
addressGeneratorQueue = Queue.Queue() addressGeneratorQueue = queue.Queue()
#: `.network.ReceiveQueueThread` instances dump objects they hear #: `.network.ReceiveQueueThread` instances dump objects they hear
#: on the network into this queue to be processed. #: on the network into this queue to be processed.
objectProcessorQueue = ObjectProcessorQueue() objectProcessorQueue = ObjectProcessorQueue()
invQueue = MultiQueue() invQueue = MultiQueue()
addrQueue = MultiQueue() addrQueue = MultiQueue()
portCheckerQueue = Queue.Queue() portCheckerQueue = queue.Queue()
receiveDataQueue = Queue.Queue() receiveDataQueue = queue.Queue()
#: The address generator thread uses this queue to get information back #: The address generator thread uses this queue to get information back
#: to the API thread. #: to the API thread.
apiAddressGeneratorReturnQueue = Queue.Queue() apiAddressGeneratorReturnQueue = queue.Queue()
#: for exceptions #: for exceptions
excQueue = Queue.Queue() excQueue = queue.Queue()

View File

@ -4,7 +4,7 @@ Track randomize ordered dict
from threading import RLock from threading import RLock
from time import time from time import time
import helper_random from . import helper_random
class RandomTrackingDict(object): class RandomTrackingDict(object):

View File

@ -16,14 +16,12 @@ import sys
from binascii import hexlify from binascii import hexlify
# Project imports. # Project imports.
import highlevelcrypto from . import highlevelcrypto, state
import state from .addresses import decodeAddress, encodeVarint
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
myECCryptorObjects = {} myECCryptorObjects = {}

View File

@ -4,13 +4,13 @@ import Queue
import threading import threading
import time import time
import state from . import state
from debug import logger from .debug import logger
from helper_sql import sqlQuery, sqlStoredProcedure from .helper_sql import sqlQuery, sqlStoredProcedure
from inventory import Inventory from .inventory import Inventory
from network import StoppableThread from .network import StoppableThread
from network.knownnodes import saveKnownNodes from .network.knownnodes import saveKnownNodes
from queues import ( from .queues import (
addressGeneratorQueue, objectProcessorQueue, UISignalQueue, workerQueue) addressGeneratorQueue, objectProcessorQueue, UISignalQueue, workerQueue)

View File

@ -8,7 +8,7 @@ import atexit
import os import os
import sys import sys
import state from . import state
try: try:
import fcntl # @UnresolvedImport import fcntl # @UnresolvedImport

View File

@ -8,7 +8,7 @@ from binascii import hexlify, unhexlify
from os import listdir, makedirs, path, remove, rmdir from os import listdir, makedirs, path, remove, rmdir
from threading import RLock from threading import RLock
from paths import lookupAppdataFolder from pybitmessage.paths import lookupAppdataFolder
from storage import InventoryItem, InventoryStorage from storage import InventoryItem, InventoryStorage
logger = logging.getLogger('default') logger = logging.getLogger('default')

View File

@ -5,7 +5,8 @@ import sqlite3
import time import time
from threading import RLock from threading import RLock
from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery
from pybitmessage.helper_sql import SqlBulkExecute, sqlExecute, sqlQuery
from storage import InventoryItem, InventoryStorage from storage import InventoryItem, InventoryStorage

View File

@ -15,11 +15,11 @@ There are also other threads in the `.network` package.
import threading import threading
from class_addressGenerator import addressGenerator from .class_addressGenerator import addressGenerator
from class_objectProcessor import objectProcessor from .class_objectProcessor import objectProcessor
from class_singleCleaner import singleCleaner from .class_singleCleaner import singleCleaner
from class_singleWorker import singleWorker from .class_singleWorker import singleWorker
from class_sqlThread import sqlThread from .class_sqlThread import sqlThread
try: try:
import prctl import prctl

View File

@ -3,11 +3,7 @@ Translating text
""" """
import os import os
import sys from . import state
if sys.version_info[0] == 3:
from . import state
else:
import state
class translateClass: class translateClass:

View File

@ -1,4 +1,4 @@
# pylint: disable=too-many-statements,too-many-branches,protected-access,no-self-use # pylint: disable=too-many-statements,too-many-branches,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
@ -12,13 +12,12 @@ from random import randint
from urlparse import urlparse from urlparse import urlparse
from xml.dom.minidom import Document, parseString from xml.dom.minidom import Document, parseString
import queues from . import queues, state
import state from .bmconfigparser import BMConfigParser
import tr from .debug import logger
from bmconfigparser import BMConfigParser from .network import BMConnectionPool, knownnodes, StoppableThread
from debug import logger from .network.node import Peer
from network import BMConnectionPool, knownnodes, StoppableThread from .tr import _translate
from network.node import Peer
def createRequestXML(service, action, arguments=None): def createRequestXML(service, action, arguments=None):
@ -269,14 +268,19 @@ class uPnPThread(StoppableThread):
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((
"MainWindow", 'UPnP port mapping established on port %1' 'updateStatusBar',
).arg(str(self.extPort)))) _translate(
"MainWindow",
"UPnP port mapping established on port %1"
).arg(str(self.extPort))
))
break break
except socket.timeout: except socket.timeout:
pass pass
except: except:
logger.error("Failure running UPnP router search.", exc_info=True) logger.error(
'Failure running UPnP router search.', exc_info=True)
for router in self.routers: for router in self.routers:
if router.extPort is None: if router.extPort is None:
self.createPortMapping(router) self.createPortMapping(router)
@ -294,7 +298,10 @@ 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',
_translate("MainWindow", "UPnP port mapping removed")
))
logger.debug("UPnP thread done") logger.debug("UPnP thread done")
def getLocalIP(self): def getLocalIP(self):