Fixed: Style and lint violations for three more of the worst violating files

This commit is contained in:
coffeedogs 2018-05-28 14:35:30 +01:00
parent 74ddda8775
commit 759b760977
No known key found for this signature in database
GPG Key ID: 9D818C503D0B7E70
3 changed files with 462 additions and 243 deletions

View File

@ -1,26 +1,58 @@
from PyQt4 import QtCore, QtGui
# pylint: disable=too-many-instance-attributes,attribute-defined-outside-init
"""
account.py
==========
import queues
Account related functions.
"""
from __future__ import absolute_import
import inspect
import re
import sys
import inspect
from helper_sql import *
from helper_ackPayload import genAckPayload
from addresses import decodeAddress
from bmconfigparser import BMConfigParser
from foldertree import AccountMixin
from pyelliptic.openssl import OpenSSL
from utils import str_broadcast_subscribers
import time
from PyQt4 import QtGui
import queues
from addresses import decodeAddress
from bmconfigparser import BMConfigParser
from helper_ackPayload import genAckPayload
from helper_sql import sqlQuery, sqlExecute
from .foldertree import AccountMixin
from .utils import str_broadcast_subscribers
def getSortedAccounts():
"""Get a sorted list of configSections"""
configSections = BMConfigParser().addresses()
configSections.sort(cmp =
lambda x,y: cmp(unicode(BMConfigParser().get(x, 'label'), 'utf-8').lower(), unicode(BMConfigParser().get(y, 'label'), 'utf-8').lower())
)
configSections.sort(
cmp=lambda x, y: cmp(
unicode(
BMConfigParser().get(
x,
'label'),
'utf-8').lower(),
unicode(
BMConfigParser().get(
y,
'label'),
'utf-8').lower()))
return configSections
def getSortedSubscriptions(count = False):
def getSortedSubscriptions(count=False):
"""
Actually return a grouped dictionary rather than a sorted list
:param count: Whether to count messages for each fromaddress in the inbox
:type count: bool, default False
:retuns: dict keys are addresses, values are dicts containing settings
:rtype: dict, default {}
"""
queryreturn = sqlQuery('SELECT label, address, enabled FROM subscriptions ORDER BY label COLLATE NOCASE ASC')
ret = {}
for row in queryreturn:
@ -37,7 +69,7 @@ def getSortedSubscriptions(count = False):
GROUP BY inbox.fromaddress, folder''', str_broadcast_subscribers)
for row in queryreturn:
address, folder, cnt = row
if not folder in ret[address]:
if folder not in ret[address]:
ret[address][folder] = {
'label': ret[address]['inbox']['label'],
'enabled': ret[address]['inbox']['enabled']
@ -45,9 +77,11 @@ def getSortedSubscriptions(count = False):
ret[address][folder]['count'] = cnt
return ret
def accountClass(address):
"""Return a BMAccount for the address"""
if not BMConfigParser().has_section(address):
# FIXME: This BROADCAST section makes no sense
# .. todo:: This BROADCAST section makes no sense
if address == str_broadcast_subscribers:
subscription = BroadcastAccount(address)
if subscription.type != AccountMixin.BROADCAST:
@ -60,8 +94,7 @@ def accountClass(address):
return subscription
try:
gateway = BMConfigParser().get(address, "gateway")
for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
# obj = g(address)
for _, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
if issubclass(cls, GatewayAccount) and cls.gatewayName == gateway:
return cls(address)
# general gateway
@ -70,12 +103,15 @@ def accountClass(address):
pass
# no gateway
return BMAccount(address)
class AccountColor(AccountMixin):
def __init__(self, address, type = None):
class AccountColor(AccountMixin): # pylint: disable=too-few-public-methods
"""Set the type of account"""
def __init__(self, address, address_type=None):
self.isEnabled = True
self.address = address
if type is None:
if address_type is None:
if address is None:
self.type = AccountMixin.ALL
elif BMConfigParser().safeGetBoolean(self.address, 'mailinglist'):
@ -83,16 +119,18 @@ class AccountColor(AccountMixin):
elif BMConfigParser().safeGetBoolean(self.address, 'chan'):
self.type = AccountMixin.CHAN
elif sqlQuery(
'''select label from subscriptions where address=?''', self.address):
'''select label from subscriptions where address=?''', self.address):
self.type = AccountMixin.SUBSCRIPTION
else:
self.type = AccountMixin.NORMAL
else:
self.type = type
self.type = address_type
class BMAccount(object):
def __init__(self, address = None):
"""Encapsulate a Bitmessage account"""
def __init__(self, address=None):
self.address = address
self.type = AccountMixin.NORMAL
if BMConfigParser().has_section(address):
@ -108,7 +146,8 @@ class BMAccount(object):
if queryreturn:
self.type = AccountMixin.SUBSCRIPTION
def getLabel(self, address = None):
def getLabel(self, address=None):
"""Get a label for this bitmessage account"""
if address is None:
address = self.address
label = address
@ -126,8 +165,10 @@ class BMAccount(object):
for row in queryreturn:
label, = row
return label
def parseMessage(self, toAddress, fromAddress, subject, message):
"""Set metadata and address labels on self"""
self.toAddress = toAddress
self.fromAddress = fromAddress
if isinstance(subject, unicode):
@ -140,36 +181,45 @@ class BMAccount(object):
class NoAccount(BMAccount):
def __init__(self, address = None):
"""Override the __init__ method on a BMAccount"""
def __init__(self, address=None): # pylint: disable=super-init-not-called
self.address = address
self.type = AccountMixin.NORMAL
def getLabel(self, address = None):
def getLabel(self, address=None):
if address is None:
address = self.address
return address
class SubscriptionAccount(BMAccount):
"""Encapsulate a subscription account"""
pass
class BroadcastAccount(BMAccount):
"""Encapsulate a broadcast account"""
pass
class GatewayAccount(BMAccount):
"""Encapsulate a gateway account"""
gatewayName = None
ALL_OK = 0
REGISTRATION_DENIED = 1
def __init__(self, address):
super(GatewayAccount, self).__init__(address)
def send(self):
"""Override the send method for gateway accounts"""
# pylint: disable=unused-variable
status, addressVersionNumber, streamNumber, ripe = decodeAddress(self.toAddress)
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
ackdata = genAckPayload(streamNumber, stealthLevel)
t = ()
sqlExecute(
'''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''',
'',
@ -179,47 +229,52 @@ class GatewayAccount(BMAccount):
self.subject,
self.message,
ackdata,
int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done.
int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done.
'msgqueued',
0, # retryNumber
'sent', # folder
2, # encodingtype
min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days
0, # retryNumber
'sent', # folder
2, # encodingtype
# not necessary to have a TTL higher than 2 days
min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2)
)
queues.workerQueue.put(('sendmessage', self.toAddress))
def parseMessage(self, toAddress, fromAddress, subject, message):
super(GatewayAccount, self).parseMessage(toAddress, fromAddress, subject, message)
class MailchuckAccount(GatewayAccount):
"""Encapsulate a particular kind of gateway account"""
# set "gateway" in keys.dat to this
gatewayName = "mailchuck"
registrationAddress = "BM-2cVYYrhaY5Gbi3KqrX9Eae2NRNrkfrhCSA"
unregistrationAddress = "BM-2cVMAHTRjZHCTPMue75XBK5Tco175DtJ9J"
relayAddress = "BM-2cWim8aZwUNqxzjMxstnUMtVEUQJeezstf"
regExpIncoming = re.compile("(.*)MAILCHUCK-FROM::(\S+) \| (.*)")
regExpOutgoing = re.compile("(\S+) (.*)")
regExpIncoming = re.compile(r"(.*)MAILCHUCK-FROM::(\S+) \| (.*)")
regExpOutgoing = re.compile(r"(\S+) (.*)")
def __init__(self, address):
super(MailchuckAccount, self).__init__(address)
self.feedback = self.ALL_OK
def createMessage(self, toAddress, fromAddress, subject, message):
"""createMessage specific to a MailchuckAccount"""
self.subject = toAddress + " " + subject
self.toAddress = self.relayAddress
self.fromAddress = fromAddress
self.message = message
def register(self, email):
"""register specific to a MailchuckAccount"""
self.toAddress = self.registrationAddress
self.subject = email
self.message = ""
self.fromAddress = self.address
self.send()
def unregister(self):
"""unregister specific to a MailchuckAccount"""
self.toAddress = self.unregistrationAddress
self.subject = ""
self.message = ""
@ -227,6 +282,7 @@ class MailchuckAccount(GatewayAccount):
self.send()
def status(self):
"""status specific to a MailchuckAccount"""
self.toAddress = self.registrationAddress
self.subject = "status"
self.message = ""
@ -234,12 +290,16 @@ class MailchuckAccount(GatewayAccount):
self.send()
def settings(self):
"""settings specific to a MailchuckAccount"""
self.toAddress = self.registrationAddress
self.subject = "config"
self.message = QtGui.QApplication.translate("Mailchuck", """# You can use this to configure your email gateway account
self.message = QtGui.QApplication.translate(
"Mailchuck",
"""# You can use this to configure your email gateway account
# Uncomment the setting you want to use
# Here are the options:
#
#
# pgp: server
# The email gateway will create and maintain PGP keys for you and sign, verify,
# encrypt and decrypt on your behalf. When you want to use PGP but are lazy,
@ -255,7 +315,7 @@ class MailchuckAccount(GatewayAccount):
#
# attachments: no
# Attachments will be ignored.
#
#
# archive: yes
# Your incoming emails will be archived on the server. Use this if you need
# help with debugging problems or you need a third party proof of emails. This
@ -279,10 +339,12 @@ class MailchuckAccount(GatewayAccount):
self.fromAddress = self.address
def parseMessage(self, toAddress, fromAddress, subject, message):
"""parseMessage specific to a MailchuckAccount"""
super(MailchuckAccount, self).parseMessage(toAddress, fromAddress, subject, message)
if fromAddress == self.relayAddress:
matches = self.regExpIncoming.search(subject)
if not matches is None:
if matches is not None:
self.subject = ""
if not matches.group(1) is None:
self.subject += matches.group(1)
@ -293,7 +355,7 @@ class MailchuckAccount(GatewayAccount):
self.fromAddress = matches.group(2)
if toAddress == self.relayAddress:
matches = self.regExpOutgoing.search(subject)
if not matches is None:
if matches is not None:
if not matches.group(2) is None:
self.subject = matches.group(2)
if not matches.group(1) is None:

View File

@ -1,15 +1,23 @@
# -*- coding: utf-8 -*-
# pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,attribute-defined-outside-init
"""
Form implementation generated from reading ui file 'settings.ui'
# Form implementation generated from reading ui file 'settings.ui'
#
# Created: Thu Dec 25 23:21:20 2014
# by: PyQt4 UI code generator 4.10.3
#
# WARNING! All changes made in this file will be lost!
Created: Thu Dec 25 23:21:20 2014
by: PyQt4 UI code generator 4.10.3
WARNING! All changes made in this file will be lost!
"""
from __future__ import absolute_import
from sys import platform
from PyQt4 import QtCore, QtGui
from languagebox import LanguageBox
from sys import platform
from . import bitmessage_icons_rc # pylint: disable=unused-import
from .languagebox import LanguageBox
try:
_fromUtf8 = QtCore.QString.fromUtf8
@ -19,21 +27,27 @@ except AttributeError:
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_settingsDialog(object):
"""Encapsulate a UI settings dialog object"""
def setupUi(self, settingsDialog):
"""Set up the UI"""
settingsDialog.setObjectName(_fromUtf8("settingsDialog"))
settingsDialog.resize(521, 413)
self.gridLayout = QtGui.QGridLayout(settingsDialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.buttonBox = QtGui.QDialogButtonBox(settingsDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
self.tabWidgetSettings = QtGui.QTabWidget(settingsDialog)
@ -64,7 +78,8 @@ class Ui_settingsDialog(object):
self.formLayout.setWidget(1, QtGui.QFormLayout.SpanningRole, self.groupBoxTray)
self.checkBoxHideTrayConnectionNotifications = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxHideTrayConnectionNotifications.setChecked(False)
self.checkBoxHideTrayConnectionNotifications.setObjectName(_fromUtf8("checkBoxHideTrayConnectionNotifications"))
self.checkBoxHideTrayConnectionNotifications.setObjectName(
_fromUtf8("checkBoxHideTrayConnectionNotifications"))
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.checkBoxHideTrayConnectionNotifications)
self.checkBoxShowTrayNotifications = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxShowTrayNotifications.setObjectName(_fromUtf8("checkBoxShowTrayNotifications"))
@ -96,7 +111,7 @@ class Ui_settingsDialog(object):
self.formLayout_2.setObjectName(_fromUtf8("formLayout_2"))
self.languageComboBox = LanguageBox(self.groupBox)
self.languageComboBox.setMinimumSize(QtCore.QSize(100, 0))
self.languageComboBox.setObjectName(_fromUtf8("languageComboBox"))
self.languageComboBox.setObjectName(_fromUtf8("languageComboBox")) # pylint: disable=not-callable
self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.languageComboBox)
self.formLayout.setWidget(9, QtGui.QFormLayout.FieldRole, self.groupBox)
self.tabWidgetSettings.addTab(self.tabUserInterface, _fromUtf8(""))
@ -108,8 +123,6 @@ class Ui_settingsDialog(object):
self.groupBox1.setObjectName(_fromUtf8("groupBox1"))
self.gridLayout_3 = QtGui.QGridLayout(self.groupBox1)
self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
#spacerItem = QtGui.QSpacerItem(125, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
#self.gridLayout_3.addItem(spacerItem, 0, 0, 1, 1)
self.label = QtGui.QLabel(self.groupBox1)
self.label.setObjectName(_fromUtf8("label"))
self.gridLayout_3.addWidget(self.label, 0, 0, 1, 1, QtCore.Qt.AlignRight)
@ -165,7 +178,8 @@ class Ui_settingsDialog(object):
self.lineEditMaxOutboundConnections.setSizePolicy(sizePolicy)
self.lineEditMaxOutboundConnections.setMaximumSize(QtCore.QSize(60, 16777215))
self.lineEditMaxOutboundConnections.setObjectName(_fromUtf8("lineEditMaxOutboundConnections"))
self.lineEditMaxOutboundConnections.setValidator(QtGui.QIntValidator(0, 8, self.lineEditMaxOutboundConnections))
self.lineEditMaxOutboundConnections.setValidator(
QtGui.QIntValidator(0, 8, self.lineEditMaxOutboundConnections))
self.gridLayout_9.addWidget(self.lineEditMaxOutboundConnections, 2, 2, 1, 1)
self.gridLayout_4.addWidget(self.groupBox_3, 2, 0, 1, 1)
self.groupBox_2 = QtGui.QGroupBox(self.tabNetworkSettings)
@ -207,7 +221,8 @@ class Ui_settingsDialog(object):
self.gridLayout_2.addWidget(self.label_6, 2, 4, 1, 1)
self.lineEditSocksPassword = QtGui.QLineEdit(self.groupBox_2)
self.lineEditSocksPassword.setEnabled(False)
self.lineEditSocksPassword.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText)
self.lineEditSocksPassword.setInputMethodHints(
QtCore.Qt.ImhHiddenText | QtCore.Qt.ImhNoAutoUppercase | QtCore.Qt.ImhNoPredictiveText)
self.lineEditSocksPassword.setEchoMode(QtGui.QLineEdit.Password)
self.lineEditSocksPassword.setObjectName(_fromUtf8("lineEditSocksPassword"))
self.gridLayout_2.addWidget(self.lineEditSocksPassword, 2, 5, 1, 1)
@ -215,7 +230,7 @@ class Ui_settingsDialog(object):
self.checkBoxSocksListen.setObjectName(_fromUtf8("checkBoxSocksListen"))
self.gridLayout_2.addWidget(self.checkBoxSocksListen, 3, 1, 1, 4)
self.comboBoxProxyType = QtGui.QComboBox(self.groupBox_2)
self.comboBoxProxyType.setObjectName(_fromUtf8("comboBoxProxyType"))
self.comboBoxProxyType.setObjectName(_fromUtf8("comboBoxProxyType")) # pylint: disable=not-callable
self.comboBoxProxyType.addItem(_fromUtf8(""))
self.comboBoxProxyType.addItem(_fromUtf8(""))
self.comboBoxProxyType.addItem(_fromUtf8(""))
@ -229,7 +244,7 @@ class Ui_settingsDialog(object):
self.gridLayout_6 = QtGui.QGridLayout(self.tabDemandedDifficulty)
self.gridLayout_6.setObjectName(_fromUtf8("gridLayout_6"))
self.label_9 = QtGui.QLabel(self.tabDemandedDifficulty)
self.label_9.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_9.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_9.setObjectName(_fromUtf8("label_9"))
self.gridLayout_6.addWidget(self.label_9, 1, 1, 1, 1)
self.label_10 = QtGui.QLabel(self.tabDemandedDifficulty)
@ -237,7 +252,7 @@ class Ui_settingsDialog(object):
self.label_10.setObjectName(_fromUtf8("label_10"))
self.gridLayout_6.addWidget(self.label_10, 2, 0, 1, 3)
self.label_11 = QtGui.QLabel(self.tabDemandedDifficulty)
self.label_11.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_11.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_11.setObjectName(_fromUtf8("label_11"))
self.gridLayout_6.addWidget(self.label_11, 3, 1, 1, 1)
self.label_8 = QtGui.QLabel(self.tabDemandedDifficulty)
@ -285,7 +300,7 @@ class Ui_settingsDialog(object):
self.gridLayout_7.addItem(spacerItem6, 1, 0, 1, 1)
self.label_13 = QtGui.QLabel(self.tabMaxAcceptableDifficulty)
self.label_13.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label_13.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_13.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_13.setObjectName(_fromUtf8("label_13"))
self.gridLayout_7.addWidget(self.label_13, 1, 1, 1, 1)
self.lineEditMaxAcceptableTotalDifficulty = QtGui.QLineEdit(self.tabMaxAcceptableDifficulty)
@ -300,7 +315,7 @@ class Ui_settingsDialog(object):
spacerItem7 = QtGui.QSpacerItem(102, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_7.addItem(spacerItem7, 2, 0, 1, 1)
self.label_14 = QtGui.QLabel(self.tabMaxAcceptableDifficulty)
self.label_14.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_14.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_14.setObjectName(_fromUtf8("label_14"))
self.gridLayout_7.addWidget(self.label_14, 2, 1, 1, 1)
self.lineEditMaxAcceptableSmallMessageDifficulty = QtGui.QLineEdit(self.tabMaxAcceptableDifficulty)
@ -310,7 +325,8 @@ class Ui_settingsDialog(object):
sizePolicy.setHeightForWidth(self.lineEditMaxAcceptableSmallMessageDifficulty.sizePolicy().hasHeightForWidth())
self.lineEditMaxAcceptableSmallMessageDifficulty.setSizePolicy(sizePolicy)
self.lineEditMaxAcceptableSmallMessageDifficulty.setMaximumSize(QtCore.QSize(70, 16777215))
self.lineEditMaxAcceptableSmallMessageDifficulty.setObjectName(_fromUtf8("lineEditMaxAcceptableSmallMessageDifficulty"))
self.lineEditMaxAcceptableSmallMessageDifficulty.setObjectName(
_fromUtf8("lineEditMaxAcceptableSmallMessageDifficulty"))
self.gridLayout_7.addWidget(self.lineEditMaxAcceptableSmallMessageDifficulty, 2, 2, 1, 1)
spacerItem8 = QtGui.QSpacerItem(20, 147, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout_7.addItem(spacerItem8, 3, 1, 1, 1)
@ -332,7 +348,7 @@ class Ui_settingsDialog(object):
self.label_16.setObjectName(_fromUtf8("label_16"))
self.gridLayout_8.addWidget(self.label_16, 0, 0, 1, 3)
self.label_17 = QtGui.QLabel(self.tabNamecoin)
self.label_17.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_17.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_17.setObjectName(_fromUtf8("label_17"))
self.gridLayout_8.addWidget(self.label_17, 2, 1, 1, 1)
self.lineEditNamecoinHost = QtGui.QLineEdit(self.tabNamecoin)
@ -344,7 +360,7 @@ class Ui_settingsDialog(object):
self.gridLayout_8.addItem(spacerItem11, 4, 0, 1, 1)
self.label_18 = QtGui.QLabel(self.tabNamecoin)
self.label_18.setEnabled(True)
self.label_18.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_18.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_18.setObjectName(_fromUtf8("label_18"))
self.gridLayout_8.addWidget(self.label_18, 3, 1, 1, 1)
self.lineEditNamecoinPort = QtGui.QLineEdit(self.tabNamecoin)
@ -353,7 +369,7 @@ class Ui_settingsDialog(object):
spacerItem12 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout_8.addItem(spacerItem12, 8, 1, 1, 1)
self.labelNamecoinUser = QtGui.QLabel(self.tabNamecoin)
self.labelNamecoinUser.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.labelNamecoinUser.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.labelNamecoinUser.setObjectName(_fromUtf8("labelNamecoinUser"))
self.gridLayout_8.addWidget(self.labelNamecoinUser, 4, 1, 1, 1)
self.lineEditNamecoinUser = QtGui.QLineEdit(self.tabNamecoin)
@ -362,11 +378,13 @@ class Ui_settingsDialog(object):
spacerItem13 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_8.addItem(spacerItem13, 5, 0, 1, 1)
self.labelNamecoinPassword = QtGui.QLabel(self.tabNamecoin)
self.labelNamecoinPassword.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.labelNamecoinPassword.setAlignment(
QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.labelNamecoinPassword.setObjectName(_fromUtf8("labelNamecoinPassword"))
self.gridLayout_8.addWidget(self.labelNamecoinPassword, 5, 1, 1, 1)
self.lineEditNamecoinPassword = QtGui.QLineEdit(self.tabNamecoin)
self.lineEditNamecoinPassword.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText)
self.lineEditNamecoinPassword.setInputMethodHints(
QtCore.Qt.ImhHiddenText | QtCore.Qt.ImhNoAutoUppercase | QtCore.Qt.ImhNoPredictiveText)
self.lineEditNamecoinPassword.setEchoMode(QtGui.QLineEdit.Password)
self.lineEditNamecoinPassword.setObjectName(_fromUtf8("lineEditNamecoinPassword"))
self.gridLayout_8.addWidget(self.lineEditNamecoinPassword, 5, 2, 1, 1)
@ -405,11 +423,11 @@ class Ui_settingsDialog(object):
self.widget.setObjectName(_fromUtf8("widget"))
self.label_19 = QtGui.QLabel(self.widget)
self.label_19.setGeometry(QtCore.QRect(10, 20, 101, 20))
self.label_19.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_19.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_19.setObjectName(_fromUtf8("label_19"))
self.label_20 = QtGui.QLabel(self.widget)
self.label_20.setGeometry(QtCore.QRect(30, 40, 80, 16))
self.label_20.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.label_20.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
self.label_20.setObjectName(_fromUtf8("label_20"))
self.lineEditDays = QtGui.QLineEdit(self.widget)
self.lineEditDays.setGeometry(QtCore.QRect(113, 20, 51, 20))
@ -431,10 +449,20 @@ class Ui_settingsDialog(object):
self.retranslateUi(settingsDialog)
self.tabWidgetSettings.setCurrentIndex(0)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), settingsDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), settingsDialog.reject)
QtCore.QObject.connect(self.checkBoxAuthentication, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditSocksUsername.setEnabled)
QtCore.QObject.connect(self.checkBoxAuthentication, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.lineEditSocksPassword.setEnabled)
QtCore.QObject.connect( # pylint: disable=no-member
self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), settingsDialog.accept)
QtCore.QObject.connect( # pylint: disable=no-member
self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), settingsDialog.reject)
QtCore.QObject.connect( # pylint: disable=no-member
self.checkBoxAuthentication,
QtCore.SIGNAL(
_fromUtf8("toggled(bool)")),
self.lineEditSocksUsername.setEnabled)
QtCore.QObject.connect( # pylint: disable=no-member
self.checkBoxAuthentication,
QtCore.SIGNAL(
_fromUtf8("toggled(bool)")),
self.lineEditSocksPassword.setEnabled)
QtCore.QMetaObject.connectSlotsByName(settingsDialog)
settingsDialog.setTabOrder(self.tabWidgetSettings, self.checkBoxStartOnLogon)
settingsDialog.setTabOrder(self.checkBoxStartOnLogon, self.checkBoxStartInTray)
@ -450,22 +478,47 @@ class Ui_settingsDialog(object):
settingsDialog.setTabOrder(self.checkBoxSocksListen, self.buttonBox)
def retranslateUi(self, settingsDialog):
"""Re-translate the UI into the supported languages"""
settingsDialog.setWindowTitle(_translate("settingsDialog", "Settings", None))
self.checkBoxStartOnLogon.setText(_translate("settingsDialog", "Start Bitmessage on user login", None))
self.groupBoxTray.setTitle(_translate("settingsDialog", "Tray", None))
self.checkBoxStartInTray.setText(_translate("settingsDialog", "Start Bitmessage in the tray (don\'t show main window)", None))
self.checkBoxStartInTray.setText(
_translate(
"settingsDialog",
"Start Bitmessage in the tray (don\'t show main window)",
None))
self.checkBoxMinimizeToTray.setText(_translate("settingsDialog", "Minimize to tray", None))
self.checkBoxTrayOnClose.setText(_translate("settingsDialog", "Close to tray", None))
self.checkBoxHideTrayConnectionNotifications.setText(_translate("settingsDialog", "Hide connection notifications", None))
self.checkBoxShowTrayNotifications.setText(_translate("settingsDialog", "Show notification when message received", None))
self.checkBoxHideTrayConnectionNotifications.setText(
_translate("settingsDialog", "Hide connection notifications", None))
self.checkBoxShowTrayNotifications.setText(
_translate(
"settingsDialog",
"Show notification when message received",
None))
self.checkBoxPortableMode.setText(_translate("settingsDialog", "Run in Portable Mode", None))
self.PortableModeDescription.setText(_translate("settingsDialog", "In Portable Mode, messages and config files are stored in the same directory as the program rather than the normal application-data folder. This makes it convenient to run Bitmessage from a USB thumb drive.", None))
self.checkBoxWillinglySendToMobile.setText(_translate("settingsDialog", "Willingly include unencrypted destination address when sending to a mobile device", None))
self.PortableModeDescription.setText(
_translate(
"settingsDialog",
"In Portable Mode, messages and config files are stored in the same directory as the"
" program rather than the normal application-data folder. This makes it convenient to"
" run Bitmessage from a USB thumb drive.",
None))
self.checkBoxWillinglySendToMobile.setText(
_translate(
"settingsDialog",
"Willingly include unencrypted destination address when sending to a mobile device",
None))
self.checkBoxUseIdenticons.setText(_translate("settingsDialog", "Use Identicons", None))
self.checkBoxReplyBelow.setText(_translate("settingsDialog", "Reply below Quote", None))
self.groupBox.setTitle(_translate("settingsDialog", "Interface Language", None))
self.languageComboBox.setItemText(0, _translate("settingsDialog", "System Settings", "system"))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabUserInterface), _translate("settingsDialog", "User Interface", None))
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabUserInterface),
_translate(
"settingsDialog", "User Interface", None))
self.groupBox1.setTitle(_translate("settingsDialog", "Listening port", None))
self.label.setText(_translate("settingsDialog", "Listen for connections on port:", None))
self.labelUPnP.setText(_translate("settingsDialog", "UPnP:", None))
@ -480,23 +533,70 @@ class Ui_settingsDialog(object):
self.checkBoxAuthentication.setText(_translate("settingsDialog", "Authentication", None))
self.label_5.setText(_translate("settingsDialog", "Username:", None))
self.label_6.setText(_translate("settingsDialog", "Pass:", None))
self.checkBoxSocksListen.setText(_translate("settingsDialog", "Listen for incoming connections when using proxy", None))
self.checkBoxSocksListen.setText(
_translate(
"settingsDialog",
"Listen for incoming connections when using proxy",
None))
self.comboBoxProxyType.setItemText(0, _translate("settingsDialog", "none", None))
self.comboBoxProxyType.setItemText(1, _translate("settingsDialog", "SOCKS4a", None))
self.comboBoxProxyType.setItemText(2, _translate("settingsDialog", "SOCKS5", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNetworkSettings), _translate("settingsDialog", "Network Settings", None))
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabNetworkSettings),
_translate(
"settingsDialog", "Network Settings", None))
self.label_9.setText(_translate("settingsDialog", "Total difficulty:", None))
self.label_10.setText(_translate("settingsDialog", "The \'Total difficulty\' affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.", None))
self.label_10.setText(
_translate(
"settingsDialog",
"The \'Total difficulty\' affects the absolute amount of work the sender must complete."
" Doubling this value doubles the amount of work.",
None))
self.label_11.setText(_translate("settingsDialog", "Small message difficulty:", None))
self.label_8.setText(_translate("settingsDialog", "When someone sends you a message, their computer must first complete some work. The difficulty of this work, by default, is 1. You may raise this default for new addresses you create by changing the values here. Any new addresses you create will require senders to meet the higher difficulty. There is one exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically notify them when you next send a message that they need only complete the minimum amount of work: difficulty 1. ", None))
self.label_12.setText(_translate("settingsDialog", "The \'Small message difficulty\' mostly only affects the difficulty of sending small messages. Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really affect large messages.", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabDemandedDifficulty), _translate("settingsDialog", "Demanded difficulty", None))
self.label_15.setText(_translate("settingsDialog", "Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.", None))
self.label_8.setText(_translate(
"settingsDialog",
"When someone sends you a message, their computer must first complete some work. The difficulty of this"
" work, by default, is 1. You may raise this default for new addresses you create by changing the values"
" here. Any new addresses you create will require senders to meet the higher difficulty. There is one"
" exception: if you add a friend or acquaintance to your address book, Bitmessage will automatically"
" notify them when you next send a message that they need only complete the minimum amount of"
" work: difficulty 1. ",
None))
self.label_12.setText(
_translate(
"settingsDialog",
"The \'Small message difficulty\' mostly only affects the difficulty of sending small messages."
" Doubling this value makes it almost twice as difficult to send a small message but doesn\'t really"
" affect large messages.",
None))
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabDemandedDifficulty),
_translate(
"settingsDialog", "Demanded difficulty", None))
self.label_15.setText(
_translate(
"settingsDialog",
"Here you may set the maximum amount of work you are willing to do to send a message to another"
" person. Setting these values to 0 means that any value is acceptable.",
None))
self.label_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None))
self.label_14.setText(_translate("settingsDialog", "Maximum acceptable small message difficulty:", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabMaxAcceptableDifficulty), _translate("settingsDialog", "Max acceptable difficulty", None))
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabMaxAcceptableDifficulty),
_translate(
"settingsDialog", "Max acceptable difficulty", None))
self.labelOpenCL.setText(_translate("settingsDialog", "Hardware GPU acceleration (OpenCL):", None))
self.label_16.setText(_translate("settingsDialog", "<html><head/><body><p>Bitmessage can utilize a different Bitcoin-based program called Namecoin to make addresses human-friendly. For example, instead of having to tell your friend your long Bitmessage address, you can simply tell him to send a message to <span style=\" font-style:italic;\">test. </span></p><p>(Getting your own Bitmessage address into Namecoin is still rather difficult).</p><p>Bitmessage can use either namecoind directly or a running nmcontrol instance.</p></body></html>", None))
self.label_16.setText(_translate(
"settingsDialog",
"<html><head/><body><p>Bitmessage can utilize a different Bitcoin-based program called Namecoin to make"
" addresses human-friendly. For example, instead of having to tell your friend your long Bitmessage"
" address, you can simply tell him to send a message to <span style=\" font-style:italic;\">test."
" </span></p><p>(Getting your own Bitmessage address into Namecoin is still rather difficult).</p>"
"<p>Bitmessage can use either namecoind directly or a running nmcontrol instance.</p></body></html>",
None))
self.label_17.setText(_translate("settingsDialog", "Host:", None))
self.label_18.setText(_translate("settingsDialog", "Port:", None))
self.labelNamecoinUser.setText(_translate("settingsDialog", "Username:", None))
@ -505,12 +605,26 @@ class Ui_settingsDialog(object):
self.label_21.setText(_translate("settingsDialog", "Connect to:", None))
self.radioButtonNamecoinNamecoind.setText(_translate("settingsDialog", "Namecoind", None))
self.radioButtonNamecoinNmcontrol.setText(_translate("settingsDialog", "NMControl", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabNamecoin), _translate("settingsDialog", "Namecoin integration", None))
self.label_7.setText(_translate("settingsDialog", "<html><head/><body><p>By default, if you send a message to someone and he is offline for more than two days, Bitmessage will send the message again after an additional two days. This will be continued with exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain number of days or months.</p><p>Leave these input fields blank for the default behavior. </p></body></html>", None))
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabNamecoin),
_translate(
"settingsDialog", "Namecoin integration", None))
self.label_7.setText(_translate(
"settingsDialog",
"<html><head/><body><p>By default, if you send a message to someone and he is offline for more than two"
" days, Bitmessage will send the message again after an additional two days. This will be continued with"
" exponential backoff forever; messages will be resent after 5, 10, 20 days ect. until the receiver"
" acknowledges them. Here you may change that behavior by having Bitmessage give up after a certain"
" number of days or months.</p><p>Leave these input fields blank for the default behavior."
" </p></body></html>",
None))
self.label_19.setText(_translate("settingsDialog", "Give up after", None))
self.label_20.setText(_translate("settingsDialog", "and", None))
self.label_22.setText(_translate("settingsDialog", "days", None))
self.label_23.setText(_translate("settingsDialog", "months.", None))
self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabResendsExpire), _translate("settingsDialog", "Resends Expire", None))
import bitmessage_icons_rc
self.tabWidgetSettings.setTabText(
self.tabWidgetSettings.indexOf(
self.tabResendsExpire),
_translate(
"settingsDialog", "Resends Expire", None))

View File

@ -1,54 +1,64 @@
# Copyright (C) 2013 by Daniel Kraft <d@domob.eu>
# This file is part of the Bitmessage project.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# pylint: disable=too-many-branches,protected-access
"""
Copyright (C) 2013 by Daniel Kraft <d@domob.eu>
This file is part of the Bitmessage project.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
.. todo:: from debug import logger crashes PyBitmessage due to a circular dependency. The debug module will also
override/disable logging.getLogger() # loggers so module level logging functions are used instead
"""
from __future__ import absolute_import
import base64
import httplib
import json
import os
import socket
import sys
import os
from bmconfigparser import BMConfigParser
import defaults
import tr # translate
# FIXME: from debug import logger crashes PyBitmessage due to a circular
# dependency. The debug module will also override/disable logging.getLogger()
# loggers so module level logging functions are used instead
import logging as logger
import defaults
import tr # translate
from bmconfigparser import BMConfigParser
configSection = "bitmessagesettings"
# Error thrown when the RPC call returns an error.
class RPCError (Exception):
class RPCError(Exception):
"""Error thrown when the RPC call returns an error."""
error = None
def __init__ (self, data):
def __init__(self, data):
super(RPCError, self).__init__()
self.error = data
def __str__(self):
return '{0}: {1}'.format(type(self).__name__, self.error)
# This class handles the Namecoin identity integration.
class namecoinConnection (object):
class namecoinConnection(object):
"""This class handles the Namecoin identity integration."""
user = None
password = None
host = None
@ -58,47 +68,51 @@ class namecoinConnection (object):
queryid = 1
con = None
# Initialise. If options are given, take the connection settings from
# them instead of loading from the configs. This can be used to test
# currently entered connection settings in the config dialog without
# actually changing the values (yet).
def __init__ (self, options = None):
def __init__(self, options=None):
"""
Initialise. If options are given, take the connection settings from
them instead of loading from the configs. This can be used to test
currently entered connection settings in the config dialog without
actually changing the values (yet).
"""
if options is None:
self.nmctype = BMConfigParser().get (configSection, "namecoinrpctype")
self.host = BMConfigParser().get (configSection, "namecoinrpchost")
self.port = int(BMConfigParser().get (configSection, "namecoinrpcport"))
self.user = BMConfigParser().get (configSection, "namecoinrpcuser")
self.password = BMConfigParser().get (configSection,
"namecoinrpcpassword")
self.nmctype = BMConfigParser().get(configSection, "namecoinrpctype")
self.host = BMConfigParser().get(configSection, "namecoinrpchost")
self.port = int(BMConfigParser().get(configSection, "namecoinrpcport"))
self.user = BMConfigParser().get(configSection, "namecoinrpcuser")
self.password = BMConfigParser().get(configSection,
"namecoinrpcpassword")
else:
self.nmctype = options["type"]
self.host = options["host"]
self.port = int(options["port"])
self.user = options["user"]
self.password = options["password"]
self.nmctype = options["type"]
self.host = options["host"]
self.port = int(options["port"])
self.user = options["user"]
self.password = options["password"]
assert self.nmctype == "namecoind" or self.nmctype == "nmcontrol"
if self.nmctype == "namecoind":
self.con = httplib.HTTPConnection(self.host, self.port, timeout = 3)
self.con = httplib.HTTPConnection(self.host, self.port, timeout=3)
# Query for the bitmessage address corresponding to the given identity
# string. If it doesn't contain a slash, id/ is prepended. We return
# the result as (Error, Address) pair, where the Error is an error
# message to display or None in case of success.
def query (self, string):
slashPos = string.find ("/")
def query(self, string):
"""
Query for the bitmessage address corresponding to the given identity
string. If it doesn't contain a slash, id/ is prepended. We return
the result as (Error, Address) pair, where the Error is an error
message to display or None in case of success.
"""
slashPos = string.find("/")
if slashPos < 0:
string = "id/" + string
try:
if self.nmctype == "namecoind":
res = self.callRPC ("name_show", [string])
res = self.callRPC("name_show", [string])
res = res["value"]
elif self.nmctype == "nmcontrol":
res = self.callRPC ("data", ["getValue", string])
res = self.callRPC("data", ["getValue", string])
res = res["reply"]
if res == False:
return (tr._translate("MainWindow",'The name %1 was not found.').arg(unicode(string)), None)
if not res:
return (tr._translate("MainWindow", 'The name %1 was not found.').arg(unicode(string)), None)
else:
assert False
except RPCError as exc:
@ -107,16 +121,16 @@ class namecoinConnection (object):
errmsg = exc.error["message"]
else:
errmsg = exc.error
return (tr._translate("MainWindow",'The namecoin query failed (%1)').arg(unicode(errmsg)), None)
except Exception as exc:
return (tr._translate("MainWindow", 'The namecoin query failed (%1)').arg(unicode(errmsg)), None)
except Exception:
logger.exception("Namecoin query exception")
return (tr._translate("MainWindow",'The namecoin query failed.'), None)
return (tr._translate("MainWindow", 'The namecoin query failed.'), None)
try:
val = json.loads (res)
val = json.loads(res)
except:
logger.exception("Namecoin query json exception")
return (tr._translate("MainWindow",'The name %1 has no valid JSON data.').arg(unicode(string)), None)
return (tr._translate("MainWindow", 'The name %1 has no valid JSON data.').arg(unicode(string)), None)
if "bitmessage" in val:
if "name" in val:
@ -124,12 +138,19 @@ class namecoinConnection (object):
else:
ret = val["bitmessage"]
return (None, ret)
return (tr._translate("MainWindow",'The name %1 has no associated Bitmessage address.').arg(unicode(string)), None)
return (
tr._translate(
"MainWindow",
'The name %1 has no associated Bitmessage address.').arg(
unicode(string)),
None)
# Test the connection settings. This routine tries to query a "getinfo"
# command, and builds either an error message or a success message with
# some info from it.
def test(self):
"""
Test the connection settings. This routine tries to query a "getinfo"
command, and builds either an error message or a success message with
some info from it.
"""
try:
if self.nmctype == "namecoind":
try:
@ -143,22 +164,30 @@ class namecoinConnection (object):
vers = vers / 100
v1 = vers
if v3 == 0:
versStr = "0.%d.%d" % (v1, v2)
versStr = "0.%d.%d" % (v1, v2)
else:
versStr = "0.%d.%d.%d" % (v1, v2, v3)
return ('success', tr._translate("MainWindow",'Success! Namecoind version %1 running.').arg(unicode(versStr)) )
versStr = "0.%d.%d.%d" % (v1, v2, v3)
message = (
'success',
tr._translate(
"MainWindow",
'Success! Namecoind version %1 running.').arg(
unicode(versStr)))
elif self.nmctype == "nmcontrol":
res = self.callRPC ("data", ["status"])
res = self.callRPC("data", ["status"])
prefix = "Plugin data running"
if ("reply" in res) and res["reply"][:len(prefix)] == prefix:
return ('success', tr._translate("MainWindow",'Success! NMControll is up and running.'))
return ('success', tr._translate("MainWindow", 'Success! NMControll is up and running.'))
logger.error("Unexpected nmcontrol reply: %s", res)
return ('failed', tr._translate("MainWindow",'Couldn\'t understand NMControl.'))
message = ('failed', tr._translate("MainWindow", 'Couldn\'t understand NMControl.'))
else:
assert False
print "Unsupported Namecoin type"
sys.exit(1)
return message
except Exception:
logger.info("Namecoin connection test failure")
@ -168,20 +197,21 @@ class namecoinConnection (object):
"MainWindow", "The connection to namecoin failed.")
)
# Helper routine that actually performs an JSON RPC call.
def callRPC (self, method, params):
def callRPC(self, method, params):
"""Helper routine that actually performs an JSON RPC call."""
data = {"method": method, "params": params, "id": self.queryid}
if self.nmctype == "namecoind":
resp = self.queryHTTP (json.dumps (data))
resp = self.queryHTTP(json.dumps(data))
elif self.nmctype == "nmcontrol":
resp = self.queryServer (json.dumps (data))
resp = self.queryServer(json.dumps(data))
else:
assert False
val = json.loads (resp)
assert False
val = json.loads(resp)
if val["id"] != self.queryid:
raise Exception ("ID mismatch in JSON RPC answer.")
raise Exception("ID mismatch in JSON RPC answer.")
if self.nmctype == "namecoind":
self.queryid = self.queryid + 1
@ -190,11 +220,12 @@ class namecoinConnection (object):
return val["result"]
if isinstance(error, bool):
raise RPCError (val["result"])
raise RPCError (error)
raise RPCError(val["result"])
raise RPCError(error)
def queryHTTP(self, data):
"""Query the server via HTTP."""
# Query the server via HTTP.
def queryHTTP (self, data):
result = None
try:
@ -206,14 +237,14 @@ class namecoinConnection (object):
self.con.putheader("Content-Length", str(len(data)))
self.con.putheader("Accept", "application/json")
authstr = "%s:%s" % (self.user, self.password)
self.con.putheader("Authorization", "Basic %s" % base64.b64encode (authstr))
self.con.putheader("Authorization", "Basic %s" % base64.b64encode(authstr))
self.con.endheaders()
self.con.send(data)
try:
resp = self.con.getresponse()
result = resp.read()
if resp.status != 200:
raise Exception ("Namecoin returned status %i: %s", resp.status, resp.reason)
raise Exception("Namecoin returned status %i: %s" % resp.status, resp.reason)
except:
logger.info("HTTP receive error")
except:
@ -221,41 +252,49 @@ class namecoinConnection (object):
return result
# Helper routine sending data to the RPC server and returning the result.
def queryServer (self, data):
def queryServer(self, data):
"""Helper routine sending data to the RPC server and returning the result."""
try:
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(3)
s.connect ((self.host, self.port))
s.sendall (data)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.settimeout(3)
s.connect((self.host, self.port))
s.sendall(data)
result = ""
while True:
tmp = s.recv (self.bufsize)
tmp = s.recv(self.bufsize)
if not tmp:
break
break
result += tmp
s.close ()
s.close()
return result
except socket.error as exc:
raise Exception ("Socket error in RPC connection: %s" % str (exc))
raise Exception("Socket error in RPC connection: %s" % str(exc))
def lookupNamecoinFolder():
"""
Look up the namecoin data folder.
.. todo:: Check whether this works on other platforms as well!
"""
# Look up the namecoin data folder.
# FIXME: Check whether this works on other platforms as well!
def lookupNamecoinFolder ():
app = "namecoin"
from os import path, environ
if sys.platform == "darwin":
if "HOME" in environ:
dataFolder = path.join (os.environ["HOME"],
"Library/Application Support/", app) + '/'
dataFolder = path.join(os.environ["HOME"],
"Library/Application Support/", app) + '/'
else:
print ("Could not find home folder, please report this message"
+ " and your OS X version to the BitMessage Github.")
print(
"Could not find home folder, please report this message"
" and your OS X version to the BitMessage Github."
)
sys.exit()
elif "win32" in sys.platform or "win64" in sys.platform:
@ -265,34 +304,38 @@ def lookupNamecoinFolder ():
return dataFolder
# Ensure all namecoin options are set, by setting those to default values
# that aren't there.
def ensureNamecoinOptions ():
if not BMConfigParser().has_option (configSection, "namecoinrpctype"):
BMConfigParser().set (configSection, "namecoinrpctype", "namecoind")
if not BMConfigParser().has_option (configSection, "namecoinrpchost"):
BMConfigParser().set (configSection, "namecoinrpchost", "localhost")
hasUser = BMConfigParser().has_option (configSection, "namecoinrpcuser")
hasPass = BMConfigParser().has_option (configSection, "namecoinrpcpassword")
hasPort = BMConfigParser().has_option (configSection, "namecoinrpcport")
def ensureNamecoinOptions():
"""
Ensure all namecoin options are set, by setting those to default values
that aren't there.
"""
if not BMConfigParser().has_option(configSection, "namecoinrpctype"):
BMConfigParser().set(configSection, "namecoinrpctype", "namecoind")
if not BMConfigParser().has_option(configSection, "namecoinrpchost"):
BMConfigParser().set(configSection, "namecoinrpchost", "localhost")
hasUser = BMConfigParser().has_option(configSection, "namecoinrpcuser")
hasPass = BMConfigParser().has_option(configSection, "namecoinrpcpassword")
hasPort = BMConfigParser().has_option(configSection, "namecoinrpcport")
# Try to read user/password from .namecoin configuration file.
defaultUser = ""
defaultPass = ""
nmcFolder = lookupNamecoinFolder ()
nmcFolder = lookupNamecoinFolder()
nmcConfig = nmcFolder + "namecoin.conf"
try:
nmc = open (nmcConfig, "r")
nmc = open(nmcConfig, "r")
while True:
line = nmc.readline ()
line = nmc.readline()
if line == "":
break
parts = line.split ("=")
if len (parts) == 2:
parts = line.split("=")
if len(parts) == 2:
key = parts[0]
val = parts[1].rstrip ()
val = parts[1].rstrip()
if key == "rpcuser" and not hasUser:
defaultUser = val
@ -300,20 +343,20 @@ def ensureNamecoinOptions ():
defaultPass = val
if key == "rpcport":
defaults.namecoinDefaultRpcPort = val
nmc.close ()
nmc.close()
except IOError:
logger.error("%s unreadable or missing, Namecoin support deactivated", nmcConfig)
except Exception as exc:
except Exception:
logger.warning("Error processing namecoin.conf", exc_info=True)
# If still nothing found, set empty at least.
if (not hasUser):
BMConfigParser().set (configSection, "namecoinrpcuser", defaultUser)
if (not hasPass):
BMConfigParser().set (configSection, "namecoinrpcpassword", defaultPass)
if not hasUser:
BMConfigParser().set(configSection, "namecoinrpcuser", defaultUser)
if not hasPass:
BMConfigParser().set(configSection, "namecoinrpcpassword", defaultPass)
# Set default port now, possibly to found value.
if (not hasPort):
BMConfigParser().set (configSection, "namecoinrpcport",
defaults.namecoinDefaultRpcPort)
if not hasPort:
BMConfigParser().set(configSection, "namecoinrpcport",
defaults.namecoinDefaultRpcPort)