This commit is contained in:
Luke Montalvo 2014-04-30 19:09:29 -05:00
commit 276b8d3125
23 changed files with 1867 additions and 199 deletions

View File

@ -68,8 +68,8 @@ cd PyBitmessage && python src/bitmessagemain.py
```
##Creating a package for installation
If you really want, you can make a package for PyBitmessage which you may
install yourself or distribute to friends. This isn't reccomended, since
If you really want, you can make a package for PyBitmessage, which you may
install yourself or distribute to friends. This isn't recommended, since
PyBitmessage is in Beta, and subject to frequent change.
####Linux
@ -78,7 +78,7 @@ First off, since PyBitmessage uses something nifty called
[packagemonkey](https://github.com/fuzzgun/packagemonkey), go ahead and get
that installed. You may have to build it from source.
Next, edit the generate.sh script. To your liking.
Next, edit the generate.sh script to your liking.
Now, run the appropriate script for the type of package you'd like to make
```

View File

@ -4,7 +4,7 @@ PyBitmessage
Bitmessage is a P2P communications protocol used to send encrypted messages to
another person or to many subscribers. It is decentralized and trustless,
meaning that you need-not inherently trust any entities like root certificate
authorities. It uses strong authentication which means that the sender of a
authorities. It uses strong authentication, which means that the sender of a
message cannot be spoofed, and it aims to hide "non-content" data, like the
sender and receiver of messages, from passive eavesdroppers like those running
warrantless wiretapping programs.

View File

@ -24,14 +24,14 @@ sed -i 's/-'${PREV_VERSION}'.so/-'${VERSION}'.so/g' debian/*.links
make clean
rm -f archpackage/*.gz
# having the root directory called name-version seems essential
# Having the root directory called name-version seems essential
mv ../${APP} ../${APP}-${VERSION}
tar -cvzf ${SOURCE} ../${APP}-${VERSION} --exclude-vcs
# rename the root directory without the version number
# Rename the root directory without the version number
mv ../${APP}-${VERSION} ../${APP}
# calculate the MD5 checksum
# Calculate the MD5 checksum
CHECKSM=$(md5sum ${SOURCE})
sed -i "s/md5sums[^)]*)/md5sums=(${CHECKSM%% *})/g" archpackage/PKGBUILD

View File

@ -29,7 +29,7 @@ sed -i 's/-'${PREV_VERSION}'.so/-'${VERSION}'.so/g' debian/*.links
make clean
make
# change the parent directory name to debian format
# Change the parent directory name to Debian format
mv ../${APP} ../${DIR}
# Create a source archive
@ -38,9 +38,9 @@ make source
# Build the package
dpkg-buildpackage -F
# sign files
# Sign files
gpg -ba ../${APP}_${VERSION}-1_${ARCH_TYPE}.deb
gpg -ba ../${APP}_${VERSION}.orig.tar.gz
# restore the parent directory name
# Restore the parent directory name
mv ../${DIR} ../${APP}

View File

@ -21,13 +21,13 @@ sed -i "s/|${PREV_VERSION}|/|${VERSION}|/g" puppypackage/*.specs
sed -i 's/VERSION='${PREV_VERSION}'/VERSION='${VERSION}'/g' puppypackage/pinstall.sh puppypackage/puninstall.sh
sed -i 's/-'${PREV_VERSION}'.so/-'${VERSION}'.so/g' debian/*.links
# create the source code in the SOURCES directory
# Create the source code in the SOURCES directory
make clean
mkdir -p ~/ebuild
rm -f ${SOURCE}
mv ../${APP} ../${APP}-${VERSION}
tar -cvzf ${SOURCE} ../${APP}-${VERSION} --exclude-vcs
# rename the root directory without the version number
# Rename the root directory without the version number
mv ../${APP}-${VERSION} ../${APP}

12
rpm.sh
View File

@ -24,25 +24,25 @@ sed -i 's/-'${PREV_VERSION}'.so/-'${VERSION}'.so/g' debian/*.links
sudo yum groupinstall "Development Tools"
sudo yum install rpmdevtools
# setup the rpmbuild directory tree
# Setup the rpmbuild directory tree
rpmdev-setuptree
# create the source code in the SOURCES directory
# Create the source code in the SOURCES directory
make clean
mkdir -p ~/rpmbuild/SOURCES
rm -f ${SOURCE}
# having the root directory called name-version seems essential
# Having the root directory called name-version seems essential
mv ../${APP} ../${APP}-${VERSION}
tar -cvzf ${SOURCE} ../${APP}-${VERSION} --exclude-vcs
# rename the root directory without the version number
# Rename the root directory without the version number
mv ../${APP}-${VERSION} ../${APP}
# copy the spec file into the SPECS directory
# Copy the spec file into the SPECS directory
cp -f rpmpackage/${APP}.spec ~/rpmbuild/SPECS
# build
# Build
cd ~/rpmbuild/SPECS
rpmbuild -ba ${APP}.spec
cd ${CURRDIR}

View File

@ -34,6 +34,7 @@ import hashlib
from pyelliptic.openssl import OpenSSL
import pickle
import platform
import textwrap
import debug
from debug import logger
import subprocess
@ -771,7 +772,7 @@ class MyForm(QtGui.QMainWindow):
if shared.config.has_section(fromAddress):
fromLabel = shared.config.get(fromAddress, 'label')
if fromLabel == '':
else:
fromLabel = fromAddress
toLabel = ''
@ -2250,6 +2251,8 @@ class MyForm(QtGui.QMainWindow):
self.settingsDialogInstance.ui.checkBoxWillinglySendToMobile.isChecked()))
shared.config.set('bitmessagesettings', 'useidenticons', str(
self.settingsDialogInstance.ui.checkBoxUseIdenticons.isChecked()))
shared.config.set('bitmessagesettings', 'replybelow', str(
self.settingsDialogInstance.ui.checkBoxReplyBelow.isChecked()))
lang_ind = int(self.settingsDialogInstance.ui.languageComboBox.currentIndex())
if not languages[lang_ind] == 'other':
@ -2613,6 +2616,28 @@ class MyForm(QtGui.QMainWindow):
# We could also select upwards, but then our problem would be with the topmost message.
# self.ui.tableWidgetInbox.clearSelection() manages to mark the message as read again.
# Format predefined text on message reply.
def quoted_text(self, message):
if not shared.safeConfigGetBoolean('bitmessagesettings', 'replybelow'):
return '\n\n------------------------------------------------------\n' + message
quoteWrapper = textwrap.TextWrapper(replace_whitespace = False,
initial_indent = '> ',
subsequent_indent = '> ',
break_long_words = False,
break_on_hyphens = False)
def quote_line(line):
# Do quote empty lines.
if line == '' or line.isspace():
return '> '
# Quote already quoted lines, but do not wrap them.
elif line[0:2] == '> ':
return '> ' + line
# Wrap and quote lines/paragraphs new to this message.
else:
return quoteWrapper.fill(line)
return '\n'.join([quote_line(l) for l in message.splitlines()]) + '\n\n'
def on_action_InboxReply(self):
currentInboxRow = self.ui.tableWidgetInbox.currentRow()
toAddressAtCurrentInboxRow = str(self.ui.tableWidgetInbox.item(
@ -2655,7 +2680,8 @@ class MyForm(QtGui.QMainWindow):
else:
self.ui.comboBoxSendFrom.setCurrentIndex(0)
self.ui.textEditMessage.setText('\n\n------------------------------------------------------\n' + unicode(messageAtCurrentInboxRow, 'utf-8)'))
quotedText = self.quoted_text(unicode(messageAtCurrentInboxRow, 'utf-8'))
self.ui.textEditMessage.setText(quotedText)
if self.ui.tableWidgetInbox.item(currentInboxRow, 2).text()[0:3] in ['Re:', 'RE:']:
self.ui.lineEditSubject.setText(
self.ui.tableWidgetInbox.item(currentInboxRow, 2).text())
@ -3318,9 +3344,11 @@ class settingsDialog(QtGui.QDialog):
shared.safeConfigGetBoolean('bitmessagesettings', 'willinglysendtomobile'))
self.ui.checkBoxUseIdenticons.setChecked(
shared.safeConfigGetBoolean('bitmessagesettings', 'useidenticons'))
self.ui.checkBoxReplyBelow.setChecked(
shared.safeConfigGetBoolean('bitmessagesettings', 'replybelow'))
global languages
languages = ['system','en','eo','fr','de','es','ru','no','ar','zh_cn','en_pirate','other']
languages = ['system','en','eo','fr','de','es','ru','no','ar','zh_cn','ja','en_pirate','other']
user_countrycode = str(shared.config.get('bitmessagesettings', 'userlocale'))
if user_countrycode in languages:
curr_index = languages.index(user_countrycode)

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'settings.ui'
#
# Created: Mon Jan 20 14:26:31 2014
# Created: Wed Apr 30 18:35:41 2014
# by: PyQt4 UI code generator 4.10.3
#
# WARNING! All changes made in this file will be lost!
@ -26,7 +26,7 @@ except AttributeError:
class Ui_settingsDialog(object):
def setupUi(self, settingsDialog):
settingsDialog.setObjectName(_fromUtf8("settingsDialog"))
settingsDialog.resize(521, 399)
settingsDialog.resize(521, 413)
self.gridLayout = QtGui.QGridLayout(settingsDialog)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.buttonBox = QtGui.QDialogButtonBox(settingsDialog)
@ -72,6 +72,9 @@ class Ui_settingsDialog(object):
self.checkBoxUseIdenticons = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxUseIdenticons.setObjectName(_fromUtf8("checkBoxUseIdenticons"))
self.formLayout.setWidget(7, QtGui.QFormLayout.LabelRole, self.checkBoxUseIdenticons)
self.checkBoxReplyBelow = QtGui.QCheckBox(self.tabUserInterface)
self.checkBoxReplyBelow.setObjectName(_fromUtf8("checkBoxReplyBelow"))
self.formLayout.setWidget(8, QtGui.QFormLayout.LabelRole, self.checkBoxReplyBelow)
self.groupBox = QtGui.QGroupBox(self.tabUserInterface)
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.formLayout_2 = QtGui.QFormLayout(self.groupBox)
@ -91,8 +94,9 @@ class Ui_settingsDialog(object):
self.languageComboBox.addItem(_fromUtf8(""))
self.languageComboBox.addItem(_fromUtf8(""))
self.languageComboBox.addItem(_fromUtf8(""))
self.languageComboBox.addItem(_fromUtf8(""))
self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.languageComboBox)
self.formLayout.setWidget(8, QtGui.QFormLayout.FieldRole, self.groupBox)
self.formLayout.setWidget(9, QtGui.QFormLayout.FieldRole, self.groupBox)
self.tabWidgetSettings.addTab(self.tabUserInterface, _fromUtf8(""))
self.tabNetworkSettings = QtGui.QWidget()
self.tabNetworkSettings.setObjectName(_fromUtf8("tabNetworkSettings"))
@ -392,6 +396,7 @@ class Ui_settingsDialog(object):
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.languageComboBox.setItemText(1, _translate("settingsDialog", "English", "en"))
@ -399,12 +404,13 @@ class Ui_settingsDialog(object):
self.languageComboBox.setItemText(3, _translate("settingsDialog", "Français", "fr"))
self.languageComboBox.setItemText(4, _translate("settingsDialog", "Deutsch", "de"))
self.languageComboBox.setItemText(5, _translate("settingsDialog", "Españl", "es"))
self.languageComboBox.setItemText(6, _translate("settingsDialog", "русский язык", "ru"))
self.languageComboBox.setItemText(6, _translate("settingsDialog", "русский", "ru"))
self.languageComboBox.setItemText(7, _translate("settingsDialog", "Norsk", "no"))
self.languageComboBox.setItemText(8, _translate("settingsDialog", "العربية", "ar"))
self.languageComboBox.setItemText(9, _translate("settingsDialog", "简体中文", "zh_cn"))
self.languageComboBox.setItemText(10, _translate("settingsDialog", "Pirate English", "en_pirate"))
self.languageComboBox.setItemText(11, _translate("settingsDialog", "Other (set in keys.dat)", "other"))
self.languageComboBox.setItemText(10, _translate("settingsDialog", "日本語", "ja"))
self.languageComboBox.setItemText(11, _translate("settingsDialog", "Pirate English", "en_pirate"))
self.languageComboBox.setItemText(12, _translate("settingsDialog", "Other (set in keys.dat)", "other"))
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))

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>521</width>
<height>399</height>
<height>413</height>
</rect>
</property>
<property name="windowTitle">
@ -105,7 +105,14 @@
</property>
</widget>
</item>
<item row="8" column="1">
<item row="8" column="0">
<widget class="QCheckBox" name="checkBoxReplyBelow">
<property name="text">
<string>Reply below Quote</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Interface Language</string>
@ -151,7 +158,7 @@
</item>
<item>
<property name="text">
<string comment="ru">русский язык</string>
<string comment="ru">русский</string>
</property>
</item>
<item>
@ -169,6 +176,11 @@
<string comment="zh_cn">简体中文</string>
</property>
</item>
<item>
<property name="text">
<string comment="ja">日本語</string>
</property>
</item>
<item>
<property name="text">
<string comment="en_pirate">Pirate English</string>

View File

@ -22,26 +22,37 @@ class outgoingSynSender(threading.Thread):
self.streamNumber = streamNumber
self.selfInitiatedConnections = selfInitiatedConnections
def _getPeer(self):
# If the user has specified a trusted peer then we'll only
# ever connect to that. Otherwise we'll pick a random one from
# the known nodes
shared.knownNodesLock.acquire()
if shared.trustedPeer:
peer = shared.trustedPeer
shared.knownNodes[self.streamNumber][peer] = time.time()
else:
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
shared.knownNodesLock.release()
return peer
def run(self):
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
time.sleep(2)
while shared.safeConfigGetBoolean('bitmessagesettings', 'sendoutgoingconnections'):
while len(self.selfInitiatedConnections[self.streamNumber]) >= 8: # maximum number of outgoing connections = 8
maximumConnections = 1 if shared.trustedPeer else 8 # maximum number of outgoing connections = 8
while len(self.selfInitiatedConnections[self.streamNumber]) >= maximumConnections:
time.sleep(10)
if shared.shutdown:
break
random.seed()
shared.knownNodesLock.acquire()
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
shared.knownNodesLock.release()
peer = self._getPeer()
shared.alreadyAttemptedConnectionsListLock.acquire()
while peer in shared.alreadyAttemptedConnectionsList or peer.host in shared.connectedHostsList:
shared.alreadyAttemptedConnectionsListLock.release()
# print 'choosing new sample'
random.seed()
shared.knownNodesLock.acquire()
peer, = random.sample(shared.knownNodes[self.streamNumber], 1)
shared.knownNodesLock.release()
peer = self._getPeer()
time.sleep(1)
# Clear out the shared.alreadyAttemptedConnectionsList every half
# hour so that this program will again attempt a connection

View File

@ -147,9 +147,9 @@ class receiveDataThread(threading.Thread):
with shared.printLock:
print 'remoteCommand', repr(remoteCommand.replace('\x00', '')), ' from', self.peer
if remoteCommand == 'version\x00\x00\x00\x00\x00':
if remoteCommand == 'version\x00\x00\x00\x00\x00' and not self.connectionIsOrWasFullyEstablished:
self.recversion(self.data[24:self.payloadLength + 24])
elif remoteCommand == 'verack\x00\x00\x00\x00\x00\x00':
elif remoteCommand == 'verack\x00\x00\x00\x00\x00\x00' and not self.connectionIsOrWasFullyEstablished:
self.recverack()
elif remoteCommand == 'addr\x00\x00\x00\x00\x00\x00\x00\x00' and self.connectionIsOrWasFullyEstablished:
self.recaddr(self.data[24:self.payloadLength + 24])
@ -237,7 +237,12 @@ class receiveDataThread(threading.Thread):
self.connectionFullyEstablished()
def connectionFullyEstablished(self):
if self.connectionIsOrWasFullyEstablished:
# there is no reason to run this function a second time
return
self.connectionIsOrWasFullyEstablished = True
# Command the corresponding sendDataThread to set its own connectionIsOrWasFullyEstablished variable to True also
self.sendDataThreadQueue.put((0, 'connectionIsOrWasFullyEstablished', 'no data'))
if not self.initiatedConnection:
shared.clientHasReceivedIncomingConnections = True
shared.UISignalQueue.put(('setStatusIcon', 'green'))
@ -301,8 +306,9 @@ class receiveDataThread(threading.Thread):
self.sendinvMessageToJustThisOnePeer(
numberOfObjectsInInvMessage, payload)
# Self explanatory. Notice that there is also a broadcastinv function for
# broadcasting invs to everyone in our stream.
# Used to send a big inv message when the connection with a node is
# first fully established. Notice that there is also a broadcastinv
# function for broadcasting invs to everyone in our stream.
def sendinvMessageToJustThisOnePeer(self, numberOfObjects, payload):
payload = encodeVarint(numberOfObjects) + payload
headerData = '\xe9\xbe\xb4\xd9' # magic bits, slighly different from Bitcoin's magic bits.
@ -313,6 +319,14 @@ class receiveDataThread(threading.Thread):
print 'Sending huge inv message with', numberOfObjects, 'objects to just this one peer'
self.sendDataThreadQueue.put((0, 'sendRawData', headerData + payload))
def _sleepForTimingAttackMitigation(self, sleepTime):
# We don't need to do the timing attack mitigation if we are
# only connected to the trusted peer because we can trust the
# peer not to attack
if sleepTime > 0 and doTimingAttackMitigation and shared.trustedPeer == None:
with shared.printLock:
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
time.sleep(sleepTime)
# We have received a broadcast message
def recbroadcast(self, data):
@ -341,10 +355,7 @@ class receiveDataThread(threading.Thread):
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
(time.time() - self.messageProcessingStartTime)
if sleepTime > 0 and doTimingAttackMitigation:
with shared.printLock:
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
time.sleep(sleepTime)
self._sleepForTimingAttackMitigation(sleepTime)
# We have received a msg message.
def recmsg(self, data):
@ -373,10 +384,7 @@ class receiveDataThread(threading.Thread):
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
(time.time() - self.messageProcessingStartTime)
if sleepTime > 0 and doTimingAttackMitigation:
with shared.printLock:
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
time.sleep(sleepTime)
self._sleepForTimingAttackMitigation(sleepTime)
# We have received a pubkey
def recpubkey(self, data):
@ -387,11 +395,7 @@ class receiveDataThread(threading.Thread):
lengthOfTimeWeShouldUseToProcessThisMessage = .1
sleepTime = lengthOfTimeWeShouldUseToProcessThisMessage - \
(time.time() - self.pubkeyProcessingStartTime)
if sleepTime > 0 and doTimingAttackMitigation:
with shared.printLock:
print 'Timing attack mitigation: Sleeping for', sleepTime, 'seconds.'
time.sleep(sleepTime)
self._sleepForTimingAttackMitigation(sleepTime)
# We have received an inv message
def recinv(self, data):
@ -665,7 +669,10 @@ class receiveDataThread(threading.Thread):
print 'knownNodes currently has', len(shared.knownNodes[self.streamNumber]), 'nodes for this stream.'
# Send a big addr message to our peer
# Send a huge addr message to our peer. This is only used
# when we fully establish a connection with a
# peer (with the full exchange of version and verack
# messages).
def sendaddr(self):
addrsInMyStream = {}
addrsInChildStreamLeft = {}
@ -750,58 +757,68 @@ class receiveDataThread(threading.Thread):
if len(data) < 83:
# This version message is unreasonably short. Forget it.
return
elif not self.verackSent:
self.remoteProtocolVersion, = unpack('>L', data[:4])
if self.remoteProtocolVersion <= 1:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Closing connection to old protocol version 1 node: ', self.peer
return
# print 'remoteProtocolVersion', self.remoteProtocolVersion
self.myExternalIP = socket.inet_ntoa(data[40:44])
# print 'myExternalIP', self.myExternalIP
self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
# print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
useragentLength, lengthOfUseragentVarint = decodeVarint(
data[80:84])
readPosition = 80 + lengthOfUseragentVarint
useragent = data[readPosition:readPosition + useragentLength]
readPosition += useragentLength
numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
data[readPosition:])
readPosition += lengthOfNumberOfStreamsInVersionMessage
self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(
data[readPosition:])
if self.verackSent:
"""
We must have already processed the remote node's version message.
There might be a time in the future when we Do want to process
a new version message, like if the remote node wants to update
the streams in which they are interested. But for now we'll
ignore this version message
"""
return
self.remoteProtocolVersion, = unpack('>L', data[:4])
if self.remoteProtocolVersion <= 1:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Remote node useragent:', useragent, ' stream number:', self.streamNumber
print 'Closing connection to old protocol version 1 node: ', self.peer
return
# print 'remoteProtocolVersion', self.remoteProtocolVersion
self.myExternalIP = socket.inet_ntoa(data[40:44])
# print 'myExternalIP', self.myExternalIP
self.remoteNodeIncomingPort, = unpack('>H', data[70:72])
# print 'remoteNodeIncomingPort', self.remoteNodeIncomingPort
useragentLength, lengthOfUseragentVarint = decodeVarint(
data[80:84])
readPosition = 80 + lengthOfUseragentVarint
useragent = data[readPosition:readPosition + useragentLength]
readPosition += useragentLength
numberOfStreamsInVersionMessage, lengthOfNumberOfStreamsInVersionMessage = decodeVarint(
data[readPosition:])
readPosition += lengthOfNumberOfStreamsInVersionMessage
self.streamNumber, lengthOfRemoteStreamNumber = decodeVarint(
data[readPosition:])
with shared.printLock:
print 'Remote node useragent:', useragent, ' stream number:', self.streamNumber
if self.streamNumber != 1:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Closed connection to', self.peer, 'because they are interested in stream', self.streamNumber, '.'
return
shared.connectedHostsList[
self.peer.host] = 1 # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
# If this was an incoming connection, then the sendData thread
# doesn't know the stream. We have to set it.
if not self.initiatedConnection:
shared.broadcastToSendDataQueues((
0, 'setStreamNumber', (self.peer, self.streamNumber)))
if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Closing connection to myself: ', self.peer
return
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
if self.streamNumber != 1:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Closed connection to', self.peer, 'because they are interested in stream', self.streamNumber, '.'
return
shared.connectedHostsList[
self.peer.host] = 1 # We use this data structure to not only keep track of what hosts we are connected to so that we don't try to connect to them again, but also to list the connections count on the Network Status tab.
# If this was an incoming connection, then the sendData thread
# doesn't know the stream. We have to set it.
if not self.initiatedConnection:
self.sendDataThreadQueue.put((0, 'setStreamNumber', self.streamNumber))
if data[72:80] == shared.eightBytesOfRandomDataUsedToDetectConnectionsToSelf:
shared.broadcastToSendDataQueues((0, 'shutdown', self.peer))
with shared.printLock:
print 'Closing connection to myself: ', self.peer
return
# The other peer's protocol version is of interest to the sendDataThread but we learn of it
# in this version message. Let us inform the sendDataThread.
self.sendDataThreadQueue.put((0, 'setRemoteProtocolVersion', self.remoteProtocolVersion))
shared.knownNodesLock.acquire()
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
shared.needToWriteKnownNodesToDisk = True
shared.knownNodesLock.release()
shared.knownNodesLock.acquire()
shared.knownNodes[self.streamNumber][shared.Peer(self.peer.host, self.remoteNodeIncomingPort)] = int(time.time())
shared.needToWriteKnownNodesToDisk = True
shared.knownNodesLock.release()
self.sendverack()
if self.initiatedConnection == False:
self.sendversion()
self.sendverack()
if self.initiatedConnection == False:
self.sendversion()
# Sends a version message
def sendversion(self):

View File

@ -25,6 +25,7 @@ class sendDataThread(threading.Thread):
self.data = ''
self.objectHashHolderInstance = objectHashHolder(self.sendDataThreadQueue)
self.objectHashHolderInstance.start()
self.connectionIsOrWasFullyEstablished = False
def setup(
@ -71,16 +72,6 @@ class sendDataThread(threading.Thread):
if data == self.peer or data == 'all':
with shared.printLock:
print 'sendDataThread (associated with', self.peer, ') ID:', id(self), 'shutting down now.'
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
with shared.printLock:
print 'len of sendDataQueues', len(shared.sendDataQueues)
break
# When you receive an incoming connection, a sendDataThread is
# created even though you don't yet know what stream number the
@ -89,12 +80,9 @@ class sendDataThread(threading.Thread):
# will continue on with the connection and will set the
# streamNumber of this send data thread here:
elif command == 'setStreamNumber':
peerInMessage, specifiedStreamNumber = data
if peerInMessage == self.peer:
with shared.printLock:
print 'setting the stream number in the sendData thread (ID:', id(self), ') to', specifiedStreamNumber
self.streamNumber = specifiedStreamNumber
self.streamNumber = data
with shared.printLock:
print 'setting the stream number in the sendData thread (ID:', id(self), ') to', self.streamNumber
elif command == 'setRemoteProtocolVersion':
specifiedRemoteProtocolVersion = data
with shared.printLock:
@ -103,6 +91,9 @@ class sendDataThread(threading.Thread):
elif command == 'advertisepeer':
self.objectHashHolderInstance.holdPeer(data)
elif command == 'sendaddr':
if not self.connectionIsOrWasFullyEstablished:
# not sending addr because we haven't sent and heard a verack from the remote node yet
return
numberOfAddressesInAddrMessage = len(
data)
payload = ''
@ -127,17 +118,13 @@ class sendDataThread(threading.Thread):
self.lastTimeISentData = int(time.time())
except:
print 'sendaddr: self.sock.sendall failed'
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
print 'sendDataThread thread (ID:', str(id(self)) + ') ending now. Was connected to', self.peer
break
elif command == 'advertiseobject':
self.objectHashHolderInstance.holdHash(data)
elif command == 'sendinv':
if not self.connectionIsOrWasFullyEstablished:
# not sending inv because we haven't sent and heard a verack from the remote node yet
return
payload = ''
for hash in data:
if hash not in self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware:
@ -153,13 +140,6 @@ class sendDataThread(threading.Thread):
self.lastTimeISentData = int(time.time())
except:
print 'sendinv: self.sock.sendall failed'
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
print 'sendDataThread thread (ID:', str(id(self)) + ') ending now. Was connected to', self.peer
break
elif command == 'pong':
self.someObjectsOfWhichThisRemoteNodeIsAlreadyAware.clear() # To save memory, let us clear this data structure from time to time. As its function is to help us keep from sending inv messages to peers which sent us the same inv message mere seconds earlier, it will be fine to clear this data structure from time to time.
@ -174,29 +154,26 @@ class sendDataThread(threading.Thread):
self.lastTimeISentData = int(time.time())
except:
print 'send pong failed'
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
print 'sendDataThread thread', self, 'ending now. Was connected to', self.peer
break
elif command == 'sendRawData':
try:
self.sock.sendall(data)
self.lastTimeISentData = int(time.time())
except:
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
print 'Sending of data to', self.peer, 'failed. sendDataThread thread', self, 'ending now.'
break
elif command == 'connectionIsOrWasFullyEstablished':
self.connectionIsOrWasFullyEstablished = True
else:
with shared.printLock:
print 'sendDataThread ID:', id(self), 'ignoring command', command, 'because the thread is not in stream', deststream
try:
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
except:
pass
shared.sendDataQueues.remove(self.sendDataThreadQueue)
with shared.printLock:
print 'Number of queues remaining in sendDataQueues:', len(shared.sendDataQueues)
self.objectHashHolderInstance.close()

View File

@ -39,6 +39,11 @@ class singleListener(threading.Thread):
return sock
def run(self):
# If there is a trusted peer then we don't want to accept
# incoming connections so we'll just abandon the thread
if shared.trustedPeer:
return
while shared.safeConfigGetBoolean('bitmessagesettings', 'dontconnect'):
time.sleep(1)
helper_bootstrap.dns()

View File

@ -11,17 +11,17 @@ def createDefaultKnownNodes(appdata):
############## Stream 1 ################
stream1 = {}
stream1[shared.Peer('176.31.246.114', 8444)] = int(time.time())
stream1[shared.Peer('109.229.197.133', 8444)] = int(time.time())
stream1[shared.Peer('174.3.101.111', 8444)] = int(time.time())
stream1[shared.Peer('90.188.238.79', 7829)] = int(time.time())
stream1[shared.Peer('184.75.69.2', 8444)] = int(time.time())
stream1[shared.Peer('60.225.209.243', 8444)] = int(time.time())
stream1[shared.Peer('5.145.140.218', 8444)] = int(time.time())
stream1[shared.Peer('5.19.255.216', 8444)] = int(time.time())
stream1[shared.Peer('193.159.162.189', 8444)] = int(time.time())
stream1[shared.Peer('86.26.15.171', 8444)] = int(time.time())
#stream1[shared.Peer('2604:2000:1380:9f:82e:148b:2746:d0c7', 8080)] = int(time.time())
stream1[shared.Peer('68.33.0.104', 8444)] = int(time.time())
stream1[shared.Peer('97.77.34.35', 8444)] = int(time.time())
stream1[shared.Peer('71.232.195.131', 8444)] = int(time.time())
stream1[shared.Peer('192.241.231.39', 8444)] = int(time.time())
stream1[shared.Peer('75.66.0.116', 8444)] = int(time.time())
stream1[shared.Peer('182.169.23.102', 8444)] = int(time.time())
stream1[shared.Peer('75.95.134.9', 8444)] = int(time.time())
stream1[shared.Peer('46.236.100.108', 48444)] = int(time.time())
stream1[shared.Peer('66.108.53.42', 8080)] = int(time.time())
############# Stream 2 #################
stream2 = {}
# None yet

View File

@ -12,6 +12,17 @@ from namecoin import ensureNamecoinOptions
storeConfigFilesInSameDirectoryAsProgramByDefault = False # The user may de-select Portable Mode in the settings if they want the config files to stay in the application data folder.
def _loadTrustedPeer():
try:
trustedPeer = shared.config.get('bitmessagesettings', 'trustedpeer')
except ConfigParser.Error:
# This probably means the trusted peer wasn't specified so we
# can just leave it as None
return
host, port = trustedPeer.split(':')
shared.trustedPeer = shared.Peer(host, int(port))
def loadConfig():
if shared.appdata:
shared.config.read(shared.appdata + 'keys.dat')
@ -90,6 +101,7 @@ def loadConfig():
shared.config.set('bitmessagesettings', 'userlocale', 'system')
shared.config.set('bitmessagesettings', 'useidenticons', 'True')
shared.config.set('bitmessagesettings', 'identiconsuffix', ''.join(random.choice("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") for x in range(12))) # a twelve character pseudo-password to salt the identicons
shared.config.set('bitmessagesettings', 'replybelow', 'False')
#start:UI setting to stop trying to send messages after X days/months
shared.config.set(
@ -122,6 +134,8 @@ def loadConfig():
with open(shared.appdata + 'keys.dat', 'wb') as configfile:
shared.config.write(configfile)
_loadTrustedPeer()
def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
try:
VER_THIS=StrictVersion(platform.version())
@ -130,4 +144,4 @@ def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
return False
except Exception as err:
print 'An Exception occurred within isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections:', err
return False
return False

View File

@ -92,6 +92,18 @@ namecoinDefaultRpcPort = "8336"
# binary distributions vs source distributions.
frozen = getattr(sys,'frozen', None)
# If the trustedpeer option is specified in keys.dat then this will
# contain a Peer which will be connected to instead of using the
# addresses advertised by other peers. The client will only connect to
# this peer and the timing attack mitigation will be disabled in order
# to download data faster. The expected use case is where the user has
# a fast connection to a trusted server where they run a BitMessage
# daemon permanently. If they then run a second instance of the client
# on a local machine periodically when they want to check for messages
# it will sync with the network a lot faster without compromising
# security.
trustedPeer = None
def isInSqlInventory(hash):
queryreturn = sqlQuery('''select hash from inventory where hash=?''', hash)
return queryreturn != []

View File

@ -5,17 +5,17 @@
<message>
<location filename="../bitmessageqt/addaddressdialog.py" line="62"/>
<source>Add new entry</source>
<translation type="unfinished">Neuen Eintrag erstellen</translation>
<translation>Neuen Eintrag erstellen</translation>
</message>
<message>
<location filename="../bitmessageqt/addaddressdialog.py" line="63"/>
<source>Label</source>
<translation type="unfinished"></translation>
<translation>Name oder Bezeichnung</translation>
</message>
<message>
<location filename="../bitmessageqt/addaddressdialog.py" line="64"/>
<source>Address</source>
<translation type="unfinished">Adresse</translation>
<translation>Adresse</translation>
</message>
</context>
<context>
@ -153,7 +153,7 @@
<message>
<location filename="../bitmessageqt/__init__.py" line="850"/>
<source>Problem: The work demanded by the recipient is more difficult than you are willing to do. %1</source>
<translation>Problem: Die vom Empfänger geforderte Arbeit ist schwerer als Sie bereit sind zu berechnen. %1</translation>
<translation>Problem: Die vom Empfänger geforderte Arbeit ist schwerer als Sie bereit sind, zu berechnen. %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="853"/>
@ -686,7 +686,7 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="601"/>
<source>The Address book is useful for adding names or labels to other people&apos;s Bitmessage addresses so that you can recognize them more easily in your inbox. You can add entries here using the &apos;Add&apos; button, or from your inbox by right-clicking on a message.</source>
<translation>Das Adressbuch ist nützlich um die Bitmessage-Adressen anderer Personen Namen oder Beschreibungen zuzuordnen, so dass Sie sie einfacher im Posteingang erkennen können. Sie können Adressen über &quot;Hinzufügen&quot; eintragen, oder über einen Rechtsklick auf eine Nachricht im Posteingang.</translation>
<translation>Das Adressbuch ist nützlich, um die Bitmessage-Adressen anderer Personen Namen oder Beschreibungen zuzuordnen, sodass Sie sie einfacher im Posteingang erkennen können. Sie können Adressen über &quot;Neuen Eintrag erstellen&quot; hinzufügen, oder über einen Rechtsklick auf eine Nachricht im Posteingang.</translation>
</message>
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="614"/>
@ -946,7 +946,7 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../bitmessageqt/__init__.py" line="2998"/>
<source>Set avatar...</source>
<translation type="unfinished"></translation>
<translation>Avatar wählen...</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="1359"/>
@ -966,7 +966,7 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../bitmessageqt/__init__.py" line="1519"/>
<source>Inventory lookups per second: %1</source>
<translation type="unfinished"></translation>
<translation>Inventory lookups pro Sekunde: %1</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="2286"/>
@ -981,12 +981,12 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../bitmessageqt/__init__.py" line="3005"/>
<source>Do you really want to remove this avatar?</source>
<translation type="unfinished"></translation>
<translation>Wollen Sie diesen Avatar wirklich entfernen?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="3013"/>
<source>You have already set an avatar for this address. Do you really want to overwrite it?</source>
<translation type="unfinished"></translation>
<translation>Sie haben bereits einen Avatar für diese Adresse gewählt. Wollen Sie ihn wirklich überschreiben?</translation>
</message>
<message>
<location filename="../bitmessageqt/__init__.py" line="3287"/>
@ -1040,7 +1040,7 @@ p, li { white-space: pre-wrap; }
<message>
<location filename="../bitmessageqt/bitmessageui.py" line="627"/>
<source>Inventory lookups per second: 0</source>
<translation type="unfinished"></translation>
<translation>Inventory lookups pro Sekunde: 0</translation>
</message>
</context>
<context>
@ -1130,7 +1130,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="190"/>
<source> (best if this is the first of many addresses you will create)</source>
<translation>(zum generieren der erste Adresse empfohlen)</translation>
<translation>(Zum Generieren der ersten Adresse empfohlen)</translation>
</message>
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="191"/>
@ -1145,7 +1145,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/newaddressdialog.py" line="181"/>
<source>Address version number: 4</source>
<translation type="unfinished">Adress-Versionsnummer: 4</translation>
<translation>Adress-Versionsnummer: 4</translation>
</message>
</context>
<context>
@ -1275,7 +1275,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/help.py" line="47"/>
<source>As Bitmessage is a collaborative project, help can be found online in the Bitmessage Wiki:</source>
<translation>Bei Bitmessage handelt es sich um ein kollaboratives Projekt, Hilfe finden Sie online in Bitmessage-Wiki:</translation>
<translation>Bitmessage ist ein kollaboratives Projekt. Hilfe finden Sie online im Bitmessage-Wiki:</translation>
</message>
</context>
<context>
@ -1293,7 +1293,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/iconglossary.py" line="84"/>
<source>You have made at least one connection to a peer using an outgoing connection but you have not yet received any incoming connections. Your firewall or home router probably isn&apos;t configured to forward incoming TCP connections to your computer. Bitmessage will work just fine but it would help the Bitmessage network if you allowed for incoming connections and will help you be a better-connected node.</source>
<translation>Sie haben mindestes eine Verbindung mit einem Netzwerkteilnehmer über eine ausgehende Verbindung, aber Sie haben noch keine eingehende Verbindung. Ihre Firewall oder Router ist vermutlich nicht richtig konfiguriert um eingehende TCP-Verbindungen an Ihren Computer weiterzuleiten. Bittmessage wird gut funktionieren, jedoch helfen Sie dem Netzwerk, wenn Sie eingehende Verbindungen erlauben. Es hilft auch Ihnen schneller und mehr Verbindungen ins Netzwerk aufzubauen.</translation>
<translation>Sie haben mindestes eine Verbindung mit einem Netzwerkteilnehmer über eine ausgehende Verbindung, aber Sie haben noch keine eingehende Verbindung. Ihre Firewall oder Ihr Router ist vermutlich nicht richtig konfiguriert, um eingehende TCP-Verbindungen an Ihren Computer weiterzuleiten. Bitmessage wird gut funktionieren, jedoch helfen Sie dem Netzwerk, wenn Sie eingehende Verbindungen erlauben. Es hilft auch Ihnen schneller und mehr Verbindungen ins Netzwerk aufzubauen.</translation>
</message>
<message>
<location filename="../bitmessageqt/iconglossary.py" line="85"/>
@ -1336,7 +1336,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/newchandialog.py" line="104"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;A chan exists when a group of people share the same decryption keys. The keys and bitmessage address used by a chan are generated from a human-friendly word or phrase (the chan name). To send a message to everyone in the chan, send a normal person-to-person message to the chan address.&lt;/p&gt;&lt;p&gt;Chans are experimental and completely unmoderatable.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ein Chan existiert, wenn eine Gruppe von Leuten sich den gleichen Entschlüsselungscode teilen. Die Schlüssel und Bitmessage-Adressen werden basierend auf einem lesbaren Wort oder Satz generiert (Dem Chan-Namen). Um eine Nachricht an den Chan zu senden, senden Sie eine normale Person-zu-Person-Nachricht an die Chan-Adresse.&lt;/p&gt;&lt;p&gt;Chans sind experimentell and völlig unmoderierbar.&lt;/p&gt;&lt;br&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Ein Chan existiert, wenn eine Gruppe von Leuten sich den gleichen Entschlüsselungscode teilen. Die Schlüssel und Bitmessage-Adressen werden basierend auf einem lesbaren Wort oder Satz generiert (dem Chan-Namen). Um eine Nachricht an den Chan zu senden, senden Sie eine normale Person-zu-Person-Nachricht an die Chan-Adresse.&lt;/p&gt;&lt;p&gt;Chans sind experimentell und völlig unmoderierbar.&lt;/p&gt;&lt;br&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../bitmessageqt/newchandialog.py" line="106"/>
@ -1346,7 +1346,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/newchandialog.py" line="101"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter a name for your chan. If you choose a sufficiently complex chan name (like a strong and unique passphrase) and none of your friends share it publicly then the chan will be secure and private. If you and someone else both create a chan with the same chan name then it is currently very likely that they will be the same chan.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Geben Sie einen Namen für Ihren Chan ein. Wenn Sie einen ausreichend komplexen Chan-Namen wählen (Wie einen starkes und einzigartigen Kennwortsatz) und keiner Ihrer Freunde ihn öffentlich weitergibt, wird der Chan sicher und privat bleiben. Wenn eine andere Person einen Chan mit dem gleichen Namen erzeugt, werden diese zu einem Chan.&lt;/p&gt;&lt;br&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Geben Sie einen Namen für Ihren Chan ein. Wenn Sie einen ausreichend komplexen Chan-Namen wählen (wie einen starken, einzigartigen Kennwortsatz) und keiner Ihrer Freunde ihn öffentlich weitergibt, wird der Chan sicher und privat bleiben. Wenn eine andere Person einen Chan mit dem gleichen Namen erzeugt, werden diese zu einem Chan.&lt;/p&gt;&lt;br&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
</context>
<context>
@ -1369,7 +1369,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="117"/>
<source>Number of addresses to make based on your passphrase:</source>
<translation>Anzahl der Adressen die basierend auf diesem Kennwortsatz erzeugt werden sollen:</translation>
<translation>Anzahl der Adressen, die basierend auf diesem Kennwortsatz erzeugt werden sollen:</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="108"/>
@ -1384,7 +1384,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="119"/>
<source>Stream number:</source>
<translation>Stream Nummer:</translation>
<translation>Stream-Nummer:</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="120"/>
@ -1394,7 +1394,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="121"/>
<source>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</source>
<translation>Verwenden Sie einige Minuten extra Rechenleistung um die Adresse(n) ein bis zwei Zeichen kürzer zu machen</translation>
<translation>Verwenden Sie einige Minuten extra Rechenleistung, um die Adresse(n) ein bis zwei Zeichen kürzer zu machen</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="122"/>
@ -1404,12 +1404,12 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="123"/>
<source>If you have previously made deterministic addresses but lost them due to an accident (like hard drive failure), you can regenerate them here. If you used the random number generator to make your addresses then this form will be of no use to you.</source>
<translation>Wenn Sie bereits deterministische Adressen erstellt haben, aber diese durch einen Unfall wie eine defekte Festplatte verloren haben, können Sie sie hier regenerieren. Wenn Sie den Zufallsgenerator verwendet haben um Ihre Adressen erstmals zu erstellen, kann dieses Formular Ihnen nicht helfen.</translation>
<translation>Wenn Sie bereits deterministische Adressen erstellt haben, aber diese durch einen Unfall (zum Beispiel durch eine defekte Festplatte) verloren haben, können Sie sie hier regenerieren. Dies funktioniert nur dann, wenn Sie bei der erstmaligen Erstellung Ihrer Adressen nicht den Zufallsgenerator verwendet haben.</translation>
</message>
<message>
<location filename="../bitmessageqt/regenerateaddresses.py" line="118"/>
<source>Address version number:</source>
<translation type="unfinished"></translation>
<translation>Adress-Versionsnummer:</translation>
</message>
</context>
<context>
@ -1427,7 +1427,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="386"/>
<source>Start Bitmessage in the tray (don&apos;t show main window)</source>
<translation>Bitmessage minimiert starten (Zeigt das Hauptfenster nicht an)</translation>
<translation>Bitmessage minimiert starten (zeigt das Hauptfenster nicht an)</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="387"/>
@ -1442,12 +1442,12 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="389"/>
<source>Run in Portable Mode</source>
<translation>In portablem Modus arbeiten</translation>
<translation>Im portablen Modus arbeiten</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="390"/>
<source>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.</source>
<translation>Im portablen Modus werden Nachrichten und Konfigurationen im gleichen Ordner abgelegt, wie sich das Programm selbst befindet anstelle im normalen Anwendungsdaten-Ordner. Das macht es möglich Bitmessage auf einem USB-Stick zu betreiben.</translation>
<translation>Im portablen Modus werden Nachrichten und Konfigurationen im gleichen Ordner abgelegt, in dem sich das Programm selbst befindet (anstatt im normalen Anwendungsdaten-Ordner). Das macht es möglich, Bitmessage auf einem USB-Stick zu betreiben.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="404"/>
@ -1522,7 +1522,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="422"/>
<source>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. </source>
<translation>Wenn jemand Ihnen eine Nachricht schickt, muss der absendende Computer erst einige Arbeit verrichten. Die Schwierigkeit dieser Arbeit ist standardmäßig 1. Sie können diesen Wert für alle neuen Adressen, die Sie generieren hier ändern. Es gibt eine Ausnahme: Wenn Sie einen Freund oder Bekannten in Ihr Adressbuch übernehmen, wird Bitmessage ihn mit der nächsten Nachricht automatisch informieren, dass er nur noch die minimale Arbeit verrichten muss: Schwierigkeit 1.</translation>
<translation>Wenn jemand Ihnen eine Nachricht schickt, muss der absendende Computer erst einige Arbeit verrichten. Die Schwierigkeit dieser Arbeit ist standardmäßig 1. Sie können diesen Wert für alle neuen Adressen, die Sie generieren, hier ändern. Es gibt eine Ausnahme: Wenn Sie einen Freund oder Bekannten in Ihr Adressbuch übernehmen, wird Bitmessage ihn mit der nächsten Nachricht automatisch informieren, dass er nur noch die minimale Arbeit verrichten muss: Schwierigkeit 1.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="419"/>
@ -1537,12 +1537,12 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="423"/>
<source>The &apos;Small message difficulty&apos; 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&apos;t really affect large messages.</source>
<translation>Die &quot;Schwierigkeit für kurze Nachrichten&quot; trifft nur auf das senden kurzen Nachrichten zu. Verdoppelung des Wertes macht es fast doppelt so schwer kurze Nachrichten zu senden, aber hat keinen Effekt bei langen Nachrichten.</translation>
<translation>Die &quot;Schwierigkeit für kurze Nachrichten&quot; trifft nur auf das Senden kurzer Nachrichten zu. Verdoppelung dieses Wertes macht es fast doppelt so schwer, kurze Nachrichten zu senden, aber hat keinen Effekt bei langen Nachrichten.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="420"/>
<source>The &apos;Total difficulty&apos; affects the absolute amount of work the sender must complete. Doubling this value doubles the amount of work.</source>
<translation>Die &quot;Gesammtschwierigkeit&quot; beeinflusst die absolute menge Arbeit die ein Sender verrichten muss. Verdoppelung dieses Wertes verdoppelt die Menge der Arbeit.</translation>
<translation>Die &quot;Gesamtschwierigkeit&quot; beeinflusst die absolute Menge Arbeit, die ein Sender verrichten muss. Verdoppelung dieses Wertes verdoppelt die Menge der Arbeit.</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="424"/>
@ -1557,7 +1557,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="426"/>
<source>Maximum acceptable total difficulty:</source>
<translation>Maximale akzeptierte Gesammtschwierigkeit:</translation>
<translation>Maximale akzeptierte Gesamtschwierigkeit:</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="427"/>
@ -1572,7 +1572,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="414"/>
<source>Listen for incoming connections when using proxy</source>
<translation>Auf eingehende Verdindungen warten, auch wenn eine Proxy-Server verwendet wird</translation>
<translation>Auf eingehende Verdindungen warten, auch wenn ein Proxy-Server verwendet wird</translation>
</message>
<message>
<location filename="../bitmessageqt/settings.py" line="391"/>
@ -1582,7 +1582,7 @@ Die Zufallszahlen-Option ist standard, jedoch haben deterministische Adressen ei
<message>
<location filename="../bitmessageqt/settings.py" line="429"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;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 &lt;span style=&quot; font-style:italic;&quot;&gt;test. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;(Getting your own Bitmessage address into Namecoin is still rather difficult).&lt;/p&gt;&lt;p&gt;Bitmessage can use either namecoind directly or a running nmcontrol instance.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bitmessage kann ein anderes Bitcoin basiertes Programm namens Namecoin nutzen um Adressen leserlicher zu machen. Zum Beispiel: Anstelle Ihrem Bekannten Ihre lange Bitmessage-Adresse vorzulesen, können Sie ihm einfach sagen, er soll eine Nachricht an &lt;span style=&quot; font-style:italic;&quot;&gt;test &lt;/span&gt;senden.&lt;/p