Changes based on style and lint checks. (final_code_quality_7)
This commit is contained in:
parent
ea38e91839
commit
0a30eb0225
|
@ -1,17 +1,22 @@
|
|||
"""
|
||||
src/bitmessageqt/messageview.py
|
||||
===============================
|
||||
|
||||
"""
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
import multiprocessing
|
||||
import Queue
|
||||
from urlparse import urlparse
|
||||
from safehtmlparser import *
|
||||
from safehtmlparser import SafeHTMLParser
|
||||
|
||||
|
||||
class MessageView(QtGui.QTextBrowser):
|
||||
"""Message content viewer class, can switch between plaintext and HTML"""
|
||||
MODE_PLAIN = 0
|
||||
MODE_HTML = 1
|
||||
|
||||
def __init__(self, parent = 0):
|
||||
|
||||
def __init__(self, parent=0):
|
||||
super(MessageView, self).__init__(parent)
|
||||
self.mode = MessageView.MODE_PLAIN
|
||||
self.mode = MessageView.MODE_PLAIN
|
||||
self.html = None
|
||||
self.setOpenExternalLinks(False)
|
||||
self.setOpenLinks(False)
|
||||
|
@ -25,12 +30,14 @@ class MessageView(QtGui.QTextBrowser):
|
|||
self.setWrappingWidth()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
"""View resize event handler"""
|
||||
super(MessageView, self).resizeEvent(event)
|
||||
self.setWrappingWidth(event.size().width())
|
||||
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
#text = textCursor.block().text()
|
||||
if event.button() == QtCore.Qt.LeftButton and self.html and self.html.has_html and self.cursorForPosition(event.pos()).block().blockNumber() == 0:
|
||||
"""Mouse press button event handler"""
|
||||
if 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:
|
||||
self.showHTML()
|
||||
else:
|
||||
|
@ -39,19 +46,24 @@ class MessageView(QtGui.QTextBrowser):
|
|||
super(MessageView, self).mousePressEvent(event)
|
||||
|
||||
def wheelEvent(self, event):
|
||||
"""Mouse wheel scroll event handler"""
|
||||
# super will actually automatically take care of zooming
|
||||
super(MessageView, self).wheelEvent(event)
|
||||
if (QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical:
|
||||
if (QtGui.QApplication.queryKeyboardModifiers() &
|
||||
QtCore.Qt.ControlModifier) == QtCore.Qt.ControlModifier and event.orientation() == QtCore.Qt.Vertical:
|
||||
zoom = self.currentFont().pointSize() * 100 / self.defaultFontPointSize
|
||||
QtGui.QApplication.activeWindow().statusBar().showMessage(QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg(str(zoom)))
|
||||
QtGui.QApplication.activeWindow().statusBar().showMessage(
|
||||
QtGui.QApplication.translate("MainWindow", "Zoom level %1%").arg(str(zoom)))
|
||||
|
||||
def setWrappingWidth(self, width=None):
|
||||
"""Set word-wrapping width"""
|
||||
self.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth)
|
||||
if width is None:
|
||||
width = self.width()
|
||||
self.setLineWrapColumnOrWidth(width)
|
||||
|
||||
def confirmURL(self, link):
|
||||
"""Show a dialog requesting URL opening confirmation"""
|
||||
if link.scheme() == "mailto":
|
||||
window = QtGui.QApplication.activeWindow()
|
||||
window.ui.lineEditTo.setText(link.path())
|
||||
|
@ -68,35 +80,39 @@ class MessageView(QtGui.QTextBrowser):
|
|||
)
|
||||
window.ui.textEditMessage.setFocus()
|
||||
return
|
||||
reply = QtGui.QMessageBox.warning(self,
|
||||
QtGui.QApplication.translate("MessageView", "Follow external link"),
|
||||
QtGui.QApplication.translate("MessageView", "The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you or download malicious data. Are you sure?").arg(unicode(link.toString())),
|
||||
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
|
||||
reply = QtGui.QMessageBox.warning(
|
||||
self,
|
||||
QtGui.QApplication.translate(
|
||||
"MessageView",
|
||||
"Follow external link"),
|
||||
QtGui.QApplication.translate(
|
||||
"MessageView",
|
||||
"The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you"
|
||||
" or download malicious data. Are you sure?").arg(unicode(link.toString())),
|
||||
QtGui.QMessageBox.Yes,
|
||||
QtGui.QMessageBox.No)
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
QtGui.QDesktopServices.openUrl(link)
|
||||
|
||||
def loadResource (self, restype, name):
|
||||
if restype == QtGui.QTextDocument.ImageResource and name.scheme() == "bmmsg":
|
||||
pass
|
||||
# QImage correctImage;
|
||||
# lookup the correct QImage from a cache
|
||||
# return QVariant::fromValue(correctImage);
|
||||
# elif restype == QtGui.QTextDocument.HtmlResource:
|
||||
# elif restype == QtGui.QTextDocument.ImageResource:
|
||||
# elif restype == QtGui.QTextDocument.StyleSheetResource:
|
||||
# elif restype == QtGui.QTextDocument.UserResource:
|
||||
else:
|
||||
pass
|
||||
# by default, this will interpret it as a local file
|
||||
# QtGui.QTextBrowser.loadResource(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
|
||||
anything)
|
||||
"""
|
||||
pass
|
||||
|
||||
def lazyRender(self):
|
||||
"""
|
||||
Partially render a message. This is to avoid UI freezing when loading huge messages. It continues loading as
|
||||
you scroll down.
|
||||
"""
|
||||
if self.rendering:
|
||||
return
|
||||
self.rendering = True
|
||||
position = self.verticalScrollBar().value()
|
||||
cursor = QtGui.QTextCursor(self.document())
|
||||
while self.outpos < len(self.out) and self.verticalScrollBar().value() >= self.document().size().height() - 2 * self.size().height():
|
||||
while self.outpos < len(self.out) and self.verticalScrollBar().value(
|
||||
) >= self.document().size().height() - 2 * self.size().height():
|
||||
startpos = self.outpos
|
||||
self.outpos += 10240
|
||||
# find next end of tag
|
||||
|
@ -108,27 +124,33 @@ class MessageView(QtGui.QTextBrowser):
|
|||
cursor.insertHtml(QtCore.QString(self.out[startpos:self.outpos]))
|
||||
self.verticalScrollBar().setValue(position)
|
||||
self.rendering = False
|
||||
|
||||
|
||||
def showPlain(self):
|
||||
"""Render message as plain text."""
|
||||
self.mode = MessageView.MODE_PLAIN
|
||||
out = self.html.raw
|
||||
if self.html.has_html:
|
||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode(QtGui.QApplication.translate("MessageView", "HTML detected, click here to display")) + "</b></div><br/>" + out
|
||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode(
|
||||
QtGui.QApplication.translate(
|
||||
"MessageView", "HTML detected, click here to display")) + "</b></div><br/>" + out
|
||||
self.out = out
|
||||
self.outpos = 0
|
||||
self.setHtml("")
|
||||
self.lazyRender()
|
||||
|
||||
def showHTML(self):
|
||||
"""Render message as HTML"""
|
||||
self.mode = MessageView.MODE_HTML
|
||||
out = self.html.sanitised
|
||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode(QtGui.QApplication.translate("MessageView", "Click here to disable HTML")) + "</b></div><br/>" + out
|
||||
out = "<div align=\"center\" style=\"text-decoration: underline;\"><b>" + unicode(
|
||||
QtGui.QApplication.translate("MessageView", "Click here to disable HTML")) + "</b></div><br/>" + out
|
||||
self.out = out
|
||||
self.outpos = 0
|
||||
self.setHtml("")
|
||||
self.lazyRender()
|
||||
|
||||
def setContent(self, data):
|
||||
"""Set message content from argument"""
|
||||
self.html = SafeHTMLParser()
|
||||
self.html.reset()
|
||||
self.html.reset_safe()
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
from PyQt4 import QtCore, QtGui
|
||||
import time
|
||||
import shared
|
||||
"""
|
||||
src/bitmessageqt/networkstatus.py
|
||||
=================================
|
||||
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from tr import _translate
|
||||
from inventory import Inventory
|
||||
import knownnodes
|
||||
import l10n
|
||||
import network.stats
|
||||
from retranslateui import RetranslateMixin
|
||||
from uisignaler import UISignaler
|
||||
import shared
|
||||
import widgets
|
||||
|
||||
from inventory import Inventory
|
||||
from network.connectionpool import BMConnectionPool
|
||||
from retranslateui import RetranslateMixin
|
||||
from tr import _translate
|
||||
from uisignaler import UISignaler
|
||||
|
||||
|
||||
class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
||||
"""Network status tab"""
|
||||
def __init__(self, parent=None):
|
||||
super(NetworkStatus, self).__init__(parent)
|
||||
widgets.load('networkstatus.ui', self)
|
||||
|
@ -29,8 +36,9 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
|||
self.startup = time.localtime()
|
||||
self.labelStartupTime.setText(_translate("networkstatus", "Since startup on %1").arg(
|
||||
l10n.formatTimestamp(self.startup)))
|
||||
|
||||
|
||||
self.UISignalThread = UISignaler.get()
|
||||
# pylint: disable=no-member
|
||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||
"updateNumberOfMessagesProcessed()"), self.updateNumberOfMessagesProcessed)
|
||||
QtCore.QObject.connect(self.UISignalThread, QtCore.SIGNAL(
|
||||
|
@ -42,57 +50,108 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
|||
|
||||
self.timer = QtCore.QTimer()
|
||||
|
||||
QtCore.QObject.connect(
|
||||
self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds)
|
||||
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.runEveryTwoSeconds)
|
||||
# pylint: enable=no-member
|
||||
|
||||
def startUpdate(self):
|
||||
"""Start a timer to update counters every 2 seconds"""
|
||||
Inventory().numberOfInventoryLookupsPerformed = 0
|
||||
self.runEveryTwoSeconds()
|
||||
self.timer.start(2000) # milliseconds
|
||||
|
||||
def stopUpdate(self):
|
||||
"""Stop counter update timer"""
|
||||
self.timer.stop()
|
||||
|
||||
def formatBytes(self, num):
|
||||
for x in [_translate("networkstatus", "byte(s)", None, QtCore.QCoreApplication.CodecForTr, num), "kB", "MB", "GB"]:
|
||||
"""Format bytes nicely (SI prefixes)"""
|
||||
# pylint: disable=no-self-use
|
||||
for x in [
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"byte(s)",
|
||||
None,
|
||||
QtCore.QCoreApplication.CodecForTr,
|
||||
num),
|
||||
"kB",
|
||||
"MB",
|
||||
"GB",
|
||||
]:
|
||||
if num < 1000.0:
|
||||
return "%3.0f %s" % (num, x)
|
||||
num /= 1000.0
|
||||
return "%3.0f %s" % (num, 'TB')
|
||||
|
||||
def formatByteRate(self, num):
|
||||
"""Format transfer speed in kB/s"""
|
||||
# pylint: disable=no-self-use
|
||||
num /= 1000
|
||||
return "%4.0f kB" % num
|
||||
|
||||
|
||||
def updateNumberOfObjectsToBeSynced(self):
|
||||
self.labelSyncStatus.setText(_translate("networkstatus", "Object(s) to be synced: %n", None, QtCore.QCoreApplication.CodecForTr, network.stats.pendingDownload() + network.stats.pendingUpload()))
|
||||
"""Update the counter for number of objects to be synced"""
|
||||
self.labelSyncStatus.setText(
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"Object(s) to be synced: %n",
|
||||
None,
|
||||
QtCore.QCoreApplication.CodecForTr,
|
||||
network.stats.pendingDownload() +
|
||||
network.stats.pendingUpload()))
|
||||
|
||||
def updateNumberOfMessagesProcessed(self):
|
||||
"""Update the counter for number of processed messages"""
|
||||
self.updateNumberOfObjectsToBeSynced()
|
||||
self.labelMessageCount.setText(_translate(
|
||||
"networkstatus", "Processed %n person-to-person message(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfMessagesProcessed))
|
||||
self.labelMessageCount.setText(
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"Processed %n person-to-person message(s).",
|
||||
None,
|
||||
QtCore.QCoreApplication.CodecForTr,
|
||||
shared.numberOfMessagesProcessed))
|
||||
|
||||
def updateNumberOfBroadcastsProcessed(self):
|
||||
"""Update the counter for the number of processed broadcasts"""
|
||||
self.updateNumberOfObjectsToBeSynced()
|
||||
self.labelBroadcastCount.setText(_translate(
|
||||
"networkstatus", "Processed %n broadcast message(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfBroadcastsProcessed))
|
||||
self.labelBroadcastCount.setText(
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"Processed %n broadcast message(s).",
|
||||
None,
|
||||
QtCore.QCoreApplication.CodecForTr,
|
||||
shared.numberOfBroadcastsProcessed))
|
||||
|
||||
def updateNumberOfPubkeysProcessed(self):
|
||||
"""Update the counter for the number of processed pubkeys"""
|
||||
self.updateNumberOfObjectsToBeSynced()
|
||||
self.labelPubkeyCount.setText(_translate(
|
||||
"networkstatus", "Processed %n public key(s).", None, QtCore.QCoreApplication.CodecForTr, shared.numberOfPubkeysProcessed))
|
||||
self.labelPubkeyCount.setText(
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"Processed %n public key(s).",
|
||||
None,
|
||||
QtCore.QCoreApplication.CodecForTr,
|
||||
shared.numberOfPubkeysProcessed))
|
||||
|
||||
def updateNumberOfBytes(self):
|
||||
"""
|
||||
This function is run every two seconds, so we divide the rate of bytes
|
||||
sent and received by 2.
|
||||
"""
|
||||
self.labelBytesRecvCount.setText(_translate(
|
||||
"networkstatus", "Down: %1/s Total: %2").arg(self.formatByteRate(network.stats.downloadSpeed()), self.formatBytes(network.stats.receivedBytes())))
|
||||
self.labelBytesSentCount.setText(_translate(
|
||||
"networkstatus", "Up: %1/s Total: %2").arg(self.formatByteRate(network.stats.uploadSpeed()), self.formatBytes(network.stats.sentBytes())))
|
||||
self.labelBytesRecvCount.setText(
|
||||
_translate(
|
||||
"networkstatus",
|
||||
"Down: %1/s Total: %2").arg(
|
||||
self.formatByteRate(network.stats.downloadSpeed()),
|
||||
self.formatBytes(network.stats.receivedBytes())))
|
||||
self.labelBytesSentCount.setText(
|
||||
_translate(
|
||||
"networkstatus", "Up: %1/s Total: %2").arg(
|
||||
self.formatByteRate(network.stats.uploadSpeed()),
|
||||
self.formatBytes(network.stats.sentBytes())))
|
||||
|
||||
def updateNetworkStatusTab(self, outbound, add, destination):
|
||||
"""Add or remove an entry to the list of connected peers"""
|
||||
# pylint: disable=too-many-branches,undefined-variable
|
||||
if outbound:
|
||||
try:
|
||||
c = BMConnectionPool().outboundConnections[destination]
|
||||
|
@ -111,33 +170,39 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
|||
|
||||
self.tableWidgetConnectionCount.setUpdatesEnabled(False)
|
||||
self.tableWidgetConnectionCount.setSortingEnabled(False)
|
||||
|
||||
if add:
|
||||
self.tableWidgetConnectionCount.insertRow(0)
|
||||
self.tableWidgetConnectionCount.setItem(0, 0,
|
||||
self.tableWidgetConnectionCount.setItem(
|
||||
0, 0,
|
||||
QtGui.QTableWidgetItem("%s:%i" % (destination.host, destination.port))
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(0, 2,
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(
|
||||
0, 2,
|
||||
QtGui.QTableWidgetItem("%s" % (c.userAgent))
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(0, 3,
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(
|
||||
0, 3,
|
||||
QtGui.QTableWidgetItem("%s" % (c.tlsVersion))
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(0, 4,
|
||||
QtGui.QTableWidgetItem("%s" % (",".join(map(str,c.streams))))
|
||||
)
|
||||
)
|
||||
self.tableWidgetConnectionCount.setItem(
|
||||
0, 4,
|
||||
QtGui.QTableWidgetItem("%s" % (",".join(map(str, c.streams))))
|
||||
)
|
||||
try:
|
||||
# FIXME hard coded stream no
|
||||
# .. todo:: FIXME: hard coded stream no
|
||||
rating = "%.1f" % (knownnodes.knownNodes[1][destination]['rating'])
|
||||
except KeyError:
|
||||
rating = "-"
|
||||
self.tableWidgetConnectionCount.setItem(0, 1,
|
||||
self.tableWidgetConnectionCount.setItem(
|
||||
0, 1,
|
||||
QtGui.QTableWidgetItem("%s" % (rating))
|
||||
)
|
||||
)
|
||||
if outbound:
|
||||
brush = QtGui.QBrush(QtGui.QColor("yellow"), QtCore.Qt.SolidPattern)
|
||||
else:
|
||||
brush = QtGui.QBrush(QtGui.QColor("green"), QtCore.Qt.SolidPattern)
|
||||
for j in (range(1)):
|
||||
for j in range(1):
|
||||
self.tableWidgetConnectionCount.item(0, j).setBackground(brush)
|
||||
self.tableWidgetConnectionCount.item(0, 0).setData(QtCore.Qt.UserRole, destination)
|
||||
self.tableWidgetConnectionCount.item(0, 1).setData(QtCore.Qt.UserRole, outbound)
|
||||
|
@ -148,11 +213,16 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
|||
if self.tableWidgetConnectionCount.item(i, 1).data(QtCore.Qt.UserRole).toPyObject() == outbound:
|
||||
self.tableWidgetConnectionCount.removeRow(i)
|
||||
break
|
||||
|
||||
self.tableWidgetConnectionCount.setUpdatesEnabled(True)
|
||||
self.tableWidgetConnectionCount.setSortingEnabled(True)
|
||||
self.labelTotalConnections.setText(_translate(
|
||||
"networkstatus", "Total Connections: %1").arg(str(self.tableWidgetConnectionCount.rowCount())))
|
||||
# FYI: The 'singlelistener' thread sets the icon color to green when it receives an incoming connection, meaning that the user's firewall is configured correctly.
|
||||
self.labelTotalConnections.setText(
|
||||
_translate(
|
||||
"networkstatus", "Total Connections: %1").arg(
|
||||
str(self.tableWidgetConnectionCount.rowCount())))
|
||||
# FYI: The 'singlelistener' thread sets the icon color to green when it
|
||||
# receives an incoming connection, meaning that the user's firewall is
|
||||
# configured correctly.
|
||||
if self.tableWidgetConnectionCount.rowCount() and shared.statusIconColor == 'red':
|
||||
self.window().setStatusIcon('yellow')
|
||||
elif self.tableWidgetConnectionCount.rowCount() == 0 and shared.statusIconColor != "red":
|
||||
|
@ -160,8 +230,9 @@ class NetworkStatus(QtGui.QWidget, RetranslateMixin):
|
|||
|
||||
# timer driven
|
||||
def runEveryTwoSeconds(self):
|
||||
self.labelLookupsPerSecond.setText(_translate(
|
||||
"networkstatus", "Inventory lookups per second: %1").arg(str(Inventory().numberOfInventoryLookupsPerformed/2)))
|
||||
"""Updates counters, runs every 2 seconds if the timer is running"""
|
||||
self.labelLookupsPerSecond.setText(_translate("networkstatus", "Inventory lookups per second: %1").arg(
|
||||
str(Inventory().numberOfInventoryLookupsPerformed / 2)))
|
||||
Inventory().numberOfInventoryLookupsPerformed = 0
|
||||
self.updateNumberOfBytes()
|
||||
self.updateNumberOfObjectsToBeSynced()
|
||||
|
|
|
@ -1,40 +1,41 @@
|
|||
"""
|
||||
src/class_singleWorker.py
|
||||
=========================
|
||||
"""
|
||||
# pylint: disable=protected-access,too-many-branches,too-many-statements,no-self-use,too-many-lines,too-many-locals
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import time
|
||||
import threading
|
||||
import hashlib
|
||||
from struct import pack
|
||||
# used when the API must execute an outside program
|
||||
from subprocess import call # nosec
|
||||
import threading
|
||||
import time
|
||||
from binascii import hexlify, unhexlify
|
||||
from struct import pack
|
||||
from subprocess import call # nosec
|
||||
|
||||
import tr
|
||||
import defaults
|
||||
import helper_inbox
|
||||
import helper_msgcoding
|
||||
import helper_random
|
||||
import highlevelcrypto
|
||||
import l10n
|
||||
import proofofwork
|
||||
import protocol
|
||||
import queues
|
||||
import state
|
||||
import shared
|
||||
import defaults
|
||||
import highlevelcrypto
|
||||
import proofofwork
|
||||
import helper_inbox
|
||||
import helper_random
|
||||
import helper_msgcoding
|
||||
import state
|
||||
import tr
|
||||
from addresses import calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint
|
||||
from bmconfigparser import BMConfigParser
|
||||
from debug import logger
|
||||
from inventory import Inventory
|
||||
from addresses import (
|
||||
decodeAddress, encodeVarint, decodeVarint, calculateInventoryHash
|
||||
)
|
||||
# from helper_generic import addDataPadding
|
||||
from helper_sql import sqlExecute, sqlQuery
|
||||
from helper_threading import StoppableThread
|
||||
from helper_sql import sqlQuery, sqlExecute
|
||||
from inventory import Inventory
|
||||
|
||||
|
||||
# This thread, of which there is only one, does the heavy lifting:
|
||||
# calculating POWs.
|
||||
|
||||
def sizeof_fmt(num, suffix='h/s'):
|
||||
"""Format hashes per seconds nicely (SI prefix)"""
|
||||
|
||||
for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']:
|
||||
if abs(num) < 1000.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
|
@ -43,14 +44,16 @@ def sizeof_fmt(num, suffix='h/s'):
|
|||
|
||||
|
||||
class singleWorker(threading.Thread, StoppableThread):
|
||||
"""Thread for performing PoW"""
|
||||
|
||||
def __init__(self):
|
||||
# QThread.__init__(self, parent)
|
||||
threading.Thread.__init__(self, name="singleWorker")
|
||||
self.initStop()
|
||||
proofofwork.init()
|
||||
|
||||
def stopThread(self):
|
||||
"""Signal through the queue that the thread should be stopped"""
|
||||
|
||||
try:
|
||||
queues.workerQueue.put(("stopThread", "data"))
|
||||
except:
|
||||
|
@ -58,6 +61,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
super(singleWorker, self).stopThread()
|
||||
|
||||
def run(self):
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
||||
while not state.sqlReady and state.shutdown == 0:
|
||||
self.stop.wait(2)
|
||||
|
@ -96,12 +100,12 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
'''SELECT ackdata FROM sent WHERE status = 'msgsent' ''')
|
||||
for row in queryreturn:
|
||||
ackdata, = row
|
||||
logger.info('Watching for ackdata ' + hexlify(ackdata))
|
||||
logger.info('Watching for ackdata %s', hexlify(ackdata))
|
||||
shared.ackdataForWhichImWatching[ackdata] = 0
|
||||
|
||||
# Fix legacy (headerless) watched ackdata to include header
|
||||
for oldack in shared.ackdataForWhichImWatching.keys():
|
||||
if (len(oldack) == 32):
|
||||
for oldack in shared.ackdataForWhichImWatching:
|
||||
if len(oldack) == 32:
|
||||
# attach legacy header, always constant (msg/1/1)
|
||||
newack = '\x00\x00\x00\x02\x01\x01' + oldack
|
||||
shared.ackdataForWhichImWatching[newack] = 0
|
||||
|
@ -226,19 +230,9 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
# inventoryHash = calculateInventoryHash(payload)
|
||||
return payload
|
||||
|
||||
# This function also broadcasts out the pubkey message
|
||||
# once it is done with the POW
|
||||
def doPOWForMyV2Pubkey(self, adressHash):
|
||||
""" 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
|
||||
"""configSections = shared.config.addresses()
|
||||
for addressInKeysFile in configSections:
|
||||
if addressInKeysFile != 'bitmessagesettings':
|
||||
status, addressVersionNumber, streamNumber, \
|
||||
hashFromThisParticularAddress = \
|
||||
decodeAddress(addressInKeysFile)
|
||||
if hash == hashFromThisParticularAddress:
|
||||
myAddress = addressInKeysFile
|
||||
break"""
|
||||
myAddress = shared.myAddressesByHash[adressHash]
|
||||
# status
|
||||
_, addressVersionNumber, streamNumber, adressHash = decodeAddress(myAddress)
|
||||
|
@ -289,11 +283,12 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
# before this finished.
|
||||
pass
|
||||
|
||||
# If this isn't a chan address, this function assembles the pubkey data,
|
||||
# does the necessary POW and sends it out. If it *is* a chan then it
|
||||
# assembles the pubkey and stores is in the pubkey table so that we can
|
||||
# send messages to "ourselves".
|
||||
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 it *is* a chan then it assembles the pubkey and stores is in the pubkey table so that we can send messages
|
||||
to "ourselves".
|
||||
"""
|
||||
try:
|
||||
myAddress = shared.myAddressesByHash[adressHash]
|
||||
except:
|
||||
|
@ -357,7 +352,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
Inventory()[inventoryHash] = (
|
||||
objectType, streamNumber, payload, embeddedTime, '')
|
||||
|
||||
logger.info('broadcasting inv with hash: ' + hexlify(inventoryHash))
|
||||
logger.info('broadcasting inv with hash: %s', hexlify(inventoryHash))
|
||||
|
||||
queues.invQueue.put((streamNumber, inventoryHash))
|
||||
queues.UISignalQueue.put(('updateStatusBar', ''))
|
||||
|
@ -370,9 +365,12 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
# before this finished.
|
||||
pass
|
||||
|
||||
# If this isn't a chan address, this function assembles
|
||||
# the pubkey data, does the necessary POW and sends it out.
|
||||
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,
|
||||
whereas in the past it directly appended it to the outgoing buffer, I think. Same with all the other methods in
|
||||
this class.
|
||||
"""
|
||||
if not BMConfigParser().has_section(myAddress):
|
||||
# The address has been deleted.
|
||||
return
|
||||
|
@ -444,7 +442,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
doubleHashOfAddressData[32:]
|
||||
)
|
||||
|
||||
logger.info('broadcasting inv with hash: ' + hexlify(inventoryHash))
|
||||
logger.info('broadcasting inv with hash: %s', hexlify(inventoryHash))
|
||||
|
||||
queues.invQueue.put((streamNumber, inventoryHash))
|
||||
queues.UISignalQueue.put(('updateStatusBar', ''))
|
||||
|
@ -459,6 +457,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
)
|
||||
|
||||
def sendBroadcast(self):
|
||||
"""Send a broadcast-type object (assemble the object, perform PoW and put it to the inv announcement queue)"""
|
||||
# Reset just in case
|
||||
sqlExecute(
|
||||
'''UPDATE sent SET status='broadcastqueued' '''
|
||||
|
@ -627,6 +626,8 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
)
|
||||
|
||||
def sendMsg(self):
|
||||
"""Send a message-type object (assemble the object, perform PoW and put it to the inv announcement queue)"""
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
# Reset just in case
|
||||
sqlExecute(
|
||||
'''UPDATE sent SET status='msgqueued' '''
|
||||
|
@ -740,10 +741,8 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
# object associated with the tag for this toAddress.
|
||||
if toAddressVersionNumber >= 4:
|
||||
doubleHashOfToAddressData = hashlib.sha512(
|
||||
hashlib.sha512(encodeVarint(
|
||||
toAddressVersionNumber) +
|
||||
encodeVarint(toStreamNumber) +
|
||||
toRipe
|
||||
hashlib.sha512(
|
||||
encodeVarint(toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe
|
||||
).digest()
|
||||
).digest()
|
||||
# The first half of the sha512 hash.
|
||||
|
@ -834,7 +833,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
queryreturn = sqlQuery(
|
||||
'SELECT transmitdata FROM pubkeys WHERE address=?',
|
||||
toaddress)
|
||||
for row in queryreturn:
|
||||
for row in queryreturn: # pylint: disable=redefined-outer-name
|
||||
pubkeyPayload, = row
|
||||
|
||||
# The pubkey message is stored with the following items
|
||||
|
@ -939,40 +938,43 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
requiredAverageProofOfWorkNonceTrialsPerByte,
|
||||
requiredPayloadLengthExtraBytes
|
||||
)
|
||||
queues.UISignalQueue.put((
|
||||
'updateSentItemStatusByAckdata', (
|
||||
ackdata,
|
||||
tr._translate(
|
||||
"MainWindow",
|
||||
"Doing work necessary to send message.\n"
|
||||
"Receiver\'s required difficulty: %1"
|
||||
" and %2"
|
||||
).arg(str(float(
|
||||
requiredAverageProofOfWorkNonceTrialsPerByte) /
|
||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||
)).arg(str(float(
|
||||
requiredPayloadLengthExtraBytes) /
|
||||
defaults.networkDefaultPayloadLengthExtraBytes
|
||||
)))))
|
||||
|
||||
queues.UISignalQueue.put(
|
||||
(
|
||||
'updateSentItemStatusByAckdata',
|
||||
(
|
||||
ackdata,
|
||||
tr._translate(
|
||||
"MainWindow",
|
||||
"Doing work necessary to send message.\n"
|
||||
"Receiver\'s required difficulty: %1"
|
||||
" and %2"
|
||||
).arg(
|
||||
str(
|
||||
float(requiredAverageProofOfWorkNonceTrialsPerByte) /
|
||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||
)
|
||||
).arg(
|
||||
str(
|
||||
float(requiredPayloadLengthExtraBytes) /
|
||||
defaults.networkDefaultPayloadLengthExtraBytes
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if status != 'forcepow':
|
||||
if (requiredAverageProofOfWorkNonceTrialsPerByte
|
||||
> BMConfigParser().getint(
|
||||
'bitmessagesettings',
|
||||
'maxacceptablenoncetrialsperbyte'
|
||||
) and
|
||||
BMConfigParser().getint(
|
||||
'bitmessagesettings',
|
||||
'maxacceptablenoncetrialsperbyte'
|
||||
) != 0) or (
|
||||
requiredPayloadLengthExtraBytes
|
||||
> BMConfigParser().getint(
|
||||
'bitmessagesettings',
|
||||
'maxacceptablepayloadlengthextrabytes'
|
||||
) and
|
||||
BMConfigParser().getint(
|
||||
'bitmessagesettings',
|
||||
'maxacceptablepayloadlengthextrabytes'
|
||||
) != 0):
|
||||
maxacceptablenoncetrialsperbyte = BMConfigParser().getint(
|
||||
'bitmessagesettings', 'maxacceptablenoncetrialsperbyte')
|
||||
maxacceptablepayloadlengthextrabytes = BMConfigParser().getint(
|
||||
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')
|
||||
cond1 = maxacceptablenoncetrialsperbyte and \
|
||||
requiredAverageProofOfWorkNonceTrialsPerByte > maxacceptablenoncetrialsperbyte
|
||||
cond2 = maxacceptablepayloadlengthextrabytes and \
|
||||
requiredPayloadLengthExtraBytes > maxacceptablepayloadlengthextrabytes
|
||||
|
||||
if cond1 or cond2:
|
||||
# The demanded difficulty is more than
|
||||
# we are willing to do.
|
||||
sqlExecute(
|
||||
|
@ -988,19 +990,15 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
" the recipient (%1 and %2) is"
|
||||
" more difficult than you are"
|
||||
" willing to do. %3"
|
||||
).arg(str(float(
|
||||
requiredAverageProofOfWorkNonceTrialsPerByte)
|
||||
/ defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
||||
)).arg(str(float(
|
||||
requiredPayloadLengthExtraBytes)
|
||||
/ defaults.networkDefaultPayloadLengthExtraBytes
|
||||
)).arg(l10n.formatTimestamp()))
|
||||
))
|
||||
).arg(str(float(requiredAverageProofOfWorkNonceTrialsPerByte) /
|
||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte)).arg(
|
||||
str(float(requiredPayloadLengthExtraBytes) /
|
||||
defaults.networkDefaultPayloadLengthExtraBytes)).arg(
|
||||
l10n.formatTimestamp()))))
|
||||
continue
|
||||
else: # if we are sending a message to ourselves or a chan..
|
||||
logger.info('Sending a message.')
|
||||
logger.debug(
|
||||
'First 150 characters of message: %r', message[:150])
|
||||
logger.debug('First 150 characters of message: %r', message[:150])
|
||||
behaviorBitfield = protocol.getBitfield(fromaddress)
|
||||
|
||||
try:
|
||||
|
@ -1199,16 +1197,14 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
Inventory()[inventoryHash] = (
|
||||
objectType, toStreamNumber, encryptedPayload, embeddedTime, '')
|
||||
if BMConfigParser().has_section(toaddress) or \
|
||||
not protocol.checkBitfield(
|
||||
behaviorBitfield, protocol.BITFIELD_DOESACK):
|
||||
not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK):
|
||||
queues.UISignalQueue.put((
|
||||
'updateSentItemStatusByAckdata', (
|
||||
ackdata,
|
||||
tr._translate(
|
||||
"MainWindow",
|
||||
"Message sent. Sent at %1"
|
||||
).arg(l10n.formatTimestamp()))
|
||||
))
|
||||
).arg(l10n.formatTimestamp()))))
|
||||
else:
|
||||
# not sending to a chan or one of my addresses
|
||||
queues.UISignalQueue.put((
|
||||
|
@ -1229,8 +1225,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
# Update the sent message in the sent table with the
|
||||
# necessary information.
|
||||
if BMConfigParser().has_section(toaddress) or \
|
||||
not protocol.checkBitfield(
|
||||
behaviorBitfield, protocol.BITFIELD_DOESACK):
|
||||
not protocol.checkBitfield(behaviorBitfield, protocol.BITFIELD_DOESACK):
|
||||
newStatus = 'msgsentnoackexpected'
|
||||
else:
|
||||
newStatus = 'msgsent'
|
||||
|
@ -1270,6 +1265,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
call([apiNotifyPath, "newMessage"])
|
||||
|
||||
def requestPubKey(self, toAddress):
|
||||
"""Send a getpubkey object"""
|
||||
toStatus, addressVersionNumber, streamNumber, ripe = decodeAddress(
|
||||
toAddress)
|
||||
if toStatus != 'success':
|
||||
|
@ -1286,7 +1282,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
''' LIMIT 1''',
|
||||
toAddress
|
||||
)
|
||||
if len(queryReturn) == 0:
|
||||
if not queryReturn:
|
||||
logger.critical(
|
||||
'BUG: Why are we requesting the pubkey for %s'
|
||||
' if there are no messages in the sent folder'
|
||||
|
@ -1389,16 +1385,14 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
).arg(l10n.formatTimestamp()))
|
||||
))
|
||||
|
||||
def generateFullAckMessage(self, ackdata, toStreamNumber, TTL):
|
||||
# It might be perfectly fine to just use the same TTL for
|
||||
# the ackdata that we use for the message. But I would rather
|
||||
# it be more difficult for attackers to associate ackData with
|
||||
# the associated msg object. However, users would want the TTL
|
||||
# of the acknowledgement to be about the same as they set
|
||||
# for the message itself. So let's set the TTL of the
|
||||
# acknowledgement to be in one of three 'buckets': 1 hour, 7
|
||||
# days, or 28 days, whichever is relatively close to what the
|
||||
# user specified.
|
||||
def generateFullAckMessage(self, ackdata, _, TTL):
|
||||
"""
|
||||
It might be perfectly fine to just use the same TTL for the ackdata that we use for the message. But I would
|
||||
rather it be more difficult for attackers to associate ackData with the associated msg object. However, users
|
||||
would want the TTL of the acknowledgement to be about the same as they set for the message itself. So let's set
|
||||
the TTL of the acknowledgement to be in one of three 'buckets': 1 hour, 7 days, or 28 days, whichever is
|
||||
relatively close to what the user specified.
|
||||
"""
|
||||
if TTL < 24 * 60 * 60: # 1 day
|
||||
TTL = 24 * 60 * 60 # 1 day
|
||||
elif TTL < 7 * 24 * 60 * 60: # 1 week
|
||||
|
|
Loading…
Reference in New Issue
Block a user